@openziti/ziti-console-lib 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/assets/styles/global.scss +212 -3
  2. package/esm2022/lib/features/data-table/cells/table-cell-name/table-cell-name.component.mjs +12 -3
  3. package/esm2022/lib/features/dynamic-widgets/text-list/text-list-input.component.mjs +2 -2
  4. package/esm2022/lib/features/list-page-features/list-page-header/list-page-header.component.mjs +22 -3
  5. package/esm2022/lib/features/projectable-forms/auth-policy/auth-policy-form.component.mjs +342 -0
  6. package/esm2022/lib/features/projectable-forms/auth-policy/auth-policy-form.service.mjs +127 -0
  7. package/esm2022/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.mjs +78 -20
  8. package/esm2022/lib/features/projectable-forms/jwt-signer/jwt-signer-form.service.mjs +2 -2
  9. package/esm2022/lib/features/projectable-forms/service/service-form.component.mjs +3 -3
  10. package/esm2022/lib/features/tag-selector/tag-selector.component.mjs +2 -2
  11. package/esm2022/lib/models/auth-policy.mjs +31 -0
  12. package/esm2022/lib/models/jwt-signer.mjs +4 -2
  13. package/esm2022/lib/pages/auth-policies/auth-policies-page.component.mjs +115 -0
  14. package/esm2022/lib/pages/auth-policies/auth-policies-page.service.mjs +207 -0
  15. package/esm2022/lib/pages/jwt-signers/jwt-signers-page.component.mjs +3 -3
  16. package/esm2022/lib/pages/terminators/terminators-page.component.mjs +2 -2
  17. package/esm2022/lib/services/node-data.service.mjs +18 -1
  18. package/esm2022/lib/services/validation.service.mjs +10 -1
  19. package/esm2022/lib/services/ziti-controller-data.service.mjs +16 -1
  20. package/esm2022/lib/services/ziti-data.service.mjs +1 -1
  21. package/esm2022/lib/ziti-console-lib.module.mjs +19 -5
  22. package/esm2022/public-api.mjs +5 -1
  23. package/fesm2022/openziti-ziti-console-lib.mjs +1080 -189
  24. package/fesm2022/openziti-ziti-console-lib.mjs.map +1 -1
  25. package/lib/features/data-table/cells/table-cell-name/table-cell-name.component.d.ts.map +1 -1
  26. package/lib/features/list-page-features/list-page-header/list-page-header.component.d.ts +1 -0
  27. package/lib/features/list-page-features/list-page-header/list-page-header.component.d.ts.map +1 -1
  28. package/lib/features/projectable-forms/auth-policy/auth-policy-form.component.d.ts +75 -0
  29. package/lib/features/projectable-forms/auth-policy/auth-policy-form.component.d.ts.map +1 -0
  30. package/lib/features/projectable-forms/auth-policy/auth-policy-form.service.d.ts +38 -0
  31. package/lib/features/projectable-forms/auth-policy/auth-policy-form.service.d.ts.map +1 -0
  32. package/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.d.ts +4 -0
  33. package/lib/features/projectable-forms/jwt-signer/jwt-signer-form.component.d.ts.map +1 -1
  34. package/lib/models/auth-policy.d.ts +8 -0
  35. package/lib/models/auth-policy.d.ts.map +1 -0
  36. package/lib/models/jwt-signer.d.ts +3 -1
  37. package/lib/models/jwt-signer.d.ts.map +1 -1
  38. package/lib/pages/auth-policies/auth-policies-page.component.d.ts +29 -0
  39. package/lib/pages/auth-policies/auth-policies-page.component.d.ts.map +1 -0
  40. package/lib/pages/auth-policies/auth-policies-page.service.d.ts +34 -0
  41. package/lib/pages/auth-policies/auth-policies-page.service.d.ts.map +1 -0
  42. package/lib/pages/jwt-signers/jwt-signers-page.component.d.ts +1 -1
  43. package/lib/services/node-data.service.d.ts +1 -0
  44. package/lib/services/node-data.service.d.ts.map +1 -1
  45. package/lib/services/validation.service.d.ts +1 -0
  46. package/lib/services/validation.service.d.ts.map +1 -1
  47. package/lib/services/ziti-controller-data.service.d.ts +1 -0
  48. package/lib/services/ziti-controller-data.service.d.ts.map +1 -1
  49. package/lib/services/ziti-data.service.d.ts +1 -0
  50. package/lib/services/ziti-data.service.d.ts.map +1 -1
  51. package/lib/ziti-console-lib.module.d.ts +20 -17
  52. package/lib/ziti-console-lib.module.d.ts.map +1 -1
  53. package/package.json +1 -1
  54. package/public-api.d.ts +4 -0
  55. package/public-api.d.ts.map +1 -1
@@ -4,7 +4,7 @@ import * as i4 from '@angular/router';
4
4
  import { NavigationEnd, RouterModule } from '@angular/router';
5
5
  import { Subject, BehaviorSubject, firstValueFrom, tap, map, Subscription } from 'rxjs';
6
6
  import { catchError } from 'rxjs/operators';
7
- import _, { isEmpty, isNumber, includes, isNil, defer, cloneDeep, set, invoke, get, debounce, isNaN as isNaN$1, forEach, unset, isBoolean, keys, isEqual, isObject, isArray, isFunction, forOwn, invert, map as map$1, isString, some, filter, delay, sortedUniq } from 'lodash';
7
+ import _, { isEmpty, isNumber, includes, isNil, defer, cloneDeep, set, invoke, get, debounce, isNaN as isNaN$1, forEach, isFunction, unset, isBoolean, keys, isEqual, isObject, isArray, forOwn, invert, map as map$1, isString, some, filter, delay, sortedUniq } from 'lodash';
8
8
  import * as i1$1 from '@angular/common/http';
9
9
  import { HttpClient, HttpParams, HttpClientModule } from '@angular/common/http';
10
10
  import * as i1 from 'ngx-logger';
@@ -40,6 +40,7 @@ import * as i5$2 from 'primeng/api';
40
40
  import * as i7 from 'ag-grid-angular';
41
41
  import { AgGridModule } from 'ag-grid-angular';
42
42
  import * as i3$2 from '@angular/cdk/bidi';
43
+ import { MatRadioModule } from '@angular/material/radio';
43
44
  import { createAjvValidator, JSONEditor, Mode } from 'vanilla-jsoneditor';
44
45
  import * as d3 from 'd3';
45
46
  import * as i6 from '@angular/material/autocomplete';
@@ -742,6 +743,15 @@ class ValidationService {
742
743
  };
743
744
  return isBase64(base64Content);
744
745
  }
746
+ isValidURI(uri) {
747
+ try {
748
+ new URL(uri);
749
+ return true;
750
+ }
751
+ catch (e) {
752
+ return false;
753
+ }
754
+ }
745
755
  redefineObject(obj) {
746
756
  for (let prop in obj) {
747
757
  if (Array.isArray(obj[prop]) && obj[prop].length == 0) {
@@ -1788,7 +1798,7 @@ class TextListInputComponent {
1788
1798
  </p-chips>
1789
1799
  <div *ngIf="error" class="error">{{error}}</div>
1790
1800
  </div>
1791
- `, isInline: true, styles: ["::ng-deep .p-element .p-chips.p-component{width:100%;font-weight:400;font-family:Open Sans,Arial,sans-serif;height:var(--defaultInputHeight);border-color:var(--stroke);border-style:solid;border-width:var(--inputBorderWidth);border-radius:var(--inputBorderRadius);padding-left:10px;padding-right:10px;outline:none;box-sizing:border-box;font-size:15px;background-color:var(--background)!important;color:var(--text);-webkit-appearance:none}::ng-deep .p-element .p-chips.p-component .p-inputtext.p-chips-multiple-container{width:100%;padding:0;border-width:var(--inputBorderWidth)}::ng-deep .p-element .p-chips.p-component .p-inputtext.p-chips-multiple-container.p-focus{border-color:var(--primaryColor)!important;box-shadow:0 0 7px 0 var(--primaryColorOpaque)!important}::ng-deep .p-element .p-chips.p-component .p-inputtext.p-chips-multiple-container.p-focus.error{border-color:var(--red)!important}::ng-deep .p-element .p-chips .p-chips-multiple-container .p-chips-input-token input{height:25px;font-size:14px;color:#495057;padding:0;margin:0;border:0 none;outline:0 none;background-color:transparent;box-shadow:none;border-radius:0;width:100%}::ng-deep .p-element .p-chips .p-chips-multiple-container .p-chips-token{margin-right:.5rem;font-family:Open Sans,sans-serif;font-weight:600;margin-top:5px;margin-bottom:5px;background:var(--primary);color:var(--white);border-radius:var(--inputBorderRadius);cursor:default;display:inline-flex;align-items:center;flex:0 0 auto;max-width:100%}::ng-deep .p-element .p-chips-token-icon{margin-left:.5rem;cursor:pointer;color:#00f;fill:red}::ng-deep .p-element .p-chips{display:inline-flex}::ng-deep .p-element .p-chips-token-label{min-width:0;overflow:auto}::ng-deep .p-element .p-chips-token-label::-webkit-scrollbar{display:none}::ng-deep .p-element .p-fluid .p-chips{display:flex}::ng-deep .p-element .p-chips-clear-icon{position:absolute;top:50%;margin-top:-.5rem;cursor:pointer}::ng-deep .p-element .p-chips-clearable .p-inputtext{position:relative}::ng-deep .p-element .p-inputtext{border:none}\n"], dependencies: [{ kind: "directive", type: i1$4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.Chips, selector: "p-chips", inputs: ["style", "styleClass", "disabled", "field", "placeholder", "max", "ariaLabel", "ariaLabelledBy", "tabindex", "inputId", "allowDuplicate", "inputStyle", "inputStyleClass", "addOnTab", "addOnBlur", "separator", "showClear"], outputs: ["onAdd", "onRemove", "onFocus", "onBlur", "onChipClick", "onClear"] }] }); }
1801
+ `, isInline: true, styles: [""], dependencies: [{ kind: "directive", type: i1$4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.Chips, selector: "p-chips", inputs: ["style", "styleClass", "disabled", "field", "placeholder", "max", "ariaLabel", "ariaLabelledBy", "tabindex", "inputId", "allowDuplicate", "inputStyle", "inputStyleClass", "addOnTab", "addOnBlur", "separator", "showClear"], outputs: ["onAdd", "onRemove", "onFocus", "onBlur", "onChipClick", "onClear"] }] }); }
1792
1802
  }
1793
1803
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TextListInputComponent, decorators: [{
1794
1804
  type: Component,
@@ -1807,7 +1817,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
1807
1817
  </p-chips>
1808
1818
  <div *ngIf="error" class="error">{{error}}</div>
1809
1819
  </div>
1810
- `, styles: ["::ng-deep .p-element .p-chips.p-component{width:100%;font-weight:400;font-family:Open Sans,Arial,sans-serif;height:var(--defaultInputHeight);border-color:var(--stroke);border-style:solid;border-width:var(--inputBorderWidth);border-radius:var(--inputBorderRadius);padding-left:10px;padding-right:10px;outline:none;box-sizing:border-box;font-size:15px;background-color:var(--background)!important;color:var(--text);-webkit-appearance:none}::ng-deep .p-element .p-chips.p-component .p-inputtext.p-chips-multiple-container{width:100%;padding:0;border-width:var(--inputBorderWidth)}::ng-deep .p-element .p-chips.p-component .p-inputtext.p-chips-multiple-container.p-focus{border-color:var(--primaryColor)!important;box-shadow:0 0 7px 0 var(--primaryColorOpaque)!important}::ng-deep .p-element .p-chips.p-component .p-inputtext.p-chips-multiple-container.p-focus.error{border-color:var(--red)!important}::ng-deep .p-element .p-chips .p-chips-multiple-container .p-chips-input-token input{height:25px;font-size:14px;color:#495057;padding:0;margin:0;border:0 none;outline:0 none;background-color:transparent;box-shadow:none;border-radius:0;width:100%}::ng-deep .p-element .p-chips .p-chips-multiple-container .p-chips-token{margin-right:.5rem;font-family:Open Sans,sans-serif;font-weight:600;margin-top:5px;margin-bottom:5px;background:var(--primary);color:var(--white);border-radius:var(--inputBorderRadius);cursor:default;display:inline-flex;align-items:center;flex:0 0 auto;max-width:100%}::ng-deep .p-element .p-chips-token-icon{margin-left:.5rem;cursor:pointer;color:#00f;fill:red}::ng-deep .p-element .p-chips{display:inline-flex}::ng-deep .p-element .p-chips-token-label{min-width:0;overflow:auto}::ng-deep .p-element .p-chips-token-label::-webkit-scrollbar{display:none}::ng-deep .p-element .p-fluid .p-chips{display:flex}::ng-deep .p-element .p-chips-clear-icon{position:absolute;top:50%;margin-top:-.5rem;cursor:pointer}::ng-deep .p-element .p-chips-clearable .p-inputtext{position:relative}::ng-deep .p-element .p-inputtext{border:none}\n"] }]
1820
+ ` }]
1811
1821
  }], propDecorators: { fieldName: [{
1812
1822
  type: Input
1813
1823
  }], fieldValue: [{
@@ -3193,9 +3203,18 @@ class TableCellNameComponent {
3193
3203
  return true;
3194
3204
  }
3195
3205
  linkClicked(event) {
3196
- this.router.navigateByUrl(`${this.cellParams.pathRoot}/${this.item.id}`);
3197
3206
  event.stopPropagation();
3198
3207
  event.preventDefault();
3208
+ if (isFunction(this.cellParams?.cellNamePreCheck)) {
3209
+ this.cellParams?.cellNamePreCheck(this.item).then((result) => {
3210
+ if (!result) {
3211
+ return;
3212
+ }
3213
+ this.router.navigateByUrl(`${this.cellParams.pathRoot}/${this.item.id}`);
3214
+ });
3215
+ return;
3216
+ }
3217
+ this.router.navigateByUrl(`${this.cellParams.pathRoot}/${this.item.id}`);
3199
3218
  }
3200
3219
  get cellText() {
3201
3220
  let val = get(this.item, this.cellParams?.colDef?.field);
@@ -4704,12 +4723,31 @@ class ListPageHeaderComponent {
4704
4723
  clickAction(value) {
4705
4724
  this.actionClicked.emit(value);
4706
4725
  }
4726
+ tabSelected(tab) {
4727
+ const parsedUrl = new URL(window.location.href);
4728
+ let path = parsedUrl.pathname;
4729
+ if (document.baseURI) {
4730
+ const base = new URL(document.baseURI).pathname;
4731
+ if (path.startsWith(base)) {
4732
+ path = path.slice(base.length);
4733
+ }
4734
+ }
4735
+ let tabUrl = tab.url;
4736
+ if (tab.url.startsWith('/')) {
4737
+ tabUrl = tab.url.slice(1);
4738
+ }
4739
+ if (path.startsWith('/')) {
4740
+ path = path.slice(1);
4741
+ }
4742
+ // Return the path without parameters
4743
+ return tabUrl === path;
4744
+ }
4707
4745
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ListPageHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4708
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ListPageHeaderComponent, selector: "lib-list-page-header", inputs: { title: "title", tabs: "tabs", showAdd: "showAdd", hideAction: "hideAction" }, outputs: { actionClicked: "actionClicked" }, ngImport: i0, template: "<div class=\"header\">\n <div class=\"title\">\n <span>{{title}}</span>\n </div>\n <div class=\"bread\"></div>\n <div class=\"line\"></div>\n <div class=\"tabs\">\n <div *ngFor=\"let tab of tabs\" class=\"tab\" [routerLink]=\"tab.url\" [hidden]=\"tab.hidden\">{{tab.label}}</div>\n </div>\n <div *ngIf=\"showAdd\" [ngClass]=\"{hideAction: hideAction}\" (click)=\"clickAction('add')\"\n class=\"action icon-plus icon-add\" data-action=\"add\"></div>\n <div *ngIf=\"!showAdd\" [ngClass]=\"{hideAction: hideAction}\" (click)=\"clickAction('delete')\"\n class=\"action icon-minus icon-delete\" data-action=\"delete\"></div>\n</div>\n", styles: [".header [class^=icon-],.header [class*=\" icon-\"]{font-family:zac,serif!important;speak:never;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.header .hideAction{display:none}.header .action{text-align:center;color:var(--white);line-height:60px;font-size:30px;width:60px;height:60px;border-radius:40px;position:absolute;right:0;top:12px;background-color:var(--primary);cursor:pointer;overflow:hidden;z-index:24;box-shadow:var(--shadow);transition:var(--transition)}.header .action.icon-delete{background-color:var(--red)}.header .line{width:100%;height:4px;background-color:var(--stroke)}.header .tabs{position:relative;display:flex;flex:1 1;flex-wrap:wrap;width:100%;font-size:14px;min-height:40px;padding-top:16px}.header .tabs .tab{position:relative;float:left;margin-right:20px;padding-bottom:5px;margin-bottom:10px;font-size:14px;font-weight:600;cursor:pointer;transition:var(--transition);border-bottom-width:4px;border-bottom-color:transparent;border-bottom-style:solid}.header .tabs .tab:hover{border-bottom-color:var(--inputBorder)}.header .title{height:30px;overflow:hidden;font-family:Russo One,serif;color:var(--primary);filter:brightness(50%);font-size:30px;text-transform:uppercase;font-weight:400;line-height:34px}@media (max-width: 1024px){.title{font-size:20px!important}.action{line-height:45px!important;font-size:20px!important;width:45px!important;height:45px!important;border-radius:40px!important;top:20px!important;right:0!important}}\n"], dependencies: [{ kind: "directive", type: i1$4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] }); }
4746
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ListPageHeaderComponent, selector: "lib-list-page-header", inputs: { title: "title", tabs: "tabs", showAdd: "showAdd", hideAction: "hideAction" }, outputs: { actionClicked: "actionClicked" }, ngImport: i0, template: "<div class=\"header\">\n <div class=\"title\">\n <span>{{title}}</span>\n </div>\n <div class=\"bread\"></div>\n <div class=\"line\"></div>\n <div class=\"tabs\">\n <div *ngFor=\"let tab of tabs\" class=\"tab\" [ngClass]=\"{selected: tabSelected(tab)}\" [routerLink]=\"tab.url\" [hidden]=\"tab.hidden\">{{tab.label}}</div>\n </div>\n <div *ngIf=\"showAdd\" [ngClass]=\"{hideAction: hideAction}\" (click)=\"clickAction('add')\"\n class=\"action icon-plus icon-add\" data-action=\"add\"></div>\n <div *ngIf=\"!showAdd\" [ngClass]=\"{hideAction: hideAction}\" (click)=\"clickAction('delete')\"\n class=\"action icon-minus icon-delete\" data-action=\"delete\"></div>\n</div>\n", styles: [".header [class^=icon-],.header [class*=\" icon-\"]{font-family:zac,serif!important;speak:never;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.header .hideAction{display:none}.header .action{text-align:center;color:var(--white);line-height:60px;font-size:30px;width:60px;height:60px;border-radius:40px;position:absolute;right:0;top:12px;background-color:var(--primary);cursor:pointer;overflow:hidden;z-index:24;box-shadow:var(--shadow);transition:var(--transition)}.header .action.icon-delete{background-color:var(--red)}.header .line{width:100%;height:4px;background-color:var(--stroke)}.header .tabs{position:relative;display:flex;flex:1 1;flex-wrap:wrap;width:100%;font-size:14px;min-height:40px;padding-top:16px}.header .tabs .tab{position:relative;float:left;margin-right:20px;padding-bottom:5px;margin-bottom:10px;font-size:14px;font-weight:600;cursor:pointer;transition:var(--transition);border-bottom-width:4px;border-bottom-color:transparent;border-bottom-style:solid}.header .tabs .tab:hover{border-bottom-color:var(--inputBorder)}.header .tabs .tab.selected,.header .tabs .tab.selected:hover{border-bottom-color:var(--primaryColor)}.header .title{height:30px;overflow:hidden;font-family:Russo One,serif;color:var(--primary);filter:brightness(50%);font-size:30px;text-transform:uppercase;font-weight:400;line-height:34px}@media (max-width: 1024px){.title{font-size:20px!important}.action{line-height:45px!important;font-size:20px!important;width:45px!important;height:45px!important;border-radius:40px!important;top:20px!important;right:0!important}}\n"], dependencies: [{ kind: "directive", type: i1$4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] }); }
4709
4747
  }
4710
4748
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ListPageHeaderComponent, decorators: [{
4711
4749
  type: Component,
4712
- args: [{ selector: 'lib-list-page-header', template: "<div class=\"header\">\n <div class=\"title\">\n <span>{{title}}</span>\n </div>\n <div class=\"bread\"></div>\n <div class=\"line\"></div>\n <div class=\"tabs\">\n <div *ngFor=\"let tab of tabs\" class=\"tab\" [routerLink]=\"tab.url\" [hidden]=\"tab.hidden\">{{tab.label}}</div>\n </div>\n <div *ngIf=\"showAdd\" [ngClass]=\"{hideAction: hideAction}\" (click)=\"clickAction('add')\"\n class=\"action icon-plus icon-add\" data-action=\"add\"></div>\n <div *ngIf=\"!showAdd\" [ngClass]=\"{hideAction: hideAction}\" (click)=\"clickAction('delete')\"\n class=\"action icon-minus icon-delete\" data-action=\"delete\"></div>\n</div>\n", styles: [".header [class^=icon-],.header [class*=\" icon-\"]{font-family:zac,serif!important;speak:never;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.header .hideAction{display:none}.header .action{text-align:center;color:var(--white);line-height:60px;font-size:30px;width:60px;height:60px;border-radius:40px;position:absolute;right:0;top:12px;background-color:var(--primary);cursor:pointer;overflow:hidden;z-index:24;box-shadow:var(--shadow);transition:var(--transition)}.header .action.icon-delete{background-color:var(--red)}.header .line{width:100%;height:4px;background-color:var(--stroke)}.header .tabs{position:relative;display:flex;flex:1 1;flex-wrap:wrap;width:100%;font-size:14px;min-height:40px;padding-top:16px}.header .tabs .tab{position:relative;float:left;margin-right:20px;padding-bottom:5px;margin-bottom:10px;font-size:14px;font-weight:600;cursor:pointer;transition:var(--transition);border-bottom-width:4px;border-bottom-color:transparent;border-bottom-style:solid}.header .tabs .tab:hover{border-bottom-color:var(--inputBorder)}.header .title{height:30px;overflow:hidden;font-family:Russo One,serif;color:var(--primary);filter:brightness(50%);font-size:30px;text-transform:uppercase;font-weight:400;line-height:34px}@media (max-width: 1024px){.title{font-size:20px!important}.action{line-height:45px!important;font-size:20px!important;width:45px!important;height:45px!important;border-radius:40px!important;top:20px!important;right:0!important}}\n"] }]
4750
+ args: [{ selector: 'lib-list-page-header', template: "<div class=\"header\">\n <div class=\"title\">\n <span>{{title}}</span>\n </div>\n <div class=\"bread\"></div>\n <div class=\"line\"></div>\n <div class=\"tabs\">\n <div *ngFor=\"let tab of tabs\" class=\"tab\" [ngClass]=\"{selected: tabSelected(tab)}\" [routerLink]=\"tab.url\" [hidden]=\"tab.hidden\">{{tab.label}}</div>\n </div>\n <div *ngIf=\"showAdd\" [ngClass]=\"{hideAction: hideAction}\" (click)=\"clickAction('add')\"\n class=\"action icon-plus icon-add\" data-action=\"add\"></div>\n <div *ngIf=\"!showAdd\" [ngClass]=\"{hideAction: hideAction}\" (click)=\"clickAction('delete')\"\n class=\"action icon-minus icon-delete\" data-action=\"delete\"></div>\n</div>\n", styles: [".header [class^=icon-],.header [class*=\" icon-\"]{font-family:zac,serif!important;speak:never;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.header .hideAction{display:none}.header .action{text-align:center;color:var(--white);line-height:60px;font-size:30px;width:60px;height:60px;border-radius:40px;position:absolute;right:0;top:12px;background-color:var(--primary);cursor:pointer;overflow:hidden;z-index:24;box-shadow:var(--shadow);transition:var(--transition)}.header .action.icon-delete{background-color:var(--red)}.header .line{width:100%;height:4px;background-color:var(--stroke)}.header .tabs{position:relative;display:flex;flex:1 1;flex-wrap:wrap;width:100%;font-size:14px;min-height:40px;padding-top:16px}.header .tabs .tab{position:relative;float:left;margin-right:20px;padding-bottom:5px;margin-bottom:10px;font-size:14px;font-weight:600;cursor:pointer;transition:var(--transition);border-bottom-width:4px;border-bottom-color:transparent;border-bottom-style:solid}.header .tabs .tab:hover{border-bottom-color:var(--inputBorder)}.header .tabs .tab.selected,.header .tabs .tab.selected:hover{border-bottom-color:var(--primaryColor)}.header .title{height:30px;overflow:hidden;font-family:Russo One,serif;color:var(--primary);filter:brightness(50%);font-size:30px;text-transform:uppercase;font-weight:400;line-height:34px}@media (max-width: 1024px){.title{font-size:20px!important}.action{line-height:45px!important;font-size:20px!important;width:45px!important;height:45px!important;border-radius:40px!important;top:20px!important;right:0!important}}\n"] }]
4713
4751
  }], propDecorators: { title: [{
4714
4752
  type: Input
4715
4753
  }], tabs: [{
@@ -6901,11 +6939,11 @@ class TagSelectorComponent {
6901
6939
  return this._selectedRoleAttributes?.length <= 0 && this._selectedNamedAttributes?.length <= 0;
6902
6940
  }
6903
6941
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TagSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6904
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: TagSelectorComponent, selector: "lib-tag-selector", inputs: { placeholder: "placeholder", disableField: "disableField", disableCreate: "disableCreate", hideOption: "hideOption", isLoading: "isLoading", errorMessage: "errorMessage", focusOnInit: "focusOnInit", selectedRoleAttributes: "selectedRoleAttributes", selectedNamedAttributes: "selectedNamedAttributes", hasError: "hasError", availableRoleAttributes: "availableRoleAttributes", availableNamedAttributes: "availableNamedAttributes" }, outputs: { addRoleAttribute: "addRoleAttribute", addNamedAttribute: "addNamedAttribute", roleAttributeRemoved: "roleAttributeRemoved", namedAttributeRemoved: "namedAttributeRemoved", selectedRoleAttributesChange: "selectedRoleAttributesChange", selectedNamedAttributesChange: "selectedNamedAttributesChange", filterChange: "filterChange" }, viewQueries: [{ propertyName: "search", first: true, predicate: ["search"], descendants: true }, { propertyName: "dropdownWrapper", first: true, predicate: ["dropdownWrapper"], descendants: true }], ngImport: i0, template: "<span (clickOutside)=\"hide()\" [ngClass]=\"{ readOnly: disableField }\" class=\"clickOutside fullWidth tagsSelector\" >\n <span\n class=\"select2 select2-container select2-container--default select2-container--below select2-container--focus\"\n dir=\"ltr\"\n >\n <span class=\"selection\">\n <span\n [ngClass]=\"{ 'select2-selection-focus': !hideSelect, tagError: _hasError }\"\n aria-expanded=\"false\"\n aria-haspopup=\"true\"\n class=\"select2-selection select2-selection--multiple\"\n role=\"combobox\"\n tabindex=\"-1\"\n >\n <input\n (focus)=\"inputFocus()\"\n (keydown)=\"handleKeyDown($event);\"\n (keyup)=\"handleKeyUp($event, filterString);\"\n (mouseup)=\"applyFilterMouseUp()\"\n [(ngModel)]=\"filterString\"\n [disabled]=\"disableField\"\n [ngClass]=\"{ empty: isNothingSelected, tagError: _hasError }\"\n aria-autocomplete=\"list\"\n autocapitalize=\"off\"\n autocomplete=\"off\"\n autocorrect=\"off\"\n class=\"select2-search__field\"\n placeholder=\"{{disableField ? (isNothingSelected ? 'Nothing selected' : '') : placeholder}}\"\n role=\"textbox\"\n spellcheck=\"false\"\n tabindex=\"0\"\n type=\"search\"\n #search\n />\n <span *ngIf=\"isLoading\" class=\"spinner\"></span>\n\n <ul\n (click)=\"openSelect()\"\n [ngClass]=\"{ error: _hasError, readOnly: disableField, empty: isNothingSelected }\"\n class=\"select2-selection__rendered\"\n >\n <li\n (click)=\"$event.stopPropagation()\"\n *ngFor=\"let item of _selectedRoleAttributes\"\n [hidden]=\"item === this.hideOption\"\n class=\"hashtag select2-selection__choice\"\n title=\"#{{ item }}\"\n >\n <span\n (click)=\"removeRoleAttribute(item); $event.stopPropagation()\"\n class=\"select2-selection__choice__remove\"\n role=\"presentation\"\n >\u00D7</span\n ><span class=\"select2-selection__choice__text\">#{{ item }}</span>\n </li>\n <li\n (click)=\"$event.stopPropagation()\"\n *ngFor=\"let item of _selectedNamedAttributes\"\n [hidden]=\"item === this.hideOption\"\n class=\"select2-selection_choice_item\"\n >\n <div class=\"attag select2-selection__choice\" title=\"@{{ item }}\">\n <span\n class=\"select2-selection__choice__remove\"\n role=\"presentation\"\n >\u00D7</span\n ><span class=\"select2-selection__choice__text\">@{{ item }}</span>\n </div>\n <div class=\"tag-name select2-selection__choice\" title=\"@{{ item }}\">\n <span\n (click)=\"removeNamedAttribute(item); $event.stopPropagation()\"\n class=\"select2-selection__choice__remove\"\n role=\"presentation\"\n >\u00D7</span\n ><span class=\"select2-selection__choice__text\">@{{ item }}</span>\n </div>\n </li>\n </ul>\n </span>\n </span>\n <span aria-hidden=\"true\" class=\"dropdown-wrapper\" tabindex=\"-1\" #dropdownWrapper></span>\n </span>\n <span *ngIf=\"_hasError\" class=\"err\">\n {{ errorMessage }}\n </span>\n\n <span\n *ngIf=\"!hideSelect\"\n [ngClass]=\"{ withBorder: !hideSelect }\"\n class=\"nf-select2-dropdown select2-dropdown--below\"\n dir=\"ltr\"\n >\n <span class=\"select2-results\">\n <ul\n aria-expanded=\"true\"\n aria-hidden=\"false\"\n aria-multiselectable=\"true\"\n class=\"select2-results__options\"\n role=\"tree\"\n >\n <li\n (click)=\"addNewAttribute(filterString)\"\n [hidden]=\"filterString === '' || isAttributeSelected(filterString)\"\n aria-selected=\"false\"\n class=\"select2-results__option hashtag\"\n role=\"treeitem\"\n title=\"{{ filterString }} (New Attribute)\"\n >\n {{ filterString }} (New Attribute)\n </li>\n <li\n (click)=\"addSelectedRoleAttribute(option)\"\n *ngFor=\"let option of displayedRoleOptions\"\n [hidden]=\"option === this.hideOption || isSelected(option)\"\n aria-selected=\"false\"\n class=\"hashtag select2-results__option\"\n role=\"treeitem\"\n >\n #{{ option }}\n </li>\n <li\n (click)=\"addSelectedNamedAttribute(option)\"\n *ngFor=\"let option of displayedNamedOptions\"\n [hidden]=\"option === this.hideOption || isSelected(option)\"\n aria-selected=\"false\"\n >\n <div class=\"attag select2-results__option\" title=\"@{{ option }}\" role=\"treeitem\">\n @{{ option }}\n </div>\n <div class=\"tag-name select2-results__option\" title=\"@{{ option }}\" role=\"treeitem\">\n @{{ option }}\n </div>\n </li>\n </ul>\n </span>\n </span>\n</span>\n", styles: [".searchSelector .tagButton{cursor:pointer;transition:.5s}.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container.select2-container--focus .select2-selection.select2-selection-focus{border-color:var(--primaryColor)}.select2-container.select2-container--focus .select2-selection .select2-selection__choice__text{cursor:text;user-select:text;-webkit-user-select:text}.select2-container--default .select2-selection--multiple .select2-selection__choice{overflow:hidden;text-wrap:wrap;display:flex}.select2-container--default .select2-selection--multiple .select2-selection__choice.attag{background-color:var(--secondary);color:transparent;position:absolute}.select2-container--default .select2-selection--multiple .select2-selection__choice.tag-name{background-color:transparent}.select2-results__options li{display:flex;flex-direction:row;width:-moz-fit-content;width:fit-content;height:-moz-fit-content;height:fit-content;position:relative}.select2-results__options li[hidden]{display:none}.select2-results__option.tag-name,.select2-results__option.attag,.select2-results__option.hashtag,.select2-selection__choice.tag-name,.select2-selection__choice.attag,.select2-selection__choice.hashtag{margin-bottom:0;margin-top:0;font-size:16px;font-weight:600;line-height:unset;padding:5px 10px;float:left;border-radius:var(--inputBorderRadius);margin-left:2px;transition:var(--transition);overflow:hidden;text-wrap:wrap;display:flex}.select2-results__option.hashtag,.select2-selection__choice.hashtag{background-color:var(--primary);position:relative;color:var(--white)}.select2-results__option.attag,.select2-selection__choice.attag{background-color:var(--secondary);color:transparent;position:absolute}.select2-results__option.tag-name,.select2-selection__choice.tag-name{background-color:transparent;position:relative;color:var(--white)}.err{color:var(--red)!important}.select2-selection{border-radius:var(--inputBorderRadius);border-width:var(--inputBorderWidth);border-color:var(--inputBorder);border-style:solid;color:var(--white);padding-left:0}.select2-selection.select2-selection-focus{border-color:var(--primaryColor)}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow-y:auto;overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir=rtl] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:flex;flex-direction:column;min-height:32px;user-select:none;-webkit-user-select:none;border-radius:var(--inputBorderRadius);border:2px solid var(--stroke);color:var(--white);padding-left:0;background-color:var(--table);overflow:hidden}.select2-container .select2-selection--multiple .select2-selection__rendered .select2-selection_choice_item{width:100%;overflow:hidden;position:relative}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow-y:auto;overflow-x:hidden;padding-left:8px;padding-right:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-results{display:flex;flex-grow:1;height:-moz-fit-content;height:fit-content;width:100%;gap:10px;padding:10px}.select2-results__options{list-style:none;margin:0;padding:0;display:flex;flex-flow:wrap;width:100%;gap:5px}.select2-results__option{display:flex;height:-moz-fit-content;height:fit-content;padding-left:10px;padding-top:2px;padding-bottom:2px;font-size:16px;font-weight:600;user-select:none;-webkit-user-select:none;margin:0}.select2-results__option[hidden]{display:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-hidden-accessible{border:0!important;clip:rect(0 0 0 0)!important;height:1px!important;margin:-1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;width:1px!important}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;width:100%;background-color:var(--background);border-radius:0 0 5px 5px;display:flex;flex-wrap:wrap;gap:5px;padding:0 5px 5px}.select2-container--default .select2-selection--multiple .select2-selection__rendered.empty{padding:0;margin:0}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__placeholder{color:var(--placeholder);margin-top:5px;float:left}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:400;margin-top:5px;margin-right:10px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:var(--white);cursor:pointer;display:inline-block;font-weight:400;margin-right:4px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:var(--white);filter:brightness(90%);transition:.3s}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:active{filter:brightness(80%);transform:scale(.97);transition:.3s}.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__placeholder,.select2-container--default[dir=rtl] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.readOnly{opacity:.75;cursor:default}.readOnly .select2-container .select2-selection__rendered:not(.empty){min-height:var(--defaultInputHeight)}.readOnly .select2-container input:disabled{font-weight:600;font-family:Open Sans,Arial,sans-serif;height:0px!important;width:100%;padding-left:10px;padding-right:10px;margin-bottom:0;border:none;outline:none;box-sizing:border-box;box-shadow:none;cursor:text;text-align:left;background-color:var(--background)!important;color:var(--tableText);text-transform:none}.readOnly .select2-container input:disabled:hover{box-shadow:none;filter:none}.readOnly .select2-container input:disabled.empty{height:50px}.fullModal .select2-container--default.select2-container--focus .select2-selection--multiple{border-radius:var(--inputBorderRadius);border:2px solid var(--inputBorder);color:var(--white);padding-left:0}.fullModal .select2-container--default .select2-selection--multiple .select2-selection__rendered{margin-bottom:-3px;border-color:var(--primaryColor)}.fullModal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove{position:absolute;left:10px;font-size:26px;cursor:pointer;display:inline-block;font-weight:400;margin-right:2px;color:var(--white)}.fullModal .select2-container--default .select2-selection--multiple{background-color:unset}.fullModal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:var(--primaryColor)}.select2-container .select2-dropdown{background-color:var(--background)}.select2-container.select2-container--default .select2-results__option[aria-selected=true]{background-color:var(--primaryColor)}.nf-select2-dropdown{background-color:var(--menu);border-top:0px;border-radius:var(--inputBorderRadius);color:var(--white);box-sizing:border-box;display:flex;flex-grow:1;height:-moz-fit-content;height:fit-content;position:absolute;width:100%;z-index:99999;max-height:200px;overflow:auto;font-weight:600;margin-top:1px;box-shadow:0 0 0 1px var(--shadow),0 8px 16px var(--shadow)!important}.select2-results__option:hover{background-color:var(--icon)!important;color:var(--white);cursor:pointer}.select2-search__field{border-width:0px;width:100%}.select2-container input{padding-top:2px;border-radius:0}.select2-container--below.select2-container--focus{width:75%}.nf-select2-dropdown.select2-dropdown--below{width:503px}.roleForm .select2-container--below.select2-container--focus,.roleForm .nf-select2-dropdown.select2-dropdown--below{width:417px}.fullWidth .select2-container--below.select2-container--focus,.fullWidth .nf-select2-dropdown.select2-dropdown--below{width:100%}.nf-select2-dropdown.select2-dropdown--below.withBorder{border:none}input{box-shadow:none;font-size:14px}.tagError{border-color:var(--red)!important}::ng-deep .select2-container ::placeholder{color:var(--placeholder)}.spinner{position:absolute;right:1em;top:1em;display:inline-block;width:32px;height:32px;border-radius:50%;background:transparent;border-top:5px solid var(--placeholder);border-right:5px solid var(--placeholder);border-bottom:5px solid transparent;border-left:5px solid transparent;animation:loading .5s infinite linear}.tagsSelector.clickOutside{position:relative}\n"], dependencies: [{ kind: "directive", type: i1$4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3$2.Dir, selector: "[dir]", inputs: ["dir"], outputs: ["dirChange"], exportAs: ["dir"] }, { kind: "directive", type: i2$1.ClickOutsideDirective, selector: "[clickOutside]", inputs: ["clickOutsideEnabled", "attachOutsideOnClick", "delayClickOutsideInit", "emitOnBlur", "exclude", "excludeBeforeClick", "clickOutsideEvents"], outputs: ["clickOutside"] }] }); }
6942
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: TagSelectorComponent, selector: "lib-tag-selector", inputs: { placeholder: "placeholder", disableField: "disableField", disableCreate: "disableCreate", hideOption: "hideOption", isLoading: "isLoading", errorMessage: "errorMessage", focusOnInit: "focusOnInit", selectedRoleAttributes: "selectedRoleAttributes", selectedNamedAttributes: "selectedNamedAttributes", hasError: "hasError", availableRoleAttributes: "availableRoleAttributes", availableNamedAttributes: "availableNamedAttributes" }, outputs: { addRoleAttribute: "addRoleAttribute", addNamedAttribute: "addNamedAttribute", roleAttributeRemoved: "roleAttributeRemoved", namedAttributeRemoved: "namedAttributeRemoved", selectedRoleAttributesChange: "selectedRoleAttributesChange", selectedNamedAttributesChange: "selectedNamedAttributesChange", filterChange: "filterChange" }, viewQueries: [{ propertyName: "search", first: true, predicate: ["search"], descendants: true }, { propertyName: "dropdownWrapper", first: true, predicate: ["dropdownWrapper"], descendants: true }], ngImport: i0, template: "<span (clickOutside)=\"hide()\" [ngClass]=\"{ readOnly: disableField }\" class=\"clickOutside fullWidth tagsSelector\" >\n <span\n class=\"select2 select2-container select2-container--default select2-container--below select2-container--focus\"\n dir=\"ltr\"\n >\n <span class=\"selection\">\n <span\n [ngClass]=\"{ 'select2-selection-focus': !hideSelect, tagError: _hasError }\"\n aria-expanded=\"false\"\n aria-haspopup=\"true\"\n class=\"select2-selection select2-selection--multiple\"\n role=\"combobox\"\n tabindex=\"-1\"\n >\n <input\n (focus)=\"inputFocus()\"\n (keydown)=\"handleKeyDown($event);\"\n (keyup)=\"handleKeyUp($event, filterString);\"\n (mouseup)=\"applyFilterMouseUp()\"\n [(ngModel)]=\"filterString\"\n [disabled]=\"disableField\"\n [ngClass]=\"{ empty: isNothingSelected, tagError: _hasError }\"\n aria-autocomplete=\"list\"\n autocapitalize=\"off\"\n autocomplete=\"off\"\n autocorrect=\"off\"\n class=\"select2-search__field\"\n placeholder=\"{{disableField ? (isNothingSelected ? 'Nothing selected' : '') : placeholder}}\"\n role=\"textbox\"\n spellcheck=\"false\"\n tabindex=\"0\"\n type=\"search\"\n #search\n />\n <span *ngIf=\"isLoading\" class=\"spinner\"></span>\n\n <ul\n (click)=\"openSelect()\"\n [ngClass]=\"{ error: _hasError, readOnly: disableField, empty: isNothingSelected }\"\n class=\"select2-selection__rendered\"\n >\n <li\n (click)=\"$event.stopPropagation()\"\n *ngFor=\"let item of _selectedRoleAttributes\"\n [hidden]=\"item === this.hideOption\"\n class=\"hashtag select2-selection__choice\"\n title=\"#{{ item }}\"\n >\n <span\n (click)=\"removeRoleAttribute(item); $event.stopPropagation()\"\n class=\"select2-selection__choice__remove\"\n role=\"presentation\"\n >\u00D7</span\n ><span class=\"select2-selection__choice__text\">#{{ item }}</span>\n </li>\n <li\n (click)=\"$event.stopPropagation()\"\n *ngFor=\"let item of _selectedNamedAttributes\"\n [hidden]=\"item === this.hideOption\"\n class=\"select2-selection_choice_item\"\n >\n <div class=\"attag select2-selection__choice\" title=\"@{{ item }}\">\n <span\n class=\"select2-selection__choice__remove\"\n role=\"presentation\"\n >\u00D7</span\n ><span class=\"select2-selection__choice__text\">@{{ item }}</span>\n </div>\n <div class=\"tag-name select2-selection__choice\" title=\"@{{ item }}\">\n <span\n (click)=\"removeNamedAttribute(item); $event.stopPropagation()\"\n class=\"select2-selection__choice__remove\"\n role=\"presentation\"\n >\u00D7</span\n ><span class=\"select2-selection__choice__text\">@{{ item }}</span>\n </div>\n </li>\n </ul>\n </span>\n </span>\n <span aria-hidden=\"true\" class=\"dropdown-wrapper\" tabindex=\"-1\" #dropdownWrapper></span>\n </span>\n <span *ngIf=\"_hasError\" class=\"err\">\n {{ errorMessage }}\n </span>\n\n <span\n *ngIf=\"!hideSelect\"\n [ngClass]=\"{ withBorder: !hideSelect }\"\n class=\"nf-select2-dropdown select2-dropdown--below\"\n dir=\"ltr\"\n >\n <span class=\"select2-results\">\n <ul\n aria-expanded=\"true\"\n aria-hidden=\"false\"\n aria-multiselectable=\"true\"\n class=\"select2-results__options\"\n role=\"tree\"\n >\n <li\n (click)=\"addNewAttribute(filterString)\"\n [hidden]=\"filterString === '' || isAttributeSelected(filterString)\"\n aria-selected=\"false\"\n class=\"select2-results__option hashtag\"\n role=\"treeitem\"\n title=\"{{ filterString }} (New Attribute)\"\n >\n {{ filterString }} (New Attribute)\n </li>\n <li\n (click)=\"addSelectedRoleAttribute(option)\"\n *ngFor=\"let option of displayedRoleOptions\"\n [hidden]=\"option === this.hideOption || isSelected(option)\"\n aria-selected=\"false\"\n class=\"hashtag select2-results__option\"\n role=\"treeitem\"\n >\n #{{ option }}\n </li>\n <li\n (click)=\"addSelectedNamedAttribute(option)\"\n *ngFor=\"let option of displayedNamedOptions\"\n [hidden]=\"option === this.hideOption || isSelected(option)\"\n aria-selected=\"false\"\n >\n <div class=\"attag select2-results__option\" title=\"@{{ option }}\" role=\"treeitem\">\n @{{ option }}\n </div>\n <div class=\"tag-name select2-results__option\" title=\"@{{ option }}\" role=\"treeitem\">\n @{{ option }}\n </div>\n </li>\n </ul>\n </span>\n </span>\n</span>\n", styles: [".searchSelector .tagButton{cursor:pointer;transition:.5s}.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container.select2-container--focus .select2-selection.select2-selection-focus{border-color:var(--primaryColor)}.select2-container.select2-container--focus .select2-selection .select2-selection__choice__text{cursor:text;user-select:text;-webkit-user-select:text}.select2-container--default .select2-selection--multiple .select2-selection__choice{overflow:hidden;text-wrap:wrap;display:flex}.select2-container--default .select2-selection--multiple .select2-selection__choice.attag{background-color:var(--secondary);color:transparent;position:absolute}.select2-container--default .select2-selection--multiple .select2-selection__choice.tag-name{background-color:transparent}.select2-results__options li{display:flex;flex-direction:row;width:-moz-fit-content;width:fit-content;height:-moz-fit-content;height:fit-content;position:relative}.select2-results__options li[hidden]{display:none}.select2-results__option.tag-name,.select2-results__option.attag,.select2-results__option.hashtag,.select2-selection__choice.tag-name,.select2-selection__choice.attag,.select2-selection__choice.hashtag{margin-bottom:0;margin-top:0;font-size:16px;font-weight:600;line-height:unset;padding:5px 10px;float:left;border-radius:var(--inputBorderRadius);margin-left:2px;transition:var(--transition);overflow:hidden;text-wrap:wrap;display:flex}.select2-results__option.hashtag,.select2-selection__choice.hashtag{background-color:var(--primary);position:relative;color:var(--white)}.select2-results__option.attag,.select2-selection__choice.attag{background-color:var(--secondary);color:transparent;position:absolute}.select2-results__option.tag-name,.select2-selection__choice.tag-name{background-color:transparent;position:relative;color:var(--white)}.err{color:var(--red)!important}.select2-selection{border-radius:var(--inputBorderRadius);border-width:var(--inputBorderWidth);border-color:var(--inputBorder);border-style:solid;color:var(--white);padding-left:0}.select2-selection.select2-selection-focus{border-color:var(--primaryColor)}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow-y:auto;overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir=rtl] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:flex;flex-direction:column;min-height:32px;user-select:none;-webkit-user-select:none;border-radius:var(--inputBorderRadius);border:2px solid var(--stroke);color:var(--white);padding-left:0;background-color:var(--table);overflow:hidden}.select2-container .select2-selection--multiple .select2-selection__rendered .select2-selection_choice_item{width:-moz-fit-content;width:fit-content;overflow:hidden;position:relative}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow-y:auto;overflow-x:hidden;padding-left:8px;padding-right:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-results{display:flex;flex-grow:1;height:-moz-fit-content;height:fit-content;width:100%;gap:10px;padding:10px}.select2-results__options{list-style:none;margin:0;padding:0;display:flex;flex-flow:wrap;width:100%;gap:5px}.select2-results__option{display:flex;height:-moz-fit-content;height:fit-content;padding-left:10px;padding-top:2px;padding-bottom:2px;font-size:16px;font-weight:600;user-select:none;-webkit-user-select:none;margin:0}.select2-results__option[hidden]{display:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-hidden-accessible{border:0!important;clip:rect(0 0 0 0)!important;height:1px!important;margin:-1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;width:1px!important}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;width:100%;background-color:var(--background);border-radius:0 0 5px 5px;display:flex;flex-wrap:wrap;gap:5px;padding:0 5px 5px}.select2-container--default .select2-selection--multiple .select2-selection__rendered.empty{padding:0;margin:0}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__placeholder{color:var(--placeholder);margin-top:5px;float:left}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:400;margin-top:5px;margin-right:10px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:var(--white);cursor:pointer;display:inline-block;font-weight:400;margin-right:4px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:var(--white);filter:brightness(90%);transition:.3s}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:active{filter:brightness(80%);transform:scale(.97);transition:.3s}.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__placeholder,.select2-container--default[dir=rtl] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.readOnly{opacity:.75;cursor:default}.readOnly .select2-container .select2-selection__rendered:not(.empty){min-height:var(--defaultInputHeight)}.readOnly .select2-container input:disabled{font-weight:600;font-family:Open Sans,Arial,sans-serif;height:0px!important;width:100%;padding-left:10px;padding-right:10px;margin-bottom:0;border:none;outline:none;box-sizing:border-box;box-shadow:none;cursor:text;text-align:left;background-color:var(--background)!important;color:var(--tableText);text-transform:none}.readOnly .select2-container input:disabled:hover{box-shadow:none;filter:none}.readOnly .select2-container input:disabled.empty{height:50px}.fullModal .select2-container--default.select2-container--focus .select2-selection--multiple{border-radius:var(--inputBorderRadius);border:2px solid var(--inputBorder);color:var(--white);padding-left:0}.fullModal .select2-container--default .select2-selection--multiple .select2-selection__rendered{margin-bottom:-3px;border-color:var(--primaryColor)}.fullModal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove{position:absolute;left:10px;font-size:26px;cursor:pointer;display:inline-block;font-weight:400;margin-right:2px;color:var(--white)}.fullModal .select2-container--default .select2-selection--multiple{background-color:unset}.fullModal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:var(--primaryColor)}.select2-container .select2-dropdown{background-color:var(--background)}.select2-container.select2-container--default .select2-results__option[aria-selected=true]{background-color:var(--primaryColor)}.nf-select2-dropdown{background-color:var(--menu);border-top:0px;border-radius:var(--inputBorderRadius);color:var(--white);box-sizing:border-box;display:flex;flex-grow:1;height:-moz-fit-content;height:fit-content;position:absolute;width:100%;z-index:99999;max-height:200px;overflow:auto;font-weight:600;margin-top:1px;box-shadow:0 0 0 1px var(--shadow),0 8px 16px var(--shadow)!important}.select2-results__option:hover{background-color:var(--icon)!important;color:var(--white);cursor:pointer}.select2-search__field{border-width:0px;width:100%}.select2-container input{padding-top:2px;border-radius:0}.select2-container--below.select2-container--focus{width:75%}.nf-select2-dropdown.select2-dropdown--below{width:503px}.roleForm .select2-container--below.select2-container--focus,.roleForm .nf-select2-dropdown.select2-dropdown--below{width:417px}.fullWidth .select2-container--below.select2-container--focus,.fullWidth .nf-select2-dropdown.select2-dropdown--below{width:100%}.nf-select2-dropdown.select2-dropdown--below.withBorder{border:none}input{box-shadow:none;font-size:14px}.tagError{border-color:var(--red)!important}::ng-deep .select2-container ::placeholder{color:var(--placeholder)}.spinner{position:absolute;right:1em;top:1em;display:inline-block;width:32px;height:32px;border-radius:50%;background:transparent;border-top:5px solid var(--placeholder);border-right:5px solid var(--placeholder);border-bottom:5px solid transparent;border-left:5px solid transparent;animation:loading .5s infinite linear}.tagsSelector.clickOutside{position:relative}\n"], dependencies: [{ kind: "directive", type: i1$4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3$2.Dir, selector: "[dir]", inputs: ["dir"], outputs: ["dirChange"], exportAs: ["dir"] }, { kind: "directive", type: i2$1.ClickOutsideDirective, selector: "[clickOutside]", inputs: ["clickOutsideEnabled", "attachOutsideOnClick", "delayClickOutsideInit", "emitOnBlur", "exclude", "excludeBeforeClick", "clickOutsideEvents"], outputs: ["clickOutside"] }] }); }
6905
6943
  }
