@posiwise/admin-module 0.0.203 → 0.0.204

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.
@@ -172,6 +172,9 @@ const ROUTERS = {
172
172
  loginNotifications: `${baseUrl}/login-notifications/`,
173
173
  incidentConfig: `${baseUrl}/incident/list/`,
174
174
  incidentDetails: `${baseUrl}/incident/`,
175
+ featureFlagsConfig: `${baseUrl}/feature-flags/list/`,
176
+ featureFlagsDetails: `${baseUrl}/feature-flags/`,
177
+ featureFlagRules: `${baseUrl}/feature-flags/rules/`,
175
178
  faqConfig: `${baseUrl}/faq/list/`,
176
179
  faqDetails: `${baseUrl}/faq/`,
177
180
  inviteUsers: `${baseUrl}/subscriptions/invite-user/`,
@@ -352,11 +355,11 @@ class ContactUsListComponent extends AppBaseComponent {
352
355
  super.ngOnDestroy();
353
356
  }
354
357
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ContactUsListComponent, deps: [{ token: i0.Injector }, { token: i1.AdminService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
355
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: ContactUsListComponent, isStandalone: false, selector: "pw-contact-us-list", usesInheritance: true, ngImport: i0, template: "<div class=\"row\">\n <div class=\"col-12 d-flex justify-content-between align-items-center text-end\">\n <h2 class=\"card-title p-0 float-start\">Contact Us</h2>\n </div>\n <div class=\"col-12 mb-3\">\n <p>The <strong>Contact US</strong> module shows all submissions from the contact forms embedded on select landing pages.<br/>\n It\u2019s your central hub to track and follow up with interested users or potential leads.</p>\n</div>\n</div>\n@if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n}\n<div class=\"primeng-datatable-container table-responsive mt-0\"\n [class.hideTable]=\"data.unfiltered_count === 0\">\n <p-table #tt\n [value]=\"data.contact_request\"\n [paginator]=\"data.object_count !== 0\"\n [rows]=\"PAGE_SIZE\"\n [totalRecords]=\"data.object_count\"\n [loading]=\"loading\"\n [lazy]=\"true\"\n [filterDelay]=\"1000\"\n (onLazyLoad)=\"onLazyLoad($event)\"\n [customSort]=\"true\">\n <!--sort order should be default empty when page load-->\n\n <!-- Caption Header, Search Bar -->\n <ng-template pTemplate=\"caption\">\n <div class=\"search-contact\">\n <div class=\"col-12 col-sm-3\">\n <p-select\n [options]=\"[\n { label: 'Select status', value: null },\n { label: 'Open', value: false },\n { label: 'Closed', value: true }\n ]\"\n placeholder=\"Select status\"\n (onChange)=\"filterClosed($event.value)\">\n </p-select>\n </div>\n <div class=\"text-end ms-auto\">\n <i class=\"fa fa-search mt-2 me-2\" aria-hidden=\"true\"></i>\n <label for=\"contact-us-list-search\" class=\"visually-hidden\">Search</label>\n <input type=\"text\"\n id=\"contact-us-list-search\"\n name=\"contact-us-list-search\"\n pInputText\n size=\"50\"\n placeholder=\"Search\"\n [(ngModel)]=\"searchText\"\n (input)=\"tt.filterGlobal($event.target.value, 'contains')\" />\n </div>\n </div>\n </ng-template>\n\n <!-- Column Header -->\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\"\n pSortableColumn=\"created_at\">\n {{ 'Admin.ContactUs.CreatedAt' | transloco }}\n <p-sortIcon field=\"created_at\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"name\">\n {{ 'Label.Name' | transloco }}\n <p-sortIcon field=\"name\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"email\">\n {{ 'Label.Email' | transloco }}\n <p-sortIcon field=\"email\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"subject\">\n {{ 'Admin.ContactUs.Subject' | transloco }}\n <p-sortIcon field=\"subject\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"message\">\n {{ 'Admin.ContactUs.Message' | transloco }}\n <p-sortIcon field=\"message\"></p-sortIcon>\n </th>\n <th class=\"actions-list-two\"\n scope=\"true\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n\n <!-- Table Body -->\n <ng-template pTemplate=\"body\"\n let-item>\n <tr>\n <td data-head=\"created_at\">{{ item?.created_at | dateFormat }}</td>\n <td data-head=\"name\">{{ item?.name }}</td>\n <td data-head=\"email\">\n <a href=\"mailto:{{ item?.email }}\">{{ item?.email }}</a>\n </td>\n <td data-head=\"subject\">{{ item?.subject }}</td>\n <td data-head=\"message\">\n <span\n [ngbTooltip]=\"item?.message\"\n container=\"body\"\n tooltipClass=\"custom-tooltip\"\n placement=\"bottom\"\n >\n {{ item?.message | textTruncate: 200 }}\n </span>\n </td>\n <td data-head=\"Action\">\n <ul class=\"list-unstyled list-inline list-action\">\n @if (!item.closed) {\n <li\n ngbTooltip=\"Close\"\n class=\"me-2 me-sm-3\"\n (keydown.enter)=\"toggleRecord(item.id, true)\"\n (click)=\"toggleRecord(item.id, true)\">\n <i class=\"fa fa-times delete-icon\" aria-hidden=\"true\"></i>\n </li>\n }\n @if (item.closed) {\n <li\n ngbTooltip=\"Re Open\"\n class=\"me-2 me-sm-3\"\n (keydown.enter)=\"onKeyDown($event, item.id)\"\n (click)=\"toggleRecord(item.id, false)\">\n <i class=\"fa fa-retweet edit-icon\" aria-hidden=\"true\"></i>\n </li>\n }\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (data.object_count === 0 && data.unfiltered_count !== 0) {\n <div>\n <pw-no-data [withImage]=\"true\" [message]=\"'Search.NoDataMessage' | transloco\" [description]=\"'Search.NoDataDescription' | transloco\" >\n </pw-no-data>\n </div>\n }\n @if (data.object_count !== 0) {\n <span class=\"total-records-count\" >Total: {{ data.object_count }}</span>\n }\n</div>\n@if (data.unfiltered_count === 0 && isLoaded) {\n <div>\n <pw-no-data [withImage]=\"true\" message=\"No Contact Requests\"> </pw-no-data>\n </div>\n}\n", styles: [".search-contact{display:flex;justify-content:space-between}@media(min-width:320px)and (max-width:720px){.search-contact{display:block}}\n"], 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: i2.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i2.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { 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: 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: "pipe", type: i11.TranslocoPipe, name: "transloco" }, { kind: "pipe", type: i15.DateFormatPipe, name: "dateFormat" }, { kind: "pipe", type: i15.TextTruncatePipe, name: "textTruncate" }] }); }
358
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: ContactUsListComponent, isStandalone: false, selector: "pw-contact-us-list", usesInheritance: true, ngImport: i0, template: "<div class=\"row\">\n <div class=\"col-12 d-flex justify-content-between align-items-center text-end\">\n <h2 class=\"card-title p-0 float-start\">Contact Us</h2>\n </div>\n <div class=\"col-12 mb-3\">\n <p>The <strong>Contact US</strong> module shows all submissions from the contact forms embedded on select landing pages.<br/>\n It\u2019s your central hub to track and follow up with interested users or potential leads.</p>\n</div>\n</div>\n@if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n}\n<div class=\"primeng-datatable-container table-responsive mt-0\"\n [class.hideTable]=\"data.unfiltered_count === 0\">\n <p-table #tt\n [value]=\"data.contact_request\"\n [paginator]=\"data.object_count !== 0\"\n [rows]=\"PAGE_SIZE\"\n [totalRecords]=\"data.object_count\"\n [loading]=\"loading\"\n [lazy]=\"true\"\n [filterDelay]=\"1000\"\n (onLazyLoad)=\"onLazyLoad($event)\"\n [customSort]=\"true\">\n <!--sort order should be default empty when page load-->\n\n <!-- Caption Header, Search Bar -->\n <ng-template pTemplate=\"caption\">\n <div class=\"search-contact\">\n <div class=\"col-12 col-sm-3\">\n <p-select\n [options]=\"[\n { label: 'Select status', value: null },\n { label: 'Open', value: false },\n { label: 'Closed', value: true }\n ]\"\n placeholder=\"Select status\"\n (onChange)=\"filterClosed($event.value)\"\n appendTo=\"body\">\n </p-select>\n </div>\n <div class=\"text-end ms-auto\">\n <i class=\"fa fa-search mt-2 me-2\" aria-hidden=\"true\"></i>\n <label for=\"contact-us-list-search\" class=\"visually-hidden\">Search</label>\n <input type=\"text\"\n id=\"contact-us-list-search\"\n name=\"contact-us-list-search\"\n pInputText\n size=\"50\"\n placeholder=\"Search\"\n [(ngModel)]=\"searchText\"\n (input)=\"tt.filterGlobal($event.target.value, 'contains')\" />\n </div>\n </div>\n </ng-template>\n\n <!-- Column Header -->\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\"\n pSortableColumn=\"created_at\">\n {{ 'Admin.ContactUs.CreatedAt' | transloco }}\n <p-sortIcon field=\"created_at\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"name\">\n {{ 'Label.Name' | transloco }}\n <p-sortIcon field=\"name\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"email\">\n {{ 'Label.Email' | transloco }}\n <p-sortIcon field=\"email\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"subject\">\n {{ 'Admin.ContactUs.Subject' | transloco }}\n <p-sortIcon field=\"subject\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"message\">\n {{ 'Admin.ContactUs.Message' | transloco }}\n <p-sortIcon field=\"message\"></p-sortIcon>\n </th>\n <th class=\"actions-list-two\"\n scope=\"true\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n\n <!-- Table Body -->\n <ng-template pTemplate=\"body\"\n let-item>\n <tr>\n <td data-head=\"created_at\">{{ item?.created_at | dateFormat }}</td>\n <td data-head=\"name\">{{ item?.name }}</td>\n <td data-head=\"email\">\n <a href=\"mailto:{{ item?.email }}\">{{ item?.email }}</a>\n </td>\n <td data-head=\"subject\">{{ item?.subject }}</td>\n <td data-head=\"message\">\n <span\n [ngbTooltip]=\"item?.message\"\n container=\"body\"\n tooltipClass=\"custom-tooltip\"\n placement=\"bottom\"\n >\n {{ item?.message | textTruncate: 200 }}\n </span>\n </td>\n <td data-head=\"Action\">\n <ul class=\"list-unstyled list-inline list-action\">\n @if (!item.closed) {\n <li\n ngbTooltip=\"Close\"\n class=\"me-2 me-sm-3\"\n (keydown.enter)=\"toggleRecord(item.id, true)\"\n (click)=\"toggleRecord(item.id, true)\">\n <i class=\"fa fa-times delete-icon\" aria-hidden=\"true\"></i>\n </li>\n }\n @if (item.closed) {\n <li\n ngbTooltip=\"Re Open\"\n class=\"me-2 me-sm-3\"\n (keydown.enter)=\"onKeyDown($event, item.id)\"\n (click)=\"toggleRecord(item.id, false)\">\n <i class=\"fa fa-retweet edit-icon\" aria-hidden=\"true\"></i>\n </li>\n }\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (data.object_count === 0 && data.unfiltered_count !== 0) {\n <div>\n <pw-no-data [withImage]=\"true\" [message]=\"'Search.NoDataMessage' | transloco\" [description]=\"'Search.NoDataDescription' | transloco\" >\n </pw-no-data>\n </div>\n }\n @if (data.object_count !== 0) {\n <span class=\"total-records-count\" >Total: {{ data.object_count }}</span>\n }\n</div>\n@if (data.unfiltered_count === 0 && isLoaded) {\n <div>\n <pw-no-data [withImage]=\"true\" message=\"No Contact Requests\"> </pw-no-data>\n </div>\n}\n", styles: [".search-contact{display:flex;justify-content:space-between}@media(min-width:320px)and (max-width:720px){.search-contact{display:block}}\n"], 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: i2.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i2.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { 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: 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: "pipe", type: i11.TranslocoPipe, name: "transloco" }, { kind: "pipe", type: i15.DateFormatPipe, name: "dateFormat" }, { kind: "pipe", type: i15.TextTruncatePipe, name: "textTruncate" }] }); }
356
359
  }
