@posiwise/admin-module 0.0.204 → 0.0.205

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.
@@ -68,13 +68,13 @@ import * as i15$1 from '@angular/cdk/drag-drop';
68
68
  import { moveItemInArray } from '@angular/cdk/drag-drop';
69
69
  import groupBy from 'lodash/groupBy';
70
70
  import { forkJoin, map, Subject, takeUntil, of } from 'rxjs';
71
+ import { finalize, debounceTime, switchMap, filter, take, concatMap, map as map$1, catchError } from 'rxjs/operators';
71
72
  import * as i3$3 from '@angular/platform-browser';
72
73
  import * as i4$3 from 'primeng/tabs';
73
74
  import uniqBy from 'lodash/uniqBy';
74
75
  import moment from 'moment';
75
76
  import { StatusCodes } from 'http-status-codes';
76
77
  import { HttpParams } from '@angular/common/http';
77
- import { debounceTime, switchMap, filter, take, concatMap, map as map$1, catchError } from 'rxjs/operators';
78
78
 
79
79
  class GlobalConfigDetailsComponent extends AppBaseComponent {
80
80
  constructor(adminService, injector, cdr) {
@@ -2747,11 +2747,11 @@ class FeatureFlagDetailsComponent extends AppBaseComponent {
2747
2747
  }
2748
2748
  loadSupportedOptions() {
2749
2749
  this.adminService.getSupportedFeatureFlagOptions().subscribe(response => {
2750
- this.flagTypeOptions = (response.flag_types || []).map(option => ({
2750
+ this.flagTypeOptions = (response.flag_types ?? []).map(option => ({
2751
2751
  label: option,
2752
2752
  value: option
2753
2753
  }));
2754
- this.statusOptions = (response.statuses || []).map(option => ({
2754
+ this.statusOptions = (response.statuses ?? []).map(option => ({
2755
2755
  label: option,
2756
2756
  value: option
2757
2757
  }));
@@ -2761,7 +2761,7 @@ class FeatureFlagDetailsComponent extends AppBaseComponent {
2761
2761
  this.adminService
2762
2762
  .getUsers({}, { subscription_id: this.subscriptionId })
2763
2763
  .subscribe(response => {
2764
- this.allUsers = response.users || [];
2764
+ this.allUsers = response.users ?? [];
2765
2765
  this.allUsers.forEach(user => {
2766
2766
  const firstName = user.first_name ?? '';
2767
2767
  const lastName = user.last_name ?? '';
@@ -2770,7 +2770,7 @@ class FeatureFlagDetailsComponent extends AppBaseComponent {
2770
2770
  });
2771
2771
  }
2772
2772
  searchOwners(event) {
2773
- const query = event.query?.toLowerCase() || '';
2773
+ const query = event.query?.toLowerCase() ?? '';
2774
2774
  this.filteredUsers = !query
2775
2775
  ? [...this.allUsers]
2776
2776
  : this.allUsers.filter(user => user.displayName.toLowerCase().includes(query));
@@ -2788,7 +2788,7 @@ class FeatureFlagDetailsComponent extends AppBaseComponent {
2788
2788
  description: response.description,
2789
2789
  flag_type: response.flag_type,
2790
2790
  status: response.status,
2791
- owner: this.allUsers.find(user => user.email === response.owner) || response.owner,
2791
+ owner: this.allUsers.find(user => user.email === response.owner) ?? response.owner,
2792
2792
  expires_at: response.expires_at ? new Date(response.expires_at) : null
2793
2793
  });
2794
2794
  },
@@ -2828,17 +2828,18 @@ class FeatureFlagDetailsComponent extends AppBaseComponent {
2828
2828
  this.router.navigate([this.routers.featureFlagsConfig]);
2829
2829
  }
2830
2830
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FeatureFlagDetailsComponent, deps: [{ token: i0.Injector }, { token: i1.AdminService }], target: i0.ɵɵFactoryTarget.Component }); }
2831
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FeatureFlagDetailsComponent, isStandalone: false, selector: "pw-feature-flag-details", usesInheritance: true, ngImport: i0, template: "<div class=\"container-fluid pw-tab\">\n <div class=\"dashboard\">\n <div class=\"dashboard-body\">\n <div class=\"me-auto col-xs-6 mt-4\">\n <a routerLink=\"/admin/feature-flags/list\" class=\"previous\"><i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i></a>\n <h3 class=\"mt-3\">{{ id ? 'Edit' : 'Add New' }} Feature Flag</h3>\n </div>\n\n @if (isLoading) {\n <div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"></p-progressSpinner>\n </div>\n }\n\n <div class=\"p-2 mt-3\">\n @if (!isLoading) {\n <form (ngSubmit)=\"onSubmit()\" [formGroup]=\"form\">\n <div class=\"row\">\n <pw-input-container class=\"col-lg-6\" label=\"Key\" name=\"key\" controlId=\"feature-flag-key\" errorMsg=\"Key is required\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.Key' | transloco\">\n <input type=\"text\" id=\"feature-flag-key\" formControlName=\"key\" class=\"form-control\" [ngClass]=\"{ 'is-invalid': submitted && f['key'].errors }\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-6\" label=\"Name\" name=\"name\" controlId=\"feature-flag-name\" errorMsg=\"Name is required\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.Name' | transloco\">\n <input type=\"text\" id=\"feature-flag-name\" formControlName=\"name\" class=\"form-control\" [ngClass]=\"{ 'is-invalid': submitted && f['name'].errors }\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-12\" label=\"Description\" name=\"description\" controlId=\"feature-flag-description\">\n <textarea id=\"feature-flag-description\" formControlName=\"description\" rows=\"4\" class=\"form-control\"></textarea>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-3\" label=\"Type\" name=\"flag_type\" controlId=\"feature-flag-type\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"flagTypeOptions\" [attr.aria-labelledby]=\"'feature-flag-type-label'\" formControlName=\"flag_type\" class=\"dropdown-bg-transparent\" placeholder=\"Select type\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-3\" label=\"Status\" name=\"status\" controlId=\"feature-flag-status\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"statusOptions\" [attr.aria-labelledby]=\"'feature-flag-status-label'\" formControlName=\"status\" class=\"dropdown-bg-transparent\" placeholder=\"Select status\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-3\" label=\"Owner\" name=\"owner\" controlId=\"feature-flag-owner\" [useAriaLabelledbyOnly]=\"true\">\n <p-autoComplete\n [suggestions]=\"filteredUsers\"\n [attr.aria-labelledby]=\"'feature-flag-owner-label'\"\n formControlName=\"owner\"\n dataKey=\"id\"\n field=\"displayName\"\n [dropdown]=\"true\"\n (completeMethod)=\"searchOwners($event)\"\n styleClass=\"w-100\"\n placeholder=\"Search owner\"\n [multiple]=\"false\"\n autocomplete=\"off\">\n </p-autoComplete>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-3\" label=\"Expires At\" name=\"expires_at\" controlId=\"feature-flag-expires_at\" [useAriaLabelledbyOnly]=\"true\">\n <p-calendar inputId=\"feature-flag-expires_at\" formControlName=\"expires_at\" [showIcon]=\"true\" [showTime]=\"true\" [appendTo]=\"'body'\" dateFormat=\"dd-M-yy\"></p-calendar>\n </pw-input-container>\n </div>\n\n <div class=\"row\">\n <div class=\"col-12 mt-4\">\n <div class=\"mb-3 text-end\">\n <button type=\"button\" class=\"btn btn-outline-default me-2\" (click)=\"onCancel()\">{{ 'Button.Cancel' | transloco }}</button>\n <button class=\"btn btn-primary\" [buttonBusy]=\"buttonBusy\">{{ 'Button.Save' | transloco }}</button>\n </div>\n </div>\n </div>\n </form>\n }\n </div>\n </div>\n </div>\n</div>", dependencies: [{ kind: "component", type: i5.AutoComplete, selector: "p-autoComplete, p-autocomplete, p-auto-complete", inputs: ["minLength", "minQueryLength", "delay", "panelStyle", "styleClass", "panelStyleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "readonly", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "autoHighlight", "forceSelection", "type", "autoZIndex", "baseZIndex", "ariaLabel", "dropdownAriaLabel", "ariaLabelledBy", "dropdownIcon", "unique", "group", "completeOnFocus", "showClear", "dropdown", "showEmptyMessage", "dropdownMode", "multiple", "addOnTab", "tabindex", "dataKey", "emptyMessage", "showTransitionOptions", "hideTransitionOptions", "autofocus", "autocomplete", "optionGroupChildren", "optionGroupLabel", "overlayOptions", "suggestions", "optionLabel", "optionValue", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover", "typeahead", "addOnBlur", "separator", "appendTo", "motionOptions"], outputs: ["completeMethod", "onSelect", "onUnselect", "onAdd", "onFocus", "onBlur", "onDropdownClick", "onClear", "onInputKeydown", "onKeyUp", "onShow", "onHide", "onLazyLoad"] }, { kind: "component", type: i3.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "directive", type: i3$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.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: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: i4.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: i1$1.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "controlId", "useAriaLabelledbyOnly", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "directive", type: i9.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i10.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i6.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i6.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: i11.TranslocoPipe, name: "transloco" }] }); }
2831
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FeatureFlagDetailsComponent, isStandalone: false, selector: "pw-feature-flag-details", usesInheritance: true, ngImport: i0, template: "<div class=\"container-fluid pw-tab\">\n <div class=\"dashboard\">\n <div class=\"dashboard-body\">\n <div class=\"me-auto col-xs-6 mt-4\">\n <a routerLink=\"/admin/feature-flags/list\" class=\"previous\" aria-label=\"Back to feature flags list\">\n <i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i>\n </a>\n <h3 class=\"mt-3\">{{ id ? 'Edit' : 'Add New' }} Feature Flag</h3>\n </div>\n\n @if (isLoading) {\n <div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"></p-progressSpinner>\n </div>\n }\n\n <div class=\"p-2 mt-3\">\n @if (!isLoading) {\n <form (ngSubmit)=\"onSubmit()\" [formGroup]=\"form\">\n <div class=\"row\">\n <pw-input-container class=\"col-lg-6\" label=\"Key\" name=\"key\" controlId=\"feature-flag-key\" errorMsg=\"Key is required\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.Key' | transloco\">\n <input type=\"text\" id=\"feature-flag-key\" formControlName=\"key\" class=\"form-control\" [ngClass]=\"{ 'is-invalid': submitted && f['key'].errors }\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-6\" label=\"Name\" name=\"name\" controlId=\"feature-flag-name\" errorMsg=\"Name is required\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.Name' | transloco\">\n <input type=\"text\" id=\"feature-flag-name\" formControlName=\"name\" class=\"form-control\" [ngClass]=\"{ 'is-invalid': submitted && f['name'].errors }\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-12\" label=\"Description\" name=\"description\" controlId=\"feature-flag-description\">\n <textarea id=\"feature-flag-description\" formControlName=\"description\" rows=\"4\" class=\"form-control\"></textarea>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-3\" label=\"Type\" name=\"flag_type\" controlId=\"feature-flag-type\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"flagTypeOptions\" [attr.aria-labelledby]=\"'feature-flag-type-label'\" formControlName=\"flag_type\" class=\"dropdown-bg-transparent\" placeholder=\"Select type\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-3\" label=\"Status\" name=\"status\" controlId=\"feature-flag-status\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"statusOptions\" [attr.aria-labelledby]=\"'feature-flag-status-label'\" formControlName=\"status\" class=\"dropdown-bg-transparent\" placeholder=\"Select status\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-3\" label=\"Owner\" name=\"owner\" controlId=\"feature-flag-owner\" [useAriaLabelledbyOnly]=\"true\">\n <p-autoComplete\n [suggestions]=\"filteredUsers\"\n [attr.aria-labelledby]=\"'feature-flag-owner-label'\"\n formControlName=\"owner\"\n dataKey=\"id\"\n field=\"displayName\"\n [dropdown]=\"true\"\n (completeMethod)=\"searchOwners($event)\"\n styleClass=\"w-100\"\n placeholder=\"Search owner\"\n [multiple]=\"false\"\n autocomplete=\"off\">\n </p-autoComplete>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-3\" label=\"Expires At\" name=\"expires_at\" controlId=\"feature-flag-expires_at\" [useAriaLabelledbyOnly]=\"true\">\n <p-datepicker inputId=\"feature-flag-expires_at\" formControlName=\"expires_at\" [showIcon]=\"true\" [showTime]=\"true\" [appendTo]=\"'body'\" dateFormat=\"dd-M-yy\"></p-datepicker>\n </pw-input-container>\n </div>\n\n <div class=\"row\">\n <div class=\"col-12 mt-4\">\n <div class=\"mb-3 text-end\">\n <button type=\"button\" class=\"btn btn-outline-default me-2\" (click)=\"onCancel()\">{{ 'Button.Cancel' | transloco }}</button>\n <button class=\"btn btn-primary\" [buttonBusy]=\"buttonBusy\">{{ 'Button.Save' | transloco }}</button>\n </div>\n </div>\n </div>\n </form>\n }\n </div>\n </div>\n </div>\n</div>", dependencies: [{ kind: "component", type: i5.AutoComplete, selector: "p-autoComplete, p-autocomplete, p-auto-complete", inputs: ["minLength", "minQueryLength", "delay", "panelStyle", "styleClass", "panelStyleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "readonly", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "autoHighlight", "forceSelection", "type", "autoZIndex", "baseZIndex", "ariaLabel", "dropdownAriaLabel", "ariaLabelledBy", "dropdownIcon", "unique", "group", "completeOnFocus", "showClear", "dropdown", "showEmptyMessage", "dropdownMode", "multiple", "addOnTab", "tabindex", "dataKey", "emptyMessage", "showTransitionOptions", "hideTransitionOptions", "autofocus", "autocomplete", "optionGroupChildren", "optionGroupLabel", "overlayOptions", "suggestions", "optionLabel", "optionValue", "id", "searchMessage", "emptySelectionMessage", "selectionMessage", "autoOptionFocus", "selectOnFocus", "searchLocale", "optionDisabled", "focusOnHover", "typeahead", "addOnBlur", "separator", "appendTo", "motionOptions"], outputs: ["completeMethod", "onSelect", "onUnselect", "onAdd", "onFocus", "onBlur", "onDropdownClick", "onClear", "onInputKeydown", "onKeyUp", "onShow", "onHide", "onLazyLoad"] }, { kind: "component", type: i3.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i8.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "styleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "readonlyInput", "shortYearCutoff", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "view", "defaultDate", "appendTo", "motionOptions"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "directive", type: i3$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.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: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: i4.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: i1$1.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "controlId", "useAriaLabelledbyOnly", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "directive", type: i9.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i10.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i6.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i6.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: i11.TranslocoPipe, name: "transloco" }] }); }
2832
2832
  }
2833
2833
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FeatureFlagDetailsComponent, decorators: [{
2834
2834
  type: Component,
2835
- args: [{ selector: 'pw-feature-flag-details', standalone: false, template: "<div class=\"container-fluid pw-tab\">\n <div class=\"dashboard\">\n <div class=\"dashboard-body\">\n <div class=\"me-auto col-xs-6 mt-4\">\n <a routerLink=\"/admin/feature-flags/list\" class=\"previous\"><i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i></a>\n <h3 class=\"mt-3\">{{ id ? 'Edit' : 'Add New' }} Feature Flag</h3>\n </div>\n\n @if (isLoading) {\n <div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"></p-progressSpinner>\n </div>\n }\n\n <div class=\"p-2 mt-3\">\n @if (!isLoading) {\n <form (ngSubmit)=\"onSubmit()\" [formGroup]=\"form\">\n <div class=\"row\">\n <pw-input-container class=\"col-lg-6\" label=\"Key\" name=\"key\" controlId=\"feature-flag-key\" errorMsg=\"Key is required\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.Key' | transloco\">\n <input type=\"text\" id=\"feature-flag-key\" formControlName=\"key\" class=\"form-control\" [ngClass]=\"{ 'is-invalid': submitted && f['key'].errors }\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-6\" label=\"Name\" name=\"name\" controlId=\"feature-flag-name\" errorMsg=\"Name is required\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.Name' | transloco\">\n <input type=\"text\" id=\"feature-flag-name\" formControlName=\"name\" class=\"form-control\" [ngClass]=\"{ 'is-invalid': submitted && f['name'].errors }\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-12\" label=\"Description\" name=\"description\" controlId=\"feature-flag-description\">\n <textarea id=\"feature-flag-description\" formControlName=\"description\" rows=\"4\" class=\"form-control\"></textarea>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-3\" label=\"Type\" name=\"flag_type\" controlId=\"feature-flag-type\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"flagTypeOptions\" [attr.aria-labelledby]=\"'feature-flag-type-label'\" formControlName=\"flag_type\" class=\"dropdown-bg-transparent\" placeholder=\"Select type\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-3\" label=\"Status\" name=\"status\" controlId=\"feature-flag-status\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"statusOptions\" [attr.aria-labelledby]=\"'feature-flag-status-label'\" formControlName=\"status\" class=\"dropdown-bg-transparent\" placeholder=\"Select status\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-3\" label=\"Owner\" name=\"owner\" controlId=\"feature-flag-owner\" [useAriaLabelledbyOnly]=\"true\">\n <p-autoComplete\n [suggestions]=\"filteredUsers\"\n [attr.aria-labelledby]=\"'feature-flag-owner-label'\"\n formControlName=\"owner\"\n dataKey=\"id\"\n field=\"displayName\"\n [dropdown]=\"true\"\n (completeMethod)=\"searchOwners($event)\"\n styleClass=\"w-100\"\n placeholder=\"Search owner\"\n [multiple]=\"false\"\n autocomplete=\"off\">\n </p-autoComplete>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-3\" label=\"Expires At\" name=\"expires_at\" controlId=\"feature-flag-expires_at\" [useAriaLabelledbyOnly]=\"true\">\n <p-calendar inputId=\"feature-flag-expires_at\" formControlName=\"expires_at\" [showIcon]=\"true\" [showTime]=\"true\" [appendTo]=\"'body'\" dateFormat=\"dd-M-yy\"></p-calendar>\n </pw-input-container>\n </div>\n\n <div class=\"row\">\n <div class=\"col-12 mt-4\">\n <div class=\"mb-3 text-end\">\n <button type=\"button\" class=\"btn btn-outline-default me-2\" (click)=\"onCancel()\">{{ 'Button.Cancel' | transloco }}</button>\n <button class=\"btn btn-primary\" [buttonBusy]=\"buttonBusy\">{{ 'Button.Save' | transloco }}</button>\n </div>\n </div>\n </div>\n </form>\n }\n </div>\n </div>\n </div>\n</div>" }]
2835
+ args: [{ selector: 'pw-feature-flag-details', standalone: false, template: "<div class=\"container-fluid pw-tab\">\n <div class=\"dashboard\">\n <div class=\"dashboard-body\">\n <div class=\"me-auto col-xs-6 mt-4\">\n <a routerLink=\"/admin/feature-flags/list\" class=\"previous\" aria-label=\"Back to feature flags list\">\n <i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i>\n </a>\n <h3 class=\"mt-3\">{{ id ? 'Edit' : 'Add New' }} Feature Flag</h3>\n </div>\n\n @if (isLoading) {\n <div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"></p-progressSpinner>\n </div>\n }\n\n <div class=\"p-2 mt-3\">\n @if (!isLoading) {\n <form (ngSubmit)=\"onSubmit()\" [formGroup]=\"form\">\n <div class=\"row\">\n <pw-input-container class=\"col-lg-6\" label=\"Key\" name=\"key\" controlId=\"feature-flag-key\" errorMsg=\"Key is required\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.Key' | transloco\">\n <input type=\"text\" id=\"feature-flag-key\" formControlName=\"key\" class=\"form-control\" [ngClass]=\"{ 'is-invalid': submitted && f['key'].errors }\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-6\" label=\"Name\" name=\"name\" controlId=\"feature-flag-name\" errorMsg=\"Name is required\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.Name' | transloco\">\n <input type=\"text\" id=\"feature-flag-name\" formControlName=\"name\" class=\"form-control\" [ngClass]=\"{ 'is-invalid': submitted && f['name'].errors }\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-12\" label=\"Description\" name=\"description\" controlId=\"feature-flag-description\">\n <textarea id=\"feature-flag-description\" formControlName=\"description\" rows=\"4\" class=\"form-control\"></textarea>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-3\" label=\"Type\" name=\"flag_type\" controlId=\"feature-flag-type\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"flagTypeOptions\" [attr.aria-labelledby]=\"'feature-flag-type-label'\" formControlName=\"flag_type\" class=\"dropdown-bg-transparent\" placeholder=\"Select type\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-3\" label=\"Status\" name=\"status\" controlId=\"feature-flag-status\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"statusOptions\" [attr.aria-labelledby]=\"'feature-flag-status-label'\" formControlName=\"status\" class=\"dropdown-bg-transparent\" placeholder=\"Select status\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-3\" label=\"Owner\" name=\"owner\" controlId=\"feature-flag-owner\" [useAriaLabelledbyOnly]=\"true\">\n <p-autoComplete\n [suggestions]=\"filteredUsers\"\n [attr.aria-labelledby]=\"'feature-flag-owner-label'\"\n formControlName=\"owner\"\n dataKey=\"id\"\n field=\"displayName\"\n [dropdown]=\"true\"\n (completeMethod)=\"searchOwners($event)\"\n styleClass=\"w-100\"\n placeholder=\"Search owner\"\n [multiple]=\"false\"\n autocomplete=\"off\">\n </p-autoComplete>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-3\" label=\"Expires At\" name=\"expires_at\" controlId=\"feature-flag-expires_at\" [useAriaLabelledbyOnly]=\"true\">\n <p-datepicker inputId=\"feature-flag-expires_at\" formControlName=\"expires_at\" [showIcon]=\"true\" [showTime]=\"true\" [appendTo]=\"'body'\" dateFormat=\"dd-M-yy\"></p-datepicker>\n </pw-input-container>\n </div>\n\n <div class=\"row\">\n <div class=\"col-12 mt-4\">\n <div class=\"mb-3 text-end\">\n <button type=\"button\" class=\"btn btn-outline-default me-2\" (click)=\"onCancel()\">{{ 'Button.Cancel' | transloco }}</button>\n <button class=\"btn btn-primary\" [buttonBusy]=\"buttonBusy\">{{ 'Button.Save' | transloco }}</button>\n </div>\n </div>\n </div>\n </form>\n }\n </div>\n </div>\n </div>\n</div>" }]
2836
2836
  }], ctorParameters: () => [{ type: i0.Injector }, { type: i1.AdminService }] });