6906
6944
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TagSelectorComponent, decorators: [{
6907
6945
  type: Component,
6908
- args: [{ selector: 'lib-tag-selector', template: "<span (clickOutside)=\"hide()\" [ngClass]=\"{ readOnly: disableField }\" class=\"clickOutside fullWidth tagsSelector\" >\n <span\n class=\"select2 select2-container select2-container--default select2-container--below select2-container--focus\"\n dir=\"ltr\"\n >\n <span class=\"selection\">\n <span\n [ngClass]=\"{ 'select2-selection-focus': !hideSelect, tagError: _hasError }\"\n aria-expanded=\"false\"\n aria-haspopup=\"true\"\n class=\"select2-selection select2-selection--multiple\"\n role=\"combobox\"\n tabindex=\"-1\"\n >\n <input\n (focus)=\"inputFocus()\"\n (keydown)=\"handleKeyDown($event);\"\n (keyup)=\"handleKeyUp($event, filterString);\"\n (mouseup)=\"applyFilterMouseUp()\"\n [(ngModel)]=\"filterString\"\n [disabled]=\"disableField\"\n [ngClass]=\"{ empty: isNothingSelected, tagError: _hasError }\"\n aria-autocomplete=\"list\"\n autocapitalize=\"off\"\n autocomplete=\"off\"\n autocorrect=\"off\"\n class=\"select2-search__field\"\n placeholder=\"{{disableField ? (isNothingSelected ? 'Nothing selected' : '') : placeholder}}\"\n role=\"textbox\"\n spellcheck=\"false\"\n tabindex=\"0\"\n type=\"search\"\n #search\n />\n <span *ngIf=\"isLoading\" class=\"spinner\"></span>\n\n <ul\n (click)=\"openSelect()\"\n [ngClass]=\"{ error: _hasError, readOnly: disableField, empty: isNothingSelected }\"\n class=\"select2-selection__rendered\"\n >\n <li\n (click)=\"$event.stopPropagation()\"\n *ngFor=\"let item of _selectedRoleAttributes\"\n [hidden]=\"item === this.hideOption\"\n class=\"hashtag select2-selection__choice\"\n title=\"#{{ item }}\"\n >\n <span\n (click)=\"removeRoleAttribute(item); $event.stopPropagation()\"\n class=\"select2-selection__choice__remove\"\n role=\"presentation\"\n >\u00D7</span\n ><span class=\"select2-selection__choice__text\">#{{ item }}</span>\n </li>\n <li\n (click)=\"$event.stopPropagation()\"\n *ngFor=\"let item of _selectedNamedAttributes\"\n [hidden]=\"item === this.hideOption\"\n class=\"select2-selection_choice_item\"\n >\n <div class=\"attag select2-selection__choice\" title=\"@{{ item }}\">\n <span\n class=\"select2-selection__choice__remove\"\n role=\"presentation\"\n >\u00D7</span\n ><span class=\"select2-selection__choice__text\">@{{ item }}</span>\n </div>\n <div class=\"tag-name select2-selection__choice\" title=\"@{{ item }}\">\n <span\n (click)=\"removeNamedAttribute(item); $event.stopPropagation()\"\n class=\"select2-selection__choice__remove\"\n role=\"presentation\"\n >\u00D7</span\n ><span class=\"select2-selection__choice__text\">@{{ item }}</span>\n </div>\n </li>\n </ul>\n </span>\n </span>\n <span aria-hidden=\"true\" class=\"dropdown-wrapper\" tabindex=\"-1\" #dropdownWrapper></span>\n </span>\n <span *ngIf=\"_hasError\" class=\"err\">\n {{ errorMessage }}\n </span>\n\n <span\n *ngIf=\"!hideSelect\"\n [ngClass]=\"{ withBorder: !hideSelect }\"\n class=\"nf-select2-dropdown select2-dropdown--below\"\n dir=\"ltr\"\n >\n <span class=\"select2-results\">\n <ul\n aria-expanded=\"true\"\n aria-hidden=\"false\"\n aria-multiselectable=\"true\"\n class=\"select2-results__options\"\n role=\"tree\"\n >\n <li\n (click)=\"addNewAttribute(filterString)\"\n [hidden]=\"filterString === '' || isAttributeSelected(filterString)\"\n aria-selected=\"false\"\n class=\"select2-results__option hashtag\"\n role=\"treeitem\"\n title=\"{{ filterString }} (New Attribute)\"\n >\n {{ filterString }} (New Attribute)\n </li>\n <li\n (click)=\"addSelectedRoleAttribute(option)\"\n *ngFor=\"let option of displayedRoleOptions\"\n [hidden]=\"option === this.hideOption || isSelected(option)\"\n aria-selected=\"false\"\n class=\"hashtag select2-results__option\"\n role=\"treeitem\"\n >\n #{{ option }}\n </li>\n <li\n (click)=\"addSelectedNamedAttribute(option)\"\n *ngFor=\"let option of displayedNamedOptions\"\n [hidden]=\"option === this.hideOption || isSelected(option)\"\n aria-selected=\"false\"\n >\n <div class=\"attag select2-results__option\" title=\"@{{ option }}\" role=\"treeitem\">\n @{{ option }}\n </div>\n <div class=\"tag-name select2-results__option\" title=\"@{{ option }}\" role=\"treeitem\">\n @{{ option }}\n </div>\n </li>\n </ul>\n </span>\n </span>\n</span>\n", styles: [".searchSelector .tagButton{cursor:pointer;transition:.5s}.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container.select2-container--focus .select2-selection.select2-selection-focus{border-color:var(--primaryColor)}.select2-container.select2-container--focus .select2-selection .select2-selection__choice__text{cursor:text;user-select:text;-webkit-user-select:text}.select2-container--default .select2-selection--multiple .select2-selection__choice{overflow:hidden;text-wrap:wrap;display:flex}.select2-container--default .select2-selection--multiple .select2-selection__choice.attag{background-color:var(--secondary);color:transparent;position:absolute}.select2-container--default .select2-selection--multiple .select2-selection__choice.tag-name{background-color:transparent}.select2-results__options li{display:flex;flex-direction:row;width:-moz-fit-content;width:fit-content;height:-moz-fit-content;height:fit-content;position:relative}.select2-results__options li[hidden]{display:none}.select2-results__option.tag-name,.select2-results__option.attag,.select2-results__option.hashtag,.select2-selection__choice.tag-name,.select2-selection__choice.attag,.select2-selection__choice.hashtag{margin-bottom:0;margin-top:0;font-size:16px;font-weight:600;line-height:unset;padding:5px 10px;float:left;border-radius:var(--inputBorderRadius);margin-left:2px;transition:var(--transition);overflow:hidden;text-wrap:wrap;display:flex}.select2-results__option.hashtag,.select2-selection__choice.hashtag{background-color:var(--primary);position:relative;color:var(--white)}.select2-results__option.attag,.select2-selection__choice.attag{background-color:var(--secondary);color:transparent;position:absolute}.select2-results__option.tag-name,.select2-selection__choice.tag-name{background-color:transparent;position:relative;color:var(--white)}.err{color:var(--red)!important}.select2-selection{border-radius:var(--inputBorderRadius);border-width:var(--inputBorderWidth);border-color:var(--inputBorder);border-style:solid;color:var(--white);padding-left:0}.select2-selection.select2-selection-focus{border-color:var(--primaryColor)}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow-y:auto;overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir=rtl] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:flex;flex-direction:column;min-height:32px;user-select:none;-webkit-user-select:none;border-radius:var(--inputBorderRadius);border:2px solid var(--stroke);color:var(--white);padding-left:0;background-color:var(--table);overflow:hidden}.select2-container .select2-selection--multiple .select2-selection__rendered .select2-selection_choice_item{width:100%;overflow:hidden;position:relative}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow-y:auto;overflow-x:hidden;padding-left:8px;padding-right:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-results{display:flex;flex-grow:1;height:-moz-fit-content;height:fit-content;width:100%;gap:10px;padding:10px}.select2-results__options{list-style:none;margin:0;padding:0;display:flex;flex-flow:wrap;width:100%;gap:5px}.select2-results__option{display:flex;height:-moz-fit-content;height:fit-content;padding-left:10px;padding-top:2px;padding-bottom:2px;font-size:16px;font-weight:600;user-select:none;-webkit-user-select:none;margin:0}.select2-results__option[hidden]{display:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-hidden-accessible{border:0!important;clip:rect(0 0 0 0)!important;height:1px!important;margin:-1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;width:1px!important}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;width:100%;background-color:var(--background);border-radius:0 0 5px 5px;display:flex;flex-wrap:wrap;gap:5px;padding:0 5px 5px}.select2-container--default .select2-selection--multiple .select2-selection__rendered.empty{padding:0;margin:0}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__placeholder{color:var(--placeholder);margin-top:5px;float:left}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:400;margin-top:5px;margin-right:10px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:var(--white);cursor:pointer;display:inline-block;font-weight:400;margin-right:4px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:var(--white);filter:brightness(90%);transition:.3s}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:active{filter:brightness(80%);transform:scale(.97);transition:.3s}.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__placeholder,.select2-container--default[dir=rtl] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.readOnly{opacity:.75;cursor:default}.readOnly .select2-container .select2-selection__rendered:not(.empty){min-height:var(--defaultInputHeight)}.readOnly .select2-container input:disabled{font-weight:600;font-family:Open Sans,Arial,sans-serif;height:0px!important;width:100%;padding-left:10px;padding-right:10px;margin-bottom:0;border:none;outline:none;box-sizing:border-box;box-shadow:none;cursor:text;text-align:left;background-color:var(--background)!important;color:var(--tableText);text-transform:none}.readOnly .select2-container input:disabled:hover{box-shadow:none;filter:none}.readOnly .select2-container input:disabled.empty{height:50px}.fullModal .select2-container--default.select2-container--focus .select2-selection--multiple{border-radius:var(--inputBorderRadius);border:2px solid var(--inputBorder);color:var(--white);padding-left:0}.fullModal .select2-container--default .select2-selection--multiple .select2-selection__rendered{margin-bottom:-3px;border-color:var(--primaryColor)}.fullModal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove{position:absolute;left:10px;font-size:26px;cursor:pointer;display:inline-block;font-weight:400;margin-right:2px;color:var(--white)}.fullModal .select2-container--default .select2-selection--multiple{background-color:unset}.fullModal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:var(--primaryColor)}.select2-container .select2-dropdown{background-color:var(--background)}.select2-container.select2-container--default .select2-results__option[aria-selected=true]{background-color:var(--primaryColor)}.nf-select2-dropdown{background-color:var(--menu);border-top:0px;border-radius:var(--inputBorderRadius);color:var(--white);box-sizing:border-box;display:flex;flex-grow:1;height:-moz-fit-content;height:fit-content;position:absolute;width:100%;z-index:99999;max-height:200px;overflow:auto;font-weight:600;margin-top:1px;box-shadow:0 0 0 1px var(--shadow),0 8px 16px var(--shadow)!important}.select2-results__option:hover{background-color:var(--icon)!important;color:var(--white);cursor:pointer}.select2-search__field{border-width:0px;width:100%}.select2-container input{padding-top:2px;border-radius:0}.select2-container--below.select2-container--focus{width:75%}.nf-select2-dropdown.select2-dropdown--below{width:503px}.roleForm .select2-container--below.select2-container--focus,.roleForm .nf-select2-dropdown.select2-dropdown--below{width:417px}.fullWidth .select2-container--below.select2-container--focus,.fullWidth .nf-select2-dropdown.select2-dropdown--below{width:100%}.nf-select2-dropdown.select2-dropdown--below.withBorder{border:none}input{box-shadow:none;font-size:14px}.tagError{border-color:var(--red)!important}::ng-deep .select2-container ::placeholder{color:var(--placeholder)}.spinner{position:absolute;right:1em;top:1em;display:inline-block;width:32px;height:32px;border-radius:50%;background:transparent;border-top:5px solid var(--placeholder);border-right:5px solid var(--placeholder);border-bottom:5px solid transparent;border-left:5px solid transparent;animation:loading .5s infinite linear}.tagsSelector.clickOutside{position:relative}\n"] }]
6946
+ args: [{ selector: 'lib-tag-selector', template: "<span (clickOutside)=\"hide()\" [ngClass]=\"{ readOnly: disableField }\" class=\"clickOutside fullWidth tagsSelector\" >\n <span\n class=\"select2 select2-container select2-container--default select2-container--below select2-container--focus\"\n dir=\"ltr\"\n >\n <span class=\"selection\">\n <span\n [ngClass]=\"{ 'select2-selection-focus': !hideSelect, tagError: _hasError }\"\n aria-expanded=\"false\"\n aria-haspopup=\"true\"\n class=\"select2-selection select2-selection--multiple\"\n role=\"combobox\"\n tabindex=\"-1\"\n >\n <input\n (focus)=\"inputFocus()\"\n (keydown)=\"handleKeyDown($event);\"\n (keyup)=\"handleKeyUp($event, filterString);\"\n (mouseup)=\"applyFilterMouseUp()\"\n [(ngModel)]=\"filterString\"\n [disabled]=\"disableField\"\n [ngClass]=\"{ empty: isNothingSelected, tagError: _hasError }\"\n aria-autocomplete=\"list\"\n autocapitalize=\"off\"\n autocomplete=\"off\"\n autocorrect=\"off\"\n class=\"select2-search__field\"\n placeholder=\"{{disableField ? (isNothingSelected ? 'Nothing selected' : '') : placeholder}}\"\n role=\"textbox\"\n spellcheck=\"false\"\n tabindex=\"0\"\n type=\"search\"\n #search\n />\n <span *ngIf=\"isLoading\" class=\"spinner\"></span>\n\n <ul\n (click)=\"openSelect()\"\n [ngClass]=\"{ error: _hasError, readOnly: disableField, empty: isNothingSelected }\"\n class=\"select2-selection__rendered\"\n >\n <li\n (click)=\"$event.stopPropagation()\"\n *ngFor=\"let item of _selectedRoleAttributes\"\n [hidden]=\"item === this.hideOption\"\n class=\"hashtag select2-selection__choice\"\n title=\"#{{ item }}\"\n >\n <span\n (click)=\"removeRoleAttribute(item); $event.stopPropagation()\"\n class=\"select2-selection__choice__remove\"\n role=\"presentation\"\n >\u00D7</span\n ><span class=\"select2-selection__choice__text\">#{{ item }}</span>\n </li>\n <li\n (click)=\"$event.stopPropagation()\"\n *ngFor=\"let item of _selectedNamedAttributes\"\n [hidden]=\"item === this.hideOption\"\n class=\"select2-selection_choice_item\"\n >\n <div class=\"attag select2-selection__choice\" title=\"@{{ item }}\">\n <span\n class=\"select2-selection__choice__remove\"\n role=\"presentation\"\n >\u00D7</span\n ><span class=\"select2-selection__choice__text\">@{{ item }}</span>\n </div>\n <div class=\"tag-name select2-selection__choice\" title=\"@{{ item }}\">\n <span\n (click)=\"removeNamedAttribute(item); $event.stopPropagation()\"\n class=\"select2-selection__choice__remove\"\n role=\"presentation\"\n >\u00D7</span\n ><span class=\"select2-selection__choice__text\">@{{ item }}</span>\n </div>\n </li>\n </ul>\n </span>\n </span>\n <span aria-hidden=\"true\" class=\"dropdown-wrapper\" tabindex=\"-1\" #dropdownWrapper></span>\n </span>\n <span *ngIf=\"_hasError\" class=\"err\">\n {{ errorMessage }}\n </span>\n\n <span\n *ngIf=\"!hideSelect\"\n [ngClass]=\"{ withBorder: !hideSelect }\"\n class=\"nf-select2-dropdown select2-dropdown--below\"\n dir=\"ltr\"\n >\n <span class=\"select2-results\">\n <ul\n aria-expanded=\"true\"\n aria-hidden=\"false\"\n aria-multiselectable=\"true\"\n class=\"select2-results__options\"\n role=\"tree\"\n >\n <li\n (click)=\"addNewAttribute(filterString)\"\n [hidden]=\"filterString === '' || isAttributeSelected(filterString)\"\n aria-selected=\"false\"\n class=\"select2-results__option hashtag\"\n role=\"treeitem\"\n title=\"{{ filterString }} (New Attribute)\"\n >\n {{ filterString }} (New Attribute)\n </li>\n <li\n (click)=\"addSelectedRoleAttribute(option)\"\n *ngFor=\"let option of displayedRoleOptions\"\n [hidden]=\"option === this.hideOption || isSelected(option)\"\n aria-selected=\"false\"\n class=\"hashtag select2-results__option\"\n role=\"treeitem\"\n >\n #{{ option }}\n </li>\n <li\n (click)=\"addSelectedNamedAttribute(option)\"\n *ngFor=\"let option of displayedNamedOptions\"\n [hidden]=\"option === this.hideOption || isSelected(option)\"\n aria-selected=\"false\"\n >\n <div class=\"attag select2-results__option\" title=\"@{{ option }}\" role=\"treeitem\">\n @{{ option }}\n </div>\n <div class=\"tag-name select2-results__option\" title=\"@{{ option }}\" role=\"treeitem\">\n @{{ option }}\n </div>\n </li>\n </ul>\n </span>\n </span>\n</span>\n", styles: [".searchSelector .tagButton{cursor:pointer;transition:.5s}.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container.select2-container--focus .select2-selection.select2-selection-focus{border-color:var(--primaryColor)}.select2-container.select2-container--focus .select2-selection .select2-selection__choice__text{cursor:text;user-select:text;-webkit-user-select:text}.select2-container--default .select2-selection--multiple .select2-selection__choice{overflow:hidden;text-wrap:wrap;display:flex}.select2-container--default .select2-selection--multiple .select2-selection__choice.attag{background-color:var(--secondary);color:transparent;position:absolute}.select2-container--default .select2-selection--multiple .select2-selection__choice.tag-name{background-color:transparent}.select2-results__options li{display:flex;flex-direction:row;width:-moz-fit-content;width:fit-content;height:-moz-fit-content;height:fit-content;position:relative}.select2-results__options li[hidden]{display:none}.select2-results__option.tag-name,.select2-results__option.attag,.select2-results__option.hashtag,.select2-selection__choice.tag-name,.select2-selection__choice.attag,.select2-selection__choice.hashtag{margin-bottom:0;margin-top:0;font-size:16px;font-weight:600;line-height:unset;padding:5px 10px;float:left;border-radius:var(--inputBorderRadius);margin-left:2px;transition:var(--transition);overflow:hidden;text-wrap:wrap;display:flex}.select2-results__option.hashtag,.select2-selection__choice.hashtag{background-color:var(--primary);position:relative;color:var(--white)}.select2-results__option.attag,.select2-selection__choice.attag{background-color:var(--secondary);color:transparent;position:absolute}.select2-results__option.tag-name,.select2-selection__choice.tag-name{background-color:transparent;position:relative;color:var(--white)}.err{color:var(--red)!important}.select2-selection{border-radius:var(--inputBorderRadius);border-width:var(--inputBorderWidth);border-color:var(--inputBorder);border-style:solid;color:var(--white);padding-left:0}.select2-selection.select2-selection-focus{border-color:var(--primaryColor)}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow-y:auto;overflow-x:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir=rtl] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:flex;flex-direction:column;min-height:32px;user-select:none;-webkit-user-select:none;border-radius:var(--inputBorderRadius);border:2px solid var(--stroke);color:var(--white);padding-left:0;background-color:var(--table);overflow:hidden}.select2-container .select2-selection--multiple .select2-selection__rendered .select2-selection_choice_item{width:-moz-fit-content;width:fit-content;overflow:hidden;position:relative}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow-y:auto;overflow-x:hidden;padding-left:8px;padding-right:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-results{display:flex;flex-grow:1;height:-moz-fit-content;height:fit-content;width:100%;gap:10px;padding:10px}.select2-results__options{list-style:none;margin:0;padding:0;display:flex;flex-flow:wrap;width:100%;gap:5px}.select2-results__option{display:flex;height:-moz-fit-content;height:fit-content;padding-left:10px;padding-top:2px;padding-bottom:2px;font-size:16px;font-weight:600;user-select:none;-webkit-user-select:none;margin:0}.select2-results__option[hidden]{display:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-hidden-accessible{border:0!important;clip:rect(0 0 0 0)!important;height:1px!important;margin:-1px!important;overflow:hidden!important;padding:0!important;position:absolute!important;width:1px!important}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;width:100%;background-color:var(--background);border-radius:0 0 5px 5px;display:flex;flex-wrap:wrap;gap:5px;padding:0 5px 5px}.select2-container--default .select2-selection--multiple .select2-selection__rendered.empty{padding:0;margin:0}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__placeholder{color:var(--placeholder);margin-top:5px;float:left}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:400;margin-top:5px;margin-right:10px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:var(--white);cursor:pointer;display:inline-block;font-weight:400;margin-right:4px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:var(--white);filter:brightness(90%);transition:.3s}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:active{filter:brightness(80%);transform:scale(.97);transition:.3s}.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__placeholder,.select2-container--default[dir=rtl] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir=rtl] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.readOnly{opacity:.75;cursor:default}.readOnly .select2-container .select2-selection__rendered:not(.empty){min-height:var(--defaultInputHeight)}.readOnly .select2-container input:disabled{font-weight:600;font-family:Open Sans,Arial,sans-serif;height:0px!important;width:100%;padding-left:10px;padding-right:10px;margin-bottom:0;border:none;outline:none;box-sizing:border-box;box-shadow:none;cursor:text;text-align:left;background-color:var(--background)!important;color:var(--tableText);text-transform:none}.readOnly .select2-container input:disabled:hover{box-shadow:none;filter:none}.readOnly .select2-container input:disabled.empty{height:50px}.fullModal .select2-container--default.select2-container--focus .select2-selection--multiple{border-radius:var(--inputBorderRadius);border:2px solid var(--inputBorder);color:var(--white);padding-left:0}.fullModal .select2-container--default .select2-selection--multiple .select2-selection__rendered{margin-bottom:-3px;border-color:var(--primaryColor)}.fullModal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove{position:absolute;left:10px;font-size:26px;cursor:pointer;display:inline-block;font-weight:400;margin-right:2px;color:var(--white)}.fullModal .select2-container--default .select2-selection--multiple{background-color:unset}.fullModal .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:var(--primaryColor)}.select2-container .select2-dropdown{background-color:var(--background)}.select2-container.select2-container--default .select2-results__option[aria-selected=true]{background-color:var(--primaryColor)}.nf-select2-dropdown{background-color:var(--menu);border-top:0px;border-radius:var(--inputBorderRadius);color:var(--white);box-sizing:border-box;display:flex;flex-grow:1;height:-moz-fit-content;height:fit-content;position:absolute;width:100%;z-index:99999;max-height:200px;overflow:auto;font-weight:600;margin-top:1px;box-shadow:0 0 0 1px var(--shadow),0 8px 16px var(--shadow)!important}.select2-results__option:hover{background-color:var(--icon)!important;color:var(--white);cursor:pointer}.select2-search__field{border-width:0px;width:100%}.select2-container input{padding-top:2px;border-radius:0}.select2-container--below.select2-container--focus{width:75%}.nf-select2-dropdown.select2-dropdown--below{width:503px}.roleForm .select2-container--below.select2-container--focus,.roleForm .nf-select2-dropdown.select2-dropdown--below{width:417px}.fullWidth .select2-container--below.select2-container--focus,.fullWidth .nf-select2-dropdown.select2-dropdown--below{width:100%}.nf-select2-dropdown.select2-dropdown--below.withBorder{border:none}input{box-shadow:none;font-size:14px}.tagError{border-color:var(--red)!important}::ng-deep .select2-container ::placeholder{color:var(--placeholder)}.spinner{position:absolute;right:1em;top:1em;display:inline-block;width:32px;height:32px;border-radius:50%;background:transparent;border-top:5px solid var(--placeholder);border-right:5px solid var(--placeholder);border-bottom:5px solid transparent;border-left:5px solid transparent;animation:loading .5s infinite linear}.tagsSelector.clickOutside{position:relative}\n"] }]
6909
6947
  }], ctorParameters: function () { return []; }, propDecorators: { placeholder: [{
6910
6948
  type: Input
6911
6949
  }], disableField: [{
@@ -16139,7 +16177,7 @@ class ServiceFormComponent extends ProjectableForm {
16139
16177
  provide: MatDialogRef,
16140
16178
  useValue: {}
16141
16179
  }
16142
- ], viewQueries: [{ propertyName: "configEditor", first: true, predicate: ["configEditor"], descendants: true, read: ConfigEditorComponent }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div class=\"projectable-form-wrapper\"\n (keyup.enter)=\"save($event)\"\n (keyup.escape)=\"returnToListPage()\"\n tabindex=\"0\"\n>\n <lib-form-header\n [data]=\"formData\"\n [title]=\"(formData.id ? 'Edit Service' : 'Create Service')\"\n [moreActions]=\"formData.moreActions\"\n (actionRequested)=\"headerActionRequested($event)\"\n [(formView)]=\"formView\"\n [saveDisabled]=\"svc.saveDisabled || formDataInvalid\"\n [saveTooltip]=\"saveButtonTooltip\"\n ></lib-form-header>\n <div class=\"edge-router-form-container projectable-form-container\">\n <div class=\"projectable-form-main-column form-group-row\" [hidden]=\"formView !== 'simple'\">\n <div class=\"form-group-column three-fifths\">\n <lib-form-field-container [title]=\"'Service Name'\" [label]=\"'Required'\">\n <input\n class=\"form-field-input\"\n placeholder=\"Name this Service\"\n [ngClass]=\"{error: svc.errors['name']}\"\n [(ngModel)]=\"formData.name\"\n autofocus\n #nameFieldInput\n />\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'Select or create Service attributes'\"\n [label]=\"'Optional'\"\n [contentStyle]=\"'z-index: 99999999'\"\n [helpText]=\"'Attributes are tags applied to a resource. Apply the same tag to other Services to form a group of Services.'\"\n >\n <lib-tag-selector\n [(selectedRoleAttributes)]=\"formData.roleAttributes\"\n [availableRoleAttributes]=\"serviceRoleAttributes\"\n [placeholder]=\"'Add attributes to group Services'\"\n ></lib-tag-selector>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'Add Configurations'\"\n (actionRequested)=\"attachConfig()\"\n (keyup.enter)=\"captureConfigEnterEvent($event)\"\n [helpText]=\"'Configurations are used to define how to intercept and host a service. Ziti Networks come with built-in configuration types (ie. intercept.v1 and host.v1)'\"\n >\n <div class=\"form-field-input-group\">\n <div class=\"config-title-row\">\n <span class=\"form-field-title\">Select a Config</span>\n </div>\n <select\n [(ngModel)]=\"svc.selectedConfigTypeId\"\n (change)=\"configTypeChanged($event)\"\n id=\"SelectedConfigType\"\n class=\"form-field-dropdown\"\n >\n <option value=\"\">Select configuration type...</option>\n <option\n *ngFor=\"let type of svc.configTypes\"\n [value]=\"type.id\"\n >\n {{ type.name }}\n </option>\n </select>\n <div class=\"dropdown-container\" [ngClass]=\"{'dropdown-loading': svc.configsLoading}\">\n <p-dropdown\n placeholder=\"Select configuration...\"\n optionLabel=\"name\"\n optionValue=\"id\"\n filterBy=\"name\"\n [options]=\"svc.filteredConfigs\"\n [filter]=\"true\"\n [showClear]=\"true\"\n [disabled]=\"!svc.selectedConfigTypeId || svc.selectedConfigTypeId === ''\"\n (change)=\"configChanged($event)\"\n [(ngModel)]=\"svc.selectedConfigId\"\n >\n <ng-template pTemplate=\"filter\" let-options=\"options\">\n <div class=\"config-filter-container\">\n <div class=\"p-inputgroup\" (click)=\"$event.stopPropagation()\">\n <span class=\"p-inputgroup-addon\"><i class=\"pi pi-search\"></i></span>\n <input\n type=\"text\"\n pInputText\n placeholder=\"Filter\"\n (keyup)=\"configFilterChangedDebounced($event)\" />\n </div>\n <button pButton\n icon=\"pi pi-times\"\n [ngClass]=\"{'configs-loading': svc.configsLoading}\"\n (click)=\"clearConfigFilter($event)\"\n severity=\"secondary\">\n </button>\n <div class=\"spinner\" *ngIf=\"svc.configsLoading\"></div>\n </div>\n </ng-template>\n </p-dropdown>\n </div>\n <div *ngIf=\"!showConfigData && svc.selectedConfigId && svc.selectedConfigId !== '' && svc.selectedConfigId !== 'preview'\" class=\"button-row-right\" >\n <div class=\"save-button\" (click)=\"svc.attachConfig(svc.selectedConfigId)\">\n {{svc.attachLabel}}\n </div>\n </div>\n <div [hidden]=\"!showConfigData\" class=\"form-field-extended-fields\" [ngClass]=\"{'cfg-preview': svc.selectedConfigId === 'preview'}\">\n <div *ngIf=\"showConfigData\" class=\"config-title-row\" style=\"margin-bottom: 10px;\">\n <span class=\"form-field-title\">Config Name</span>\n <div\n class=\"save-button\"\n (click)=\"attachConfig()\"\n *ngIf=\"svc.selectedConfigId !== 'preview'\"\n >{{svc.attachLabel}}\n </div>\n </div>\n <input\n *ngIf=\"showConfigData\"\n [(ngModel)]=\"svc.newConfigName\"\n class=\"form-field-input\"\n [placeholder]=\"'New Config Name'\"\n [ngClass]=\"{error: svc.configErrors['name']}\"\n style=\"margin-bottom: 20px;\"\n />\n <div class=\"config-title-row\" style=\"margin-bottom: 10px;\">\n <span class=\"form-field-title\">Configuration Data</span>\n <div class=\"form-header-toggle-container\" *ngIf=\"svc.selectedConfigId !== 'preview'\">\n <span\n class=\"toggle-option-text\"\n [ngClass]=\"{'toggle-option-selected': !svc.configJsonView}\"\n (click)=\"svc.toggleJSONView()\"\n >\n FORM\n </span>\n <div class=\"form-header-toggle\" (click)=\"svc.toggleJSONView()\">\n <div\n class=\"form-toggle-switch\"\n [ngClass]=\"{'toggle-left': !svc.configJsonView, 'toggle-right': svc.configJsonView}\"\n >\n <div class=\"form-toggle-indicator\"></div>\n <div class=\"form-toggle-indicator\"></div>\n </div>\n </div>\n <span\n class=\"toggle-option-text\"\n [ngClass]=\"{'toggle-option-selected': svc.configJsonView}\"\n (click)=\"svc.toggleJSONView()\"\n >\n JSON\n </span>\n </div>\n </div>\n <lib-config-editor\n [(configData)]=\"svc.configData\"\n [schema]=\"svc.selectedSchema\"\n [showJsonView]=\"svc.configJsonView\"\n [(configErrors)]=\"svc.configErrors\"\n #configEditor\n ></lib-config-editor>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-toggle [(toggleOn)]=\"showMore\" style=\"margin: 0px 10px\"></lib-form-field-toggle>\n <div *ngIf=\"showMore\" class=\"form-group-column\">\n <lib-form-field-container\n [title]=\"'Terminator Strategy'\"\n [title2]=\"'Encryption'\"\n [layout]=\"'row'\"\n [helpText]=\"'Pick a strategy to determine how to rank available terminators for a service'\"\n [helpText2]=\"'Encrypts packets when entering or leaving the network.'\"\n class=\"form-field-advanced\"\n >\n <select\n [(ngModel)]=\"formData.terminatorStrategy\"\n id=\"authPolicyId\"\n class=\"form-field-dropdown\"\n >\n <option value=\"\">Select a Strategy....</option>\n <option\n *ngFor=\"let strat of strategies\"\n [value]=\"strat.id\"\n >\n {{ strat.label }}\n </option>\n </select>\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"config-container-label\">Require Encryption</div>\n <div\n (click)=\"toggleEncryptionRequired()\"\n [ngClass]=\"{ on: formData.encryptionRequired }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.encryptionRequired\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.encryptionRequired\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'Custom Tags'\"\n [label]=\"'OPTIONAL'\"\n class=\"form-field-advanced\"\n >\n <lib-custom-tags [(tags)]=\"formData.tags\"></lib-custom-tags>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column two-fifths\">\n <lib-form-field-container\n [title]=\"'Associated Entities'\"\n [label]=\"'Click for detailed view'\"\n [helpText]=\"'List the configs, policies, and terminators that are associated with this service. Click on the entity name to navigate to the entity\\'s detailed view.'\"\n [class]=\"'no-gap'\"\n >\n <div class=\"form-row space-between\" style=\"margin-top: 0;\">\n <div class=\"config-title-row\">\n <span class=\"form-field-title\">Configurations</span>\n </div>\n <span class=\"form-field-count\">{{svc.addedConfigs ? svc.addedConfigs.length : 0}}</span>\n </div>\n <lib-preview-list\n [isLoading]=\"svc.associatedConfigsLoading\"\n [allNames]=\"svc.addedConfigs\"\n [allowRemove]=\"true\"\n [clickable]=\"true\"\n [showfilter]=\"false\"\n [tooltip]=\"'View Config'\"\n (itemRemoved)=\"svc.removeConfig($event)\"\n (itemSelected)=\"svc.previewConfig($event, router)\"\n ></lib-preview-list>\n <div class=\"form-row space-between\">\n <div class=\"config-title-row\">\n <span class=\"form-field-title\">Service Policies</span>\n </div>\n <span class=\"form-field-count\">{{svc.associatedServicePoliciesTotal}}</span>\n </div>\n <lib-preview-list\n [isLoading]=\"svc.associatedServicePoliciesLoading\"\n [clickable]=\"true\"\n (itemSelected)=\"svc.previewPolicy($event, router)\"\n [tooltip]=\"'View Service Policy'\"\n [allNames]=\"svc.associatedServicePolicies\"\n [showfilter]=\"false\"\n ></lib-preview-list>\n <div class=\"form-row space-between\">\n <div class=\"config-title-row\">\n <span class=\"form-field-title\">Terminators</span>\n </div>\n <span class=\"form-field-count\">{{svc.associatedTerminators ? svc.associatedTerminators.length : 0}}</span>\n </div>\n <lib-preview-list\n [isLoading]=\"svc.associatedTerminatorsLoading\"\n [clickable]=\"true\"\n (itemSelected)=\"svc.previewTerminator($event, router)\"\n [tooltip]=\"'View Terminator'\"\n [allNames]=\"svc.associatedTerminators\"\n [showfilter]=\"false\"\n ></lib-preview-list>\n </lib-form-field-container>\n<!-- <lib-form-field-container\n *ngIf=\"formData.id\"\n [title]=\"'Associated Service Policies'\"\n [count]=\"svc.associatedServicePolicies.length\"\n [helpText]=\"'Preview list of all service policies that this service is associated with.'\"\n >\n </lib-form-field-container>-->\n <lib-form-field-container\n [title]=\"'API Calls'\"\n [label]=\"''\"\n [class]=\"'api-call-container'\"\n [helpText]=\"'Preview of the API URL and data model that is used to create/update this service'\"\n >\n <div class=\"form-row\">\n <input class=\"form-field-input\" [value]=\"apiCallURL\" readonly/>\n <div class=\"url-copy icon-copy copy\" (click)=\"copyToClipboard(apiCallURL)\"></div>\n </div>\n <lib-json-view *ngIf=\"formData\" [(data)]=\"svc.apiData\" [readOnly]=\"true\" [showCopy]=\"true\"></lib-json-view>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column\" *ngIf=\"formView === 'raw'\">\n <lib-json-view *ngIf=\"formData\" [(data)]=\"formData\" [(jsonInvalid)]=\"formDataInvalid\"></lib-json-view>\n </div>\n </div>\n</div>\n<lib-loading-indicator *ngIf=\"isLoading\" [isLoading]=\"isLoading\"></lib-loading-indicator>", styles: [".edge-router-form-container{display:flex;flex-direction:column;height:100%;width:100%;align-items:center;gap:15px}.form-field-dropdown{background-image:url(\"data:image/svg+xml,%3C%3Fxml version%3D%221.0%22 encoding%3D%22utf-8%22%3F%3E%3C!-- Generator%3A Adobe Illustrator 23.0.3%2C SVG Export Plug-In . SVG Version%3A 6.00 Build 0) --%3E%3Csvg id%3D'Stroke_Color' style%3D'enable-background%3Anew 0 0 20.2 10.8%3B' version%3D'1.1' viewBox%3D'0 0 20.2 10.8' x%3D'0px' xml%3Aspace%3D'preserve' xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg' y%3D'0px'%3E%3Cstyle type%3D'text%2Fcss'%3E%09.st0 %7B fill%3A %23668291%3B %7D%3C%2Fstyle%3E %3Cg%3E%09%3Cpath class%3D'st0' d%3D'M19.8%2C1.7c0%2C0.4-0.1%2C0.7-0.4%2C0.9l-8.5%2C7.3c-0.5%2C0.4-1.2%2C0.4-1.6%2C0L0.7%2C2.7C0.2%2C2.2%2C0.2%2C1.5%2C0.6%2C0.9%09%09c0.5-0.5%2C1.2-0.6%2C1.8-0.1l7.7%2C6.6l7.7-6.6c0.5-0.5%2C1.3-0.4%2C1.8%2C0.1C19.7%2C1.2%2C19.8%2C1.5%2C19.8%2C1.7z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E\");background-position:center right 10px;background-repeat:no-repeat;background-size:18px;padding-right:28px}.form-field-extended-fields{position:relative;display:flex;flex-direction:column}.form-field-extended-fields.cfg-preview{opacity:.8;filter:grayscale(.4);pointer-events:none}.form-header-toggle-container{display:flex;flex-direction:row;align-items:center}.form-header-toggle-container .form-header-toggle{display:flex;flex-direction:row;width:30px;height:18px;border-radius:10px;border-color:var(--inputBorder);border-style:solid;border-width:var(--inputBorderWidth);margin-left:5px;cursor:pointer;position:relative;margin-right:5px}.form-header-toggle-container .form-header-toggle:hover{filter:brightness(90%)}.form-header-toggle-container .form-header-toggle:active{transform:translateY(1px);filter:brightness(80%)}.form-header-toggle-container .form-header-toggle .form-toggle-switch{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;height:100%;margin-left:3px;position:absolute;transition:.5s;left:0}.form-header-toggle-container .form-header-toggle .form-toggle-switch.toggle-right{left:10px}.form-header-toggle-container .form-header-toggle .form-toggle-switch.toggle-right .form-toggle-indicator{border-color:var(--red)}.form-header-toggle-container .form-header-toggle .form-toggle-switch .form-toggle-indicator{height:10px;border-color:var(--green);border-style:solid;border-left-width:1px;border-right-width:1px;position:relative;margin-left:2px}.form-header-toggle-container .toggle-option-text{font-size:13px;font-weight:600;color:var(--placeholder);cursor:pointer}.form-header-toggle-container .toggle-option-text:hover{filter:brightness(90%)}.form-header-toggle-container .toggle-option-text:hover.toggle-option-selected{filter:unset}.form-header-toggle-container .toggle-option-text.toggle-option-selected{color:var(--tableText);cursor:default}.jsonButton{position:relative;top:0;margin:0;padding:10px;height:30px}.disabled{opacity:.5;pointer-events:none}.attach-config{display:flex;align-items:center;justify-content:center;font-weight:600;font-size:14px;background:var(--primary);padding:7px;border-radius:var(--inputBorderRadius);color:var(--white);cursor:pointer;box-shadow:0 3px 9px 0 var(--primaryColorOpaque);border:none;width:-moz-fit-content;width:fit-content}.attach-config:active{background:#648293;box-shadow:none;transform:translateY(1px)}.attach-config:hover{outline:0;filter:brightness(90%);box-shadow:0 2px 3px 0 var(--primaryColorOpaque)}::ng-deep .admin-toggle{width:100%;width:35%;display:flex}::ng-deep .admin-toggle .form-field-line{display:none}::ng-deep .admin-toggle .toggle{width:100%}::ng-deep .is-admin-container .form-field-title-container.title-container-2{width:35%!important}.svc-test-result{position:absolute;transition:var(--transition);height:0;width:100%;background-color:var(--background);bottom:0;font-weight:600;padding-left:10px;padding-right:10px;border-color:var(--inputBorder);border-style:solid;border-width:var(--inputBorderWidth);border-bottom-right-radius:var(--inputBorderRadius);border-bottom-left-radius:var(--inputBorderRadius);border-top-style:none}.svc-test-result.test-result-open{height:-moz-fit-content;height:fit-content;box-shadow:0 -2px 11px 0 var(--boxShadow);padding-bottom:15px;padding-top:15px}.svc-test-result .close.icon-close{top:10px;right:10px;font-size:18px;height:18px;width:18px;line-height:18px}.dropdown-container{display:flex;flex-direction:column;position:relative}.dropdown-container .spinner{display:inline-block;width:var(--spinnerSizeMedium);height:var(--spinnerSizeMedium);border-radius:50%;background:transparent;border-top:var(--spinerBorderTopMedium);border-right:var(--spinerBorderRightMedium);border-bottom:var(--spinerBorderBottomMedium);border-left:var(--spinerBorderLeftMedium);animation:loading .5s infinite linear;margin-left:var(--marginSmall);position:absolute;right:18px;top:20px;opacity:.7}.config-filter-container{display:flex;flex-direction:row}.config-filter-container .p-inputtext{border-radius:0;border-width:1px;border-color:var(--stroke);border-style:solid}.config-filter-container .p-inputtext:focus{box-shadow:none}.config-filter-container .p-inputgroup-addon{border-top-left-radius:var(--inputBorderRadius);border-bottom-left-radius:var(--inputBorderRadius)}.config-filter-container .p-button{border-radius:0;border-top-right-radius:var(--inputBorderRadius);border-bottom-right-radius:var(--inputBorderRadius);background-color:var(--primary)}.config-filter-container .p-button.configs-loading .p-button-icon{display:none}.config-filter-container .p-button:focus{box-shadow:none}::ng-deep .config-filter-container .p-button.configs-loading .p-button-icon{display:none}::ng-deep .admin-toggle .form-field-toggle-container:focus .form-field-label{color:var(--primaryColor)}::ng-deep .admin-toggle .form-field-toggle-container:focus .form-field-line{border-color:var(--primaryColor)}::ng-deep .admin-toggle .form-field-toggle-container:focus .toggle{border-color:var(--primaryColor);border-style:solid;border-width:var(--inputBorderWidth)}::ng-deep .admin-toggle .form-field-toggle-container:focus .toggle .switch{top:1px}::ng-deep .form-field-extended-fields .form-field-extended-fields{padding:0}\n"], dependencies: [{ kind: "directive", type: i1$4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i6$1.InputText, selector: "[pInputText]" }, { kind: "directive", type: i5$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i8.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { kind: "component", type: i4$2.Dropdown, selector: "p-dropdown", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: FormHeaderComponent, selector: "lib-form-header", inputs: ["data", "title", "moreActions", "formView", "saveDisabled", "saveTooltip", "actionButtonText", "moreActionsText"], outputs: ["formViewChange", "actionRequested"] }, { kind: "component", type: FormFieldContainerComponent, selector: "lib-form-field-container", inputs: ["title", "title2", "layout", "helpText", "helpText2", "label", "count", "action", "actionLabel", "class", "contentStyle", "showHeader", "headerActions"], outputs: ["actionRequested"] }, { kind: "component", type: PreviewListComponent, selector: "lib-preview-list", inputs: ["label", "clickable", "isLoading", "allNames", "items", "allowRemove", "tooltip", "showfilter"], outputs: ["itemSelected", "itemRemoved"] }, { kind: "component", type: LoadingIndicatorComponent, selector: "lib-loading-indicator", inputs: ["isLoading"] }, { kind: "component", type: FormFieldToggleComponent, selector: "lib-form-field-toggle", inputs: ["label", "orientation", "labelOn", "labelOff", "toggleOn"], outputs: ["toggleOnChange"] }, { kind: "component", type: JsonViewComponent, selector: "lib-json-view", inputs: ["data", "schema", "readOnly", "jsonInvalid", "showCopy"], outputs: ["dataChange", "jsonChange", "jsonInvalidChange"] }, { kind: "component", type: TagSelectorComponent, selector: "lib-tag-selector", inputs: ["placeholder", "disableField", "disableCreate", "hideOption", "isLoading", "errorMessage", "focusOnInit", "selectedRoleAttributes", "selectedNamedAttributes", "hasError", "availableRoleAttributes", "availableNamedAttributes"], outputs: ["addRoleAttribute", "addNamedAttribute", "roleAttributeRemoved", "namedAttributeRemoved", "selectedRoleAttributesChange", "selectedNamedAttributesChange", "filterChange"] }, { kind: "component", type: CustomTagsComponent, selector: "lib-custom-tags", inputs: ["tags"], outputs: ["tagsChange"] }, { kind: "component", type: ConfigEditorComponent, selector: "lib-config-editor", inputs: ["configErrors", "configData", "showJsonView", "schema"], outputs: ["configErrorsChange", "configDataChange"] }] }); }
16180
+ ], viewQueries: [{ propertyName: "configEditor", first: true, predicate: ["configEditor"], descendants: true, read: ConfigEditorComponent }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div class=\"projectable-form-wrapper\"\n (keyup.enter)=\"save($event)\"\n (keyup.escape)=\"returnToListPage()\"\n tabindex=\"0\"\n>\n <lib-form-header\n [data]=\"formData\"\n [title]=\"(formData.id ? 'Edit Service' : 'Create Service')\"\n [moreActions]=\"formData.moreActions\"\n (actionRequested)=\"headerActionRequested($event)\"\n [(formView)]=\"formView\"\n [saveDisabled]=\"svc.saveDisabled || formDataInvalid\"\n [saveTooltip]=\"saveButtonTooltip\"\n ></lib-form-header>\n <div class=\"edge-router-form-container projectable-form-container\">\n <div class=\"projectable-form-main-column form-group-row\" [hidden]=\"formView !== 'simple'\">\n <div class=\"form-group-column three-fifths\">\n <lib-form-field-container [title]=\"'Service Name'\" [label]=\"'Required'\">\n <input\n class=\"form-field-input\"\n placeholder=\"Name this Service\"\n [ngClass]=\"{error: svc.errors['name']}\"\n [(ngModel)]=\"formData.name\"\n autofocus\n #nameFieldInput\n />\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'Select or create Service attributes'\"\n [label]=\"'Optional'\"\n [contentStyle]=\"'z-index: 99999999'\"\n [helpText]=\"'Attributes are tags applied to a resource. Apply the same tag to other Services to form a group of Services.'\"\n >\n <lib-tag-selector\n [(selectedRoleAttributes)]=\"formData.roleAttributes\"\n [availableRoleAttributes]=\"serviceRoleAttributes\"\n [placeholder]=\"'Add attributes to group Services'\"\n ></lib-tag-selector>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'Add Configurations'\"\n (actionRequested)=\"attachConfig()\"\n (keyup.enter)=\"captureConfigEnterEvent($event)\"\n [helpText]=\"'Configurations are used to define how to intercept and host a service. Ziti Networks come with built-in configuration types (ie. intercept.v1 and host.v1)'\"\n >\n <div class=\"form-field-input-group\">\n <div class=\"config-title-row\">\n <span class=\"form-field-title\">Select a Config</span>\n </div>\n <select\n [(ngModel)]=\"svc.selectedConfigTypeId\"\n (change)=\"configTypeChanged($event)\"\n id=\"SelectedConfigType\"\n class=\"form-field-dropdown\"\n >\n <option value=\"\">Select configuration type...</option>\n <option\n *ngFor=\"let type of svc.configTypes\"\n [value]=\"type.id\"\n >\n {{ type.name }}\n </option>\n </select>\n <div class=\"dropdown-container\" [ngClass]=\"{'dropdown-loading': svc.configsLoading}\">\n <p-dropdown\n placeholder=\"Select configuration...\"\n optionLabel=\"name\"\n optionValue=\"id\"\n filterBy=\"name\"\n [options]=\"svc.filteredConfigs\"\n [filter]=\"true\"\n [showClear]=\"true\"\n [disabled]=\"!svc.selectedConfigTypeId || svc.selectedConfigTypeId === ''\"\n (change)=\"configChanged($event)\"\n [(ngModel)]=\"svc.selectedConfigId\"\n >\n <ng-template pTemplate=\"filter\" let-options=\"options\">\n <div class=\"dropdown-filter-container\">\n <div class=\"p-inputgroup\" (click)=\"$event.stopPropagation()\">\n <span class=\"p-inputgroup-addon\"><i class=\"pi pi-search\"></i></span>\n <input\n type=\"text\"\n pInputText\n placeholder=\"Filter\"\n (keyup)=\"configFilterChangedDebounced($event)\" />\n </div>\n <button pButton\n icon=\"pi pi-times\"\n [ngClass]=\"{'configs-loading': svc.configsLoading}\"\n (click)=\"clearConfigFilter($event)\"\n severity=\"secondary\">\n </button>\n <div class=\"spinner\" *ngIf=\"svc.configsLoading\"></div>\n </div>\n </ng-template>\n </p-dropdown>\n </div>\n <div *ngIf=\"!showConfigData && svc.selectedConfigId && svc.selectedConfigId !== '' && svc.selectedConfigId !== 'preview'\" class=\"button-row-right\" >\n <div class=\"save-button\" (click)=\"svc.attachConfig(svc.selectedConfigId)\">\n {{svc.attachLabel}}\n </div>\n </div>\n <div [hidden]=\"!showConfigData\" class=\"form-field-extended-fields\" [ngClass]=\"{'cfg-preview': svc.selectedConfigId === 'preview'}\">\n <div *ngIf=\"showConfigData\" class=\"config-title-row\" style=\"margin-bottom: 10px;\">\n <span class=\"form-field-title\">Config Name</span>\n <div\n class=\"save-button\"\n (click)=\"attachConfig()\"\n *ngIf=\"svc.selectedConfigId !== 'preview'\"\n >{{svc.attachLabel}}\n </div>\n </div>\n <input\n *ngIf=\"showConfigData\"\n [(ngModel)]=\"svc.newConfigName\"\n class=\"form-field-input\"\n [placeholder]=\"'New Config Name'\"\n [ngClass]=\"{error: svc.configErrors['name']}\"\n style=\"margin-bottom: 20px;\"\n />\n <div class=\"config-title-row\" style=\"margin-bottom: 10px;\">\n <span class=\"form-field-title\">Configuration Data</span>\n <div class=\"form-header-toggle-container\" *ngIf=\"svc.selectedConfigId !== 'preview'\">\n <span\n class=\"toggle-option-text\"\n [ngClass]=\"{'toggle-option-selected': !svc.configJsonView}\"\n (click)=\"svc.toggleJSONView()\"\n >\n FORM\n </span>\n <div class=\"form-header-toggle\" (click)=\"svc.toggleJSONView()\">\n <div\n class=\"form-toggle-switch\"\n [ngClass]=\"{'toggle-left': !svc.configJsonView, 'toggle-right': svc.configJsonView}\"\n >\n <div class=\"form-toggle-indicator\"></div>\n <div class=\"form-toggle-indicator\"></div>\n </div>\n </div>\n <span\n class=\"toggle-option-text\"\n [ngClass]=\"{'toggle-option-selected': svc.configJsonView}\"\n (click)=\"svc.toggleJSONView()\"\n >\n JSON\n </span>\n </div>\n </div>\n <lib-config-editor\n [(configData)]=\"svc.configData\"\n [schema]=\"svc.selectedSchema\"\n [showJsonView]=\"svc.configJsonView\"\n [(configErrors)]=\"svc.configErrors\"\n #configEditor\n ></lib-config-editor>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-toggle [(toggleOn)]=\"showMore\" style=\"margin: 0px 10px\"></lib-form-field-toggle>\n <div *ngIf=\"showMore\" class=\"form-group-column\">\n <lib-form-field-container\n [title]=\"'Terminator Strategy'\"\n [title2]=\"'Encryption'\"\n [layout]=\"'row'\"\n [helpText]=\"'Pick a strategy to determine how to rank available terminators for a service'\"\n [helpText2]=\"'Encrypts packets when entering or leaving the network.'\"\n class=\"form-field-advanced\"\n >\n <select\n [(ngModel)]=\"formData.terminatorStrategy\"\n id=\"authPolicyId\"\n class=\"form-field-dropdown\"\n >\n <option value=\"\">Select a Strategy....</option>\n <option\n *ngFor=\"let strat of strategies\"\n [value]=\"strat.id\"\n >\n {{ strat.label }}\n </option>\n </select>\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"config-container-label\">Require Encryption</div>\n <div\n (click)=\"toggleEncryptionRequired()\"\n [ngClass]=\"{ on: formData.encryptionRequired }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.encryptionRequired\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.encryptionRequired\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'Custom Tags'\"\n [label]=\"'OPTIONAL'\"\n class=\"form-field-advanced\"\n >\n <lib-custom-tags [(tags)]=\"formData.tags\"></lib-custom-tags>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column two-fifths\">\n <lib-form-field-container\n [title]=\"'Associated Entities'\"\n [label]=\"'Click for detailed view'\"\n [helpText]=\"'List the configs, policies, and terminators that are associated with this service. Click on the entity name to navigate to the entity\\'s detailed view.'\"\n [class]=\"'no-gap'\"\n >\n <div class=\"form-row space-between\" style=\"margin-top: 0;\">\n <div class=\"config-title-row\">\n <span class=\"form-field-title\">Configurations</span>\n </div>\n <span class=\"form-field-count\">{{svc.addedConfigs ? svc.addedConfigs.length : 0}}</span>\n </div>\n <lib-preview-list\n [isLoading]=\"svc.associatedConfigsLoading\"\n [allNames]=\"svc.addedConfigs\"\n [allowRemove]=\"true\"\n [clickable]=\"true\"\n [showfilter]=\"false\"\n [tooltip]=\"'View Config'\"\n (itemRemoved)=\"svc.removeConfig($event)\"\n (itemSelected)=\"svc.previewConfig($event, router)\"\n ></lib-preview-list>\n <div class=\"form-row space-between\">\n <div class=\"config-title-row\">\n <span class=\"form-field-title\">Service Policies</span>\n </div>\n <span class=\"form-field-count\">{{svc.associatedServicePoliciesTotal}}</span>\n </div>\n <lib-preview-list\n [isLoading]=\"svc.associatedServicePoliciesLoading\"\n [clickable]=\"true\"\n (itemSelected)=\"svc.previewPolicy($event, router)\"\n [tooltip]=\"'View Service Policy'\"\n [allNames]=\"svc.associatedServicePolicies\"\n [showfilter]=\"false\"\n ></lib-preview-list>\n <div class=\"form-row space-between\">\n <div class=\"config-title-row\">\n <span class=\"form-field-title\">Terminators</span>\n </div>\n <span class=\"form-field-count\">{{svc.associatedTerminators ? svc.associatedTerminators.length : 0}}</span>\n </div>\n <lib-preview-list\n [isLoading]=\"svc.associatedTerminatorsLoading\"\n [clickable]=\"true\"\n (itemSelected)=\"svc.previewTerminator($event, router)\"\n [tooltip]=\"'View Terminator'\"\n [allNames]=\"svc.associatedTerminators\"\n [showfilter]=\"false\"\n ></lib-preview-list>\n </lib-form-field-container>\n<!-- <lib-form-field-container\n *ngIf=\"formData.id\"\n [title]=\"'Associated Service Policies'\"\n [count]=\"svc.associatedServicePolicies.length\"\n [helpText]=\"'Preview list of all service policies that this service is associated with.'\"\n >\n </lib-form-field-container>-->\n <lib-form-field-container\n [title]=\"'API Calls'\"\n [label]=\"''\"\n [class]=\"'api-call-container'\"\n [helpText]=\"'Preview of the API URL and data model that is used to create/update this service'\"\n >\n <div class=\"form-row\">\n <input class=\"form-field-input\" [value]=\"apiCallURL\" readonly/>\n <div class=\"url-copy icon-copy copy\" (click)=\"copyToClipboard(apiCallURL)\"></div>\n </div>\n <lib-json-view *ngIf=\"formData\" [(data)]=\"svc.apiData\" [readOnly]=\"true\" [showCopy]=\"true\"></lib-json-view>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column\" *ngIf=\"formView === 'raw'\">\n <lib-json-view *ngIf=\"formData\" [(data)]=\"formData\" [(jsonInvalid)]=\"formDataInvalid\"></lib-json-view>\n </div>\n </div>\n</div>\n<lib-loading-indicator *ngIf=\"isLoading\" [isLoading]=\"isLoading\"></lib-loading-indicator>", styles: [".edge-router-form-container{display:flex;flex-direction:column;height:100%;width:100%;align-items:center;gap:15px}.form-field-dropdown{background-image:url(\"data:image/svg+xml,%3C%3Fxml version%3D%221.0%22 encoding%3D%22utf-8%22%3F%3E%3C!-- Generator%3A Adobe Illustrator 23.0.3%2C SVG Export Plug-In . SVG Version%3A 6.00 Build 0) --%3E%3Csvg id%3D'Stroke_Color' style%3D'enable-background%3Anew 0 0 20.2 10.8%3B' version%3D'1.1' viewBox%3D'0 0 20.2 10.8' x%3D'0px' xml%3Aspace%3D'preserve' xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg' y%3D'0px'%3E%3Cstyle type%3D'text%2Fcss'%3E%09.st0 %7B fill%3A %23668291%3B %7D%3C%2Fstyle%3E %3Cg%3E%09%3Cpath class%3D'st0' d%3D'M19.8%2C1.7c0%2C0.4-0.1%2C0.7-0.4%2C0.9l-8.5%2C7.3c-0.5%2C0.4-1.2%2C0.4-1.6%2C0L0.7%2C2.7C0.2%2C2.2%2C0.2%2C1.5%2C0.6%2C0.9%09%09c0.5-0.5%2C1.2-0.6%2C1.8-0.1l7.7%2C6.6l7.7-6.6c0.5-0.5%2C1.3-0.4%2C1.8%2C0.1C19.7%2C1.2%2C19.8%2C1.5%2C19.8%2C1.7z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E\");background-position:center right 10px;background-repeat:no-repeat;background-size:18px;padding-right:28px}.form-field-extended-fields{position:relative;display:flex;flex-direction:column}.form-field-extended-fields.cfg-preview{opacity:.8;filter:grayscale(.4);pointer-events:none}.form-header-toggle-container{display:flex;flex-direction:row;align-items:center}.form-header-toggle-container .form-header-toggle{display:flex;flex-direction:row;width:30px;height:18px;border-radius:10px;border-color:var(--inputBorder);border-style:solid;border-width:var(--inputBorderWidth);margin-left:5px;cursor:pointer;position:relative;margin-right:5px}.form-header-toggle-container .form-header-toggle:hover{filter:brightness(90%)}.form-header-toggle-container .form-header-toggle:active{transform:translateY(1px);filter:brightness(80%)}.form-header-toggle-container .form-header-toggle .form-toggle-switch{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;height:100%;margin-left:3px;position:absolute;transition:.5s;left:0}.form-header-toggle-container .form-header-toggle .form-toggle-switch.toggle-right{left:10px}.form-header-toggle-container .form-header-toggle .form-toggle-switch.toggle-right .form-toggle-indicator{border-color:var(--red)}.form-header-toggle-container .form-header-toggle .form-toggle-switch .form-toggle-indicator{height:10px;border-color:var(--green);border-style:solid;border-left-width:1px;border-right-width:1px;position:relative;margin-left:2px}.form-header-toggle-container .toggle-option-text{font-size:13px;font-weight:600;color:var(--placeholder);cursor:pointer}.form-header-toggle-container .toggle-option-text:hover{filter:brightness(90%)}.form-header-toggle-container .toggle-option-text:hover.toggle-option-selected{filter:unset}.form-header-toggle-container .toggle-option-text.toggle-option-selected{color:var(--tableText);cursor:default}.jsonButton{position:relative;top:0;margin:0;padding:10px;height:30px}.disabled{opacity:.5;pointer-events:none}.attach-config{display:flex;align-items:center;justify-content:center;font-weight:600;font-size:14px;background:var(--primary);padding:7px;border-radius:var(--inputBorderRadius);color:var(--white);cursor:pointer;box-shadow:0 3px 9px 0 var(--primaryColorOpaque);border:none;width:-moz-fit-content;width:fit-content}.attach-config:active{background:#648293;box-shadow:none;transform:translateY(1px)}.attach-config:hover{outline:0;filter:brightness(90%);box-shadow:0 2px 3px 0 var(--primaryColorOpaque)}::ng-deep .admin-toggle{width:100%;width:35%;display:flex}::ng-deep .admin-toggle .form-field-line{display:none}::ng-deep .admin-toggle .toggle{width:100%}::ng-deep .is-admin-container .form-field-title-container.title-container-2{width:35%!important}.svc-test-result{position:absolute;transition:var(--transition);height:0;width:100%;background-color:var(--background);bottom:0;font-weight:600;padding-left:10px;padding-right:10px;border-color:var(--inputBorder);border-style:solid;border-width:var(--inputBorderWidth);border-bottom-right-radius:var(--inputBorderRadius);border-bottom-left-radius:var(--inputBorderRadius);border-top-style:none}.svc-test-result.test-result-open{height:-moz-fit-content;height:fit-content;box-shadow:0 -2px 11px 0 var(--boxShadow);padding-bottom:15px;padding-top:15px}.svc-test-result .close.icon-close{top:10px;right:10px;font-size:18px;height:18px;width:18px;line-height:18px}.dropdown-container{display:flex;flex-direction:column;position:relative}::ng-deep .admin-toggle .form-field-toggle-container:focus .form-field-label{color:var(--primaryColor)}::ng-deep .admin-toggle .form-field-toggle-container:focus .form-field-line{border-color:var(--primaryColor)}::ng-deep .admin-toggle .form-field-toggle-container:focus .toggle{border-color:var(--primaryColor);border-style:solid;border-width:var(--inputBorderWidth)}::ng-deep .admin-toggle .form-field-toggle-container:focus .toggle .switch{top:1px}::ng-deep .form-field-extended-fields .form-field-extended-fields{padding:0}\n"], dependencies: [{ kind: "directive", type: i1$4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i6$1.InputText, selector: "[pInputText]" }, { kind: "directive", type: i5$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i8.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { kind: "component", type: i4$2.Dropdown, selector: "p-dropdown", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: FormHeaderComponent, selector: "lib-form-header", inputs: ["data", "title", "moreActions", "formView", "saveDisabled", "saveTooltip", "actionButtonText", "moreActionsText"], outputs: ["formViewChange", "actionRequested"] }, { kind: "component", type: FormFieldContainerComponent, selector: "lib-form-field-container", inputs: ["title", "title2", "layout", "helpText", "helpText2", "label", "count", "action", "actionLabel", "class", "contentStyle", "showHeader", "headerActions"], outputs: ["actionRequested"] }, { kind: "component", type: PreviewListComponent, selector: "lib-preview-list", inputs: ["label", "clickable", "isLoading", "allNames", "items", "allowRemove", "tooltip", "showfilter"], outputs: ["itemSelected", "itemRemoved"] }, { kind: "component", type: LoadingIndicatorComponent, selector: "lib-loading-indicator", inputs: ["isLoading"] }, { kind: "component", type: FormFieldToggleComponent, selector: "lib-form-field-toggle", inputs: ["label", "orientation", "labelOn", "labelOff", "toggleOn"], outputs: ["toggleOnChange"] }, { kind: "component", type: JsonViewComponent, selector: "lib-json-view", inputs: ["data", "schema", "readOnly", "jsonInvalid", "showCopy"], outputs: ["dataChange", "jsonChange", "jsonInvalidChange"] }, { kind: "component", type: TagSelectorComponent, selector: "lib-tag-selector", inputs: ["placeholder", "disableField", "disableCreate", "hideOption", "isLoading", "errorMessage", "focusOnInit", "selectedRoleAttributes", "selectedNamedAttributes", "hasError", "availableRoleAttributes", "availableNamedAttributes"], outputs: ["addRoleAttribute", "addNamedAttribute", "roleAttributeRemoved", "namedAttributeRemoved", "selectedRoleAttributesChange", "selectedNamedAttributesChange", "filterChange"] }, { kind: "component", type: CustomTagsComponent, selector: "lib-custom-tags", inputs: ["tags"], outputs: ["tagsChange"] }, { kind: "component", type: ConfigEditorComponent, selector: "lib-config-editor", inputs: ["configErrors", "configData", "showJsonView", "schema"], outputs: ["configErrorsChange", "configDataChange"] }] }); }
16143
16181
  }