357
360
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ContactUsListComponent, decorators: [{
358
361
  type: Component,
359
- args: [{ selector: 'pw-contact-us-list', standalone: false, template: "<div class=\"row\">\n <div class=\"col-12 d-flex justify-content-between align-items-center text-end\">\n <h2 class=\"card-title p-0 float-start\">Contact Us</h2>\n </div>\n <div class=\"col-12 mb-3\">\n <p>The <strong>Contact US</strong> module shows all submissions from the contact forms embedded on select landing pages.<br/>\n It\u2019s your central hub to track and follow up with interested users or potential leads.</p>\n</div>\n</div>\n@if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n}\n<div class=\"primeng-datatable-container table-responsive mt-0\"\n [class.hideTable]=\"data.unfiltered_count === 0\">\n <p-table #tt\n [value]=\"data.contact_request\"\n [paginator]=\"data.object_count !== 0\"\n [rows]=\"PAGE_SIZE\"\n [totalRecords]=\"data.object_count\"\n [loading]=\"loading\"\n [lazy]=\"true\"\n [filterDelay]=\"1000\"\n (onLazyLoad)=\"onLazyLoad($event)\"\n [customSort]=\"true\">\n <!--sort order should be default empty when page load-->\n\n <!-- Caption Header, Search Bar -->\n <ng-template pTemplate=\"caption\">\n <div class=\"search-contact\">\n <div class=\"col-12 col-sm-3\">\n <p-select\n [options]=\"[\n { label: 'Select status', value: null },\n { label: 'Open', value: false },\n { label: 'Closed', value: true }\n ]\"\n placeholder=\"Select status\"\n (onChange)=\"filterClosed($event.value)\">\n </p-select>\n </div>\n <div class=\"text-end ms-auto\">\n <i class=\"fa fa-search mt-2 me-2\" aria-hidden=\"true\"></i>\n <label for=\"contact-us-list-search\" class=\"visually-hidden\">Search</label>\n <input type=\"text\"\n id=\"contact-us-list-search\"\n name=\"contact-us-list-search\"\n pInputText\n size=\"50\"\n placeholder=\"Search\"\n [(ngModel)]=\"searchText\"\n (input)=\"tt.filterGlobal($event.target.value, 'contains')\" />\n </div>\n </div>\n </ng-template>\n\n <!-- Column Header -->\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\"\n pSortableColumn=\"created_at\">\n {{ 'Admin.ContactUs.CreatedAt' | transloco }}\n <p-sortIcon field=\"created_at\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"name\">\n {{ 'Label.Name' | transloco }}\n <p-sortIcon field=\"name\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"email\">\n {{ 'Label.Email' | transloco }}\n <p-sortIcon field=\"email\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"subject\">\n {{ 'Admin.ContactUs.Subject' | transloco }}\n <p-sortIcon field=\"subject\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"message\">\n {{ 'Admin.ContactUs.Message' | transloco }}\n <p-sortIcon field=\"message\"></p-sortIcon>\n </th>\n <th class=\"actions-list-two\"\n scope=\"true\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n\n <!-- Table Body -->\n <ng-template pTemplate=\"body\"\n let-item>\n <tr>\n <td data-head=\"created_at\">{{ item?.created_at | dateFormat }}</td>\n <td data-head=\"name\">{{ item?.name }}</td>\n <td data-head=\"email\">\n <a href=\"mailto:{{ item?.email }}\">{{ item?.email }}</a>\n </td>\n <td data-head=\"subject\">{{ item?.subject }}</td>\n <td data-head=\"message\">\n <span\n [ngbTooltip]=\"item?.message\"\n container=\"body\"\n tooltipClass=\"custom-tooltip\"\n placement=\"bottom\"\n >\n {{ item?.message | textTruncate: 200 }}\n </span>\n </td>\n <td data-head=\"Action\">\n <ul class=\"list-unstyled list-inline list-action\">\n @if (!item.closed) {\n <li\n ngbTooltip=\"Close\"\n class=\"me-2 me-sm-3\"\n (keydown.enter)=\"toggleRecord(item.id, true)\"\n (click)=\"toggleRecord(item.id, true)\">\n <i class=\"fa fa-times delete-icon\" aria-hidden=\"true\"></i>\n </li>\n }\n @if (item.closed) {\n <li\n ngbTooltip=\"Re Open\"\n class=\"me-2 me-sm-3\"\n (keydown.enter)=\"onKeyDown($event, item.id)\"\n (click)=\"toggleRecord(item.id, false)\">\n <i class=\"fa fa-retweet edit-icon\" aria-hidden=\"true\"></i>\n </li>\n }\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (data.object_count === 0 && data.unfiltered_count !== 0) {\n <div>\n <pw-no-data [withImage]=\"true\" [message]=\"'Search.NoDataMessage' | transloco\" [description]=\"'Search.NoDataDescription' | transloco\" >\n </pw-no-data>\n </div>\n }\n @if (data.object_count !== 0) {\n <span class=\"total-records-count\" >Total: {{ data.object_count }}</span>\n }\n</div>\n@if (data.unfiltered_count === 0 && isLoaded) {\n <div>\n <pw-no-data [withImage]=\"true\" message=\"No Contact Requests\"> </pw-no-data>\n </div>\n}\n", styles: [".search-contact{display:flex;justify-content:space-between}@media(min-width:320px)and (max-width:720px){.search-contact{display:block}}\n"] }]
362
+ args: [{ selector: 'pw-contact-us-list', standalone: false, template: "<div class=\"row\">\n <div class=\"col-12 d-flex justify-content-between align-items-center text-end\">\n <h2 class=\"card-title p-0 float-start\">Contact Us</h2>\n </div>\n <div class=\"col-12 mb-3\">\n <p>The <strong>Contact US</strong> module shows all submissions from the contact forms embedded on select landing pages.<br/>\n It\u2019s your central hub to track and follow up with interested users or potential leads.</p>\n</div>\n</div>\n@if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n}\n<div class=\"primeng-datatable-container table-responsive mt-0\"\n [class.hideTable]=\"data.unfiltered_count === 0\">\n <p-table #tt\n [value]=\"data.contact_request\"\n [paginator]=\"data.object_count !== 0\"\n [rows]=\"PAGE_SIZE\"\n [totalRecords]=\"data.object_count\"\n [loading]=\"loading\"\n [lazy]=\"true\"\n [filterDelay]=\"1000\"\n (onLazyLoad)=\"onLazyLoad($event)\"\n [customSort]=\"true\">\n <!--sort order should be default empty when page load-->\n\n <!-- Caption Header, Search Bar -->\n <ng-template pTemplate=\"caption\">\n <div class=\"search-contact\">\n <div class=\"col-12 col-sm-3\">\n <p-select\n [options]=\"[\n { label: 'Select status', value: null },\n { label: 'Open', value: false },\n { label: 'Closed', value: true }\n ]\"\n placeholder=\"Select status\"\n (onChange)=\"filterClosed($event.value)\"\n appendTo=\"body\">\n </p-select>\n </div>\n <div class=\"text-end ms-auto\">\n <i class=\"fa fa-search mt-2 me-2\" aria-hidden=\"true\"></i>\n <label for=\"contact-us-list-search\" class=\"visually-hidden\">Search</label>\n <input type=\"text\"\n id=\"contact-us-list-search\"\n name=\"contact-us-list-search\"\n pInputText\n size=\"50\"\n placeholder=\"Search\"\n [(ngModel)]=\"searchText\"\n (input)=\"tt.filterGlobal($event.target.value, 'contains')\" />\n </div>\n </div>\n </ng-template>\n\n <!-- Column Header -->\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\"\n pSortableColumn=\"created_at\">\n {{ 'Admin.ContactUs.CreatedAt' | transloco }}\n <p-sortIcon field=\"created_at\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"name\">\n {{ 'Label.Name' | transloco }}\n <p-sortIcon field=\"name\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"email\">\n {{ 'Label.Email' | transloco }}\n <p-sortIcon field=\"email\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"subject\">\n {{ 'Admin.ContactUs.Subject' | transloco }}\n <p-sortIcon field=\"subject\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"message\">\n {{ 'Admin.ContactUs.Message' | transloco }}\n <p-sortIcon field=\"message\"></p-sortIcon>\n </th>\n <th class=\"actions-list-two\"\n scope=\"true\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n\n <!-- Table Body -->\n <ng-template pTemplate=\"body\"\n let-item>\n <tr>\n <td data-head=\"created_at\">{{ item?.created_at | dateFormat }}</td>\n <td data-head=\"name\">{{ item?.name }}</td>\n <td data-head=\"email\">\n <a href=\"mailto:{{ item?.email }}\">{{ item?.email }}</a>\n </td>\n <td data-head=\"subject\">{{ item?.subject }}</td>\n <td data-head=\"message\">\n <span\n [ngbTooltip]=\"item?.message\"\n container=\"body\"\n tooltipClass=\"custom-tooltip\"\n placement=\"bottom\"\n >\n {{ item?.message | textTruncate: 200 }}\n </span>\n </td>\n <td data-head=\"Action\">\n <ul class=\"list-unstyled list-inline list-action\">\n @if (!item.closed) {\n <li\n ngbTooltip=\"Close\"\n class=\"me-2 me-sm-3\"\n (keydown.enter)=\"toggleRecord(item.id, true)\"\n (click)=\"toggleRecord(item.id, true)\">\n <i class=\"fa fa-times delete-icon\" aria-hidden=\"true\"></i>\n </li>\n }\n @if (item.closed) {\n <li\n ngbTooltip=\"Re Open\"\n class=\"me-2 me-sm-3\"\n (keydown.enter)=\"onKeyDown($event, item.id)\"\n (click)=\"toggleRecord(item.id, false)\">\n <i class=\"fa fa-retweet edit-icon\" aria-hidden=\"true\"></i>\n </li>\n }\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (data.object_count === 0 && data.unfiltered_count !== 0) {\n <div>\n <pw-no-data [withImage]=\"true\" [message]=\"'Search.NoDataMessage' | transloco\" [description]=\"'Search.NoDataDescription' | transloco\" >\n </pw-no-data>\n </div>\n }\n @if (data.object_count !== 0) {\n <span class=\"total-records-count\" >Total: {{ data.object_count }}</span>\n }\n</div>\n@if (data.unfiltered_count === 0 && isLoaded) {\n <div>\n <pw-no-data [withImage]=\"true\" message=\"No Contact Requests\"> </pw-no-data>\n </div>\n}\n", styles: [".search-contact{display:flex;justify-content:space-between}@media(min-width:320px)and (max-width:720px){.search-contact{display:block}}\n"] }]
360
363
  }], ctorParameters: () => [{ type: i0.Injector }, { type: i1.AdminService }, { type: i0.ChangeDetectorRef }] });
361
364
 
362
365
  class ContactUsTabsComponent {
@@ -2713,6 +2716,371 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
2713
2716
  }]
2714
2717
  }] });
2715
2718
 
