@posiwise/admin-module 0.0.251 → 0.0.252
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i5$2 from "@angular/common";
|
|
2
2
|
import { CommonModule, DatePipe } from "@angular/common";
|
|
3
3
|
import * as i0 from "@angular/core";
|
|
4
|
-
import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, EventEmitter, Injectable, NgModule, Output, Pipe, SecurityContext, ViewChild, ViewChildren, ViewEncapsulation } from "@angular/core";
|
|
4
|
+
import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, Component, DestroyRef, EventEmitter, Injectable, Input, NgModule, Output, Pipe, SecurityContext, ViewChild, ViewChildren, ViewEncapsulation, inject } from "@angular/core";
|
|
5
5
|
import * as i10 from "@angular/forms";
|
|
6
6
|
import { FormsModule, ReactiveFormsModule, UntypedFormControl, Validators } from "@angular/forms";
|
|
7
7
|
import * as i13 from "@angular-magic/ngx-gp-autocomplete";
|
|
@@ -75,6 +75,7 @@ import { Subject, finalize, forkJoin, map, of, takeUntil } from "rxjs";
|
|
|
75
75
|
import { catchError, concatMap, debounceTime, filter, finalize as finalize$1, map as map$1, switchMap, take } from "rxjs/operators";
|
|
76
76
|
import * as i3 from "@angular/platform-browser";
|
|
77
77
|
import * as i4$1 from "primeng/tabs";
|
|
78
|
+
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
|
78
79
|
import uniqBy from "lodash/uniqBy";
|
|
79
80
|
import moment from "moment";
|
|
80
81
|
import { StatusCodes } from "http-status-codes";
|
|
@@ -17808,6 +17809,244 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
17808
17809
|
{ type: i6$2.ConfirmDialogService }
|
|
17809
17810
|
]
|
|
17810
17811
|
});
|
|
17812
|
+
const DEFAULT_PROVIDER = "airwallex";
|
|
17813
|
+
var ProductBackupCardComponent = class ProductBackupCardComponent {
|
|
17814
|
+
constructor() {
|
|
17815
|
+
this.submitted = false;
|
|
17816
|
+
this.destroyRef = inject(DestroyRef);
|
|
17817
|
+
this.providers = [{
|
|
17818
|
+
label: "Airwallex",
|
|
17819
|
+
value: "airwallex"
|
|
17820
|
+
}, {
|
|
17821
|
+
label: "Braintree",
|
|
17822
|
+
value: "braintree"
|
|
17823
|
+
}];
|
|
17824
|
+
}
|
|
17825
|
+
ngOnInit() {
|
|
17826
|
+
if (!this.form.contains("second_payment_provider")) this.form.addControl("second_payment_provider", new UntypedFormControl(this.provider || DEFAULT_PROVIDER));
|
|
17827
|
+
const control = this.form.get("second_payment_provider");
|
|
17828
|
+
control.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((value) => {
|
|
17829
|
+
if (!value) control.setValue(DEFAULT_PROVIDER, { emitEvent: false });
|
|
17830
|
+
});
|
|
17831
|
+
if (!control.value) control.setValue(DEFAULT_PROVIDER, { emitEvent: false });
|
|
17832
|
+
}
|
|
17833
|
+
get required() {
|
|
17834
|
+
return !!this.form.get("second_payment_required")?.value;
|
|
17835
|
+
}
|
|
17836
|
+
static {
|
|
17837
|
+
this.ɵfac = i0.ɵɵngDeclareFactory({
|
|
17838
|
+
minVersion: "12.0.0",
|
|
17839
|
+
version: "22.2.0",
|
|
17840
|
+
ngImport: i0,
|
|
17841
|
+
type: ProductBackupCardComponent,
|
|
17842
|
+
deps: [],
|
|
17843
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
17844
|
+
});
|
|
17845
|
+
}
|
|
17846
|
+
static {
|
|
17847
|
+
this.ɵcmp = i0.ɵɵngDeclareComponent({
|
|
17848
|
+
minVersion: "17.0.0",
|
|
17849
|
+
version: "22.2.0",
|
|
17850
|
+
type: ProductBackupCardComponent,
|
|
17851
|
+
isStandalone: false,
|
|
17852
|
+
selector: "pw-product-backup-card",
|
|
17853
|
+
inputs: {
|
|
17854
|
+
form: "form",
|
|
17855
|
+
provider: "provider",
|
|
17856
|
+
submitted: "submitted"
|
|
17857
|
+
},
|
|
17858
|
+
host: { classAttribute: "col-12 col-md-8" },
|
|
17859
|
+
ngImport: i0,
|
|
17860
|
+
template: "<div class=\"row\" [formGroup]=\"form\">\n <div class=\"col-12 col-md-6\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.SecondPaymentRequired' | transloco\"\n [label]=\"'Admin.Products.SecondPaymentRequired' | transloco\" name=\"second_payment_required\" controlId=\"product-second_payment_required\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"second_payment_required\" name=\"second_payment_required\"\n [attr.aria-labelledby]=\"'product-second_payment_required-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && form.get('second_payment_required')?.errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n @if (required) {\n <div class=\"col-12 col-md-6\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.SecondPaymentProvider' | transloco\"\n [label]=\"'Admin.Products.SecondPaymentProvider' | transloco\" name=\"second_payment_provider\" controlId=\"product-second_payment_provider\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-second_payment_provider-label'\"\n [options]=\"providers\"\n formControlName=\"second_payment_provider\"\n optionValue=\"value\"\n optionLabel=\"label\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n }\n</div>\n",
|
|
17861
|
+
dependencies: [
|
|
17862
|
+
{
|
|
17863
|
+
kind: "component",
|
|
17864
|
+
type: i2$2.Select,
|
|
17865
|
+
selector: "p-select",
|
|
17866
|
+
inputs: [
|
|
17867
|
+
"id",
|
|
17868
|
+
"scrollHeight",
|
|
17869
|
+
"filter",
|
|
17870
|
+
"panelStyle",
|
|
17871
|
+
"panelStyleClass",
|
|
17872
|
+
"readonly",
|
|
17873
|
+
"editable",
|
|
17874
|
+
"tabindex",
|
|
17875
|
+
"placeholder",
|
|
17876
|
+
"loadingIcon",
|
|
17877
|
+
"filterPlaceholder",
|
|
17878
|
+
"filterLocale",
|
|
17879
|
+
"inputId",
|
|
17880
|
+
"dataKey",
|
|
17881
|
+
"filterBy",
|
|
17882
|
+
"filterFields",
|
|
17883
|
+
"autofocus",
|
|
17884
|
+
"resetFilterOnHide",
|
|
17885
|
+
"checkmark",
|
|
17886
|
+
"dropdownIcon",
|
|
17887
|
+
"loading",
|
|
17888
|
+
"optionLabel",
|
|
17889
|
+
"optionValue",
|
|
17890
|
+
"optionDisabled",
|
|
17891
|
+
"optionGroupLabel",
|
|
17892
|
+
"optionGroupChildren",
|
|
17893
|
+
"group",
|
|
17894
|
+
"showClear",
|
|
17895
|
+
"emptyFilterMessage",
|
|
17896
|
+
"emptyMessage",
|
|
17897
|
+
"lazy",
|
|
17898
|
+
"virtualScroll",
|
|
17899
|
+
"virtualScrollItemSize",
|
|
17900
|
+
"virtualScrollOptions",
|
|
17901
|
+
"overlayOptions",
|
|
17902
|
+
"ariaFilterLabel",
|
|
17903
|
+
"ariaLabel",
|
|
17904
|
+
"ariaLabelledBy",
|
|
17905
|
+
"filterMatchMode",
|
|
17906
|
+
"tooltip",
|
|
17907
|
+
"tooltipPosition",
|
|
17908
|
+
"tooltipPositionStyle",
|
|
17909
|
+
"tooltipStyleClass",
|
|
17910
|
+
"focusOnHover",
|
|
17911
|
+
"selectOnFocus",
|
|
17912
|
+
"multiple",
|
|
17913
|
+
"autoOptionFocus",
|
|
17914
|
+
"autofocusFilter",
|
|
17915
|
+
"filterValue",
|
|
17916
|
+
"options",
|
|
17917
|
+
"appendTo",
|
|
17918
|
+
"motionOptions"
|
|
17919
|
+
],
|
|
17920
|
+
outputs: [
|
|
17921
|
+
"onChange",
|
|
17922
|
+
"onFilter",
|
|
17923
|
+
"onFocus",
|
|
17924
|
+
"onBlur",
|
|
17925
|
+
"onClick",
|
|
17926
|
+
"onShow",
|
|
17927
|
+
"onHide",
|
|
17928
|
+
"onClear",
|
|
17929
|
+
"onLazyLoad"
|
|
17930
|
+
]
|
|
17931
|
+
},
|
|
17932
|
+
{
|
|
17933
|
+
kind: "directive",
|
|
17934
|
+
type: i5$2.NgClass,
|
|
17935
|
+
selector: "[ngClass]",
|
|
17936
|
+
inputs: ["class", "ngClass"]
|
|
17937
|
+
},
|
|
17938
|
+
{
|
|
17939
|
+
kind: "directive",
|
|
17940
|
+
type: i10.NgControlStatus,
|
|
17941
|
+
selector: "[formControlName],[ngModel],[formControl]"
|
|
17942
|
+
},
|
|
17943
|
+
{
|
|
17944
|
+
kind: "directive",
|
|
17945
|
+
type: i10.NgControlStatusGroup,
|
|
17946
|
+
selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]"
|
|
17947
|
+
},
|
|
17948
|
+
{
|
|
17949
|
+
kind: "component",
|
|
17950
|
+
type: i5.UiSwitchComponent,
|
|
17951
|
+
selector: "ui-switch",
|
|
17952
|
+
inputs: [
|
|
17953
|
+
"size",
|
|
17954
|
+
"color",
|
|
17955
|
+
"switchOffColor",
|
|
17956
|
+
"switchColor",
|
|
17957
|
+
"defaultBgColor",
|
|
17958
|
+
"defaultBoColor",
|
|
17959
|
+
"checkedLabel",
|
|
17960
|
+
"uncheckedLabel",
|
|
17961
|
+
"checkedTextColor",
|
|
17962
|
+
"uncheckedTextColor",
|
|
17963
|
+
"beforeChange",
|
|
17964
|
+
"ariaLabel",
|
|
17965
|
+
"checked",
|
|
17966
|
+
"disabled",
|
|
17967
|
+
"reverse",
|
|
17968
|
+
"loading"
|
|
17969
|
+
],
|
|
17970
|
+
outputs: [
|
|
17971
|
+
"change",
|
|
17972
|
+
"changeEvent",
|
|
17973
|
+
"valueChange"
|
|
17974
|
+
]
|
|
17975
|
+
},
|
|
17976
|
+
{
|
|
17977
|
+
kind: "component",
|
|
17978
|
+
type: i6$2.InputContainerComponent,
|
|
17979
|
+
selector: "pw-input-container",
|
|
17980
|
+
inputs: [
|
|
17981
|
+
"name",
|
|
17982
|
+
"controlId",
|
|
17983
|
+
"useAriaLabelledbyOnly",
|
|
17984
|
+
"label",
|
|
17985
|
+
"labelClass",
|
|
17986
|
+
"tooltipPosition",
|
|
17987
|
+
"required",
|
|
17988
|
+
"errorMsg",
|
|
17989
|
+
"isReadOnly",
|
|
17990
|
+
"showTooltip",
|
|
17991
|
+
"tooltipText",
|
|
17992
|
+
"showTriangle",
|
|
17993
|
+
"afterLabel",
|
|
17994
|
+
"showAfterLabel",
|
|
17995
|
+
"showTriangleText",
|
|
17996
|
+
"isLeftTooltip"
|
|
17997
|
+
]
|
|
17998
|
+
},
|
|
17999
|
+
{
|
|
18000
|
+
kind: "directive",
|
|
18001
|
+
type: i10.FormGroupDirective,
|
|
18002
|
+
selector: "[formGroup]",
|
|
18003
|
+
inputs: ["formGroup"],
|
|
18004
|
+
outputs: ["ngSubmit"],
|
|
18005
|
+
exportAs: ["ngForm"]
|
|
18006
|
+
},
|
|
18007
|
+
{
|
|
18008
|
+
kind: "directive",
|
|
18009
|
+
type: i10.FormControlName,
|
|
18010
|
+
selector: "[formControlName]",
|
|
18011
|
+
inputs: [
|
|
18012
|
+
"formControlName",
|
|
18013
|
+
"disabled",
|
|
18014
|
+
"ngModel"
|
|
18015
|
+
],
|
|
18016
|
+
outputs: ["ngModelChange"]
|
|
18017
|
+
},
|
|
18018
|
+
{
|
|
18019
|
+
kind: "pipe",
|
|
18020
|
+
type: i8$2.TranslocoPipe,
|
|
18021
|
+
name: "transloco"
|
|
18022
|
+
}
|
|
18023
|
+
]
|
|
18024
|
+
});
|
|
18025
|
+
}
|
|
18026
|
+
};
|
|
18027
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
18028
|
+
minVersion: "12.0.0",
|
|
18029
|
+
version: "22.2.0",
|
|
18030
|
+
ngImport: i0,
|
|
18031
|
+
type: ProductBackupCardComponent,
|
|
18032
|
+
decorators: [{
|
|
18033
|
+
type: Component,
|
|
18034
|
+
args: [{
|
|
18035
|
+
selector: "pw-product-backup-card",
|
|
18036
|
+
host: { class: "col-12 col-md-8" },
|
|
18037
|
+
standalone: false,
|
|
18038
|
+
template: "<div class=\"row\" [formGroup]=\"form\">\n <div class=\"col-12 col-md-6\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.SecondPaymentRequired' | transloco\"\n [label]=\"'Admin.Products.SecondPaymentRequired' | transloco\" name=\"second_payment_required\" controlId=\"product-second_payment_required\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"second_payment_required\" name=\"second_payment_required\"\n [attr.aria-labelledby]=\"'product-second_payment_required-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && form.get('second_payment_required')?.errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n @if (required) {\n <div class=\"col-12 col-md-6\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.SecondPaymentProvider' | transloco\"\n [label]=\"'Admin.Products.SecondPaymentProvider' | transloco\" name=\"second_payment_provider\" controlId=\"product-second_payment_provider\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-second_payment_provider-label'\"\n [options]=\"providers\"\n formControlName=\"second_payment_provider\"\n optionValue=\"value\"\n optionLabel=\"label\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n }\n</div>\n"
|
|
18039
|
+
}]
|
|
18040
|
+
}],
|
|
18041
|
+
propDecorators: {
|
|
18042
|
+
form: [{
|
|
18043
|
+
type: Input,
|
|
18044
|
+
args: [{ required: true }]
|
|
18045
|
+
}],
|
|
18046
|
+
provider: [{ type: Input }],
|
|
18047
|
+
submitted: [{ type: Input }]
|
|
18048
|
+
}
|
|
18049
|
+
});
|
|
17811
18050
|
var ProductDetailsComponent = class ProductDetailsComponent extends AppBaseComponent {
|
|
17812
18051
|
constructor(injector, cdr, productService, modalService, adminService) {
|
|
17813
18052
|
super(injector);
|
|
@@ -18147,7 +18386,7 @@ var ProductDetailsComponent = class ProductDetailsComponent extends AppBaseCompo
|
|
|
18147
18386
|
selector: "pw-product-details",
|
|
18148
18387
|
usesInheritance: true,
|
|
18149
18388
|
ngImport: i0,
|
|
18150
|
-
template: "<div class=\"container-fluid pw-tab product-form overflow-hidden\">\n <div class=\"dashboard\">\n <div class=\"dashboard-body\">\n <div class=\"me-auto col-xs-6 mt-4\">\n <a (click)=\"back()\" class=\"previous\" aria-label=\"Back\"><i class=\"fa fa-arrow-alt-circle-left\"\n aria-hidden=\"true\"></i></a>\n <h3 class=\"\">Product: {{ data?.name ? data?.name : 'Add New' }}</h3>\n </div>\n @if (isLoading) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progress-spinner strokeWidth=\"2\"> </p-progress-spinner>\n </div>\n }\n @if (!isLoading) {\n <div class=\"my-4\">\n <div class=\"mb-5\">\n <p-accordion class=\"pw-accordion-info\">\n <p-accordion-panel value=\"0\">\n <p-accordion-header>\n <i class=\"far fa-circle-info me-2 text-muted\"></i> How to configure a product\n </p-accordion-header>\n <p-accordion-content>\n <div class=\"row g-4 product-howto\">\n <div class=\"col-12 col-lg-7\">\n <h6 class=\"howto-title\">Product / feature binding</h6>\n <dl class=\"howto-defs\">\n <dt><code>category</code></dt>\n <dd>The product type — e.g. <code>seat_pricing</code> or <code>item_pricing</code>.</dd>\n <dt><code>feature_key</code></dt>\n <dd>Describes the main feature.</dd>\n <dt><code>permission_key</code></dt>\n <dd>A user can be subscribed to only one product per <code>permission_key</code>.</dd>\n <dt><code>product_key</code></dt>\n <dd>Unique per product; drives the frontend permission binding.</dd>\n </dl>\n <p class=\"howto-note\">\n Resulting permission key:\n <code>{{ 'Pages.Product.{permission_key}.{product_key}' }}</code>.\n For a feature tied to an existing product, set its <strong>dependency product</strong> accordingly.\n </p>\n </div>\n <div class=\"col-12 col-lg-5\">\n <h6 class=\"howto-title\">Setting up a free product</h6>\n <ul class=\"howto-list\">\n <li>Leave <code>Stripe Plan</code> empty.</li>\n <li>Set <code>Price per unit</code> to <code>0</code>.</li>\n <li>Set <code>Trial days</code> to a large value (e.g. <code>99999</code>).</li>\n <li>Turn <code>Visible</code> off.</li>\n </ul>\n </div>\n </div>\n </p-accordion-content>\n </p-accordion-panel>\n </p-accordion>\n </div>\n </div>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSave()\">\n <h3>{{ 'Admin.Products.Section.Identity' | transloco }}</h3>\n @if (id) {\n <div class=\"row\">\n <div class=\"col-md-6\">\n <div class=\"text-start mt-3\">\n <div class=\"image-container\">\n <h4 class=\"mb-2\"> {{ 'User.Subscriptions.FullLogo' | transloco }} <span class=\"tooltip-wrap ms-1\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.FullLogo'|transloco\" [appendTo]=\"'body'\"\n [tooltipPosition]=\"'top'\">\n <i class=\"far fa-info-circle text-muted\"></i>\n </span>\n </h4>\n @if (fullLogo && !fullLogo.includes('no_image_uploaded') && !fullLogoBroken) {\n <img [src]=\"fullLogo\" alt=\"Demo Logo\" class=\"image full-logo\"\n role=\"presentation\" (error)=\"fullLogoBroken = true\" />\n <div class=\"overlay mt-2\" (click)=\"openModal(content)\" (keydown.enter)=\"openModal(content)\">\n <div class=\"overlay-text\">\n <a>{{ 'User.Profile.Change' | transloco }}</a>\n </div>\n </div>\n } @else {\n <div class=\"logo-dropzone full-dropzone\" role=\"button\" tabindex=\"0\"\n aria-label=\"Upload full logo\" (keydown.enter)=\"openModal(content)\" (click)=\"openModal(content)\">\n <i class=\"fas fa-upload\"></i>\n <span class=\"dropzone-title\">Upload a logo</span>\n <span class=\"dropzone-hint\">PNG or JPG</span>\n </div>\n }\n </div>\n </div>\n </div>\n <div class=\"col-md-6\">\n <div class=\"text-start mt-3\">\n <div class=\"image-container\">\n <h4 class=\"mb-2\"> {{ 'User.Subscriptions.SquaredLogo' | transloco }} <span class=\"tooltip-wrap ms-1\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.SquaredLogo'|transloco\" [appendTo]=\"'body'\"\n [tooltipPosition]=\"'top'\">\n <i class=\"far fa-info-circle text-muted\"></i>\n </span>\n </h4>\n @if (squaredLogo && !squaredLogo.includes('no_image_uploaded') && !squaredLogoBroken) {\n <img [src]=\"squaredLogo\" alt=\"Company Logo\" class=\"squared_logo\"\n role=\"presentation\" (error)=\"squaredLogoBroken = true\" />\n <div class=\"overlay mt-2\" (keydown.enter)=\"openModal(squaredLogoContent)\" (click)=\"openModal(squaredLogoContent)\">\n <div class=\"overlay-text\">\n <a>{{ 'User.Profile.Change' | transloco }}</a>\n </div>\n </div>\n } @else {\n <div class=\"logo-dropzone squared-dropzone\" role=\"button\" tabindex=\"0\"\n aria-label=\"Upload squared logo\" (keydown.enter)=\"openModal(squaredLogoContent)\" (click)=\"openModal(squaredLogoContent)\">\n <i class=\"fas fa-upload\"></i>\n <span class=\"dropzone-title\">Upload a logo</span>\n <span class=\"dropzone-hint\">PNG or JPG</span>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n }\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Name' | transloco\"\n [label]=\"'Label.Name' | transloco\" name=\"name\" controlId=\"product-name\"\n [isLeftTooltip]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.Name' | transloco\">\n <input type=\"text\" id=\"product-name\" class=\"form-control\" formControlName=\"name\"\n [placeholder]=\"'Admin.Products.Placeholder.Name' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f['name'].errors }\"\n [attr.aria-label]=\"'Label.Name' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.NickName' | transloco\"\n [label]=\"'Admin.Products.NickName' | transloco\" name=\"nickname\" controlId=\"product-nickname\"\n [errorMsg]=\"'Admin.Products.Validation.NickName' | transloco\">\n <input type=\"text\" id=\"product-nickname\" class=\"form-control\" formControlName=\"nickname\"\n [placeholder]=\"'Admin.Products.Placeholder.NickName' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f['nickname'].errors }\"\n [attr.aria-label]=\"'Admin.Products.NickName' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.DocumentationUrl' | transloco\"\n [label]=\"'Admin.Products.DocumentationUrl' | transloco\" name=\"documentation_url\" controlId=\"product-documentation_url\">\n <input type=\"text\" id=\"product-documentation_url\" class=\"form-control\" formControlName=\"documentation_url\"\n [placeholder]=\"'Admin.Products.Placeholder.DocumentationUrl' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['documentation_url'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.DocumentationUrl' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12\" id=\"descriptionEditor\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Description' | transloco\"\n [label]=\"'Admin.Products.Description' | transloco\" name=\"description\" controlId=\"product-description\" [useAriaLabelledbyOnly]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.Description' | transloco\">\n <quill-editor [attr.aria-labelledby]=\"'product-description-label'\" [styles]=\"{ height: '220px' }\" formControlName=\"description\" class=\"quillEditor\" [modules]=\"editorConfig\"\n [placeholder]=\"'Admin.Products.Placeholder.Description' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f['description'].errors, 'quill-container': true}\">\n </quill-editor>\n </pw-input-container>\n </div>\n </div>\n\n <!-- Section: Pricing & Billing -->\n <h3>{{ 'Admin.Products.Section.Pricing' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Price' | transloco\"\n [isLeftTooltip]=\"true\"\n [label]=\"'Admin.Products.Price' | transloco\" name=\"price_per_unit\" controlId=\"product-price_per_unit\"\n [errorMsg]=\"'Admin.Products.Validation.Name' | transloco\">\n <input type=\"text\" id=\"product-price_per_unit\" numbersOnly class=\"form-control\" formControlName=\"price_per_unit\"\n [placeholder]=\"'Admin.Products.Placeholder.Price' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['price_per_unit'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.Price' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n @if (supportedCurrency$ | async; as currency) {\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Currency' | transloco\"\n [label]=\"'Admin.Products.Currency' | transloco\" name=\"currency\" controlId=\"product-currency\" [useAriaLabelledbyOnly]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.Currency' | transloco\">\n <p-select\n [attr.aria-labelledby]=\"'product-currency-label'\"\n [options]=\"currency['regions']\"\n formControlName=\"currency\"\n [ngClass]=\"{ 'is-invalid': submitted && f['currency'].errors }\"\n [placeholder]=\"'Admin.Products.Placeholder.Currency' | transloco\"\n [showClear]=\"false\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n }\n @if (supportedRegions$ | async; as region) {\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Region' | transloco\"\n [isLeftTooltip]=\"true\"\n [label]=\"'Admin.Products.Region' | transloco\" name=\"region\" controlId=\"product-region\" [useAriaLabelledbyOnly]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.Region' | transloco\">\n <p-select\n [attr.aria-labelledby]=\"'product-region-label'\"\n [options]=\"region['regions']\"\n formControlName=\"region\"\n [ngClass]=\"{ 'is-invalid': submitted && f['region'].errors }\"\n [placeholder]=\"'Admin.Products.Placeholder.Region' | transloco\"\n [showClear]=\"false\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n }\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.BillingFrequency' | transloco\"\n [label]=\"'Admin.Products.BillingFrequency' | transloco\" name=\"billing_frequency\" controlId=\"product-billing_frequency\" [useAriaLabelledbyOnly]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.BillingFrequency' | transloco\">\n <p-select inputId=\"product-billing_frequency\"\n [options]=\"frequency\" class=\"dropdown-bg-transparent\" [attr.aria-labelledby]=\"'product-billing_frequency-label'\" formControlName=\"billing_frequency\"\n [placeholder]=\"'Admin.Products.Placeholder.BillingFrequency' | transloco\"\n [required]=\"true\" [ngClass]=\"{\n 'is-invalid': submitted && f['billing_frequency'].errors\n }\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Admin.Products.MinUnit' | transloco\" [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MinUnits' | transloco\" name=\"min_units\" controlId=\"product-min_units\"\n [errorMsg]=\"'Admin.Products.Validation.MinUnit' | transloco\">\n <input type=\"number\" id=\"product-min_units\" min=\"1\" class=\"form-control\" formControlName=\"min_units\" [ngClass]=\"{\n 'is-invalid': submitted && f['min_units'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.MinUnit' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Admin.Products.MaxUnit' | transloco\" [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MaxUnits' | transloco\" name=\"max_units\" controlId=\"product-max_units\"\n [errorMsg]=\"'Admin.Products.Validation.MaxUnit' | transloco\">\n <input type=\"number\" id=\"product-max_units\" min=\"1\" class=\"form-control\" formControlName=\"max_units\" [ngClass]=\"{\n 'is-invalid': submitted && f['max_units'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.MaxUnit' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.StripePlan' | transloco\"\n [label]=\"'Admin.Products.StripePlan' | transloco\" name=\"stripe_plan_id\" controlId=\"product-stripe_plan_id\">\n <input type=\"text\" id=\"product-stripe_plan_id\" class=\"form-control\" formControlName=\"stripe_plan_id\"\n [placeholder]=\"'Admin.Products.Placeholder.StripePlan' | transloco\"\n [attr.aria-label]=\"'Admin.Products.StripePlan' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'Pages.Alpha'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.ProrationBehavior' | transloco\"\n [label]=\"'Admin.Products.ProrationBehavior' | transloco\" name=\"proration_behavior\" controlId=\"product-proration_behavior\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-proration_behavior-label'\"\n [options]=\"prorationBehaviors\"\n formControlName=\"proration_behavior\"\n [placeholder]=\"'Admin.Products.Placeholder.ProrationBehavior' | transloco\"\n optionValue=\"value\"\n optionLabel=\"label\"\n [showClear]=\"true\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'Pages.Alpha'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.UnsubscribeStripeBehavior' | transloco\"\n [label]=\"'Admin.Products.UnsubscribeStripeBehavior' | transloco\" name=\"unsubscribe_stripe_behavior\" controlId=\"product-unsubscribe_stripe_behavior\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-unsubscribe_stripe_behavior-label'\"\n [options]=\"unsubscribeBehaviors\"\n formControlName=\"unsubscribe_stripe_behavior\"\n [placeholder]=\"'Admin.Products.Placeholder.UnsubscribeBehavior' | transloco\"\n optionValue=\"value\"\n optionLabel=\"label\"\n [showClear]=\"true\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'SuperAdmin'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.SecondPaymentRequired' | transloco\"\n [label]=\"'Admin.Products.SecondPaymentRequired' | transloco\" name=\"second_payment_required\" controlId=\"product-second_payment_required\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"second_payment_required\" name=\"second_payment_required\"\n [attr.aria-labelledby]=\"'product-second_payment_required-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['second_payment_required'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n </div>\n\n <!-- Section: Trial -->\n <h3>{{ 'Admin.Products.Section.Trial' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.TrialDays' | transloco\"\n [label]=\"'Admin.Products.TrialDays' | transloco\" name=\"trial_days\" controlId=\"product-trial_days\"\n [errorMsg]=\"'Admin.Products.Validation.TrialDays' | transloco\">\n <input type=\"number\" id=\"product-trial_days\" min=\"0\" class=\"form-control\" formControlName=\"trial_days\" [ngClass]=\"{\n 'is-invalid': submitted && f['trial_days'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.TrialDays' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MaxTrialHits' | transloco\"\n [label]=\"'Admin.Products.MaxTrialHits' | transloco\" name=\"max_hits_trial\" controlId=\"product-max_hits_trial\">\n <input type=\"number\" id=\"product-max_hits_trial\" min=\"0\" class=\"form-control\" formControlName=\"max_hits_trial\" [ngClass]=\"{\n 'is-invalid': submitted && f['max_hits_trial'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.MaxTrialHits' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.TrialHits' | transloco\"\n [label]=\"'Admin.Products.TrialHits' | transloco\" name=\"max_hits\" controlId=\"product-max_hits\">\n <input type=\"number\" id=\"product-max_hits\" min=\"0\" class=\"form-control\" formControlName=\"max_hits\"\n [ngClass]=\"{ 'is-invalid': submitted && f['max_hits'].errors }\"\n [attr.aria-label]=\"'Admin.Products.TrialHits' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n </div>\n\n <!-- Section: Feature & Permission Binding -->\n <h3>{{ 'Admin.Products.Section.Binding' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Admin.Products.Category' | transloco\"\n [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.PermissionKey' | transloco\"\n name=\"category\" controlId=\"product-category\" [useAriaLabelledbyOnly]=\"true\" [errorMsg]=\"'Admin.Products.Validation.Category' | transloco\">\n <p-select inputId=\"product-category\"\n [options]=\"categories\" class=\"dropdown-bg-transparent\" [attr.aria-labelledby]=\"'product-category-label'\" formControlName=\"category\"\n [placeholder]=\"'Admin.Products.Placeholder.Category' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f['category'].errors }\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.FeatureKey' | transloco\"\n [label]=\"'Admin.Products.FeatureKey' | transloco\" name=\"feature_key\" controlId=\"product-feature_key\"\n [errorMsg]=\"'Admin.Products.Validation.FeatureKey' | transloco\">\n <input type=\"text\" id=\"product-feature_key\" class=\"form-control\"\n [placeholder]=\"'Admin.Products.Placeholder.FeatureKey' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['feature_key'].errors\n }\" formControlName=\"feature_key\"\n [attr.aria-label]=\"'Admin.Products.FeatureKey' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.PermissionKey' | transloco\"\n [label]=\"'Admin.Products.PermissionKey' | transloco\" name=\"permission_key\" controlId=\"product-permission_key\"\n [errorMsg]=\"'Admin.Products.Validation.PermissionKey' | transloco\">\n <input type=\"text\" id=\"product-permission_key\" class=\"form-control\"\n [placeholder]=\"'Admin.Products.Placeholder.PermissionKey' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['permission_key'].errors\n }\" formControlName=\"permission_key\"\n [attr.aria-label]=\"'Admin.Products.PermissionKey' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Admin.Products.ProductKey' | transloco\"\n [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.PermissionKey' | transloco\"\n name=\"product_key\" controlId=\"product-product_key\"\n [errorMsg]=\"'Admin.Products.Validation.ProductKey' | transloco\">\n <input type=\"text\" id=\"product-product_key\" class=\"form-control\" formControlName=\"product_key\"\n [placeholder]=\"'Admin.Products.Placeholder.ProductKey' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['product_key'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.ProductKey' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <span class=\"pw-label-style\" id=\"product-dependency_products-label\" [pTooltip]=\"'Admin.Products.Tooltip.DependencyProducts' | transloco\" tooltipPosition=\"top\" appendTo=\"body\"> {{ 'Admin.Products.DependencyProducts' | transloco }}<i class=\"far fa-info-circle\" aria-hidden=\"true\"></i>\n </span>\n <p-multiselect inputId=\"product-dependency_products\"\n [options]=\"productsList\" [(ngModel)]=\"selectedScopes\"\n [placeholder]=\"'Admin.Products.Placeholder.DependencyProducts' | transloco\"\n [attr.aria-labelledby]=\"'product-dependency_products-label'\"\n [ngModelOptions]=\"{ standalone: true }\" (onChange)=\"onSearchCriteria($event)\" [showHeader]=\"false\"\n maxSelectedLabels=\"1\" appendTo=\"body\">\n </p-multiselect>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <span class=\"pw-label-style\" id=\"product-roles-label\" [pTooltip]=\"'Admin.Subscriptions.Tooltip.AssignedRoles' | transloco\" tooltipPosition=\"top\" appendTo=\"body\">{{ 'Admin.Products.AssignedRoles' | transloco }} <i class=\"far fa-info-circle\" aria-hidden=\"true\"></i>\n </span>\n <p-multiselect inputId=\"product-roles\" [options]=\"allRoles\" formControlName=\"roles\" appendTo=\"body\"\n [placeholder]=\"'Admin.Products.Placeholder.Roles' | transloco\"\n [attr.aria-labelledby]=\"'product-roles-label'\"></p-multiselect>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'SuperAdmin'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MasterProduct' | transloco\"\n [label]=\"'Admin.Products.MasterProduct' | transloco\" name=\"master_product_id\" controlId=\"product-master_product_id\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-master_product_id-label'\"\n [options]=\"productsList\"\n formControlName=\"master_product_id\"\n [placeholder]=\"'Admin.Products.Placeholder.MasterProduct' | transloco\"\n optionValue=\"value\"\n optionLabel=\"label\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'SuperAdmin'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.IsMasterProduct' | transloco\"\n [label]=\"'Admin.Products.IsMasterProduct' | transloco\" name=\"is_master_product\" controlId=\"product-is_master_product\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"is_master_product\" name=\"is_master_product\"\n [attr.aria-labelledby]=\"'product-is_master_product-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['is_master_product'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'SuperAdmin'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MultipleAllowed' | transloco\"\n [label]=\"'Admin.Products.MultipleAllowed' | transloco\" class=\"nowrap\" name=\"multiple_allowed\" controlId=\"product-multiple_allowed\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"multiple_allowed\" name=\"multiple_allowed\"\n [attr.aria-labelledby]=\"'product-multiple_allowed-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['multiple_allowed'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n </div>\n\n <!-- Section: Onboarding & Signup -->\n <h3>{{ 'Admin.Products.Section.Signup' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-12\" id=\"signupInstructionsEditor\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.SignupInstructions' | transloco\"\n [label]=\"'Admin.Products.SignupInstructions' | transloco\" name=\"signup_instructions\" controlId=\"product-signup_instructions\" [useAriaLabelledbyOnly]=\"true\">\n <quill-editor [attr.aria-labelledby]=\"'product-signup_instructions-label'\" [styles]=\"{ height: '220px' }\" formControlName=\"signup_instructions\" class=\"quillEditor\" [modules]=\"editorConfig\"\n [placeholder]=\"'Admin.Products.Placeholder.SignupInstructions' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['signup_instructions'].errors, 'quill-container': true\n }\">\n </quill-editor>\n </pw-input-container>\n </div>\n <div class=\"col-12\" id=\"signupEmployeesEditor\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.SignupInstructionEmployees' | transloco\"\n [label]=\"'Admin.Products.SignupInstructionEmployees' | transloco\" name=\"signup_instruction_employees\" controlId=\"product-signup_instruction_employees\" [useAriaLabelledbyOnly]=\"true\">\n <quill-editor [attr.aria-labelledby]=\"'product-signup_instruction_employees-label'\" [styles]=\"{ height: '220px' }\" formControlName=\"signup_instruction_employees\" class=\"quillEditor\" [modules]=\"editorConfig\"\n [placeholder]=\"'Admin.Products.Placeholder.SignupInstructionEmployees' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['signup_instruction_employees'].errors, 'quill-container': true\n }\">\n </quill-editor>\n </pw-input-container>\n </div>\n </div>\n\n <!-- Section: Visibility, Support & Compliance -->\n <h3>{{ 'Admin.Products.Section.Visibility' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-6 col-md-3\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.IsActive' | transloco\"\n [label]=\"'Admin.Products.IsActive' | transloco\" name=\"active\" controlId=\"product-active\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"active\" name=\"active\"\n [attr.aria-labelledby]=\"'product-active-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['active'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-6 col-md-3\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.IsVisible' | transloco\"\n [label]=\"'Admin.Products.IsVisible' | transloco\" name=\"visible\" controlId=\"product-visible\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"visible\" name=\"visible\"\n [attr.aria-labelledby]=\"'product-visible-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['visible'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-6 col-md-3\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MembersVisible' | transloco\"\n [label]=\"'Admin.Products.MembersVisible' | transloco\" name=\"members_visible\" controlId=\"product-members_visible\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"members_visible\" name=\"members_visible\"\n [attr.aria-labelledby]=\"'product-members_visible-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['members_visible'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-6 col-md-3\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.ChatVisible' | transloco\"\n [label]=\"'Admin.Products.ChatVisible' | transloco\" name=\"chat_visible\" controlId=\"product-chat_visible\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"chat_visible\" name=\"chat_visible\"\n [attr.aria-labelledby]=\"'product-chat_visible-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['chat_visible'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.ProductPrivacyService' | transloco\"\n [label]=\"'Admin.Products.ProductPrivacyService' | transloco\" name=\"product_privacy_service_id\" controlId=\"product-product_privacy_service_id\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-product_privacy_service_id-label'\"\n [options]=\"allTos\"\n formControlName=\"product_privacy_service_id\"\n [placeholder]=\"'Admin.Products.Placeholder.PrivacyService' | transloco\"\n optionValue=\"id\"\n optionLabel=\"title\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.GitLabServiceDeskEmail' | transloco\"\n [label]=\"'Admin.Products.GitLabServiceDeskEmail' | transloco\" name=\"gitlab_service_desk_email\" controlId=\"product-gitlab_service_desk_email\">\n <input type=\"text\" id=\"product-gitlab_service_desk_email\" class=\"form-control\" formControlName=\"gitlab_service_desk_email\"\n [placeholder]=\"'Admin.Products.Placeholder.GitlabServiceDeskEmail' | transloco\"\n [attr.aria-label]=\"'Admin.Products.GitLabServiceDeskEmail' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.LoginDefaultRoute' | transloco\"\n [label]=\"'Admin.Products.LoginDefaultRoute' | transloco\" name=\"login_default_route\" controlId=\"product-login_default_route\">\n <input type=\"text\" id=\"product-login_default_route\" class=\"form-control\" formControlName=\"login_default_route\"\n [placeholder]=\"'Admin.Products.Placeholder.LoginDefaultRoute' | transloco\"\n [attr.aria-label]=\"'Admin.Products.LoginDefaultRoute' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'Pages.Alpha'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.PartnerProducts' | transloco\"\n [label]=\"'Admin.Products.PartnerProducts' | transloco\" name=\"partner_products\" controlId=\"product-partner_products\" [useAriaLabelledbyOnly]=\"true\">\n <p-multiselect inputId=\"product-partner_products\"\n [options]=\"productsList\" (onChange)=\"onSearchPartnerProducts($event)\"\n [placeholder]=\"'Admin.Products.Placeholder.PartnerProducts' | transloco\"\n [attr.aria-labelledby]=\"'product-partner_products-label'\"\n [ngModelOptions]=\"{ standalone: true }\" [showToggleAll]=\"true\" [(ngModel)]=\"selectedPartnerProducts\"\n [showHeader]=\"true\" maxSelectedLabels=\"1\" appendTo=\"body\">\n </p-multiselect>\n </pw-input-container>\n </div>\n </div>\n </div>\n\n <div class=\"row text-end mt-4\">\n <div class=\"col-12\">\n <button type=\"button\" class=\"btn btn-outline-default me-2\" (click)=\"back()\"> {{ 'Button.Cancel' |\n transloco }} </button>\n <button type=\"submit\" [buttonBusy]=\"submitted\" class=\"btn btn-primary\" *rbacAllow=\"'Pages.Admin.Product.Edit'\"> {{ 'Button.Submit'\n | transloco }} </button>\n </div>\n </div>\n </form>\n }\n </div>\n </div>\n</div>\n<ng-template #content let-modal>\n <div class=\"modal-header\">\n <h3 class=\"modal-title mb-0 p-0\">{{ 'User.Subscriptions.FullLogo' | transloco }}</h3>\n <button type=\"button\" class=\"btn-close float-end\" aria-label=\"Close\" (click)=\"modal.dismiss()\">\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile (imageSelectionEvent)=\"onImageSelection($event)\" aspectRatio=\"fullLogo\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n</ng-template>\n<ng-template #squaredLogoContent let-modal>\n <div class=\"modal-header\">\n <h3 class=\"modal-title mb-0 p-0\">{{ 'User.Subscriptions.SquaredLogo' | transloco }}</h3>\n <button type=\"button\" class=\"btn-close float-end\" aria-label=\"Close\" (click)=\"modal.dismiss()\">\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile (imageSelectionEvent)=\"uploadSquaredLogo($event)\" aspectRatio=\"auto\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n</ng-template>\n",
|
|
18389
|
+
template: "<div class=\"container-fluid pw-tab product-form overflow-hidden\">\n <div class=\"dashboard\">\n <div class=\"dashboard-body\">\n <div class=\"me-auto col-xs-6 mt-4\">\n <a (click)=\"back()\" class=\"previous\" aria-label=\"Back\"><i class=\"fa fa-arrow-alt-circle-left\"\n aria-hidden=\"true\"></i></a>\n <h3 class=\"\">Product: {{ data?.name ? data?.name : 'Add New' }}</h3>\n </div>\n @if (isLoading) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progress-spinner strokeWidth=\"2\"> </p-progress-spinner>\n </div>\n }\n @if (!isLoading) {\n <div class=\"my-4\">\n <div class=\"mb-5\">\n <p-accordion class=\"pw-accordion-info\">\n <p-accordion-panel value=\"0\">\n <p-accordion-header>\n <i class=\"far fa-circle-info me-2 text-muted\"></i> How to configure a product\n </p-accordion-header>\n <p-accordion-content>\n <div class=\"row g-4 product-howto\">\n <div class=\"col-12 col-lg-7\">\n <h6 class=\"howto-title\">Product / feature binding</h6>\n <dl class=\"howto-defs\">\n <dt><code>category</code></dt>\n <dd>The product type — e.g. <code>seat_pricing</code> or <code>item_pricing</code>.</dd>\n <dt><code>feature_key</code></dt>\n <dd>Describes the main feature.</dd>\n <dt><code>permission_key</code></dt>\n <dd>A user can be subscribed to only one product per <code>permission_key</code>.</dd>\n <dt><code>product_key</code></dt>\n <dd>Unique per product; drives the frontend permission binding.</dd>\n </dl>\n <p class=\"howto-note\">\n Resulting permission key:\n <code>{{ 'Pages.Product.{permission_key}.{product_key}' }}</code>.\n For a feature tied to an existing product, set its <strong>dependency product</strong> accordingly.\n </p>\n </div>\n <div class=\"col-12 col-lg-5\">\n <h6 class=\"howto-title\">Setting up a free product</h6>\n <ul class=\"howto-list\">\n <li>Leave <code>Stripe Plan</code> empty.</li>\n <li>Set <code>Price per unit</code> to <code>0</code>.</li>\n <li>Set <code>Trial days</code> to a large value (e.g. <code>99999</code>).</li>\n <li>Turn <code>Visible</code> off.</li>\n </ul>\n </div>\n </div>\n </p-accordion-content>\n </p-accordion-panel>\n </p-accordion>\n </div>\n </div>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSave()\">\n <h3>{{ 'Admin.Products.Section.Identity' | transloco }}</h3>\n @if (id) {\n <div class=\"row\">\n <div class=\"col-md-6\">\n <div class=\"text-start mt-3\">\n <div class=\"image-container\">\n <h4 class=\"mb-2\"> {{ 'User.Subscriptions.FullLogo' | transloco }} <span class=\"tooltip-wrap ms-1\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.FullLogo'|transloco\" [appendTo]=\"'body'\"\n [tooltipPosition]=\"'top'\">\n <i class=\"far fa-info-circle text-muted\"></i>\n </span>\n </h4>\n @if (fullLogo && !fullLogo.includes('no_image_uploaded') && !fullLogoBroken) {\n <img [src]=\"fullLogo\" alt=\"Demo Logo\" class=\"image full-logo\"\n role=\"presentation\" (error)=\"fullLogoBroken = true\" />\n <div class=\"overlay mt-2\" (click)=\"openModal(content)\" (keydown.enter)=\"openModal(content)\">\n <div class=\"overlay-text\">\n <a>{{ 'User.Profile.Change' | transloco }}</a>\n </div>\n </div>\n } @else {\n <div class=\"logo-dropzone full-dropzone\" role=\"button\" tabindex=\"0\"\n aria-label=\"Upload full logo\" (keydown.enter)=\"openModal(content)\" (click)=\"openModal(content)\">\n <i class=\"fas fa-upload\"></i>\n <span class=\"dropzone-title\">Upload a logo</span>\n <span class=\"dropzone-hint\">PNG or JPG</span>\n </div>\n }\n </div>\n </div>\n </div>\n <div class=\"col-md-6\">\n <div class=\"text-start mt-3\">\n <div class=\"image-container\">\n <h4 class=\"mb-2\"> {{ 'User.Subscriptions.SquaredLogo' | transloco }} <span class=\"tooltip-wrap ms-1\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.SquaredLogo'|transloco\" [appendTo]=\"'body'\"\n [tooltipPosition]=\"'top'\">\n <i class=\"far fa-info-circle text-muted\"></i>\n </span>\n </h4>\n @if (squaredLogo && !squaredLogo.includes('no_image_uploaded') && !squaredLogoBroken) {\n <img [src]=\"squaredLogo\" alt=\"Company Logo\" class=\"squared_logo\"\n role=\"presentation\" (error)=\"squaredLogoBroken = true\" />\n <div class=\"overlay mt-2\" (keydown.enter)=\"openModal(squaredLogoContent)\" (click)=\"openModal(squaredLogoContent)\">\n <div class=\"overlay-text\">\n <a>{{ 'User.Profile.Change' | transloco }}</a>\n </div>\n </div>\n } @else {\n <div class=\"logo-dropzone squared-dropzone\" role=\"button\" tabindex=\"0\"\n aria-label=\"Upload squared logo\" (keydown.enter)=\"openModal(squaredLogoContent)\" (click)=\"openModal(squaredLogoContent)\">\n <i class=\"fas fa-upload\"></i>\n <span class=\"dropzone-title\">Upload a logo</span>\n <span class=\"dropzone-hint\">PNG or JPG</span>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n }\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Name' | transloco\"\n [label]=\"'Label.Name' | transloco\" name=\"name\" controlId=\"product-name\"\n [isLeftTooltip]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.Name' | transloco\">\n <input type=\"text\" id=\"product-name\" class=\"form-control\" formControlName=\"name\"\n [placeholder]=\"'Admin.Products.Placeholder.Name' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f['name'].errors }\"\n [attr.aria-label]=\"'Label.Name' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.NickName' | transloco\"\n [label]=\"'Admin.Products.NickName' | transloco\" name=\"nickname\" controlId=\"product-nickname\"\n [errorMsg]=\"'Admin.Products.Validation.NickName' | transloco\">\n <input type=\"text\" id=\"product-nickname\" class=\"form-control\" formControlName=\"nickname\"\n [placeholder]=\"'Admin.Products.Placeholder.NickName' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f['nickname'].errors }\"\n [attr.aria-label]=\"'Admin.Products.NickName' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.DocumentationUrl' | transloco\"\n [label]=\"'Admin.Products.DocumentationUrl' | transloco\" name=\"documentation_url\" controlId=\"product-documentation_url\">\n <input type=\"text\" id=\"product-documentation_url\" class=\"form-control\" formControlName=\"documentation_url\"\n [placeholder]=\"'Admin.Products.Placeholder.DocumentationUrl' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['documentation_url'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.DocumentationUrl' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12\" id=\"descriptionEditor\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Description' | transloco\"\n [label]=\"'Admin.Products.Description' | transloco\" name=\"description\" controlId=\"product-description\" [useAriaLabelledbyOnly]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.Description' | transloco\">\n <quill-editor [attr.aria-labelledby]=\"'product-description-label'\" [styles]=\"{ height: '220px' }\" formControlName=\"description\" class=\"quillEditor\" [modules]=\"editorConfig\"\n [placeholder]=\"'Admin.Products.Placeholder.Description' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f['description'].errors, 'quill-container': true}\">\n </quill-editor>\n </pw-input-container>\n </div>\n </div>\n\n <!-- Section: Pricing & Billing -->\n <h3>{{ 'Admin.Products.Section.Pricing' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Price' | transloco\"\n [isLeftTooltip]=\"true\"\n [label]=\"'Admin.Products.Price' | transloco\" name=\"price_per_unit\" controlId=\"product-price_per_unit\"\n [errorMsg]=\"'Admin.Products.Validation.Name' | transloco\">\n <input type=\"text\" id=\"product-price_per_unit\" numbersOnly class=\"form-control\" formControlName=\"price_per_unit\"\n [placeholder]=\"'Admin.Products.Placeholder.Price' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['price_per_unit'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.Price' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n @if (supportedCurrency$ | async; as currency) {\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Currency' | transloco\"\n [label]=\"'Admin.Products.Currency' | transloco\" name=\"currency\" controlId=\"product-currency\" [useAriaLabelledbyOnly]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.Currency' | transloco\">\n <p-select\n [attr.aria-labelledby]=\"'product-currency-label'\"\n [options]=\"currency['regions']\"\n formControlName=\"currency\"\n [ngClass]=\"{ 'is-invalid': submitted && f['currency'].errors }\"\n [placeholder]=\"'Admin.Products.Placeholder.Currency' | transloco\"\n [showClear]=\"false\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n }\n @if (supportedRegions$ | async; as region) {\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Region' | transloco\"\n [isLeftTooltip]=\"true\"\n [label]=\"'Admin.Products.Region' | transloco\" name=\"region\" controlId=\"product-region\" [useAriaLabelledbyOnly]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.Region' | transloco\">\n <p-select\n [attr.aria-labelledby]=\"'product-region-label'\"\n [options]=\"region['regions']\"\n formControlName=\"region\"\n [ngClass]=\"{ 'is-invalid': submitted && f['region'].errors }\"\n [placeholder]=\"'Admin.Products.Placeholder.Region' | transloco\"\n [showClear]=\"false\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n }\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.BillingFrequency' | transloco\"\n [label]=\"'Admin.Products.BillingFrequency' | transloco\" name=\"billing_frequency\" controlId=\"product-billing_frequency\" [useAriaLabelledbyOnly]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.BillingFrequency' | transloco\">\n <p-select inputId=\"product-billing_frequency\"\n [options]=\"frequency\" class=\"dropdown-bg-transparent\" [attr.aria-labelledby]=\"'product-billing_frequency-label'\" formControlName=\"billing_frequency\"\n [placeholder]=\"'Admin.Products.Placeholder.BillingFrequency' | transloco\"\n [required]=\"true\" [ngClass]=\"{\n 'is-invalid': submitted && f['billing_frequency'].errors\n }\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Admin.Products.MinUnit' | transloco\" [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MinUnits' | transloco\" name=\"min_units\" controlId=\"product-min_units\"\n [errorMsg]=\"'Admin.Products.Validation.MinUnit' | transloco\">\n <input type=\"number\" id=\"product-min_units\" min=\"1\" class=\"form-control\" formControlName=\"min_units\" [ngClass]=\"{\n 'is-invalid': submitted && f['min_units'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.MinUnit' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Admin.Products.MaxUnit' | transloco\" [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MaxUnits' | transloco\" name=\"max_units\" controlId=\"product-max_units\"\n [errorMsg]=\"'Admin.Products.Validation.MaxUnit' | transloco\">\n <input type=\"number\" id=\"product-max_units\" min=\"1\" class=\"form-control\" formControlName=\"max_units\" [ngClass]=\"{\n 'is-invalid': submitted && f['max_units'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.MaxUnit' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.StripePlan' | transloco\"\n [label]=\"'Admin.Products.StripePlan' | transloco\" name=\"stripe_plan_id\" controlId=\"product-stripe_plan_id\">\n <input type=\"text\" id=\"product-stripe_plan_id\" class=\"form-control\" formControlName=\"stripe_plan_id\"\n [placeholder]=\"'Admin.Products.Placeholder.StripePlan' | transloco\"\n [attr.aria-label]=\"'Admin.Products.StripePlan' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'Pages.Alpha'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.ProrationBehavior' | transloco\"\n [label]=\"'Admin.Products.ProrationBehavior' | transloco\" name=\"proration_behavior\" controlId=\"product-proration_behavior\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-proration_behavior-label'\"\n [options]=\"prorationBehaviors\"\n formControlName=\"proration_behavior\"\n [placeholder]=\"'Admin.Products.Placeholder.ProrationBehavior' | transloco\"\n optionValue=\"value\"\n optionLabel=\"label\"\n [showClear]=\"true\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'Pages.Alpha'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.UnsubscribeStripeBehavior' | transloco\"\n [label]=\"'Admin.Products.UnsubscribeStripeBehavior' | transloco\" name=\"unsubscribe_stripe_behavior\" controlId=\"product-unsubscribe_stripe_behavior\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-unsubscribe_stripe_behavior-label'\"\n [options]=\"unsubscribeBehaviors\"\n formControlName=\"unsubscribe_stripe_behavior\"\n [placeholder]=\"'Admin.Products.Placeholder.UnsubscribeBehavior' | transloco\"\n optionValue=\"value\"\n optionLabel=\"label\"\n [showClear]=\"true\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <pw-product-backup-card *rbacAllow=\"'SuperAdmin'\" [form]=\"form\" [provider]=\"data?.second_payment_provider\"\n [submitted]=\"submitted\"></pw-product-backup-card>\n </div>\n\n <!-- Section: Trial -->\n <h3>{{ 'Admin.Products.Section.Trial' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.TrialDays' | transloco\"\n [label]=\"'Admin.Products.TrialDays' | transloco\" name=\"trial_days\" controlId=\"product-trial_days\"\n [errorMsg]=\"'Admin.Products.Validation.TrialDays' | transloco\">\n <input type=\"number\" id=\"product-trial_days\" min=\"0\" class=\"form-control\" formControlName=\"trial_days\" [ngClass]=\"{\n 'is-invalid': submitted && f['trial_days'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.TrialDays' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MaxTrialHits' | transloco\"\n [label]=\"'Admin.Products.MaxTrialHits' | transloco\" name=\"max_hits_trial\" controlId=\"product-max_hits_trial\">\n <input type=\"number\" id=\"product-max_hits_trial\" min=\"0\" class=\"form-control\" formControlName=\"max_hits_trial\" [ngClass]=\"{\n 'is-invalid': submitted && f['max_hits_trial'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.MaxTrialHits' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.TrialHits' | transloco\"\n [label]=\"'Admin.Products.TrialHits' | transloco\" name=\"max_hits\" controlId=\"product-max_hits\">\n <input type=\"number\" id=\"product-max_hits\" min=\"0\" class=\"form-control\" formControlName=\"max_hits\"\n [ngClass]=\"{ 'is-invalid': submitted && f['max_hits'].errors }\"\n [attr.aria-label]=\"'Admin.Products.TrialHits' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n </div>\n\n <!-- Section: Feature & Permission Binding -->\n <h3>{{ 'Admin.Products.Section.Binding' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Admin.Products.Category' | transloco\"\n [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.PermissionKey' | transloco\"\n name=\"category\" controlId=\"product-category\" [useAriaLabelledbyOnly]=\"true\" [errorMsg]=\"'Admin.Products.Validation.Category' | transloco\">\n <p-select inputId=\"product-category\"\n [options]=\"categories\" class=\"dropdown-bg-transparent\" [attr.aria-labelledby]=\"'product-category-label'\" formControlName=\"category\"\n [placeholder]=\"'Admin.Products.Placeholder.Category' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f['category'].errors }\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.FeatureKey' | transloco\"\n [label]=\"'Admin.Products.FeatureKey' | transloco\" name=\"feature_key\" controlId=\"product-feature_key\"\n [errorMsg]=\"'Admin.Products.Validation.FeatureKey' | transloco\">\n <input type=\"text\" id=\"product-feature_key\" class=\"form-control\"\n [placeholder]=\"'Admin.Products.Placeholder.FeatureKey' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['feature_key'].errors\n }\" formControlName=\"feature_key\"\n [attr.aria-label]=\"'Admin.Products.FeatureKey' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.PermissionKey' | transloco\"\n [label]=\"'Admin.Products.PermissionKey' | transloco\" name=\"permission_key\" controlId=\"product-permission_key\"\n [errorMsg]=\"'Admin.Products.Validation.PermissionKey' | transloco\">\n <input type=\"text\" id=\"product-permission_key\" class=\"form-control\"\n [placeholder]=\"'Admin.Products.Placeholder.PermissionKey' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['permission_key'].errors\n }\" formControlName=\"permission_key\"\n [attr.aria-label]=\"'Admin.Products.PermissionKey' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Admin.Products.ProductKey' | transloco\"\n [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.PermissionKey' | transloco\"\n name=\"product_key\" controlId=\"product-product_key\"\n [errorMsg]=\"'Admin.Products.Validation.ProductKey' | transloco\">\n <input type=\"text\" id=\"product-product_key\" class=\"form-control\" formControlName=\"product_key\"\n [placeholder]=\"'Admin.Products.Placeholder.ProductKey' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['product_key'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.ProductKey' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <span class=\"pw-label-style\" id=\"product-dependency_products-label\" [pTooltip]=\"'Admin.Products.Tooltip.DependencyProducts' | transloco\" tooltipPosition=\"top\" appendTo=\"body\"> {{ 'Admin.Products.DependencyProducts' | transloco }}<i class=\"far fa-info-circle\" aria-hidden=\"true\"></i>\n </span>\n <p-multiselect inputId=\"product-dependency_products\"\n [options]=\"productsList\" [(ngModel)]=\"selectedScopes\"\n [placeholder]=\"'Admin.Products.Placeholder.DependencyProducts' | transloco\"\n [attr.aria-labelledby]=\"'product-dependency_products-label'\"\n [ngModelOptions]=\"{ standalone: true }\" (onChange)=\"onSearchCriteria($event)\" [showHeader]=\"false\"\n maxSelectedLabels=\"1\" appendTo=\"body\">\n </p-multiselect>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <span class=\"pw-label-style\" id=\"product-roles-label\" [pTooltip]=\"'Admin.Subscriptions.Tooltip.AssignedRoles' | transloco\" tooltipPosition=\"top\" appendTo=\"body\">{{ 'Admin.Products.AssignedRoles' | transloco }} <i class=\"far fa-info-circle\" aria-hidden=\"true\"></i>\n </span>\n <p-multiselect inputId=\"product-roles\" [options]=\"allRoles\" formControlName=\"roles\" appendTo=\"body\"\n [placeholder]=\"'Admin.Products.Placeholder.Roles' | transloco\"\n [attr.aria-labelledby]=\"'product-roles-label'\"></p-multiselect>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'SuperAdmin'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MasterProduct' | transloco\"\n [label]=\"'Admin.Products.MasterProduct' | transloco\" name=\"master_product_id\" controlId=\"product-master_product_id\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-master_product_id-label'\"\n [options]=\"productsList\"\n formControlName=\"master_product_id\"\n [placeholder]=\"'Admin.Products.Placeholder.MasterProduct' | transloco\"\n optionValue=\"value\"\n optionLabel=\"label\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'SuperAdmin'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.IsMasterProduct' | transloco\"\n [label]=\"'Admin.Products.IsMasterProduct' | transloco\" name=\"is_master_product\" controlId=\"product-is_master_product\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"is_master_product\" name=\"is_master_product\"\n [attr.aria-labelledby]=\"'product-is_master_product-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['is_master_product'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'SuperAdmin'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MultipleAllowed' | transloco\"\n [label]=\"'Admin.Products.MultipleAllowed' | transloco\" class=\"nowrap\" name=\"multiple_allowed\" controlId=\"product-multiple_allowed\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"multiple_allowed\" name=\"multiple_allowed\"\n [attr.aria-labelledby]=\"'product-multiple_allowed-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['multiple_allowed'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n </div>\n\n <!-- Section: Onboarding & Signup -->\n <h3>{{ 'Admin.Products.Section.Signup' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-12\" id=\"signupInstructionsEditor\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.SignupInstructions' | transloco\"\n [label]=\"'Admin.Products.SignupInstructions' | transloco\" name=\"signup_instructions\" controlId=\"product-signup_instructions\" [useAriaLabelledbyOnly]=\"true\">\n <quill-editor [attr.aria-labelledby]=\"'product-signup_instructions-label'\" [styles]=\"{ height: '220px' }\" formControlName=\"signup_instructions\" class=\"quillEditor\" [modules]=\"editorConfig\"\n [placeholder]=\"'Admin.Products.Placeholder.SignupInstructions' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['signup_instructions'].errors, 'quill-container': true\n }\">\n </quill-editor>\n </pw-input-container>\n </div>\n <div class=\"col-12\" id=\"signupEmployeesEditor\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.SignupInstructionEmployees' | transloco\"\n [label]=\"'Admin.Products.SignupInstructionEmployees' | transloco\" name=\"signup_instruction_employees\" controlId=\"product-signup_instruction_employees\" [useAriaLabelledbyOnly]=\"true\">\n <quill-editor [attr.aria-labelledby]=\"'product-signup_instruction_employees-label'\" [styles]=\"{ height: '220px' }\" formControlName=\"signup_instruction_employees\" class=\"quillEditor\" [modules]=\"editorConfig\"\n [placeholder]=\"'Admin.Products.Placeholder.SignupInstructionEmployees' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['signup_instruction_employees'].errors, 'quill-container': true\n }\">\n </quill-editor>\n </pw-input-container>\n </div>\n </div>\n\n <!-- Section: Visibility, Support & Compliance -->\n <h3>{{ 'Admin.Products.Section.Visibility' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-6 col-md-3\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.IsActive' | transloco\"\n [label]=\"'Admin.Products.IsActive' | transloco\" name=\"active\" controlId=\"product-active\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"active\" name=\"active\"\n [attr.aria-labelledby]=\"'product-active-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['active'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-6 col-md-3\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.IsVisible' | transloco\"\n [label]=\"'Admin.Products.IsVisible' | transloco\" name=\"visible\" controlId=\"product-visible\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"visible\" name=\"visible\"\n [attr.aria-labelledby]=\"'product-visible-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['visible'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-6 col-md-3\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MembersVisible' | transloco\"\n [label]=\"'Admin.Products.MembersVisible' | transloco\" name=\"members_visible\" controlId=\"product-members_visible\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"members_visible\" name=\"members_visible\"\n [attr.aria-labelledby]=\"'product-members_visible-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['members_visible'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-6 col-md-3\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.ChatVisible' | transloco\"\n [label]=\"'Admin.Products.ChatVisible' | transloco\" name=\"chat_visible\" controlId=\"product-chat_visible\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"chat_visible\" name=\"chat_visible\"\n [attr.aria-labelledby]=\"'product-chat_visible-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['chat_visible'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.ProductPrivacyService' | transloco\"\n [label]=\"'Admin.Products.ProductPrivacyService' | transloco\" name=\"product_privacy_service_id\" controlId=\"product-product_privacy_service_id\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-product_privacy_service_id-label'\"\n [options]=\"allTos\"\n formControlName=\"product_privacy_service_id\"\n [placeholder]=\"'Admin.Products.Placeholder.PrivacyService' | transloco\"\n optionValue=\"id\"\n optionLabel=\"title\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.GitLabServiceDeskEmail' | transloco\"\n [label]=\"'Admin.Products.GitLabServiceDeskEmail' | transloco\" name=\"gitlab_service_desk_email\" controlId=\"product-gitlab_service_desk_email\">\n <input type=\"text\" id=\"product-gitlab_service_desk_email\" class=\"form-control\" formControlName=\"gitlab_service_desk_email\"\n [placeholder]=\"'Admin.Products.Placeholder.GitlabServiceDeskEmail' | transloco\"\n [attr.aria-label]=\"'Admin.Products.GitLabServiceDeskEmail' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.LoginDefaultRoute' | transloco\"\n [label]=\"'Admin.Products.LoginDefaultRoute' | transloco\" name=\"login_default_route\" controlId=\"product-login_default_route\">\n <input type=\"text\" id=\"product-login_default_route\" class=\"form-control\" formControlName=\"login_default_route\"\n [placeholder]=\"'Admin.Products.Placeholder.LoginDefaultRoute' | transloco\"\n [attr.aria-label]=\"'Admin.Products.LoginDefaultRoute' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'Pages.Alpha'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.PartnerProducts' | transloco\"\n [label]=\"'Admin.Products.PartnerProducts' | transloco\" name=\"partner_products\" controlId=\"product-partner_products\" [useAriaLabelledbyOnly]=\"true\">\n <p-multiselect inputId=\"product-partner_products\"\n [options]=\"productsList\" (onChange)=\"onSearchPartnerProducts($event)\"\n [placeholder]=\"'Admin.Products.Placeholder.PartnerProducts' | transloco\"\n [attr.aria-labelledby]=\"'product-partner_products-label'\"\n [ngModelOptions]=\"{ standalone: true }\" [showToggleAll]=\"true\" [(ngModel)]=\"selectedPartnerProducts\"\n [showHeader]=\"true\" maxSelectedLabels=\"1\" appendTo=\"body\">\n </p-multiselect>\n </pw-input-container>\n </div>\n </div>\n </div>\n\n <div class=\"row text-end mt-4\">\n <div class=\"col-12\">\n <button type=\"button\" class=\"btn btn-outline-default me-2\" (click)=\"back()\"> {{ 'Button.Cancel' |\n transloco }} </button>\n <button type=\"submit\" [buttonBusy]=\"submitted\" class=\"btn btn-primary\" *rbacAllow=\"'Pages.Admin.Product.Edit'\"> {{ 'Button.Submit'\n | transloco }} </button>\n </div>\n </div>\n </form>\n }\n </div>\n </div>\n</div>\n<ng-template #content let-modal>\n <div class=\"modal-header\">\n <h3 class=\"modal-title mb-0 p-0\">{{ 'User.Subscriptions.FullLogo' | transloco }}</h3>\n <button type=\"button\" class=\"btn-close float-end\" aria-label=\"Close\" (click)=\"modal.dismiss()\">\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile (imageSelectionEvent)=\"onImageSelection($event)\" aspectRatio=\"fullLogo\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n</ng-template>\n<ng-template #squaredLogoContent let-modal>\n <div class=\"modal-header\">\n <h3 class=\"modal-title mb-0 p-0\">{{ 'User.Subscriptions.SquaredLogo' | transloco }}</h3>\n <button type=\"button\" class=\"btn-close float-end\" aria-label=\"Close\" (click)=\"modal.dismiss()\">\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile (imageSelectionEvent)=\"uploadSquaredLogo($event)\" aspectRatio=\"auto\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n</ng-template>\n",
|
|
18151
18390
|
styles: [".pw-label-style.info-circle{display:inline-block;line-height:1.5}.pw-label-style.info-circle:after{top:-7px}.nowrap{white-space:nowrap}textarea{height:180px}:host .full-logo,:host .squared_logo{background:#f7f8fa;border:1px solid #e2e5ea;border-radius:8px;object-fit:contain;padding:12px}:host .full-logo{height:120px;width:280px}:host .squared_logo{height:150px;width:150px}:host .overlay{cursor:pointer;margin-top:8px}:host .overlay-text a{color:var(--first, #1769e1);cursor:pointer;font-weight:600}:host .overlay-text a:hover{text-decoration:underline}:host .image-container>h4{color:var(--titles, #222);font-size:14px;font-weight:600}:host form>h3{display:block;border-top:1px solid #e2e5ea;margin-top:2rem;padding-top:1.25rem}:host form>h3:first-child{border-top:0;margin-top:.5rem;padding-top:0}:host .product-howto{font-size:.9rem}:host .howto-title{font-weight:700;margin-bottom:.85rem}:host .howto-defs{margin:0}:host .howto-defs dt{font-weight:600;margin-top:.55rem}:host .howto-defs dd{margin:.1rem 0 0;color:var(--bs-secondary-color, #6c757d)}:host .howto-list{margin:0;padding-left:1.1rem}:host .howto-list li{margin-bottom:.45rem}:host .howto-note{margin-top:1rem;color:var(--bs-secondary-color, #6c757d)}:host .product-howto code{background:#1769e114;color:var(--first, #1769e1);padding:.1rem .4rem;border-radius:4px;font-size:.85em}\n"],
|
|
18152
18391
|
dependencies: [
|
|
18153
18392
|
{
|
|
@@ -18546,6 +18785,16 @@ var ProductDetailsComponent = class ProductDetailsComponent extends AppBaseCompo
|
|
|
18546
18785
|
type: i11.QuillEditorComponent,
|
|
18547
18786
|
selector: "quill-editor"
|
|
18548
18787
|
},
|
|
18788
|
+
{
|
|
18789
|
+
kind: "component",
|
|
18790
|
+
type: ProductBackupCardComponent,
|
|
18791
|
+
selector: "pw-product-backup-card",
|
|
18792
|
+
inputs: [
|
|
18793
|
+
"form",
|
|
18794
|
+
"provider",
|
|
18795
|
+
"submitted"
|
|
18796
|
+
]
|
|
18797
|
+
},
|
|
18549
18798
|
{
|
|
18550
18799
|
kind: "pipe",
|
|
18551
18800
|
type: i5$2.AsyncPipe,
|
|
@@ -18571,7 +18820,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
18571
18820
|
args: [{
|
|
18572
18821
|
selector: "pw-product-details",
|
|
18573
18822
|
standalone: false,
|
|
18574
|
-
template: "<div class=\"container-fluid pw-tab product-form overflow-hidden\">\n <div class=\"dashboard\">\n <div class=\"dashboard-body\">\n <div class=\"me-auto col-xs-6 mt-4\">\n <a (click)=\"back()\" class=\"previous\" aria-label=\"Back\"><i class=\"fa fa-arrow-alt-circle-left\"\n aria-hidden=\"true\"></i></a>\n <h3 class=\"\">Product: {{ data?.name ? data?.name : 'Add New' }}</h3>\n </div>\n @if (isLoading) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progress-spinner strokeWidth=\"2\"> </p-progress-spinner>\n </div>\n }\n @if (!isLoading) {\n <div class=\"my-4\">\n <div class=\"mb-5\">\n <p-accordion class=\"pw-accordion-info\">\n <p-accordion-panel value=\"0\">\n <p-accordion-header>\n <i class=\"far fa-circle-info me-2 text-muted\"></i> How to configure a product\n </p-accordion-header>\n <p-accordion-content>\n <div class=\"row g-4 product-howto\">\n <div class=\"col-12 col-lg-7\">\n <h6 class=\"howto-title\">Product / feature binding</h6>\n <dl class=\"howto-defs\">\n <dt><code>category</code></dt>\n <dd>The product type — e.g. <code>seat_pricing</code> or <code>item_pricing</code>.</dd>\n <dt><code>feature_key</code></dt>\n <dd>Describes the main feature.</dd>\n <dt><code>permission_key</code></dt>\n <dd>A user can be subscribed to only one product per <code>permission_key</code>.</dd>\n <dt><code>product_key</code></dt>\n <dd>Unique per product; drives the frontend permission binding.</dd>\n </dl>\n <p class=\"howto-note\">\n Resulting permission key:\n <code>{{ 'Pages.Product.{permission_key}.{product_key}' }}</code>.\n For a feature tied to an existing product, set its <strong>dependency product</strong> accordingly.\n </p>\n </div>\n <div class=\"col-12 col-lg-5\">\n <h6 class=\"howto-title\">Setting up a free product</h6>\n <ul class=\"howto-list\">\n <li>Leave <code>Stripe Plan</code> empty.</li>\n <li>Set <code>Price per unit</code> to <code>0</code>.</li>\n <li>Set <code>Trial days</code> to a large value (e.g. <code>99999</code>).</li>\n <li>Turn <code>Visible</code> off.</li>\n </ul>\n </div>\n </div>\n </p-accordion-content>\n </p-accordion-panel>\n </p-accordion>\n </div>\n </div>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSave()\">\n <h3>{{ 'Admin.Products.Section.Identity' | transloco }}</h3>\n @if (id) {\n <div class=\"row\">\n <div class=\"col-md-6\">\n <div class=\"text-start mt-3\">\n <div class=\"image-container\">\n <h4 class=\"mb-2\"> {{ 'User.Subscriptions.FullLogo' | transloco }} <span class=\"tooltip-wrap ms-1\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.FullLogo'|transloco\" [appendTo]=\"'body'\"\n [tooltipPosition]=\"'top'\">\n <i class=\"far fa-info-circle text-muted\"></i>\n </span>\n </h4>\n @if (fullLogo && !fullLogo.includes('no_image_uploaded') && !fullLogoBroken) {\n <img [src]=\"fullLogo\" alt=\"Demo Logo\" class=\"image full-logo\"\n role=\"presentation\" (error)=\"fullLogoBroken = true\" />\n <div class=\"overlay mt-2\" (click)=\"openModal(content)\" (keydown.enter)=\"openModal(content)\">\n <div class=\"overlay-text\">\n <a>{{ 'User.Profile.Change' | transloco }}</a>\n </div>\n </div>\n } @else {\n <div class=\"logo-dropzone full-dropzone\" role=\"button\" tabindex=\"0\"\n aria-label=\"Upload full logo\" (keydown.enter)=\"openModal(content)\" (click)=\"openModal(content)\">\n <i class=\"fas fa-upload\"></i>\n <span class=\"dropzone-title\">Upload a logo</span>\n <span class=\"dropzone-hint\">PNG or JPG</span>\n </div>\n }\n </div>\n </div>\n </div>\n <div class=\"col-md-6\">\n <div class=\"text-start mt-3\">\n <div class=\"image-container\">\n <h4 class=\"mb-2\"> {{ 'User.Subscriptions.SquaredLogo' | transloco }} <span class=\"tooltip-wrap ms-1\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.SquaredLogo'|transloco\" [appendTo]=\"'body'\"\n [tooltipPosition]=\"'top'\">\n <i class=\"far fa-info-circle text-muted\"></i>\n </span>\n </h4>\n @if (squaredLogo && !squaredLogo.includes('no_image_uploaded') && !squaredLogoBroken) {\n <img [src]=\"squaredLogo\" alt=\"Company Logo\" class=\"squared_logo\"\n role=\"presentation\" (error)=\"squaredLogoBroken = true\" />\n <div class=\"overlay mt-2\" (keydown.enter)=\"openModal(squaredLogoContent)\" (click)=\"openModal(squaredLogoContent)\">\n <div class=\"overlay-text\">\n <a>{{ 'User.Profile.Change' | transloco }}</a>\n </div>\n </div>\n } @else {\n <div class=\"logo-dropzone squared-dropzone\" role=\"button\" tabindex=\"0\"\n aria-label=\"Upload squared logo\" (keydown.enter)=\"openModal(squaredLogoContent)\" (click)=\"openModal(squaredLogoContent)\">\n <i class=\"fas fa-upload\"></i>\n <span class=\"dropzone-title\">Upload a logo</span>\n <span class=\"dropzone-hint\">PNG or JPG</span>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n }\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Name' | transloco\"\n [label]=\"'Label.Name' | transloco\" name=\"name\" controlId=\"product-name\"\n [isLeftTooltip]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.Name' | transloco\">\n <input type=\"text\" id=\"product-name\" class=\"form-control\" formControlName=\"name\"\n [placeholder]=\"'Admin.Products.Placeholder.Name' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f['name'].errors }\"\n [attr.aria-label]=\"'Label.Name' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.NickName' | transloco\"\n [label]=\"'Admin.Products.NickName' | transloco\" name=\"nickname\" controlId=\"product-nickname\"\n [errorMsg]=\"'Admin.Products.Validation.NickName' | transloco\">\n <input type=\"text\" id=\"product-nickname\" class=\"form-control\" formControlName=\"nickname\"\n [placeholder]=\"'Admin.Products.Placeholder.NickName' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f['nickname'].errors }\"\n [attr.aria-label]=\"'Admin.Products.NickName' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.DocumentationUrl' | transloco\"\n [label]=\"'Admin.Products.DocumentationUrl' | transloco\" name=\"documentation_url\" controlId=\"product-documentation_url\">\n <input type=\"text\" id=\"product-documentation_url\" class=\"form-control\" formControlName=\"documentation_url\"\n [placeholder]=\"'Admin.Products.Placeholder.DocumentationUrl' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['documentation_url'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.DocumentationUrl' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12\" id=\"descriptionEditor\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Description' | transloco\"\n [label]=\"'Admin.Products.Description' | transloco\" name=\"description\" controlId=\"product-description\" [useAriaLabelledbyOnly]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.Description' | transloco\">\n <quill-editor [attr.aria-labelledby]=\"'product-description-label'\" [styles]=\"{ height: '220px' }\" formControlName=\"description\" class=\"quillEditor\" [modules]=\"editorConfig\"\n [placeholder]=\"'Admin.Products.Placeholder.Description' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f['description'].errors, 'quill-container': true}\">\n </quill-editor>\n </pw-input-container>\n </div>\n </div>\n\n <!-- Section: Pricing & Billing -->\n <h3>{{ 'Admin.Products.Section.Pricing' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Price' | transloco\"\n [isLeftTooltip]=\"true\"\n [label]=\"'Admin.Products.Price' | transloco\" name=\"price_per_unit\" controlId=\"product-price_per_unit\"\n [errorMsg]=\"'Admin.Products.Validation.Name' | transloco\">\n <input type=\"text\" id=\"product-price_per_unit\" numbersOnly class=\"form-control\" formControlName=\"price_per_unit\"\n [placeholder]=\"'Admin.Products.Placeholder.Price' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['price_per_unit'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.Price' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n @if (supportedCurrency$ | async; as currency) {\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Currency' | transloco\"\n [label]=\"'Admin.Products.Currency' | transloco\" name=\"currency\" controlId=\"product-currency\" [useAriaLabelledbyOnly]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.Currency' | transloco\">\n <p-select\n [attr.aria-labelledby]=\"'product-currency-label'\"\n [options]=\"currency['regions']\"\n formControlName=\"currency\"\n [ngClass]=\"{ 'is-invalid': submitted && f['currency'].errors }\"\n [placeholder]=\"'Admin.Products.Placeholder.Currency' | transloco\"\n [showClear]=\"false\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n }\n @if (supportedRegions$ | async; as region) {\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Region' | transloco\"\n [isLeftTooltip]=\"true\"\n [label]=\"'Admin.Products.Region' | transloco\" name=\"region\" controlId=\"product-region\" [useAriaLabelledbyOnly]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.Region' | transloco\">\n <p-select\n [attr.aria-labelledby]=\"'product-region-label'\"\n [options]=\"region['regions']\"\n formControlName=\"region\"\n [ngClass]=\"{ 'is-invalid': submitted && f['region'].errors }\"\n [placeholder]=\"'Admin.Products.Placeholder.Region' | transloco\"\n [showClear]=\"false\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n }\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.BillingFrequency' | transloco\"\n [label]=\"'Admin.Products.BillingFrequency' | transloco\" name=\"billing_frequency\" controlId=\"product-billing_frequency\" [useAriaLabelledbyOnly]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.BillingFrequency' | transloco\">\n <p-select inputId=\"product-billing_frequency\"\n [options]=\"frequency\" class=\"dropdown-bg-transparent\" [attr.aria-labelledby]=\"'product-billing_frequency-label'\" formControlName=\"billing_frequency\"\n [placeholder]=\"'Admin.Products.Placeholder.BillingFrequency' | transloco\"\n [required]=\"true\" [ngClass]=\"{\n 'is-invalid': submitted && f['billing_frequency'].errors\n }\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Admin.Products.MinUnit' | transloco\" [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MinUnits' | transloco\" name=\"min_units\" controlId=\"product-min_units\"\n [errorMsg]=\"'Admin.Products.Validation.MinUnit' | transloco\">\n <input type=\"number\" id=\"product-min_units\" min=\"1\" class=\"form-control\" formControlName=\"min_units\" [ngClass]=\"{\n 'is-invalid': submitted && f['min_units'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.MinUnit' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Admin.Products.MaxUnit' | transloco\" [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MaxUnits' | transloco\" name=\"max_units\" controlId=\"product-max_units\"\n [errorMsg]=\"'Admin.Products.Validation.MaxUnit' | transloco\">\n <input type=\"number\" id=\"product-max_units\" min=\"1\" class=\"form-control\" formControlName=\"max_units\" [ngClass]=\"{\n 'is-invalid': submitted && f['max_units'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.MaxUnit' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.StripePlan' | transloco\"\n [label]=\"'Admin.Products.StripePlan' | transloco\" name=\"stripe_plan_id\" controlId=\"product-stripe_plan_id\">\n <input type=\"text\" id=\"product-stripe_plan_id\" class=\"form-control\" formControlName=\"stripe_plan_id\"\n [placeholder]=\"'Admin.Products.Placeholder.StripePlan' | transloco\"\n [attr.aria-label]=\"'Admin.Products.StripePlan' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'Pages.Alpha'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.ProrationBehavior' | transloco\"\n [label]=\"'Admin.Products.ProrationBehavior' | transloco\" name=\"proration_behavior\" controlId=\"product-proration_behavior\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-proration_behavior-label'\"\n [options]=\"prorationBehaviors\"\n formControlName=\"proration_behavior\"\n [placeholder]=\"'Admin.Products.Placeholder.ProrationBehavior' | transloco\"\n optionValue=\"value\"\n optionLabel=\"label\"\n [showClear]=\"true\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'Pages.Alpha'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.UnsubscribeStripeBehavior' | transloco\"\n [label]=\"'Admin.Products.UnsubscribeStripeBehavior' | transloco\" name=\"unsubscribe_stripe_behavior\" controlId=\"product-unsubscribe_stripe_behavior\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-unsubscribe_stripe_behavior-label'\"\n [options]=\"unsubscribeBehaviors\"\n formControlName=\"unsubscribe_stripe_behavior\"\n [placeholder]=\"'Admin.Products.Placeholder.UnsubscribeBehavior' | transloco\"\n optionValue=\"value\"\n optionLabel=\"label\"\n [showClear]=\"true\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'SuperAdmin'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.SecondPaymentRequired' | transloco\"\n [label]=\"'Admin.Products.SecondPaymentRequired' | transloco\" name=\"second_payment_required\" controlId=\"product-second_payment_required\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"second_payment_required\" name=\"second_payment_required\"\n [attr.aria-labelledby]=\"'product-second_payment_required-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['second_payment_required'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n </div>\n\n <!-- Section: Trial -->\n <h3>{{ 'Admin.Products.Section.Trial' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.TrialDays' | transloco\"\n [label]=\"'Admin.Products.TrialDays' | transloco\" name=\"trial_days\" controlId=\"product-trial_days\"\n [errorMsg]=\"'Admin.Products.Validation.TrialDays' | transloco\">\n <input type=\"number\" id=\"product-trial_days\" min=\"0\" class=\"form-control\" formControlName=\"trial_days\" [ngClass]=\"{\n 'is-invalid': submitted && f['trial_days'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.TrialDays' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MaxTrialHits' | transloco\"\n [label]=\"'Admin.Products.MaxTrialHits' | transloco\" name=\"max_hits_trial\" controlId=\"product-max_hits_trial\">\n <input type=\"number\" id=\"product-max_hits_trial\" min=\"0\" class=\"form-control\" formControlName=\"max_hits_trial\" [ngClass]=\"{\n 'is-invalid': submitted && f['max_hits_trial'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.MaxTrialHits' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.TrialHits' | transloco\"\n [label]=\"'Admin.Products.TrialHits' | transloco\" name=\"max_hits\" controlId=\"product-max_hits\">\n <input type=\"number\" id=\"product-max_hits\" min=\"0\" class=\"form-control\" formControlName=\"max_hits\"\n [ngClass]=\"{ 'is-invalid': submitted && f['max_hits'].errors }\"\n [attr.aria-label]=\"'Admin.Products.TrialHits' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n </div>\n\n <!-- Section: Feature & Permission Binding -->\n <h3>{{ 'Admin.Products.Section.Binding' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Admin.Products.Category' | transloco\"\n [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.PermissionKey' | transloco\"\n name=\"category\" controlId=\"product-category\" [useAriaLabelledbyOnly]=\"true\" [errorMsg]=\"'Admin.Products.Validation.Category' | transloco\">\n <p-select inputId=\"product-category\"\n [options]=\"categories\" class=\"dropdown-bg-transparent\" [attr.aria-labelledby]=\"'product-category-label'\" formControlName=\"category\"\n [placeholder]=\"'Admin.Products.Placeholder.Category' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f['category'].errors }\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.FeatureKey' | transloco\"\n [label]=\"'Admin.Products.FeatureKey' | transloco\" name=\"feature_key\" controlId=\"product-feature_key\"\n [errorMsg]=\"'Admin.Products.Validation.FeatureKey' | transloco\">\n <input type=\"text\" id=\"product-feature_key\" class=\"form-control\"\n [placeholder]=\"'Admin.Products.Placeholder.FeatureKey' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['feature_key'].errors\n }\" formControlName=\"feature_key\"\n [attr.aria-label]=\"'Admin.Products.FeatureKey' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.PermissionKey' | transloco\"\n [label]=\"'Admin.Products.PermissionKey' | transloco\" name=\"permission_key\" controlId=\"product-permission_key\"\n [errorMsg]=\"'Admin.Products.Validation.PermissionKey' | transloco\">\n <input type=\"text\" id=\"product-permission_key\" class=\"form-control\"\n [placeholder]=\"'Admin.Products.Placeholder.PermissionKey' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['permission_key'].errors\n }\" formControlName=\"permission_key\"\n [attr.aria-label]=\"'Admin.Products.PermissionKey' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Admin.Products.ProductKey' | transloco\"\n [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.PermissionKey' | transloco\"\n name=\"product_key\" controlId=\"product-product_key\"\n [errorMsg]=\"'Admin.Products.Validation.ProductKey' | transloco\">\n <input type=\"text\" id=\"product-product_key\" class=\"form-control\" formControlName=\"product_key\"\n [placeholder]=\"'Admin.Products.Placeholder.ProductKey' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['product_key'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.ProductKey' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <span class=\"pw-label-style\" id=\"product-dependency_products-label\" [pTooltip]=\"'Admin.Products.Tooltip.DependencyProducts' | transloco\" tooltipPosition=\"top\" appendTo=\"body\"> {{ 'Admin.Products.DependencyProducts' | transloco }}<i class=\"far fa-info-circle\" aria-hidden=\"true\"></i>\n </span>\n <p-multiselect inputId=\"product-dependency_products\"\n [options]=\"productsList\" [(ngModel)]=\"selectedScopes\"\n [placeholder]=\"'Admin.Products.Placeholder.DependencyProducts' | transloco\"\n [attr.aria-labelledby]=\"'product-dependency_products-label'\"\n [ngModelOptions]=\"{ standalone: true }\" (onChange)=\"onSearchCriteria($event)\" [showHeader]=\"false\"\n maxSelectedLabels=\"1\" appendTo=\"body\">\n </p-multiselect>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <span class=\"pw-label-style\" id=\"product-roles-label\" [pTooltip]=\"'Admin.Subscriptions.Tooltip.AssignedRoles' | transloco\" tooltipPosition=\"top\" appendTo=\"body\">{{ 'Admin.Products.AssignedRoles' | transloco }} <i class=\"far fa-info-circle\" aria-hidden=\"true\"></i>\n </span>\n <p-multiselect inputId=\"product-roles\" [options]=\"allRoles\" formControlName=\"roles\" appendTo=\"body\"\n [placeholder]=\"'Admin.Products.Placeholder.Roles' | transloco\"\n [attr.aria-labelledby]=\"'product-roles-label'\"></p-multiselect>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'SuperAdmin'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MasterProduct' | transloco\"\n [label]=\"'Admin.Products.MasterProduct' | transloco\" name=\"master_product_id\" controlId=\"product-master_product_id\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-master_product_id-label'\"\n [options]=\"productsList\"\n formControlName=\"master_product_id\"\n [placeholder]=\"'Admin.Products.Placeholder.MasterProduct' | transloco\"\n optionValue=\"value\"\n optionLabel=\"label\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'SuperAdmin'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.IsMasterProduct' | transloco\"\n [label]=\"'Admin.Products.IsMasterProduct' | transloco\" name=\"is_master_product\" controlId=\"product-is_master_product\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"is_master_product\" name=\"is_master_product\"\n [attr.aria-labelledby]=\"'product-is_master_product-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['is_master_product'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'SuperAdmin'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MultipleAllowed' | transloco\"\n [label]=\"'Admin.Products.MultipleAllowed' | transloco\" class=\"nowrap\" name=\"multiple_allowed\" controlId=\"product-multiple_allowed\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"multiple_allowed\" name=\"multiple_allowed\"\n [attr.aria-labelledby]=\"'product-multiple_allowed-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['multiple_allowed'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n </div>\n\n <!-- Section: Onboarding & Signup -->\n <h3>{{ 'Admin.Products.Section.Signup' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-12\" id=\"signupInstructionsEditor\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.SignupInstructions' | transloco\"\n [label]=\"'Admin.Products.SignupInstructions' | transloco\" name=\"signup_instructions\" controlId=\"product-signup_instructions\" [useAriaLabelledbyOnly]=\"true\">\n <quill-editor [attr.aria-labelledby]=\"'product-signup_instructions-label'\" [styles]=\"{ height: '220px' }\" formControlName=\"signup_instructions\" class=\"quillEditor\" [modules]=\"editorConfig\"\n [placeholder]=\"'Admin.Products.Placeholder.SignupInstructions' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['signup_instructions'].errors, 'quill-container': true\n }\">\n </quill-editor>\n </pw-input-container>\n </div>\n <div class=\"col-12\" id=\"signupEmployeesEditor\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.SignupInstructionEmployees' | transloco\"\n [label]=\"'Admin.Products.SignupInstructionEmployees' | transloco\" name=\"signup_instruction_employees\" controlId=\"product-signup_instruction_employees\" [useAriaLabelledbyOnly]=\"true\">\n <quill-editor [attr.aria-labelledby]=\"'product-signup_instruction_employees-label'\" [styles]=\"{ height: '220px' }\" formControlName=\"signup_instruction_employees\" class=\"quillEditor\" [modules]=\"editorConfig\"\n [placeholder]=\"'Admin.Products.Placeholder.SignupInstructionEmployees' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['signup_instruction_employees'].errors, 'quill-container': true\n }\">\n </quill-editor>\n </pw-input-container>\n </div>\n </div>\n\n <!-- Section: Visibility, Support & Compliance -->\n <h3>{{ 'Admin.Products.Section.Visibility' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-6 col-md-3\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.IsActive' | transloco\"\n [label]=\"'Admin.Products.IsActive' | transloco\" name=\"active\" controlId=\"product-active\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"active\" name=\"active\"\n [attr.aria-labelledby]=\"'product-active-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['active'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-6 col-md-3\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.IsVisible' | transloco\"\n [label]=\"'Admin.Products.IsVisible' | transloco\" name=\"visible\" controlId=\"product-visible\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"visible\" name=\"visible\"\n [attr.aria-labelledby]=\"'product-visible-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['visible'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-6 col-md-3\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MembersVisible' | transloco\"\n [label]=\"'Admin.Products.MembersVisible' | transloco\" name=\"members_visible\" controlId=\"product-members_visible\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"members_visible\" name=\"members_visible\"\n [attr.aria-labelledby]=\"'product-members_visible-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['members_visible'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-6 col-md-3\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.ChatVisible' | transloco\"\n [label]=\"'Admin.Products.ChatVisible' | transloco\" name=\"chat_visible\" controlId=\"product-chat_visible\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"chat_visible\" name=\"chat_visible\"\n [attr.aria-labelledby]=\"'product-chat_visible-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['chat_visible'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.ProductPrivacyService' | transloco\"\n [label]=\"'Admin.Products.ProductPrivacyService' | transloco\" name=\"product_privacy_service_id\" controlId=\"product-product_privacy_service_id\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-product_privacy_service_id-label'\"\n [options]=\"allTos\"\n formControlName=\"product_privacy_service_id\"\n [placeholder]=\"'Admin.Products.Placeholder.PrivacyService' | transloco\"\n optionValue=\"id\"\n optionLabel=\"title\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.GitLabServiceDeskEmail' | transloco\"\n [label]=\"'Admin.Products.GitLabServiceDeskEmail' | transloco\" name=\"gitlab_service_desk_email\" controlId=\"product-gitlab_service_desk_email\">\n <input type=\"text\" id=\"product-gitlab_service_desk_email\" class=\"form-control\" formControlName=\"gitlab_service_desk_email\"\n [placeholder]=\"'Admin.Products.Placeholder.GitlabServiceDeskEmail' | transloco\"\n [attr.aria-label]=\"'Admin.Products.GitLabServiceDeskEmail' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.LoginDefaultRoute' | transloco\"\n [label]=\"'Admin.Products.LoginDefaultRoute' | transloco\" name=\"login_default_route\" controlId=\"product-login_default_route\">\n <input type=\"text\" id=\"product-login_default_route\" class=\"form-control\" formControlName=\"login_default_route\"\n [placeholder]=\"'Admin.Products.Placeholder.LoginDefaultRoute' | transloco\"\n [attr.aria-label]=\"'Admin.Products.LoginDefaultRoute' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'Pages.Alpha'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.PartnerProducts' | transloco\"\n [label]=\"'Admin.Products.PartnerProducts' | transloco\" name=\"partner_products\" controlId=\"product-partner_products\" [useAriaLabelledbyOnly]=\"true\">\n <p-multiselect inputId=\"product-partner_products\"\n [options]=\"productsList\" (onChange)=\"onSearchPartnerProducts($event)\"\n [placeholder]=\"'Admin.Products.Placeholder.PartnerProducts' | transloco\"\n [attr.aria-labelledby]=\"'product-partner_products-label'\"\n [ngModelOptions]=\"{ standalone: true }\" [showToggleAll]=\"true\" [(ngModel)]=\"selectedPartnerProducts\"\n [showHeader]=\"true\" maxSelectedLabels=\"1\" appendTo=\"body\">\n </p-multiselect>\n </pw-input-container>\n </div>\n </div>\n </div>\n\n <div class=\"row text-end mt-4\">\n <div class=\"col-12\">\n <button type=\"button\" class=\"btn btn-outline-default me-2\" (click)=\"back()\"> {{ 'Button.Cancel' |\n transloco }} </button>\n <button type=\"submit\" [buttonBusy]=\"submitted\" class=\"btn btn-primary\" *rbacAllow=\"'Pages.Admin.Product.Edit'\"> {{ 'Button.Submit'\n | transloco }} </button>\n </div>\n </div>\n </form>\n }\n </div>\n </div>\n</div>\n<ng-template #content let-modal>\n <div class=\"modal-header\">\n <h3 class=\"modal-title mb-0 p-0\">{{ 'User.Subscriptions.FullLogo' | transloco }}</h3>\n <button type=\"button\" class=\"btn-close float-end\" aria-label=\"Close\" (click)=\"modal.dismiss()\">\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile (imageSelectionEvent)=\"onImageSelection($event)\" aspectRatio=\"fullLogo\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n</ng-template>\n<ng-template #squaredLogoContent let-modal>\n <div class=\"modal-header\">\n <h3 class=\"modal-title mb-0 p-0\">{{ 'User.Subscriptions.SquaredLogo' | transloco }}</h3>\n <button type=\"button\" class=\"btn-close float-end\" aria-label=\"Close\" (click)=\"modal.dismiss()\">\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile (imageSelectionEvent)=\"uploadSquaredLogo($event)\" aspectRatio=\"auto\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n</ng-template>\n",
|
|
18823
|
+
template: "<div class=\"container-fluid pw-tab product-form overflow-hidden\">\n <div class=\"dashboard\">\n <div class=\"dashboard-body\">\n <div class=\"me-auto col-xs-6 mt-4\">\n <a (click)=\"back()\" class=\"previous\" aria-label=\"Back\"><i class=\"fa fa-arrow-alt-circle-left\"\n aria-hidden=\"true\"></i></a>\n <h3 class=\"\">Product: {{ data?.name ? data?.name : 'Add New' }}</h3>\n </div>\n @if (isLoading) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progress-spinner strokeWidth=\"2\"> </p-progress-spinner>\n </div>\n }\n @if (!isLoading) {\n <div class=\"my-4\">\n <div class=\"mb-5\">\n <p-accordion class=\"pw-accordion-info\">\n <p-accordion-panel value=\"0\">\n <p-accordion-header>\n <i class=\"far fa-circle-info me-2 text-muted\"></i> How to configure a product\n </p-accordion-header>\n <p-accordion-content>\n <div class=\"row g-4 product-howto\">\n <div class=\"col-12 col-lg-7\">\n <h6 class=\"howto-title\">Product / feature binding</h6>\n <dl class=\"howto-defs\">\n <dt><code>category</code></dt>\n <dd>The product type — e.g. <code>seat_pricing</code> or <code>item_pricing</code>.</dd>\n <dt><code>feature_key</code></dt>\n <dd>Describes the main feature.</dd>\n <dt><code>permission_key</code></dt>\n <dd>A user can be subscribed to only one product per <code>permission_key</code>.</dd>\n <dt><code>product_key</code></dt>\n <dd>Unique per product; drives the frontend permission binding.</dd>\n </dl>\n <p class=\"howto-note\">\n Resulting permission key:\n <code>{{ 'Pages.Product.{permission_key}.{product_key}' }}</code>.\n For a feature tied to an existing product, set its <strong>dependency product</strong> accordingly.\n </p>\n </div>\n <div class=\"col-12 col-lg-5\">\n <h6 class=\"howto-title\">Setting up a free product</h6>\n <ul class=\"howto-list\">\n <li>Leave <code>Stripe Plan</code> empty.</li>\n <li>Set <code>Price per unit</code> to <code>0</code>.</li>\n <li>Set <code>Trial days</code> to a large value (e.g. <code>99999</code>).</li>\n <li>Turn <code>Visible</code> off.</li>\n </ul>\n </div>\n </div>\n </p-accordion-content>\n </p-accordion-panel>\n </p-accordion>\n </div>\n </div>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSave()\">\n <h3>{{ 'Admin.Products.Section.Identity' | transloco }}</h3>\n @if (id) {\n <div class=\"row\">\n <div class=\"col-md-6\">\n <div class=\"text-start mt-3\">\n <div class=\"image-container\">\n <h4 class=\"mb-2\"> {{ 'User.Subscriptions.FullLogo' | transloco }} <span class=\"tooltip-wrap ms-1\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.FullLogo'|transloco\" [appendTo]=\"'body'\"\n [tooltipPosition]=\"'top'\">\n <i class=\"far fa-info-circle text-muted\"></i>\n </span>\n </h4>\n @if (fullLogo && !fullLogo.includes('no_image_uploaded') && !fullLogoBroken) {\n <img [src]=\"fullLogo\" alt=\"Demo Logo\" class=\"image full-logo\"\n role=\"presentation\" (error)=\"fullLogoBroken = true\" />\n <div class=\"overlay mt-2\" (click)=\"openModal(content)\" (keydown.enter)=\"openModal(content)\">\n <div class=\"overlay-text\">\n <a>{{ 'User.Profile.Change' | transloco }}</a>\n </div>\n </div>\n } @else {\n <div class=\"logo-dropzone full-dropzone\" role=\"button\" tabindex=\"0\"\n aria-label=\"Upload full logo\" (keydown.enter)=\"openModal(content)\" (click)=\"openModal(content)\">\n <i class=\"fas fa-upload\"></i>\n <span class=\"dropzone-title\">Upload a logo</span>\n <span class=\"dropzone-hint\">PNG or JPG</span>\n </div>\n }\n </div>\n </div>\n </div>\n <div class=\"col-md-6\">\n <div class=\"text-start mt-3\">\n <div class=\"image-container\">\n <h4 class=\"mb-2\"> {{ 'User.Subscriptions.SquaredLogo' | transloco }} <span class=\"tooltip-wrap ms-1\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.SquaredLogo'|transloco\" [appendTo]=\"'body'\"\n [tooltipPosition]=\"'top'\">\n <i class=\"far fa-info-circle text-muted\"></i>\n </span>\n </h4>\n @if (squaredLogo && !squaredLogo.includes('no_image_uploaded') && !squaredLogoBroken) {\n <img [src]=\"squaredLogo\" alt=\"Company Logo\" class=\"squared_logo\"\n role=\"presentation\" (error)=\"squaredLogoBroken = true\" />\n <div class=\"overlay mt-2\" (keydown.enter)=\"openModal(squaredLogoContent)\" (click)=\"openModal(squaredLogoContent)\">\n <div class=\"overlay-text\">\n <a>{{ 'User.Profile.Change' | transloco }}</a>\n </div>\n </div>\n } @else {\n <div class=\"logo-dropzone squared-dropzone\" role=\"button\" tabindex=\"0\"\n aria-label=\"Upload squared logo\" (keydown.enter)=\"openModal(squaredLogoContent)\" (click)=\"openModal(squaredLogoContent)\">\n <i class=\"fas fa-upload\"></i>\n <span class=\"dropzone-title\">Upload a logo</span>\n <span class=\"dropzone-hint\">PNG or JPG</span>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n }\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Name' | transloco\"\n [label]=\"'Label.Name' | transloco\" name=\"name\" controlId=\"product-name\"\n [isLeftTooltip]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.Name' | transloco\">\n <input type=\"text\" id=\"product-name\" class=\"form-control\" formControlName=\"name\"\n [placeholder]=\"'Admin.Products.Placeholder.Name' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f['name'].errors }\"\n [attr.aria-label]=\"'Label.Name' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.NickName' | transloco\"\n [label]=\"'Admin.Products.NickName' | transloco\" name=\"nickname\" controlId=\"product-nickname\"\n [errorMsg]=\"'Admin.Products.Validation.NickName' | transloco\">\n <input type=\"text\" id=\"product-nickname\" class=\"form-control\" formControlName=\"nickname\"\n [placeholder]=\"'Admin.Products.Placeholder.NickName' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f['nickname'].errors }\"\n [attr.aria-label]=\"'Admin.Products.NickName' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.DocumentationUrl' | transloco\"\n [label]=\"'Admin.Products.DocumentationUrl' | transloco\" name=\"documentation_url\" controlId=\"product-documentation_url\">\n <input type=\"text\" id=\"product-documentation_url\" class=\"form-control\" formControlName=\"documentation_url\"\n [placeholder]=\"'Admin.Products.Placeholder.DocumentationUrl' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['documentation_url'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.DocumentationUrl' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12\" id=\"descriptionEditor\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Description' | transloco\"\n [label]=\"'Admin.Products.Description' | transloco\" name=\"description\" controlId=\"product-description\" [useAriaLabelledbyOnly]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.Description' | transloco\">\n <quill-editor [attr.aria-labelledby]=\"'product-description-label'\" [styles]=\"{ height: '220px' }\" formControlName=\"description\" class=\"quillEditor\" [modules]=\"editorConfig\"\n [placeholder]=\"'Admin.Products.Placeholder.Description' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f['description'].errors, 'quill-container': true}\">\n </quill-editor>\n </pw-input-container>\n </div>\n </div>\n\n <!-- Section: Pricing & Billing -->\n <h3>{{ 'Admin.Products.Section.Pricing' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Price' | transloco\"\n [isLeftTooltip]=\"true\"\n [label]=\"'Admin.Products.Price' | transloco\" name=\"price_per_unit\" controlId=\"product-price_per_unit\"\n [errorMsg]=\"'Admin.Products.Validation.Name' | transloco\">\n <input type=\"text\" id=\"product-price_per_unit\" numbersOnly class=\"form-control\" formControlName=\"price_per_unit\"\n [placeholder]=\"'Admin.Products.Placeholder.Price' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['price_per_unit'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.Price' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n @if (supportedCurrency$ | async; as currency) {\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Currency' | transloco\"\n [label]=\"'Admin.Products.Currency' | transloco\" name=\"currency\" controlId=\"product-currency\" [useAriaLabelledbyOnly]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.Currency' | transloco\">\n <p-select\n [attr.aria-labelledby]=\"'product-currency-label'\"\n [options]=\"currency['regions']\"\n formControlName=\"currency\"\n [ngClass]=\"{ 'is-invalid': submitted && f['currency'].errors }\"\n [placeholder]=\"'Admin.Products.Placeholder.Currency' | transloco\"\n [showClear]=\"false\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n }\n @if (supportedRegions$ | async; as region) {\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.Region' | transloco\"\n [isLeftTooltip]=\"true\"\n [label]=\"'Admin.Products.Region' | transloco\" name=\"region\" controlId=\"product-region\" [useAriaLabelledbyOnly]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.Region' | transloco\">\n <p-select\n [attr.aria-labelledby]=\"'product-region-label'\"\n [options]=\"region['regions']\"\n formControlName=\"region\"\n [ngClass]=\"{ 'is-invalid': submitted && f['region'].errors }\"\n [placeholder]=\"'Admin.Products.Placeholder.Region' | transloco\"\n [showClear]=\"false\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n }\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.BillingFrequency' | transloco\"\n [label]=\"'Admin.Products.BillingFrequency' | transloco\" name=\"billing_frequency\" controlId=\"product-billing_frequency\" [useAriaLabelledbyOnly]=\"true\"\n [errorMsg]=\"'Admin.Products.Validation.BillingFrequency' | transloco\">\n <p-select inputId=\"product-billing_frequency\"\n [options]=\"frequency\" class=\"dropdown-bg-transparent\" [attr.aria-labelledby]=\"'product-billing_frequency-label'\" formControlName=\"billing_frequency\"\n [placeholder]=\"'Admin.Products.Placeholder.BillingFrequency' | transloco\"\n [required]=\"true\" [ngClass]=\"{\n 'is-invalid': submitted && f['billing_frequency'].errors\n }\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Admin.Products.MinUnit' | transloco\" [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MinUnits' | transloco\" name=\"min_units\" controlId=\"product-min_units\"\n [errorMsg]=\"'Admin.Products.Validation.MinUnit' | transloco\">\n <input type=\"number\" id=\"product-min_units\" min=\"1\" class=\"form-control\" formControlName=\"min_units\" [ngClass]=\"{\n 'is-invalid': submitted && f['min_units'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.MinUnit' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Admin.Products.MaxUnit' | transloco\" [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MaxUnits' | transloco\" name=\"max_units\" controlId=\"product-max_units\"\n [errorMsg]=\"'Admin.Products.Validation.MaxUnit' | transloco\">\n <input type=\"number\" id=\"product-max_units\" min=\"1\" class=\"form-control\" formControlName=\"max_units\" [ngClass]=\"{\n 'is-invalid': submitted && f['max_units'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.MaxUnit' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.StripePlan' | transloco\"\n [label]=\"'Admin.Products.StripePlan' | transloco\" name=\"stripe_plan_id\" controlId=\"product-stripe_plan_id\">\n <input type=\"text\" id=\"product-stripe_plan_id\" class=\"form-control\" formControlName=\"stripe_plan_id\"\n [placeholder]=\"'Admin.Products.Placeholder.StripePlan' | transloco\"\n [attr.aria-label]=\"'Admin.Products.StripePlan' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'Pages.Alpha'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.ProrationBehavior' | transloco\"\n [label]=\"'Admin.Products.ProrationBehavior' | transloco\" name=\"proration_behavior\" controlId=\"product-proration_behavior\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-proration_behavior-label'\"\n [options]=\"prorationBehaviors\"\n formControlName=\"proration_behavior\"\n [placeholder]=\"'Admin.Products.Placeholder.ProrationBehavior' | transloco\"\n optionValue=\"value\"\n optionLabel=\"label\"\n [showClear]=\"true\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'Pages.Alpha'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.UnsubscribeStripeBehavior' | transloco\"\n [label]=\"'Admin.Products.UnsubscribeStripeBehavior' | transloco\" name=\"unsubscribe_stripe_behavior\" controlId=\"product-unsubscribe_stripe_behavior\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-unsubscribe_stripe_behavior-label'\"\n [options]=\"unsubscribeBehaviors\"\n formControlName=\"unsubscribe_stripe_behavior\"\n [placeholder]=\"'Admin.Products.Placeholder.UnsubscribeBehavior' | transloco\"\n optionValue=\"value\"\n optionLabel=\"label\"\n [showClear]=\"true\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <pw-product-backup-card *rbacAllow=\"'SuperAdmin'\" [form]=\"form\" [provider]=\"data?.second_payment_provider\"\n [submitted]=\"submitted\"></pw-product-backup-card>\n </div>\n\n <!-- Section: Trial -->\n <h3>{{ 'Admin.Products.Section.Trial' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.TrialDays' | transloco\"\n [label]=\"'Admin.Products.TrialDays' | transloco\" name=\"trial_days\" controlId=\"product-trial_days\"\n [errorMsg]=\"'Admin.Products.Validation.TrialDays' | transloco\">\n <input type=\"number\" id=\"product-trial_days\" min=\"0\" class=\"form-control\" formControlName=\"trial_days\" [ngClass]=\"{\n 'is-invalid': submitted && f['trial_days'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.TrialDays' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MaxTrialHits' | transloco\"\n [label]=\"'Admin.Products.MaxTrialHits' | transloco\" name=\"max_hits_trial\" controlId=\"product-max_hits_trial\">\n <input type=\"number\" id=\"product-max_hits_trial\" min=\"0\" class=\"form-control\" formControlName=\"max_hits_trial\" [ngClass]=\"{\n 'is-invalid': submitted && f['max_hits_trial'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.MaxTrialHits' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.TrialHits' | transloco\"\n [label]=\"'Admin.Products.TrialHits' | transloco\" name=\"max_hits\" controlId=\"product-max_hits\">\n <input type=\"number\" id=\"product-max_hits\" min=\"0\" class=\"form-control\" formControlName=\"max_hits\"\n [ngClass]=\"{ 'is-invalid': submitted && f['max_hits'].errors }\"\n [attr.aria-label]=\"'Admin.Products.TrialHits' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n </div>\n\n <!-- Section: Feature & Permission Binding -->\n <h3>{{ 'Admin.Products.Section.Binding' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Admin.Products.Category' | transloco\"\n [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.PermissionKey' | transloco\"\n name=\"category\" controlId=\"product-category\" [useAriaLabelledbyOnly]=\"true\" [errorMsg]=\"'Admin.Products.Validation.Category' | transloco\">\n <p-select inputId=\"product-category\"\n [options]=\"categories\" class=\"dropdown-bg-transparent\" [attr.aria-labelledby]=\"'product-category-label'\" formControlName=\"category\"\n [placeholder]=\"'Admin.Products.Placeholder.Category' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f['category'].errors }\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.FeatureKey' | transloco\"\n [label]=\"'Admin.Products.FeatureKey' | transloco\" name=\"feature_key\" controlId=\"product-feature_key\"\n [errorMsg]=\"'Admin.Products.Validation.FeatureKey' | transloco\">\n <input type=\"text\" id=\"product-feature_key\" class=\"form-control\"\n [placeholder]=\"'Admin.Products.Placeholder.FeatureKey' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['feature_key'].errors\n }\" formControlName=\"feature_key\"\n [attr.aria-label]=\"'Admin.Products.FeatureKey' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.PermissionKey' | transloco\"\n [label]=\"'Admin.Products.PermissionKey' | transloco\" name=\"permission_key\" controlId=\"product-permission_key\"\n [errorMsg]=\"'Admin.Products.Validation.PermissionKey' | transloco\">\n <input type=\"text\" id=\"product-permission_key\" class=\"form-control\"\n [placeholder]=\"'Admin.Products.Placeholder.PermissionKey' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['permission_key'].errors\n }\" formControlName=\"permission_key\"\n [attr.aria-label]=\"'Admin.Products.PermissionKey' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [label]=\"'Admin.Products.ProductKey' | transloco\"\n [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.PermissionKey' | transloco\"\n name=\"product_key\" controlId=\"product-product_key\"\n [errorMsg]=\"'Admin.Products.Validation.ProductKey' | transloco\">\n <input type=\"text\" id=\"product-product_key\" class=\"form-control\" formControlName=\"product_key\"\n [placeholder]=\"'Admin.Products.Placeholder.ProductKey' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['product_key'].errors\n }\"\n [attr.aria-label]=\"'Admin.Products.ProductKey' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <span class=\"pw-label-style\" id=\"product-dependency_products-label\" [pTooltip]=\"'Admin.Products.Tooltip.DependencyProducts' | transloco\" tooltipPosition=\"top\" appendTo=\"body\"> {{ 'Admin.Products.DependencyProducts' | transloco }}<i class=\"far fa-info-circle\" aria-hidden=\"true\"></i>\n </span>\n <p-multiselect inputId=\"product-dependency_products\"\n [options]=\"productsList\" [(ngModel)]=\"selectedScopes\"\n [placeholder]=\"'Admin.Products.Placeholder.DependencyProducts' | transloco\"\n [attr.aria-labelledby]=\"'product-dependency_products-label'\"\n [ngModelOptions]=\"{ standalone: true }\" (onChange)=\"onSearchCriteria($event)\" [showHeader]=\"false\"\n maxSelectedLabels=\"1\" appendTo=\"body\">\n </p-multiselect>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <span class=\"pw-label-style\" id=\"product-roles-label\" [pTooltip]=\"'Admin.Subscriptions.Tooltip.AssignedRoles' | transloco\" tooltipPosition=\"top\" appendTo=\"body\">{{ 'Admin.Products.AssignedRoles' | transloco }} <i class=\"far fa-info-circle\" aria-hidden=\"true\"></i>\n </span>\n <p-multiselect inputId=\"product-roles\" [options]=\"allRoles\" formControlName=\"roles\" appendTo=\"body\"\n [placeholder]=\"'Admin.Products.Placeholder.Roles' | transloco\"\n [attr.aria-labelledby]=\"'product-roles-label'\"></p-multiselect>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'SuperAdmin'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MasterProduct' | transloco\"\n [label]=\"'Admin.Products.MasterProduct' | transloco\" name=\"master_product_id\" controlId=\"product-master_product_id\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-master_product_id-label'\"\n [options]=\"productsList\"\n formControlName=\"master_product_id\"\n [placeholder]=\"'Admin.Products.Placeholder.MasterProduct' | transloco\"\n optionValue=\"value\"\n optionLabel=\"label\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'SuperAdmin'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.IsMasterProduct' | transloco\"\n [label]=\"'Admin.Products.IsMasterProduct' | transloco\" name=\"is_master_product\" controlId=\"product-is_master_product\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"is_master_product\" name=\"is_master_product\"\n [attr.aria-labelledby]=\"'product-is_master_product-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['is_master_product'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'SuperAdmin'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MultipleAllowed' | transloco\"\n [label]=\"'Admin.Products.MultipleAllowed' | transloco\" class=\"nowrap\" name=\"multiple_allowed\" controlId=\"product-multiple_allowed\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"multiple_allowed\" name=\"multiple_allowed\"\n [attr.aria-labelledby]=\"'product-multiple_allowed-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['multiple_allowed'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n </div>\n\n <!-- Section: Onboarding & Signup -->\n <h3>{{ 'Admin.Products.Section.Signup' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-12\" id=\"signupInstructionsEditor\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.SignupInstructions' | transloco\"\n [label]=\"'Admin.Products.SignupInstructions' | transloco\" name=\"signup_instructions\" controlId=\"product-signup_instructions\" [useAriaLabelledbyOnly]=\"true\">\n <quill-editor [attr.aria-labelledby]=\"'product-signup_instructions-label'\" [styles]=\"{ height: '220px' }\" formControlName=\"signup_instructions\" class=\"quillEditor\" [modules]=\"editorConfig\"\n [placeholder]=\"'Admin.Products.Placeholder.SignupInstructions' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['signup_instructions'].errors, 'quill-container': true\n }\">\n </quill-editor>\n </pw-input-container>\n </div>\n <div class=\"col-12\" id=\"signupEmployeesEditor\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.SignupInstructionEmployees' | transloco\"\n [label]=\"'Admin.Products.SignupInstructionEmployees' | transloco\" name=\"signup_instruction_employees\" controlId=\"product-signup_instruction_employees\" [useAriaLabelledbyOnly]=\"true\">\n <quill-editor [attr.aria-labelledby]=\"'product-signup_instruction_employees-label'\" [styles]=\"{ height: '220px' }\" formControlName=\"signup_instruction_employees\" class=\"quillEditor\" [modules]=\"editorConfig\"\n [placeholder]=\"'Admin.Products.Placeholder.SignupInstructionEmployees' | transloco\" [ngClass]=\"{\n 'is-invalid': submitted && f['signup_instruction_employees'].errors, 'quill-container': true\n }\">\n </quill-editor>\n </pw-input-container>\n </div>\n </div>\n\n <!-- Section: Visibility, Support & Compliance -->\n <h3>{{ 'Admin.Products.Section.Visibility' | transloco }}</h3>\n <div class=\"row\">\n <div class=\"col-6 col-md-3\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\" [tooltipText]=\"'Admin.Products.Tooltip.IsActive' | transloco\"\n [label]=\"'Admin.Products.IsActive' | transloco\" name=\"active\" controlId=\"product-active\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"active\" name=\"active\"\n [attr.aria-labelledby]=\"'product-active-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['active'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-6 col-md-3\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.IsVisible' | transloco\"\n [label]=\"'Admin.Products.IsVisible' | transloco\" name=\"visible\" controlId=\"product-visible\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"visible\" name=\"visible\"\n [attr.aria-labelledby]=\"'product-visible-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['visible'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-6 col-md-3\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.MembersVisible' | transloco\"\n [label]=\"'Admin.Products.MembersVisible' | transloco\" name=\"members_visible\" controlId=\"product-members_visible\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"members_visible\" name=\"members_visible\"\n [attr.aria-labelledby]=\"'product-members_visible-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['members_visible'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-6 col-md-3\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.ChatVisible' | transloco\"\n [label]=\"'Admin.Products.ChatVisible' | transloco\" name=\"chat_visible\" controlId=\"product-chat_visible\" [useAriaLabelledbyOnly]=\"true\">\n <ui-switch class=\"d-block\" formControlName=\"chat_visible\" name=\"chat_visible\"\n [attr.aria-labelledby]=\"'product-chat_visible-label'\"\n [ngClass]=\"{ 'is-invalid': submitted && f['chat_visible'].errors }\">\n </ui-switch>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.ProductPrivacyService' | transloco\"\n [label]=\"'Admin.Products.ProductPrivacyService' | transloco\" name=\"product_privacy_service_id\" controlId=\"product-product_privacy_service_id\" [useAriaLabelledbyOnly]=\"true\">\n <p-select\n [attr.aria-labelledby]=\"'product-product_privacy_service_id-label'\"\n [options]=\"allTos\"\n formControlName=\"product_privacy_service_id\"\n [placeholder]=\"'Admin.Products.Placeholder.PrivacyService' | transloco\"\n optionValue=\"id\"\n optionLabel=\"title\">\n </p-select>\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.GitLabServiceDeskEmail' | transloco\"\n [label]=\"'Admin.Products.GitLabServiceDeskEmail' | transloco\" name=\"gitlab_service_desk_email\" controlId=\"product-gitlab_service_desk_email\">\n <input type=\"text\" id=\"product-gitlab_service_desk_email\" class=\"form-control\" formControlName=\"gitlab_service_desk_email\"\n [placeholder]=\"'Admin.Products.Placeholder.GitlabServiceDeskEmail' | transloco\"\n [attr.aria-label]=\"'Admin.Products.GitLabServiceDeskEmail' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.LoginDefaultRoute' | transloco\"\n [label]=\"'Admin.Products.LoginDefaultRoute' | transloco\" name=\"login_default_route\" controlId=\"product-login_default_route\">\n <input type=\"text\" id=\"product-login_default_route\" class=\"form-control\" formControlName=\"login_default_route\"\n [placeholder]=\"'Admin.Products.Placeholder.LoginDefaultRoute' | transloco\"\n [attr.aria-label]=\"'Admin.Products.LoginDefaultRoute' | transloco\" />\n </pw-input-container>\n </div>\n </div>\n <div class=\"col-12 col-md-4\" *rbacAllow=\"'Pages.Alpha'\">\n <div class=\"mb-3\">\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'Admin.Products.Tooltip.PartnerProducts' | transloco\"\n [label]=\"'Admin.Products.PartnerProducts' | transloco\" name=\"partner_products\" controlId=\"product-partner_products\" [useAriaLabelledbyOnly]=\"true\">\n <p-multiselect inputId=\"product-partner_products\"\n [options]=\"productsList\" (onChange)=\"onSearchPartnerProducts($event)\"\n [placeholder]=\"'Admin.Products.Placeholder.PartnerProducts' | transloco\"\n [attr.aria-labelledby]=\"'product-partner_products-label'\"\n [ngModelOptions]=\"{ standalone: true }\" [showToggleAll]=\"true\" [(ngModel)]=\"selectedPartnerProducts\"\n [showHeader]=\"true\" maxSelectedLabels=\"1\" appendTo=\"body\">\n </p-multiselect>\n </pw-input-container>\n </div>\n </div>\n </div>\n\n <div class=\"row text-end mt-4\">\n <div class=\"col-12\">\n <button type=\"button\" class=\"btn btn-outline-default me-2\" (click)=\"back()\"> {{ 'Button.Cancel' |\n transloco }} </button>\n <button type=\"submit\" [buttonBusy]=\"submitted\" class=\"btn btn-primary\" *rbacAllow=\"'Pages.Admin.Product.Edit'\"> {{ 'Button.Submit'\n | transloco }} </button>\n </div>\n </div>\n </form>\n }\n </div>\n </div>\n</div>\n<ng-template #content let-modal>\n <div class=\"modal-header\">\n <h3 class=\"modal-title mb-0 p-0\">{{ 'User.Subscriptions.FullLogo' | transloco }}</h3>\n <button type=\"button\" class=\"btn-close float-end\" aria-label=\"Close\" (click)=\"modal.dismiss()\">\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile (imageSelectionEvent)=\"onImageSelection($event)\" aspectRatio=\"fullLogo\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n</ng-template>\n<ng-template #squaredLogoContent let-modal>\n <div class=\"modal-header\">\n <h3 class=\"modal-title mb-0 p-0\">{{ 'User.Subscriptions.SquaredLogo' | transloco }}</h3>\n <button type=\"button\" class=\"btn-close float-end\" aria-label=\"Close\" (click)=\"modal.dismiss()\">\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile (imageSelectionEvent)=\"uploadSquaredLogo($event)\" aspectRatio=\"auto\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n</ng-template>\n",
|
|
18575
18824
|
styles: [".pw-label-style.info-circle{display:inline-block;line-height:1.5}.pw-label-style.info-circle:after{top:-7px}.nowrap{white-space:nowrap}textarea{height:180px}:host .full-logo,:host .squared_logo{background:#f7f8fa;border:1px solid #e2e5ea;border-radius:8px;object-fit:contain;padding:12px}:host .full-logo{height:120px;width:280px}:host .squared_logo{height:150px;width:150px}:host .overlay{cursor:pointer;margin-top:8px}:host .overlay-text a{color:var(--first, #1769e1);cursor:pointer;font-weight:600}:host .overlay-text a:hover{text-decoration:underline}:host .image-container>h4{color:var(--titles, #222);font-size:14px;font-weight:600}:host form>h3{display:block;border-top:1px solid #e2e5ea;margin-top:2rem;padding-top:1.25rem}:host form>h3:first-child{border-top:0;margin-top:.5rem;padding-top:0}:host .product-howto{font-size:.9rem}:host .howto-title{font-weight:700;margin-bottom:.85rem}:host .howto-defs{margin:0}:host .howto-defs dt{font-weight:600;margin-top:.55rem}:host .howto-defs dd{margin:.1rem 0 0;color:var(--bs-secondary-color, #6c757d)}:host .howto-list{margin:0;padding-left:1.1rem}:host .howto-list li{margin-bottom:.45rem}:host .howto-note{margin-top:1rem;color:var(--bs-secondary-color, #6c757d)}:host .product-howto code{background:#1769e114;color:var(--first, #1769e1);padding:.1rem .4rem;border-radius:4px;font-size:.85em}\n"]
|
|
18576
18825
|
}]
|
|
18577
18826
|
}],
|
|
@@ -36964,6 +37213,7 @@ var AdminModule = class AdminModule {
|
|
|
36964
37213
|
NewsletterItemDetailsComponent,
|
|
36965
37214
|
NewsLetterItemViewComponent,
|
|
36966
37215
|
ProductDetailsComponent,
|
|
37216
|
+
ProductBackupCardComponent,
|
|
36967
37217
|
RoleDetailsComponent,
|
|
36968
37218
|
TagsTabsComponent,
|
|
36969
37219
|
TipComponent,
|
|
@@ -37173,6 +37423,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
37173
37423
|
NewsletterItemDetailsComponent,
|
|
37174
37424
|
NewsLetterItemViewComponent,
|
|
37175
37425
|
ProductDetailsComponent,
|
|
37426
|
+
ProductBackupCardComponent,
|
|
37176
37427
|
RoleDetailsComponent,
|
|
37177
37428
|
TagsTabsComponent,
|
|
37178
37429
|
TipComponent,
|