16144
16182
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ServiceFormComponent, decorators: [{
16145
16183
  type: Component,
@@ -16148,7 +16186,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
16148
16186
  provide: MatDialogRef,
16149
16187
  useValue: {}
16150
16188
  }
16151
- ], template: "<div class=\"projectable-form-wrapper\"\n (keyup.enter)=\"save($event)\"\n (keyup.escape)=\"returnToListPage()\"\n tabindex=\"0\"\n>\n <lib-form-header\n [data]=\"formData\"\n [title]=\"(formData.id ? 'Edit Service' : 'Create Service')\"\n [moreActions]=\"formData.moreActions\"\n (actionRequested)=\"headerActionRequested($event)\"\n [(formView)]=\"formView\"\n [saveDisabled]=\"svc.saveDisabled || formDataInvalid\"\n [saveTooltip]=\"saveButtonTooltip\"\n ></lib-form-header>\n <div class=\"edge-router-form-container projectable-form-container\">\n <div class=\"projectable-form-main-column form-group-row\" [hidden]=\"formView !== 'simple'\">\n <div class=\"form-group-column three-fifths\">\n <lib-form-field-container [title]=\"'Service Name'\" [label]=\"'Required'\">\n <input\n class=\"form-field-input\"\n placeholder=\"Name this Service\"\n [ngClass]=\"{error: svc.errors['name']}\"\n [(ngModel)]=\"formData.name\"\n autofocus\n #nameFieldInput\n />\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'Select or create Service attributes'\"\n [label]=\"'Optional'\"\n [contentStyle]=\"'z-index: 99999999'\"\n [helpText]=\"'Attributes are tags applied to a resource. Apply the same tag to other Services to form a group of Services.'\"\n >\n <lib-tag-selector\n [(selectedRoleAttributes)]=\"formData.roleAttributes\"\n [availableRoleAttributes]=\"serviceRoleAttributes\"\n [placeholder]=\"'Add attributes to group Services'\"\n ></lib-tag-selector>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'Add Configurations'\"\n (actionRequested)=\"attachConfig()\"\n (keyup.enter)=\"captureConfigEnterEvent($event)\"\n [helpText]=\"'Configurations are used to define how to intercept and host a service. Ziti Networks come with built-in configuration types (ie. intercept.v1 and host.v1)'\"\n >\n <div class=\"form-field-input-group\">\n <div class=\"config-title-row\">\n <span class=\"form-field-title\">Select a Config</span>\n </div>\n <select\n [(ngModel)]=\"svc.selectedConfigTypeId\"\n (change)=\"configTypeChanged($event)\"\n id=\"SelectedConfigType\"\n class=\"form-field-dropdown\"\n >\n <option value=\"\">Select configuration type...</option>\n <option\n *ngFor=\"let type of svc.configTypes\"\n [value]=\"type.id\"\n >\n {{ type.name }}\n </option>\n </select>\n <div class=\"dropdown-container\" [ngClass]=\"{'dropdown-loading': svc.configsLoading}\">\n <p-dropdown\n placeholder=\"Select configuration...\"\n optionLabel=\"name\"\n optionValue=\"id\"\n filterBy=\"name\"\n [options]=\"svc.filteredConfigs\"\n [filter]=\"true\"\n [showClear]=\"true\"\n [disabled]=\"!svc.selectedConfigTypeId || svc.selectedConfigTypeId === ''\"\n (change)=\"configChanged($event)\"\n [(ngModel)]=\"svc.selectedConfigId\"\n >\n <ng-template pTemplate=\"filter\" let-options=\"options\">\n <div class=\"config-filter-container\">\n <div class=\"p-inputgroup\" (click)=\"$event.stopPropagation()\">\n <span class=\"p-inputgroup-addon\"><i class=\"pi pi-search\"></i></span>\n <input\n type=\"text\"\n pInputText\n placeholder=\"Filter\"\n (keyup)=\"configFilterChangedDebounced($event)\" />\n </div>\n <button pButton\n icon=\"pi pi-times\"\n [ngClass]=\"{'configs-loading': svc.configsLoading}\"\n (click)=\"clearConfigFilter($event)\"\n severity=\"secondary\">\n </button>\n <div class=\"spinner\" *ngIf=\"svc.configsLoading\"></div>\n </div>\n </ng-template>\n </p-dropdown>\n </div>\n <div *ngIf=\"!showConfigData && svc.selectedConfigId && svc.selectedConfigId !== '' && svc.selectedConfigId !== 'preview'\" class=\"button-row-right\" >\n <div class=\"save-button\" (click)=\"svc.attachConfig(svc.selectedConfigId)\">\n {{svc.attachLabel}}\n </div>\n </div>\n <div [hidden]=\"!showConfigData\" class=\"form-field-extended-fields\" [ngClass]=\"{'cfg-preview': svc.selectedConfigId === 'preview'}\">\n <div *ngIf=\"showConfigData\" class=\"config-title-row\" style=\"margin-bottom: 10px;\">\n <span class=\"form-field-title\">Config Name</span>\n <div\n class=\"save-button\"\n (click)=\"attachConfig()\"\n *ngIf=\"svc.selectedConfigId !== 'preview'\"\n >{{svc.attachLabel}}\n </div>\n </div>\n <input\n *ngIf=\"showConfigData\"\n [(ngModel)]=\"svc.newConfigName\"\n class=\"form-field-input\"\n [placeholder]=\"'New Config Name'\"\n [ngClass]=\"{error: svc.configErrors['name']}\"\n style=\"margin-bottom: 20px;\"\n />\n <div class=\"config-title-row\" style=\"margin-bottom: 10px;\">\n <span class=\"form-field-title\">Configuration Data</span>\n <div class=\"form-header-toggle-container\" *ngIf=\"svc.selectedConfigId !== 'preview'\">\n <span\n class=\"toggle-option-text\"\n [ngClass]=\"{'toggle-option-selected': !svc.configJsonView}\"\n (click)=\"svc.toggleJSONView()\"\n >\n FORM\n </span>\n <div class=\"form-header-toggle\" (click)=\"svc.toggleJSONView()\">\n <div\n class=\"form-toggle-switch\"\n [ngClass]=\"{'toggle-left': !svc.configJsonView, 'toggle-right': svc.configJsonView}\"\n >\n <div class=\"form-toggle-indicator\"></div>\n <div class=\"form-toggle-indicator\"></div>\n </div>\n </div>\n <span\n class=\"toggle-option-text\"\n [ngClass]=\"{'toggle-option-selected': svc.configJsonView}\"\n (click)=\"svc.toggleJSONView()\"\n >\n JSON\n </span>\n </div>\n </div>\n <lib-config-editor\n [(configData)]=\"svc.configData\"\n [schema]=\"svc.selectedSchema\"\n [showJsonView]=\"svc.configJsonView\"\n [(configErrors)]=\"svc.configErrors\"\n #configEditor\n ></lib-config-editor>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-toggle [(toggleOn)]=\"showMore\" style=\"margin: 0px 10px\"></lib-form-field-toggle>\n <div *ngIf=\"showMore\" class=\"form-group-column\">\n <lib-form-field-container\n [title]=\"'Terminator Strategy'\"\n [title2]=\"'Encryption'\"\n [layout]=\"'row'\"\n [helpText]=\"'Pick a strategy to determine how to rank available terminators for a service'\"\n [helpText2]=\"'Encrypts packets when entering or leaving the network.'\"\n class=\"form-field-advanced\"\n >\n <select\n [(ngModel)]=\"formData.terminatorStrategy\"\n id=\"authPolicyId\"\n class=\"form-field-dropdown\"\n >\n <option value=\"\">Select a Strategy....</option>\n <option\n *ngFor=\"let strat of strategies\"\n [value]=\"strat.id\"\n >\n {{ strat.label }}\n </option>\n </select>\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"config-container-label\">Require Encryption</div>\n <div\n (click)=\"toggleEncryptionRequired()\"\n [ngClass]=\"{ on: formData.encryptionRequired }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.encryptionRequired\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.encryptionRequired\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'Custom Tags'\"\n [label]=\"'OPTIONAL'\"\n class=\"form-field-advanced\"\n >\n <lib-custom-tags [(tags)]=\"formData.tags\"></lib-custom-tags>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column two-fifths\">\n <lib-form-field-container\n [title]=\"'Associated Entities'\"\n [label]=\"'Click for detailed view'\"\n [helpText]=\"'List the configs, policies, and terminators that are associated with this service. Click on the entity name to navigate to the entity\\'s detailed view.'\"\n [class]=\"'no-gap'\"\n >\n <div class=\"form-row space-between\" style=\"margin-top: 0;\">\n <div class=\"config-title-row\">\n <span class=\"form-field-title\">Configurations</span>\n </div>\n <span class=\"form-field-count\">{{svc.addedConfigs ? svc.addedConfigs.length : 0}}</span>\n </div>\n <lib-preview-list\n [isLoading]=\"svc.associatedConfigsLoading\"\n [allNames]=\"svc.addedConfigs\"\n [allowRemove]=\"true\"\n [clickable]=\"true\"\n [showfilter]=\"false\"\n [tooltip]=\"'View Config'\"\n (itemRemoved)=\"svc.removeConfig($event)\"\n (itemSelected)=\"svc.previewConfig($event, router)\"\n ></lib-preview-list>\n <div class=\"form-row space-between\">\n <div class=\"config-title-row\">\n <span class=\"form-field-title\">Service Policies</span>\n </div>\n <span class=\"form-field-count\">{{svc.associatedServicePoliciesTotal}}</span>\n </div>\n <lib-preview-list\n [isLoading]=\"svc.associatedServicePoliciesLoading\"\n [clickable]=\"true\"\n (itemSelected)=\"svc.previewPolicy($event, router)\"\n [tooltip]=\"'View Service Policy'\"\n [allNames]=\"svc.associatedServicePolicies\"\n [showfilter]=\"false\"\n ></lib-preview-list>\n <div class=\"form-row space-between\">\n <div class=\"config-title-row\">\n <span class=\"form-field-title\">Terminators</span>\n </div>\n <span class=\"form-field-count\">{{svc.associatedTerminators ? svc.associatedTerminators.length : 0}}</span>\n </div>\n <lib-preview-list\n [isLoading]=\"svc.associatedTerminatorsLoading\"\n [clickable]=\"true\"\n (itemSelected)=\"svc.previewTerminator($event, router)\"\n [tooltip]=\"'View Terminator'\"\n [allNames]=\"svc.associatedTerminators\"\n [showfilter]=\"false\"\n ></lib-preview-list>\n </lib-form-field-container>\n<!-- <lib-form-field-container\n *ngIf=\"formData.id\"\n [title]=\"'Associated Service Policies'\"\n [count]=\"svc.associatedServicePolicies.length\"\n [helpText]=\"'Preview list of all service policies that this service is associated with.'\"\n >\n </lib-form-field-container>-->\n <lib-form-field-container\n [title]=\"'API Calls'\"\n [label]=\"''\"\n [class]=\"'api-call-container'\"\n [helpText]=\"'Preview of the API URL and data model that is used to create/update this service'\"\n >\n <div class=\"form-row\">\n <input class=\"form-field-input\" [value]=\"apiCallURL\" readonly/>\n <div class=\"url-copy icon-copy copy\" (click)=\"copyToClipboard(apiCallURL)\"></div>\n </div>\n <lib-json-view *ngIf=\"formData\" [(data)]=\"svc.apiData\" [readOnly]=\"true\" [showCopy]=\"true\"></lib-json-view>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column\" *ngIf=\"formView === 'raw'\">\n <lib-json-view *ngIf=\"formData\" [(data)]=\"formData\" [(jsonInvalid)]=\"formDataInvalid\"></lib-json-view>\n </div>\n </div>\n</div>\n<lib-loading-indicator *ngIf=\"isLoading\" [isLoading]=\"isLoading\"></lib-loading-indicator>", styles: [".edge-router-form-container{display:flex;flex-direction:column;height:100%;width:100%;align-items:center;gap:15px}.form-field-dropdown{background-image:url(\"data:image/svg+xml,%3C%3Fxml version%3D%221.0%22 encoding%3D%22utf-8%22%3F%3E%3C!-- Generator%3A Adobe Illustrator 23.0.3%2C SVG Export Plug-In . SVG Version%3A 6.00 Build 0) --%3E%3Csvg id%3D'Stroke_Color' style%3D'enable-background%3Anew 0 0 20.2 10.8%3B' version%3D'1.1' viewBox%3D'0 0 20.2 10.8' x%3D'0px' xml%3Aspace%3D'preserve' xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg' y%3D'0px'%3E%3Cstyle type%3D'text%2Fcss'%3E%09.st0 %7B fill%3A %23668291%3B %7D%3C%2Fstyle%3E %3Cg%3E%09%3Cpath class%3D'st0' d%3D'M19.8%2C1.7c0%2C0.4-0.1%2C0.7-0.4%2C0.9l-8.5%2C7.3c-0.5%2C0.4-1.2%2C0.4-1.6%2C0L0.7%2C2.7C0.2%2C2.2%2C0.2%2C1.5%2C0.6%2C0.9%09%09c0.5-0.5%2C1.2-0.6%2C1.8-0.1l7.7%2C6.6l7.7-6.6c0.5-0.5%2C1.3-0.4%2C1.8%2C0.1C19.7%2C1.2%2C19.8%2C1.5%2C19.8%2C1.7z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E\");background-position:center right 10px;background-repeat:no-repeat;background-size:18px;padding-right:28px}.form-field-extended-fields{position:relative;display:flex;flex-direction:column}.form-field-extended-fields.cfg-preview{opacity:.8;filter:grayscale(.4);pointer-events:none}.form-header-toggle-container{display:flex;flex-direction:row;align-items:center}.form-header-toggle-container .form-header-toggle{display:flex;flex-direction:row;width:30px;height:18px;border-radius:10px;border-color:var(--inputBorder);border-style:solid;border-width:var(--inputBorderWidth);margin-left:5px;cursor:pointer;position:relative;margin-right:5px}.form-header-toggle-container .form-header-toggle:hover{filter:brightness(90%)}.form-header-toggle-container .form-header-toggle:active{transform:translateY(1px);filter:brightness(80%)}.form-header-toggle-container .form-header-toggle .form-toggle-switch{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;height:100%;margin-left:3px;position:absolute;transition:.5s;left:0}.form-header-toggle-container .form-header-toggle .form-toggle-switch.toggle-right{left:10px}.form-header-toggle-container .form-header-toggle .form-toggle-switch.toggle-right .form-toggle-indicator{border-color:var(--red)}.form-header-toggle-container .form-header-toggle .form-toggle-switch .form-toggle-indicator{height:10px;border-color:var(--green);border-style:solid;border-left-width:1px;border-right-width:1px;position:relative;margin-left:2px}.form-header-toggle-container .toggle-option-text{font-size:13px;font-weight:600;color:var(--placeholder);cursor:pointer}.form-header-toggle-container .toggle-option-text:hover{filter:brightness(90%)}.form-header-toggle-container .toggle-option-text:hover.toggle-option-selected{filter:unset}.form-header-toggle-container .toggle-option-text.toggle-option-selected{color:var(--tableText);cursor:default}.jsonButton{position:relative;top:0;margin:0;padding:10px;height:30px}.disabled{opacity:.5;pointer-events:none}.attach-config{display:flex;align-items:center;justify-content:center;font-weight:600;font-size:14px;background:var(--primary);padding:7px;border-radius:var(--inputBorderRadius);color:var(--white);cursor:pointer;box-shadow:0 3px 9px 0 var(--primaryColorOpaque);border:none;width:-moz-fit-content;width:fit-content}.attach-config:active{background:#648293;box-shadow:none;transform:translateY(1px)}.attach-config:hover{outline:0;filter:brightness(90%);box-shadow:0 2px 3px 0 var(--primaryColorOpaque)}::ng-deep .admin-toggle{width:100%;width:35%;display:flex}::ng-deep .admin-toggle .form-field-line{display:none}::ng-deep .admin-toggle .toggle{width:100%}::ng-deep .is-admin-container .form-field-title-container.title-container-2{width:35%!important}.svc-test-result{position:absolute;transition:var(--transition);height:0;width:100%;background-color:var(--background);bottom:0;font-weight:600;padding-left:10px;padding-right:10px;border-color:var(--inputBorder);border-style:solid;border-width:var(--inputBorderWidth);border-bottom-right-radius:var(--inputBorderRadius);border-bottom-left-radius:var(--inputBorderRadius);border-top-style:none}.svc-test-result.test-result-open{height:-moz-fit-content;height:fit-content;box-shadow:0 -2px 11px 0 var(--boxShadow);padding-bottom:15px;padding-top:15px}.svc-test-result .close.icon-close{top:10px;right:10px;font-size:18px;height:18px;width:18px;line-height:18px}.dropdown-container{display:flex;flex-direction:column;position:relative}.dropdown-container .spinner{display:inline-block;width:var(--spinnerSizeMedium);height:var(--spinnerSizeMedium);border-radius:50%;background:transparent;border-top:var(--spinerBorderTopMedium);border-right:var(--spinerBorderRightMedium);border-bottom:var(--spinerBorderBottomMedium);border-left:var(--spinerBorderLeftMedium);animation:loading .5s infinite linear;margin-left:var(--marginSmall);position:absolute;right:18px;top:20px;opacity:.7}.config-filter-container{display:flex;flex-direction:row}.config-filter-container .p-inputtext{border-radius:0;border-width:1px;border-color:var(--stroke);border-style:solid}.config-filter-container .p-inputtext:focus{box-shadow:none}.config-filter-container .p-inputgroup-addon{border-top-left-radius:var(--inputBorderRadius);border-bottom-left-radius:var(--inputBorderRadius)}.config-filter-container .p-button{border-radius:0;border-top-right-radius:var(--inputBorderRadius);border-bottom-right-radius:var(--inputBorderRadius);background-color:var(--primary)}.config-filter-container .p-button.configs-loading .p-button-icon{display:none}.config-filter-container .p-button:focus{box-shadow:none}::ng-deep .config-filter-container .p-button.configs-loading .p-button-icon{display:none}::ng-deep .admin-toggle .form-field-toggle-container:focus .form-field-label{color:var(--primaryColor)}::ng-deep .admin-toggle .form-field-toggle-container:focus .form-field-line{border-color:var(--primaryColor)}::ng-deep .admin-toggle .form-field-toggle-container:focus .toggle{border-color:var(--primaryColor);border-style:solid;border-width:var(--inputBorderWidth)}::ng-deep .admin-toggle .form-field-toggle-container:focus .toggle .switch{top:1px}::ng-deep .form-field-extended-fields .form-field-extended-fields{padding:0}\n"] }]
16189
+ ], template: "<div class=\"projectable-form-wrapper\"\n (keyup.enter)=\"save($event)\"\n (keyup.escape)=\"returnToListPage()\"\n tabindex=\"0\"\n>\n <lib-form-header\n [data]=\"formData\"\n [title]=\"(formData.id ? 'Edit Service' : 'Create Service')\"\n [moreActions]=\"formData.moreActions\"\n (actionRequested)=\"headerActionRequested($event)\"\n [(formView)]=\"formView\"\n [saveDisabled]=\"svc.saveDisabled || formDataInvalid\"\n [saveTooltip]=\"saveButtonTooltip\"\n ></lib-form-header>\n <div class=\"edge-router-form-container projectable-form-container\">\n <div class=\"projectable-form-main-column form-group-row\" [hidden]=\"formView !== 'simple'\">\n <div class=\"form-group-column three-fifths\">\n <lib-form-field-container [title]=\"'Service Name'\" [label]=\"'Required'\">\n <input\n class=\"form-field-input\"\n placeholder=\"Name this Service\"\n [ngClass]=\"{error: svc.errors['name']}\"\n [(ngModel)]=\"formData.name\"\n autofocus\n #nameFieldInput\n />\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'Select or create Service attributes'\"\n [label]=\"'Optional'\"\n [contentStyle]=\"'z-index: 99999999'\"\n [helpText]=\"'Attributes are tags applied to a resource. Apply the same tag to other Services to form a group of Services.'\"\n >\n <lib-tag-selector\n [(selectedRoleAttributes)]=\"formData.roleAttributes\"\n [availableRoleAttributes]=\"serviceRoleAttributes\"\n [placeholder]=\"'Add attributes to group Services'\"\n ></lib-tag-selector>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'Add Configurations'\"\n (actionRequested)=\"attachConfig()\"\n (keyup.enter)=\"captureConfigEnterEvent($event)\"\n [helpText]=\"'Configurations are used to define how to intercept and host a service. Ziti Networks come with built-in configuration types (ie. intercept.v1 and host.v1)'\"\n >\n <div class=\"form-field-input-group\">\n <div class=\"config-title-row\">\n <span class=\"form-field-title\">Select a Config</span>\n </div>\n <select\n [(ngModel)]=\"svc.selectedConfigTypeId\"\n (change)=\"configTypeChanged($event)\"\n id=\"SelectedConfigType\"\n class=\"form-field-dropdown\"\n >\n <option value=\"\">Select configuration type...</option>\n <option\n *ngFor=\"let type of svc.configTypes\"\n [value]=\"type.id\"\n >\n {{ type.name }}\n </option>\n </select>\n <div class=\"dropdown-container\" [ngClass]=\"{'dropdown-loading': svc.configsLoading}\">\n <p-dropdown\n placeholder=\"Select configuration...\"\n optionLabel=\"name\"\n optionValue=\"id\"\n filterBy=\"name\"\n [options]=\"svc.filteredConfigs\"\n [filter]=\"true\"\n [showClear]=\"true\"\n [disabled]=\"!svc.selectedConfigTypeId || svc.selectedConfigTypeId === ''\"\n (change)=\"configChanged($event)\"\n [(ngModel)]=\"svc.selectedConfigId\"\n >\n <ng-template pTemplate=\"filter\" let-options=\"options\">\n <div class=\"dropdown-filter-container\">\n <div class=\"p-inputgroup\" (click)=\"$event.stopPropagation()\">\n <span class=\"p-inputgroup-addon\"><i class=\"pi pi-search\"></i></span>\n <input\n type=\"text\"\n pInputText\n placeholder=\"Filter\"\n (keyup)=\"configFilterChangedDebounced($event)\" />\n </div>\n <button pButton\n icon=\"pi pi-times\"\n [ngClass]=\"{'configs-loading': svc.configsLoading}\"\n (click)=\"clearConfigFilter($event)\"\n severity=\"secondary\">\n </button>\n <div class=\"spinner\" *ngIf=\"svc.configsLoading\"></div>\n </div>\n </ng-template>\n </p-dropdown>\n </div>\n <div *ngIf=\"!showConfigData && svc.selectedConfigId && svc.selectedConfigId !== '' && svc.selectedConfigId !== 'preview'\" class=\"button-row-right\" >\n <div class=\"save-button\" (click)=\"svc.attachConfig(svc.selectedConfigId)\">\n {{svc.attachLabel}}\n </div>\n </div>\n <div [hidden]=\"!showConfigData\" class=\"form-field-extended-fields\" [ngClass]=\"{'cfg-preview': svc.selectedConfigId === 'preview'}\">\n <div *ngIf=\"showConfigData\" class=\"config-title-row\" style=\"margin-bottom: 10px;\">\n <span class=\"form-field-title\">Config Name</span>\n <div\n class=\"save-button\"\n (click)=\"attachConfig()\"\n *ngIf=\"svc.selectedConfigId !== 'preview'\"\n >{{svc.attachLabel}}\n </div>\n </div>\n <input\n *ngIf=\"showConfigData\"\n [(ngModel)]=\"svc.newConfigName\"\n class=\"form-field-input\"\n [placeholder]=\"'New Config Name'\"\n [ngClass]=\"{error: svc.configErrors['name']}\"\n style=\"margin-bottom: 20px;\"\n />\n <div class=\"config-title-row\" style=\"margin-bottom: 10px;\">\n <span class=\"form-field-title\">Configuration Data</span>\n <div class=\"form-header-toggle-container\" *ngIf=\"svc.selectedConfigId !== 'preview'\">\n <span\n class=\"toggle-option-text\"\n [ngClass]=\"{'toggle-option-selected': !svc.configJsonView}\"\n (click)=\"svc.toggleJSONView()\"\n >\n FORM\n </span>\n <div class=\"form-header-toggle\" (click)=\"svc.toggleJSONView()\">\n <div\n class=\"form-toggle-switch\"\n [ngClass]=\"{'toggle-left': !svc.configJsonView, 'toggle-right': svc.configJsonView}\"\n >\n <div class=\"form-toggle-indicator\"></div>\n <div class=\"form-toggle-indicator\"></div>\n </div>\n </div>\n <span\n class=\"toggle-option-text\"\n [ngClass]=\"{'toggle-option-selected': svc.configJsonView}\"\n (click)=\"svc.toggleJSONView()\"\n >\n JSON\n </span>\n </div>\n </div>\n <lib-config-editor\n [(configData)]=\"svc.configData\"\n [schema]=\"svc.selectedSchema\"\n [showJsonView]=\"svc.configJsonView\"\n [(configErrors)]=\"svc.configErrors\"\n #configEditor\n ></lib-config-editor>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-toggle [(toggleOn)]=\"showMore\" style=\"margin: 0px 10px\"></lib-form-field-toggle>\n <div *ngIf=\"showMore\" class=\"form-group-column\">\n <lib-form-field-container\n [title]=\"'Terminator Strategy'\"\n [title2]=\"'Encryption'\"\n [layout]=\"'row'\"\n [helpText]=\"'Pick a strategy to determine how to rank available terminators for a service'\"\n [helpText2]=\"'Encrypts packets when entering or leaving the network.'\"\n class=\"form-field-advanced\"\n >\n <select\n [(ngModel)]=\"formData.terminatorStrategy\"\n id=\"authPolicyId\"\n class=\"form-field-dropdown\"\n >\n <option value=\"\">Select a Strategy....</option>\n <option\n *ngFor=\"let strat of strategies\"\n [value]=\"strat.id\"\n >\n {{ strat.label }}\n </option>\n </select>\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"config-container-label\">Require Encryption</div>\n <div\n (click)=\"toggleEncryptionRequired()\"\n [ngClass]=\"{ on: formData.encryptionRequired }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.encryptionRequired\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.encryptionRequired\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'Custom Tags'\"\n [label]=\"'OPTIONAL'\"\n class=\"form-field-advanced\"\n >\n <lib-custom-tags [(tags)]=\"formData.tags\"></lib-custom-tags>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column two-fifths\">\n <lib-form-field-container\n [title]=\"'Associated Entities'\"\n [label]=\"'Click for detailed view'\"\n [helpText]=\"'List the configs, policies, and terminators that are associated with this service. Click on the entity name to navigate to the entity\\'s detailed view.'\"\n [class]=\"'no-gap'\"\n >\n <div class=\"form-row space-between\" style=\"margin-top: 0;\">\n <div class=\"config-title-row\">\n <span class=\"form-field-title\">Configurations</span>\n </div>\n <span class=\"form-field-count\">{{svc.addedConfigs ? svc.addedConfigs.length : 0}}</span>\n </div>\n <lib-preview-list\n [isLoading]=\"svc.associatedConfigsLoading\"\n [allNames]=\"svc.addedConfigs\"\n [allowRemove]=\"true\"\n [clickable]=\"true\"\n [showfilter]=\"false\"\n [tooltip]=\"'View Config'\"\n (itemRemoved)=\"svc.removeConfig($event)\"\n (itemSelected)=\"svc.previewConfig($event, router)\"\n ></lib-preview-list>\n <div class=\"form-row space-between\">\n <div class=\"config-title-row\">\n <span class=\"form-field-title\">Service Policies</span>\n </div>\n <span class=\"form-field-count\">{{svc.associatedServicePoliciesTotal}}</span>\n </div>\n <lib-preview-list\n [isLoading]=\"svc.associatedServicePoliciesLoading\"\n [clickable]=\"true\"\n (itemSelected)=\"svc.previewPolicy($event, router)\"\n [tooltip]=\"'View Service Policy'\"\n [allNames]=\"svc.associatedServicePolicies\"\n [showfilter]=\"false\"\n ></lib-preview-list>\n <div class=\"form-row space-between\">\n <div class=\"config-title-row\">\n <span class=\"form-field-title\">Terminators</span>\n </div>\n <span class=\"form-field-count\">{{svc.associatedTerminators ? svc.associatedTerminators.length : 0}}</span>\n </div>\n <lib-preview-list\n [isLoading]=\"svc.associatedTerminatorsLoading\"\n [clickable]=\"true\"\n (itemSelected)=\"svc.previewTerminator($event, router)\"\n [tooltip]=\"'View Terminator'\"\n [allNames]=\"svc.associatedTerminators\"\n [showfilter]=\"false\"\n ></lib-preview-list>\n </lib-form-field-container>\n<!-- <lib-form-field-container\n *ngIf=\"formData.id\"\n [title]=\"'Associated Service Policies'\"\n [count]=\"svc.associatedServicePolicies.length\"\n [helpText]=\"'Preview list of all service policies that this service is associated with.'\"\n >\n </lib-form-field-container>-->\n <lib-form-field-container\n [title]=\"'API Calls'\"\n [label]=\"''\"\n [class]=\"'api-call-container'\"\n [helpText]=\"'Preview of the API URL and data model that is used to create/update this service'\"\n >\n <div class=\"form-row\">\n <input class=\"form-field-input\" [value]=\"apiCallURL\" readonly/>\n <div class=\"url-copy icon-copy copy\" (click)=\"copyToClipboard(apiCallURL)\"></div>\n </div>\n <lib-json-view *ngIf=\"formData\" [(data)]=\"svc.apiData\" [readOnly]=\"true\" [showCopy]=\"true\"></lib-json-view>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column\" *ngIf=\"formView === 'raw'\">\n <lib-json-view *ngIf=\"formData\" [(data)]=\"formData\" [(jsonInvalid)]=\"formDataInvalid\"></lib-json-view>\n </div>\n </div>\n</div>\n<lib-loading-indicator *ngIf=\"isLoading\" [isLoading]=\"isLoading\"></lib-loading-indicator>", styles: [".edge-router-form-container{display:flex;flex-direction:column;height:100%;width:100%;align-items:center;gap:15px}.form-field-dropdown{background-image:url(\"data:image/svg+xml,%3C%3Fxml version%3D%221.0%22 encoding%3D%22utf-8%22%3F%3E%3C!-- Generator%3A Adobe Illustrator 23.0.3%2C SVG Export Plug-In . SVG Version%3A 6.00 Build 0) --%3E%3Csvg id%3D'Stroke_Color' style%3D'enable-background%3Anew 0 0 20.2 10.8%3B' version%3D'1.1' viewBox%3D'0 0 20.2 10.8' x%3D'0px' xml%3Aspace%3D'preserve' xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg' y%3D'0px'%3E%3Cstyle type%3D'text%2Fcss'%3E%09.st0 %7B fill%3A %23668291%3B %7D%3C%2Fstyle%3E %3Cg%3E%09%3Cpath class%3D'st0' d%3D'M19.8%2C1.7c0%2C0.4-0.1%2C0.7-0.4%2C0.9l-8.5%2C7.3c-0.5%2C0.4-1.2%2C0.4-1.6%2C0L0.7%2C2.7C0.2%2C2.2%2C0.2%2C1.5%2C0.6%2C0.9%09%09c0.5-0.5%2C1.2-0.6%2C1.8-0.1l7.7%2C6.6l7.7-6.6c0.5-0.5%2C1.3-0.4%2C1.8%2C0.1C19.7%2C1.2%2C19.8%2C1.5%2C19.8%2C1.7z'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E\");background-position:center right 10px;background-repeat:no-repeat;background-size:18px;padding-right:28px}.form-field-extended-fields{position:relative;display:flex;flex-direction:column}.form-field-extended-fields.cfg-preview{opacity:.8;filter:grayscale(.4);pointer-events:none}.form-header-toggle-container{display:flex;flex-direction:row;align-items:center}.form-header-toggle-container .form-header-toggle{display:flex;flex-direction:row;width:30px;height:18px;border-radius:10px;border-color:var(--inputBorder);border-style:solid;border-width:var(--inputBorderWidth);margin-left:5px;cursor:pointer;position:relative;margin-right:5px}.form-header-toggle-container .form-header-toggle:hover{filter:brightness(90%)}.form-header-toggle-container .form-header-toggle:active{transform:translateY(1px);filter:brightness(80%)}.form-header-toggle-container .form-header-toggle .form-toggle-switch{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;height:100%;margin-left:3px;position:absolute;transition:.5s;left:0}.form-header-toggle-container .form-header-toggle .form-toggle-switch.toggle-right{left:10px}.form-header-toggle-container .form-header-toggle .form-toggle-switch.toggle-right .form-toggle-indicator{border-color:var(--red)}.form-header-toggle-container .form-header-toggle .form-toggle-switch .form-toggle-indicator{height:10px;border-color:var(--green);border-style:solid;border-left-width:1px;border-right-width:1px;position:relative;margin-left:2px}.form-header-toggle-container .toggle-option-text{font-size:13px;font-weight:600;color:var(--placeholder);cursor:pointer}.form-header-toggle-container .toggle-option-text:hover{filter:brightness(90%)}.form-header-toggle-container .toggle-option-text:hover.toggle-option-selected{filter:unset}.form-header-toggle-container .toggle-option-text.toggle-option-selected{color:var(--tableText);cursor:default}.jsonButton{position:relative;top:0;margin:0;padding:10px;height:30px}.disabled{opacity:.5;pointer-events:none}.attach-config{display:flex;align-items:center;justify-content:center;font-weight:600;font-size:14px;background:var(--primary);padding:7px;border-radius:var(--inputBorderRadius);color:var(--white);cursor:pointer;box-shadow:0 3px 9px 0 var(--primaryColorOpaque);border:none;width:-moz-fit-content;width:fit-content}.attach-config:active{background:#648293;box-shadow:none;transform:translateY(1px)}.attach-config:hover{outline:0;filter:brightness(90%);box-shadow:0 2px 3px 0 var(--primaryColorOpaque)}::ng-deep .admin-toggle{width:100%;width:35%;display:flex}::ng-deep .admin-toggle .form-field-line{display:none}::ng-deep .admin-toggle .toggle{width:100%}::ng-deep .is-admin-container .form-field-title-container.title-container-2{width:35%!important}.svc-test-result{position:absolute;transition:var(--transition);height:0;width:100%;background-color:var(--background);bottom:0;font-weight:600;padding-left:10px;padding-right:10px;border-color:var(--inputBorder);border-style:solid;border-width:var(--inputBorderWidth);border-bottom-right-radius:var(--inputBorderRadius);border-bottom-left-radius:var(--inputBorderRadius);border-top-style:none}.svc-test-result.test-result-open{height:-moz-fit-content;height:fit-content;box-shadow:0 -2px 11px 0 var(--boxShadow);padding-bottom:15px;padding-top:15px}.svc-test-result .close.icon-close{top:10px;right:10px;font-size:18px;height:18px;width:18px;line-height:18px}.dropdown-container{display:flex;flex-direction:column;position:relative}::ng-deep .admin-toggle .form-field-toggle-container:focus .form-field-label{color:var(--primaryColor)}::ng-deep .admin-toggle .form-field-toggle-container:focus .form-field-line{border-color:var(--primaryColor)}::ng-deep .admin-toggle .form-field-toggle-container:focus .toggle{border-color:var(--primaryColor);border-style:solid;border-width:var(--inputBorderWidth)}::ng-deep .admin-toggle .form-field-toggle-container:focus .toggle .switch{top:1px}::ng-deep .form-field-extended-fields .form-field-extended-fields{padding:0}\n"] }]
16152
16190
  }], ctorParameters: function () { return [{ type: SettingsService, decorators: [{
16153
16191
  type: Inject,
16154
16192
  args: [SETTINGS_SERVICE]
@@ -20211,7 +20249,7 @@ class TerminatorsPageComponent extends ListPageComponent {
20211
20249
  this.formDataChanged = false;
20212
20250
  }
20213
20251
  ngOnInit() {
20214
- this.tabs = this.tabNames.getTabs('terminators');
20252
+ this.tabs = this.tabNames.getTabs('identities');
20215
20253
  this.svc.refreshData = this.refreshData;
20216
20254
  super.ngOnInit();
20217
20255
  }
@@ -20882,11 +20920,11 @@ class JwtSignersPageComponent extends ListPageComponent {
20882
20920
  this.formDataChanged = event;
20883
20921
  }
20884
20922
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: JwtSignersPageComponent, deps: [{ token: JwtSignersPageService }, { token: DataTableFilterService }, { token: TabNameService }, { token: ConsoleEventsService }, { token: i3$1.MatDialog }], target: i0.ɵɵFactoryTarget.Component }); }
20885
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: JwtSignersPageComponent, selector: "lib-configurations", usesInheritance: true, ngImport: i0, template: "<div class=\"ziti-page-container ziti-configs-container\">\n <lib-list-page-header [title]=\"title\"\n [tabs]=\"tabs\"\n [showAdd]=\"!itemsSelected\"\n (actionClicked)=\"headerActionClicked($event)\"></lib-list-page-header>\n\n <lib-data-table [tableId]=\"'configurations'\"\n [rowData]=\"rowData\"\n [columnDefinitions]=\"columnDefs\"\n (actionRequested)=\"tableAction($event)\"\n [startCount]=\"startCount\"\n [endCount]=\"endCount\"\n [totalCount]=\"totalCount\"\n [emptyMsg]=\"'No Configurations defined, Click the plus to add a Configuration.'\"\n [filterApplied]=\"filterApplied\"\n [menuItems]=\"svc.menuItems\"\n (gridReady)=\"gridReady($event)\"\n >\n </lib-data-table>\n</div>\n", styles: [".configurations{width:100%;height:100%;display:flex;flex-direction:column;position:relative;flex:1 1 auto}\n"], dependencies: [{ kind: "component", type: ListPageHeaderComponent, selector: "lib-list-page-header", inputs: ["title", "tabs", "showAdd", "hideAction"], outputs: ["actionClicked"] }, { kind: "component", type: DataTableComponent, selector: "lib-data-table", inputs: ["rowData", "expandRowData", "collapseRowData", "rowValidation", "isTimeSearchAvailable", "isLoading", "tableId", "options", "validateService", "rowsToggled", "tableRefreshCount", "view", "serverSideDataSource", "allowDownload", "startCount", "endCount", "totalCount", "emptyMsg", "filterApplied", "menuItems", "headerActions", "noItemsClass", "entityTypeName", "showNoItemsAdd", "currentPage", "noItemsImage", "rowHeight", "filterName", "filterColumn", "columnDefinitions", "refreshCount"], outputs: ["actionRequested", "gridReady", "dragStart", "dragLeave", "pageChanged"] }] }); }
20923
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: JwtSignersPageComponent, selector: "lib-jwt-signers", usesInheritance: true, ngImport: i0, template: "<div class=\"ziti-page-container ziti-configs-container\">\n <lib-list-page-header [title]=\"title\"\n [tabs]=\"tabs\"\n [showAdd]=\"!itemsSelected\"\n (actionClicked)=\"headerActionClicked($event)\"></lib-list-page-header>\n\n <lib-data-table [tableId]=\"'configurations'\"\n [rowData]=\"rowData\"\n [columnDefinitions]=\"columnDefs\"\n (actionRequested)=\"tableAction($event)\"\n [startCount]=\"startCount\"\n [endCount]=\"endCount\"\n [totalCount]=\"totalCount\"\n [emptyMsg]=\"'No Configurations defined, Click the plus to add a Configuration.'\"\n [filterApplied]=\"filterApplied\"\n [menuItems]=\"svc.menuItems\"\n (gridReady)=\"gridReady($event)\"\n >\n </lib-data-table>\n</div>\n", styles: [".configurations{width:100%;height:100%;display:flex;flex-direction:column;position:relative;flex:1 1 auto}\n"], dependencies: [{ kind: "component", type: ListPageHeaderComponent, selector: "lib-list-page-header", inputs: ["title", "tabs", "showAdd", "hideAction"], outputs: ["actionClicked"] }, { kind: "component", type: DataTableComponent, selector: "lib-data-table", inputs: ["rowData", "expandRowData", "collapseRowData", "rowValidation", "isTimeSearchAvailable", "isLoading", "tableId", "options", "validateService", "rowsToggled", "tableRefreshCount", "view", "serverSideDataSource", "allowDownload", "startCount", "endCount", "totalCount", "emptyMsg", "filterApplied", "menuItems", "headerActions", "noItemsClass", "entityTypeName", "showNoItemsAdd", "currentPage", "noItemsImage", "rowHeight", "filterName", "filterColumn", "columnDefinitions", "refreshCount"], outputs: ["actionRequested", "gridReady", "dragStart", "dragLeave", "pageChanged"] }] }); }
20886
20924
  }