2837
2837
 
2838
2838
  class FeatureFlagRulesComponent extends AppBaseComponent {
2839
- constructor(injector, adminService) {
2839
+ constructor(injector, adminService, cdr) {
2840
2840
  super(injector);
2841
2841
  this.adminService = adminService;
2842
+ this.cdr = cdr;
2842
2843
  this.routers = ROUTERS;
2843
2844
  this.ruleForm = AppAdmin.getFeatureFlagRuleForm();
2844
2845
  this.featureFlagId = 0;
@@ -2854,10 +2855,14 @@ class FeatureFlagRulesComponent extends AppBaseComponent {
2854
2855
  }
2855
2856
  ngOnInit() {
2856
2857
  this.route.params.subscribe(params => {
2857
- this.featureFlagId = +params['id'] || 0;
2858
+ const parsedId = Number(params['id']);
2859
+ this.featureFlagId = Number.isFinite(parsedId) ? parsedId : 0;
2858
2860
  this.loadPageData();
2859
2861
  });
2860
2862
  }
2863
+ nonEmpty(value) {
2864
+ return value && value.length > 0 ? value : undefined;
2865
+ }
2861
2866
  get rf() {
2862
2867
  return this.ruleForm.controls;
2863
2868
  }
@@ -2868,38 +2873,44 @@ class FeatureFlagRulesComponent extends AppBaseComponent {
2868
2873
  }
2869
2874
  this.isLoading = true;
2870
2875
  this.loadSupportedOptions();
2871
- this.loadFeatureFlag();
2872
- this.loadRules();
2876
+ forkJoin({
2877
+ flag: this.adminService.getFeatureFlagById(this.featureFlagId),
2878
+ rulesResponse: this.adminService.getFeatureFlagRules(this.featureFlagId)
2879
+ })
2880
+ .pipe(finalize(() => {
2881
+ this.isLoading = false;
2882
+ this.cdr.detectChanges();
2883
+ }))
2884
+ .subscribe({
2885
+ next: ({ flag, rulesResponse }) => {
2886
+ const name = flag.name?.trim();
2887
+ const key = flag.key?.trim();
2888
+ this.featureFlagName =
2889
+ this.nonEmpty(name) ?? this.nonEmpty(key) ?? 'Feature Flag';
2890
+ this.rules = rulesResponse.feature_flag_rules ?? [];
2891
+ }
2892
+ });
2873
2893
  }
2874
2894
  loadSupportedOptions() {
2875
2895
  this.adminService.getSupportedFeatureFlagRuleOptions().subscribe(response => {
2876
- this.targetTypeOptions = (response.target_types || []).map(option => ({
2896
+ this.targetTypeOptions = (response.target_types ?? []).map(option => ({
2877
2897
  label: option,
2878
2898
  value: option
2879
2899
  }));
2880
- this.environmentOptions = (response.environments || []).map(option => ({
2900
+ this.environmentOptions = (response.environments ?? []).map(option => ({
2881
2901
  label: option,
2882
2902
  value: option
2883
2903
  }));
2884
- this.productFeatureKeyOptions = (response.product_feature_keys || []).map(option => ({
2904
+ this.productFeatureKeyOptions = (response.product_feature_keys ?? []).map(option => ({
2885
2905
  label: option,
2886
2906
  value: option
2887
2907
  }));
2888
2908
  });
2889
2909
  }
2890
- loadFeatureFlag() {
2891
- this.adminService.getFeatureFlagById(this.featureFlagId).subscribe({
2892
- next: response => {
2893
- this.featureFlagName = response.name || response.key || 'Feature Flag';
2894
- },
2895
- complete: () => {
2896
- this.isLoading = false;
2897
- }
2898
- });
2899
- }
2900
2910
  loadRules() {
2901
2911
  this.adminService.getFeatureFlagRules(this.featureFlagId).subscribe(response => {
2902
- this.rules = response.feature_flag_rules || [];
2912
+ this.rules = response.feature_flag_rules ?? [];
2913
+ this.cdr.detectChanges();
2903
2914
  });
2904
2915
  }
2905
2916
  editRule(rule) {
@@ -2974,13 +2985,13 @@ class FeatureFlagRulesComponent extends AppBaseComponent {
2974
2985
  backToFlags() {
2975
2986
  this.router.navigate([this.routers.featureFlagsConfig]);
2976
2987
  }
2977
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FeatureFlagRulesComponent, deps: [{ token: i0.Injector }, { token: i1.AdminService }], target: i0.ɵɵFactoryTarget.Component }); }
2978
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FeatureFlagRulesComponent, isStandalone: false, selector: "pw-feature-flag-rules", usesInheritance: true, ngImport: i0, template: "<div class=\"container-fluid pw-tab\">\n <div class=\"dashboard\">\n <div class=\"dashboard-body\">\n <div class=\"me-auto col-xs-6 mt-4\">\n <a [routerLink]=\"routers.featureFlagsConfig\" class=\"previous\"><i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i></a>\n <h3 class=\"mt-3\">Feature Flag Rules \u2014 {{ featureFlagName }}</h3>\n </div>\n\n @if (isLoading) {\n <div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"></p-progressSpinner>\n </div>\n }\n\n @if (!isLoading) {\n <div class=\"p-2 mt-3\">\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\n <h4 class=\"mb-0\">Manage Rules</h4>\n </div>\n\n <form [formGroup]=\"ruleForm\" (ngSubmit)=\"saveRule()\" class=\"mb-4\">\n <div class=\"row\">\n <pw-input-container class=\"col-lg-4\" label=\"Environment\" name=\"environment\" controlId=\"feature-flag-rule-environment\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"environmentOptions\" formControlName=\"environment\" class=\"dropdown-bg-transparent\" placeholder=\"Select environment\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Product Feature Key\" name=\"product_feature_key\" controlId=\"feature-flag-rule-product_feature_key\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"productFeatureKeyOptions\" formControlName=\"product_feature_key\" class=\"dropdown-bg-transparent\" placeholder=\"Select product feature key\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Target Type\" name=\"target_type\" controlId=\"feature-flag-rule-target_type\" errorMsg=\"Target type is required\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"targetTypeOptions\" formControlName=\"target_type\" class=\"dropdown-bg-transparent\" placeholder=\"Select target type\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Target Value\" name=\"target_value\" controlId=\"feature-flag-rule-target_value\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.TargetValue' | transloco\">\n <input type=\"text\" id=\"feature-flag-rule-target_value\" formControlName=\"target_value\" class=\"form-control\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Priority\" name=\"priority\" controlId=\"feature-flag-rule-priority\" errorMsg=\"Priority is required\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.Priority' | transloco\">\n <input type=\"number\" id=\"feature-flag-rule-priority\" formControlName=\"priority\" class=\"form-control\" [ngClass]=\"{ 'is-invalid': ruleSubmitted && rf['priority'].errors }\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Rollout Percentage\" name=\"rollout_percentage\" controlId=\"feature-flag-rule-rollout_percentage\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.RolloutPercentage' | transloco\">\n <input type=\"number\" id=\"feature-flag-rule-rollout_percentage\" formControlName=\"rollout_percentage\" class=\"form-control\" min=\"0\" max=\"100\" />\n </pw-input-container>\n\n <div class=\"col-lg-3 d-flex align-items-end\">\n <div>\n <span id=\"feature-flag-rule-enabled-label\" class=\"pw-label-style\">Enabled</span><br />\n <ui-switch formControlName=\"enabled\" [attr.aria-labelledby]=\"'feature-flag-rule-enabled-label'\"></ui-switch>\n </div>\n </div>\n\n <div class=\"col-lg-9 d-flex align-items-end justify-content-end gap-2\">\n @if (editingRuleId) {\n <button type=\"button\" class=\"btn btn-outline-default\" (click)=\"resetRuleForm()\">\n Cancel editing rule\n </button>\n }\n <button type=\"submit\" class=\"btn btn-primary\" [buttonBusy]=\"ruleButtonBusy\">\n {{ editingRuleId ? 'Update Rule' : 'Add Rule' }}\n </button>\n </div>\n </div>\n </form>\n\n <div class=\"row primeng-datatable-container mt-0\">\n <div class=\"col-12 px-0\">\n <p-table [value]=\"rules\">\n <ng-template pTemplate=\"header\">\n <tr>\n <th>Environment</th>\n <th>Product Feature Key</th>\n <th>Target Type</th>\n <th>Target Value</th>\n <th>Enabled</th>\n <th>Priority</th>\n <th>Rollout %</th>\n <th class=\"actions-list-two\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-rule>\n <tr>\n <td>{{ rule.environment || '-' }}</td>\n <td>{{ rule.product_feature_key || '-' }}</td>\n <td>{{ rule.target_type }}</td>\n <td>{{ rule.target_value || '-' }}</td>\n <td><span class=\"badge\" [ngClass]=\"rule.enabled ? 'bg-success' : 'bg-secondary'\">{{ rule.enabled }}</span></td>\n <td>{{ rule.priority }}</td>\n <td>{{ rule.rollout_percentage ?? '-' }}</td>\n <td>\n <ul class=\"list-unstyled list-inline list-action\">\n <li ngbTooltip=\"Edit\" class=\"me-2 me-sm-2\">\n <i class=\"fa fa-edit edit-icon\" (click)=\"editRule(rule)\" aria-hidden=\"true\"></i>\n </li>\n <li ngbTooltip=\"Delete\" class=\"me-2 me-sm-2\">\n <i class=\"fa fa-trash delete-icon\" (click)=\"deleteRule(rule)\" aria-hidden=\"true\"></i>\n </li>\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (rules.length === 0) {\n <pw-no-data [withImage]=\"true\" [message]=\"'No feature flag rules found'\"></pw-no-data>\n }\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n</div>", dependencies: [{ kind: "component", type: i2.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i3$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: i3.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "directive", type: i2$1.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "directive", type: i3$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.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: i6.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i6.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "component", type: i7.UiSwitchComponent, selector: "ui-switch", inputs: ["size", "color", "switchOffColor", "switchColor", "defaultBgColor", "defaultBoColor", "checkedLabel", "uncheckedLabel", "checkedTextColor", "uncheckedTextColor", "beforeChange", "ariaLabel", "checked", "disabled", "reverse", "loading"], outputs: ["change", "changeEvent", "valueChange"] }, { kind: "component", type: i4.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: i1$1.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "controlId", "useAriaLabelledbyOnly", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "component", type: i1$1.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "directive", type: i9.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i10.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i6.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i6.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: i11.TranslocoPipe, name: "transloco" }] }); }
2988
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FeatureFlagRulesComponent, deps: [{ token: i0.Injector }, { token: i1.AdminService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
2989
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FeatureFlagRulesComponent, isStandalone: false, selector: "pw-feature-flag-rules", usesInheritance: true, ngImport: i0, template: "<div class=\"container-fluid pw-tab\">\n <div class=\"dashboard\">\n <div class=\"dashboard-body\">\n <div class=\"me-auto col-xs-6 mt-4\">\n <a [routerLink]=\"routers.featureFlagsConfig\" class=\"previous\" aria-label=\"Back to feature flags\">\n <i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i>\n </a>\n <h3 class=\"mt-3\">Feature Flag Rules \u2014 {{ featureFlagName }}</h3>\n </div>\n\n @if (isLoading) {\n <div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"></p-progressSpinner>\n </div>\n }\n\n @if (!isLoading) {\n <div class=\"p-2 mt-3\">\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\n <h4 class=\"mb-0\">Manage Rules</h4>\n </div>\n\n <form [formGroup]=\"ruleForm\" (ngSubmit)=\"saveRule()\" class=\"mb-4\">\n <div class=\"row\">\n <pw-input-container class=\"col-lg-4\" label=\"Environment\" name=\"environment\" controlId=\"feature-flag-rule-environment\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"environmentOptions\" formControlName=\"environment\" class=\"dropdown-bg-transparent\" placeholder=\"Select environment\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Product Feature Key\" name=\"product_feature_key\" controlId=\"feature-flag-rule-product_feature_key\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"productFeatureKeyOptions\" formControlName=\"product_feature_key\" class=\"dropdown-bg-transparent\" placeholder=\"Select product feature key\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Target Type\" name=\"target_type\" controlId=\"feature-flag-rule-target_type\" errorMsg=\"Target type is required\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"targetTypeOptions\" formControlName=\"target_type\" class=\"dropdown-bg-transparent\" placeholder=\"Select target type\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Target Value\" name=\"target_value\" controlId=\"feature-flag-rule-target_value\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.TargetValue' | transloco\">\n <input type=\"text\" id=\"feature-flag-rule-target_value\" formControlName=\"target_value\" class=\"form-control\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Priority\" name=\"priority\" controlId=\"feature-flag-rule-priority\" errorMsg=\"Priority is required\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.Priority' | transloco\">\n <input type=\"number\" id=\"feature-flag-rule-priority\" formControlName=\"priority\" class=\"form-control\" [ngClass]=\"{ 'is-invalid': ruleSubmitted && rf['priority'].errors }\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Rollout Percentage\" name=\"rollout_percentage\" controlId=\"feature-flag-rule-rollout_percentage\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.RolloutPercentage' | transloco\">\n <input type=\"number\" id=\"feature-flag-rule-rollout_percentage\" formControlName=\"rollout_percentage\" class=\"form-control\" min=\"0\" max=\"100\" />\n </pw-input-container>\n\n <div class=\"col-lg-3 d-flex align-items-end\">\n <div>\n <span id=\"feature-flag-rule-enabled-label\" class=\"pw-label-style\">Enabled</span><br />\n <ui-switch formControlName=\"enabled\" [attr.aria-labelledby]=\"'feature-flag-rule-enabled-label'\"></ui-switch>\n </div>\n </div>\n\n <div class=\"col-lg-9 d-flex align-items-end justify-content-end gap-2\">\n @if (editingRuleId) {\n <button type=\"button\" class=\"btn btn-outline-default\" (click)=\"resetRuleForm()\">\n Cancel editing rule\n </button>\n }\n <button type=\"submit\" class=\"btn btn-primary\" [buttonBusy]=\"ruleButtonBusy\">\n {{ editingRuleId ? 'Update Rule' : 'Add Rule' }}\n </button>\n </div>\n </div>\n </form>\n\n <div class=\"row primeng-datatable-container mt-0\">\n <div class=\"col-12 px-0\">\n <p-table [value]=\"rules\">\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"col\">Environment</th>\n <th scope=\"col\">Product Feature Key</th>\n <th scope=\"col\">Target Type</th>\n <th scope=\"col\">Target Value</th>\n <th scope=\"col\">Enabled</th>\n <th scope=\"col\">Priority</th>\n <th scope=\"col\">Rollout %</th>\n <th scope=\"col\" class=\"actions-list-two\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-rule>\n <tr>\n <td>{{ rule.environment || '-' }}</td>\n <td>{{ rule.product_feature_key || '-' }}</td>\n <td>{{ rule.target_type }}</td>\n <td>{{ rule.target_value || '-' }}</td>\n <td><span class=\"badge\" [ngClass]=\"rule.enabled ? 'bg-success' : 'bg-secondary'\">{{ rule.enabled }}</span></td>\n <td>{{ rule.priority }}</td>\n <td>{{ rule.rollout_percentage ?? '-' }}</td>\n <td>\n <ul class=\"list-unstyled list-inline list-action\">\n <li ngbTooltip=\"Edit\" class=\"me-2 me-sm-2\">\n <button\n type=\"button\"\n class=\"btn p-0 border-0 bg-transparent\"\n aria-label=\"Edit rule\"\n (click)=\"editRule(rule)\">\n <i class=\"fa fa-edit edit-icon\"></i>\n </button>\n </li>\n <li ngbTooltip=\"Delete\" class=\"me-2 me-sm-2\">\n <button\n type=\"button\"\n class=\"btn p-0 border-0 bg-transparent\"\n aria-label=\"Delete rule\"\n (click)=\"deleteRule(rule)\">\n <i class=\"fa fa-trash delete-icon\"></i>\n </button>\n </li>\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (rules.length === 0) {\n <pw-no-data [withImage]=\"true\" [message]=\"'No feature flag rules found'\"></pw-no-data>\n }\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n</div>", dependencies: [{ kind: "component", type: i2.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i3$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: i3.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "directive", type: i2$1.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "directive", type: i3$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.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: i6.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i6.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "component", type: i7.UiSwitchComponent, selector: "ui-switch", inputs: ["size", "color", "switchOffColor", "switchColor", "defaultBgColor", "defaultBoColor", "checkedLabel", "uncheckedLabel", "checkedTextColor", "uncheckedTextColor", "beforeChange", "ariaLabel", "checked", "disabled", "reverse", "loading"], outputs: ["change", "changeEvent", "valueChange"] }, { kind: "component", type: i4.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: i1$1.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "controlId", "useAriaLabelledbyOnly", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "component", type: i1$1.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "directive", type: i9.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i10.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i6.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i6.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: i11.TranslocoPipe, name: "transloco" }] }); }
2979
2990
  }
2980
2991
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FeatureFlagRulesComponent, decorators: [{
2981
2992
  type: Component,
2982
- args: [{ selector: 'pw-feature-flag-rules', standalone: false, template: "<div class=\"container-fluid pw-tab\">\n <div class=\"dashboard\">\n <div class=\"dashboard-body\">\n <div class=\"me-auto col-xs-6 mt-4\">\n <a [routerLink]=\"routers.featureFlagsConfig\" class=\"previous\"><i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i></a>\n <h3 class=\"mt-3\">Feature Flag Rules \u2014 {{ featureFlagName }}</h3>\n </div>\n\n @if (isLoading) {\n <div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"></p-progressSpinner>\n </div>\n }\n\n @if (!isLoading) {\n <div class=\"p-2 mt-3\">\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\n <h4 class=\"mb-0\">Manage Rules</h4>\n </div>\n\n <form [formGroup]=\"ruleForm\" (ngSubmit)=\"saveRule()\" class=\"mb-4\">\n <div class=\"row\">\n <pw-input-container class=\"col-lg-4\" label=\"Environment\" name=\"environment\" controlId=\"feature-flag-rule-environment\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"environmentOptions\" formControlName=\"environment\" class=\"dropdown-bg-transparent\" placeholder=\"Select environment\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Product Feature Key\" name=\"product_feature_key\" controlId=\"feature-flag-rule-product_feature_key\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"productFeatureKeyOptions\" formControlName=\"product_feature_key\" class=\"dropdown-bg-transparent\" placeholder=\"Select product feature key\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Target Type\" name=\"target_type\" controlId=\"feature-flag-rule-target_type\" errorMsg=\"Target type is required\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"targetTypeOptions\" formControlName=\"target_type\" class=\"dropdown-bg-transparent\" placeholder=\"Select target type\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Target Value\" name=\"target_value\" controlId=\"feature-flag-rule-target_value\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.TargetValue' | transloco\">\n <input type=\"text\" id=\"feature-flag-rule-target_value\" formControlName=\"target_value\" class=\"form-control\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Priority\" name=\"priority\" controlId=\"feature-flag-rule-priority\" errorMsg=\"Priority is required\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.Priority' | transloco\">\n <input type=\"number\" id=\"feature-flag-rule-priority\" formControlName=\"priority\" class=\"form-control\" [ngClass]=\"{ 'is-invalid': ruleSubmitted && rf['priority'].errors }\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Rollout Percentage\" name=\"rollout_percentage\" controlId=\"feature-flag-rule-rollout_percentage\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.RolloutPercentage' | transloco\">\n <input type=\"number\" id=\"feature-flag-rule-rollout_percentage\" formControlName=\"rollout_percentage\" class=\"form-control\" min=\"0\" max=\"100\" />\n </pw-input-container>\n\n <div class=\"col-lg-3 d-flex align-items-end\">\n <div>\n <span id=\"feature-flag-rule-enabled-label\" class=\"pw-label-style\">Enabled</span><br />\n <ui-switch formControlName=\"enabled\" [attr.aria-labelledby]=\"'feature-flag-rule-enabled-label'\"></ui-switch>\n </div>\n </div>\n\n <div class=\"col-lg-9 d-flex align-items-end justify-content-end gap-2\">\n @if (editingRuleId) {\n <button type=\"button\" class=\"btn btn-outline-default\" (click)=\"resetRuleForm()\">\n Cancel editing rule\n </button>\n }\n <button type=\"submit\" class=\"btn btn-primary\" [buttonBusy]=\"ruleButtonBusy\">\n {{ editingRuleId ? 'Update Rule' : 'Add Rule' }}\n </button>\n </div>\n </div>\n </form>\n\n <div class=\"row primeng-datatable-container mt-0\">\n <div class=\"col-12 px-0\">\n <p-table [value]=\"rules\">\n <ng-template pTemplate=\"header\">\n <tr>\n <th>Environment</th>\n <th>Product Feature Key</th>\n <th>Target Type</th>\n <th>Target Value</th>\n <th>Enabled</th>\n <th>Priority</th>\n <th>Rollout %</th>\n <th class=\"actions-list-two\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-rule>\n <tr>\n <td>{{ rule.environment || '-' }}</td>\n <td>{{ rule.product_feature_key || '-' }}</td>\n <td>{{ rule.target_type }}</td>\n <td>{{ rule.target_value || '-' }}</td>\n <td><span class=\"badge\" [ngClass]=\"rule.enabled ? 'bg-success' : 'bg-secondary'\">{{ rule.enabled }}</span></td>\n <td>{{ rule.priority }}</td>\n <td>{{ rule.rollout_percentage ?? '-' }}</td>\n <td>\n <ul class=\"list-unstyled list-inline list-action\">\n <li ngbTooltip=\"Edit\" class=\"me-2 me-sm-2\">\n <i class=\"fa fa-edit edit-icon\" (click)=\"editRule(rule)\" aria-hidden=\"true\"></i>\n </li>\n <li ngbTooltip=\"Delete\" class=\"me-2 me-sm-2\">\n <i class=\"fa fa-trash delete-icon\" (click)=\"deleteRule(rule)\" aria-hidden=\"true\"></i>\n </li>\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (rules.length === 0) {\n <pw-no-data [withImage]=\"true\" [message]=\"'No feature flag rules found'\"></pw-no-data>\n }\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n</div>" }]
2983
- }], ctorParameters: () => [{ type: i0.Injector }, { type: i1.AdminService }] });
2993
+ args: [{ selector: 'pw-feature-flag-rules', standalone: false, template: "<div class=\"container-fluid pw-tab\">\n <div class=\"dashboard\">\n <div class=\"dashboard-body\">\n <div class=\"me-auto col-xs-6 mt-4\">\n <a [routerLink]=\"routers.featureFlagsConfig\" class=\"previous\" aria-label=\"Back to feature flags\">\n <i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i>\n </a>\n <h3 class=\"mt-3\">Feature Flag Rules \u2014 {{ featureFlagName }}</h3>\n </div>\n\n @if (isLoading) {\n <div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"></p-progressSpinner>\n </div>\n }\n\n @if (!isLoading) {\n <div class=\"p-2 mt-3\">\n <div class=\"d-flex justify-content-between align-items-center mb-3\">\n <h4 class=\"mb-0\">Manage Rules</h4>\n </div>\n\n <form [formGroup]=\"ruleForm\" (ngSubmit)=\"saveRule()\" class=\"mb-4\">\n <div class=\"row\">\n <pw-input-container class=\"col-lg-4\" label=\"Environment\" name=\"environment\" controlId=\"feature-flag-rule-environment\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"environmentOptions\" formControlName=\"environment\" class=\"dropdown-bg-transparent\" placeholder=\"Select environment\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Product Feature Key\" name=\"product_feature_key\" controlId=\"feature-flag-rule-product_feature_key\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"productFeatureKeyOptions\" formControlName=\"product_feature_key\" class=\"dropdown-bg-transparent\" placeholder=\"Select product feature key\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Target Type\" name=\"target_type\" controlId=\"feature-flag-rule-target_type\" errorMsg=\"Target type is required\" [useAriaLabelledbyOnly]=\"true\">\n <p-select [options]=\"targetTypeOptions\" formControlName=\"target_type\" class=\"dropdown-bg-transparent\" placeholder=\"Select target type\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Target Value\" name=\"target_value\" controlId=\"feature-flag-rule-target_value\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.TargetValue' | transloco\">\n <input type=\"text\" id=\"feature-flag-rule-target_value\" formControlName=\"target_value\" class=\"form-control\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Priority\" name=\"priority\" controlId=\"feature-flag-rule-priority\" errorMsg=\"Priority is required\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.Priority' | transloco\">\n <input type=\"number\" id=\"feature-flag-rule-priority\" formControlName=\"priority\" class=\"form-control\" [ngClass]=\"{ 'is-invalid': ruleSubmitted && rf['priority'].errors }\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-lg-4\" label=\"Rollout Percentage\" name=\"rollout_percentage\" controlId=\"feature-flag-rule-rollout_percentage\"\n [showTooltip]=\"true\" [tooltipText]=\"'FeatureFlag.Tooltip.RolloutPercentage' | transloco\">\n <input type=\"number\" id=\"feature-flag-rule-rollout_percentage\" formControlName=\"rollout_percentage\" class=\"form-control\" min=\"0\" max=\"100\" />\n </pw-input-container>\n\n <div class=\"col-lg-3 d-flex align-items-end\">\n <div>\n <span id=\"feature-flag-rule-enabled-label\" class=\"pw-label-style\">Enabled</span><br />\n <ui-switch formControlName=\"enabled\" [attr.aria-labelledby]=\"'feature-flag-rule-enabled-label'\"></ui-switch>\n </div>\n </div>\n\n <div class=\"col-lg-9 d-flex align-items-end justify-content-end gap-2\">\n @if (editingRuleId) {\n <button type=\"button\" class=\"btn btn-outline-default\" (click)=\"resetRuleForm()\">\n Cancel editing rule\n </button>\n }\n <button type=\"submit\" class=\"btn btn-primary\" [buttonBusy]=\"ruleButtonBusy\">\n {{ editingRuleId ? 'Update Rule' : 'Add Rule' }}\n </button>\n </div>\n </div>\n </form>\n\n <div class=\"row primeng-datatable-container mt-0\">\n <div class=\"col-12 px-0\">\n <p-table [value]=\"rules\">\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"col\">Environment</th>\n <th scope=\"col\">Product Feature Key</th>\n <th scope=\"col\">Target Type</th>\n <th scope=\"col\">Target Value</th>\n <th scope=\"col\">Enabled</th>\n <th scope=\"col\">Priority</th>\n <th scope=\"col\">Rollout %</th>\n <th scope=\"col\" class=\"actions-list-two\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-rule>\n <tr>\n <td>{{ rule.environment || '-' }}</td>\n <td>{{ rule.product_feature_key || '-' }}</td>\n <td>{{ rule.target_type }}</td>\n <td>{{ rule.target_value || '-' }}</td>\n <td><span class=\"badge\" [ngClass]=\"rule.enabled ? 'bg-success' : 'bg-secondary'\">{{ rule.enabled }}</span></td>\n <td>{{ rule.priority }}</td>\n <td>{{ rule.rollout_percentage ?? '-' }}</td>\n <td>\n <ul class=\"list-unstyled list-inline list-action\">\n <li ngbTooltip=\"Edit\" class=\"me-2 me-sm-2\">\n <button\n type=\"button\"\n class=\"btn p-0 border-0 bg-transparent\"\n aria-label=\"Edit rule\"\n (click)=\"editRule(rule)\">\n <i class=\"fa fa-edit edit-icon\"></i>\n </button>\n </li>\n <li ngbTooltip=\"Delete\" class=\"me-2 me-sm-2\">\n <button\n type=\"button\"\n class=\"btn p-0 border-0 bg-transparent\"\n aria-label=\"Delete rule\"\n (click)=\"deleteRule(rule)\">\n <i class=\"fa fa-trash delete-icon\"></i>\n </button>\n </li>\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (rules.length === 0) {\n <pw-no-data [withImage]=\"true\" [message]=\"'No feature flag rules found'\"></pw-no-data>\n }\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n</div>" }]
2994
+ }], ctorParameters: () => [{ type: i0.Injector }, { type: i1.AdminService }, { type: i0.ChangeDetectorRef }] });
2984
2995
 