2719
+ class FeatureFlagDetailsComponent extends AppBaseComponent {
2720
+ constructor(injector, adminService) {
2721
+ super(injector);
2722
+ this.adminService = adminService;
2723
+ this.form = AppAdmin.getFeatureFlagForm();
2724
+ this.routers = ROUTERS;
2725
+ this.id = 0;
2726
+ this.isLoading = true;
2727
+ this.submitted = false;
2728
+ this.buttonBusy = false;
2729
+ this.flagTypeOptions = [];
2730
+ this.statusOptions = [];
2731
+ this.allUsers = [];
2732
+ this.filteredUsers = [];
2733
+ }
2734
+ ngOnInit() {
2735
+ this.subscriptionId = PermissionService.selectedSubscription?.id;
2736
+ this.loadSupportedOptions();
2737
+ this.loadOwners();
2738
+ this.route.params.subscribe(params => {
2739
+ this.id = +params['id'] || 0;
2740
+ if (this.id) {
2741
+ this.getFeatureFlag();
2742
+ }
2743
+ else {
2744
+ this.isLoading = false;
2745
+ }
2746
+ });
2747
+ }
2748
+ loadSupportedOptions() {
2749
+ this.adminService.getSupportedFeatureFlagOptions().subscribe(response => {
2750
+ this.flagTypeOptions = (response.flag_types || []).map(option => ({
2751
+ label: option,
2752
+ value: option
2753
+ }));
2754
+ this.statusOptions = (response.statuses || []).map(option => ({
2755
+ label: option,
2756
+ value: option
2757
+ }));
2758
+ });
2759
+ }
2760
+ loadOwners() {
2761
+ this.adminService
2762
+ .getUsers({}, { subscription_id: this.subscriptionId })
2763
+ .subscribe(response => {
2764
+ this.allUsers = response.users || [];
2765
+ this.allUsers.forEach(user => {
2766
+ const firstName = user.first_name ?? '';
2767
+ const lastName = user.last_name ?? '';
2768
+ user.displayName = `${firstName} ${lastName} ${user.email}`.trim();
2769
+ });
2770
+ });
2771
+ }
2772
+ searchOwners(event) {
2773
+ const query = event.query?.toLowerCase() || '';
2774
+ this.filteredUsers = !query
2775
+ ? [...this.allUsers]
2776
+ : this.allUsers.filter(user => user.displayName.toLowerCase().includes(query));
2777
+ }
2778
+ get f() {
2779
+ return this.form.controls;
2780
+ }
2781
+ getFeatureFlag() {
2782
+ this.adminService.getFeatureFlagById(this.id).subscribe({
2783
+ next: response => {
2784
+ this.form.patchValue({
2785
+ id: response.id,
2786
+ key: response.key,
2787
+ name: response.name,
2788
+ description: response.description,
2789
+ flag_type: response.flag_type,
2790
+ status: response.status,
2791
+ owner: this.allUsers.find(user => user.email === response.owner) || response.owner,
2792
+ expires_at: response.expires_at ? new Date(response.expires_at) : null
2793
+ });
2794
+ },
2795
+ complete: () => {
2796
+ this.isLoading = false;
2797
+ }
2798
+ });
2799
+ }
2800
+ onSubmit() {
2801
+ this.form.markAllAsTouched();
2802
+ this.submitted = true;
2803
+ if (!this.form.valid) {
2804
+ return;
2805
+ }
2806
+ this.buttonBusy = true;
2807
+ const formValue = this.form.value;
2808
+ const payload = {
2809
+ ...formValue,
2810
+ owner: typeof formValue.owner === 'string' ? formValue.owner : formValue.owner?.email
2811
+ };
2812
+ const request$ = this.id
2813
+ ? this.adminService.updateFeatureFlag(this.id, payload)
2814
+ : this.adminService.createFeatureFlag(payload);
2815
+ request$.subscribe({
2816
+ next: () => {
2817
+ this.toast.success(this.id
2818
+ ? 'Feature flag updated successfully.'
2819
+ : 'Feature flag created successfully.');
2820
+ this.router.navigate([this.routers.featureFlagsConfig]);
2821
+ },
2822
+ complete: () => {
2823
+ this.buttonBusy = false;
2824
+ }
2825
+ });
2826
+ }
2827
+ onCancel() {
2828
+ this.router.navigate([this.routers.featureFlagsConfig]);
2829
+ }
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" }] }); }
2832
+ }
2833
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FeatureFlagDetailsComponent, decorators: [{
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>" }]
2836
+ }], ctorParameters: () => [{ type: i0.Injector }, { type: i1.AdminService }] });
2837
+
2838
+ class FeatureFlagRulesComponent extends AppBaseComponent {
2839
+ constructor(injector, adminService) {
2840
+ super(injector);
2841
+ this.adminService = adminService;
2842
+ this.routers = ROUTERS;
2843
+ this.ruleForm = AppAdmin.getFeatureFlagRuleForm();
2844
+ this.featureFlagId = 0;
2845
+ this.featureFlagName = '';
2846
+ this.isLoading = true;
2847
+ this.ruleSubmitted = false;
2848
+ this.ruleButtonBusy = false;
2849
+ this.rules = [];
2850
+ this.editingRuleId = null;
2851
+ this.targetTypeOptions = [];
2852
+ this.environmentOptions = [];
2853
+ this.productFeatureKeyOptions = [];
2854
+ }
2855
+ ngOnInit() {
2856
+ this.route.params.subscribe(params => {
2857
+ this.featureFlagId = +params['id'] || 0;
2858
+ this.loadPageData();
2859
+ });
2860
+ }
2861
+ get rf() {
2862
+ return this.ruleForm.controls;
2863
+ }
2864
+ loadPageData() {
2865
+ if (!this.featureFlagId) {
2866
+ this.isLoading = false;
2867
+ return;
2868
+ }
2869
+ this.isLoading = true;
2870
+ this.loadSupportedOptions();
2871
+ this.loadFeatureFlag();
2872
+ this.loadRules();
2873
+ }
2874
+ loadSupportedOptions() {
2875
+ this.adminService.getSupportedFeatureFlagRuleOptions().subscribe(response => {
2876
+ this.targetTypeOptions = (response.target_types || []).map(option => ({
2877
+ label: option,
2878
+ value: option
2879
+ }));
2880
+ this.environmentOptions = (response.environments || []).map(option => ({
2881
+ label: option,
2882
+ value: option
2883
+ }));
2884
+ this.productFeatureKeyOptions = (response.product_feature_keys || []).map(option => ({
2885
+ label: option,
2886
+ value: option
2887
+ }));
2888
+ });
2889
+ }
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
+ loadRules() {
2901
+ this.adminService.getFeatureFlagRules(this.featureFlagId).subscribe(response => {
2902
+ this.rules = response.feature_flag_rules || [];
2903
+ });
2904
+ }
2905
+ editRule(rule) {
2906
+ this.editingRuleId = rule.id;
2907
+ this.ruleForm.patchValue({
2908
+ environment: rule.environment,
2909
+ product_feature_key: rule.product_feature_key,
2910
+ target_type: rule.target_type,
2911
+ target_value: rule.target_value,
2912
+ enabled: rule.enabled,
2913
+ priority: rule.priority,
2914
+ rollout_percentage: rule.rollout_percentage
2915
+ });
2916
+ }
2917
+ resetRuleForm() {
2918
+ this.ruleForm.reset({
2919
+ environment: null,
2920
+ product_feature_key: null,
2921
+ target_type: null,
2922
+ target_value: '',
2923
+ enabled: false,
2924
+ priority: 0,
2925
+ rollout_percentage: null
2926
+ });
2927
+ this.ruleSubmitted = false;
2928
+ this.editingRuleId = null;
2929
+ }
2930
+ saveRule() {
2931
+ this.ruleForm.markAllAsTouched();
2932
+ this.ruleSubmitted = true;
2933
+ if (!this.ruleForm.valid) {
2934
+ return;
2935
+ }
2936
+ this.ruleButtonBusy = true;
2937
+ const payload = this.ruleForm.value;
2938
+ const request$ = this.editingRuleId
2939
+ ? this.adminService.updateFeatureFlagRule(this.featureFlagId, this.editingRuleId, payload)
2940
+ : this.adminService.createFeatureFlagRule(this.featureFlagId, payload);
2941
+ request$.subscribe({
2942
+ next: () => {
2943
+ this.toast.success(this.editingRuleId
2944
+ ? 'Feature flag rule updated successfully.'
2945
+ : 'Feature flag rule created successfully.');
2946
+ this.loadRules();
2947
+ this.resetRuleForm();
2948
+ },
2949
+ complete: () => {
2950
+ this.ruleButtonBusy = false;
2951
+ }
2952
+ });
2953
+ }
2954
+ deleteRule(rule) {
2955
+ swal.fire({
2956
+ title: 'Delete feature flag rule?',
2957
+ text: `This will remove the rule with target type ${rule.target_type}.`,
2958
+ icon: 'warning',
2959
+ showCancelButton: true,
2960
+ confirmButtonText: 'Delete'
2961
+ }).then(result => {
2962
+ if (!result.isConfirmed) {
2963
+ return;
2964
+ }
2965
+ this.adminService.deleteFeatureFlagRule(this.featureFlagId, rule.id).subscribe(() => {
2966
+ this.toast.success('Feature flag rule has been destroyed.');
2967
+ this.loadRules();
2968
+ if (this.editingRuleId === rule.id) {
2969
+ this.resetRuleForm();
2970
+ }
2971
+ });
2972
+ });
2973
+ }
2974
+ backToFlags() {
2975
+ this.router.navigate([this.routers.featureFlagsConfig]);
2976
+ }
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" }] }); }
2979
+ }
2980
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FeatureFlagRulesComponent, decorators: [{
2981
+ 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 }] });
2984
+
2985
+ class FeatureFlagsListComponent extends AppBaseComponent {
2986
+ constructor(injector, adminService) {
2987
+ super(injector);
2988
+ this.adminService = adminService;
2989
+ this.PAGE_SIZE = PAGE_SIZE;
2990
+ this.routers = ROUTERS;
2991
+ this.buttonBusy = false;
2992
+ this.isLoaded = true;
2993
+ this.searchText = '';
2994
+ this.featureFlags = [];
2995
+ this.totalRecords = 0;
2996
+ this.page = 1;
2997
+ }
2998
+ onLazyLoad(event) {
2999
+ const pageDetails = HelperService.onTableLazyLoad(event);
3000
+ this.page = pageDetails.page;
3001
+ this.loadFeatureFlags({
3002
+ page: pageDetails.page,
3003
+ page_size: PAGE_SIZE,
3004
+ order_by: pageDetails.sortField,
3005
+ order_direction: pageDetails.sortOrder
3006
+ });
3007
+ }
3008
+ loadFeatureFlags(paging) {
3009
+ this.isLoaded = false;
3010
+ this.adminService.getFeatureFlags(paging).subscribe({
3011
+ next: response => {
3012
+ this.featureFlags = response.feature_flags ?? [];
3013
+ this.totalRecords = response.object_count ?? this.featureFlags.length;
3014
+ },
3015
+ complete: () => {
3016
+ this.isLoaded = true;
3017
+ }
3018
+ });
3019
+ }
3020
+ navigateToEdit(item) {
3021
+ this.router.navigate([this.routers.featureFlagsDetails + item.id], {
3022
+ state: { data: item }
3023
+ });
3024
+ }
3025
+ navigateToRules(item) {
3026
+ this.router.navigate([this.routers.featureFlagRules + item.id], {
3027
+ state: { data: item }
3028
+ });
3029
+ }
3030
+ onDelete(item) {
3031
+ swal.fire({
3032
+ title: 'Delete feature flag?',
3033
+ text: `This will remove ${item.name || item.key}.`,
3034
+ icon: 'warning',
3035
+ showCancelButton: true,
3036
+ confirmButtonText: 'Delete'
3037
+ }).then(result => {
3038
+ if (!result.isConfirmed) {
3039
+ return;
3040
+ }
3041
+ this.buttonBusy = true;
3042
+ this.adminService.deleteFeatureFlag(item.id).subscribe({
3043
+ next: () => {
3044
+ this.toast.success('Feature flag has been destroyed.');
3045
+ this.loadFeatureFlags({ page: 1, page_size: PAGE_SIZE });
3046
+ },
3047
+ complete: () => {
3048
+ this.buttonBusy = false;
3049
+ }
3050
+ });
3051
+ });
3052
+ }
3053
+ 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" }] }); }
3055
+ }
3056
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FeatureFlagsListComponent, decorators: [{
3057
+ 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>" }]
3059
+ }], ctorParameters: () => [{ type: i0.Injector }, { type: i1.AdminService }] });
3060
+
3061
+ class FeatureFlagsTabsComponent {
3062
+ constructor() {
3063
+ this.items = [
3064
+ {
3065
+ id: 'feature-flags',
3066
+ label: 'Feature Flags',
3067
+ icon: 'fa fa-fw fa-toggle-on',
3068
+ routerLink: ['/admin/feature-flags/list']
3069
+ }
3070
+ ];
3071
+ }
3072
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FeatureFlagsTabsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3073
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.6", type: FeatureFlagsTabsComponent, isStandalone: false, selector: "feature-flags-tabs", ngImport: i0, template: `<pw-tabs [items]="items"></pw-tabs>`, isInline: true, dependencies: [{ kind: "component", type: i1$1.PwTabsComponent, selector: "pw-tabs", inputs: ["items", "withSubscription"] }] }); }
3074
+ }
3075
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FeatureFlagsTabsComponent, decorators: [{
3076
+ type: Component,
3077
+ args: [{
3078
+ selector: 'feature-flags-tabs',
3079
+ template: `<pw-tabs [items]="items"></pw-tabs>`,
3080
+ standalone: false
3081
+ }]
3082
+ }] });
3083
+
2716
3084
  class FeedbackQuestionsDetailsComponent extends AppBaseComponent {
2717
3085
  constructor(injector, cdr, adminService, productService) {
2718
3086
  super(injector);
@@ -8075,11 +8443,11 @@ class SubscriptionsListComponent extends AppBaseComponent {
8075
8443
  super.ngOnDestroy();
8076
8444
  }
8077
8445
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: SubscriptionsListComponent, deps: [{ token: i1$2.ProductService }, { token: i1.AdminService }, { token: i6.UntypedFormBuilder }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }, { token: i1$2.CommonService }], target: i0.ɵɵFactoryTarget.Component }); }
8078
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: SubscriptionsListComponent, isStandalone: false, selector: "pw-subscriptions-list", viewQueries: [{ propertyName: "refProduct", first: true, predicate: ["refProduct"], descendants: true }, { propertyName: "recoverSubscriptionPasswordModal", first: true, predicate: ["recoverSubscriptionPasswordModal"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"row\">\n <div\n class=\"col-12 d-flex justify-content-between align-items-center\">\n <h2 class=\"card-title p-0 float-start\">Subscriptions</h2>\n <a class=\"btn btn-sm btn-outline-primary float-end\"\n id=\"btn-create\"\n [routerLink]=\"[routers.inviteUsers]\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i> Invite a User to a Trial\n </a>\n </div>\n</div>\n<div class=\"p-2 mt-3\">\n <div class=\"w-100 text-center mt-3\">\n @if (!isLoaded) {\n <p-progressSpinner> </p-progressSpinner>\n }\n </div>\n <div class=\"primeng-datatable-container table-responsive mt-0\"\n [class.hideTable]=\"totalRecordsUnFiltered === 0\">\n <p-table #dt\n [value]=\"subscriptions\"\n [paginator]=\"totalRecords !== 0\"\n [rows]=\"PAGE_SIZE\"\n [lazy]=\"true\"\n [totalRecords]=\"totalRecords\"\n [loading]=\"loading\"\n [filterDelay]=\"1000\"\n (onLazyLoad)=\"onLazyLoad($event)\"\n [customSort]=\"true\">\n <ng-template pTemplate=\"caption\">\n @if (subscriptionInsights) {\n <div class=\"row mb-4\">\n @for (temp of objectKeys(subscriptionInsights); track temp) {\n <div class=\"col-12 col-lg-3 mt-2 summary\">\n <div class=\"card\">\n <div class=\"card-body\">\n @for (item of subscriptionInsights[temp]; track item) {\n <div>\n <p class=\"mb-0 px-2\">{{ item?.title }}\n @if (item?.info) {\n <span\n [pTooltip]=\"item?.info\">\n <i class=\"fas fa-info-circle\"></i>\n </span>\n }\n </p>\n <h4 class=\"fw-bold mt-2 mb-2\">\n {{ item?.value }}\n </h4>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n <div class=\"search-filter\">\n <div class=\"col-12 col-sm-4\">\n <p-multiSelect inputId=\"subscriptions-list-feature-keys\"\n placeholder=\"Select Feature Keys\"\n [showToggleAll]=\"true\"\n [showHeader]=\"true\"\n [(ngModel)]=\"selectedFeatureKeys\"\n [options]=\"searchOptions\"\n (onChange)=\"onSearchOptionChange($event)\"\n appendTo=\"body\">\n </p-multiSelect>\n </div>\n <div class=\"col-12 col-sm-4\">\n <p-select\n inputId=\"subscriptions-list-status\"\n [options]=\"subscriptionStatus\"\n [placeholder]=\"'Select status'\"\n (onChange)=\"filterByStatus($event.value)\"\n [(ngModel)]=\"status\">\n </p-select>\n </div>\n <div class=\"text-end\">\n <label for=\"subscriptions-list-search\" class=\"visually-hidden\">Search Subscription</label>\n <i class=\"fa fa-search mt-2 me-2 d-none\" aria-hidden=\"true\"></i>\n <input type=\"text\"\n id=\"subscriptions-list-search\"\n name=\"subscriptions-list-search\"\n [(ngModel)]=\"searchText\"\n pInputText\n size=\"30\"\n placeholder=\"Search Subscription...\"\n class=\"mw-90\"\n (input)=\"dt.filterGlobal($event.target.value, 'contains')\" />\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\"\n pSortableColumn=\"id\">\n {{ 'Admin.Subscriptions.Id' | transloco }}\n <p-sortIcon field=\"id\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"organisation\">\n {{ 'Admin.Subscriptions.Organization' | transloco }}\n <p-sortIcon field=\"organisation\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"contact_name\">\n {{ 'Admin.Subscriptions.ContactName' | transloco }}\n <p-sortIcon field=\"contact_name\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"contact_email\">\n {{ 'Admin.Subscriptions.ContactEmail' | transloco }}\n <p-sortIcon field=\"contact_email\"></p-sortIcon>\n </th>\n <th scope=\"true\">{{ 'Admin.Subscriptions.Product' | transloco }}</th>\n <th scope=\"true\">{{ 'Admin.Subscriptions.Currency' | transloco }}</th>\n <th scope=\"true\">{{ 'Admin.Subscriptions.PricePerMonth' | transloco }}</th>\n <th scope=\"true\"\n pSortableColumn=\"stripe_customer_id\">\n {{ 'Admin.Subscriptions.Paid' | transloco }}\n <p-sortIcon field=\"stripe_customer_id\"></p-sortIcon>\n </th>\n <th scope=\"true\">{{ 'Admin.Subscriptions.Billing' | transloco }}</th>\n <th scope=\"true\"\n class=\"expires-at-width\">\n {{ 'Admin.Subscriptions.ExpiresAt' | transloco }}\n </th>\n <th scope=\"true\"\n pSortableColumn=\"sessions_total\">\n {{ 'Admin.Subscriptions.SessionsTotal' | transloco }}\n <p-sortIcon field=\"sessions_total\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"sessions_last_month\">\n {{ 'Admin.Subscriptions.SessionsTotalLastMonth' | transloco }}\n <p-sortIcon field=\"sessions_last_month\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"deleted_at\">\n {{ 'Admin.Subscriptions.Deleted' | transloco }}\n <p-sortIcon field=\"deleted_at\"></p-sortIcon>\n </th>\n <th class=\"actions-list-two\"\n scope=\"true\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-item>\n <tr>\n <td data-head=\"id\">{{ item.id }}</td>\n <td data-head=\"Organization\">\n <span class=\"cursor-pointer custom-break-word\"\n [pTooltip]=\"item.organisation\"\n tooltipPosition=\"top\">{{ item.organisation | textTruncate: 20 }}</span>\n </td>\n <td data-head=\"ContactName\"\n class=\"custom-break-word\">\n {{ item.contact_name }}\n </td>\n <td data-head=\"ContactEmail\">{{ item.contact_email }}</td>\n <td data-head=\"Name\">\n <span class=\"cursor-pointer custom-break-word\"\n [pTooltip]=\"item.productName\"\n tooltipPosition=\"top\">{{ item.productName }}</span>\n </td>\n <td data-head=\"Currency\">\n <span [appDynamicBadge]=\"{ itemsArray: currency, item: item.currency }\"\n color=\"blue-grey\"\n class=\"badge\">{{ item.currency }}</span>\n </td>\n <td data-head=\"Price/M\">\n <span>{{ (item.price / 100).toFixed(2) | currency:item.currency }}\n @if (item?.discount && objectKeys(item?.discount)?.length) {\n <i\n class=\"fa fa-info-circle\"\n aria-hidden=\"true\"\n [pTooltip]=\"item?.discount | json\"\n tooltipPosition=\"top\"\n ></i>\n }\n </span>\n </td>\n <td data-head=\"Paid\">\n @if (item?.unsubscribed_at) {\n <span class=\"badge bg-warning d-inline-flex align-items-center\">\n Unsub\n @if (item?.reason_to_cancel) {\n <i class=\"fa fa-info-circle ms-2\"\n [pTooltip]=\"item.reason_to_cancel\"\n tooltipPosition=\"top\"\n aria-hidden=\"true\"></i>\n }\n </span>\n }\n @if (!item?.unsubscribed_at) {\n @if ((item?.stripe_customer_id || item?.external_payment) && item?.signed_up_at) {\n <span class=\"badge bg-success\">Yes</span>\n } @else {\n <span class=\"badge bg-blue-grey\">No</span>\n }\n }\n @if (item?.pause_collection && objectKeys(item?.pause_collection)?.length) {\n <span\n class=\"ms-2\"\n [pTooltip]=\"item?.pause_collection | json\"\n tooltipPosition=\"top\">\n <i class=\"fas fa-exclamation-triangle text-warning\"></i>\n </span>\n }\n </td>\n <td data-head=\"Billing\">\n <span class=\"badge\"\n [appDynamicBadge]=\"{\n itemsArray: billingFrequency,\n item: item?.billingFrequency\n }\"\n color=\"blue-grey\">{{ item.billingFrequency }}</span>\n </td>\n <td data-head=\"Expires\">\n <span [ngClass]=\"getExpiresAtColor(item)\">{{item?.expires_at | dateFormat}}</span><br />\n <span>{{item?.created_at | sinceAgo}}</span>\n </td>\n <td data-head=\"S#\">{{ item?.sessions_total }}</td>\n <td data-head=\"S/m #\">\n <span [ngClass]=\"{\n 'text-danger fw-bold': item?.sessions_last_month < 3\n }\">{{ item?.sessions_last_month }}</span>\n </td>\n <td data-head=\"Deleted\">\n @if (item?.deleted_at) {\n <span\n class=\"badge bg-danger\">Yes</span>\n }\n @if (!item?.deleted_at) {\n <span\n class=\"badge bg-blue-grey\">No</span>\n }\n </td>\n <td data-head=\"Action\">\n <ul class=\"list-unstyled list-inline list-action\">\n <li ngbTooltip=\"Edit\"\n class=\"me-2 me-sm-3\"\n [routerLink]=\"[routers.subscriptionDetails, item.id]\">\n <i class=\"fa fa-edit edit-icon\" aria-hidden=\"true\"></i>\n </li>\n @if (item.deleted) {\n <li ngbTooltip=\"Reactivate subscription\"\n class=\"me-2 me-sm-3\"\n *rbacAllow=\"'Pages.Alpha'\"\n (keydown.enter)=\"openRecoverSubscriptionModal(item)\"\n (click)=\"openRecoverSubscriptionModal(item)\">\n <i class=\"fa fa-trash delete-icon text-success\" aria-hidden=\"true\"></i>\n </li>\n } @else {\n <li ngbTooltip=\"Delete\"\n class=\"me-2 me-sm-3\"\n *rbacAllow=\"'Pages.Admin.Subscription.Delete'\"\n (keydown.enter)=\"onDelete(item)\"\n (click)=\"onDelete(item)\">\n <i class=\"fa fa-trash delete-icon\" aria-hidden=\"true\"></i>\n </li>\n }\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (totalRecords === 0 && totalRecordsUnFiltered !== 0) {\n <div>\n <pw-no-data [withImage]=\"true\" [message]=\"'Search.NoDataMessage' | transloco\" [description]=\"'Search.NoDataDescription' | transloco\" >\n </pw-no-data>\n </div>\n }\n @if (totalRecords !== 0) {\n <span class=\"total-records-count\">{{ 'Label.Total' | transloco }}: {{ totalRecords }}</span>\n }\n </div>\n</div>\n@if (totalRecordsUnFiltered === 0 && isLoaded) {\n <pw-no-data [withImage]=\"true\" [message]=\"'Admin.Subscriptions.NoSubscriptionMessage' | transloco\">\n </pw-no-data>\n}\n<pw-password-validation\n #recoverSubscriptionPasswordModal\n (successEvent)=\"onRecoverConfirmed()\">\n</pw-password-validation>\n\n", styles: [":root{--first: rgb(23 105 225);--second: rgb(54 194 131);--third: rgb(255 171 0);--text: rgb(34 34 34);--tabs_bg: rgb(23 105 225);--tabs_sub_bg: rgb(70, 136, 236);--tabs_text: rgb(255 255 255);--titles: rgb(34 34 34);--sidebar_bg: rgb(0, 48, 63);--sidebar_text: rgb(255 255 255)}@media(min-width:767px){.table-responsive td,.table-responsive th{font-size:11px!important}}.expires-at-width{width:8%}.custom-break-word{word-break:break-word!important}.summary .card{padding-bottom:0}.summary .card .card-body{padding-top:20px;text-align:center}.summary .card .card-body p,.summary .card .card-body h4{font-size:14px}@media(min-width:320px)and (max-width:720px){.primeng-datatable-container .search-filter{display:flex;flex-direction:column;gap:.5rem;justify-content:space-between}}\n"], 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: i2.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i2.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "directive", type: i4$2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { 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: i7$2.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { 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: i3$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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: i1$1.PasswordValidationComponent, selector: "pw-password-validation", inputs: ["confirmMessage"], outputs: ["successEvent"] }, { 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: i9.DynamicBadgeDirective, selector: "[appDynamicBadge]", inputs: ["appDynamicBadge", "color", "colorByName", "dataName"] }, { kind: "directive", type: i9.RbacAllowDirective, selector: "[rbacAllow]", inputs: ["rbacAllow"] }, { kind: "directive", type: i10.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i3$1.JsonPipe, name: "json" }, { kind: "pipe", type: i3$1.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i11.TranslocoPipe, name: "transloco" }, { kind: "pipe", type: i15.DateFormatPipe, name: "dateFormat" }, { kind: "pipe", type: i15.SinceAgoPipe, name: "sinceAgo" }, { kind: "pipe", type: i15.TextTruncatePipe, name: "textTruncate" }] }); }
8446
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: SubscriptionsListComponent, isStandalone: false, selector: "pw-subscriptions-list", viewQueries: [{ propertyName: "refProduct", first: true, predicate: ["refProduct"], descendants: true }, { propertyName: "recoverSubscriptionPasswordModal", first: true, predicate: ["recoverSubscriptionPasswordModal"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"row\">\n <div\n class=\"col-12 d-flex justify-content-between align-items-center\">\n <h2 class=\"card-title p-0 float-start\">Subscriptions</h2>\n <a class=\"btn btn-sm btn-outline-primary float-end\"\n id=\"btn-create\"\n [routerLink]=\"[routers.inviteUsers]\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i> Invite a User to a Trial\n </a>\n </div>\n</div>\n<div class=\"p-2 mt-3\">\n <div class=\"w-100 text-center mt-3\">\n @if (!isLoaded) {\n <p-progressSpinner> </p-progressSpinner>\n }\n </div>\n <div class=\"primeng-datatable-container table-responsive mt-0\"\n [class.hideTable]=\"totalRecordsUnFiltered === 0\">\n <p-table #dt\n [value]=\"subscriptions\"\n [paginator]=\"totalRecords !== 0\"\n [rows]=\"PAGE_SIZE\"\n [lazy]=\"true\"\n [totalRecords]=\"totalRecords\"\n [loading]=\"loading\"\n [filterDelay]=\"1000\"\n (onLazyLoad)=\"onLazyLoad($event)\"\n [customSort]=\"true\">\n <ng-template pTemplate=\"caption\">\n @if (subscriptionInsights) {\n <div class=\"row mb-4\">\n @for (temp of objectKeys(subscriptionInsights); track temp) {\n <div class=\"col-12 col-lg-3 mt-2 summary\">\n <div class=\"card\">\n <div class=\"card-body\">\n @for (item of subscriptionInsights[temp]; track item) {\n <div>\n <p class=\"mb-0 px-2\">{{ item?.title }}\n @if (item?.info) {\n <span\n [pTooltip]=\"item?.info\">\n <i class=\"fas fa-info-circle\"></i>\n </span>\n }\n </p>\n <h4 class=\"fw-bold mt-2 mb-2\">\n {{ item?.value }}\n </h4>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n <div class=\"search-filter\">\n <div class=\"col-12 col-sm-4\">\n <p-multiSelect inputId=\"subscriptions-list-feature-keys\"\n placeholder=\"Select Feature Keys\"\n [showToggleAll]=\"true\"\n [showHeader]=\"true\"\n [(ngModel)]=\"selectedFeatureKeys\"\n [options]=\"searchOptions\"\n (onChange)=\"onSearchOptionChange($event)\"\n appendTo=\"body\">\n </p-multiSelect>\n </div>\n <div class=\"col-12 col-sm-4\">\n <p-select\n inputId=\"subscriptions-list-status\"\n [options]=\"subscriptionStatus\"\n [placeholder]=\"'Select status'\"\n (onChange)=\"filterByStatus($event.value)\"\n [(ngModel)]=\"status\"\n appendTo=\"body\">\n </p-select>\n </div>\n <div class=\"text-end\">\n <label for=\"subscriptions-list-search\" class=\"visually-hidden\">Search Subscription</label>\n <i class=\"fa fa-search mt-2 me-2 d-none\" aria-hidden=\"true\"></i>\n <input type=\"text\"\n id=\"subscriptions-list-search\"\n name=\"subscriptions-list-search\"\n [(ngModel)]=\"searchText\"\n pInputText\n size=\"30\"\n placeholder=\"Search Subscription...\"\n class=\"mw-90\"\n (input)=\"dt.filterGlobal($event.target.value, 'contains')\" />\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\"\n pSortableColumn=\"id\">\n {{ 'Admin.Subscriptions.Id' | transloco }}\n <p-sortIcon field=\"id\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"organisation\">\n {{ 'Admin.Subscriptions.Organization' | transloco }}\n <p-sortIcon field=\"organisation\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"contact_name\">\n {{ 'Admin.Subscriptions.ContactName' | transloco }}\n <p-sortIcon field=\"contact_name\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"contact_email\">\n {{ 'Admin.Subscriptions.ContactEmail' | transloco }}\n <p-sortIcon field=\"contact_email\"></p-sortIcon>\n </th>\n <th scope=\"true\">{{ 'Admin.Subscriptions.Product' | transloco }}</th>\n <th scope=\"true\">{{ 'Admin.Subscriptions.Currency' | transloco }}</th>\n <th scope=\"true\">{{ 'Admin.Subscriptions.PricePerMonth' | transloco }}</th>\n <th scope=\"true\"\n pSortableColumn=\"stripe_customer_id\">\n {{ 'Admin.Subscriptions.Paid' | transloco }}\n <p-sortIcon field=\"stripe_customer_id\"></p-sortIcon>\n </th>\n <th scope=\"true\">{{ 'Admin.Subscriptions.Billing' | transloco }}</th>\n <th scope=\"true\"\n class=\"expires-at-width\">\n {{ 'Admin.Subscriptions.ExpiresAt' | transloco }}\n </th>\n <th scope=\"true\"\n pSortableColumn=\"sessions_total\">\n {{ 'Admin.Subscriptions.SessionsTotal' | transloco }}\n <p-sortIcon field=\"sessions_total\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"sessions_last_month\">\n {{ 'Admin.Subscriptions.SessionsTotalLastMonth' | transloco }}\n <p-sortIcon field=\"sessions_last_month\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"deleted_at\">\n {{ 'Admin.Subscriptions.Deleted' | transloco }}\n <p-sortIcon field=\"deleted_at\"></p-sortIcon>\n </th>\n <th class=\"actions-list-two\"\n scope=\"true\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-item>\n <tr>\n <td data-head=\"id\">{{ item.id }}</td>\n <td data-head=\"Organization\">\n <span class=\"cursor-pointer custom-break-word\"\n [pTooltip]=\"item.organisation\"\n tooltipPosition=\"top\">{{ item.organisation | textTruncate: 20 }}</span>\n </td>\n <td data-head=\"ContactName\"\n class=\"custom-break-word\">\n {{ item.contact_name }}\n </td>\n <td data-head=\"ContactEmail\">{{ item.contact_email }}</td>\n <td data-head=\"Name\">\n <span class=\"cursor-pointer custom-break-word\"\n [pTooltip]=\"item.productName\"\n tooltipPosition=\"top\">{{ item.productName }}</span>\n </td>\n <td data-head=\"Currency\">\n <span [appDynamicBadge]=\"{ itemsArray: currency, item: item.currency }\"\n color=\"blue-grey\"\n class=\"badge\">{{ item.currency }}</span>\n </td>\n <td data-head=\"Price/M\">\n <span>{{ (item.price / 100).toFixed(2) | currency:item.currency }}\n @if (item?.discount && objectKeys(item?.discount)?.length) {\n <i\n class=\"fa fa-info-circle\"\n aria-hidden=\"true\"\n [pTooltip]=\"item?.discount | json\"\n tooltipPosition=\"top\"\n ></i>\n }\n </span>\n </td>\n <td data-head=\"Paid\">\n @if (item?.unsubscribed_at) {\n <span class=\"badge bg-warning d-inline-flex align-items-center\">\n Unsub\n @if (item?.reason_to_cancel) {\n <i class=\"fa fa-info-circle ms-2\"\n [pTooltip]=\"item.reason_to_cancel\"\n tooltipPosition=\"top\"\n aria-hidden=\"true\"></i>\n }\n </span>\n }\n @if (!item?.unsubscribed_at) {\n @if ((item?.stripe_customer_id || item?.external_payment) && item?.signed_up_at) {\n <span class=\"badge bg-success\">Yes</span>\n } @else {\n <span class=\"badge bg-blue-grey\">No</span>\n }\n }\n @if (item?.pause_collection && objectKeys(item?.pause_collection)?.length) {\n <span\n class=\"ms-2\"\n [pTooltip]=\"item?.pause_collection | json\"\n tooltipPosition=\"top\">\n <i class=\"fas fa-exclamation-triangle text-warning\"></i>\n </span>\n }\n </td>\n <td data-head=\"Billing\">\n <span class=\"badge\"\n [appDynamicBadge]=\"{\n itemsArray: billingFrequency,\n item: item?.billingFrequency\n }\"\n color=\"blue-grey\">{{ item.billingFrequency }}</span>\n </td>\n <td data-head=\"Expires\">\n <span [ngClass]=\"getExpiresAtColor(item)\">{{item?.expires_at | dateFormat}}</span><br />\n <span>{{item?.created_at | sinceAgo}}</span>\n </td>\n <td data-head=\"S#\">{{ item?.sessions_total }}</td>\n <td data-head=\"S/m #\">\n <span [ngClass]=\"{\n 'text-danger fw-bold': item?.sessions_last_month < 3\n }\">{{ item?.sessions_last_month }}</span>\n </td>\n <td data-head=\"Deleted\">\n @if (item?.deleted_at) {\n <span\n class=\"badge bg-danger\">Yes</span>\n }\n @if (!item?.deleted_at) {\n <span\n class=\"badge bg-blue-grey\">No</span>\n }\n </td>\n <td data-head=\"Action\">\n <ul class=\"list-unstyled list-inline list-action\">\n <li ngbTooltip=\"Edit\"\n class=\"me-2 me-sm-3\"\n [routerLink]=\"[routers.subscriptionDetails, item.id]\">\n <i class=\"fa fa-edit edit-icon\" aria-hidden=\"true\"></i>\n </li>\n @if (item.deleted) {\n <li ngbTooltip=\"Reactivate subscription\"\n class=\"me-2 me-sm-3\"\n *rbacAllow=\"'Pages.Alpha'\"\n (keydown.enter)=\"openRecoverSubscriptionModal(item)\"\n (click)=\"openRecoverSubscriptionModal(item)\">\n <i class=\"fa fa-trash delete-icon text-success\" aria-hidden=\"true\"></i>\n </li>\n } @else {\n <li ngbTooltip=\"Delete\"\n class=\"me-2 me-sm-3\"\n *rbacAllow=\"'Pages.Admin.Subscription.Delete'\"\n (keydown.enter)=\"onDelete(item)\"\n (click)=\"onDelete(item)\">\n <i class=\"fa fa-trash delete-icon\" aria-hidden=\"true\"></i>\n </li>\n }\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (totalRecords === 0 && totalRecordsUnFiltered !== 0) {\n <div>\n <pw-no-data [withImage]=\"true\" [message]=\"'Search.NoDataMessage' | transloco\" [description]=\"'Search.NoDataDescription' | transloco\" >\n </pw-no-data>\n </div>\n }\n @if (totalRecords !== 0) {\n <span class=\"total-records-count\">{{ 'Label.Total' | transloco }}: {{ totalRecords }}</span>\n }\n </div>\n</div>\n@if (totalRecordsUnFiltered === 0 && isLoaded) {\n <pw-no-data [withImage]=\"true\" [message]=\"'Admin.Subscriptions.NoSubscriptionMessage' | transloco\">\n </pw-no-data>\n}\n<pw-password-validation\n #recoverSubscriptionPasswordModal\n (successEvent)=\"onRecoverConfirmed()\">\n</pw-password-validation>\n\n", styles: [":root{--first: rgb(23 105 225);--second: rgb(54 194 131);--third: rgb(255 171 0);--text: rgb(34 34 34);--tabs_bg: rgb(23 105 225);--tabs_sub_bg: rgb(70, 136, 236);--tabs_text: rgb(255 255 255);--titles: rgb(34 34 34);--sidebar_bg: rgb(0, 48, 63);--sidebar_text: rgb(255 255 255)}@media(min-width:767px){.table-responsive td,.table-responsive th{font-size:11px!important}}.expires-at-width{width:8%}.custom-break-word{word-break:break-word!important}.summary .card{padding-bottom:0}.summary .card .card-body{padding-top:20px;text-align:center}.summary .card .card-body p,.summary .card .card-body h4{font-size:14px}@media(min-width:320px)and (max-width:720px){.primeng-datatable-container .search-filter{display:flex;flex-direction:column;gap:.5rem;justify-content:space-between}}\n"], 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: i2.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i2.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "directive", type: i4$2.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { 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: i7$2.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { 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: i3$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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: i1$1.PasswordValidationComponent, selector: "pw-password-validation", inputs: ["confirmMessage"], outputs: ["successEvent"] }, { 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: i9.DynamicBadgeDirective, selector: "[appDynamicBadge]", inputs: ["appDynamicBadge", "color", "colorByName", "dataName"] }, { kind: "directive", type: i9.RbacAllowDirective, selector: "[rbacAllow]", inputs: ["rbacAllow"] }, { kind: "directive", type: i10.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i3$1.JsonPipe, name: "json" }, { kind: "pipe", type: i3$1.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i11.TranslocoPipe, name: "transloco" }, { kind: "pipe", type: i15.DateFormatPipe, name: "dateFormat" }, { kind: "pipe", type: i15.SinceAgoPipe, name: "sinceAgo" }, { kind: "pipe", type: i15.TextTruncatePipe, name: "textTruncate" }] }); }
8079
8447
  }