20887
20925
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: JwtSignersPageComponent, decorators: [{
20888
20926
  type: Component,
20889
- args: [{ selector: 'lib-configurations', template: "<div class=\"ziti-page-container ziti-configs-container\">\n <lib-list-page-header [title]=\"title\"\n [tabs]=\"tabs\"\n [showAdd]=\"!itemsSelected\"\n (actionClicked)=\"headerActionClicked($event)\"></lib-list-page-header>\n\n <lib-data-table [tableId]=\"'configurations'\"\n [rowData]=\"rowData\"\n [columnDefinitions]=\"columnDefs\"\n (actionRequested)=\"tableAction($event)\"\n [startCount]=\"startCount\"\n [endCount]=\"endCount\"\n [totalCount]=\"totalCount\"\n [emptyMsg]=\"'No Configurations defined, Click the plus to add a Configuration.'\"\n [filterApplied]=\"filterApplied\"\n [menuItems]=\"svc.menuItems\"\n (gridReady)=\"gridReady($event)\"\n >\n </lib-data-table>\n</div>\n", styles: [".configurations{width:100%;height:100%;display:flex;flex-direction:column;position:relative;flex:1 1 auto}\n"] }]
20927
+ args: [{ selector: 'lib-jwt-signers', template: "<div class=\"ziti-page-container ziti-configs-container\">\n <lib-list-page-header [title]=\"title\"\n [tabs]=\"tabs\"\n [showAdd]=\"!itemsSelected\"\n (actionClicked)=\"headerActionClicked($event)\"></lib-list-page-header>\n\n <lib-data-table [tableId]=\"'configurations'\"\n [rowData]=\"rowData\"\n [columnDefinitions]=\"columnDefs\"\n (actionRequested)=\"tableAction($event)\"\n [startCount]=\"startCount\"\n [endCount]=\"endCount\"\n [totalCount]=\"totalCount\"\n [emptyMsg]=\"'No Configurations defined, Click the plus to add a Configuration.'\"\n [filterApplied]=\"filterApplied\"\n [menuItems]=\"svc.menuItems\"\n (gridReady)=\"gridReady($event)\"\n >\n </lib-data-table>\n</div>\n", styles: [".configurations{width:100%;height:100%;display:flex;flex-direction:column;position:relative;flex:1 1 auto}\n"] }]
20890
20928
  }], ctorParameters: function () { return [{ type: JwtSignersPageService }, { type: DataTableFilterService }, { type: TabNameService }, { type: ConsoleEventsService }, { type: i3$1.MatDialog }]; } });