2985
2996
  class FeatureFlagsListComponent extends AppBaseComponent {
2986
2997
  constructor(injector, adminService) {
@@ -2995,6 +3006,9 @@ class FeatureFlagsListComponent extends AppBaseComponent {
2995
3006
  this.totalRecords = 0;
2996
3007
  this.page = 1;
2997
3008
  }
3009
+ nonEmpty(value) {
3010
+ return value && value.length > 0 ? value : undefined;
3011
+ }
2998
3012
  onLazyLoad(event) {
2999
3013
  const pageDetails = HelperService.onTableLazyLoad(event);
3000
3014
  this.page = pageDetails.page;
@@ -3028,9 +3042,12 @@ class FeatureFlagsListComponent extends AppBaseComponent {
3028
3042
  });
3029
3043
  }
3030
3044
  onDelete(item) {
3045
+ const name = item.name?.trim();
3046
+ const key = item.key?.trim();
3047
+ const displayName = this.nonEmpty(name) ?? this.nonEmpty(key) ?? 'this feature flag';
3031
3048
  swal.fire({
3032
3049
  title: 'Delete feature flag?',
3033
- text: `This will remove ${item.name || item.key}.`,
3050
+ text: `This will remove ${displayName}.`,
3034
3051
  icon: 'warning',
3035
3052
  showCancelButton: true,
3036
3053
  confirmButtonText: 'Delete'
@@ -3051,11 +3068,11 @@ class FeatureFlagsListComponent extends AppBaseComponent {
3051
3068
  });
3052
3069
  }
3053
3070
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FeatureFlagsListComponent, deps: [{ token: i0.Injector }, { token: i1.AdminService }], target: i0.ɵɵFactoryTarget.Component }); }
3054
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FeatureFlagsListComponent, isStandalone: false, selector: "pw-feature-flags-list", usesInheritance: true, ngImport: i0, template: "<div class=\"row\" [class.custom-disable-wrapper]=\"buttonBusy\">\n <div class=\"col-12 d-flex flex-wrap justify-content-between align-items-center\">\n <h2 class=\"card-title p-0 float-start\">Feature Flags</h2>\n <a [routerLink]=\"[routers.featureFlagsDetails + 'add']\" class=\"btn btn-sm btn-outline-primary float-end\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i> {{ 'Label.AddNew' | transloco }} Feature Flag\n </a>\n </div>\n <div class=\"col-12 mb-3\">\n <p>Manage feature flags for controlled rollout, testing, and admin-driven enablement.</p>\n </div>\n</div>\n\n@if (!isLoaded) {\n<div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"></p-progressSpinner>\n</div>\n}\n\n<div class=\"row primeng-datatable-container mt-0\" [class.custom-disable-wrapper]=\"buttonBusy\">\n <div class=\"col-12 px-0\">\n <p-table\n [value]=\"featureFlags\"\n [paginator]=\"totalRecords !== 0\"\n [lazy]=\"true\"\n [rows]=\"PAGE_SIZE\"\n [totalRecords]=\"totalRecords\"\n [filterDelay]=\"300\"\n (onLazyLoad)=\"onLazyLoad($event)\">\n <ng-template pTemplate=\"caption\">\n <div class=\"text-end\">\n <i class=\"fa fa-search mt-2 me-2\" aria-hidden=\"true\"></i>\n <input type=\"text\" [(ngModel)]=\"searchText\" pInputText size=\"50\" placeholder=\"Search feature flags...\" class=\"mw-90\" />\n </div>\n </ng-template>\n <ng-template pTemplate=\"header\">\n <tr>\n <th>Key</th>\n <th>Name</th>\n <th>Status</th>\n <th>Type</th>\n <th>Owner</th>\n <th>Expires</th>\n <th class=\"actions-list-two\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-flag>\n <tr>\n <td>{{ flag.key }}</td>\n <td>{{ flag.name }}</td>\n <td><span class=\"badge bg-info\">{{ flag.status || 'draft' }}</span></td>\n <td>{{ flag.flag_type || '-' }}</td>\n <td>{{ flag.owner || '-' }}</td>\n <td>{{ flag.expires_at ? (flag.expires_at | date:'dd-MMM-yyyy HH:mm') : '-' }}</td>\n <td>\n <ul class=\"list-unstyled list-inline list-action\">\n <li ngbTooltip=\"Edit\" class=\"me-2 me-sm-2\">\n <i class=\"fa fa-edit edit-icon\" (click)=\"navigateToEdit(flag)\" aria-hidden=\"true\"></i>\n </li>\n <li ngbTooltip=\"Rules\" class=\"me-2 me-sm-2\">\n <i class=\"fa fa-list-ul edit-icon\" (click)=\"navigateToRules(flag)\" aria-hidden=\"true\"></i>\n </li>\n <li ngbTooltip=\"Delete\" class=\"me-2 me-sm-2\">\n <i class=\"fa fa-trash delete-icon\" (click)=\"onDelete(flag)\" aria-hidden=\"true\"></i>\n </li>\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (totalRecords === 0) {\n <pw-no-data [withImage]=\"true\" [message]=\"'No feature flags found'\"></pw-no-data>\n }\n </div>\n</div>", dependencies: [{ kind: "component", type: i2.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i3$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "directive", type: i2$1.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "directive", type: i6.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: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: i1$1.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "directive", type: i10.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i3$1.DatePipe, name: "date" }, { kind: "pipe", type: i11.TranslocoPipe, name: "transloco" }] }); }
3071
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FeatureFlagsListComponent, isStandalone: false, selector: "pw-feature-flags-list", usesInheritance: true, ngImport: i0, template: "<div class=\"row\" [class.custom-disable-wrapper]=\"buttonBusy\">\n <div class=\"col-12 d-flex flex-wrap justify-content-between align-items-center\">\n <h2 class=\"card-title p-0 float-start\">Feature Flags</h2>\n <a [routerLink]=\"[routers.featureFlagsDetails + 'add']\" class=\"btn btn-sm btn-outline-primary float-end\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i> {{ 'Label.AddNew' | transloco }} Feature Flag\n </a>\n </div>\n <div class=\"col-12 mb-3\">\n <p>Manage feature flags for controlled rollout, testing, and admin-driven enablement.</p>\n </div>\n</div>\n\n@if (!isLoaded) {\n<div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"></p-progressSpinner>\n</div>\n}\n\n<div class=\"row primeng-datatable-container mt-0\" [class.custom-disable-wrapper]=\"buttonBusy\">\n <div class=\"col-12 px-0\">\n <p-table\n [value]=\"featureFlags\"\n [paginator]=\"totalRecords !== 0\"\n [lazy]=\"true\"\n [rows]=\"PAGE_SIZE\"\n [totalRecords]=\"totalRecords\"\n [filterDelay]=\"300\"\n (onLazyLoad)=\"onLazyLoad($event)\">\n <ng-template pTemplate=\"caption\">\n <div class=\"text-end\">\n <i class=\"fa fa-search mt-2 me-2\" aria-hidden=\"true\"></i>\n <input type=\"text\" [(ngModel)]=\"searchText\" pInputText size=\"50\" placeholder=\"Search feature flags...\" class=\"mw-90\" />\n </div>\n </ng-template>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"col\">Key</th>\n <th scope=\"col\">Name</th>\n <th scope=\"col\">Status</th>\n <th scope=\"col\">Type</th>\n <th scope=\"col\">Owner</th>\n <th scope=\"col\">Expires</th>\n <th scope=\"col\" class=\"actions-list-two\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-flag>\n <tr>\n <td>{{ flag.key }}</td>\n <td>{{ flag.name }}</td>\n <td><span class=\"badge bg-info\">{{ flag.status || 'draft' }}</span></td>\n <td>{{ flag.flag_type || '-' }}</td>\n <td>{{ flag.owner || '-' }}</td>\n <td>{{ flag.expires_at ? (flag.expires_at | date:'dd-MMM-yyyy HH:mm') : '-' }}</td>\n <td>\n <ul class=\"list-unstyled list-inline list-action\">\n <li ngbTooltip=\"Edit\" class=\"me-2 me-sm-2\">\n <button\n type=\"button\"\n class=\"btn p-0 border-0 bg-transparent\"\n aria-label=\"Edit feature flag\"\n (click)=\"navigateToEdit(flag)\">\n <i class=\"fa fa-edit edit-icon\"></i>\n </button>\n </li>\n <li ngbTooltip=\"Rules\" class=\"me-2 me-sm-2\">\n <button\n type=\"button\"\n class=\"btn p-0 border-0 bg-transparent\"\n aria-label=\"Manage feature flag rules\"\n (click)=\"navigateToRules(flag)\">\n <i class=\"fa fa-list-ul edit-icon\"></i>\n </button>\n </li>\n <li ngbTooltip=\"Delete\" class=\"me-2 me-sm-2\">\n <button\n type=\"button\"\n class=\"btn p-0 border-0 bg-transparent\"\n aria-label=\"Delete feature flag\"\n (click)=\"onDelete(flag)\">\n <i class=\"fa fa-trash delete-icon\"></i>\n </button>\n </li>\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (totalRecords === 0) {\n <pw-no-data [withImage]=\"true\" [message]=\"'No feature flags found'\"></pw-no-data>\n }\n </div>\n</div>", dependencies: [{ kind: "component", type: i2.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i3$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i4$1.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "directive", type: i2$1.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "directive", type: i6.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: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: i1$1.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "directive", type: i10.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i3$1.DatePipe, name: "date" }, { kind: "pipe", type: i11.TranslocoPipe, name: "transloco" }] }); }
3055
3072
  }