8080
8448
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: SubscriptionsListComponent, decorators: [{
8081
8449
  type: Component,
8082
- args: [{ selector: 'pw-subscriptions-list', standalone: false, template: "<div class=\"row\">\n <div\n class=\"col-12 d-flex justify-content-between align-items-center\">\n <h2 class=\"card-title p-0 float-start\">Subscriptions</h2>\n <a class=\"btn btn-sm btn-outline-primary float-end\"\n id=\"btn-create\"\n [routerLink]=\"[routers.inviteUsers]\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i> Invite a User to a Trial\n </a>\n </div>\n</div>\n<div class=\"p-2 mt-3\">\n <div class=\"w-100 text-center mt-3\">\n @if (!isLoaded) {\n <p-progressSpinner> </p-progressSpinner>\n }\n </div>\n <div class=\"primeng-datatable-container table-responsive mt-0\"\n [class.hideTable]=\"totalRecordsUnFiltered === 0\">\n <p-table #dt\n [value]=\"subscriptions\"\n [paginator]=\"totalRecords !== 0\"\n [rows]=\"PAGE_SIZE\"\n [lazy]=\"true\"\n [totalRecords]=\"totalRecords\"\n [loading]=\"loading\"\n [filterDelay]=\"1000\"\n (onLazyLoad)=\"onLazyLoad($event)\"\n [customSort]=\"true\">\n <ng-template pTemplate=\"caption\">\n @if (subscriptionInsights) {\n <div class=\"row mb-4\">\n @for (temp of objectKeys(subscriptionInsights); track temp) {\n <div class=\"col-12 col-lg-3 mt-2 summary\">\n <div class=\"card\">\n <div class=\"card-body\">\n @for (item of subscriptionInsights[temp]; track item) {\n <div>\n <p class=\"mb-0 px-2\">{{ item?.title }}\n @if (item?.info) {\n <span\n [pTooltip]=\"item?.info\">\n <i class=\"fas fa-info-circle\"></i>\n </span>\n }\n </p>\n <h4 class=\"fw-bold mt-2 mb-2\">\n {{ item?.value }}\n </h4>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n <div class=\"search-filter\">\n <div class=\"col-12 col-sm-4\">\n <p-multiSelect inputId=\"subscriptions-list-feature-keys\"\n placeholder=\"Select Feature Keys\"\n [showToggleAll]=\"true\"\n [showHeader]=\"true\"\n [(ngModel)]=\"selectedFeatureKeys\"\n [options]=\"searchOptions\"\n (onChange)=\"onSearchOptionChange($event)\"\n appendTo=\"body\">\n </p-multiSelect>\n </div>\n <div class=\"col-12 col-sm-4\">\n <p-select\n inputId=\"subscriptions-list-status\"\n [options]=\"subscriptionStatus\"\n [placeholder]=\"'Select status'\"\n (onChange)=\"filterByStatus($event.value)\"\n [(ngModel)]=\"status\">\n </p-select>\n </div>\n <div class=\"text-end\">\n <label for=\"subscriptions-list-search\" class=\"visually-hidden\">Search Subscription</label>\n <i class=\"fa fa-search mt-2 me-2 d-none\" aria-hidden=\"true\"></i>\n <input type=\"text\"\n id=\"subscriptions-list-search\"\n name=\"subscriptions-list-search\"\n [(ngModel)]=\"searchText\"\n pInputText\n size=\"30\"\n placeholder=\"Search Subscription...\"\n class=\"mw-90\"\n (input)=\"dt.filterGlobal($event.target.value, 'contains')\" />\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\"\n pSortableColumn=\"id\">\n {{ 'Admin.Subscriptions.Id' | transloco }}\n <p-sortIcon field=\"id\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"organisation\">\n {{ 'Admin.Subscriptions.Organization' | transloco }}\n <p-sortIcon field=\"organisation\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"contact_name\">\n {{ 'Admin.Subscriptions.ContactName' | transloco }}\n <p-sortIcon field=\"contact_name\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"contact_email\">\n {{ 'Admin.Subscriptions.ContactEmail' | transloco }}\n <p-sortIcon field=\"contact_email\"></p-sortIcon>\n </th>\n <th scope=\"true\">{{ 'Admin.Subscriptions.Product' | transloco }}</th>\n <th scope=\"true\">{{ 'Admin.Subscriptions.Currency' | transloco }}</th>\n <th scope=\"true\">{{ 'Admin.Subscriptions.PricePerMonth' | transloco }}</th>\n <th scope=\"true\"\n pSortableColumn=\"stripe_customer_id\">\n {{ 'Admin.Subscriptions.Paid' | transloco }}\n <p-sortIcon field=\"stripe_customer_id\"></p-sortIcon>\n </th>\n <th scope=\"true\">{{ 'Admin.Subscriptions.Billing' | transloco }}</th>\n <th scope=\"true\"\n class=\"expires-at-width\">\n {{ 'Admin.Subscriptions.ExpiresAt' | transloco }}\n </th>\n <th scope=\"true\"\n pSortableColumn=\"sessions_total\">\n {{ 'Admin.Subscriptions.SessionsTotal' | transloco }}\n <p-sortIcon field=\"sessions_total\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"sessions_last_month\">\n {{ 'Admin.Subscriptions.SessionsTotalLastMonth' | transloco }}\n <p-sortIcon field=\"sessions_last_month\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"deleted_at\">\n {{ 'Admin.Subscriptions.Deleted' | transloco }}\n <p-sortIcon field=\"deleted_at\"></p-sortIcon>\n </th>\n <th class=\"actions-list-two\"\n scope=\"true\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-item>\n <tr>\n <td data-head=\"id\">{{ item.id }}</td>\n <td data-head=\"Organization\">\n <span class=\"cursor-pointer custom-break-word\"\n [pTooltip]=\"item.organisation\"\n tooltipPosition=\"top\">{{ item.organisation | textTruncate: 20 }}</span>\n </td>\n <td data-head=\"ContactName\"\n class=\"custom-break-word\">\n {{ item.contact_name }}\n </td>\n <td data-head=\"ContactEmail\">{{ item.contact_email }}</td>\n <td data-head=\"Name\">\n <span class=\"cursor-pointer custom-break-word\"\n [pTooltip]=\"item.productName\"\n tooltipPosition=\"top\">{{ item.productName }}</span>\n </td>\n <td data-head=\"Currency\">\n <span [appDynamicBadge]=\"{ itemsArray: currency, item: item.currency }\"\n color=\"blue-grey\"\n class=\"badge\">{{ item.currency }}</span>\n </td>\n <td data-head=\"Price/M\">\n <span>{{ (item.price / 100).toFixed(2) | currency:item.currency }}\n @if (item?.discount && objectKeys(item?.discount)?.length) {\n <i\n class=\"fa fa-info-circle\"\n aria-hidden=\"true\"\n [pTooltip]=\"item?.discount | json\"\n tooltipPosition=\"top\"\n ></i>\n }\n </span>\n </td>\n <td data-head=\"Paid\">\n @if (item?.unsubscribed_at) {\n <span class=\"badge bg-warning d-inline-flex align-items-center\">\n Unsub\n @if (item?.reason_to_cancel) {\n <i class=\"fa fa-info-circle ms-2\"\n [pTooltip]=\"item.reason_to_cancel\"\n tooltipPosition=\"top\"\n aria-hidden=\"true\"></i>\n }\n </span>\n }\n @if (!item?.unsubscribed_at) {\n @if ((item?.stripe_customer_id || item?.external_payment) && item?.signed_up_at) {\n <span class=\"badge bg-success\">Yes</span>\n } @else {\n <span class=\"badge bg-blue-grey\">No</span>\n }\n }\n @if (item?.pause_collection && objectKeys(item?.pause_collection)?.length) {\n <span\n class=\"ms-2\"\n [pTooltip]=\"item?.pause_collection | json\"\n tooltipPosition=\"top\">\n <i class=\"fas fa-exclamation-triangle text-warning\"></i>\n </span>\n }\n </td>\n <td data-head=\"Billing\">\n <span class=\"badge\"\n [appDynamicBadge]=\"{\n itemsArray: billingFrequency,\n item: item?.billingFrequency\n }\"\n color=\"blue-grey\">{{ item.billingFrequency }}</span>\n </td>\n <td data-head=\"Expires\">\n <span [ngClass]=\"getExpiresAtColor(item)\">{{item?.expires_at | dateFormat}}</span><br />\n <span>{{item?.created_at | sinceAgo}}</span>\n </td>\n <td data-head=\"S#\">{{ item?.sessions_total }}</td>\n <td data-head=\"S/m #\">\n <span [ngClass]=\"{\n 'text-danger fw-bold': item?.sessions_last_month < 3\n }\">{{ item?.sessions_last_month }}</span>\n </td>\n <td data-head=\"Deleted\">\n @if (item?.deleted_at) {\n <span\n class=\"badge bg-danger\">Yes</span>\n }\n @if (!item?.deleted_at) {\n <span\n class=\"badge bg-blue-grey\">No</span>\n }\n </td>\n <td data-head=\"Action\">\n <ul class=\"list-unstyled list-inline list-action\">\n <li ngbTooltip=\"Edit\"\n class=\"me-2 me-sm-3\"\n [routerLink]=\"[routers.subscriptionDetails, item.id]\">\n <i class=\"fa fa-edit edit-icon\" aria-hidden=\"true\"></i>\n </li>\n @if (item.deleted) {\n <li ngbTooltip=\"Reactivate subscription\"\n class=\"me-2 me-sm-3\"\n *rbacAllow=\"'Pages.Alpha'\"\n (keydown.enter)=\"openRecoverSubscriptionModal(item)\"\n (click)=\"openRecoverSubscriptionModal(item)\">\n <i class=\"fa fa-trash delete-icon text-success\" aria-hidden=\"true\"></i>\n </li>\n } @else {\n <li ngbTooltip=\"Delete\"\n class=\"me-2 me-sm-3\"\n *rbacAllow=\"'Pages.Admin.Subscription.Delete'\"\n (keydown.enter)=\"onDelete(item)\"\n (click)=\"onDelete(item)\">\n <i class=\"fa fa-trash delete-icon\" aria-hidden=\"true\"></i>\n </li>\n }\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (totalRecords === 0 && totalRecordsUnFiltered !== 0) {\n <div>\n <pw-no-data [withImage]=\"true\" [message]=\"'Search.NoDataMessage' | transloco\" [description]=\"'Search.NoDataDescription' | transloco\" >\n </pw-no-data>\n </div>\n }\n @if (totalRecords !== 0) {\n <span class=\"total-records-count\">{{ 'Label.Total' | transloco }}: {{ totalRecords }}</span>\n }\n </div>\n</div>\n@if (totalRecordsUnFiltered === 0 && isLoaded) {\n <pw-no-data [withImage]=\"true\" [message]=\"'Admin.Subscriptions.NoSubscriptionMessage' | transloco\">\n </pw-no-data>\n}\n<pw-password-validation\n #recoverSubscriptionPasswordModal\n (successEvent)=\"onRecoverConfirmed()\">\n</pw-password-validation>\n\n", styles: [":root{--first: rgb(23 105 225);--second: rgb(54 194 131);--third: rgb(255 171 0);--text: rgb(34 34 34);--tabs_bg: rgb(23 105 225);--tabs_sub_bg: rgb(70, 136, 236);--tabs_text: rgb(255 255 255);--titles: rgb(34 34 34);--sidebar_bg: rgb(0, 48, 63);--sidebar_text: rgb(255 255 255)}@media(min-width:767px){.table-responsive td,.table-responsive th{font-size:11px!important}}.expires-at-width{width:8%}.custom-break-word{word-break:break-word!important}.summary .card{padding-bottom:0}.summary .card .card-body{padding-top:20px;text-align:center}.summary .card .card-body p,.summary .card .card-body h4{font-size:14px}@media(min-width:320px)and (max-width:720px){.primeng-datatable-container .search-filter{display:flex;flex-direction:column;gap:.5rem;justify-content:space-between}}\n"] }]
8450
+ args: [{ selector: 'pw-subscriptions-list', standalone: false, template: "<div class=\"row\">\n <div\n class=\"col-12 d-flex justify-content-between align-items-center\">\n <h2 class=\"card-title p-0 float-start\">Subscriptions</h2>\n <a class=\"btn btn-sm btn-outline-primary float-end\"\n id=\"btn-create\"\n [routerLink]=\"[routers.inviteUsers]\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i> Invite a User to a Trial\n </a>\n </div>\n</div>\n<div class=\"p-2 mt-3\">\n <div class=\"w-100 text-center mt-3\">\n @if (!isLoaded) {\n <p-progressSpinner> </p-progressSpinner>\n }\n </div>\n <div class=\"primeng-datatable-container table-responsive mt-0\"\n [class.hideTable]=\"totalRecordsUnFiltered === 0\">\n <p-table #dt\n [value]=\"subscriptions\"\n [paginator]=\"totalRecords !== 0\"\n [rows]=\"PAGE_SIZE\"\n [lazy]=\"true\"\n [totalRecords]=\"totalRecords\"\n [loading]=\"loading\"\n [filterDelay]=\"1000\"\n (onLazyLoad)=\"onLazyLoad($event)\"\n [customSort]=\"true\">\n <ng-template pTemplate=\"caption\">\n @if (subscriptionInsights) {\n <div class=\"row mb-4\">\n @for (temp of objectKeys(subscriptionInsights); track temp) {\n <div class=\"col-12 col-lg-3 mt-2 summary\">\n <div class=\"card\">\n <div class=\"card-body\">\n @for (item of subscriptionInsights[temp]; track item) {\n <div>\n <p class=\"mb-0 px-2\">{{ item?.title }}\n @if (item?.info) {\n <span\n [pTooltip]=\"item?.info\">\n <i class=\"fas fa-info-circle\"></i>\n </span>\n }\n </p>\n <h4 class=\"fw-bold mt-2 mb-2\">\n {{ item?.value }}\n </h4>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n }\n <div class=\"search-filter\">\n <div class=\"col-12 col-sm-4\">\n <p-multiSelect inputId=\"subscriptions-list-feature-keys\"\n placeholder=\"Select Feature Keys\"\n [showToggleAll]=\"true\"\n [showHeader]=\"true\"\n [(ngModel)]=\"selectedFeatureKeys\"\n [options]=\"searchOptions\"\n (onChange)=\"onSearchOptionChange($event)\"\n appendTo=\"body\">\n </p-multiSelect>\n </div>\n <div class=\"col-12 col-sm-4\">\n <p-select\n inputId=\"subscriptions-list-status\"\n [options]=\"subscriptionStatus\"\n [placeholder]=\"'Select status'\"\n (onChange)=\"filterByStatus($event.value)\"\n [(ngModel)]=\"status\"\n appendTo=\"body\">\n </p-select>\n </div>\n <div class=\"text-end\">\n <label for=\"subscriptions-list-search\" class=\"visually-hidden\">Search Subscription</label>\n <i class=\"fa fa-search mt-2 me-2 d-none\" aria-hidden=\"true\"></i>\n <input type=\"text\"\n id=\"subscriptions-list-search\"\n name=\"subscriptions-list-search\"\n [(ngModel)]=\"searchText\"\n pInputText\n size=\"30\"\n placeholder=\"Search Subscription...\"\n class=\"mw-90\"\n (input)=\"dt.filterGlobal($event.target.value, 'contains')\" />\n </div>\n </div>\n </ng-template>\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"true\"\n pSortableColumn=\"id\">\n {{ 'Admin.Subscriptions.Id' | transloco }}\n <p-sortIcon field=\"id\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"organisation\">\n {{ 'Admin.Subscriptions.Organization' | transloco }}\n <p-sortIcon field=\"organisation\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"contact_name\">\n {{ 'Admin.Subscriptions.ContactName' | transloco }}\n <p-sortIcon field=\"contact_name\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"contact_email\">\n {{ 'Admin.Subscriptions.ContactEmail' | transloco }}\n <p-sortIcon field=\"contact_email\"></p-sortIcon>\n </th>\n <th scope=\"true\">{{ 'Admin.Subscriptions.Product' | transloco }}</th>\n <th scope=\"true\">{{ 'Admin.Subscriptions.Currency' | transloco }}</th>\n <th scope=\"true\">{{ 'Admin.Subscriptions.PricePerMonth' | transloco }}</th>\n <th scope=\"true\"\n pSortableColumn=\"stripe_customer_id\">\n {{ 'Admin.Subscriptions.Paid' | transloco }}\n <p-sortIcon field=\"stripe_customer_id\"></p-sortIcon>\n </th>\n <th scope=\"true\">{{ 'Admin.Subscriptions.Billing' | transloco }}</th>\n <th scope=\"true\"\n class=\"expires-at-width\">\n {{ 'Admin.Subscriptions.ExpiresAt' | transloco }}\n </th>\n <th scope=\"true\"\n pSortableColumn=\"sessions_total\">\n {{ 'Admin.Subscriptions.SessionsTotal' | transloco }}\n <p-sortIcon field=\"sessions_total\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"sessions_last_month\">\n {{ 'Admin.Subscriptions.SessionsTotalLastMonth' | transloco }}\n <p-sortIcon field=\"sessions_last_month\"></p-sortIcon>\n </th>\n <th scope=\"true\"\n pSortableColumn=\"deleted_at\">\n {{ 'Admin.Subscriptions.Deleted' | transloco }}\n <p-sortIcon field=\"deleted_at\"></p-sortIcon>\n </th>\n <th class=\"actions-list-two\"\n scope=\"true\">{{ 'Label.Actions' | transloco }}</th>\n </tr>\n </ng-template>\n <ng-template pTemplate=\"body\"\n let-item>\n <tr>\n <td data-head=\"id\">{{ item.id }}</td>\n <td data-head=\"Organization\">\n <span class=\"cursor-pointer custom-break-word\"\n [pTooltip]=\"item.organisation\"\n tooltipPosition=\"top\">{{ item.organisation | textTruncate: 20 }}</span>\n </td>\n <td data-head=\"ContactName\"\n class=\"custom-break-word\">\n {{ item.contact_name }}\n </td>\n <td data-head=\"ContactEmail\">{{ item.contact_email }}</td>\n <td data-head=\"Name\">\n <span class=\"cursor-pointer custom-break-word\"\n [pTooltip]=\"item.productName\"\n tooltipPosition=\"top\">{{ item.productName }}</span>\n </td>\n <td data-head=\"Currency\">\n <span [appDynamicBadge]=\"{ itemsArray: currency, item: item.currency }\"\n color=\"blue-grey\"\n class=\"badge\">{{ item.currency }}</span>\n </td>\n <td data-head=\"Price/M\">\n <span>{{ (item.price / 100).toFixed(2) | currency:item.currency }}\n @if (item?.discount && objectKeys(item?.discount)?.length) {\n <i\n class=\"fa fa-info-circle\"\n aria-hidden=\"true\"\n [pTooltip]=\"item?.discount | json\"\n tooltipPosition=\"top\"\n ></i>\n }\n </span>\n </td>\n <td data-head=\"Paid\">\n @if (item?.unsubscribed_at) {\n <span class=\"badge bg-warning d-inline-flex align-items-center\">\n Unsub\n @if (item?.reason_to_cancel) {\n <i class=\"fa fa-info-circle ms-2\"\n [pTooltip]=\"item.reason_to_cancel\"\n tooltipPosition=\"top\"\n aria-hidden=\"true\"></i>\n }\n </span>\n }\n @if (!item?.unsubscribed_at) {\n @if ((item?.stripe_customer_id || item?.external_payment) && item?.signed_up_at) {\n <span class=\"badge bg-success\">Yes</span>\n } @else {\n <span class=\"badge bg-blue-grey\">No</span>\n }\n }\n @if (item?.pause_collection && objectKeys(item?.pause_collection)?.length) {\n <span\n class=\"ms-2\"\n [pTooltip]=\"item?.pause_collection | json\"\n tooltipPosition=\"top\">\n <i class=\"fas fa-exclamation-triangle text-warning\"></i>\n </span>\n }\n </td>\n <td data-head=\"Billing\">\n <span class=\"badge\"\n [appDynamicBadge]=\"{\n itemsArray: billingFrequency,\n item: item?.billingFrequency\n }\"\n color=\"blue-grey\">{{ item.billingFrequency }}</span>\n </td>\n <td data-head=\"Expires\">\n <span [ngClass]=\"getExpiresAtColor(item)\">{{item?.expires_at | dateFormat}}</span><br />\n <span>{{item?.created_at | sinceAgo}}</span>\n </td>\n <td data-head=\"S#\">{{ item?.sessions_total }}</td>\n <td data-head=\"S/m #\">\n <span [ngClass]=\"{\n 'text-danger fw-bold': item?.sessions_last_month < 3\n }\">{{ item?.sessions_last_month }}</span>\n </td>\n <td data-head=\"Deleted\">\n @if (item?.deleted_at) {\n <span\n class=\"badge bg-danger\">Yes</span>\n }\n @if (!item?.deleted_at) {\n <span\n class=\"badge bg-blue-grey\">No</span>\n }\n </td>\n <td data-head=\"Action\">\n <ul class=\"list-unstyled list-inline list-action\">\n <li ngbTooltip=\"Edit\"\n class=\"me-2 me-sm-3\"\n [routerLink]=\"[routers.subscriptionDetails, item.id]\">\n <i class=\"fa fa-edit edit-icon\" aria-hidden=\"true\"></i>\n </li>\n @if (item.deleted) {\n <li ngbTooltip=\"Reactivate subscription\"\n class=\"me-2 me-sm-3\"\n *rbacAllow=\"'Pages.Alpha'\"\n (keydown.enter)=\"openRecoverSubscriptionModal(item)\"\n (click)=\"openRecoverSubscriptionModal(item)\">\n <i class=\"fa fa-trash delete-icon text-success\" aria-hidden=\"true\"></i>\n </li>\n } @else {\n <li ngbTooltip=\"Delete\"\n class=\"me-2 me-sm-3\"\n *rbacAllow=\"'Pages.Admin.Subscription.Delete'\"\n (keydown.enter)=\"onDelete(item)\"\n (click)=\"onDelete(item)\">\n <i class=\"fa fa-trash delete-icon\" aria-hidden=\"true\"></i>\n </li>\n }\n </ul>\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (totalRecords === 0 && totalRecordsUnFiltered !== 0) {\n <div>\n <pw-no-data [withImage]=\"true\" [message]=\"'Search.NoDataMessage' | transloco\" [description]=\"'Search.NoDataDescription' | transloco\" >\n </pw-no-data>\n </div>\n }\n @if (totalRecords !== 0) {\n <span class=\"total-records-count\">{{ 'Label.Total' | transloco }}: {{ totalRecords }}</span>\n }\n </div>\n</div>\n@if (totalRecordsUnFiltered === 0 && isLoaded) {\n <pw-no-data [withImage]=\"true\" [message]=\"'Admin.Subscriptions.NoSubscriptionMessage' | transloco\">\n </pw-no-data>\n}\n<pw-password-validation\n #recoverSubscriptionPasswordModal\n (successEvent)=\"onRecoverConfirmed()\">\n</pw-password-validation>\n\n", styles: [":root{--first: rgb(23 105 225);--second: rgb(54 194 131);--third: rgb(255 171 0);--text: rgb(34 34 34);--tabs_bg: rgb(23 105 225);--tabs_sub_bg: rgb(70, 136, 236);--tabs_text: rgb(255 255 255);--titles: rgb(34 34 34);--sidebar_bg: rgb(0, 48, 63);--sidebar_text: rgb(255 255 255)}@media(min-width:767px){.table-responsive td,.table-responsive th{font-size:11px!important}}.expires-at-width{width:8%}.custom-break-word{word-break:break-word!important}.summary .card{padding-bottom:0}.summary .card .card-body{padding-top:20px;text-align:center}.summary .card .card-body p,.summary .card .card-body h4{font-size:14px}@media(min-width:320px)and (max-width:720px){.primeng-datatable-container .search-filter{display:flex;flex-direction:column;gap:.5rem;justify-content:space-between}}\n"] }]
8083
8451
  }], ctorParameters: () => [{ type: i1$2.ProductService }, { type: i1.AdminService }, { type: i6.UntypedFormBuilder }, { type: i0.Injector }, { type: i0.ChangeDetectorRef }, { type: i1$2.CommonService }], propDecorators: { refProduct: [{
8084
8452
  type: ViewChild,
8085
8453
  args: ['refProduct']
@@ -10427,6 +10795,54 @@ const routes = [
10427
10795
  }
10428
10796
  ]
10429
10797
  },
10798
+ {
10799
+ path: 'feature-flags',
10800
+ data: {
10801
+ title: 'Feature Flags',
10802
+ permission: 'Pages.Admin'
10803
+ },
10804
+ children: [
10805
+ {
10806
+ path: '',
10807
+ component: FeatureFlagsTabsComponent,
10808
+ children: [
10809
+ {
10810
+ path: '',
10811
+ redirectTo: 'list',
10812
+ pathMatch: 'full'
10813
+ },
10814
+ {
10815
+ path: 'list',
10816
+ component: FeatureFlagsListComponent
10817
+ }
10818
+ ]
10819
+ },
10820
+ {
10821
+ path: 'add',
10822
+ component: FeatureFlagDetailsComponent,
10823
+ data: {
10824
+ title: 'Add Feature Flag',
10825
+ permission: 'Pages.Admin'
10826
+ }
10827
+ },
10828
+ {
10829
+ path: ':id',
10830
+ component: FeatureFlagDetailsComponent,
10831
+ data: {
10832
+ title: 'Edit Feature Flag',
10833
+ permission: 'Pages.Admin'
10834
+ }
10835
+ },
10836
+ {
10837
+ path: 'rules/:id',
10838
+ component: FeatureFlagRulesComponent,
10839
+ data: {
10840
+ title: 'Feature Flag Rules',
10841
+ permission: 'Pages.Admin'
10842
+ }
10843
+ }
10844
+ ]
10845
+ },
10430
10846
  {
10431
10847
  path: 'faq',
10432
10848
  data: {
@@ -11225,6 +11641,10 @@ class AdminModule {
11225
11641
  LoginNotificationDetailsComponent,
11226
11642
  FeedbackQuestionsListComponent,
11227
11643
  FeedbackQuestionsDetailsComponent,
11644
+ FeatureFlagsListComponent,
11645
+ FeatureFlagDetailsComponent,
11646
+ FeatureFlagRulesComponent,
11647
+ FeatureFlagsTabsComponent,
11228
11648
  UserDetailsComponent,
11229
11649
  ProductsTabComponent,
11230
11650
  SubscriptionDetailsComponent,
@@ -11404,6 +11824,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
11404
11824
  LoginNotificationDetailsComponent,
11405
11825
  FeedbackQuestionsListComponent,
11406
11826
  FeedbackQuestionsDetailsComponent,
11827
+ FeatureFlagsListComponent,
11828
+ FeatureFlagDetailsComponent,
11829
+ FeatureFlagRulesComponent,
11830
+ FeatureFlagsTabsComponent,
11407
11831
  UserDetailsComponent,
11408
11832
  ProductsTabComponent,
11409
11833
  SubscriptionDetailsComponent,
@@ -11543,13 +11967,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
11543
11967
  }] });