20891
20929
 
20892
20930
  class JwtSigner {
@@ -20894,13 +20932,15 @@ class JwtSigner {
20894
20932
  this.name = '';
20895
20933
  this.audience = '';
20896
20934
  this.issuer = '';
20897
- this.certPem = '';
20935
+ this.clientId = '';
20898
20936
  this.claimsProperty = '';
20899
20937
  this.enabled = true;
20900
20938
  this.useExternalId = false;
20901
20939
  this.externalAuthUrl = '';
20902
20940
  this.kid = '';
20941
+ this.scopes = [];
20903
20942
  this.jwksEndpoint = undefined;
20943
+ this.certPem = undefined;
20904
20944
  this.tags = {};
20905
20945
  }
20906
20946
  }
@@ -20921,7 +20961,7 @@ class JwtSignerFormService {
20921
20961
  const data = this.getJwtSignerDataModel(formData, isUpdate);
20922
20962
  let prom;
20923
20963
  if (isUpdate) {
20924
- prom = this.dataService.patch('external-jwt-signers', data, formData.id, true);
20964
+ prom = this.dataService.put('external-jwt-signers', data, formData.id, true);
20925
20965
  }
20926
20966
  else {
20927
20967
  prom = this.dataService.post('external-jwt-signers', data, true);
@@ -21023,6 +21063,7 @@ class JwtSignerFormComponent extends ProjectableForm {
21023
21063
  this.items = [];
21024
21064
  this.settings = {};
21025
21065
  this.fileSelectOpening = false;
21066
+ this.signatureMethod = "JWKS_ENDPOINT";
21026
21067
  this.entityType = 'external-jwt-signers';
21027
21068
  this.entityClass = JwtSigner;
21028
21069
  this._apiData = {};
@@ -21103,17 +21144,40 @@ class JwtSignerFormComponent extends ProjectableForm {
21103
21144
  this.errors.issuer = true;
21104
21145
  labels.push('Issuer');
21105
21146
  }
21106
- if (isEmpty(this.formData.certPem)) {
21147
+ if (isEmpty(this.formData.certPem) && isEmpty(this.formData.jwksEndpoint)) {
21107
21148
  this.errors.certPem = true;
21108
- labels.push('Cert PEM');
21149
+ this.errors.jwksEndpoint = true;
21150
+ labels.push('Cert PEM or JWKS Endpoint');
21109
21151
  }
21110
21152
  if (!isEmpty(this.errors)) {
21111
21153
  let missingFields = labels.join(', ');
21112
21154
  growlers.push(new GrowlerModel('error', 'Invalid', `Missing Form Data`, `Please enter a value for the highlighted fields: ${missingFields}`));
21113
21155
  }
21114
- if (!isEmpty(this.formData.certPem?.trim()) && !this.validationService.isValidPEM(this.formData.certPem?.trim())) {
21115
- this.errors.certPem = true;
21116
- growlers.push(new GrowlerModel('error', 'Invalid', `Cert PEM Invalid`, `The value you have entered for the Cert PEM field is invalid. Please check your input and try again.`));
21156
+ if (!isEmpty(growlers)) {
21157
+ growlers.forEach((growlerData) => {
21158
+ this.growlerService.show(growlerData);
21159
+ });
21160
+ return isEmpty(this.errors);
21161
+ }
21162
+ if (this.signatureMethod === 'JWKS_ENDPOINT') {
21163
+ if (isEmpty(this.formData.jwksEndpoint)) {
21164
+ this.errors.jwksEndpoint = true;
21165
+ growlers.push(new GrowlerModel('error', 'Invalid', `Missing JWKS Endpoint`, `Please enter a URI for the JWKS Endpoint.`));
21166
+ }
21167
+ else if (!this.validationService.isValidURI(this.formData.jwksEndpoint)) {
21168
+ this.errors.jwksEndpoint = true;
21169
+ growlers.push(new GrowlerModel('error', 'Invalid', `JWKS Endpoint Invalid`, `The value you have entered for the JWKS Endpoint field is invalid. Please check your input and try again.`));
21170
+ }
21171
+ }
21172
+ else if (this.signatureMethod === 'CERT_PEM') {
21173
+ if (isEmpty(this.formData.certPem)) {
21174
+ this.errors.certPem = true;
21175
+ growlers.push(new GrowlerModel('error', 'Invalid', `Missing Cert PEM`, `Please enter a URI for the JWKS Endpoint.`));
21176
+ }
21177
+ else if (!this.validationService.isValidPEM(this.formData.certPem?.trim())) {
21178
+ this.errors.certPem = true;
21179
+ growlers.push(new GrowlerModel('error', 'Invalid', `Cert PEM Invalid`, `The Cert PEM you entered is invalid. Please check your input and try again.`));
21180
+ }
21117
21181
  }
21118
21182
  growlers.forEach((growlerData) => {
21119
21183
  this.growlerService.show(growlerData);
@@ -21128,12 +21192,14 @@ class JwtSignerFormComponent extends ProjectableForm {
21128
21192
  name: this.formData.name || '',
21129
21193
  audience: this.formData.audience || '',
21130
21194
  issuer: this.formData.issuer || '',
21195
+ clientId: this.formData.clientId || '',
21131
21196
  certPem: this.formData.certPem || '',
21132
21197
  claimsProperty: this.formData.claimsProperty || '',
21133
21198
  enabled: this.formData.enabled,
21134
21199
  useExternalId: this.formData.useExternalId,
21135
- externalAuthUrl: this.formData.externalAuthUrl || '',
21136
21200
  kid: this.formData.kid || '',
21201
+ externalAuthUrl: this.formData.externalAuthUrl || '',
21202
+ scopes: this.formData.scopes || [],
21137
21203
  tags: this.formData.tags || {}
21138
21204
  };
21139
21205
  if (!isEmpty(this.formData.jwksEndpoint)) {
@@ -21145,6 +21211,12 @@ class JwtSignerFormComponent extends ProjectableForm {
21145
21211
  if (this.formData.id) {
21146
21212
  data.id = this.formData.id;
21147
21213
  }
21214
+ if (this.signatureMethod === 'JWKS_ENDPOINT') {
21215
+ data.certPem = undefined;
21216
+ }
21217
+ else {
21218
+ data.jwksEndpoint = undefined;
21219
+ }
21148
21220
  this._apiData = data;
21149
21221
  return this._apiData;
21150
21222
  }
@@ -21160,6 +21232,21 @@ class JwtSignerFormComponent extends ProjectableForm {
21160
21232
  toggleUseExternalId() {
21161
21233
  this.formData.useExternalId = !this.formData.useExternalId;
21162
21234
  }
21235
+ radioKeyDownHandler(event) {
21236
+ switch (event.key) {
21237
+ case 'ArrowLeft':
21238
+ this.signatureMethod = 'JWKS_ENDPOINT';
21239
+ break;
21240
+ case 'ArrowRight':
21241
+ this.signatureMethod = 'CERT_PEM';
21242
+ break;
21243
+ default:
21244
+ break;
21245
+ }
21246
+ }
21247
+ selectSignatureMethod(method) {
21248
+ this.signatureMethod = method;
21249
+ }
21163
21250
  openFileSelect(event) {
21164
21251
  this.filterInput.nativeElement.click();
21165
21252
  this.fileSelectOpening = true;
@@ -21215,12 +21302,22 @@ class JwtSignerFormComponent extends ProjectableForm {
21215
21302
  const growlerData = new GrowlerModel('success', 'Success', `Text Copied`, `CURL command copied to clipboard`);
21216
21303
  this.growlerService.show(growlerData);
21217
21304
  }
21305
+ scopesOnKeyup(event) {
21306
+ const key = event.key?.toLowerCase();
21307
+ if (key === " " || key === 'enter') {
21308
+ event.preventDefault();
21309
+ event.stopPropagation();
21310
+ const element = event.target;
21311
+ element.blur();
21312
+ element.focus();
21313
+ }
21314
+ }
21218
21315
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: JwtSignerFormComponent, deps: [{ token: JwtSignerFormService }, { token: SchemaService }, { token: GrowlerService }, { token: SHAREDZ_EXTENSION }, { token: SETTINGS_SERVICE }, { token: ZITI_DATA_SERVICE }, { token: i4.Router }, { token: i4.ActivatedRoute }, { token: i1$4.Location }, { token: ValidationService }], target: i0.ɵɵFactoryTarget.Component }); }
21219
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: JwtSignerFormComponent, selector: "lib-configuration", inputs: { formData: "formData", errors: "errors" }, outputs: { close: "close" }, viewQueries: [{ propertyName: "filterInput", first: true, predicate: ["fileSelect"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"projectable-form-wrapper\"\n (keyup.enter)=\"save($event)\"\n (keyup.escape)=\"closeModal(false)\"\n tabindex=\"0\"\n>\n <lib-form-header\n [data]=\"formData\"\n [title]=\"(formData.id ? 'JWT Signer Details' : 'Create JWT Signer')\"\n [moreActions]=\"formData.moreActions\"\n (actionRequested)=\"headerActionRequested($event)\"\n [(formView)]=\"formView\"\n [saveDisabled]=\"svc.saveDisabled || formDataInvalid\"\n ></lib-form-header>\n <div class=\"jwt-signer-form-container projectable-form-container\">\n <div class=\"projectable-form-main-column form-group-row\" [hidden]=\"formView !== 'simple'\">\n <div class=\"form-group-column three-fifths\">\n <lib-form-field-container\n [title]=\"'Name'\"\n [label]=\"'Required'\"\n >\n <input class=\"form-field-input read-only\" [(ngModel)]=\"formData.name\" [ngClass]=\"{error: errors['name']}\" placeholder=\"Name this JWT Signer\"/>\n </lib-form-field-container>\n <lib-form-field-container\n [layout]=\"'column'\"\n [showHeader]=\"false\"\n >\n <div class=\"form-field-label-container\">\n <div class=\"form-field-header\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Issuer</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"The &quot;issuer&quot; field on the JWT Signer must match the &quot;iss&quot; field on the JWT\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <span class=\"form-field-label\" >Required</span>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter issuer\" [(ngModel)]=\"formData.issuer\" [ngClass]=\"{error: errors['issuer']}\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Claims Property</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"The &quot;claimsProperty&quot; must match the &quot;id&quot; field on a ziti identity (or externalId if &quot;Use External ID&quot; is enabled)\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter claims property, defaults to &quot;sub&quot;\" [(ngModel)]=\"formData.claimsProperty\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Audience</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"The &quot;audience&quot; field on the JWT Signer must match the &quot;aud&quot; field on the JWT\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter audience\" [(ngModel)]=\"formData.audience\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">External Auth Url</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Unauthenticated clients can enumerate External JWT Signers that have an &quot;externalAuthUrl&quot; property. Clients will receive the name of the External JWT Signer and the &quot;externalAuthUrl&quot; only. This information can allow clients to initiate client authentication to the target identity provider.\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter external auth URL\" [(ngModel)]=\"formData.externalAuthUrl\"/>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n [showHeader]=\"false\"\n [layout]=\"'row'\"\n >\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"config-container-label\">ENABLED</div>\n <div\n (click)=\"toggleEnabled()\"\n [ngClass]=\"{ on: formData.enabled }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.enabled\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.enabled\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"config-container-label\">Use External ID</div>\n <div\n (click)=\"toggleUseExternalId()\"\n [ngClass]=\"{ on: formData.useExternalId }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.useExternalId\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.useExternalId\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-toggle [(toggleOn)]=\"showMore\" (toggleOnChange)=\"showMoreChanged($event)\" style=\"margin: 0px 10px\"></lib-form-field-toggle>\n <div [hidden]=\"!showMore\" class=\"form-group-column\">\n <lib-form-field-container\n [title]=\"'Custom Tags'\"\n [label]=\"'OPTIONAL'\"\n class=\"form-field-advanced\"\n >\n <lib-custom-tags [(tags)]=\"formData.tags\"></lib-custom-tags>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column two-fifths\">\n <lib-form-field-container\n [title]=\"'Certificate Definition'\"\n [label]=\"'REQUIRED'\"\n >\n <div class=\"form-field-input-group\">\n <div class=\"form-field-label-container select-file-label-container\">\n <div class=\"form-field-header\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">PEM</span>\n </div>\n <span class=\"select-file-button\" (click)=\"openFileSelect($event)\">\n Select File\n <div class=\"spinner\" *ngIf=\"fileSelectOpening\"></div>\n </span>\n <input #fileSelect type=\"file\" style=\"display:none\" (change)=\"selectPemFile($event)\">\n </div>\n <textarea placeholder=\"Paste pem contents or select file\" [(ngModel)]=\"formData.certPem\" [ngClass]=\"{error: errors['certPem']}\"></textarea>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-header\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">KID</span>\n </div>\n <span class=\"form-field-label\" >Optional</span>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter KID\" [(ngModel)]=\"formData.kid\"/>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'JWKS Endpoint'\"\n [label]=\"'Optional'\"\n >\n <input class=\"form-field-input read-only\" placeholder=\"Enter endpoint URL\" [(ngModel)]=\"formData.jwksEndpoint\"/>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'API Calls'\"\n [headerActions]=\"apiOptions\"\n (actionRequested)=\"apiActionRequested($event)\"\n [class]=\"'api-data-no-wrap'\"\n >\n <div class=\"form-row\">\n <input class=\"form-field-input\" [value]=\"apiCallURL\"/>\n <div class=\"icon-copy copy\" (click)=\"copyToClipboard(apiCallURL)\"></div>\n </div>\n <lib-json-view *ngIf=\"formData\" [(data)]=\"apiData\" [readOnly]=\"true\" [showCopy]=\"true\"></lib-json-view>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column\" *ngIf=\"formView === 'raw'\">\n <lib-json-view *ngIf=\"formData\" [(data)]=\"formData\"></lib-json-view>\n </div>\n </div>\n</div>\n<lib-loading-indicator *ngIf=\"isLoading\" [isLoading]=\"isLoading\"></lib-loading-indicator>\n", styles: ["@charset \"UTF-8\";.jwt-signer-form-container{display:flex;flex-direction:column;height:100%;width:100%;align-items:center;gap:var(--gapXL)}.jwt-signer-form-container .select-file-button{padding-left:var(--paddingMedium);padding-right:var(--paddingMedium);height:25px;width:-moz-fit-content;width:fit-content;white-space:nowrap;display:flex;align-items:center;justify-content:center;font-weight:600;font-size:14px;background:var(--primary);border-style:solid;border-width:1px;border-color:var(--stroke);color:var(--white);cursor:pointer;border-radius:var(--inputBorderRadius);gap:var(--marginMedium)}.jwt-signer-form-container .select-file-button:hover{filter:brightness(.8)}.jwt-signer-form-container .select-file-button:active{filter:grayscale(1);transform:translateY(1px)}.jwt-signer-form-container .select-file-button .spinner{display:inline-block;width:8px;height:8px;border-radius:50%;background:transparent;border-top:2px solid white;border-right:2px solid white;border-bottom:2px solid transparent;border-left:2px solid transparent;animation:loading .5s infinite linear}.jwt-signer-form-container .select-file-label-container{gap:var(--marginMedium)}::ng-deep .jwt-signer-form-container select:disabled,::ng-deep .jwt-signer-form-container input:disabled{opacity:.75!important;cursor:text;background-color:var(--stroke)!important}::ng-deep .api-data-no-wrap .jse-text-mode{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller .cm-content{width:100%;overflow:auto}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller .cm-content .\\37cr{white-space:nowrap}\n"], dependencies: [{ kind: "directive", type: i1$4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: FormHeaderComponent, selector: "lib-form-header", inputs: ["data", "title", "moreActions", "formView", "saveDisabled", "saveTooltip", "actionButtonText", "moreActionsText"], outputs: ["formViewChange", "actionRequested"] }, { kind: "component", type: FormFieldContainerComponent, selector: "lib-form-field-container", inputs: ["title", "title2", "layout", "helpText", "helpText2", "label", "count", "action", "actionLabel", "class", "contentStyle", "showHeader", "headerActions"], outputs: ["actionRequested"] }, { kind: "component", type: LoadingIndicatorComponent, selector: "lib-loading-indicator", inputs: ["isLoading"] }, { kind: "component", type: FormFieldToggleComponent, selector: "lib-form-field-toggle", inputs: ["label", "orientation", "labelOn", "labelOff", "toggleOn"], outputs: ["toggleOnChange"] }, { kind: "component", type: JsonViewComponent, selector: "lib-json-view", inputs: ["data", "schema", "readOnly", "jsonInvalid", "showCopy"], outputs: ["dataChange", "jsonChange", "jsonInvalidChange"] }, { kind: "component", type: CustomTagsComponent, selector: "lib-custom-tags", inputs: ["tags"], outputs: ["tagsChange"] }] }); }
21316
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: JwtSignerFormComponent, selector: "lib-configuration", inputs: { formData: "formData", errors: "errors" }, outputs: { close: "close" }, viewQueries: [{ propertyName: "filterInput", first: true, predicate: ["fileSelect"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"projectable-form-wrapper\"\n (keyup.enter)=\"save($event)\"\n (keyup.escape)=\"closeModal(false)\"\n tabindex=\"0\"\n>\n <lib-form-header\n [data]=\"formData\"\n [title]=\"(formData.id ? 'JWT Signer Details' : 'Create JWT Signer')\"\n [moreActions]=\"formData.moreActions\"\n (actionRequested)=\"headerActionRequested($event)\"\n [(formView)]=\"formView\"\n [saveDisabled]=\"svc.saveDisabled || formDataInvalid\"\n ></lib-form-header>\n <div class=\"jwt-signer-form-container projectable-form-container\">\n <div class=\"projectable-form-main-column form-group-row\" [hidden]=\"formView !== 'simple'\">\n <div class=\"form-group-column three-fifths\">\n <lib-form-field-container\n [title]=\"'Name'\"\n [label]=\"'Required'\"\n >\n <input class=\"form-field-input read-only\" [(ngModel)]=\"formData.name\" [ngClass]=\"{error: errors['name']}\" placeholder=\"Name this JWT Signer\"/>\n </lib-form-field-container>\n <lib-form-field-container\n [layout]=\"'column'\"\n [showHeader]=\"false\"\n >\n <div class=\"form-field-label-container\">\n <div class=\"form-field-header\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Issuer</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"The &quot;issuer&quot; field on the JWT Signer must match the &quot;iss&quot; field on the JWT\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <span class=\"form-field-label\" >Required</span>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter issuer\" [(ngModel)]=\"formData.issuer\" [ngClass]=\"{error: errors['issuer']}\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Audience</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"The expected &quot;aud&quot; (audience) field on the JWT\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter audience\" [(ngModel)]=\"formData.audience\"/>\n </div>\n <div class=\"form-field-row\">\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Claims Property</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"The field on the JWT for mapping to an identity. Matches the identity's id or externalId if &quot;Use External Id&quot; is set to true. Defaults to &quot;sub&quot;\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter claims property\" [(ngModel)]=\"formData.claimsProperty\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-header\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\" style=\"font-weight: 600; font-size: 14px;\">External ID</div>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"If enabled, will match the &quot;claimsProperty&quot; to an identity's &quot;externalId&quot; field. If false, it will match to the identity's id field.\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n </div>\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">Use External ID</div>\n </div>\n <div\n (click)=\"toggleUseExternalId()\"\n [ngClass]=\"{ on: formData.useExternalId }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.useExternalId\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.useExternalId\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-toggle [(toggleOn)]=\"showMore\" (toggleOnChange)=\"showMoreChanged($event)\" style=\"margin: 0px 10px\"></lib-form-field-toggle>\n <div [hidden]=\"!showMore\" class=\"form-group-column\">\n <lib-form-field-container\n [showHeader]=\"false\"\n class=\"form-field-advanced\"\n >\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Client ID</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"The client id to use when authenticating to the IDP\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter client ID\" [(ngModel)]=\"formData.clientId\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">External Auth Url</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"The URL that users are directed to, to obtain a JWT\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter external auth URL\" [(ngModel)]=\"formData.externalAuthUrl\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Scopes</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Enter as a comma or space seperated list of claims/permissions\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <p-chips (keyup)=\"scopesOnKeyup($event)\"\n [(ngModel)]=\"formData.scopes\"\n [allowDuplicate]=\"false\"\n placeholder=\"Enter scopes\"\n [addOnBlur]=\"true\"\n separator=\",\">\n </p-chips>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'Custom Tags'\"\n [label]=\"'OPTIONAL'\"\n class=\"form-field-advanced\"\n >\n <lib-custom-tags [(tags)]=\"formData.tags\"></lib-custom-tags>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column two-fifths\">\n <lib-form-field-container\n [title]=\"'Verification'\"\n [label]=\"'REQUIRED'\"\n >\n <div class=\"radio-group-container\" (keydown)=\"radioKeyDownHandler($event)\" tabindex=\"0\">\n <div class=\"radio-button-container\" [ngClass]=\"{'selected': signatureMethod === 'JWKS_ENDPOINT'}\" (click)=\"selectSignatureMethod('JWKS_ENDPOINT')\">\n <div class=\"radio-button-circle\">\n <div class=\"radio-button-inner-circle\"></div>\n </div>\n <span class=\"radio-button-label\">JWKS Endpoint</span>\n </div>\n <div class=\"radio-button-container\" [ngClass]=\"{'selected': signatureMethod === 'CERT_PEM'}\" (click)=\"selectSignatureMethod('CERT_PEM')\">\n <div class=\"radio-button-circle\">\n <div class=\"radio-button-inner-circle\"></div>\n </div>\n <span class=\"radio-button-label\">Cert PEM</span>\n </div>\n </div>\n <div *ngIf=\"signatureMethod === 'JWKS_ENDPOINT'\" class=\"form-field-input-group\">\n <div class=\"form-field-label-container select-file-label-container\">\n <div class=\"form-field-header\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">JWKS Endpoint</span>\n </div>\n </div>\n <input class=\"form-field-input read-only\" placeholder=\"Enter endpoint URL\" [(ngModel)]=\"formData.jwksEndpoint\" [ngClass]=\"{error: errors['certPem']}\"/>\n </div>\n </div>\n <div *ngIf=\"signatureMethod === 'CERT_PEM'\" class=\"form-field-input-group\">\n <div class=\"form-field-label-container select-file-label-container\">\n <div class=\"form-field-header\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">PEM</span>\n </div>\n <span class=\"select-file-button\" (click)=\"openFileSelect($event)\">\n Select File\n <div class=\"spinner\" *ngIf=\"fileSelectOpening\"></div>\n </span>\n <input #fileSelect type=\"file\" style=\"display:none\" (change)=\"selectPemFile($event)\">\n </div>\n <textarea placeholder=\"Paste pem contents or select file\" [(ngModel)]=\"formData.certPem\" [ngClass]=\"{error: errors['certPem']}\"></textarea>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-header\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">KID</span>\n </div>\n <span class=\"form-field-label\" >Optional</span>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter KID\" [(ngModel)]=\"formData.kid\"/>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n [showHeader]=\"false\"\n >\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"config-container-label\">ENABLED</div>\n <div\n (click)=\"toggleEnabled()\"\n [ngClass]=\"{ on: formData.enabled }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.enabled\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.enabled\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'API Calls'\"\n [headerActions]=\"apiOptions\"\n (actionRequested)=\"apiActionRequested($event)\"\n [class]=\"'api-data-no-wrap'\"\n >\n <div class=\"form-row\">\n <input class=\"form-field-input\" [value]=\"apiCallURL\"/>\n <div class=\"icon-copy copy\" (click)=\"copyToClipboard(apiCallURL)\"></div>\n </div>\n <lib-json-view *ngIf=\"formData\" [(data)]=\"apiData\" [readOnly]=\"true\" [showCopy]=\"true\"></lib-json-view>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column\" *ngIf=\"formView === 'raw'\">\n <lib-json-view *ngIf=\"formData\" [(data)]=\"formData\"></lib-json-view>\n </div>\n </div>\n</div>\n<lib-loading-indicator *ngIf=\"isLoading\" [isLoading]=\"isLoading\"></lib-loading-indicator>\n", styles: ["@charset \"UTF-8\";.jwt-signer-form-container{display:flex;flex-direction:column;height:100%;width:100%;align-items:center;gap:var(--gapXL)}.jwt-signer-form-container .select-file-button{padding-left:var(--paddingMedium);padding-right:var(--paddingMedium);height:25px;width:-moz-fit-content;width:fit-content;white-space:nowrap;display:flex;align-items:center;justify-content:center;font-weight:600;font-size:14px;background:var(--primary);border-style:solid;border-width:1px;border-color:var(--stroke);color:var(--white);cursor:pointer;border-radius:var(--inputBorderRadius);gap:var(--marginMedium);margin-top:-5px}.jwt-signer-form-container .select-file-button:hover{filter:brightness(.8)}.jwt-signer-form-container .select-file-button:active{filter:grayscale(1);transform:translateY(1px)}.jwt-signer-form-container .select-file-button .spinner{display:inline-block;width:8px;height:8px;border-radius:50%;background:transparent;border-top:2px solid white;border-right:2px solid white;border-bottom:2px solid transparent;border-left:2px solid transparent;animation:loading .5s infinite linear}.jwt-signer-form-container .select-file-label-container{gap:var(--marginMedium)}::ng-deep .jwt-signer-form-container select:disabled,::ng-deep .jwt-signer-form-container input:disabled{opacity:.75!important;cursor:text;background-color:var(--stroke)!important}::ng-deep .api-data-no-wrap .jse-text-mode{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller .cm-content{width:100%;overflow:auto}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller .cm-content .\\37cr{white-space:nowrap}.radio-group-container{display:flex;gap:var(--marginLarge)}.radio-group-container:focus .radio-button-container .radio-button-circle{border-color:var(--primaryColor)}.radio-group-container .radio-button-container{display:flex;flex-direction:row;align-items:center;background-color:var(--formGroup);border-radius:var(--inputBorderRadius);width:100%;padding-left:var(--paddingMedium);padding-right:var(--paddingMedium);padding-top:var(--paddingLarge);padding-bottom:var(--paddingLarge);cursor:pointer;gap:var(--marginMedium)}.radio-group-container .radio-button-container .radio-button-circle{display:flex;width:21px;height:21px;border-radius:21px;border-width:2px;border-style:solid;border-color:var(--offWhite);align-items:center;justify-content:center;background-color:var(--offWhite)}.radio-group-container .radio-button-container .radio-button-circle .radio-button-inner-circle{display:none;width:15px;height:15px;border-radius:15px;align-items:center;justify-content:center;background-color:var(--primaryColor)}.radio-group-container .radio-button-container.selected .radio-button-circle .radio-button-inner-circle{display:flex}.radio-group-container .radio-button-container:active .radio-button-circle .radio-button-inner-circle{display:flex;background-color:var(--menu)}.radio-group-container .radio-button-container .radio-button-label{color:var(--offWhite);font-size:14px;font-weight:600}\n"], dependencies: [{ kind: "directive", type: i1$4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.Chips, selector: "p-chips", inputs: ["style", "styleClass", "disabled", "field", "placeholder", "max", "ariaLabel", "ariaLabelledBy", "tabindex", "inputId", "allowDuplicate", "inputStyle", "inputStyleClass", "addOnTab", "addOnBlur", "separator", "showClear"], outputs: ["onAdd", "onRemove", "onFocus", "onBlur", "onChipClick", "onClear"] }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: FormHeaderComponent, selector: "lib-form-header", inputs: ["data", "title", "moreActions", "formView", "saveDisabled", "saveTooltip", "actionButtonText", "moreActionsText"], outputs: ["formViewChange", "actionRequested"] }, { kind: "component", type: FormFieldContainerComponent, selector: "lib-form-field-container", inputs: ["title", "title2", "layout", "helpText", "helpText2", "label", "count", "action", "actionLabel", "class", "contentStyle", "showHeader", "headerActions"], outputs: ["actionRequested"] }, { kind: "component", type: LoadingIndicatorComponent, selector: "lib-loading-indicator", inputs: ["isLoading"] }, { kind: "component", type: FormFieldToggleComponent, selector: "lib-form-field-toggle", inputs: ["label", "orientation", "labelOn", "labelOff", "toggleOn"], outputs: ["toggleOnChange"] }, { kind: "component", type: JsonViewComponent, selector: "lib-json-view", inputs: ["data", "schema", "readOnly", "jsonInvalid", "showCopy"], outputs: ["dataChange", "jsonChange", "jsonInvalidChange"] }, { kind: "component", type: CustomTagsComponent, selector: "lib-custom-tags", inputs: ["tags"], outputs: ["tagsChange"] }] }); }
21220
21317
  }
21221
21318
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: JwtSignerFormComponent, decorators: [{
21222
21319
  type: Component,
21223
- args: [{ selector: 'lib-configuration', template: "<div class=\"projectable-form-wrapper\"\n (keyup.enter)=\"save($event)\"\n (keyup.escape)=\"closeModal(false)\"\n tabindex=\"0\"\n>\n <lib-form-header\n [data]=\"formData\"\n [title]=\"(formData.id ? 'JWT Signer Details' : 'Create JWT Signer')\"\n [moreActions]=\"formData.moreActions\"\n (actionRequested)=\"headerActionRequested($event)\"\n [(formView)]=\"formView\"\n [saveDisabled]=\"svc.saveDisabled || formDataInvalid\"\n ></lib-form-header>\n <div class=\"jwt-signer-form-container projectable-form-container\">\n <div class=\"projectable-form-main-column form-group-row\" [hidden]=\"formView !== 'simple'\">\n <div class=\"form-group-column three-fifths\">\n <lib-form-field-container\n [title]=\"'Name'\"\n [label]=\"'Required'\"\n >\n <input class=\"form-field-input read-only\" [(ngModel)]=\"formData.name\" [ngClass]=\"{error: errors['name']}\" placeholder=\"Name this JWT Signer\"/>\n </lib-form-field-container>\n <lib-form-field-container\n [layout]=\"'column'\"\n [showHeader]=\"false\"\n >\n <div class=\"form-field-label-container\">\n <div class=\"form-field-header\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Issuer</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"The &quot;issuer&quot; field on the JWT Signer must match the &quot;iss&quot; field on the JWT\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <span class=\"form-field-label\" >Required</span>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter issuer\" [(ngModel)]=\"formData.issuer\" [ngClass]=\"{error: errors['issuer']}\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Claims Property</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"The &quot;claimsProperty&quot; must match the &quot;id&quot; field on a ziti identity (or externalId if &quot;Use External ID&quot; is enabled)\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter claims property, defaults to &quot;sub&quot;\" [(ngModel)]=\"formData.claimsProperty\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Audience</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"The &quot;audience&quot; field on the JWT Signer must match the &quot;aud&quot; field on the JWT\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter audience\" [(ngModel)]=\"formData.audience\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">External Auth Url</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Unauthenticated clients can enumerate External JWT Signers that have an &quot;externalAuthUrl&quot; property. Clients will receive the name of the External JWT Signer and the &quot;externalAuthUrl&quot; only. This information can allow clients to initiate client authentication to the target identity provider.\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter external auth URL\" [(ngModel)]=\"formData.externalAuthUrl\"/>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n [showHeader]=\"false\"\n [layout]=\"'row'\"\n >\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"config-container-label\">ENABLED</div>\n <div\n (click)=\"toggleEnabled()\"\n [ngClass]=\"{ on: formData.enabled }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.enabled\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.enabled\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"config-container-label\">Use External ID</div>\n <div\n (click)=\"toggleUseExternalId()\"\n [ngClass]=\"{ on: formData.useExternalId }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.useExternalId\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.useExternalId\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-toggle [(toggleOn)]=\"showMore\" (toggleOnChange)=\"showMoreChanged($event)\" style=\"margin: 0px 10px\"></lib-form-field-toggle>\n <div [hidden]=\"!showMore\" class=\"form-group-column\">\n <lib-form-field-container\n [title]=\"'Custom Tags'\"\n [label]=\"'OPTIONAL'\"\n class=\"form-field-advanced\"\n >\n <lib-custom-tags [(tags)]=\"formData.tags\"></lib-custom-tags>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column two-fifths\">\n <lib-form-field-container\n [title]=\"'Certificate Definition'\"\n [label]=\"'REQUIRED'\"\n >\n <div class=\"form-field-input-group\">\n <div class=\"form-field-label-container select-file-label-container\">\n <div class=\"form-field-header\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">PEM</span>\n </div>\n <span class=\"select-file-button\" (click)=\"openFileSelect($event)\">\n Select File\n <div class=\"spinner\" *ngIf=\"fileSelectOpening\"></div>\n </span>\n <input #fileSelect type=\"file\" style=\"display:none\" (change)=\"selectPemFile($event)\">\n </div>\n <textarea placeholder=\"Paste pem contents or select file\" [(ngModel)]=\"formData.certPem\" [ngClass]=\"{error: errors['certPem']}\"></textarea>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-header\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">KID</span>\n </div>\n <span class=\"form-field-label\" >Optional</span>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter KID\" [(ngModel)]=\"formData.kid\"/>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'JWKS Endpoint'\"\n [label]=\"'Optional'\"\n >\n <input class=\"form-field-input read-only\" placeholder=\"Enter endpoint URL\" [(ngModel)]=\"formData.jwksEndpoint\"/>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'API Calls'\"\n [headerActions]=\"apiOptions\"\n (actionRequested)=\"apiActionRequested($event)\"\n [class]=\"'api-data-no-wrap'\"\n >\n <div class=\"form-row\">\n <input class=\"form-field-input\" [value]=\"apiCallURL\"/>\n <div class=\"icon-copy copy\" (click)=\"copyToClipboard(apiCallURL)\"></div>\n </div>\n <lib-json-view *ngIf=\"formData\" [(data)]=\"apiData\" [readOnly]=\"true\" [showCopy]=\"true\"></lib-json-view>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column\" *ngIf=\"formView === 'raw'\">\n <lib-json-view *ngIf=\"formData\" [(data)]=\"formData\"></lib-json-view>\n </div>\n </div>\n</div>\n<lib-loading-indicator *ngIf=\"isLoading\" [isLoading]=\"isLoading\"></lib-loading-indicator>\n", styles: ["@charset \"UTF-8\";.jwt-signer-form-container{display:flex;flex-direction:column;height:100%;width:100%;align-items:center;gap:var(--gapXL)}.jwt-signer-form-container .select-file-button{padding-left:var(--paddingMedium);padding-right:var(--paddingMedium);height:25px;width:-moz-fit-content;width:fit-content;white-space:nowrap;display:flex;align-items:center;justify-content:center;font-weight:600;font-size:14px;background:var(--primary);border-style:solid;border-width:1px;border-color:var(--stroke);color:var(--white);cursor:pointer;border-radius:var(--inputBorderRadius);gap:var(--marginMedium)}.jwt-signer-form-container .select-file-button:hover{filter:brightness(.8)}.jwt-signer-form-container .select-file-button:active{filter:grayscale(1);transform:translateY(1px)}.jwt-signer-form-container .select-file-button .spinner{display:inline-block;width:8px;height:8px;border-radius:50%;background:transparent;border-top:2px solid white;border-right:2px solid white;border-bottom:2px solid transparent;border-left:2px solid transparent;animation:loading .5s infinite linear}.jwt-signer-form-container .select-file-label-container{gap:var(--marginMedium)}::ng-deep .jwt-signer-form-container select:disabled,::ng-deep .jwt-signer-form-container input:disabled{opacity:.75!important;cursor:text;background-color:var(--stroke)!important}::ng-deep .api-data-no-wrap .jse-text-mode{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller .cm-content{width:100%;overflow:auto}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller .cm-content .\\37cr{white-space:nowrap}\n"] }]
21320
+ args: [{ selector: 'lib-configuration', template: "<div class=\"projectable-form-wrapper\"\n (keyup.enter)=\"save($event)\"\n (keyup.escape)=\"closeModal(false)\"\n tabindex=\"0\"\n>\n <lib-form-header\n [data]=\"formData\"\n [title]=\"(formData.id ? 'JWT Signer Details' : 'Create JWT Signer')\"\n [moreActions]=\"formData.moreActions\"\n (actionRequested)=\"headerActionRequested($event)\"\n [(formView)]=\"formView\"\n [saveDisabled]=\"svc.saveDisabled || formDataInvalid\"\n ></lib-form-header>\n <div class=\"jwt-signer-form-container projectable-form-container\">\n <div class=\"projectable-form-main-column form-group-row\" [hidden]=\"formView !== 'simple'\">\n <div class=\"form-group-column three-fifths\">\n <lib-form-field-container\n [title]=\"'Name'\"\n [label]=\"'Required'\"\n >\n <input class=\"form-field-input read-only\" [(ngModel)]=\"formData.name\" [ngClass]=\"{error: errors['name']}\" placeholder=\"Name this JWT Signer\"/>\n </lib-form-field-container>\n <lib-form-field-container\n [layout]=\"'column'\"\n [showHeader]=\"false\"\n >\n <div class=\"form-field-label-container\">\n <div class=\"form-field-header\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Issuer</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"The &quot;issuer&quot; field on the JWT Signer must match the &quot;iss&quot; field on the JWT\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <span class=\"form-field-label\" >Required</span>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter issuer\" [(ngModel)]=\"formData.issuer\" [ngClass]=\"{error: errors['issuer']}\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Audience</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"The expected &quot;aud&quot; (audience) field on the JWT\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter audience\" [(ngModel)]=\"formData.audience\"/>\n </div>\n <div class=\"form-field-row\">\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Claims Property</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"The field on the JWT for mapping to an identity. Matches the identity's id or externalId if &quot;Use External Id&quot; is set to true. Defaults to &quot;sub&quot;\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter claims property\" [(ngModel)]=\"formData.claimsProperty\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-header\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\" style=\"font-weight: 600; font-size: 14px;\">External ID</div>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"If enabled, will match the &quot;claimsProperty&quot; to an identity's &quot;externalId&quot; field. If false, it will match to the identity's id field.\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n </div>\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">Use External ID</div>\n </div>\n <div\n (click)=\"toggleUseExternalId()\"\n [ngClass]=\"{ on: formData.useExternalId }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.useExternalId\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.useExternalId\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-toggle [(toggleOn)]=\"showMore\" (toggleOnChange)=\"showMoreChanged($event)\" style=\"margin: 0px 10px\"></lib-form-field-toggle>\n <div [hidden]=\"!showMore\" class=\"form-group-column\">\n <lib-form-field-container\n [showHeader]=\"false\"\n class=\"form-field-advanced\"\n >\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Client ID</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"The client id to use when authenticating to the IDP\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter client ID\" [(ngModel)]=\"formData.clientId\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">External Auth Url</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"The URL that users are directed to, to obtain a JWT\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter external auth URL\" [(ngModel)]=\"formData.externalAuthUrl\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Scopes</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Enter as a comma or space seperated list of claims/permissions\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <p-chips (keyup)=\"scopesOnKeyup($event)\"\n [(ngModel)]=\"formData.scopes\"\n [allowDuplicate]=\"false\"\n placeholder=\"Enter scopes\"\n [addOnBlur]=\"true\"\n separator=\",\">\n </p-chips>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'Custom Tags'\"\n [label]=\"'OPTIONAL'\"\n class=\"form-field-advanced\"\n >\n <lib-custom-tags [(tags)]=\"formData.tags\"></lib-custom-tags>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column two-fifths\">\n <lib-form-field-container\n [title]=\"'Verification'\"\n [label]=\"'REQUIRED'\"\n >\n <div class=\"radio-group-container\" (keydown)=\"radioKeyDownHandler($event)\" tabindex=\"0\">\n <div class=\"radio-button-container\" [ngClass]=\"{'selected': signatureMethod === 'JWKS_ENDPOINT'}\" (click)=\"selectSignatureMethod('JWKS_ENDPOINT')\">\n <div class=\"radio-button-circle\">\n <div class=\"radio-button-inner-circle\"></div>\n </div>\n <span class=\"radio-button-label\">JWKS Endpoint</span>\n </div>\n <div class=\"radio-button-container\" [ngClass]=\"{'selected': signatureMethod === 'CERT_PEM'}\" (click)=\"selectSignatureMethod('CERT_PEM')\">\n <div class=\"radio-button-circle\">\n <div class=\"radio-button-inner-circle\"></div>\n </div>\n <span class=\"radio-button-label\">Cert PEM</span>\n </div>\n </div>\n <div *ngIf=\"signatureMethod === 'JWKS_ENDPOINT'\" class=\"form-field-input-group\">\n <div class=\"form-field-label-container select-file-label-container\">\n <div class=\"form-field-header\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">JWKS Endpoint</span>\n </div>\n </div>\n <input class=\"form-field-input read-only\" placeholder=\"Enter endpoint URL\" [(ngModel)]=\"formData.jwksEndpoint\" [ngClass]=\"{error: errors['certPem']}\"/>\n </div>\n </div>\n <div *ngIf=\"signatureMethod === 'CERT_PEM'\" class=\"form-field-input-group\">\n <div class=\"form-field-label-container select-file-label-container\">\n <div class=\"form-field-header\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">PEM</span>\n </div>\n <span class=\"select-file-button\" (click)=\"openFileSelect($event)\">\n Select File\n <div class=\"spinner\" *ngIf=\"fileSelectOpening\"></div>\n </span>\n <input #fileSelect type=\"file\" style=\"display:none\" (change)=\"selectPemFile($event)\">\n </div>\n <textarea placeholder=\"Paste pem contents or select file\" [(ngModel)]=\"formData.certPem\" [ngClass]=\"{error: errors['certPem']}\"></textarea>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-header\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">KID</span>\n </div>\n <span class=\"form-field-label\" >Optional</span>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter KID\" [(ngModel)]=\"formData.kid\"/>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n [showHeader]=\"false\"\n >\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"config-container-label\">ENABLED</div>\n <div\n (click)=\"toggleEnabled()\"\n [ngClass]=\"{ on: formData.enabled }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.enabled\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.enabled\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'API Calls'\"\n [headerActions]=\"apiOptions\"\n (actionRequested)=\"apiActionRequested($event)\"\n [class]=\"'api-data-no-wrap'\"\n >\n <div class=\"form-row\">\n <input class=\"form-field-input\" [value]=\"apiCallURL\"/>\n <div class=\"icon-copy copy\" (click)=\"copyToClipboard(apiCallURL)\"></div>\n </div>\n <lib-json-view *ngIf=\"formData\" [(data)]=\"apiData\" [readOnly]=\"true\" [showCopy]=\"true\"></lib-json-view>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column\" *ngIf=\"formView === 'raw'\">\n <lib-json-view *ngIf=\"formData\" [(data)]=\"formData\"></lib-json-view>\n </div>\n </div>\n</div>\n<lib-loading-indicator *ngIf=\"isLoading\" [isLoading]=\"isLoading\"></lib-loading-indicator>\n", styles: ["@charset \"UTF-8\";.jwt-signer-form-container{display:flex;flex-direction:column;height:100%;width:100%;align-items:center;gap:var(--gapXL)}.jwt-signer-form-container .select-file-button{padding-left:var(--paddingMedium);padding-right:var(--paddingMedium);height:25px;width:-moz-fit-content;width:fit-content;white-space:nowrap;display:flex;align-items:center;justify-content:center;font-weight:600;font-size:14px;background:var(--primary);border-style:solid;border-width:1px;border-color:var(--stroke);color:var(--white);cursor:pointer;border-radius:var(--inputBorderRadius);gap:var(--marginMedium);margin-top:-5px}.jwt-signer-form-container .select-file-button:hover{filter:brightness(.8)}.jwt-signer-form-container .select-file-button:active{filter:grayscale(1);transform:translateY(1px)}.jwt-signer-form-container .select-file-button .spinner{display:inline-block;width:8px;height:8px;border-radius:50%;background:transparent;border-top:2px solid white;border-right:2px solid white;border-bottom:2px solid transparent;border-left:2px solid transparent;animation:loading .5s infinite linear}.jwt-signer-form-container .select-file-label-container{gap:var(--marginMedium)}::ng-deep .jwt-signer-form-container select:disabled,::ng-deep .jwt-signer-form-container input:disabled{opacity:.75!important;cursor:text;background-color:var(--stroke)!important}::ng-deep .api-data-no-wrap .jse-text-mode{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller .cm-content{width:100%;overflow:auto}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller .cm-content .\\37cr{white-space:nowrap}.radio-group-container{display:flex;gap:var(--marginLarge)}.radio-group-container:focus .radio-button-container .radio-button-circle{border-color:var(--primaryColor)}.radio-group-container .radio-button-container{display:flex;flex-direction:row;align-items:center;background-color:var(--formGroup);border-radius:var(--inputBorderRadius);width:100%;padding-left:var(--paddingMedium);padding-right:var(--paddingMedium);padding-top:var(--paddingLarge);padding-bottom:var(--paddingLarge);cursor:pointer;gap:var(--marginMedium)}.radio-group-container .radio-button-container .radio-button-circle{display:flex;width:21px;height:21px;border-radius:21px;border-width:2px;border-style:solid;border-color:var(--offWhite);align-items:center;justify-content:center;background-color:var(--offWhite)}.radio-group-container .radio-button-container .radio-button-circle .radio-button-inner-circle{display:none;width:15px;height:15px;border-radius:15px;align-items:center;justify-content:center;background-color:var(--primaryColor)}.radio-group-container .radio-button-container.selected .radio-button-circle .radio-button-inner-circle{display:flex}.radio-group-container .radio-button-container:active .radio-button-circle .radio-button-inner-circle{display:flex;background-color:var(--menu)}.radio-group-container .radio-button-container .radio-button-label{color:var(--offWhite);font-size:14px;font-weight:600}\n"] }]
21224
21321
  }], ctorParameters: function () { return [{ type: JwtSignerFormService }, { type: SchemaService }, { type: GrowlerService }, { type: undefined, decorators: [{
21225
21322
  type: Inject,
21226
21323
  args: [SHAREDZ_EXTENSION]
@@ -21256,171 +21353,928 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
21256
21353
  See the License for the specific language governing permissions and
21257
21354
  limitations under the License.
21258
21355
  */
21259
- function playerFactory() {
21260
- return import(/* webpackChunkName: 'lottie-web' */ 'lottie-web');
21261
- }
21262
- class OpenZitiConsoleLibModule {
21263
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OpenZitiConsoleLibModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
21264
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: OpenZitiConsoleLibModule, declarations: [ZacWrapperComponent,
21265
- SafePipe,
21266
- ExtendableComponent,
21267
- StringInputComponent,
21268
- NumberInputComponent,
21269
- BooleanToggleInputComponent,
21270
- ObjectComponent,
21271
- SelectorInputComponent,
21272
- TextListInputComponent,
21273
- CheckboxListInputComponent,
21274
- ProtocolAddressPortInputComponent,
21275
- SideToolbarComponent,
21276
- SideNavbarComponent,
21277
- SideBannerComponent,
21278
- PasswordInputComponent,
21279
- TerminatorFormComponent,
21280
- ConfigurationsPageComponent,
21281
- ListPageHeaderComponent,
21282
- FilterBarComponent,
21283
- ListPageFormComponent,
21284
- IdentitiesPageComponent,
21285
- EdgeRoutersPageComponent,
21286
- DataTableComponent,
21287
- TableCellSelectComponent,
21288
- TableColumnSelectComponent,
21289
- TableCellMenuComponent,
21290
- TableColumnMenuComponent,
21291
- TableColumnDefaultComponent,
21292
- TableColumnFilterComponent,
21293
- IdentityFormComponent,
21294
- EdgeRouterFormComponent,
21295
- HiddenColumnsBarComponent,
21296
- FilterBarComponent,
21297
- ExtendableComponent,
21298
- ConfirmComponent,
21299
- NoItemsComponent,
21300
- SideModalComponent,
21301
- FormHeaderComponent,
21302
- FormFieldContainerComponent,
21303
- PreviewListComponent,
21304
- LoadingIndicatorComponent,
21305
- FormFieldToggleComponent,
21306
- JsonViewComponent,
21307
- TagSelectorComponent,
21308
- QrCodeComponent,
21309
- TableCellTokenComponent,
21310
- OSTooltipComponent,
21311
- SDKTooltipComponent,
21312
- OverridesComponent,
21313
- ResetEnrollmentComponent,
21314
- IdentityServicePathComponent,
21315
- NetworkVisualizerComponent,
21316
- CustomTagsComponent,
21317
- ServicesPageComponent,
21318
- ServiceFormComponent,
21319
- PortRangesComponent,
21320
- ForwardingConfigComponent,
21321
- CardListComponent,
21322
- SimpleServiceComponent,
21323
- CardComponent,
21324
- CreationSummaryDialogComponent,
21325
- ConfigEditorComponent,
21326
- ServicePoliciesPageComponent,
21327
- ServicePolicyFormComponent,
21328
- EdgeRouterPoliciesPageComponent,
21329
- EdgeRouterPolicyFormComponent,
21330
- MultiActionButtonComponent,
21331
- TableCellNameComponent,
21332
- ServiceEdgeRouterPoliciesPageComponent,
21333
- ServiceEdgeRouterPolicyFormComponent,
21334
- TerminatorsPageComponent,
21335
- TerminatorFormComponent,
21336
- ConfigurationFormComponent,
21337
- JwtSignersPageComponent,
21338
- JwtSignerFormComponent], imports: [CommonModule,
21339
- FormsModule,
21340
- MatDialogModule,
21341
- HttpClientModule,
21342
- ZacRoutingModule,
21343
- ChipsModule,
21344
- CalendarModule,
21345
- AgGridModule,
21346
- QRCodeModule,
21347
- ClickOutsideModule,
21348
- NgJsonEditorModule,
21349
- MatTooltipModule,
21350
- MatAutocompleteModule, i1$2.LottieModule, DropdownModule], exports: [ZacWrapperComponent,
21351
- ExtendableComponent,
21352
- SideToolbarComponent,
21353
- SideNavbarComponent,
21354
- SideBannerComponent,
21355
- StringInputComponent,
21356
- SelectorInputComponent,
21357
- PasswordInputComponent,
21358
- NumberInputComponent,
21359
- BooleanToggleInputComponent,
21360
- ObjectComponent,
21361
- TextListInputComponent,
21362
- IdentityServicePathComponent,
21363
- NetworkVisualizerComponent,
21364
- CheckboxListInputComponent,
21365
- ProtocolAddressPortInputComponent,
21366
- ConfigurationsPageComponent,
21367
- ConfigurationFormComponent,
21368
- EdgeRouterFormComponent,
21369
- IdentitiesPageComponent,
21370
- EdgeRoutersPageComponent,
21371
- ServicesPageComponent,
21372
- ZacRoutingModule,
21373
- SideModalComponent,
21374
- IdentityFormComponent,
21375
- LoadingIndicatorComponent,
21376
- GrowlerModule,
21377
- FormFieldContainerComponent,
21378
- FormFieldToggleComponent,
21379
- ServiceFormComponent,
21380
- ServicePoliciesPageComponent,
21381
- ServicePolicyFormComponent,
21382
- EdgeRouterPoliciesPageComponent,
21383
- TerminatorsPageComponent,
21384
- TerminatorFormComponent,
21385
- JwtSignersPageComponent,
21386
- JwtSignerFormComponent] }); }
21387
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OpenZitiConsoleLibModule, providers: [
21388
- { provide: SHAREDZ_EXTENSION, useClass: ExtensionsNoopService },
21389
- { provide: ZITI_NAVIGATOR, useValue: {} },
21356
+ class AuthPoliciesPageService extends ListPageServiceClass {
21357
+ constructor(schemaSvc, settings, filterService, csvDownloadService, extService, router, dialogForm) {
21358
+ super(settings, filterService, csvDownloadService, extService, router);
21359
+ this.schemaSvc = schemaSvc;
21360
+ this.router = router;
21361
+ this.dialogForm = dialogForm;
21362
+ this.paging = this.DEFAULT_PAGING;
21363
+ this.resourceType = 'auth-policies';
21364
+ this.selectedConfig = {};
21365
+ this.modalType = '';
21366
+ this.menuItems = [
21367
+ { name: 'Edit', action: 'update' },
21368
+ { name: 'Delete', action: 'delete' },
21369
+ ];
21370
+ this.validate = (formData) => {
21371
+ return Promise.resolve({ passed: true });
21372
+ };
21373
+ }
21374
+ initTableColumns() {
21375
+ const allowedHeaderComponentParams = {
21376
+ filterType: 'SELECT',
21377
+ enableSorting: true,
21378
+ filterOptions: [
21379
+ { label: 'All', value: '' },
21380
+ { label: 'Allowed', value: true },
21381
+ { label: 'Not Allowed', value: false },
21382
+ ]
21383
+ };
21384
+ const createdAtHeaderComponentParams = {
21385
+ filterType: 'DATETIME',
21386
+ };
21387
+ return [
21390
21388
  {
21391
- provide: APP_INITIALIZER,
21392
- useFactory: onAppInit,
21393
- deps: [Injector],
21394
- multi: true
21389
+ colId: 'name',
21390
+ field: 'name',
21391
+ headerName: 'Name',
21392
+ headerComponent: TableColumnDefaultComponent,
21393
+ headerComponentParams: this.headerComponentParams,
21394
+ cellRenderer: TableCellNameComponent,
21395
+ cellRendererParams: { pathRoot: this.basePath, cellNamePreCheck: this.checkDefaultAuthPolicy.bind(this) },
21396
+ onCellClicked: (data) => {
21397
+ if (this.hasSelectedText()) {
21398
+ return;
21399
+ }
21400
+ this.checkDefaultAuthPolicy(data?.data).then((result) => {
21401
+ if (!result) {
21402
+ return;
21403
+ }
21404
+ this.openEditForm(data?.data?.id);
21405
+ });
21406
+ },
21407
+ resizable: true,
21408
+ cellClass: 'nf-cell-vert-align tCol',
21409
+ sortable: true,
21410
+ filter: true,
21411
+ sortColumn: this.sort.bind(this)
21395
21412
  },
21396
- ], imports: [CommonModule,
21397
- FormsModule,
21398
- MatDialogModule,
21399
- HttpClientModule,
21400
- ZacRoutingModule,
21401
- ChipsModule,
21402
- CalendarModule,
21403
- AgGridModule,
21404
- QRCodeModule,
21405
- ClickOutsideModule,
21406
- NgJsonEditorModule,
21407
- MatTooltipModule,
21408
- MatAutocompleteModule,
21409
- LottieModule.forRoot({ player: playerFactory }),
21410
- DropdownModule, ZacRoutingModule,
21411
- GrowlerModule] }); }
21412
- }
21413
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OpenZitiConsoleLibModule, decorators: [{
21414
- type: NgModule,
21415
- args: [{
21416
- declarations: [
21417
- ZacWrapperComponent,
21418
- SafePipe,
21419
- ExtendableComponent,
21420
- StringInputComponent,
21421
- NumberInputComponent,
21422
- BooleanToggleInputComponent,
21423
- ObjectComponent,
21413
+ {
21414
+ colId: 'primary.cert.allowed',
21415
+ field: 'primary.cert.allowed',
21416
+ headerName: 'Cert',
21417
+ headerComponent: TableColumnDefaultComponent,
21418
+ headerComponentParams: allowedHeaderComponentParams,
21419
+ resizable: true,
21420
+ cellClass: 'nf-cell-vert-align tCol',
21421
+ sortable: true,
21422
+ filter: true,
21423
+ sortColumn: this.sort.bind(this),
21424
+ },
21425
+ {
21426
+ colId: 'primary.extJwt.allowed',
21427
+ field: 'primary.extJwt.allowed',
21428
+ headerName: 'External JWT',
21429
+ headerComponent: TableColumnDefaultComponent,
21430
+ headerComponentParams: allowedHeaderComponentParams,
21431
+ resizable: true,
21432
+ cellClass: 'nf-cell-vert-align tCol',
21433
+ sortable: true,
21434
+ filter: true,
21435
+ sortColumn: this.sort.bind(this),
21436
+ },
21437
+ {
21438
+ colId: 'primary.updb.allowed',
21439
+ field: 'primary.updb.allowed',
21440
+ headerName: 'UPDB',
21441
+ headerComponent: TableColumnDefaultComponent,
21442
+ headerComponentParams: allowedHeaderComponentParams,
21443
+ resizable: true,
21444
+ cellClass: 'nf-cell-vert-align tCol',
21445
+ sortable: true,
21446
+ filter: true,
21447
+ sortColumn: this.sort.bind(this),
21448
+ },
21449
+ {
21450
+ colId: 'createdAt',
21451
+ field: 'createdAt',
21452
+ headerName: 'Created At',
21453
+ headerComponent: TableColumnDefaultComponent,
21454
+ headerComponentParams: createdAtHeaderComponentParams,
21455
+ valueFormatter: this.createdAtFormatter,
21456
+ resizable: true,
21457
+ cellClass: 'nf-cell-vert-align tCol',
21458
+ }
21459
+ ];
21460
+ }
21461
+ checkDefaultAuthPolicy(authPolicy) {
21462
+ if (authPolicy.id !== 'default') {
21463
+ return Promise.resolve(true);
21464
+ }
21465
+ const confirmationMessage = `<p>WARNING: Do not change the default policy unless you're sure you know what you are doing.</p>
21466
+ <p>Before changing the default policy, it's recommended that you make another policy and apply that to other users first. Then make sure you can still authenticate. </p>
21467
+ <p>Do you still want to continue?</p>`;
21468
+ const data = {
21469
+ appendId: 'ConfirmDefaultAuthPolicy',
21470
+ title: 'Are You Sure?',
21471
+ message: confirmationMessage,
21472
+ confirmLabel: 'Yes',
21473
+ cancelLabel: 'Oops, no get me out of here',
21474
+ showCancelLink: true
21475
+ };
21476
+ this.dialogRef = this.dialogForm.open(ConfirmComponent, {
21477
+ data: data,
21478
+ autoFocus: false,
21479
+ });
21480
+ return firstValueFrom(this.dialogRef.afterClosed());
21481
+ }
21482
+ getData(filters, sort) {
21483
+ // we can customize filters or sorting here before moving on...
21484
+ return super.getTableData(this.resourceType, this.paging, filters, sort)
21485
+ .then((results) => {
21486
+ return this.processData(results);
21487
+ });
21488
+ }
21489
+ processData(results) {
21490
+ if (!isEmpty(results?.data)) {
21491
+ //pre-process data before rendering
21492
+ results.data = this.addActionsPerRow(results);
21493
+ }
21494
+ return results;
21495
+ }
21496
+ addActionsPerRow(results) {
21497
+ return results.data.map((row) => {
21498
+ row.actionList = ['update', 'delete'];
21499
+ return row;
21500
+ });
21501
+ }
21502
+ openUpdate(item) {
21503
+ this.modalType = 'auth-policy';
21504
+ if (item) {
21505
+ this.selectedConfig = item;
21506
+ this.selectedConfig.badges = [];
21507
+ unset(this.selectedConfig, '_links');
21508
+ }
21509
+ else {
21510
+ this.selectedConfig = new Service$1();
21511
+ }
21512
+ this.sideModalOpen = true;
21513
+ }
21514
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthPoliciesPageService, deps: [{ token: SchemaService }, { token: SETTINGS_SERVICE }, { token: DataTableFilterService }, { token: CsvDownloadService }, { token: SHAREDZ_EXTENSION }, { token: i4.Router }, { token: i3$1.MatDialog }], target: i0.ɵɵFactoryTarget.Injectable }); }
21515
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthPoliciesPageService, providedIn: 'root' }); }
21516
+ }
21517
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthPoliciesPageService, decorators: [{
21518
+ type: Injectable,
21519
+ args: [{
21520
+ providedIn: 'root'
21521
+ }]
21522
+ }], ctorParameters: function () { return [{ type: SchemaService }, { type: SettingsService, decorators: [{
21523
+ type: Inject,
21524
+ args: [SETTINGS_SERVICE]
21525
+ }] }, { type: DataTableFilterService }, { type: CsvDownloadService }, { type: undefined, decorators: [{
21526
+ type: Inject,
21527
+ args: [SHAREDZ_EXTENSION]
21528
+ }] }, { type: i4.Router }, { type: i3$1.MatDialog }]; } });
21529
+
21530
+ /*
21531
+ Copyright NetFoundry Inc.
21532
+
21533
+ Licensed under the Apache License, Version 2.0 (the "License");
21534
+ you may not use this file except in compliance with the License.
21535
+ You may obtain a copy of the License at
21536
+
21537
+ https://www.apache.org/licenses/LICENSE-2.0
21538
+
21539
+ Unless required by applicable law or agreed to in writing, software
21540
+ distributed under the License is distributed on an "AS IS" BASIS,
21541
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21542
+ See the License for the specific language governing permissions and
21543
+ limitations under the License.
21544
+ */
21545
+ class AuthPoliciesPageComponent extends ListPageComponent {
21546
+ constructor(svc, filterService, tabNames, consoleEvents, dialogForm) {
21547
+ super(filterService, svc, consoleEvents, dialogForm);
21548
+ this.svc = svc;
21549
+ this.tabNames = tabNames;
21550
+ this.title = 'Auth Policies Management';
21551
+ this.formDataChanged = false;
21552
+ }
21553
+ ngOnInit() {
21554
+ this.tabs = this.tabNames.getTabs('policies');
21555
+ this.svc.refreshData = this.refreshData;
21556
+ super.ngOnInit();
21557
+ }
21558
+ headerActionClicked(action) {
21559
+ switch (action) {
21560
+ case 'add':
21561
+ this.svc.openEditForm();
21562
+ break;
21563
+ case 'edit':
21564
+ this.svc.openEditForm();
21565
+ break;
21566
+ case 'delete':
21567
+ let defaultPolicy;
21568
+ const selectedItems = this.rowData.filter((row) => {
21569
+ if (row.id === 'default') {
21570
+ defaultPolicy = row;
21571
+ }
21572
+ return row.selected;
21573
+ });
21574
+ this.svc.checkDefaultAuthPolicy(defaultPolicy).then((result) => {
21575
+ if (!result) {
21576
+ return;
21577
+ }
21578
+ const label = selectedItems.length > 1 ? 'auth policies' : 'auth policy';
21579
+ this.openBulkDelete(selectedItems, label);
21580
+ });
21581
+ break;
21582
+ default:
21583
+ }
21584
+ }
21585
+ tableAction(event) {
21586
+ switch (event?.action) {
21587
+ case 'toggleAll':
21588
+ case 'toggleItem':
21589
+ this.itemToggled(event.item);
21590
+ break;
21591
+ case 'update':
21592
+ this.svc.checkDefaultAuthPolicy(event.item).then((result) => {
21593
+ if (!result) {
21594
+ return;
21595
+ }
21596
+ this.svc.openEditForm(event.item?.id);
21597
+ });
21598
+ break;
21599
+ case 'create':
21600
+ this.svc.openEditForm();
21601
+ break;
21602
+ case 'delete':
21603
+ this.svc.checkDefaultAuthPolicy(event.item).then((result) => {
21604
+ if (!result) {
21605
+ return;
21606
+ }
21607
+ this.deleteItem(event.item);
21608
+ });
21609
+ break;
21610
+ default:
21611
+ break;
21612
+ }
21613
+ }
21614
+ deleteItem(item) {
21615
+ this.openBulkDelete([item], 'auth-policy');
21616
+ }
21617
+ closeModal(event) {
21618
+ this.svc.sideModalOpen = false;
21619
+ if (event?.refresh) {
21620
+ this.refreshData();
21621
+ }
21622
+ }
21623
+ dataChanged(event) {
21624
+ this.formDataChanged = event;
21625
+ }
21626
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthPoliciesPageComponent, deps: [{ token: AuthPoliciesPageService }, { token: DataTableFilterService }, { token: TabNameService }, { token: ConsoleEventsService }, { token: i3$1.MatDialog }], target: i0.ɵɵFactoryTarget.Component }); }
21627
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AuthPoliciesPageComponent, selector: "lib-auth-policies", usesInheritance: true, ngImport: i0, template: "<div class=\"ziti-page-container ziti-configs-container\">\n <lib-list-page-header [title]=\"title\"\n [tabs]=\"tabs\"\n [showAdd]=\"!itemsSelected\"\n (actionClicked)=\"headerActionClicked($event)\"></lib-list-page-header>\n\n <lib-data-table [tableId]=\"'configurations'\"\n [rowData]=\"rowData\"\n [columnDefinitions]=\"columnDefs\"\n (actionRequested)=\"tableAction($event)\"\n [startCount]=\"startCount\"\n [endCount]=\"endCount\"\n [totalCount]=\"totalCount\"\n [emptyMsg]=\"'No Configurations defined, Click the plus to add a Configuration.'\"\n [filterApplied]=\"filterApplied\"\n [menuItems]=\"svc.menuItems\"\n (gridReady)=\"gridReady($event)\"\n >\n </lib-data-table>\n</div>\n", styles: [".configurations{width:100%;height:100%;display:flex;flex-direction:column;position:relative;flex:1 1 auto}\n"], dependencies: [{ kind: "component", type: ListPageHeaderComponent, selector: "lib-list-page-header", inputs: ["title", "tabs", "showAdd", "hideAction"], outputs: ["actionClicked"] }, { kind: "component", type: DataTableComponent, selector: "lib-data-table", inputs: ["rowData", "expandRowData", "collapseRowData", "rowValidation", "isTimeSearchAvailable", "isLoading", "tableId", "options", "validateService", "rowsToggled", "tableRefreshCount", "view", "serverSideDataSource", "allowDownload", "startCount", "endCount", "totalCount", "emptyMsg", "filterApplied", "menuItems", "headerActions", "noItemsClass", "entityTypeName", "showNoItemsAdd", "currentPage", "noItemsImage", "rowHeight", "filterName", "filterColumn", "columnDefinitions", "refreshCount"], outputs: ["actionRequested", "gridReady", "dragStart", "dragLeave", "pageChanged"] }] }); }
21628
+ }
21629
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthPoliciesPageComponent, decorators: [{
21630
+ type: Component,
21631
+ args: [{ selector: 'lib-auth-policies', template: "<div class=\"ziti-page-container ziti-configs-container\">\n <lib-list-page-header [title]=\"title\"\n [tabs]=\"tabs\"\n [showAdd]=\"!itemsSelected\"\n (actionClicked)=\"headerActionClicked($event)\"></lib-list-page-header>\n\n <lib-data-table [tableId]=\"'configurations'\"\n [rowData]=\"rowData\"\n [columnDefinitions]=\"columnDefs\"\n (actionRequested)=\"tableAction($event)\"\n [startCount]=\"startCount\"\n [endCount]=\"endCount\"\n [totalCount]=\"totalCount\"\n [emptyMsg]=\"'No Configurations defined, Click the plus to add a Configuration.'\"\n [filterApplied]=\"filterApplied\"\n [menuItems]=\"svc.menuItems\"\n (gridReady)=\"gridReady($event)\"\n >\n </lib-data-table>\n</div>\n", styles: [".configurations{width:100%;height:100%;display:flex;flex-direction:column;position:relative;flex:1 1 auto}\n"] }]
21632
+ }], ctorParameters: function () { return [{ type: AuthPoliciesPageService }, { type: DataTableFilterService }, { type: TabNameService }, { type: ConsoleEventsService }, { type: i3$1.MatDialog }]; } });
21633
+
21634
+ class AuthPolicy {
21635
+ constructor() {
21636
+ this.name = '';
21637
+ this.id = '';
21638
+ this.primary = {
21639
+ cert: {
21640
+ allowed: false,
21641
+ allowExpiredCerts: false,
21642
+ },
21643
+ extJwt: {
21644
+ allowed: false,
21645
+ allowedSigners: []
21646
+ },
21647
+ updb: {
21648
+ allowed: false,
21649
+ lockoutDurationMinutes: 0,
21650
+ maxAttempts: 5,
21651
+ minPasswordLength: 5,
21652
+ requireMixedCase: false,
21653
+ requireNumberChar: false,
21654
+ requireSpecialChar: false
21655
+ }
21656
+ };
21657
+ this.secondary = {
21658
+ requireTotp: false,
21659
+ requireExtJwtSigner: undefined
21660
+ };
21661
+ this.tags = {};
21662
+ }
21663
+ }
21664
+
21665
+ class AuthPolicyFormService {
21666
+ constructor(dataService, extService, growlerService, validationService) {
21667
+ this.dataService = dataService;
21668
+ this.extService = extService;
21669
+ this.growlerService = growlerService;
21670
+ this.validationService = validationService;
21671
+ this.items = [];
21672
+ this.errors = [];
21673
+ this.saveDisabled = false;
21674
+ this.jwtSigners = [];
21675
+ this.jwtSignerNamedAttributes = [];
21676
+ this.jwtSignerNamedAttributesMap = {};
21677
+ this.jwtSignersLoading = false;
21678
+ this.paging = {
21679
+ filter: "",
21680
+ noSearch: true,
21681
+ order: "asc",
21682
+ page: 1,
21683
+ searchOn: "name",
21684
+ sort: "name",
21685
+ total: 100
21686
+ };
21687
+ }
21688
+ getJwtSignerNamedAttributes() {
21689
+ return this.dataService.get('external-jwt-signers', { rawFilter: true, filter: '', sort: 'name', order: 'asc', total: -1, page: 1 }, []).then((result) => {
21690
+ const namedAttributes = result.data.map((identity) => {
21691
+ this.jwtSignerNamedAttributesMap[identity.name] = identity.id;
21692
+ return identity.name;
21693
+ });
21694
+ this.jwtSignerNamedAttributes = namedAttributes;
21695
+ return namedAttributes;
21696
+ });
21697
+ }
21698
+ getJwtSigners(filters = [], page = 1) {
21699
+ this.jwtSignersLoading = true;
21700
+ const paging = cloneDeep(this.paging);
21701
+ if (filters.length > 0) {
21702
+ paging.noSearch = false;
21703
+ }
21704
+ return this.dataService.get('external-jwt-signers', paging, filters).then((result) => {
21705
+ this.jwtSigners = result.data;
21706
+ }).finally(() => {
21707
+ this.jwtSignersLoading = false;
21708
+ });
21709
+ }
21710
+ save(formData) {
21711
+ const isUpdate = !isEmpty(formData.id);
21712
+ const data = this.getAuthPolicyDataModel(formData, isUpdate);
21713
+ let prom;
21714
+ if (isUpdate) {
21715
+ prom = this.dataService.put('auth-policies', data, formData.id, true);
21716
+ }
21717
+ else {
21718
+ prom = this.dataService.post('auth-policies', data, true);
21719
+ }
21720
+ return prom.then(async (result) => {
21721
+ const id = isUpdate ? formData.id : (result?.data?.id || result?.id);
21722
+ let config = await this.dataService.getSubdata('auth-policies', id, '').then((svcData) => {
21723
+ return svcData.data;
21724
+ });
21725
+ return this.extService.formDataSaved(config).then((formSavedResult) => {
21726
+ if (!formSavedResult) {
21727
+ return config;
21728
+ }
21729
+ const growlerData = new GrowlerModel('success', 'Success', `Auth Policy ${isUpdate ? 'Updated' : 'Created'}`, `Successfully ${isUpdate ? 'updated' : 'created'} Auth Policy: ${formData.name}`);
21730
+ this.growlerService.show(growlerData);
21731
+ return config;
21732
+ }).catch((result) => {
21733
+ return false;
21734
+ });
21735
+ }).catch((resp) => {
21736
+ let errorMessage;
21737
+ if (resp?.error?.error?.cause?.message) {
21738
+ errorMessage = resp?.error?.error?.cause?.message;
21739
+ }
21740
+ else if (resp?.error?.error?.cause?.reason) {
21741
+ errorMessage = resp?.error?.error?.cause?.reason;
21742
+ }
21743
+ else if (resp?.error?.message) {
21744
+ errorMessage = resp?.error?.message;
21745
+ }
21746
+ else {
21747
+ errorMessage = 'An unknown error occurred';
21748
+ }
21749
+ const growlerData = new GrowlerModel('error', 'Error', `Error Creating Auth Policy`, errorMessage);
21750
+ this.growlerService.show(growlerData);
21751
+ throw resp;
21752
+ });
21753
+ }
21754
+ getAuthPolicyDataModel(formData, isUpdate) {
21755
+ const saveModel = new AuthPolicy();
21756
+ const modelProperties = keys(saveModel);
21757
+ modelProperties.forEach((prop) => {
21758
+ switch (prop) {
21759
+ default:
21760
+ saveModel[prop] = formData[prop];
21761
+ }
21762
+ });
21763
+ return saveModel;
21764
+ }
21765
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthPolicyFormService, deps: [{ token: ZITI_DATA_SERVICE }, { token: SHAREDZ_EXTENSION }, { token: GrowlerService }, { token: ValidationService }], target: i0.ɵɵFactoryTarget.Injectable }); }
21766
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthPolicyFormService, providedIn: 'root' }); }
21767
+ }
21768
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthPolicyFormService, decorators: [{
21769
+ type: Injectable,
21770
+ args: [{
21771
+ providedIn: 'root'
21772
+ }]
21773
+ }], ctorParameters: function () { return [{ type: ZitiDataService, decorators: [{
21774
+ type: Inject,
21775
+ args: [ZITI_DATA_SERVICE]
21776
+ }] }, { type: undefined, decorators: [{
21777
+ type: Inject,
21778
+ args: [SHAREDZ_EXTENSION]
21779
+ }] }, { type: GrowlerService }, { type: ValidationService }]; } });
21780
+
21781
+ /*
21782
+ Copyright NetFoundry Inc.
21783
+
21784
+ Licensed under the Apache License, Version 2.0 (the "License");
21785
+ you may not use this file except in compliance with the License.
21786
+ You may obtain a copy of the License at
21787
+
21788
+ https://www.apache.org/licenses/LICENSE-2.0
21789
+
21790
+ Unless required by applicable law or agreed to in writing, software
21791
+ distributed under the License is distributed on an "AS IS" BASIS,
21792
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21793
+ See the License for the specific language governing permissions and
21794
+ limitations under the License.
21795
+ */
21796
+ class AuthPolicyFormComponent extends ProjectableForm {
21797
+ constructor(svc, schemaSvc, growlerService, extService, settingsService, zitiService, router, route, location, validationService) {
21798
+ super(growlerService, extService, zitiService, router, route, location);
21799
+ this.svc = svc;
21800
+ this.schemaSvc = schemaSvc;
21801
+ this.settingsService = settingsService;
21802
+ this.zitiService = zitiService;
21803
+ this.router = router;
21804
+ this.route = route;
21805
+ this.validationService = validationService;
21806
+ this.formData = new AuthPolicy();
21807
+ this.errors = {};
21808
+ this.close = new EventEmitter();
21809
+ this.allowedJwtSignerAttributes = [];
21810
+ this.formView = 'simple';
21811
+ this.options = [];
21812
+ this.isEditing = !isEmpty(this.formData.id);
21813
+ this.formDataInvalid = false;
21814
+ this.editMode = false;
21815
+ this.items = [];
21816
+ this.settings = {};
21817
+ this.fileSelectOpening = false;
21818
+ this.entityType = 'auth-policies';
21819
+ this.entityClass = AuthPolicy;
21820
+ this.jwtSignersFilterChangedDebounced = debounce(this.jwtSignerFilterChanged.bind(this), 200);
21821
+ this._apiData = {};
21822
+ }
21823
+ ngOnInit() {
21824
+ super.ngOnInit();
21825
+ this.svc.getJwtSigners();
21826
+ this.svc.getJwtSignerNamedAttributes().then(() => {
21827
+ this.initSelectedAttributes();
21828
+ });
21829
+ this.settingsService.settingsChange.subscribe((results) => {
21830
+ this.settings = results;
21831
+ });
21832
+ }
21833
+ entityUpdated() {
21834
+ super.entityUpdated();
21835
+ }
21836
+ ngOnDestroy() {
21837
+ this.clearForm();
21838
+ }
21839
+ headerActionRequested(event) {
21840
+ switch (event.name) {
21841
+ case 'save':
21842
+ this.save(event);
21843
+ break;
21844
+ case 'close':
21845
+ this.returnToListPage();
21846
+ break;
21847
+ case 'toggle-view':
21848
+ this.formView = event.data;
21849
+ break;
21850
+ }
21851
+ }
21852
+ clear() {
21853
+ this.formData.configTypeId = '';
21854
+ this.clearForm();
21855
+ }
21856
+ clearForm() {
21857
+ this.items.forEach((item) => {
21858
+ if (item?.component)
21859
+ item.component.destroy();
21860
+ });
21861
+ this.errors = {};
21862
+ this.items = [];
21863
+ this.formData = new AuthPolicy();
21864
+ if (this.subscription)
21865
+ this.subscription.unsubscribe();
21866
+ }
21867
+ allowedJwtSignersChanged(event) {
21868
+ this.formData.primary.extJwt.allowedSigners = this.getSelectedAttributes(this.allowedJwtSignerAttributes, this.svc.jwtSignerNamedAttributesMap);
21869
+ }
21870
+ getSelectedAttributes(namedAttributes, namedAttributeMap) {
21871
+ const prependedNamedAttributes = namedAttributes.map((attr) => {
21872
+ return namedAttributeMap[attr];
21873
+ });
21874
+ return [...prependedNamedAttributes];
21875
+ }
21876
+ initSelectedAttributes() {
21877
+ const jwtSignerNamedAttributesMap = invert(this.svc.jwtSignerNamedAttributesMap);
21878
+ this.formData.primary?.extJwt?.allowedSigners?.forEach(attr => {
21879
+ this.allowedJwtSignerAttributes.push(jwtSignerNamedAttributesMap[attr]);
21880
+ });
21881
+ }
21882
+ async save(event) {
21883
+ if (!this.validate()) {
21884
+ return;
21885
+ }
21886
+ const tagVals = this.getTagValues();
21887
+ if (!isEmpty(tagVals)) {
21888
+ forOwn(tagVals, (value, key) => {
21889
+ this.formData.tags[key] = value;
21890
+ });
21891
+ }
21892
+ const apiData = this.apiData;
21893
+ apiData.id = this.formData.id;
21894
+ this.isLoading = true;
21895
+ this.svc.save(apiData).then((result) => {
21896
+ if (this.isModal) {
21897
+ this.closeModal(true, true);
21898
+ return;
21899
+ }
21900
+ this.initData = this.formData;
21901
+ this._dataChange = false;
21902
+ this.returnToListPage();
21903
+ }).finally(() => {
21904
+ this.isLoading = false;
21905
+ });
21906
+ }
21907
+ validate() {
21908
+ this.errors = {};
21909
+ const labels = [];
21910
+ const growlers = [];
21911
+ if (isEmpty(this.formData.name)) {
21912
+ this.errors.name = true;
21913
+ labels.push('Name');
21914
+ }
21915
+ if (!isEmpty(this.errors)) {
21916
+ let missingFields = labels.join(', ');
21917
+ growlers.push(new GrowlerModel('error', 'Invalid', `Missing Form Data`, `Please enter a value for the highlighted fields: ${missingFields}`));
21918
+ }
21919
+ if (!isEmpty(growlers)) {
21920
+ growlers.forEach((growlerData) => {
21921
+ this.growlerService.show(growlerData);
21922
+ });
21923
+ return isEmpty(this.errors);
21924
+ }
21925
+ growlers.forEach((growlerData) => {
21926
+ this.growlerService.show(growlerData);
21927
+ });
21928
+ return isEmpty(this.errors);
21929
+ }
21930
+ get apiCallURL() {
21931
+ return this.settings.selectedEdgeController + '/edge/management/v1/auth-policies' + (this.formData.id ? `/${this.formData.id}` : '');
21932
+ }
21933
+ get apiData() {
21934
+ const data = {
21935
+ name: this.formData.name || '',
21936
+ primary: this.formData.primary || {},
21937
+ secondary: this.formData.secondary || {},
21938
+ tags: this.formData.tags || {}
21939
+ };
21940
+ this._apiData = data;
21941
+ return this._apiData;
21942
+ }
21943
+ set apiData(data) {
21944
+ this._apiData = data;
21945
+ }
21946
+ dataChanged(event) {
21947
+ this._apiData = cloneDeep(this.apiData);
21948
+ }
21949
+ toggleCertAllowed() {
21950
+ this.formData.primary.cert.allowed = !this.formData.primary.cert.allowed;
21951
+ if (!this.formData.primary.cert.allowed) {
21952
+ this.formData.primary.cert.allowExpiredCerts = false;
21953
+ }
21954
+ }
21955
+ toggleExtJwtAllowed() {
21956
+ this.formData.primary.extJwt.allowed = !this.formData.primary.extJwt.allowed;
21957
+ }
21958
+ toggleUpdbAllowed() {
21959
+ this.formData.primary.updb.allowed = !this.formData.primary.updb.allowed;
21960
+ }
21961
+ toggleAllowExpiredCerts() {
21962
+ this.formData.primary.cert.allowExpiredCerts = !this.formData.primary.cert.allowExpiredCerts;
21963
+ }
21964
+ toggleUpdbMixed() {
21965
+ this.formData.primary.updb.requireMixedCase = !this.formData.primary.updb.requireMixedCase;
21966
+ }
21967
+ toggleUpdbNumeric() {
21968
+ this.formData.primary.updb.requireNumericChar = !this.formData.primary.updb.requireNumericChar;
21969
+ }
21970
+ toggleUpdbSpecial() {
21971
+ this.formData.primary.updb.requireSpecialChar = !this.formData.primary.updb.requireSpecialChar;
21972
+ }
21973
+ toggleRequireTotp() {
21974
+ this.formData.secondary.requireTotp = !this.formData.secondary.requireTotp;
21975
+ }
21976
+ openFileSelect(event) {
21977
+ this.filterInput.nativeElement.click();
21978
+ this.fileSelectOpening = true;
21979
+ delay(() => {
21980
+ this.fileSelectOpening = false;
21981
+ }, 1000);
21982
+ }
21983
+ selectPemFile(event) {
21984
+ console.log(event);
21985
+ const file = event?.target?.files[0];
21986
+ if (file) {
21987
+ const fileReader = new FileReader();
21988
+ fileReader.onload = (fileLoadedEvent) => {
21989
+ const textFromSelectedFile = fileLoadedEvent.target?.result;
21990
+ if (!this.validationService.isValidPEM(textFromSelectedFile?.trim())) {
21991
+ this.errors.certPem = true;
21992
+ const growlerData = new GrowlerModel('error', 'Invalid', `Cert PEM Invalid`, `The file selected for the Cert PEM field is invalid. Please check your input and try again.`);
21993
+ this.growlerService.show(growlerData);
21994
+ this.formData.certPem = 'Invalid PEM. Please select or enter a valid PEM certificate.';
21995
+ }
21996
+ else {
21997
+ unset(this.errors, 'certPem');
21998
+ this.formData.certPem = textFromSelectedFile;
21999
+ }
22000
+ };
22001
+ fileReader.readAsText(file, "UTF-8");
22002
+ }
22003
+ }
22004
+ apiActionRequested(action) {
22005
+ switch (action.id) {
22006
+ case 'cli':
22007
+ this.copyCLICommand();
22008
+ break;
22009
+ case 'curl':
22010
+ this.copyCURLCommand();
22011
+ break;
22012
+ }
22013
+ }
22014
+ copyCLICommand() {
22015
+ const command = `ziti edge ${this.formData.id ? 'update' : 'create'} auth-policy ${this.formData.id ? `'${this.formData.id}'` : ''} ${this.formData.id ? '--name' : ''} '${this.formData.name}' --primary-cert-allowed '${this.formData.primary.cert.allowed}' --primary-cert-expired-allowed '${this.formData.primary.cert.allowExpiredCerts}' --primary-ext-jwt-allowed '${this.formData.primary.extJwt.allowed}' --primary-ext-jwt-allowed-signers ${this.formData.primary.extJwt.allowedSigners.join(',') || ''} --primary-updb-allowed '${this.formData.primary.updb.allowed}' --primary-updb-lockout-min ${this.formData.primary.updb.lockoutDurationMinutes} --primary-updb-max-attempts ${this.formData.primary.updb.maxAttempts} --primary-updb-min-length ${this.formData.primary.updb.minPasswordLength} --primary-updb-req-mixed-case '${this.formData.primary.updb.requireMixedCase}' --primary-updb-req-numbers '${this.formData.primary.updb.requireNumberChar}' --primary-updb-req-special '${this.formData.primary.updb.requireSpecialChar}' --secondary-req-ext-jwt-signer '${this.formData.secondary.requireExtJwtSigner}' --secondary-req-totp '${this.formData.secondary.requireTotp}' --tags-json '${JSON.stringify(this.formData.tags)}'`;
22016
+ navigator.clipboard.writeText(command);
22017
+ const growlerData = new GrowlerModel('success', 'Success', `Text Copied`, `CLI command copied to clipboard`);
22018
+ this.growlerService.show(growlerData);
22019
+ }
22020
+ copyCURLCommand() {
22021
+ const command = `curl '${this.apiCallURL}' \\
22022
+ ${this.formData.id ? '--request PATCH \\' : '\\'}
22023
+ -H 'accept: application/json' \\
22024
+ -H 'content-type: application/json' \\
22025
+ -H 'zt-session: ${this.settings.session.id}' \\
22026
+ --data-raw '${JSON.stringify(this.apiData)}'`;
22027
+ navigator.clipboard.writeText(command);
22028
+ const growlerData = new GrowlerModel('success', 'Success', `Text Copied`, `CURL command copied to clipboard`);
22029
+ this.growlerService.show(growlerData);
22030
+ }
22031
+ scopesOnKeyup(event) {
22032
+ const key = event.key?.toLowerCase();
22033
+ if (key === " " || key === 'enter') {
22034
+ event.preventDefault();
22035
+ event.stopPropagation();
22036
+ const element = event.target;
22037
+ element.blur();
22038
+ element.focus();
22039
+ }
22040
+ }
22041
+ jwtSignerFilterChanged(event) {
22042
+ if (event?.keyCode === KEY_CODES.LEFT_ARROW || event?.keyCode === KEY_CODES.RIGHT_ARROW || event?.keyCode === KEY_CODES.UP_ARROW || event?.keyCode === KEY_CODES.DOWN_ARROW) {
22043
+ return;
22044
+ }
22045
+ let filters = [];
22046
+ if (event?.target?.value) {
22047
+ filters.push({
22048
+ columnId: 'name',
22049
+ value: event.target.value,
22050
+ label: event.target.value,
22051
+ filterName: 'Name',
22052
+ type: 'TEXTINPUT',
22053
+ });
22054
+ }
22055
+ this.svc.getJwtSigners(filters, 1);
22056
+ }
22057
+ secondaryJwtSignerChanged(event) {
22058
+ this.svc.filteredJwtSigners = this.svc.jwtSigners.filter((jwtSigner) => {
22059
+ return jwtSigner.id === this.formData.secondary.requireExtJwtSigner;
22060
+ });
22061
+ }
22062
+ clearJwtSignerFilter(event) {
22063
+ const filters = [];
22064
+ this.svc.getJwtSigners(filters, 1);
22065
+ }
22066
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthPolicyFormComponent, deps: [{ token: AuthPolicyFormService }, { token: SchemaService }, { token: GrowlerService }, { token: SHAREDZ_EXTENSION }, { token: SETTINGS_SERVICE }, { token: ZITI_DATA_SERVICE }, { token: i4.Router }, { token: i4.ActivatedRoute }, { token: i1$4.Location }, { token: ValidationService }], target: i0.ɵɵFactoryTarget.Component }); }
22067
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AuthPolicyFormComponent, selector: "lib-configuration", inputs: { formData: "formData", errors: "errors" }, outputs: { close: "close" }, viewQueries: [{ propertyName: "filterInput", first: true, predicate: ["fileSelect"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"projectable-form-wrapper\"\n (keyup.enter)=\"save($event)\"\n (keyup.escape)=\"closeModal(false)\"\n tabindex=\"0\"\n>\n <lib-form-header\n [data]=\"formData\"\n [title]=\"(formData.id ? 'Auth Policy Details' : 'Create Auth Policy')\"\n [moreActions]=\"formData.moreActions\"\n (actionRequested)=\"headerActionRequested($event)\"\n [(formView)]=\"formView\"\n [saveDisabled]=\"svc.saveDisabled || formDataInvalid\"\n ></lib-form-header>\n <div class=\"jwt-signer-form-container projectable-form-container\">\n <div class=\"projectable-form-main-column form-group-row\" [hidden]=\"formView !== 'simple'\">\n <div class=\"form-group-column three-fifths\">\n <lib-form-field-container\n [title]=\"'Name'\"\n [label]=\"'Required'\"\n >\n <input class=\"form-field-input read-only\" [(ngModel)]=\"formData.name\" [ngClass]=\"{error: errors['name']}\" placeholder=\"Name this JWT Signer\"/>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'Primary Authentication'\"\n [layout]=\"'row'\"\n >\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">Cert</div>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Allow x509 certificate based authentication\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <div\n (click)=\"toggleCertAllowed()\"\n [ngClass]=\"{ on: formData.primary.cert.allowed }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.primary.cert.allowed\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.primary.cert.allowed\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">Ext JWT</div>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Allow externally signed JWT bearer tokens\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <div\n (click)=\"toggleExtJwtAllowed()\"\n [ngClass]=\"{ on: formData.primary.extJwt.allowed }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.primary.extJwt.allowed\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.primary.extJwt.allowed\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">UPDB</div>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Allow authentication via a traditional &quot;Username Password Database&quot;\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <div\n (click)=\"toggleUpdbAllowed()\"\n [ngClass]=\"{ on: formData.primary.updb.allowed }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.primary.updb.allowed\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.primary.updb.allowed\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n *ngIf=\"formData.primary.cert.allowed\"\n [title]=\"'Cert Options'\"\n [layout]=\"'row'\"\n >\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">Allow Expired Certificates</div>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Allow expired client certificates to authenticate\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <div\n (click)=\"toggleAllowExpiredCerts()\"\n [ngClass]=\"{ on: formData.primary.cert.allowExpiredCerts }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.primary.cert.allowExpiredCerts\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.primary.cert.allowExpiredCerts\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n *ngIf=\"formData.primary.extJwt.allowed\"\n [title]=\"'Ext JWT Options'\"\n [layout]=\"'column'\"\n >\n <div class=\"form-field-label-container allowed-signers-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Allowed JWT Signers</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Choose which External JWT Signers may be used for authentication\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <lib-tag-selector\n [(selectedNamedAttributes)]=\"allowedJwtSignerAttributes\"\n [availableNamedAttributes]=\"svc.jwtSignerNamedAttributes\"\n [placeholder]=\"'Select which External JWT Signers to allow'\"\n (selectedNamedAttributesChange)=\"allowedJwtSignersChanged($event)\"\n ></lib-tag-selector>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n *ngIf=\"formData.primary.updb.allowed\"\n [title]=\"'UPDB Options'\"\n [layout]=\"'column'\"\n >\n <div class=\"form-field-row updb-input-options\">\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Minimum Length</span>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter a numeric value\" type=\"number\" [(ngModel)]=\"formData.primary.updb.minPasswordLength\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Max Attempts</span>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter a numeric value\" type=\"number\" [(ngModel)]=\"formData.primary.updb.maxAttempts\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Lockout Duration <div class=\"form-sub-text\">(min)</div></span>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter time in min\" type=\"number\" [(ngModel)]=\"formData.primary.updb.lockoutDurationMinutes\"/>\n </div>\n </div>\n <div class=\"form-field-row\">\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">Mixed Case</div>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Require upper and lower case charachters\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <div\n (click)=\"toggleUpdbMixed()\"\n [ngClass]=\"{ on: formData.primary.updb.requireMixedCase }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.primary.updb.requireMixedCase\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.primary.updb.requireMixedCase\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">Numeric</div>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Require numerical charachters 0-9\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <div\n (click)=\"toggleUpdbNumeric()\"\n [ngClass]=\"{ on: formData.primary.updb.requireNumericChar }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.primary.updb.requireNumericChar\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.primary.updb.requireNumericChar\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">Special</div>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Require special (non-alpha numeric) charachters. ie. !%$@*\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <div\n (click)=\"toggleUpdbSpecial()\"\n [ngClass]=\"{ on: formData.primary.updb.requireSpecialChar }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.primary.updb.requireSpecialChar\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.primary.updb.requireSpecialChar\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-toggle [(toggleOn)]=\"showMore\" (toggleOnChange)=\"showMoreChanged($event)\" style=\"margin: 0px 10px\"></lib-form-field-toggle>\n <div [hidden]=\"!showMore\" class=\"form-group-column\">\n <lib-form-field-container\n [title]=\"'Custom Tags'\"\n [label]=\"'OPTIONAL'\"\n class=\"form-field-advanced\"\n >\n <lib-custom-tags [(tags)]=\"formData.tags\"></lib-custom-tags>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column two-fifths\">\n <lib-form-field-container\n [title]=\"'Secondary Authentication'\"\n [label]=\"'OPTIONAL'\"\n [layout]=\"'column'\"\n [contentStyle]=\"'z-index: 1000001'\"\n >\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">TOTP MFA</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Require authenticating clients to have TOTP MFA enabled (Time-based, One-Time Password)\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">Require TOTP</div>\n </div>\n <div\n (click)=\"toggleRequireTotp()\"\n [ngClass]=\"{ on: formData.secondary.requireTotp }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.secondary.requireTotp\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.secondary.requireTotp\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">JWT Signer</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Require every client request to have a JWT from the specified External JTW Signer in the HTTP Authentication header\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <p-dropdown\n placeholder=\"Select JWT Signer...\"\n optionLabel=\"name\"\n optionValue=\"id\"\n filterBy=\"name\"\n [options]=\"svc.jwtSigners\"\n [filter]=\"true\"\n [showClear]=\"true\"\n (change)=\"secondaryJwtSignerChanged($event)\"\n [(ngModel)]=\"formData.secondary.requireExtJwtSigner\"\n >\n <ng-template pTemplate=\"filter\" let-options=\"options\">\n <div class=\"dropdown-filter-container\">\n <div class=\"p-inputgroup\" (click)=\"$event.stopPropagation()\">\n <span class=\"p-inputgroup-addon\"><i class=\"pi pi-search\"></i></span>\n <input\n type=\"text\"\n pInputText\n placeholder=\"Filter\"\n (keyup)=\"jwtSignersFilterChangedDebounced($event)\" />\n </div>\n <button pButton\n icon=\"pi pi-times\"\n [ngClass]=\"{'configs-loading': svc.jwtSignersLoading}\"\n (click)=\"clearJwtSignerFilter($event)\"\n severity=\"secondary\">\n </button>\n <div class=\"spinner\" *ngIf=\"svc.jwtSignersLoading\"></div>\n </div>\n </ng-template>\n </p-dropdown>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'API Calls'\"\n [headerActions]=\"apiOptions\"\n (actionRequested)=\"apiActionRequested($event)\"\n [class]=\"'api-data-no-wrap'\"\n >\n <div class=\"form-row\">\n <input class=\"form-field-input\" [value]=\"apiCallURL\"/>\n <div class=\"icon-copy copy\" (click)=\"copyToClipboard(apiCallURL)\"></div>\n </div>\n <lib-json-view *ngIf=\"formData\" [(data)]=\"apiData\" [readOnly]=\"true\" [showCopy]=\"true\"></lib-json-view>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column\" *ngIf=\"formView === 'raw'\">\n <lib-json-view *ngIf=\"formData\" [(data)]=\"formData\"></lib-json-view>\n </div>\n </div>\n</div>\n<lib-loading-indicator *ngIf=\"isLoading\" [isLoading]=\"isLoading\"></lib-loading-indicator>\n", styles: ["@charset \"UTF-8\";.form-group-column.three-fifths{min-width:500px}.jwt-signer-form-container{display:flex;flex-direction:column;height:100%;width:100%;align-items:center;gap:var(--gapXL)}.jwt-signer-form-container .select-file-button{padding-left:var(--paddingMedium);padding-right:var(--paddingMedium);height:25px;width:-moz-fit-content;width:fit-content;white-space:nowrap;display:flex;align-items:center;justify-content:center;font-weight:600;font-size:14px;background:var(--primary);border-style:solid;border-width:1px;border-color:var(--stroke);color:var(--white);cursor:pointer;border-radius:var(--inputBorderRadius);gap:var(--marginMedium);margin-top:-5px}.jwt-signer-form-container .select-file-button:hover{filter:brightness(.8)}.jwt-signer-form-container .select-file-button:active{filter:grayscale(1);transform:translateY(1px)}.jwt-signer-form-container .select-file-button .spinner{display:inline-block;width:8px;height:8px;border-radius:50%;background:transparent;border-top:2px solid white;border-right:2px solid white;border-bottom:2px solid transparent;border-left:2px solid transparent;animation:loading .5s infinite linear}.jwt-signer-form-container .select-file-label-container{gap:var(--marginMedium)}.jwt-signer-form-container .updb-input-options{margin-top:var(--marginSmall);background-color:var(--formGroup);padding:var(--paddingMedium);border-radius:var(--inputBorderRadius)}.jwt-signer-form-container .updb-input-options .form-field-title{color:var(--offWhite)}::ng-deep .jwt-signer-form-container select:disabled,::ng-deep .jwt-signer-form-container input:disabled{opacity:.75!important;cursor:text;background-color:var(--stroke)!important}::ng-deep .api-data-no-wrap .jse-text-mode{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller .cm-content{width:100%;overflow:auto}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller .cm-content .\\37cr{white-space:nowrap}.radio-group-container{display:flex;gap:var(--marginLarge)}.radio-group-container:focus .radio-button-container .radio-button-circle{border-color:var(--primaryColor)}.radio-group-container .radio-button-container{display:flex;flex-direction:row;align-items:center;background-color:var(--formGroup);border-radius:var(--inputBorderRadius);width:100%;padding-left:var(--paddingMedium);padding-right:var(--paddingMedium);padding-top:var(--paddingLarge);padding-bottom:var(--paddingLarge);cursor:pointer;gap:var(--marginMedium)}.radio-group-container .radio-button-container .radio-button-circle{display:flex;width:21px;height:21px;border-radius:21px;border-width:2px;border-style:solid;border-color:var(--offWhite);align-items:center;justify-content:center;background-color:var(--offWhite)}.radio-group-container .radio-button-container .radio-button-circle .radio-button-inner-circle{display:none;width:15px;height:15px;border-radius:15px;align-items:center;justify-content:center;background-color:var(--primaryColor)}.radio-group-container .radio-button-container.selected .radio-button-circle .radio-button-inner-circle{display:flex}.radio-group-container .radio-button-container:active .radio-button-circle .radio-button-inner-circle{display:flex;background-color:var(--menu)}.radio-group-container .radio-button-container .radio-button-label{color:var(--offWhite);font-size:14px;font-weight:600}.allowed-signers-container{background-color:var(--formGroup);padding:var(--paddingMedium);border-radius:var(--inputBorderRadius)}.allowed-signers-container .form-field-title{color:var(--offWhite)}\n"], dependencies: [{ kind: "directive", type: i1$4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i6$1.InputText, selector: "[pInputText]" }, { kind: "directive", type: i5$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i8.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { kind: "directive", type: i2.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: i4$2.Dropdown, selector: "p-dropdown", inputs: ["id", "scrollHeight", "filter", "name", "style", "panelStyle", "styleClass", "panelStyleClass", "readonly", "required", "editable", "appendTo", "tabindex", "placeholder", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "autoDisplayFirst", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "maxlength", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "disabled", "itemSize", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "filterValue", "options"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: FormHeaderComponent, selector: "lib-form-header", inputs: ["data", "title", "moreActions", "formView", "saveDisabled", "saveTooltip", "actionButtonText", "moreActionsText"], outputs: ["formViewChange", "actionRequested"] }, { kind: "component", type: FormFieldContainerComponent, selector: "lib-form-field-container", inputs: ["title", "title2", "layout", "helpText", "helpText2", "label", "count", "action", "actionLabel", "class", "contentStyle", "showHeader", "headerActions"], outputs: ["actionRequested"] }, { kind: "component", type: LoadingIndicatorComponent, selector: "lib-loading-indicator", inputs: ["isLoading"] }, { kind: "component", type: FormFieldToggleComponent, selector: "lib-form-field-toggle", inputs: ["label", "orientation", "labelOn", "labelOff", "toggleOn"], outputs: ["toggleOnChange"] }, { kind: "component", type: JsonViewComponent, selector: "lib-json-view", inputs: ["data", "schema", "readOnly", "jsonInvalid", "showCopy"], outputs: ["dataChange", "jsonChange", "jsonInvalidChange"] }, { kind: "component", type: TagSelectorComponent, selector: "lib-tag-selector", inputs: ["placeholder", "disableField", "disableCreate", "hideOption", "isLoading", "errorMessage", "focusOnInit", "selectedRoleAttributes", "selectedNamedAttributes", "hasError", "availableRoleAttributes", "availableNamedAttributes"], outputs: ["addRoleAttribute", "addNamedAttribute", "roleAttributeRemoved", "namedAttributeRemoved", "selectedRoleAttributesChange", "selectedNamedAttributesChange", "filterChange"] }, { kind: "component", type: CustomTagsComponent, selector: "lib-custom-tags", inputs: ["tags"], outputs: ["tagsChange"] }] }); }
22068
+ }
22069
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AuthPolicyFormComponent, decorators: [{
22070
+ type: Component,
22071
+ args: [{ selector: 'lib-configuration', template: "<div class=\"projectable-form-wrapper\"\n (keyup.enter)=\"save($event)\"\n (keyup.escape)=\"closeModal(false)\"\n tabindex=\"0\"\n>\n <lib-form-header\n [data]=\"formData\"\n [title]=\"(formData.id ? 'Auth Policy Details' : 'Create Auth Policy')\"\n [moreActions]=\"formData.moreActions\"\n (actionRequested)=\"headerActionRequested($event)\"\n [(formView)]=\"formView\"\n [saveDisabled]=\"svc.saveDisabled || formDataInvalid\"\n ></lib-form-header>\n <div class=\"jwt-signer-form-container projectable-form-container\">\n <div class=\"projectable-form-main-column form-group-row\" [hidden]=\"formView !== 'simple'\">\n <div class=\"form-group-column three-fifths\">\n <lib-form-field-container\n [title]=\"'Name'\"\n [label]=\"'Required'\"\n >\n <input class=\"form-field-input read-only\" [(ngModel)]=\"formData.name\" [ngClass]=\"{error: errors['name']}\" placeholder=\"Name this JWT Signer\"/>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'Primary Authentication'\"\n [layout]=\"'row'\"\n >\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">Cert</div>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Allow x509 certificate based authentication\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <div\n (click)=\"toggleCertAllowed()\"\n [ngClass]=\"{ on: formData.primary.cert.allowed }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.primary.cert.allowed\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.primary.cert.allowed\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">Ext JWT</div>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Allow externally signed JWT bearer tokens\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <div\n (click)=\"toggleExtJwtAllowed()\"\n [ngClass]=\"{ on: formData.primary.extJwt.allowed }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.primary.extJwt.allowed\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.primary.extJwt.allowed\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">UPDB</div>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Allow authentication via a traditional &quot;Username Password Database&quot;\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <div\n (click)=\"toggleUpdbAllowed()\"\n [ngClass]=\"{ on: formData.primary.updb.allowed }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.primary.updb.allowed\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.primary.updb.allowed\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n *ngIf=\"formData.primary.cert.allowed\"\n [title]=\"'Cert Options'\"\n [layout]=\"'row'\"\n >\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">Allow Expired Certificates</div>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Allow expired client certificates to authenticate\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <div\n (click)=\"toggleAllowExpiredCerts()\"\n [ngClass]=\"{ on: formData.primary.cert.allowExpiredCerts }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.primary.cert.allowExpiredCerts\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.primary.cert.allowExpiredCerts\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n *ngIf=\"formData.primary.extJwt.allowed\"\n [title]=\"'Ext JWT Options'\"\n [layout]=\"'column'\"\n >\n <div class=\"form-field-label-container allowed-signers-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Allowed JWT Signers</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Choose which External JWT Signers may be used for authentication\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <lib-tag-selector\n [(selectedNamedAttributes)]=\"allowedJwtSignerAttributes\"\n [availableNamedAttributes]=\"svc.jwtSignerNamedAttributes\"\n [placeholder]=\"'Select which External JWT Signers to allow'\"\n (selectedNamedAttributesChange)=\"allowedJwtSignersChanged($event)\"\n ></lib-tag-selector>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n *ngIf=\"formData.primary.updb.allowed\"\n [title]=\"'UPDB Options'\"\n [layout]=\"'column'\"\n >\n <div class=\"form-field-row updb-input-options\">\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Minimum Length</span>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter a numeric value\" type=\"number\" [(ngModel)]=\"formData.primary.updb.minPasswordLength\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Max Attempts</span>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter a numeric value\" type=\"number\" [(ngModel)]=\"formData.primary.updb.maxAttempts\"/>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">Lockout Duration <div class=\"form-sub-text\">(min)</div></span>\n </div>\n <input class=\"form-field-input\" placeholder=\"Enter time in min\" type=\"number\" [(ngModel)]=\"formData.primary.updb.lockoutDurationMinutes\"/>\n </div>\n </div>\n <div class=\"form-field-row\">\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">Mixed Case</div>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Require upper and lower case charachters\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <div\n (click)=\"toggleUpdbMixed()\"\n [ngClass]=\"{ on: formData.primary.updb.requireMixedCase }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.primary.updb.requireMixedCase\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.primary.updb.requireMixedCase\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">Numeric</div>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Require numerical charachters 0-9\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <div\n (click)=\"toggleUpdbNumeric()\"\n [ngClass]=\"{ on: formData.primary.updb.requireNumericChar }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.primary.updb.requireNumericChar\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.primary.updb.requireNumericChar\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">Special</div>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Require special (non-alpha numeric) charachters. ie. !%$@*\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <div\n (click)=\"toggleUpdbSpecial()\"\n [ngClass]=\"{ on: formData.primary.updb.requireSpecialChar }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.primary.updb.requireSpecialChar\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.primary.updb.requireSpecialChar\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </div>\n </lib-form-field-container>\n <lib-form-field-toggle [(toggleOn)]=\"showMore\" (toggleOnChange)=\"showMoreChanged($event)\" style=\"margin: 0px 10px\"></lib-form-field-toggle>\n <div [hidden]=\"!showMore\" class=\"form-group-column\">\n <lib-form-field-container\n [title]=\"'Custom Tags'\"\n [label]=\"'OPTIONAL'\"\n class=\"form-field-advanced\"\n >\n <lib-custom-tags [(tags)]=\"formData.tags\"></lib-custom-tags>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column two-fifths\">\n <lib-form-field-container\n [title]=\"'Secondary Authentication'\"\n [label]=\"'OPTIONAL'\"\n [layout]=\"'column'\"\n [contentStyle]=\"'z-index: 1000001'\"\n >\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">TOTP MFA</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Require authenticating clients to have TOTP MFA enabled (Time-based, One-Time Password)\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <div class=\"config-item\">\n <div class=\"config-container toggle-container\">\n <div class=\"form-field-title-container\">\n <div class=\"config-container-label\">Require TOTP</div>\n </div>\n <div\n (click)=\"toggleRequireTotp()\"\n [ngClass]=\"{ on: formData.secondary.requireTotp }\"\n class=\"toggle\"\n >\n <span [hidden]=\"!formData.secondary.requireTotp\" class=\"on-label\">YES</span>\n <span [hidden]=\"formData.secondary.requireTotp\" class=\"off-label\">NO</span>\n <div class=\"switch\"></div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"form-field-label-container\">\n <div class=\"form-field-title-container\">\n <span class=\"form-field-title\">JWT Signer</span>\n <div\n class=\"form-field-info infoicon\"\n matTooltip=\"Require every client request to have a JWT from the specified External JTW Signer in the HTTP Authentication header\"\n matTooltipPosition=\"below\"\n ></div>\n </div>\n <p-dropdown\n placeholder=\"Select JWT Signer...\"\n optionLabel=\"name\"\n optionValue=\"id\"\n filterBy=\"name\"\n [options]=\"svc.jwtSigners\"\n [filter]=\"true\"\n [showClear]=\"true\"\n (change)=\"secondaryJwtSignerChanged($event)\"\n [(ngModel)]=\"formData.secondary.requireExtJwtSigner\"\n >\n <ng-template pTemplate=\"filter\" let-options=\"options\">\n <div class=\"dropdown-filter-container\">\n <div class=\"p-inputgroup\" (click)=\"$event.stopPropagation()\">\n <span class=\"p-inputgroup-addon\"><i class=\"pi pi-search\"></i></span>\n <input\n type=\"text\"\n pInputText\n placeholder=\"Filter\"\n (keyup)=\"jwtSignersFilterChangedDebounced($event)\" />\n </div>\n <button pButton\n icon=\"pi pi-times\"\n [ngClass]=\"{'configs-loading': svc.jwtSignersLoading}\"\n (click)=\"clearJwtSignerFilter($event)\"\n severity=\"secondary\">\n </button>\n <div class=\"spinner\" *ngIf=\"svc.jwtSignersLoading\"></div>\n </div>\n </ng-template>\n </p-dropdown>\n </div>\n </lib-form-field-container>\n <lib-form-field-container\n [title]=\"'API Calls'\"\n [headerActions]=\"apiOptions\"\n (actionRequested)=\"apiActionRequested($event)\"\n [class]=\"'api-data-no-wrap'\"\n >\n <div class=\"form-row\">\n <input class=\"form-field-input\" [value]=\"apiCallURL\"/>\n <div class=\"icon-copy copy\" (click)=\"copyToClipboard(apiCallURL)\"></div>\n </div>\n <lib-json-view *ngIf=\"formData\" [(data)]=\"apiData\" [readOnly]=\"true\" [showCopy]=\"true\"></lib-json-view>\n </lib-form-field-container>\n </div>\n </div>\n <div class=\"form-group-column\" *ngIf=\"formView === 'raw'\">\n <lib-json-view *ngIf=\"formData\" [(data)]=\"formData\"></lib-json-view>\n </div>\n </div>\n</div>\n<lib-loading-indicator *ngIf=\"isLoading\" [isLoading]=\"isLoading\"></lib-loading-indicator>\n", styles: ["@charset \"UTF-8\";.form-group-column.three-fifths{min-width:500px}.jwt-signer-form-container{display:flex;flex-direction:column;height:100%;width:100%;align-items:center;gap:var(--gapXL)}.jwt-signer-form-container .select-file-button{padding-left:var(--paddingMedium);padding-right:var(--paddingMedium);height:25px;width:-moz-fit-content;width:fit-content;white-space:nowrap;display:flex;align-items:center;justify-content:center;font-weight:600;font-size:14px;background:var(--primary);border-style:solid;border-width:1px;border-color:var(--stroke);color:var(--white);cursor:pointer;border-radius:var(--inputBorderRadius);gap:var(--marginMedium);margin-top:-5px}.jwt-signer-form-container .select-file-button:hover{filter:brightness(.8)}.jwt-signer-form-container .select-file-button:active{filter:grayscale(1);transform:translateY(1px)}.jwt-signer-form-container .select-file-button .spinner{display:inline-block;width:8px;height:8px;border-radius:50%;background:transparent;border-top:2px solid white;border-right:2px solid white;border-bottom:2px solid transparent;border-left:2px solid transparent;animation:loading .5s infinite linear}.jwt-signer-form-container .select-file-label-container{gap:var(--marginMedium)}.jwt-signer-form-container .updb-input-options{margin-top:var(--marginSmall);background-color:var(--formGroup);padding:var(--paddingMedium);border-radius:var(--inputBorderRadius)}.jwt-signer-form-container .updb-input-options .form-field-title{color:var(--offWhite)}::ng-deep .jwt-signer-form-container select:disabled,::ng-deep .jwt-signer-form-container input:disabled{opacity:.75!important;cursor:text;background-color:var(--stroke)!important}::ng-deep .api-data-no-wrap .jse-text-mode{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller{width:100%}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller .cm-content{width:100%;overflow:auto}::ng-deep .api-data-no-wrap .jse-text-mode .cm-editor .cm-scroller .cm-content .\\37cr{white-space:nowrap}.radio-group-container{display:flex;gap:var(--marginLarge)}.radio-group-container:focus .radio-button-container .radio-button-circle{border-color:var(--primaryColor)}.radio-group-container .radio-button-container{display:flex;flex-direction:row;align-items:center;background-color:var(--formGroup);border-radius:var(--inputBorderRadius);width:100%;padding-left:var(--paddingMedium);padding-right:var(--paddingMedium);padding-top:var(--paddingLarge);padding-bottom:var(--paddingLarge);cursor:pointer;gap:var(--marginMedium)}.radio-group-container .radio-button-container .radio-button-circle{display:flex;width:21px;height:21px;border-radius:21px;border-width:2px;border-style:solid;border-color:var(--offWhite);align-items:center;justify-content:center;background-color:var(--offWhite)}.radio-group-container .radio-button-container .radio-button-circle .radio-button-inner-circle{display:none;width:15px;height:15px;border-radius:15px;align-items:center;justify-content:center;background-color:var(--primaryColor)}.radio-group-container .radio-button-container.selected .radio-button-circle .radio-button-inner-circle{display:flex}.radio-group-container .radio-button-container:active .radio-button-circle .radio-button-inner-circle{display:flex;background-color:var(--menu)}.radio-group-container .radio-button-container .radio-button-label{color:var(--offWhite);font-size:14px;font-weight:600}.allowed-signers-container{background-color:var(--formGroup);padding:var(--paddingMedium);border-radius:var(--inputBorderRadius)}.allowed-signers-container .form-field-title{color:var(--offWhite)}\n"] }]
22072
+ }], ctorParameters: function () { return [{ type: AuthPolicyFormService }, { type: SchemaService }, { type: GrowlerService }, { type: undefined, decorators: [{
22073
+ type: Inject,
22074
+ args: [SHAREDZ_EXTENSION]
22075
+ }] }, { type: SettingsService, decorators: [{
22076
+ type: Inject,
22077
+ args: [SETTINGS_SERVICE]
22078
+ }] }, { type: ZitiDataService, decorators: [{
22079
+ type: Inject,
22080
+ args: [ZITI_DATA_SERVICE]
22081
+ }] }, { type: i4.Router }, { type: i4.ActivatedRoute }, { type: i1$4.Location }, { type: ValidationService }]; }, propDecorators: { formData: [{
22082
+ type: Input
22083
+ }], errors: [{
22084
+ type: Input
22085
+ }], close: [{
22086
+ type: Output
22087
+ }], filterInput: [{
22088
+ type: ViewChild,
22089
+ args: ['fileSelect']
22090
+ }] } });
22091
+
22092
+ /*
22093
+ Copyright NetFoundry Inc.
22094
+
22095
+ Licensed under the Apache License, Version 2.0 (the "License");
22096
+ you may not use this file except in compliance with the License.
22097
+ You may obtain a copy of the License at
22098
+
22099
+ https://www.apache.org/licenses/LICENSE-2.0
22100
+
22101
+ Unless required by applicable law or agreed to in writing, software
22102
+ distributed under the License is distributed on an "AS IS" BASIS,
22103
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22104
+ See the License for the specific language governing permissions and
22105
+ limitations under the License.
22106
+ */
22107
+ function playerFactory() {
22108
+ return import(/* webpackChunkName: 'lottie-web' */ 'lottie-web');
22109
+ }
22110
+ class OpenZitiConsoleLibModule {
22111
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OpenZitiConsoleLibModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
22112
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.2.12", ngImport: i0, type: OpenZitiConsoleLibModule, declarations: [ZacWrapperComponent,
22113
+ SafePipe,
22114
+ ExtendableComponent,
22115
+ StringInputComponent,
22116
+ NumberInputComponent,
22117
+ BooleanToggleInputComponent,
22118
+ ObjectComponent,
22119
+ SelectorInputComponent,
22120
+ TextListInputComponent,
22121
+ CheckboxListInputComponent,
22122
+ ProtocolAddressPortInputComponent,
22123
+ SideToolbarComponent,
22124
+ SideNavbarComponent,
22125
+ SideBannerComponent,
22126
+ PasswordInputComponent,
22127
+ TerminatorFormComponent,
22128
+ ConfigurationsPageComponent,
22129
+ ListPageHeaderComponent,
22130
+ FilterBarComponent,
22131
+ ListPageFormComponent,
22132
+ IdentitiesPageComponent,
22133
+ EdgeRoutersPageComponent,
22134
+ DataTableComponent,
22135
+ TableCellSelectComponent,
22136
+ TableColumnSelectComponent,
22137
+ TableCellMenuComponent,
22138
+ TableColumnMenuComponent,
22139
+ TableColumnDefaultComponent,
22140
+ TableColumnFilterComponent,
22141
+ IdentityFormComponent,
22142
+ EdgeRouterFormComponent,
22143
+ HiddenColumnsBarComponent,
22144
+ FilterBarComponent,
22145
+ ExtendableComponent,
22146
+ ConfirmComponent,
22147
+ NoItemsComponent,
22148
+ SideModalComponent,
22149
+ FormHeaderComponent,
22150
+ FormFieldContainerComponent,
22151
+ PreviewListComponent,
22152
+ LoadingIndicatorComponent,
22153
+ FormFieldToggleComponent,
22154
+ JsonViewComponent,
22155
+ TagSelectorComponent,
22156
+ QrCodeComponent,
22157
+ TableCellTokenComponent,
22158
+ OSTooltipComponent,
22159
+ SDKTooltipComponent,
22160
+ OverridesComponent,
22161
+ ResetEnrollmentComponent,
22162
+ IdentityServicePathComponent,
22163
+ NetworkVisualizerComponent,
22164
+ CustomTagsComponent,
22165
+ ServicesPageComponent,
22166
+ ServiceFormComponent,
22167
+ PortRangesComponent,
22168
+ ForwardingConfigComponent,
22169
+ CardListComponent,
22170
+ SimpleServiceComponent,
22171
+ CardComponent,
22172
+ CreationSummaryDialogComponent,
22173
+ ConfigEditorComponent,
22174
+ ServicePoliciesPageComponent,
22175
+ ServicePolicyFormComponent,
22176
+ EdgeRouterPoliciesPageComponent,
22177
+ EdgeRouterPolicyFormComponent,
22178
+ MultiActionButtonComponent,
22179
+ TableCellNameComponent,
22180
+ ServiceEdgeRouterPoliciesPageComponent,
22181
+ ServiceEdgeRouterPolicyFormComponent,
22182
+ TerminatorsPageComponent,
22183
+ TerminatorFormComponent,
22184
+ ConfigurationFormComponent,
22185
+ JwtSignersPageComponent,
22186
+ JwtSignerFormComponent,
22187
+ AuthPoliciesPageComponent,
22188
+ AuthPolicyFormComponent], imports: [CommonModule,
22189
+ FormsModule,
22190
+ MatDialogModule,
22191
+ MatRadioModule,
22192
+ HttpClientModule,
22193
+ ZacRoutingModule,
22194
+ ChipsModule,
22195
+ CalendarModule,
22196
+ AgGridModule,
22197
+ QRCodeModule,
22198
+ ClickOutsideModule,
22199
+ NgJsonEditorModule,
22200
+ MatTooltipModule,
22201
+ MatAutocompleteModule, i1$2.LottieModule, DropdownModule], exports: [ZacWrapperComponent,
22202
+ ExtendableComponent,
22203
+ SideToolbarComponent,
22204
+ SideNavbarComponent,
22205
+ SideBannerComponent,
22206
+ StringInputComponent,
22207
+ SelectorInputComponent,
22208
+ PasswordInputComponent,
22209
+ NumberInputComponent,
22210
+ BooleanToggleInputComponent,
22211
+ ObjectComponent,
22212
+ TextListInputComponent,
22213
+ IdentityServicePathComponent,
22214
+ NetworkVisualizerComponent,
22215
+ CheckboxListInputComponent,
22216
+ ProtocolAddressPortInputComponent,
22217
+ ConfigurationsPageComponent,
22218
+ ConfigurationFormComponent,
22219
+ EdgeRouterFormComponent,
22220
+ IdentitiesPageComponent,
22221
+ EdgeRoutersPageComponent,
22222
+ ServicesPageComponent,
22223
+ ZacRoutingModule,
22224
+ SideModalComponent,
22225
+ IdentityFormComponent,
22226
+ LoadingIndicatorComponent,
22227
+ GrowlerModule,
22228
+ FormFieldContainerComponent,
22229
+ FormFieldToggleComponent,
22230
+ ServiceFormComponent,
22231
+ ServicePoliciesPageComponent,
22232
+ ServicePolicyFormComponent,
22233
+ EdgeRouterPoliciesPageComponent,
22234
+ TerminatorsPageComponent,
22235
+ TerminatorFormComponent,
22236
+ JwtSignersPageComponent,
22237
+ JwtSignerFormComponent,
22238
+ AuthPoliciesPageComponent,
22239
+ AuthPolicyFormComponent] }); }
22240
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OpenZitiConsoleLibModule, providers: [
22241
+ { provide: SHAREDZ_EXTENSION, useClass: ExtensionsNoopService },
22242
+ { provide: ZITI_NAVIGATOR, useValue: {} },
22243
+ {
22244
+ provide: APP_INITIALIZER,
22245
+ useFactory: onAppInit,
22246
+ deps: [Injector],
22247
+ multi: true
22248
+ },
22249
+ ], imports: [CommonModule,
22250
+ FormsModule,
22251
+ MatDialogModule,
22252
+ MatRadioModule,
22253
+ HttpClientModule,
22254
+ ZacRoutingModule,
22255
+ ChipsModule,
22256
+ CalendarModule,
22257
+ AgGridModule,
22258
+ QRCodeModule,
22259
+ ClickOutsideModule,
22260
+ NgJsonEditorModule,
22261
+ MatTooltipModule,
22262
+ MatAutocompleteModule,
22263
+ LottieModule.forRoot({ player: playerFactory }),
22264
+ DropdownModule, ZacRoutingModule,
22265
+ GrowlerModule] }); }
22266
+ }
22267
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: OpenZitiConsoleLibModule, decorators: [{
22268
+ type: NgModule,
22269
+ args: [{
22270
+ declarations: [
22271
+ ZacWrapperComponent,
22272
+ SafePipe,
22273
+ ExtendableComponent,
22274
+ StringInputComponent,
22275
+ NumberInputComponent,
22276
+ BooleanToggleInputComponent,
22277
+ ObjectComponent,
21424
22278
  SelectorInputComponent,
21425
22279
  TextListInputComponent,
21426
22280
  CheckboxListInputComponent,
@@ -21488,12 +22342,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
21488
22342
  TerminatorFormComponent,
21489
22343
  ConfigurationFormComponent,
21490
22344
  JwtSignersPageComponent,
21491
- JwtSignerFormComponent
22345
+ JwtSignerFormComponent,
22346
+ AuthPoliciesPageComponent,
22347
+ AuthPolicyFormComponent
21492
22348
  ],
21493
22349
  imports: [
21494
22350
  CommonModule,
21495
22351
  FormsModule,
21496
22352
  MatDialogModule,
22353
+ MatRadioModule,
21497
22354
  HttpClientModule,
21498
22355
  ZacRoutingModule,
21499
22356
  ChipsModule,
@@ -21544,7 +22401,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
21544
22401
  TerminatorsPageComponent,
21545
22402
  TerminatorFormComponent,
21546
22403
  JwtSignersPageComponent,
21547
- JwtSignerFormComponent
22404
+ JwtSignerFormComponent,
22405
+ AuthPoliciesPageComponent,
22406
+ AuthPolicyFormComponent
21548
22407
  ],
21549
22408
  providers: [
21550
22409
  { provide: SHAREDZ_EXTENSION, useClass: ExtensionsNoopService },
@@ -22598,6 +23457,23 @@ class NodeDataService extends ZitiDataService {
22598
23457
  return results;
22599
23458
  })));
22600
23459
  }
23460
+ put(type, model, id, chained = false) {
23461
+ let clientSub;
23462
+ const nodeServerURL = window.location.origin;
23463
+ const serviceUrl = nodeServerURL + '/api/dataSave';
23464
+ const body = { paging: this.DEFAULT_PAGING, type: type, save: model, id: id, chained: chained };
23465
+ return firstValueFrom(this.httpClient.post(serviceUrl, body, {}).pipe(catchError((err) => {
23466
+ const error = "Server Not Accessible";
23467
+ if (err.code !== "ECONNREFUSED")
23468
+ throw (err);
23469
+ throw ({ error: error });
23470
+ }), map((results) => {
23471
+ if (!isEmpty(results.error)) {
23472
+ throw ({ error: results.error });
23473
+ }
23474
+ return results;
23475
+ })));
23476
+ }
22601
23477
  patch(type, model, id, chained = false) {
22602
23478
  let clientSub;
22603
23479
  const nodeServerURL = window.location.origin;
@@ -22901,6 +23777,21 @@ class ZitiControllerDataService extends ZitiDataService {
22901
23777
  return result;
22902
23778
  })));