3056
3073
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FeatureFlagsListComponent, decorators: [{
3057
3074
  type: Component,
3058
- args: [{ selector: 'pw-feature-flags-list', standalone: false, template: "<div class=\"row\" [class.custom-disable-wrapper]=\"buttonBusy\">\n <div class=\"col-12 d-flex flex-wrap justify-content-between align-items-center\">\n <h2 class=\"card-title p-0 float-start\">Feature Flags</h2>\n <a [routerLink]=\"[routers.featureFlagsDetails + 'add']\" class=\"btn btn-sm btn-outline-primary float-end\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i> {{ 'Label.AddNew' | transloco }} Feature Flag\n </a>\n </div>\n <div class=\"col-12 mb-3\">\n <p>Manage feature flags for controlled rollout, testing, and admin-driven enablement.</p>\n </div>\n</div>\n\n@if (!isLoaded) {\n<div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"></p-progressSpinner>\n</div>\n}\n\n<div class=\"row primeng-datatable-container mt-0\" [class.custom-disable-wrapper]=\"buttonBusy\">\n <div class=\"col-12 px-0\">\n <p-table\n [value]=\"featureFlags\"\n [paginator]=\"totalRecords !== 0\"\n [lazy]=\"true\"\n [rows]=\"PAGE_SIZE\"\n [totalRecords]=\"totalRecords\"\n [filterDelay]=\"300\"\n (onLazyLoad)=\"onLazyLoad($event)\">\n <ng-template pTemplate=\"caption\">\n <div class=\"text-end\">\n <i class=\"fa fa-search mt-2 me-2\" aria-hidden=\"true\"></i>\n <input type=\"text\" [(ngModel)]=\"searchText\" pInputText size=\"50\" placeholder=\"Search feature flags...\" class=\"mw-90\" />\n </div>\n </ng-template>\n <ng-template pTemplate=\"header\">\n <tr>\n <th>Key</th>\n <th>Name</th>\n <th>Status</th>\n <th>Type</th>\n <th>Owner</th>\n <th>Expires</th>\n <th class=\"actions-list-two\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-flag>\n <tr>\n <td>{{ flag.key }}</td>\n <td>{{ flag.name }}</td>\n <td><span class=\"badge bg-info\">{{ flag.status || 'draft' }}</span></td>\n <td>{{ flag.flag_type || '-' }}</td>\n <td>{{ flag.owner || '-' }}</td>\n <td>{{ flag.expires_at ? (flag.expires_at | date:'dd-MMM-yyyy HH:mm') : '-' }}</td>\n <td>\n <ul class=\"list-unstyled list-inline list-action\">\n <li ngbTooltip=\"Edit\" class=\"me-2 me-sm-2\">\n <i class=\"fa fa-edit edit-icon\" (click)=\"navigateToEdit(flag)\" aria-hidden=\"true\"></i>\n </li>\n <li ngbTooltip=\"Rules\" class=\"me-2 me-sm-2\">\n <i class=\"fa fa-list-ul edit-icon\" (click)=\"navigateToRules(flag)\" aria-hidden=\"true\"></i>\n </li>\n <li ngbTooltip=\"Delete\" class=\"me-2 me-sm-2\">\n <i class=\"fa fa-trash delete-icon\" (click)=\"onDelete(flag)\" aria-hidden=\"true\"></i>\n </li>\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (totalRecords === 0) {\n <pw-no-data [withImage]=\"true\" [message]=\"'No feature flags found'\"></pw-no-data>\n }\n </div>\n</div>" }]
3075
+ args: [{ selector: 'pw-feature-flags-list', standalone: false, template: "<div class=\"row\" [class.custom-disable-wrapper]=\"buttonBusy\">\n <div class=\"col-12 d-flex flex-wrap justify-content-between align-items-center\">\n <h2 class=\"card-title p-0 float-start\">Feature Flags</h2>\n <a [routerLink]=\"[routers.featureFlagsDetails + 'add']\" class=\"btn btn-sm btn-outline-primary float-end\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i> {{ 'Label.AddNew' | transloco }} Feature Flag\n </a>\n </div>\n <div class=\"col-12 mb-3\">\n <p>Manage feature flags for controlled rollout, testing, and admin-driven enablement.</p>\n </div>\n</div>\n\n@if (!isLoaded) {\n<div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"></p-progressSpinner>\n</div>\n}\n\n<div class=\"row primeng-datatable-container mt-0\" [class.custom-disable-wrapper]=\"buttonBusy\">\n <div class=\"col-12 px-0\">\n <p-table\n [value]=\"featureFlags\"\n [paginator]=\"totalRecords !== 0\"\n [lazy]=\"true\"\n [rows]=\"PAGE_SIZE\"\n [totalRecords]=\"totalRecords\"\n [filterDelay]=\"300\"\n (onLazyLoad)=\"onLazyLoad($event)\">\n <ng-template pTemplate=\"caption\">\n <div class=\"text-end\">\n <i class=\"fa fa-search mt-2 me-2\" aria-hidden=\"true\"></i>\n <input type=\"text\" [(ngModel)]=\"searchText\" pInputText size=\"50\" placeholder=\"Search feature flags...\" class=\"mw-90\" />\n </div>\n </ng-template>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"col\">Key</th>\n <th scope=\"col\">Name</th>\n <th scope=\"col\">Status</th>\n <th scope=\"col\">Type</th>\n <th scope=\"col\">Owner</th>\n <th scope=\"col\">Expires</th>\n <th scope=\"col\" class=\"actions-list-two\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\" let-flag>\n <tr>\n <td>{{ flag.key }}</td>\n <td>{{ flag.name }}</td>\n <td><span class=\"badge bg-info\">{{ flag.status || 'draft' }}</span></td>\n <td>{{ flag.flag_type || '-' }}</td>\n <td>{{ flag.owner || '-' }}</td>\n <td>{{ flag.expires_at ? (flag.expires_at | date:'dd-MMM-yyyy HH:mm') : '-' }}</td>\n <td>\n <ul class=\"list-unstyled list-inline list-action\">\n <li ngbTooltip=\"Edit\" class=\"me-2 me-sm-2\">\n <button\n type=\"button\"\n class=\"btn p-0 border-0 bg-transparent\"\n aria-label=\"Edit feature flag\"\n (click)=\"navigateToEdit(flag)\">\n <i class=\"fa fa-edit edit-icon\"></i>\n </button>\n </li>\n <li ngbTooltip=\"Rules\" class=\"me-2 me-sm-2\">\n <button\n type=\"button\"\n class=\"btn p-0 border-0 bg-transparent\"\n aria-label=\"Manage feature flag rules\"\n (click)=\"navigateToRules(flag)\">\n <i class=\"fa fa-list-ul edit-icon\"></i>\n </button>\n </li>\n <li ngbTooltip=\"Delete\" class=\"me-2 me-sm-2\">\n <button\n type=\"button\"\n class=\"btn p-0 border-0 bg-transparent\"\n aria-label=\"Delete feature flag\"\n (click)=\"onDelete(flag)\">\n <i class=\"fa fa-trash delete-icon\"></i>\n </button>\n </li>\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (totalRecords === 0) {\n <pw-no-data [withImage]=\"true\" [message]=\"'No feature flags found'\"></pw-no-data>\n }\n </div>\n</div>" }]
3059
3076
  }], ctorParameters: () => [{ type: i0.Injector }, { type: i1.AdminService }] });