11544
11968
 
11545
11969
  class AdminGuardService {
11546
- constructor(userService, router, permissionService) {
11970
+ constructor(userService, router, featureFlagService, permissionService) {
11547
11971
  this.userService = userService;
11548
11972
  this.router = router;
11973
+ this.featureFlagService = featureFlagService;
11549
11974
  this.permissionService = permissionService;
11550
11975
  }
11551
11976
  canLoad(route) {
11552
11977
  return this.userService.getUserInfo().pipe(take(1), concatMap(user => {
11978
+ this.featureFlagService.user = user;
11553
11979
  this.permissionService.user = user;
11554
11980
  if (route.data && this.permissionService.isGranted(route.data['permission'])) {
11555
11981
  return of(true);
@@ -11570,12 +11996,12 @@ class AdminGuardService {
11570
11996
  return of(false);
11571
11997
  }));
11572
11998
  }
11573
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: AdminGuardService, deps: [{ token: i1$2.UserService }, { token: i10.Router }, { token: i1$2.PermissionService }], target: i0.ɵɵFactoryTarget.Injectable }); }
11999
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: AdminGuardService, deps: [{ token: i1$2.UserService }, { token: i10.Router }, { token: i1$2.FeatureFlagService }, { token: i1$2.PermissionService }], target: i0.ɵɵFactoryTarget.Injectable }); }
11574
12000
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: AdminGuardService }); }
11575
12001
  }
11576
12002
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: AdminGuardService, decorators: [{
11577
12003
  type: Injectable
11578
- }], ctorParameters: () => [{ type: i1$2.UserService }, { type: i10.Router }, { type: i1$2.PermissionService }] });
12004
+ }], ctorParameters: () => [{ type: i1$2.UserService }, { type: i10.Router }, { type: i1$2.FeatureFlagService }, { type: i1$2.PermissionService }] });
11579
12005
 
11580
12006
  // Admin
11581
12007