22903
23779
  }
23780
+ put(type, model, id, chained = false) {
23781
+ const apiVersions = this.settingsService.apiVersions || {};
23782
+ const prefix = apiVersions["edge-management"]?.v1?.path || '/edge/management/v1';
23783
+ const url = this.settingsService.settings.selectedEdgeController;
23784
+ const serviceUrl = url + prefix + "/" + type + '/' + id;
23785
+ this.httpClient.patch(serviceUrl, model, {});
23786
+ return firstValueFrom(this.httpClient.put(serviceUrl, model, {}).pipe(catchError((err) => {
23787
+ const error = "Server Not Accessible";
23788
+ if (err.code !== "ECONNREFUSED")
23789
+ throw (err);
23790
+ throw ({ error: error });
23791
+ }), map((result) => {
23792
+ return result;
23793
+ })));
23794
+ }
22904
23795
  patch(type, model, id, chained = false) {
22905
23796
  const apiVersions = this.settingsService.apiVersions || {};
22906
23797
  const prefix = apiVersions["edge-management"]?.v1?.path || '/edge/management/v1';
@@ -23140,5 +24031,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
23140
24031
  * Generated bundle index. Do not edit.
23141
24032
  */
23142
24033
 
23143
- export { BooleanToggleInputComponent, COMPONENTS, CardListComponent, CheckboxListInputComponent, ConfigurationFormComponent, ConfigurationService, ConfigurationsPageComponent, CsvDownloadService, DEACTIVATE_GUARD, DataTableFilterService, DeactivateGuardService, EDGE_ROUTER_EXTENSION_SERVICE, EDGE_ROUTER_POLICY_EXTENSION_SERVICE, EdgeRouter, EdgeRouterFormComponent, EdgeRouterFormService, EdgeRouterPoliciesPageComponent, EdgeRouterPoliciesPageService, EdgeRouterPolicyFormComponent, EdgeRouterPolicyFormService, EdgeRoutersPageComponent, EdgeRoutersPageService, Entity, ExtendableComponent, ExtensionsNoopService, FormFieldContainerComponent, FormFieldToggleComponent, FormHeaderComponent, GrowlerComponent, GrowlerModel, GrowlerModule, GrowlerService, IDENTITY_EXTENSION_SERVICE, IdentitiesPageComponent, IdentitiesPageService, Identity$1 as Identity, IdentityFormComponent, IdentityFormService, IdentityServicePathComponent, JwtSignerFormComponent, JwtSignerFormService, JwtSignersPageComponent, JwtSignersPageService, KEY_CODES, ListPageComponent, ListPageServiceClass, LoadingIndicatorComponent, LoggerService, LoginServiceClass, NetworkVisualizerComponent, NodeDataService, NodeWrapperService, NoopLoginService, NoopTabInterceptorService, NumberInputComponent, ObjectComponent, OpenZitiConsoleLibModule, PasswordInputComponent, ProjectableForm, ProtocolAddressPortInputComponent, ResetEnrollmentService, SERVICE_EDGE_ROUTER_POLICY_EXTENSION_SERVICE, SERVICE_EXTENSION_SERVICE, SERVICE_POLICY_EXTENSION_SERVICE, SETTINGS_SERVICE, SHAREDZ_EXTENSION, SelectorInputComponent, ServiceEdgeRouterPoliciesPageComponent, ServiceEdgeRouterPoliciesPageService, ServiceEdgeRouterPolicyFormComponent, ServiceEdgeRouterPolicyFormService, ServiceFormComponent, ServiceFormService, ServicePoliciesPageComponent, ServicePoliciesPageService, ServicePolicyFormComponent, ServicePolicyFormService, ServicesPageComponent, ServicesPageService, SettingsService, SettingsServiceClass, SideBannerComponent, SideModalComponent, SideNavbarComponent, SideToolbarComponent, SimpleServiceComponent, StringInputComponent, TabNameService, TerminatorFormComponent, TerminatorFormService, TerminatorsPageComponent, TerminatorsPageService, TextListInputComponent, VERSION, VisualizerServiceClass, ZAC_LOGIN_SERVICE, ZAC_WRAPPER_SERVICE, ZITI_DATA_SERVICE, ZITI_DOMAIN_CONTROLLER, ZITI_NAVIGATOR, ZITI_TAB_OVERRIDES, ZITI_URLS, ZacRoutingModule, ZacWrapperComponent, ZacWrapperService, ZacWrapperServiceClass, ZitiControllerDataService, ZitiDataService, playerFactory };
24034
+ export { AuthPoliciesPageComponent, AuthPoliciesPageService, AuthPolicyFormComponent, AuthPolicyFormService, BooleanToggleInputComponent, COMPONENTS, CardListComponent, CheckboxListInputComponent, ConfigurationFormComponent, ConfigurationService, ConfigurationsPageComponent, CsvDownloadService, DEACTIVATE_GUARD, DataTableFilterService, DeactivateGuardService, EDGE_ROUTER_EXTENSION_SERVICE, EDGE_ROUTER_POLICY_EXTENSION_SERVICE, EdgeRouter, EdgeRouterFormComponent, EdgeRouterFormService, EdgeRouterPoliciesPageComponent, EdgeRouterPoliciesPageService, EdgeRouterPolicyFormComponent, EdgeRouterPolicyFormService, EdgeRoutersPageComponent, EdgeRoutersPageService, Entity, ExtendableComponent, ExtensionsNoopService, FormFieldContainerComponent, FormFieldToggleComponent, FormHeaderComponent, GrowlerComponent, GrowlerModel, GrowlerModule, GrowlerService, IDENTITY_EXTENSION_SERVICE, IdentitiesPageComponent, IdentitiesPageService, Identity$1 as Identity, IdentityFormComponent, IdentityFormService, IdentityServicePathComponent, JwtSignerFormComponent, JwtSignerFormService, JwtSignersPageComponent, JwtSignersPageService, KEY_CODES, ListPageComponent, ListPageServiceClass, LoadingIndicatorComponent, LoggerService, LoginServiceClass, NetworkVisualizerComponent, NodeDataService, NodeWrapperService, NoopLoginService, NoopTabInterceptorService, NumberInputComponent, ObjectComponent, OpenZitiConsoleLibModule, PasswordInputComponent, ProjectableForm, ProtocolAddressPortInputComponent, ResetEnrollmentService, SERVICE_EDGE_ROUTER_POLICY_EXTENSION_SERVICE, SERVICE_EXTENSION_SERVICE, SERVICE_POLICY_EXTENSION_SERVICE, SETTINGS_SERVICE, SHAREDZ_EXTENSION, SelectorInputComponent, ServiceEdgeRouterPoliciesPageComponent, ServiceEdgeRouterPoliciesPageService, ServiceEdgeRouterPolicyFormComponent, ServiceEdgeRouterPolicyFormService, ServiceFormComponent, ServiceFormService, ServicePoliciesPageComponent, ServicePoliciesPageService, ServicePolicyFormComponent, ServicePolicyFormService, ServicesPageComponent, ServicesPageService, SettingsService, SettingsServiceClass, SideBannerComponent, SideModalComponent, SideNavbarComponent, SideToolbarComponent, SimpleServiceComponent, StringInputComponent, TabNameService, TerminatorFormComponent, TerminatorFormService, TerminatorsPageComponent, TerminatorsPageService, TextListInputComponent, VERSION, VisualizerServiceClass, ZAC_LOGIN_SERVICE, ZAC_WRAPPER_SERVICE, ZITI_DATA_SERVICE, ZITI_DOMAIN_CONTROLLER, ZITI_NAVIGATOR, ZITI_TAB_OVERRIDES, ZITI_URLS, ZacRoutingModule, ZacWrapperComponent, ZacWrapperService, ZacWrapperServiceClass, ZitiControllerDataService, ZitiDataService, playerFactory };
23144
24035
  //# sourceMappingURL=openziti-ziti-console-lib.mjs.map