3060
3077
 
3061
3078
  class FeatureFlagsTabsComponent {
@@ -10372,62 +10389,40 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
10372
10389
  args: [{ selector: 'pw-users-information-sidebar', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<div class=\"users-information-sidebar\">\n <p class=\"users-information-sidebar__lead\">\n {{ 'Admin.Users.SidebarIntro.Lead' | transloco }}\n </p>\n <ul class=\"users-information-sidebar__list\">\n <li>{{ 'Admin.Users.SidebarIntro.FilterHint' | transloco }}</li>\n <li>{{ 'Admin.Users.SidebarIntro.SearchHint' | transloco }}</li>\n </ul>\n</div>\n", styles: [".users-information-sidebar{color:#333;padding:0 .25rem}.users-information-sidebar__lead{line-height:1.45;margin:0 0 1rem}.users-information-sidebar__list{line-height:1.45;margin:0;padding-left:1.15rem}\n"] }]
10373
10390
  }] });
10374
10391
 
10375
- class UserListComponent extends AppBaseComponent {
10376
- constructor(adminService, toaster, productService, injector, authService, cdr, windowService, sidebarService) {
10392
+ class UsersListBaseComponent extends AppBaseComponent {
10393
+ constructor(adminService, productService, injector, cdr, sidebarService) {
10377
10394
  super(injector);
10378
10395
  this.adminService = adminService;
10379
- this.toaster = toaster;
10380
10396
  this.productService = productService;
10381
- this.authService = authService;
10382
10397
  this.cdr = cdr;
10383
- this.windowService = windowService;
10384
10398
  this.sidebarService = sidebarService;
10385
10399
  this.page = 1;
10386
10400
  this.filterByProducts = [];
10387
10401
  this.filterByRoles = [];
10402
+ this.filterByFeatureKeys = [];
10403
+ this.filterByAlphaBeta = [];
10388
10404
  this.users = [];
10389
10405
  this.allUsers = [];
10390
10406
  this.loading = true;
10391
10407
  this.isLoaded = false;
10392
- this.searchOptions = [
10393
- {
10394
- label: 'Role',
10395
- value: 'role'
10396
- },
10397
- {
10398
- label: 'Product',
10399
- value: 'product'
10400
- },
10401
- {
10402
- label: 'Feature Key',
10403
- value: 'feature_key'
10404
- }
10405
- ];
10406
- this.searchText = '';
10407
10408
  this.searchDataSource = [];
10408
10409
  this.featureKeysList = [];
10409
- this.filterByFeatureKeys = [];
10410
10410
  this.criteria = [];
10411
- this.routers = ROUTERS;
10412
- this.masterProductId = this.appConfig.master_subscription.product_id;
10413
10411
  this.totalRecordsUnFiltered = 0;
10412
+ this.searchText = '';
10413
+ this.masterProductId = this.appConfig.master_subscription.product_id;
10414
+ this.searchOptions = [
10415
+ { label: 'Role', value: 'role' },
10416
+ { label: 'Product', value: 'product' },
10417
+ { label: 'Feature Key', value: 'feature_key' },
10418
+ { label: 'Alpha / Beta', value: 'alpha_beta' }
10419
+ ];
10420
+ this.alphaBetaOptions = [
10421
+ { label: 'Alpha', value: 'alpha' },
10422
+ { label: 'Beta', value: 'beta' }
10423
+ ];
10414
10424
  this.getTableState();
10415
10425
  }
10416
- ngOnInit() {
10417
- this.subscriptionId = PermissionService.selectedSubscription?.id;
10418
- this.chatPermission = `${PermissionService.selectedProduct?.permission}.${PermissionService.selectedProduct?.feature_key}`;
10419
- this.getRoles();
10420
- this.getProducts();
10421
- this.userStore().subscribe(response => {
10422
- this.currentUser = response;
10423
- this.cdr.markForCheck();
10424
- });
10425
- this.sidebarService.registerContent({
10426
- id: 'users-info',
10427
- title: 'Users Information',
10428
- component: UsersInformationSidebarComponent
10429
- });
10430
- }
10431
10426
  getTableState() {
10432
10427
  this.localStorage.getItem$('user-list-state').subscribe(result => {
10433
10428
  if (result) {
@@ -10456,20 +10451,21 @@ class UserListComponent extends AppBaseComponent {
10456
10451
  }
10457
10452
  }
10458
10453
  initializeCriteria(res) {
10459
- if (res?.selectedOption?.value === 'feature_key') {
10454
+ const val = res?.selectedOption?.value;
10455
+ if (val === 'feature_key')
10460
10456
  this.criteria = res?.filterByFeatureKeys ?? [];
10461
- }
10462
- if (res?.selectedOption?.value === 'product') {
10457
+ if (val === 'product')
10463
10458
  this.criteria = res?.filterByProducts ?? [];
10464
- }
10465
- if (res?.selectedOption?.value === 'role') {
10459
+ if (val === 'role')
10466
10460
  this.criteria = res?.filterByRoles ?? [];
10467
- }
10461
+ if (val === 'alpha_beta')
10462
+ this.criteria = res?.filterByAlphaBeta ?? [];
10468
10463
  }
10469
10464
  initializeFilters(res) {
10470
10465
  this.filterByFeatureKeys = res?.filterByFeatureKeys ?? [];
10471
10466
  this.filterByProducts = res?.filterByProducts ?? [];
10472
10467
  this.filterByRoles = res?.filterByRoles ?? [];
10468
+ this.filterByAlphaBeta = res?.filterByAlphaBeta ?? [];
10473
10469
  }
10474
10470
  onLazyLoad(event) {
10475
10471
  const pageDetails = HelperService.onTableLazyLoad(event);
@@ -10484,12 +10480,7 @@ class UserListComponent extends AppBaseComponent {
10484
10480
  }
10485
10481
  getRoles() {
10486
10482
  this.adminService.getRoles({}, this.subscriptionId).subscribe(response => {
10487
- this.allRoles = response.roles.map(item => {
10488
- return {
10489
- label: item.name,
10490
- value: item.id
10491
- };
10492
- });
10483
+ this.allRoles = response.roles.map(item => ({ label: item.name, value: item.id }));
10493
10484
  this.cdr.markForCheck();
10494
10485
  });
10495
10486
  }
@@ -10501,22 +10492,15 @@ class UserListComponent extends AppBaseComponent {
10501
10492
  })
10502
10493
  .subscribe(resp => {
10503
10494
  if (resp.products) {
10504
- this.productList = resp.products.map(element => {
10505
- return {
10506
- value: element.id,
10507
- label: element.name ?? ''
10508
- };
10509
- });
10510
- this.featureKeysList = resp.products.map(element => {
10511
- return {
10512
- value: element.feature_key,
10513
- label: element.feature_key ?? ''
10514
- };
10515
- });
10516
- this.productList.unshift({
10517
- label: 'None',
10518
- value: null
10519
- });
10495
+ this.productList = resp.products.map(e => ({
10496
+ value: e.id,
10497
+ label: e.name ?? ''
10498
+ }));
10499
+ this.featureKeysList = resp.products.map(e => ({
10500
+ value: e.feature_key,
10501
+ label: e.feature_key ?? ''
10502
+ }));
10503
+ this.productList.unshift({ label: 'None', value: null });
10520
10504
  }
10521
10505
  this.cdr.markForCheck();
10522
10506
  });
@@ -10529,6 +10513,10 @@ class UserListComponent extends AppBaseComponent {
10529
10513
  feature_keys: this.filterByFeatureKeys.join() || '',
10530
10514
  subscription_id: this.subscriptionId
10531
10515
  };
10516
+ if (this.filterByAlphaBeta.includes('alpha'))
10517
+ params.alpha = true;
10518
+ if (this.filterByAlphaBeta.includes('beta'))
10519
+ params.beta = true;
10532
10520
  this.adminService.getUsers(paging, params).subscribe(response => {
10533
10521
  this.users = response.users;
10534
10522
  this.allUsers = [...this.users];
@@ -10539,70 +10527,86 @@ class UserListComponent extends AppBaseComponent {
10539
10527
  this.cdr.markForCheck();
10540
10528
  });
10541
10529
  }
10530
+ }
10531
+
10532
+ class UserListComponent extends UsersListBaseComponent {
10533
+ constructor(adminService, toaster, productService, injector, authService, cdr, windowService, sidebarService) {
10534
+ super(adminService, productService, injector, cdr, sidebarService);
10535
+ this.toaster = toaster;
10536
+ this.authService = authService;
10537
+ this.windowService = windowService;
10538
+ this.routers = ROUTERS;
10539
+ }
10540
+ ngOnInit() {
10541
+ this.subscriptionId = PermissionService.selectedSubscription?.id;
10542
+ this.chatPermission = `${PermissionService.selectedProduct?.permission}.${PermissionService.selectedProduct?.feature_key}`;
10543
+ this.getRoles();
10544
+ this.getProducts();
10545
+ this.userStore().subscribe(response => {
10546
+ this.currentUser = response;
10547
+ this.cdr.markForCheck();
10548
+ });
10549
+ this.sidebarService.registerContent({
10550
+ id: 'users-info',
10551
+ title: 'Users Information',
10552
+ component: UsersInformationSidebarComponent
10553
+ });
10554
+ }
10542
10555
  onSearchOptionChange($event) {
10543
10556
  this.criteria = [];
10544
10557
  this.selectedOption = this.searchOptions.find(x => x.value === $event.value[0]);
10545
- if (this.selectedOption && this.selectedOption.value === 'role') {
10558
+ if (this.selectedOption?.value === 'role')
10546
10559
  this.searchDataSource = this.allRoles;
10547
- }
10548
- else if (this.selectedOption && this.selectedOption.value === 'product') {
10560
+ else if (this.selectedOption?.value === 'product')
10549
10561
  this.searchDataSource = this.productList;
10550
- }
10551
- else if (this.selectedOption && this.selectedOption.value === 'feature_key') {
10562
+ else if (this.selectedOption?.value === 'feature_key')
10552
10563
  this.searchDataSource = this.featureKeysList;
10553
- }
10564
+ else if (this.selectedOption?.value === 'alpha_beta')
10565
+ this.searchDataSource = this.alphaBetaOptions;
10554
10566
  else {
10555
10567
  this.searchDataSource = [];
10556
10568
  this.clearFilters();
10557
- this.getUsers({
10558
- page: this.page,
10559
- page_size: PAGE_SIZE
10560
- });
10569
+ this.getUsers({ page: this.page, page_size: PAGE_SIZE });
10561
10570
  }
10562
10571
  }
10563
10572
  clearFilters() {
10564
10573
  this.filterByProducts = [];
10565
10574
  this.filterByFeatureKeys = [];
10566
10575
  this.filterByRoles = [];
10576
+ this.filterByAlphaBeta = [];
10567
10577
  }
10568
10578
  onSearchCriteria(evt) {
10569
10579
  this.clearFilters();
10570
- if (this.selectedOption.value === 'role') {
10580
+ if (this.selectedOption.value === 'role')
10571
10581
  this.onRoleChange(evt);
10572
- }
10573
- else if (this.selectedOption.value === 'product') {
10582
+ else if (this.selectedOption.value === 'product')
10574
10583
  this.onProductChange(evt);
10575
- }
10576
- else if (this.selectedOption.value === 'feature_key') {
10584
+ else if (this.selectedOption.value === 'feature_key')
10577
10585
  this.onFeatureKeyChange(evt);
10578
- }
10579
- else {
10586
+ else if (this.selectedOption.value === 'alpha_beta')
10587
+ this.onAlphaBetaChange(evt);
10588
+ else
10580
10589
  this.searchDataSource = [];
10581
- }
10582
10590
  }
10583
10591
  onRoleChange(event) {
10584
10592
  this.clearFilters();
10585
10593
  this.filterByRoles = event.value;
10586
- this.getUsers({
10587
- page: this.page,
10588
- page_size: PAGE_SIZE
10589
- });
10594
+ this.getUsers({ page: this.page, page_size: PAGE_SIZE });
10590
10595
  }
10591
10596
  onProductChange(event) {
10592
10597
  this.clearFilters();
10593
10598
  this.filterByProducts = event.value;
10594
- this.getUsers({
10595
- page: this.page,
10596
- page_size: PAGE_SIZE
10597
- });
10599
+ this.getUsers({ page: this.page, page_size: PAGE_SIZE });
10598
10600
  }
10599
10601
  onFeatureKeyChange(event) {
10600
10602
  this.clearFilters();
10601
10603
  this.filterByFeatureKeys = event.value;
10602
- this.getUsers({
10603
- page: this.page,
10604
- page_size: PAGE_SIZE
10605
- });
10604
+ this.getUsers({ page: this.page, page_size: PAGE_SIZE });
10605
+ }
10606
+ onAlphaBetaChange(event) {
10607
+ this.clearFilters();
10608
+ this.filterByAlphaBeta = event.value;
10609
+ this.getUsers({ page: this.page, page_size: PAGE_SIZE });
10606
10610
  }
10607
10611
  onDelete(user) {
10608
10612
  this.userToDelete = user;
@@ -10614,11 +10618,7 @@ class UserListComponent extends AppBaseComponent {
10614
10618
  .subscribe(() => {
10615
10619
  this.users = this.users.filter(x => x.id !== this.userToDelete.id);
10616
10620
  this.toaster.success(this.translation.translate('Admin.Users.DeletedMessage'));
10617
- this.getUsers({
10618
- page: this.page,
10619
- page_size: PAGE_SIZE,
10620
- search: this.searchText
10621
- });
10621
+ this.getUsers({ page: this.page, page_size: PAGE_SIZE, search: this.searchText });
10622
10622
  this.cdr.markForCheck();
10623
10623
  })
10624
10624
  .add(() => {
@@ -10641,10 +10641,7 @@ class UserListComponent extends AppBaseComponent {
10641
10641
  })
10642
10642
  .subscribe(_ => {
10643
10643
  this.toast.success(`You're now being logged in as another user...`);
10644
- // wait for 2 sec before redirecting user to home page
10645
- setTimeout(() => {
10646
- this.windowService.replaceUrl('/home');
10647
- }, 2000);
10644
+ setTimeout(() => this.windowService.replaceUrl('/home'), 2000);
10648
10645
  this.cdr.markForCheck();
10649
10646
  });
10650
10647
  this.cdr.markForCheck();
@@ -10657,6 +10654,7 @@ class UserListComponent extends AppBaseComponent {
10657
10654
  filterByFeatureKeys: this.filterByFeatureKeys,
10658
10655
  filterByRoles: this.filterByRoles,
10659
10656
  filterByProducts: this.filterByProducts,
10657
+ filterByAlphaBeta: this.filterByAlphaBeta,
10660
10658
  selectedOption: this.selectedOption,
10661
10659
  searchDataSource: this.searchDataSource
10662
10660
  };