@posiwise/user-module 0.0.147 → 0.0.148
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,39 +1,41 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as i5 from '@angular/common';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { ViewChild, Component, EventEmitter, Output, Input, NgModule } from '@angular/core';
|
|
4
|
+
import { ViewChild, Component, EventEmitter, Output, Input, HostListener, Optional, Self, Directive, Pipe, NgModule } from '@angular/core';
|
|
5
5
|
import * as i2 from '@angular/forms';
|
|
6
6
|
import { Validators, ReactiveFormsModule, FormsModule } from '@angular/forms';
|
|
7
7
|
import * as i1 from '@angular/router';
|
|
8
8
|
import { RouterModule } from '@angular/router';
|
|
9
|
-
import * as i6
|
|
9
|
+
import * as i6 from '@angular-magic/ngx-gp-autocomplete';
|
|
10
10
|
import { NgxGpAutocompleteModule } from '@angular-magic/ngx-gp-autocomplete';
|
|
11
11
|
import { AppConfigService } from '@posiwise/app-config-service';
|
|
12
|
+
import * as i3 from '@posiwise/app-loader';
|
|
13
|
+
import { AppLoaderModule } from '@posiwise/app-loader';
|
|
12
14
|
import { CoreTranslocoModule } from '@posiwise/core-transloco';
|
|
13
15
|
import * as i4 from '@posiwise/directives';
|
|
14
16
|
import { DirectivesModule } from '@posiwise/directives';
|
|
15
|
-
import * as i6$
|
|
17
|
+
import * as i6$1 from '@posiwise/pipes';
|
|
16
18
|
import { PipesModule } from '@posiwise/pipes';
|
|
17
|
-
import * as
|
|
19
|
+
import * as i7 from '@posiwise/shared-components';
|
|
18
20
|
import { SharedComponentsModule } from '@posiwise/shared-components';
|
|
19
|
-
import * as i6$
|
|
21
|
+
import * as i6$2 from 'ngx-captcha';
|
|
20
22
|
import { NgxCaptchaModule } from 'ngx-captcha';
|
|
21
23
|
import * as i11$1 from 'ngx-ui-switch';
|
|
22
24
|
import { UiSwitchModule } from 'ngx-ui-switch';
|
|
23
25
|
import * as i2$2 from 'primeng/accordion';
|
|
24
26
|
import { AccordionModule } from 'primeng/accordion';
|
|
25
|
-
import * as i7$
|
|
27
|
+
import * as i7$3 from 'primeng/datepicker';
|
|
26
28
|
import { DatePickerModule } from 'primeng/datepicker';
|
|
27
|
-
import * as i7 from 'primeng/fileupload';
|
|
29
|
+
import * as i7$2 from 'primeng/fileupload';
|
|
28
30
|
import { FileUploadModule } from 'primeng/fileupload';
|
|
29
31
|
import * as i1$3 from 'primeng/inputtext';
|
|
30
32
|
import { InputTextModule } from 'primeng/inputtext';
|
|
31
33
|
import { MultiSelectModule } from 'primeng/multiselect';
|
|
32
34
|
import * as i4$1 from 'primeng/progressspinner';
|
|
33
35
|
import { ProgressSpinnerModule } from 'primeng/progressspinner';
|
|
34
|
-
import * as i6$
|
|
36
|
+
import * as i6$3 from 'primeng/rating';
|
|
35
37
|
import { RatingModule } from 'primeng/rating';
|
|
36
|
-
import * as
|
|
38
|
+
import * as i7$1 from 'primeng/select';
|
|
37
39
|
import { SelectModule } from 'primeng/select';
|
|
38
40
|
import * as i8$1 from 'primeng/selectbutton';
|
|
39
41
|
import { SelectButtonModule } from 'primeng/selectbutton';
|
|
@@ -99,7 +101,7 @@ class AccountComponent {
|
|
|
99
101
|
this.activeItem = this.menu['activeItem'];
|
|
100
102
|
}
|
|
101
103
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: AccountComponent, deps: [{ token: i1.Router }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
102
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.6", type: AccountComponent, isStandalone: false, selector: "pw-user-account", viewQueries: [{ propertyName: "menu", first: true, predicate: ["menuItems"], descendants: true, static: true }], ngImport: i0, template: "<pw-tabs [items]=\"items\"></pw-tabs>\n", dependencies: [{ kind: "component", type:
|
|
104
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.6", type: AccountComponent, isStandalone: false, selector: "pw-user-account", viewQueries: [{ propertyName: "menu", first: true, predicate: ["menuItems"], descendants: true, static: true }], ngImport: i0, template: "<pw-tabs [items]=\"items\"></pw-tabs>\n", dependencies: [{ kind: "component", type: i7.PwTabsComponent, selector: "pw-tabs", inputs: ["items", "withSubscription"] }] }); }
|
|
103
105
|
}
|
|
104
106
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: AccountComponent, decorators: [{
|
|
105
107
|
type: Component,
|
|
@@ -474,7 +476,7 @@ class AccountDetailsComponent extends AppBaseComponent {
|
|
|
474
476
|
});
|
|
475
477
|
}
|
|
476
478
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: AccountDetailsComponent, deps: [{ token: i2.UntypedFormBuilder }, { token: i1$1.NgbModal }, { token: i1$2.AuthService }, { token: i1$2.GeoService }, { token: i1$2.ProfileService }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
477
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: AccountDetailsComponent, isStandalone: false, selector: "pw-account-details", viewQueries: [{ propertyName: "placesRef", first: true, predicate: ["ngxPlaces"], descendants: true }, { propertyName: "passwordRef", first: true, predicate: ["password"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"w-100 text-center\">\n @if (!isLoaded) {\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n }\n</div>\n<div class=\"row gx-3 mb-3\">\n <div class=\"col-md-4\">\n <section class=\"card p-4 h-100 d-flex flex-column\">\n <h2>{{ 'User.Profile.Avatar' | transloco }}</h2>\n <div class=\"text-center d-flex flex-column justify-content-center flex-grow-1 mt-1\">\n <div class=\"image-container\">\n <img [src]=\"image\"\n width=\"150\"\n height=\"150\"\n class=\"image rounded-circle\"\n alt=\"User Male\"\n (error)=\"handleImageError($event, 'assets/img/icons/male.png')\" />\n <div class=\"overlay\"\n (keydown.enter)=\"openModal(content)\"\n (click)=\"openModal(content)\">\n <div class=\"overlay-text\">{{ 'User.Profile.Change' | transloco }}</div>\n </div>\n </div>\n <h4 class=\"mt-2\">{{ user?.first_name }} {{ user?.last_name }}</h4>\n <a aria-label=\"Navigate to Target\"\n class=\"d-inline-block mb-2\"\n (click)=\"openModal(content)\">\n {{ 'User.Profile.EditAvatar' | transloco }}</a>\n </div>\n </section>\n </div>\n <div class=\"col-md-8\">\n <section id=\"user-profile\"\n class=\"card p-4 overflow-visible h-100\">\n <form [formGroup]=\"profileForm\"\n (ngSubmit)=\"onProfileFormSubmit()\">\n <h2>{{ 'User.Profile.UserProfile' | transloco }}</h2>\n <div class=\"row mt-3\">\n <div class=\"col-sm-12 col-md-6 col-lg-6\">\n <pw-input-container label=\"First Name\"\n name=\"first_name\"\n controlId=\"account-first_name\"\n errorMsg=\"Please enter first Name\">\n <input type=\"text\"\n id=\"account-first_name\"\n class=\"form-control\"\n formControlName=\"first_name\"\n autocomplete=\"given-name\" name=\"input_first_name_9\"/>\n </pw-input-container>\n <pw-input-container label=\"Preferred name\"\n name=\"preferred_name\"\n controlId=\"account-preferred_name\"\n errorMsg=\"Please enter preferred Name\">\n <input type=\"text\"\n id=\"account-preferred_name\"\n class=\"form-control\"\n formControlName=\"preferred_name\"\n autocomplete=\"username\" name=\"input_preferred_name_10\"/>\n </pw-input-container>\n @if (countries$ | async; as countries) {\n <pw-input-container label=\"Country\"\n name=\"country\"\n controlId=\"account-country\"\n [useAriaLabelledbyOnly]=\"true\"\n errorMsg=\"Please select a country\">\n <p-select\n [attr.aria-labelledby]=\"'account-country-label'\"\n [options]=\"countries\"\n optionLabel=\"name\"\n optionValue=\"code\"\n formControlName=\"country\"\n (onChange)=\"getRegion($event.value)\"\n placeholder=\"{{ 'User.Profile.SelectCountry' | transloco }}\">\n </p-select>\n </pw-input-container>\n }\n <pw-input-container label=\"Province\"\n name=\"province\"\n controlId=\"account-province\"\n errorMsg=\"Please enter province\">\n <input type=\"text\"\n id=\"account-province\"\n class=\"form-control\"\n formControlName=\"province\"\n autocomplete=\"postal-code\" name=\"input_province_11\"/>\n </pw-input-container>\n <pw-input-container label=\"Website Url\"\n name=\"website_url\"\n controlId=\"account-website_url\"\n errorMsg=\"Please enter Website\">\n <input type=\"text\"\n id=\"account-website_url\"\n class=\"form-control\"\n formControlName=\"website_url\"\n autocomplete=\"url\" name=\"input_website_url_12\"/>\n </pw-input-container>\n </div>\n <div class=\"col-sm-12 col-md-6 col-lg-6\">\n <pw-input-container label=\"Last Name\"\n name=\"last_name\"\n controlId=\"account-last_name\"\n errorMsg=\"Please enter last Name\">\n <input type=\"text\"\n id=\"account-last_name\"\n class=\"form-control\"\n formControlName=\"last_name\"\n autocomplete=\"family-name\" name=\"input_last_name_13\"/>\n </pw-input-container>\n <pw-input-container label=\"Date of Birth\"\n name=\"dob\"\n controlId=\"account-dob\"\n errorMsg=\"Please enter date of birth\">\n <div class=\"input-group\">\n <input class=\"form-control\"\n id=\"account-dob\"\n name=\"dob\"\n placeholder=\"dd-mmm-yyyy\"\n formControlName=\"dob\"\n ngbDatepicker\n #d=\"ngbDatepicker\"\n [minDate]=\"{ day: 1, month: 1, year: 1950 }\"\n [maxDate]=\"{ day: 31, month: 12, year: 2018 }\" />\n <button class=\"btn btn-primary\"\n type=\"button\"\n id=\"account-dob-trigger\"\n aria-label=\"Open date picker for date of birth\"\n (click)=\"d.toggle()\">\n <i class=\"fa fa-calendar\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </pw-input-container>\n <pw-input-container label=\"State\"\n name=\"state\"\n controlId=\"account-state\"\n [useAriaLabelledbyOnly]=\"true\"\n errorMsg=\"Please select a state\">\n <p-select\n [attr.aria-labelledby]=\"'account-state-label'\"\n [options]=\"states\"\n [(ngModel)]=\"selectedState\"\n optionLabel=\"name\"\n optionValue=\"code\"\n formControlName=\"state\"\n [placeholder]=\"'User.Profile.SelectState' | transloco\">\n </p-select>\n </pw-input-container>\n <pw-input-container label=\"Location\"\n name=\"location\"\n controlId=\"account-location\"\n [useAriaLabelledbyOnly]=\"true\">\n <input ngx-gp-autocomplete\n id=\"account-location\"\n name=\"location\"\n class=\"form-control\"\n [attr.aria-labelledby]=\"'account-location-label'\"\n #places=\"ngx-places\"\n formControlName=\"location\"\n (onAddressChange)=\"handleAddressChange($event)\" />\n </pw-input-container>\n <pw-input-container label=\"Phone Number\"\n name=\"phone_number\"\n controlId=\"account-phone_number\"\n errorMsg=\"Please enter phone number\">\n <input type=\"text\"\n id=\"account-phone_number\"\n class=\"form-control\"\n formControlName=\"phone_number\"\n autocomplete=\"tel\" name=\"input_phone_number_16\"/>\n </pw-input-container>\n </div>\n <div class=\"col-12 text-end\">\n <div class=\"mb-3\">\n <button class=\"btn btn-raised btn-primary\" [buttonBusy]=\"profileBusyButton\">\n {{ 'Button.Save' | transloco }}\n </button>\n </div>\n </div>\n </div>\n </form>\n </section>\n </div>\n</div>\n<div class=\"row gx-3 mb-3\">\n <div class=\"col-md-6\">\n <section id=\"email-section\"\n class=\"card p-4 h-100\">\n <div class=\"row\">\n <div class=\"col-12\">\n <h2>{{ 'User.Account.RegisteredEmail' | transloco }}</h2>\n <section id=\"email-form\">\n <form [formGroup]=\"emailForm\"\n (ngSubmit)=\"onEmailFormSubmit()\">\n <!-- Email Address -->\n <div class=\"mt-0\">\n <span id=\"account-primary-email-label\" class=\"me-3 pw-label-style\">{{ 'User.Account.PrimaryEmail' | transloco }}:\n </span>\n <strong>{{ validatedEmail }}</strong>\n <div class=\"mt-1\">\n @if (!toggleEmail) {\n <a class=\"btn btn-raised btn-outline-primary\"\n aria-label=\"Navigate to Target\"\n (click)=\"shouldUserChangeEmail()\">\n {{ 'User.Account.ChangeEmail' | transloco }}</a>\n }\n @if (toggleEmail) {\n <div class=\"row\">\n <div class=\"clearfix\"></div>\n <div class=\"col-12 mb-3\">\n @if (!passwordVerified) {\n <input type=\"password\"\n class=\"form-control\"\n id=\"account-email-current-password\"\n name=\"currentPassword\"\n #password\n placeholder=\"Current Password\"\n autocomplete=\"current-password\"\n (keyup)=\"checkValidity()\" />\n }\n @if (passwordVerified) {\n <input type=\"text\"\n class=\"form-control\"\n id=\"account-new-email\"\n name=\"newEmail\"\n placeholder=\"New Email\"\n autocomplete=\"email\"\n formControlName=\"email\" />\n }\n </div>\n <div class=\"col-12\">\n @if (toggleEmail) {\n <a\n class=\"btn btn-raised btn-outline-default my-2 me-2\"\n aria-label=\"Navigate to Target\"\n (click)=\"onToggleEmail()\">{{ 'Button.Cancel' | transloco }}</a>\n }\n @if (!passwordVerified) {\n <button class=\"btn btn-raised btn-primary\"\n type=\"submit\"\n [buttonBusy]=\"validatePasswordBusyButton\"\n (click)=\"validatePassword()\"\n [disabled]=\"isCurrentPasswordValid\">\n {{ 'User.Account.Validate' | transloco }}\n </button>\n }\n @if (passwordVerified) {\n <button type=\"submit\"\n class=\"btn btn-raised btn-primary\"\n [buttonBusy]=\"emailBusyButton\"\n >\n {{\n 'User.Account.SendVerification' | transloco\n }}\n </button>\n }\n </div>\n </div>\n }\n </div>\n </div>\n <section id=\"slug\"\n class=\"mb-2 mt-3\">\n <div>\n <span class=\"me-3 pw-label-style\" id=\"account-nickname-label\">{{ 'User.Account.NickName' | transloco }}:</span>\n <span class=\"tooltip-wrap me-3\" [pTooltip]=\"'User.Account.HandleTooltip' | transloco\" [appendTo]=\"'body'\" tooltipPosition=\"top\"><i class=\"far fa-info-circle text-muted\"></i></span>\n <strong>{{ slug }}</strong>\n <div class=\"mt-1\">\n @if (!toggleNickName) {\n <a class=\"btn btn-raised btn-outline-primary me-2\"\n aria-label=\"Navigate to Target\"\n (click)=\"toggleNickName = true\">\n {{ 'User.Account.ChangeNickname' | transloco }}</a>\n }\n @if (toggleNickName) {\n <div class=\"mb-3\">\n <input type=\"text\"\n id=\"account-nickname\"\n name=\"nickname\"\n class=\"form-control slug-input\"\n aria-labelledby=\"account-nickname-label\"\n [(ngModel)]=\"slug\"\n [ngModelOptions]=\"{ standalone: true }\" />\n </div>\n <div>\n <button type=\"button\"\n class=\"btn btn-raised btn-outline-default\"\n (click)=\"toggleNickName = false\">\n {{ 'Button.Cancel' | transloco }}\n </button>\n <button type=\"button\"\n class=\"btn btn-raised btn-primary ms-2\"\n [buttonBusy]=\"slugBusyButton\"\n [disabled]=\"slug?.length < 2\"\n (click)=\"onUpdateSlug()\">\n {{ 'User.Account.UpdateNickname' | transloco }}\n </button>\n </div>\n }\n </div>\n </div>\n </section>\n </form>\n </section>\n </div>\n </div>\n </section>\n </div>\n <div class=\"col-md-6\">\n <section id=\"password-change\"\n class=\"card p-4 h-100\">\n <form [formGroup]=\"passwordForm\"\n (ngSubmit)=\"onPasswordFormSubmit()\">\n <div class=\"row\">\n <div class=\"col-12\">\n <h2>{{ 'User.Account.ChangePassword' | transloco }}</h2>\n </div>\n @if (!user?.has_password) {\n <div class=\"text-danger mx-3 my-2\">\n <div>\n You don't have a password set, click on\n <em>{{ 'User.Account.ChangePassword' | transloco }}</em>.\n </div>\n <div>{{ 'User.Profile.PictureMessage' | transloco }}</div>\n </div>\n }\n @if (user?.has_password) {\n <div class=\"col-12\"\n >\n @if (togglePassword) {\n <div class=\"mb-3\">\n <label for=\"account-current-password\">{{ 'User.Account.CurrentPassword' | transloco }}</label>\n <input type=\"password\"\n id=\"account-current-password\"\n class=\"form-control\"\n formControlName=\"currentPassword\"\n autocomplete=\"current-password\" name=\"input_currentPassword_4\"/>\n @if (\n !passwordForm.get('currentPassword').valid &&\n (passwordForm.get('currentPassword').dirty ||\n passwordForm.get('currentPassword').touched)\n ) {\n <small class=\"form-text text-muted danger\"\n >\n {{ 'User.Account.Required' | transloco }}\n </small>\n }\n </div>\n <div class=\"mb-3\">\n <label for=\"account-new-password\">{{ 'User.Account.NewPassword' | transloco }}</label>\n <input type=\"password\"\n id=\"account-new-password\"\n class=\"form-control\"\n formControlName=\"newPassword\"\n autocomplete=\"new-password\" name=\"input_newPassword_5\"/>\n @if (\n !passwordForm.get('newPassword').valid &&\n (passwordForm.get('newPassword').dirty ||\n passwordForm.get('newPassword').touched)\n ) {\n <small class=\"form-text text-muted danger\"\n >{{ 'User.Account.Validation.StrongPassword' | transloco }}\n </small>\n }\n </div>\n <div class=\"mb-3\">\n <label for=\"account-confirm-password\">{{\n 'User.Account.ConfirmPassword' | transloco\n }}</label>\n <input type=\"password\"\n id=\"account-confirm-password\"\n class=\"form-control\"\n formControlName=\"confirmPassword\"\n autocomplete=\"new-password\" name=\"input_confirmPassword_6\"/>\n @if (\n passwordForm.get('confirmPassword').touched &&\n passwordForm.get('confirmPassword').errors\n ?.MatchPassword\n ) {\n <div class=\"text-danger\"\n >\n {{ 'User.Account.Validation.PasswordsMatch' | transloco }}\n </div>\n }\n </div>\n <div class=\"mb-3\">\n @if (togglePassword) {\n <a class=\"btn btn-raised btn-outline-default\"\n aria-label=\"Navigate to Target\"\n data-bs-target=\"\"\n (click)=\"onTogglePassword()\">\n {{ 'Button.Cancel' | transloco }}</a>\n }\n <button class=\"btn btn-raised btn-primary ms-2\"\n [buttonBusy]=\"passwordBusyButton\"\n [disabled]=\"!passwordForm.valid\">\n {{ 'User.Account.UpdatePassword' | transloco }}\n </button>\n </div>\n }\n <div>\n @if (!togglePassword) {\n <a class=\"btn btn-raised btn-outline-primary\"\n aria-label=\"Navigate to Target\"\n data-bs-target=\"\"\n (click)=\"togglePassword = !togglePassword\">\n {{ 'User.Account.ChangePassword' | transloco }}</a>\n }\n </div>\n </div>\n }\n @if (!user?.has_password) {\n <div class=\"col-12\"\n >\n <a class=\"btn btn-raised btn-primary me-2\"\n aria-label=\"Navigate to Target\"\n data-bs-target=\"\"\n (click)=\"sendMailToResetPassword()\">\n {{ 'User.Account.ChangePassword' | transloco }}</a>\n </div>\n }\n </div>\n </form>\n </section>\n </div>\n @if (user?.api_keys?.api_hits_max > 0) {\n <div class=\"col-12 mt-3\">\n <section id=\"api-credentials\"\n class=\"card p-4 h-auto\">\n <div class=\"row\">\n <div class=\"col-12\">\n <h2>{{ 'User.Subscriptions.APICredentials.Title' | transloco }}</h2>\n <p>\n {{ 'User.Subscriptions.APICredentials.Description' | transloco }}\n </p>\n <!-- pb (not mb): .card .mb-3:last-child is margin-reset in this component's scss -->\n <p class=\"text-muted small mb-0 pb-3\">\n <i class=\"fas fa-info-circle me-1\"></i>\n {{ 'User.Subscriptions.APICredentials.SubscriptionClientIdNote' | transloco }}\n </p>\n </div>\n <div class=\"col-12 col-md-6\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"account-api-token\">{{ 'User.Account.APIUserToken' | transloco }}</label>\n <div class=\"input-group\">\n <input type=\"text\"\n id=\"account-api-token\"\n name=\"api_token\"\n class=\"form-control\"\n [value]=\"showApiToken ? user?.api_keys?.api_user_token || ('User.Subscriptions.APICredentials.NoTokenAvailable' | transloco) : '*************************'\"\n readonly />\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"toggleApiTokenVisibility()\">\n {{ showApiToken ? ('User.Subscriptions.APICredentials.Hide' | transloco) : ('User.Subscriptions.APICredentials.View' | transloco) }}\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-12 col-md-6\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"account-api-client-id\">{{ 'User.Account.APIUserId' | transloco }}</label>\n <div class=\"input-group\">\n <input type=\"text\"\n id=\"account-api-client-id\"\n name=\"api_client_id\"\n class=\"form-control\"\n [value]=\"showApiClientId ? user?.api_keys?.api_user_id || ('User.Subscriptions.APICredentials.NoClientIdAvailable' | transloco) : '*************************'\"\n readonly />\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"toggleApiClientIdVisibility()\">\n {{ showApiClientId ? ('User.Subscriptions.APICredentials.Hide' | transloco) : ('User.Subscriptions.APICredentials.View' | transloco) }}\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-12 mt-3\">\n <div class=\"d-flex align-items-center gap-3\">\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"refreshApiTokens()\"\n [disabled]=\"refreshingTokens\">\n <i class=\"fas fa-sync-alt me-2\" [class.fa-spin]=\"refreshingTokens\"></i>\n {{ refreshingTokens ? ('User.Subscriptions.APICredentials.Refreshing' | transloco) : ('User.Subscriptions.APICredentials.RefreshTokens' | transloco) }}\n </button>\n <div class=\"d-flex align-items-center gap-2\">\n @if (user?.api_keys?.api_hits !== null) {\n <span class=\"text-muted\">{{ 'User.Subscriptions.APICredentials.ApiHits' | transloco }}:</span>\n <span class=\"fw-bold\">{{ user.api_keys.api_hits | number }}</span>\n }\n @if (user?.api_keys?.api_hits_max !== null) {\n <span class=\"text-muted\">{{ 'User.Subscriptions.APICredentials.ApiHitsMax' | transloco }}:</span>\n <span class=\"fw-bold\">{{ user.api_keys.api_hits_max | number }}</span>\n }\n <!-- Show utilization percentage when both values exist -->\n @if (user?.api_keys?.api_hits !== null && user?.api_keys?.api_hits_max !== null && user?.api_keys?.api_hits_max > 0) {\n <span class=\"text-muted ms-2\">(</span>\n <span class=\"fw-bold\" [ngClass]=\"{\n 'text-success': (user.api_keys.api_hits / user.api_keys.api_hits_max) <= 0.8,\n 'text-warning': (user.api_keys.api_hits / user.api_keys.api_hits_max) > 0.8 && (user.api_keys.api_hits / user.api_keys.api_hits_max) <= 0.9,\n 'text-danger': (user.api_keys.api_hits / user.api_keys.api_hits_max) > 0.9\n }\">\n {{ (user.api_keys.api_hits / user.api_keys.api_hits_max * 100) | number:'1.0-0' }}% consumed\n </span>\n <span class=\"text-muted\">)</span>\n }\n </div>\n </div>\n </div>\n </div>\n </section>\n </div>\n }\n</div>\n<ng-template #content\n let-modal>\n <div class=\"card m-0\">\n <div class=\"card-content\">\n <div class=\"card-title\">\n <h3 class=\"modal-title\">{{ 'User.Profile.ProfilePicture' | transloco }}</h3>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n </button>\n </div>\n <div class=\"card-header\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile\n aspectRatio=\"auto\"\n (imageSelectionEvent)=\"onImageSelection($event)\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n </div>\n </div>\n</ng-template>\n", styles: [".card .mb-2:last-child,.card .mb-3:last-child{margin-bottom:0!important}.overlay{left:50%;opacity:0;position:absolute;text-align:center;top:50%;transform:translate(-50%,-50%);transition:.5s ease}.image-container{position:relative}.image-container:hover .image{opacity:.3}.image-container:hover .overlay{opacity:0}.overlay-text{background:#f0efef80;border-radius:50%;color:#000;font-size:16px;height:150px;line-height:150px;text-align:center;vertical-align:middle;width:150px}@media screen and (max-width:767px){.card-body{padding:20px!important}}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i6$1.NgxGpAutocompleteDirective, selector: "[ngx-gp-autocomplete]", inputs: ["options"], outputs: ["onAddressChange"], exportAs: ["ngx-places"] }, { kind: "component", type: i6$2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i9.ProfileImageCropperComponent, selector: "pw-image-cropper", inputs: ["aspectRatio", "dynamicData"], outputs: ["imageSelectionEvent", "closeEvent", "fileChangeEvent"] }, { kind: "component", type: i5.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "controlId", "useAriaLabelledbyOnly", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "directive", type: i11.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "directive", type: i1$1.NgbInputDatepicker, selector: "input[ngbDatepicker]", inputs: ["autoClose", "contentTemplate", "datepickerClass", "dayTemplate", "dayTemplateData", "displayMonths", "firstDayOfWeek", "footerTemplate", "markDisabled", "minDate", "maxDate", "navigation", "outsideDays", "placement", "popperOptions", "restoreFocus", "showWeekNumbers", "startDate", "container", "positionTarget", "weekdays", "disabled"], outputs: ["dateSelect", "navigate", "closed"], exportAs: ["ngbDatepicker"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.DecimalPipe, name: "number" }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
479
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: AccountDetailsComponent, isStandalone: false, selector: "pw-account-details", viewQueries: [{ propertyName: "placesRef", first: true, predicate: ["ngxPlaces"], descendants: true }, { propertyName: "passwordRef", first: true, predicate: ["password"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"w-100 text-center\">\n @if (!isLoaded) {\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n }\n</div>\n<div class=\"row gx-3 mb-3\">\n <div class=\"col-md-4\">\n <section class=\"card p-4 h-100 d-flex flex-column\">\n <h2>{{ 'User.Profile.Avatar' | transloco }}</h2>\n <div class=\"text-center d-flex flex-column justify-content-center flex-grow-1 mt-1\">\n <div class=\"image-container\">\n <img [src]=\"image\"\n width=\"150\"\n height=\"150\"\n class=\"image rounded-circle\"\n alt=\"User Male\"\n (error)=\"handleImageError($event, 'assets/img/icons/male.png')\" />\n <div class=\"overlay\"\n (keydown.enter)=\"openModal(content)\"\n (click)=\"openModal(content)\">\n <div class=\"overlay-text\">{{ 'User.Profile.Change' | transloco }}</div>\n </div>\n </div>\n <h4 class=\"mt-2\">{{ user?.first_name }} {{ user?.last_name }}</h4>\n <a aria-label=\"Navigate to Target\"\n class=\"d-inline-block mb-2\"\n (click)=\"openModal(content)\">\n {{ 'User.Profile.EditAvatar' | transloco }}</a>\n </div>\n </section>\n </div>\n <div class=\"col-md-8\">\n <section id=\"user-profile\"\n class=\"card p-4 overflow-visible h-100\">\n <form [formGroup]=\"profileForm\"\n (ngSubmit)=\"onProfileFormSubmit()\">\n <h2>{{ 'User.Profile.UserProfile' | transloco }}</h2>\n <div class=\"row mt-3\">\n <div class=\"col-sm-12 col-md-6 col-lg-6\">\n <pw-input-container label=\"First Name\"\n name=\"first_name\"\n controlId=\"account-first_name\"\n errorMsg=\"Please enter first Name\">\n <input type=\"text\"\n id=\"account-first_name\"\n class=\"form-control\"\n formControlName=\"first_name\"\n autocomplete=\"given-name\" name=\"input_first_name_9\"/>\n </pw-input-container>\n <pw-input-container label=\"Preferred name\"\n name=\"preferred_name\"\n controlId=\"account-preferred_name\"\n errorMsg=\"Please enter preferred Name\">\n <input type=\"text\"\n id=\"account-preferred_name\"\n class=\"form-control\"\n formControlName=\"preferred_name\"\n autocomplete=\"username\" name=\"input_preferred_name_10\"/>\n </pw-input-container>\n @if (countries$ | async; as countries) {\n <pw-input-container label=\"Country\"\n name=\"country\"\n controlId=\"account-country\"\n [useAriaLabelledbyOnly]=\"true\"\n errorMsg=\"Please select a country\">\n <p-select\n [attr.aria-labelledby]=\"'account-country-label'\"\n [options]=\"countries\"\n optionLabel=\"name\"\n optionValue=\"code\"\n formControlName=\"country\"\n (onChange)=\"getRegion($event.value)\"\n placeholder=\"{{ 'User.Profile.SelectCountry' | transloco }}\">\n </p-select>\n </pw-input-container>\n }\n <pw-input-container label=\"Province\"\n name=\"province\"\n controlId=\"account-province\"\n errorMsg=\"Please enter province\">\n <input type=\"text\"\n id=\"account-province\"\n class=\"form-control\"\n formControlName=\"province\"\n autocomplete=\"postal-code\" name=\"input_province_11\"/>\n </pw-input-container>\n <pw-input-container label=\"Website Url\"\n name=\"website_url\"\n controlId=\"account-website_url\"\n errorMsg=\"Please enter Website\">\n <input type=\"text\"\n id=\"account-website_url\"\n class=\"form-control\"\n formControlName=\"website_url\"\n autocomplete=\"url\" name=\"input_website_url_12\"/>\n </pw-input-container>\n </div>\n <div class=\"col-sm-12 col-md-6 col-lg-6\">\n <pw-input-container label=\"Last Name\"\n name=\"last_name\"\n controlId=\"account-last_name\"\n errorMsg=\"Please enter last Name\">\n <input type=\"text\"\n id=\"account-last_name\"\n class=\"form-control\"\n formControlName=\"last_name\"\n autocomplete=\"family-name\" name=\"input_last_name_13\"/>\n </pw-input-container>\n <pw-input-container label=\"Date of Birth\"\n name=\"dob\"\n controlId=\"account-dob\"\n errorMsg=\"Please enter date of birth\">\n <div class=\"input-group\">\n <input class=\"form-control\"\n id=\"account-dob\"\n name=\"dob\"\n placeholder=\"dd-mmm-yyyy\"\n formControlName=\"dob\"\n ngbDatepicker\n #d=\"ngbDatepicker\"\n [minDate]=\"{ day: 1, month: 1, year: 1950 }\"\n [maxDate]=\"{ day: 31, month: 12, year: 2018 }\" />\n <button class=\"btn btn-primary\"\n type=\"button\"\n id=\"account-dob-trigger\"\n aria-label=\"Open date picker for date of birth\"\n (click)=\"d.toggle()\">\n <i class=\"fa fa-calendar\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </pw-input-container>\n <pw-input-container label=\"State\"\n name=\"state\"\n controlId=\"account-state\"\n [useAriaLabelledbyOnly]=\"true\"\n errorMsg=\"Please select a state\">\n <p-select\n [attr.aria-labelledby]=\"'account-state-label'\"\n [options]=\"states\"\n [(ngModel)]=\"selectedState\"\n optionLabel=\"name\"\n optionValue=\"code\"\n formControlName=\"state\"\n [placeholder]=\"'User.Profile.SelectState' | transloco\">\n </p-select>\n </pw-input-container>\n <pw-input-container label=\"Location\"\n name=\"location\"\n controlId=\"account-location\"\n [useAriaLabelledbyOnly]=\"true\">\n <input ngx-gp-autocomplete\n id=\"account-location\"\n name=\"location\"\n class=\"form-control\"\n [attr.aria-labelledby]=\"'account-location-label'\"\n #places=\"ngx-places\"\n formControlName=\"location\"\n (onAddressChange)=\"handleAddressChange($event)\" />\n </pw-input-container>\n <pw-input-container label=\"Phone Number\"\n name=\"phone_number\"\n controlId=\"account-phone_number\"\n errorMsg=\"Please enter phone number\">\n <input type=\"text\"\n id=\"account-phone_number\"\n class=\"form-control\"\n formControlName=\"phone_number\"\n autocomplete=\"tel\" name=\"input_phone_number_16\"/>\n </pw-input-container>\n </div>\n <div class=\"col-12 text-end\">\n <div class=\"mb-3\">\n <button class=\"btn btn-raised btn-primary\" [buttonBusy]=\"profileBusyButton\">\n {{ 'Button.Save' | transloco }}\n </button>\n </div>\n </div>\n </div>\n </form>\n </section>\n </div>\n</div>\n<div class=\"row gx-3 mb-3\">\n <div class=\"col-md-6\">\n <section id=\"email-section\"\n class=\"card p-4 h-100\">\n <div class=\"row\">\n <div class=\"col-12\">\n <h2>{{ 'User.Account.RegisteredEmail' | transloco }}</h2>\n <section id=\"email-form\">\n <form [formGroup]=\"emailForm\"\n (ngSubmit)=\"onEmailFormSubmit()\">\n <!-- Email Address -->\n <div class=\"mt-0\">\n <span id=\"account-primary-email-label\" class=\"me-3 pw-label-style\">{{ 'User.Account.PrimaryEmail' | transloco }}:\n </span>\n <strong>{{ validatedEmail }}</strong>\n <div class=\"mt-1\">\n @if (!toggleEmail) {\n <a class=\"btn btn-raised btn-outline-primary\"\n aria-label=\"Navigate to Target\"\n (click)=\"shouldUserChangeEmail()\">\n {{ 'User.Account.ChangeEmail' | transloco }}</a>\n }\n @if (toggleEmail) {\n <div class=\"row\">\n <div class=\"clearfix\"></div>\n <div class=\"col-12 mb-3\">\n @if (!passwordVerified) {\n <input type=\"password\"\n class=\"form-control\"\n id=\"account-email-current-password\"\n name=\"currentPassword\"\n #password\n placeholder=\"Current Password\"\n autocomplete=\"current-password\"\n (keyup)=\"checkValidity()\" />\n }\n @if (passwordVerified) {\n <input type=\"text\"\n class=\"form-control\"\n id=\"account-new-email\"\n name=\"newEmail\"\n placeholder=\"New Email\"\n autocomplete=\"email\"\n formControlName=\"email\" />\n }\n </div>\n <div class=\"col-12\">\n @if (toggleEmail) {\n <a\n class=\"btn btn-raised btn-outline-default my-2 me-2\"\n aria-label=\"Navigate to Target\"\n (click)=\"onToggleEmail()\">{{ 'Button.Cancel' | transloco }}</a>\n }\n @if (!passwordVerified) {\n <button class=\"btn btn-raised btn-primary\"\n type=\"submit\"\n [buttonBusy]=\"validatePasswordBusyButton\"\n (click)=\"validatePassword()\"\n [disabled]=\"isCurrentPasswordValid\">\n {{ 'User.Account.Validate' | transloco }}\n </button>\n }\n @if (passwordVerified) {\n <button type=\"submit\"\n class=\"btn btn-raised btn-primary\"\n [buttonBusy]=\"emailBusyButton\"\n >\n {{\n 'User.Account.SendVerification' | transloco\n }}\n </button>\n }\n </div>\n </div>\n }\n </div>\n </div>\n <section id=\"slug\"\n class=\"mb-2 mt-3\">\n <div>\n <span class=\"me-3 pw-label-style\" id=\"account-nickname-label\">{{ 'User.Account.NickName' | transloco }}:</span>\n <span class=\"tooltip-wrap me-3\" [pTooltip]=\"'User.Account.HandleTooltip' | transloco\" [appendTo]=\"'body'\" tooltipPosition=\"top\"><i class=\"far fa-info-circle text-muted\"></i></span>\n <strong>{{ slug }}</strong>\n <div class=\"mt-1\">\n @if (!toggleNickName) {\n <a class=\"btn btn-raised btn-outline-primary me-2\"\n aria-label=\"Navigate to Target\"\n (click)=\"toggleNickName = true\">\n {{ 'User.Account.ChangeNickname' | transloco }}</a>\n }\n @if (toggleNickName) {\n <div class=\"mb-3\">\n <input type=\"text\"\n id=\"account-nickname\"\n name=\"nickname\"\n class=\"form-control slug-input\"\n aria-labelledby=\"account-nickname-label\"\n [(ngModel)]=\"slug\"\n [ngModelOptions]=\"{ standalone: true }\" />\n </div>\n <div>\n <button type=\"button\"\n class=\"btn btn-raised btn-outline-default\"\n (click)=\"toggleNickName = false\">\n {{ 'Button.Cancel' | transloco }}\n </button>\n <button type=\"button\"\n class=\"btn btn-raised btn-primary ms-2\"\n [buttonBusy]=\"slugBusyButton\"\n [disabled]=\"slug?.length < 2\"\n (click)=\"onUpdateSlug()\">\n {{ 'User.Account.UpdateNickname' | transloco }}\n </button>\n </div>\n }\n </div>\n </div>\n </section>\n </form>\n </section>\n </div>\n </div>\n </section>\n </div>\n <div class=\"col-md-6\">\n <section id=\"password-change\"\n class=\"card p-4 h-100\">\n <form [formGroup]=\"passwordForm\"\n (ngSubmit)=\"onPasswordFormSubmit()\">\n <div class=\"row\">\n <div class=\"col-12\">\n <h2>{{ 'User.Account.ChangePassword' | transloco }}</h2>\n </div>\n @if (!user?.has_password) {\n <div class=\"text-danger mx-3 my-2\">\n <div>\n You don't have a password set, click on\n <em>{{ 'User.Account.ChangePassword' | transloco }}</em>.\n </div>\n <div>{{ 'User.Profile.PictureMessage' | transloco }}</div>\n </div>\n }\n @if (user?.has_password) {\n <div class=\"col-12\"\n >\n @if (togglePassword) {\n <div class=\"mb-3\">\n <label for=\"account-current-password\">{{ 'User.Account.CurrentPassword' | transloco }}</label>\n <input type=\"password\"\n id=\"account-current-password\"\n class=\"form-control\"\n formControlName=\"currentPassword\"\n autocomplete=\"current-password\" name=\"input_currentPassword_4\"/>\n @if (\n !passwordForm.get('currentPassword').valid &&\n (passwordForm.get('currentPassword').dirty ||\n passwordForm.get('currentPassword').touched)\n ) {\n <small class=\"form-text text-muted danger\"\n >\n {{ 'User.Account.Required' | transloco }}\n </small>\n }\n </div>\n <div class=\"mb-3\">\n <label for=\"account-new-password\">{{ 'User.Account.NewPassword' | transloco }}</label>\n <input type=\"password\"\n id=\"account-new-password\"\n class=\"form-control\"\n formControlName=\"newPassword\"\n autocomplete=\"new-password\" name=\"input_newPassword_5\"/>\n @if (\n !passwordForm.get('newPassword').valid &&\n (passwordForm.get('newPassword').dirty ||\n passwordForm.get('newPassword').touched)\n ) {\n <small class=\"form-text text-muted danger\"\n >{{ 'User.Account.Validation.StrongPassword' | transloco }}\n </small>\n }\n </div>\n <div class=\"mb-3\">\n <label for=\"account-confirm-password\">{{\n 'User.Account.ConfirmPassword' | transloco\n }}</label>\n <input type=\"password\"\n id=\"account-confirm-password\"\n class=\"form-control\"\n formControlName=\"confirmPassword\"\n autocomplete=\"new-password\" name=\"input_confirmPassword_6\"/>\n @if (\n passwordForm.get('confirmPassword').touched &&\n passwordForm.get('confirmPassword').errors\n ?.MatchPassword\n ) {\n <div class=\"text-danger\"\n >\n {{ 'User.Account.Validation.PasswordsMatch' | transloco }}\n </div>\n }\n </div>\n <div class=\"mb-3\">\n @if (togglePassword) {\n <a class=\"btn btn-raised btn-outline-default\"\n aria-label=\"Navigate to Target\"\n data-bs-target=\"\"\n (click)=\"onTogglePassword()\">\n {{ 'Button.Cancel' | transloco }}</a>\n }\n <button class=\"btn btn-raised btn-primary ms-2\"\n [buttonBusy]=\"passwordBusyButton\"\n [disabled]=\"!passwordForm.valid\">\n {{ 'User.Account.UpdatePassword' | transloco }}\n </button>\n </div>\n }\n <div>\n @if (!togglePassword) {\n <a class=\"btn btn-raised btn-outline-primary\"\n aria-label=\"Navigate to Target\"\n data-bs-target=\"\"\n (click)=\"togglePassword = !togglePassword\">\n {{ 'User.Account.ChangePassword' | transloco }}</a>\n }\n </div>\n </div>\n }\n @if (!user?.has_password) {\n <div class=\"col-12\"\n >\n <a class=\"btn btn-raised btn-primary me-2\"\n aria-label=\"Navigate to Target\"\n data-bs-target=\"\"\n (click)=\"sendMailToResetPassword()\">\n {{ 'User.Account.ChangePassword' | transloco }}</a>\n </div>\n }\n </div>\n </form>\n </section>\n </div>\n @if (user?.api_keys?.api_hits_max > 0) {\n <div class=\"col-12 mt-3\">\n <section id=\"api-credentials\"\n class=\"card p-4 h-auto\">\n <div class=\"row\">\n <div class=\"col-12\">\n <h2>{{ 'User.Subscriptions.APICredentials.Title' | transloco }}</h2>\n <p>\n {{ 'User.Subscriptions.APICredentials.Description' | transloco }}\n </p>\n <!-- pb (not mb): .card .mb-3:last-child is margin-reset in this component's scss -->\n <p class=\"text-muted small mb-0 pb-3\">\n <i class=\"fas fa-info-circle me-1\"></i>\n {{ 'User.Subscriptions.APICredentials.SubscriptionClientIdNote' | transloco }}\n </p>\n </div>\n <div class=\"col-12 col-md-6\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"account-api-token\">{{ 'User.Account.APIUserToken' | transloco }}</label>\n <div class=\"input-group\">\n <input type=\"text\"\n id=\"account-api-token\"\n name=\"api_token\"\n class=\"form-control\"\n [value]=\"showApiToken ? user?.api_keys?.api_user_token || ('User.Subscriptions.APICredentials.NoTokenAvailable' | transloco) : '*************************'\"\n readonly />\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"toggleApiTokenVisibility()\">\n {{ showApiToken ? ('User.Subscriptions.APICredentials.Hide' | transloco) : ('User.Subscriptions.APICredentials.View' | transloco) }}\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-12 col-md-6\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"account-api-client-id\">{{ 'User.Account.APIUserId' | transloco }}</label>\n <div class=\"input-group\">\n <input type=\"text\"\n id=\"account-api-client-id\"\n name=\"api_client_id\"\n class=\"form-control\"\n [value]=\"showApiClientId ? user?.api_keys?.api_user_id || ('User.Subscriptions.APICredentials.NoClientIdAvailable' | transloco) : '*************************'\"\n readonly />\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"toggleApiClientIdVisibility()\">\n {{ showApiClientId ? ('User.Subscriptions.APICredentials.Hide' | transloco) : ('User.Subscriptions.APICredentials.View' | transloco) }}\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-12 mt-3\">\n <div class=\"d-flex align-items-center gap-3\">\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"refreshApiTokens()\"\n [disabled]=\"refreshingTokens\">\n <i class=\"fas fa-sync-alt me-2\" [class.fa-spin]=\"refreshingTokens\"></i>\n {{ refreshingTokens ? ('User.Subscriptions.APICredentials.Refreshing' | transloco) : ('User.Subscriptions.APICredentials.RefreshTokens' | transloco) }}\n </button>\n <div class=\"d-flex align-items-center gap-2\">\n @if (user?.api_keys?.api_hits !== null) {\n <span class=\"text-muted\">{{ 'User.Subscriptions.APICredentials.ApiHits' | transloco }}:</span>\n <span class=\"fw-bold\">{{ user.api_keys.api_hits | number }}</span>\n }\n @if (user?.api_keys?.api_hits_max !== null) {\n <span class=\"text-muted\">{{ 'User.Subscriptions.APICredentials.ApiHitsMax' | transloco }}:</span>\n <span class=\"fw-bold\">{{ user.api_keys.api_hits_max | number }}</span>\n }\n <!-- Show utilization percentage when both values exist -->\n @if (user?.api_keys?.api_hits !== null && user?.api_keys?.api_hits_max !== null && user?.api_keys?.api_hits_max > 0) {\n <span class=\"text-muted ms-2\">(</span>\n <span class=\"fw-bold\" [ngClass]=\"{\n 'text-success-muted': (user.api_keys.api_hits / user.api_keys.api_hits_max) <= 0.8,\n 'text-warning': (user.api_keys.api_hits / user.api_keys.api_hits_max) > 0.8 && (user.api_keys.api_hits / user.api_keys.api_hits_max) <= 0.9,\n 'text-danger': (user.api_keys.api_hits / user.api_keys.api_hits_max) > 0.9\n }\">\n {{ (user.api_keys.api_hits / user.api_keys.api_hits_max * 100) | number:'1.0-0' }}% consumed\n </span>\n <span class=\"text-muted\">)</span>\n }\n </div>\n </div>\n </div>\n </div>\n </section>\n </div>\n }\n</div>\n<ng-template #content\n let-modal>\n <div class=\"card m-0\">\n <div class=\"card-content\">\n <div class=\"card-title\">\n <h3 class=\"modal-title\">{{ 'User.Profile.ProfilePicture' | transloco }}</h3>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n </button>\n </div>\n <div class=\"card-header\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile\n aspectRatio=\"auto\"\n (imageSelectionEvent)=\"onImageSelection($event)\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n </div>\n </div>\n</ng-template>\n", styles: [".card .mb-2:last-child,.card .mb-3:last-child{margin-bottom:0!important}.overlay{left:50%;opacity:0;position:absolute;text-align:center;top:50%;transform:translate(-50%,-50%);transition:.5s ease}.image-container{position:relative}.image-container:hover .image{opacity:.3}.image-container:hover .overlay{opacity:0}.overlay-text{background:#f0efef80;border-radius:50%;color:#000;font-size:16px;height:150px;line-height:150px;text-align:center;vertical-align:middle;width:150px}@media screen and (max-width:767px){.card-body{padding:20px!important}}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i6.NgxGpAutocompleteDirective, selector: "[ngx-gp-autocomplete]", inputs: ["options"], outputs: ["onAddressChange"], exportAs: ["ngx-places"] }, { kind: "component", type: i7$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i9.ProfileImageCropperComponent, selector: "pw-image-cropper", inputs: ["aspectRatio", "dynamicData"], outputs: ["imageSelectionEvent", "closeEvent", "fileChangeEvent"] }, { kind: "component", type: i7.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "controlId", "useAriaLabelledbyOnly", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "directive", type: i11.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "directive", type: i1$1.NgbInputDatepicker, selector: "input[ngbDatepicker]", inputs: ["autoClose", "contentTemplate", "datepickerClass", "dayTemplate", "dayTemplateData", "displayMonths", "firstDayOfWeek", "footerTemplate", "markDisabled", "minDate", "maxDate", "navigation", "outsideDays", "placement", "popperOptions", "restoreFocus", "showWeekNumbers", "startDate", "container", "positionTarget", "weekdays", "disabled"], outputs: ["dateSelect", "navigate", "closed"], exportAs: ["ngbDatepicker"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.DecimalPipe, name: "number" }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
478
480
|
}
|
|
479
481
|
__decorate([
|
|
480
482
|
ValidateForm('profileForm'),
|
|
@@ -484,7 +486,7 @@ __decorate([
|
|
|
484
486
|
], AccountDetailsComponent.prototype, "onProfileFormSubmit", null);
|
|
485
487
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: AccountDetailsComponent, decorators: [{
|
|
486
488
|
type: Component,
|
|
487
|
-
args: [{ selector: 'pw-account-details', standalone: false, template: "<div class=\"w-100 text-center\">\n @if (!isLoaded) {\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n }\n</div>\n<div class=\"row gx-3 mb-3\">\n <div class=\"col-md-4\">\n <section class=\"card p-4 h-100 d-flex flex-column\">\n <h2>{{ 'User.Profile.Avatar' | transloco }}</h2>\n <div class=\"text-center d-flex flex-column justify-content-center flex-grow-1 mt-1\">\n <div class=\"image-container\">\n <img [src]=\"image\"\n width=\"150\"\n height=\"150\"\n class=\"image rounded-circle\"\n alt=\"User Male\"\n (error)=\"handleImageError($event, 'assets/img/icons/male.png')\" />\n <div class=\"overlay\"\n (keydown.enter)=\"openModal(content)\"\n (click)=\"openModal(content)\">\n <div class=\"overlay-text\">{{ 'User.Profile.Change' | transloco }}</div>\n </div>\n </div>\n <h4 class=\"mt-2\">{{ user?.first_name }} {{ user?.last_name }}</h4>\n <a aria-label=\"Navigate to Target\"\n class=\"d-inline-block mb-2\"\n (click)=\"openModal(content)\">\n {{ 'User.Profile.EditAvatar' | transloco }}</a>\n </div>\n </section>\n </div>\n <div class=\"col-md-8\">\n <section id=\"user-profile\"\n class=\"card p-4 overflow-visible h-100\">\n <form [formGroup]=\"profileForm\"\n (ngSubmit)=\"onProfileFormSubmit()\">\n <h2>{{ 'User.Profile.UserProfile' | transloco }}</h2>\n <div class=\"row mt-3\">\n <div class=\"col-sm-12 col-md-6 col-lg-6\">\n <pw-input-container label=\"First Name\"\n name=\"first_name\"\n controlId=\"account-first_name\"\n errorMsg=\"Please enter first Name\">\n <input type=\"text\"\n id=\"account-first_name\"\n class=\"form-control\"\n formControlName=\"first_name\"\n autocomplete=\"given-name\" name=\"input_first_name_9\"/>\n </pw-input-container>\n <pw-input-container label=\"Preferred name\"\n name=\"preferred_name\"\n controlId=\"account-preferred_name\"\n errorMsg=\"Please enter preferred Name\">\n <input type=\"text\"\n id=\"account-preferred_name\"\n class=\"form-control\"\n formControlName=\"preferred_name\"\n autocomplete=\"username\" name=\"input_preferred_name_10\"/>\n </pw-input-container>\n @if (countries$ | async; as countries) {\n <pw-input-container label=\"Country\"\n name=\"country\"\n controlId=\"account-country\"\n [useAriaLabelledbyOnly]=\"true\"\n errorMsg=\"Please select a country\">\n <p-select\n [attr.aria-labelledby]=\"'account-country-label'\"\n [options]=\"countries\"\n optionLabel=\"name\"\n optionValue=\"code\"\n formControlName=\"country\"\n (onChange)=\"getRegion($event.value)\"\n placeholder=\"{{ 'User.Profile.SelectCountry' | transloco }}\">\n </p-select>\n </pw-input-container>\n }\n <pw-input-container label=\"Province\"\n name=\"province\"\n controlId=\"account-province\"\n errorMsg=\"Please enter province\">\n <input type=\"text\"\n id=\"account-province\"\n class=\"form-control\"\n formControlName=\"province\"\n autocomplete=\"postal-code\" name=\"input_province_11\"/>\n </pw-input-container>\n <pw-input-container label=\"Website Url\"\n name=\"website_url\"\n controlId=\"account-website_url\"\n errorMsg=\"Please enter Website\">\n <input type=\"text\"\n id=\"account-website_url\"\n class=\"form-control\"\n formControlName=\"website_url\"\n autocomplete=\"url\" name=\"input_website_url_12\"/>\n </pw-input-container>\n </div>\n <div class=\"col-sm-12 col-md-6 col-lg-6\">\n <pw-input-container label=\"Last Name\"\n name=\"last_name\"\n controlId=\"account-last_name\"\n errorMsg=\"Please enter last Name\">\n <input type=\"text\"\n id=\"account-last_name\"\n class=\"form-control\"\n formControlName=\"last_name\"\n autocomplete=\"family-name\" name=\"input_last_name_13\"/>\n </pw-input-container>\n <pw-input-container label=\"Date of Birth\"\n name=\"dob\"\n controlId=\"account-dob\"\n errorMsg=\"Please enter date of birth\">\n <div class=\"input-group\">\n <input class=\"form-control\"\n id=\"account-dob\"\n name=\"dob\"\n placeholder=\"dd-mmm-yyyy\"\n formControlName=\"dob\"\n ngbDatepicker\n #d=\"ngbDatepicker\"\n [minDate]=\"{ day: 1, month: 1, year: 1950 }\"\n [maxDate]=\"{ day: 31, month: 12, year: 2018 }\" />\n <button class=\"btn btn-primary\"\n type=\"button\"\n id=\"account-dob-trigger\"\n aria-label=\"Open date picker for date of birth\"\n (click)=\"d.toggle()\">\n <i class=\"fa fa-calendar\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </pw-input-container>\n <pw-input-container label=\"State\"\n name=\"state\"\n controlId=\"account-state\"\n [useAriaLabelledbyOnly]=\"true\"\n errorMsg=\"Please select a state\">\n <p-select\n [attr.aria-labelledby]=\"'account-state-label'\"\n [options]=\"states\"\n [(ngModel)]=\"selectedState\"\n optionLabel=\"name\"\n optionValue=\"code\"\n formControlName=\"state\"\n [placeholder]=\"'User.Profile.SelectState' | transloco\">\n </p-select>\n </pw-input-container>\n <pw-input-container label=\"Location\"\n name=\"location\"\n controlId=\"account-location\"\n [useAriaLabelledbyOnly]=\"true\">\n <input ngx-gp-autocomplete\n id=\"account-location\"\n name=\"location\"\n class=\"form-control\"\n [attr.aria-labelledby]=\"'account-location-label'\"\n #places=\"ngx-places\"\n formControlName=\"location\"\n (onAddressChange)=\"handleAddressChange($event)\" />\n </pw-input-container>\n <pw-input-container label=\"Phone Number\"\n name=\"phone_number\"\n controlId=\"account-phone_number\"\n errorMsg=\"Please enter phone number\">\n <input type=\"text\"\n id=\"account-phone_number\"\n class=\"form-control\"\n formControlName=\"phone_number\"\n autocomplete=\"tel\" name=\"input_phone_number_16\"/>\n </pw-input-container>\n </div>\n <div class=\"col-12 text-end\">\n <div class=\"mb-3\">\n <button class=\"btn btn-raised btn-primary\" [buttonBusy]=\"profileBusyButton\">\n {{ 'Button.Save' | transloco }}\n </button>\n </div>\n </div>\n </div>\n </form>\n </section>\n </div>\n</div>\n<div class=\"row gx-3 mb-3\">\n <div class=\"col-md-6\">\n <section id=\"email-section\"\n class=\"card p-4 h-100\">\n <div class=\"row\">\n <div class=\"col-12\">\n <h2>{{ 'User.Account.RegisteredEmail' | transloco }}</h2>\n <section id=\"email-form\">\n <form [formGroup]=\"emailForm\"\n (ngSubmit)=\"onEmailFormSubmit()\">\n <!-- Email Address -->\n <div class=\"mt-0\">\n <span id=\"account-primary-email-label\" class=\"me-3 pw-label-style\">{{ 'User.Account.PrimaryEmail' | transloco }}:\n </span>\n <strong>{{ validatedEmail }}</strong>\n <div class=\"mt-1\">\n @if (!toggleEmail) {\n <a class=\"btn btn-raised btn-outline-primary\"\n aria-label=\"Navigate to Target\"\n (click)=\"shouldUserChangeEmail()\">\n {{ 'User.Account.ChangeEmail' | transloco }}</a>\n }\n @if (toggleEmail) {\n <div class=\"row\">\n <div class=\"clearfix\"></div>\n <div class=\"col-12 mb-3\">\n @if (!passwordVerified) {\n <input type=\"password\"\n class=\"form-control\"\n id=\"account-email-current-password\"\n name=\"currentPassword\"\n #password\n placeholder=\"Current Password\"\n autocomplete=\"current-password\"\n (keyup)=\"checkValidity()\" />\n }\n @if (passwordVerified) {\n <input type=\"text\"\n class=\"form-control\"\n id=\"account-new-email\"\n name=\"newEmail\"\n placeholder=\"New Email\"\n autocomplete=\"email\"\n formControlName=\"email\" />\n }\n </div>\n <div class=\"col-12\">\n @if (toggleEmail) {\n <a\n class=\"btn btn-raised btn-outline-default my-2 me-2\"\n aria-label=\"Navigate to Target\"\n (click)=\"onToggleEmail()\">{{ 'Button.Cancel' | transloco }}</a>\n }\n @if (!passwordVerified) {\n <button class=\"btn btn-raised btn-primary\"\n type=\"submit\"\n [buttonBusy]=\"validatePasswordBusyButton\"\n (click)=\"validatePassword()\"\n [disabled]=\"isCurrentPasswordValid\">\n {{ 'User.Account.Validate' | transloco }}\n </button>\n }\n @if (passwordVerified) {\n <button type=\"submit\"\n class=\"btn btn-raised btn-primary\"\n [buttonBusy]=\"emailBusyButton\"\n >\n {{\n 'User.Account.SendVerification' | transloco\n }}\n </button>\n }\n </div>\n </div>\n }\n </div>\n </div>\n <section id=\"slug\"\n class=\"mb-2 mt-3\">\n <div>\n <span class=\"me-3 pw-label-style\" id=\"account-nickname-label\">{{ 'User.Account.NickName' | transloco }}:</span>\n <span class=\"tooltip-wrap me-3\" [pTooltip]=\"'User.Account.HandleTooltip' | transloco\" [appendTo]=\"'body'\" tooltipPosition=\"top\"><i class=\"far fa-info-circle text-muted\"></i></span>\n <strong>{{ slug }}</strong>\n <div class=\"mt-1\">\n @if (!toggleNickName) {\n <a class=\"btn btn-raised btn-outline-primary me-2\"\n aria-label=\"Navigate to Target\"\n (click)=\"toggleNickName = true\">\n {{ 'User.Account.ChangeNickname' | transloco }}</a>\n }\n @if (toggleNickName) {\n <div class=\"mb-3\">\n <input type=\"text\"\n id=\"account-nickname\"\n name=\"nickname\"\n class=\"form-control slug-input\"\n aria-labelledby=\"account-nickname-label\"\n [(ngModel)]=\"slug\"\n [ngModelOptions]=\"{ standalone: true }\" />\n </div>\n <div>\n <button type=\"button\"\n class=\"btn btn-raised btn-outline-default\"\n (click)=\"toggleNickName = false\">\n {{ 'Button.Cancel' | transloco }}\n </button>\n <button type=\"button\"\n class=\"btn btn-raised btn-primary ms-2\"\n [buttonBusy]=\"slugBusyButton\"\n [disabled]=\"slug?.length < 2\"\n (click)=\"onUpdateSlug()\">\n {{ 'User.Account.UpdateNickname' | transloco }}\n </button>\n </div>\n }\n </div>\n </div>\n </section>\n </form>\n </section>\n </div>\n </div>\n </section>\n </div>\n <div class=\"col-md-6\">\n <section id=\"password-change\"\n class=\"card p-4 h-100\">\n <form [formGroup]=\"passwordForm\"\n (ngSubmit)=\"onPasswordFormSubmit()\">\n <div class=\"row\">\n <div class=\"col-12\">\n <h2>{{ 'User.Account.ChangePassword' | transloco }}</h2>\n </div>\n @if (!user?.has_password) {\n <div class=\"text-danger mx-3 my-2\">\n <div>\n You don't have a password set, click on\n <em>{{ 'User.Account.ChangePassword' | transloco }}</em>.\n </div>\n <div>{{ 'User.Profile.PictureMessage' | transloco }}</div>\n </div>\n }\n @if (user?.has_password) {\n <div class=\"col-12\"\n >\n @if (togglePassword) {\n <div class=\"mb-3\">\n <label for=\"account-current-password\">{{ 'User.Account.CurrentPassword' | transloco }}</label>\n <input type=\"password\"\n id=\"account-current-password\"\n class=\"form-control\"\n formControlName=\"currentPassword\"\n autocomplete=\"current-password\" name=\"input_currentPassword_4\"/>\n @if (\n !passwordForm.get('currentPassword').valid &&\n (passwordForm.get('currentPassword').dirty ||\n passwordForm.get('currentPassword').touched)\n ) {\n <small class=\"form-text text-muted danger\"\n >\n {{ 'User.Account.Required' | transloco }}\n </small>\n }\n </div>\n <div class=\"mb-3\">\n <label for=\"account-new-password\">{{ 'User.Account.NewPassword' | transloco }}</label>\n <input type=\"password\"\n id=\"account-new-password\"\n class=\"form-control\"\n formControlName=\"newPassword\"\n autocomplete=\"new-password\" name=\"input_newPassword_5\"/>\n @if (\n !passwordForm.get('newPassword').valid &&\n (passwordForm.get('newPassword').dirty ||\n passwordForm.get('newPassword').touched)\n ) {\n <small class=\"form-text text-muted danger\"\n >{{ 'User.Account.Validation.StrongPassword' | transloco }}\n </small>\n }\n </div>\n <div class=\"mb-3\">\n <label for=\"account-confirm-password\">{{\n 'User.Account.ConfirmPassword' | transloco\n }}</label>\n <input type=\"password\"\n id=\"account-confirm-password\"\n class=\"form-control\"\n formControlName=\"confirmPassword\"\n autocomplete=\"new-password\" name=\"input_confirmPassword_6\"/>\n @if (\n passwordForm.get('confirmPassword').touched &&\n passwordForm.get('confirmPassword').errors\n ?.MatchPassword\n ) {\n <div class=\"text-danger\"\n >\n {{ 'User.Account.Validation.PasswordsMatch' | transloco }}\n </div>\n }\n </div>\n <div class=\"mb-3\">\n @if (togglePassword) {\n <a class=\"btn btn-raised btn-outline-default\"\n aria-label=\"Navigate to Target\"\n data-bs-target=\"\"\n (click)=\"onTogglePassword()\">\n {{ 'Button.Cancel' | transloco }}</a>\n }\n <button class=\"btn btn-raised btn-primary ms-2\"\n [buttonBusy]=\"passwordBusyButton\"\n [disabled]=\"!passwordForm.valid\">\n {{ 'User.Account.UpdatePassword' | transloco }}\n </button>\n </div>\n }\n <div>\n @if (!togglePassword) {\n <a class=\"btn btn-raised btn-outline-primary\"\n aria-label=\"Navigate to Target\"\n data-bs-target=\"\"\n (click)=\"togglePassword = !togglePassword\">\n {{ 'User.Account.ChangePassword' | transloco }}</a>\n }\n </div>\n </div>\n }\n @if (!user?.has_password) {\n <div class=\"col-12\"\n >\n <a class=\"btn btn-raised btn-primary me-2\"\n aria-label=\"Navigate to Target\"\n data-bs-target=\"\"\n (click)=\"sendMailToResetPassword()\">\n {{ 'User.Account.ChangePassword' | transloco }}</a>\n </div>\n }\n </div>\n </form>\n </section>\n </div>\n @if (user?.api_keys?.api_hits_max > 0) {\n <div class=\"col-12 mt-3\">\n <section id=\"api-credentials\"\n class=\"card p-4 h-auto\">\n <div class=\"row\">\n <div class=\"col-12\">\n <h2>{{ 'User.Subscriptions.APICredentials.Title' | transloco }}</h2>\n <p>\n {{ 'User.Subscriptions.APICredentials.Description' | transloco }}\n </p>\n <!-- pb (not mb): .card .mb-3:last-child is margin-reset in this component's scss -->\n <p class=\"text-muted small mb-0 pb-3\">\n <i class=\"fas fa-info-circle me-1\"></i>\n {{ 'User.Subscriptions.APICredentials.SubscriptionClientIdNote' | transloco }}\n </p>\n </div>\n <div class=\"col-12 col-md-6\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"account-api-token\">{{ 'User.Account.APIUserToken' | transloco }}</label>\n <div class=\"input-group\">\n <input type=\"text\"\n id=\"account-api-token\"\n name=\"api_token\"\n class=\"form-control\"\n [value]=\"showApiToken ? user?.api_keys?.api_user_token || ('User.Subscriptions.APICredentials.NoTokenAvailable' | transloco) : '*************************'\"\n readonly />\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"toggleApiTokenVisibility()\">\n {{ showApiToken ? ('User.Subscriptions.APICredentials.Hide' | transloco) : ('User.Subscriptions.APICredentials.View' | transloco) }}\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-12 col-md-6\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"account-api-client-id\">{{ 'User.Account.APIUserId' | transloco }}</label>\n <div class=\"input-group\">\n <input type=\"text\"\n id=\"account-api-client-id\"\n name=\"api_client_id\"\n class=\"form-control\"\n [value]=\"showApiClientId ? user?.api_keys?.api_user_id || ('User.Subscriptions.APICredentials.NoClientIdAvailable' | transloco) : '*************************'\"\n readonly />\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"toggleApiClientIdVisibility()\">\n {{ showApiClientId ? ('User.Subscriptions.APICredentials.Hide' | transloco) : ('User.Subscriptions.APICredentials.View' | transloco) }}\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-12 mt-3\">\n <div class=\"d-flex align-items-center gap-3\">\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"refreshApiTokens()\"\n [disabled]=\"refreshingTokens\">\n <i class=\"fas fa-sync-alt me-2\" [class.fa-spin]=\"refreshingTokens\"></i>\n {{ refreshingTokens ? ('User.Subscriptions.APICredentials.Refreshing' | transloco) : ('User.Subscriptions.APICredentials.RefreshTokens' | transloco) }}\n </button>\n <div class=\"d-flex align-items-center gap-2\">\n @if (user?.api_keys?.api_hits !== null) {\n <span class=\"text-muted\">{{ 'User.Subscriptions.APICredentials.ApiHits' | transloco }}:</span>\n <span class=\"fw-bold\">{{ user.api_keys.api_hits | number }}</span>\n }\n @if (user?.api_keys?.api_hits_max !== null) {\n <span class=\"text-muted\">{{ 'User.Subscriptions.APICredentials.ApiHitsMax' | transloco }}:</span>\n <span class=\"fw-bold\">{{ user.api_keys.api_hits_max | number }}</span>\n }\n <!-- Show utilization percentage when both values exist -->\n @if (user?.api_keys?.api_hits !== null && user?.api_keys?.api_hits_max !== null && user?.api_keys?.api_hits_max > 0) {\n <span class=\"text-muted ms-2\">(</span>\n <span class=\"fw-bold\" [ngClass]=\"{\n 'text-success': (user.api_keys.api_hits / user.api_keys.api_hits_max) <= 0.8,\n 'text-warning': (user.api_keys.api_hits / user.api_keys.api_hits_max) > 0.8 && (user.api_keys.api_hits / user.api_keys.api_hits_max) <= 0.9,\n 'text-danger': (user.api_keys.api_hits / user.api_keys.api_hits_max) > 0.9\n }\">\n {{ (user.api_keys.api_hits / user.api_keys.api_hits_max * 100) | number:'1.0-0' }}% consumed\n </span>\n <span class=\"text-muted\">)</span>\n }\n </div>\n </div>\n </div>\n </div>\n </section>\n </div>\n }\n</div>\n<ng-template #content\n let-modal>\n <div class=\"card m-0\">\n <div class=\"card-content\">\n <div class=\"card-title\">\n <h3 class=\"modal-title\">{{ 'User.Profile.ProfilePicture' | transloco }}</h3>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n </button>\n </div>\n <div class=\"card-header\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile\n aspectRatio=\"auto\"\n (imageSelectionEvent)=\"onImageSelection($event)\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n </div>\n </div>\n</ng-template>\n", styles: [".card .mb-2:last-child,.card .mb-3:last-child{margin-bottom:0!important}.overlay{left:50%;opacity:0;position:absolute;text-align:center;top:50%;transform:translate(-50%,-50%);transition:.5s ease}.image-container{position:relative}.image-container:hover .image{opacity:.3}.image-container:hover .overlay{opacity:0}.overlay-text{background:#f0efef80;border-radius:50%;color:#000;font-size:16px;height:150px;line-height:150px;text-align:center;vertical-align:middle;width:150px}@media screen and (max-width:767px){.card-body{padding:20px!important}}\n"] }]
|
|
489
|
+
args: [{ selector: 'pw-account-details', standalone: false, template: "<div class=\"w-100 text-center\">\n @if (!isLoaded) {\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n }\n</div>\n<div class=\"row gx-3 mb-3\">\n <div class=\"col-md-4\">\n <section class=\"card p-4 h-100 d-flex flex-column\">\n <h2>{{ 'User.Profile.Avatar' | transloco }}</h2>\n <div class=\"text-center d-flex flex-column justify-content-center flex-grow-1 mt-1\">\n <div class=\"image-container\">\n <img [src]=\"image\"\n width=\"150\"\n height=\"150\"\n class=\"image rounded-circle\"\n alt=\"User Male\"\n (error)=\"handleImageError($event, 'assets/img/icons/male.png')\" />\n <div class=\"overlay\"\n (keydown.enter)=\"openModal(content)\"\n (click)=\"openModal(content)\">\n <div class=\"overlay-text\">{{ 'User.Profile.Change' | transloco }}</div>\n </div>\n </div>\n <h4 class=\"mt-2\">{{ user?.first_name }} {{ user?.last_name }}</h4>\n <a aria-label=\"Navigate to Target\"\n class=\"d-inline-block mb-2\"\n (click)=\"openModal(content)\">\n {{ 'User.Profile.EditAvatar' | transloco }}</a>\n </div>\n </section>\n </div>\n <div class=\"col-md-8\">\n <section id=\"user-profile\"\n class=\"card p-4 overflow-visible h-100\">\n <form [formGroup]=\"profileForm\"\n (ngSubmit)=\"onProfileFormSubmit()\">\n <h2>{{ 'User.Profile.UserProfile' | transloco }}</h2>\n <div class=\"row mt-3\">\n <div class=\"col-sm-12 col-md-6 col-lg-6\">\n <pw-input-container label=\"First Name\"\n name=\"first_name\"\n controlId=\"account-first_name\"\n errorMsg=\"Please enter first Name\">\n <input type=\"text\"\n id=\"account-first_name\"\n class=\"form-control\"\n formControlName=\"first_name\"\n autocomplete=\"given-name\" name=\"input_first_name_9\"/>\n </pw-input-container>\n <pw-input-container label=\"Preferred name\"\n name=\"preferred_name\"\n controlId=\"account-preferred_name\"\n errorMsg=\"Please enter preferred Name\">\n <input type=\"text\"\n id=\"account-preferred_name\"\n class=\"form-control\"\n formControlName=\"preferred_name\"\n autocomplete=\"username\" name=\"input_preferred_name_10\"/>\n </pw-input-container>\n @if (countries$ | async; as countries) {\n <pw-input-container label=\"Country\"\n name=\"country\"\n controlId=\"account-country\"\n [useAriaLabelledbyOnly]=\"true\"\n errorMsg=\"Please select a country\">\n <p-select\n [attr.aria-labelledby]=\"'account-country-label'\"\n [options]=\"countries\"\n optionLabel=\"name\"\n optionValue=\"code\"\n formControlName=\"country\"\n (onChange)=\"getRegion($event.value)\"\n placeholder=\"{{ 'User.Profile.SelectCountry' | transloco }}\">\n </p-select>\n </pw-input-container>\n }\n <pw-input-container label=\"Province\"\n name=\"province\"\n controlId=\"account-province\"\n errorMsg=\"Please enter province\">\n <input type=\"text\"\n id=\"account-province\"\n class=\"form-control\"\n formControlName=\"province\"\n autocomplete=\"postal-code\" name=\"input_province_11\"/>\n </pw-input-container>\n <pw-input-container label=\"Website Url\"\n name=\"website_url\"\n controlId=\"account-website_url\"\n errorMsg=\"Please enter Website\">\n <input type=\"text\"\n id=\"account-website_url\"\n class=\"form-control\"\n formControlName=\"website_url\"\n autocomplete=\"url\" name=\"input_website_url_12\"/>\n </pw-input-container>\n </div>\n <div class=\"col-sm-12 col-md-6 col-lg-6\">\n <pw-input-container label=\"Last Name\"\n name=\"last_name\"\n controlId=\"account-last_name\"\n errorMsg=\"Please enter last Name\">\n <input type=\"text\"\n id=\"account-last_name\"\n class=\"form-control\"\n formControlName=\"last_name\"\n autocomplete=\"family-name\" name=\"input_last_name_13\"/>\n </pw-input-container>\n <pw-input-container label=\"Date of Birth\"\n name=\"dob\"\n controlId=\"account-dob\"\n errorMsg=\"Please enter date of birth\">\n <div class=\"input-group\">\n <input class=\"form-control\"\n id=\"account-dob\"\n name=\"dob\"\n placeholder=\"dd-mmm-yyyy\"\n formControlName=\"dob\"\n ngbDatepicker\n #d=\"ngbDatepicker\"\n [minDate]=\"{ day: 1, month: 1, year: 1950 }\"\n [maxDate]=\"{ day: 31, month: 12, year: 2018 }\" />\n <button class=\"btn btn-primary\"\n type=\"button\"\n id=\"account-dob-trigger\"\n aria-label=\"Open date picker for date of birth\"\n (click)=\"d.toggle()\">\n <i class=\"fa fa-calendar\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </pw-input-container>\n <pw-input-container label=\"State\"\n name=\"state\"\n controlId=\"account-state\"\n [useAriaLabelledbyOnly]=\"true\"\n errorMsg=\"Please select a state\">\n <p-select\n [attr.aria-labelledby]=\"'account-state-label'\"\n [options]=\"states\"\n [(ngModel)]=\"selectedState\"\n optionLabel=\"name\"\n optionValue=\"code\"\n formControlName=\"state\"\n [placeholder]=\"'User.Profile.SelectState' | transloco\">\n </p-select>\n </pw-input-container>\n <pw-input-container label=\"Location\"\n name=\"location\"\n controlId=\"account-location\"\n [useAriaLabelledbyOnly]=\"true\">\n <input ngx-gp-autocomplete\n id=\"account-location\"\n name=\"location\"\n class=\"form-control\"\n [attr.aria-labelledby]=\"'account-location-label'\"\n #places=\"ngx-places\"\n formControlName=\"location\"\n (onAddressChange)=\"handleAddressChange($event)\" />\n </pw-input-container>\n <pw-input-container label=\"Phone Number\"\n name=\"phone_number\"\n controlId=\"account-phone_number\"\n errorMsg=\"Please enter phone number\">\n <input type=\"text\"\n id=\"account-phone_number\"\n class=\"form-control\"\n formControlName=\"phone_number\"\n autocomplete=\"tel\" name=\"input_phone_number_16\"/>\n </pw-input-container>\n </div>\n <div class=\"col-12 text-end\">\n <div class=\"mb-3\">\n <button class=\"btn btn-raised btn-primary\" [buttonBusy]=\"profileBusyButton\">\n {{ 'Button.Save' | transloco }}\n </button>\n </div>\n </div>\n </div>\n </form>\n </section>\n </div>\n</div>\n<div class=\"row gx-3 mb-3\">\n <div class=\"col-md-6\">\n <section id=\"email-section\"\n class=\"card p-4 h-100\">\n <div class=\"row\">\n <div class=\"col-12\">\n <h2>{{ 'User.Account.RegisteredEmail' | transloco }}</h2>\n <section id=\"email-form\">\n <form [formGroup]=\"emailForm\"\n (ngSubmit)=\"onEmailFormSubmit()\">\n <!-- Email Address -->\n <div class=\"mt-0\">\n <span id=\"account-primary-email-label\" class=\"me-3 pw-label-style\">{{ 'User.Account.PrimaryEmail' | transloco }}:\n </span>\n <strong>{{ validatedEmail }}</strong>\n <div class=\"mt-1\">\n @if (!toggleEmail) {\n <a class=\"btn btn-raised btn-outline-primary\"\n aria-label=\"Navigate to Target\"\n (click)=\"shouldUserChangeEmail()\">\n {{ 'User.Account.ChangeEmail' | transloco }}</a>\n }\n @if (toggleEmail) {\n <div class=\"row\">\n <div class=\"clearfix\"></div>\n <div class=\"col-12 mb-3\">\n @if (!passwordVerified) {\n <input type=\"password\"\n class=\"form-control\"\n id=\"account-email-current-password\"\n name=\"currentPassword\"\n #password\n placeholder=\"Current Password\"\n autocomplete=\"current-password\"\n (keyup)=\"checkValidity()\" />\n }\n @if (passwordVerified) {\n <input type=\"text\"\n class=\"form-control\"\n id=\"account-new-email\"\n name=\"newEmail\"\n placeholder=\"New Email\"\n autocomplete=\"email\"\n formControlName=\"email\" />\n }\n </div>\n <div class=\"col-12\">\n @if (toggleEmail) {\n <a\n class=\"btn btn-raised btn-outline-default my-2 me-2\"\n aria-label=\"Navigate to Target\"\n (click)=\"onToggleEmail()\">{{ 'Button.Cancel' | transloco }}</a>\n }\n @if (!passwordVerified) {\n <button class=\"btn btn-raised btn-primary\"\n type=\"submit\"\n [buttonBusy]=\"validatePasswordBusyButton\"\n (click)=\"validatePassword()\"\n [disabled]=\"isCurrentPasswordValid\">\n {{ 'User.Account.Validate' | transloco }}\n </button>\n }\n @if (passwordVerified) {\n <button type=\"submit\"\n class=\"btn btn-raised btn-primary\"\n [buttonBusy]=\"emailBusyButton\"\n >\n {{\n 'User.Account.SendVerification' | transloco\n }}\n </button>\n }\n </div>\n </div>\n }\n </div>\n </div>\n <section id=\"slug\"\n class=\"mb-2 mt-3\">\n <div>\n <span class=\"me-3 pw-label-style\" id=\"account-nickname-label\">{{ 'User.Account.NickName' | transloco }}:</span>\n <span class=\"tooltip-wrap me-3\" [pTooltip]=\"'User.Account.HandleTooltip' | transloco\" [appendTo]=\"'body'\" tooltipPosition=\"top\"><i class=\"far fa-info-circle text-muted\"></i></span>\n <strong>{{ slug }}</strong>\n <div class=\"mt-1\">\n @if (!toggleNickName) {\n <a class=\"btn btn-raised btn-outline-primary me-2\"\n aria-label=\"Navigate to Target\"\n (click)=\"toggleNickName = true\">\n {{ 'User.Account.ChangeNickname' | transloco }}</a>\n }\n @if (toggleNickName) {\n <div class=\"mb-3\">\n <input type=\"text\"\n id=\"account-nickname\"\n name=\"nickname\"\n class=\"form-control slug-input\"\n aria-labelledby=\"account-nickname-label\"\n [(ngModel)]=\"slug\"\n [ngModelOptions]=\"{ standalone: true }\" />\n </div>\n <div>\n <button type=\"button\"\n class=\"btn btn-raised btn-outline-default\"\n (click)=\"toggleNickName = false\">\n {{ 'Button.Cancel' | transloco }}\n </button>\n <button type=\"button\"\n class=\"btn btn-raised btn-primary ms-2\"\n [buttonBusy]=\"slugBusyButton\"\n [disabled]=\"slug?.length < 2\"\n (click)=\"onUpdateSlug()\">\n {{ 'User.Account.UpdateNickname' | transloco }}\n </button>\n </div>\n }\n </div>\n </div>\n </section>\n </form>\n </section>\n </div>\n </div>\n </section>\n </div>\n <div class=\"col-md-6\">\n <section id=\"password-change\"\n class=\"card p-4 h-100\">\n <form [formGroup]=\"passwordForm\"\n (ngSubmit)=\"onPasswordFormSubmit()\">\n <div class=\"row\">\n <div class=\"col-12\">\n <h2>{{ 'User.Account.ChangePassword' | transloco }}</h2>\n </div>\n @if (!user?.has_password) {\n <div class=\"text-danger mx-3 my-2\">\n <div>\n You don't have a password set, click on\n <em>{{ 'User.Account.ChangePassword' | transloco }}</em>.\n </div>\n <div>{{ 'User.Profile.PictureMessage' | transloco }}</div>\n </div>\n }\n @if (user?.has_password) {\n <div class=\"col-12\"\n >\n @if (togglePassword) {\n <div class=\"mb-3\">\n <label for=\"account-current-password\">{{ 'User.Account.CurrentPassword' | transloco }}</label>\n <input type=\"password\"\n id=\"account-current-password\"\n class=\"form-control\"\n formControlName=\"currentPassword\"\n autocomplete=\"current-password\" name=\"input_currentPassword_4\"/>\n @if (\n !passwordForm.get('currentPassword').valid &&\n (passwordForm.get('currentPassword').dirty ||\n passwordForm.get('currentPassword').touched)\n ) {\n <small class=\"form-text text-muted danger\"\n >\n {{ 'User.Account.Required' | transloco }}\n </small>\n }\n </div>\n <div class=\"mb-3\">\n <label for=\"account-new-password\">{{ 'User.Account.NewPassword' | transloco }}</label>\n <input type=\"password\"\n id=\"account-new-password\"\n class=\"form-control\"\n formControlName=\"newPassword\"\n autocomplete=\"new-password\" name=\"input_newPassword_5\"/>\n @if (\n !passwordForm.get('newPassword').valid &&\n (passwordForm.get('newPassword').dirty ||\n passwordForm.get('newPassword').touched)\n ) {\n <small class=\"form-text text-muted danger\"\n >{{ 'User.Account.Validation.StrongPassword' | transloco }}\n </small>\n }\n </div>\n <div class=\"mb-3\">\n <label for=\"account-confirm-password\">{{\n 'User.Account.ConfirmPassword' | transloco\n }}</label>\n <input type=\"password\"\n id=\"account-confirm-password\"\n class=\"form-control\"\n formControlName=\"confirmPassword\"\n autocomplete=\"new-password\" name=\"input_confirmPassword_6\"/>\n @if (\n passwordForm.get('confirmPassword').touched &&\n passwordForm.get('confirmPassword').errors\n ?.MatchPassword\n ) {\n <div class=\"text-danger\"\n >\n {{ 'User.Account.Validation.PasswordsMatch' | transloco }}\n </div>\n }\n </div>\n <div class=\"mb-3\">\n @if (togglePassword) {\n <a class=\"btn btn-raised btn-outline-default\"\n aria-label=\"Navigate to Target\"\n data-bs-target=\"\"\n (click)=\"onTogglePassword()\">\n {{ 'Button.Cancel' | transloco }}</a>\n }\n <button class=\"btn btn-raised btn-primary ms-2\"\n [buttonBusy]=\"passwordBusyButton\"\n [disabled]=\"!passwordForm.valid\">\n {{ 'User.Account.UpdatePassword' | transloco }}\n </button>\n </div>\n }\n <div>\n @if (!togglePassword) {\n <a class=\"btn btn-raised btn-outline-primary\"\n aria-label=\"Navigate to Target\"\n data-bs-target=\"\"\n (click)=\"togglePassword = !togglePassword\">\n {{ 'User.Account.ChangePassword' | transloco }}</a>\n }\n </div>\n </div>\n }\n @if (!user?.has_password) {\n <div class=\"col-12\"\n >\n <a class=\"btn btn-raised btn-primary me-2\"\n aria-label=\"Navigate to Target\"\n data-bs-target=\"\"\n (click)=\"sendMailToResetPassword()\">\n {{ 'User.Account.ChangePassword' | transloco }}</a>\n </div>\n }\n </div>\n </form>\n </section>\n </div>\n @if (user?.api_keys?.api_hits_max > 0) {\n <div class=\"col-12 mt-3\">\n <section id=\"api-credentials\"\n class=\"card p-4 h-auto\">\n <div class=\"row\">\n <div class=\"col-12\">\n <h2>{{ 'User.Subscriptions.APICredentials.Title' | transloco }}</h2>\n <p>\n {{ 'User.Subscriptions.APICredentials.Description' | transloco }}\n </p>\n <!-- pb (not mb): .card .mb-3:last-child is margin-reset in this component's scss -->\n <p class=\"text-muted small mb-0 pb-3\">\n <i class=\"fas fa-info-circle me-1\"></i>\n {{ 'User.Subscriptions.APICredentials.SubscriptionClientIdNote' | transloco }}\n </p>\n </div>\n <div class=\"col-12 col-md-6\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"account-api-token\">{{ 'User.Account.APIUserToken' | transloco }}</label>\n <div class=\"input-group\">\n <input type=\"text\"\n id=\"account-api-token\"\n name=\"api_token\"\n class=\"form-control\"\n [value]=\"showApiToken ? user?.api_keys?.api_user_token || ('User.Subscriptions.APICredentials.NoTokenAvailable' | transloco) : '*************************'\"\n readonly />\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"toggleApiTokenVisibility()\">\n {{ showApiToken ? ('User.Subscriptions.APICredentials.Hide' | transloco) : ('User.Subscriptions.APICredentials.View' | transloco) }}\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-12 col-md-6\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"account-api-client-id\">{{ 'User.Account.APIUserId' | transloco }}</label>\n <div class=\"input-group\">\n <input type=\"text\"\n id=\"account-api-client-id\"\n name=\"api_client_id\"\n class=\"form-control\"\n [value]=\"showApiClientId ? user?.api_keys?.api_user_id || ('User.Subscriptions.APICredentials.NoClientIdAvailable' | transloco) : '*************************'\"\n readonly />\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"toggleApiClientIdVisibility()\">\n {{ showApiClientId ? ('User.Subscriptions.APICredentials.Hide' | transloco) : ('User.Subscriptions.APICredentials.View' | transloco) }}\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-12 mt-3\">\n <div class=\"d-flex align-items-center gap-3\">\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"refreshApiTokens()\"\n [disabled]=\"refreshingTokens\">\n <i class=\"fas fa-sync-alt me-2\" [class.fa-spin]=\"refreshingTokens\"></i>\n {{ refreshingTokens ? ('User.Subscriptions.APICredentials.Refreshing' | transloco) : ('User.Subscriptions.APICredentials.RefreshTokens' | transloco) }}\n </button>\n <div class=\"d-flex align-items-center gap-2\">\n @if (user?.api_keys?.api_hits !== null) {\n <span class=\"text-muted\">{{ 'User.Subscriptions.APICredentials.ApiHits' | transloco }}:</span>\n <span class=\"fw-bold\">{{ user.api_keys.api_hits | number }}</span>\n }\n @if (user?.api_keys?.api_hits_max !== null) {\n <span class=\"text-muted\">{{ 'User.Subscriptions.APICredentials.ApiHitsMax' | transloco }}:</span>\n <span class=\"fw-bold\">{{ user.api_keys.api_hits_max | number }}</span>\n }\n <!-- Show utilization percentage when both values exist -->\n @if (user?.api_keys?.api_hits !== null && user?.api_keys?.api_hits_max !== null && user?.api_keys?.api_hits_max > 0) {\n <span class=\"text-muted ms-2\">(</span>\n <span class=\"fw-bold\" [ngClass]=\"{\n 'text-success-muted': (user.api_keys.api_hits / user.api_keys.api_hits_max) <= 0.8,\n 'text-warning': (user.api_keys.api_hits / user.api_keys.api_hits_max) > 0.8 && (user.api_keys.api_hits / user.api_keys.api_hits_max) <= 0.9,\n 'text-danger': (user.api_keys.api_hits / user.api_keys.api_hits_max) > 0.9\n }\">\n {{ (user.api_keys.api_hits / user.api_keys.api_hits_max * 100) | number:'1.0-0' }}% consumed\n </span>\n <span class=\"text-muted\">)</span>\n }\n </div>\n </div>\n </div>\n </div>\n </section>\n </div>\n }\n</div>\n<ng-template #content\n let-modal>\n <div class=\"card m-0\">\n <div class=\"card-content\">\n <div class=\"card-title\">\n <h3 class=\"modal-title\">{{ 'User.Profile.ProfilePicture' | transloco }}</h3>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n </button>\n </div>\n <div class=\"card-header\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile\n aspectRatio=\"auto\"\n (imageSelectionEvent)=\"onImageSelection($event)\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n </div>\n </div>\n</ng-template>\n", styles: [".card .mb-2:last-child,.card .mb-3:last-child{margin-bottom:0!important}.overlay{left:50%;opacity:0;position:absolute;text-align:center;top:50%;transform:translate(-50%,-50%);transition:.5s ease}.image-container{position:relative}.image-container:hover .image{opacity:.3}.image-container:hover .overlay{opacity:0}.overlay-text{background:#f0efef80;border-radius:50%;color:#000;font-size:16px;height:150px;line-height:150px;text-align:center;vertical-align:middle;width:150px}@media screen and (max-width:767px){.card-body{padding:20px!important}}\n"] }]
|
|
488
490
|
}], ctorParameters: () => [{ type: i2.UntypedFormBuilder }, { type: i1$1.NgbModal }, { type: i1$2.AuthService }, { type: i1$2.GeoService }, { type: i1$2.ProfileService }, { type: i0.Injector }, { type: i0.ChangeDetectorRef }], propDecorators: { placesRef: [{
|
|
489
491
|
type: ViewChild,
|
|
490
492
|
args: ['ngxPlaces']
|
|
@@ -565,7 +567,7 @@ class AddSubscriptionComponent extends AppBaseComponent {
|
|
|
565
567
|
super.ngOnDestroy();
|
|
566
568
|
}
|
|
567
569
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: AddSubscriptionComponent, deps: [{ token: i1$2.ProductService }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
568
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: AddSubscriptionComponent, isStandalone: false, selector: "pw-add-subscription", usesInheritance: true, ngImport: i0, template: "@if (isLoaded && !selectedProduct) {\n <div\n class=\"mt-4\">\n <div class=\"d-flex align-items-start category-tabs-row\">\n <a aria-label=\"Navigate to Target\"\n [routerLink]=\"['/account/subscriptions']\"\n class=\"previous\"><i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i>\n </a>\n <div class=\"d-flex category-tabs\">\n @for (item of subscribedPermissionKeys; track item; let i = $index) {\n <div class=\"toggle\"\n >\n <input type=\"radio\"\n name=\"sizeBy\"\n value=\"option{{ i + 1 }}\"\n id=\"option{{ i + 1 }}\"\n (change)=\"onChangeCategory(item)\"\n [checked]=\"i === 0\" />\n <label for=\"option{{ i + 1 }}\">{{ item }}</label>\n </div>\n }\n </div>\n </div>\n <ul class=\"row animated fadeIn d-flex\">\n @for (product of availableProducts; track trackByProduct($index, product)) {\n <li\n class=\"col-sm-12 col-md-6 col-xl-4 my-3 mt-sm-2\">\n <div class=\"card\">\n <div class=\"card-content\">\n <div class=\"card-header\">\n <h4 class=\"text-bold-500 primary mb-3\">{{ product.name }}</h4>\n @if (product.price_per_unit) {\n @if (product?.purchased_units) {\n <h5\n class=\"my-3 branding-color-1\">\n Currently {{ product.currency | currencySymbol\n }}{{\n (\n (product.purchased_units * product.price_per_unit) /\n 100\n ) | number:'1.2-2'\n }} / {{ product.billing_frequency }}\n </h5>\n }\n <h5 class=\"my-3\">\n Min\n {{product.min_units > 1 ? (product.min_units + ' Seats'): (product.min_units + ' Seat')}}\n - {{ product.currency | currencySymbol\n }}{{\n ((product.min_units * product.price_per_unit) / 100) | number:'1.2-2'\n }} / {{ product.billing_frequency }}\n </h5>\n <h5 class=\"d-inline-block text-bold-600 mb-2\">\n {{ product.currency | currencySymbol\n }}{{ (product.price_per_unit / 100) | number:'1.2-2' }} / {{\n product.billing_frequency\n }} / seat\n </h5>\n } @else {\n <div class=\"d-inline-block text-bold-600 mb-2\">Free</div>\n }\n <p class=\"mb-2\"\n [innerHTML]=\"product?.description\"></p>\n </div>\n <div class=\"card-footer px-3\">\n @if (\n !product.is_subscribed &&\n !product.trial_subscription &&\n product.stripe_plan_id\n ) {\n <a aria-label=\"Navigate to Target\"\n (click)=\"onSelection(product)\"\n class=\"card-btn btn btn-raised me-1 btn-primary btn-sm\">\n {{ 'User.Subscriptions.Subscribe' | transloco }}\n </a>\n }\n @if (\n !product.is_subscribed &&\n product.trial_subscription &&\n product.stripe_plan_id\n ) {\n <div class=\"mt-3\"\n >\n <a aria-label=\"Navigate to Target\"\n (click)=\"onSelection(product)\"\n class=\"card-btn btn btn-raised me-1 btn-primary btn-sm\">\n {{ 'Button.Upgrade' | transloco }}\n </a>\n <span class=\"badge bg-secondary position-absolute trial-badge\">{{ 'User.Subscriptions.Trial' | transloco }}\n </span>\n </div>\n }\n @if (\n product.is_subscribed &&\n !product.trial_subscription &&\n !product.is_deleted\n ) {\n <span\n class=\"card-btn badge bg-default text-white\">\n {{ 'User.Subscriptions.Subscribed' | transloco }}\n </span>\n }\n @if (\n product.is_subscribed &&\n product.trial_subscription &&\n product.price_per_unit === 0 &&\n !product.is_deleted &&\n !product.stripe_plan_id\n ) {\n <span\n class=\"card-btn badge bg-default text-white\">\n Free\n </span>\n }\n @if (product.is_deleted) {\n <span\n class=\"card-btn badge bg-default text-white\">\n {{ 'User.Subscriptions.UnsubscribedButActive' | transloco }}\n </span>\n }\n </div>\n </div>\n </div>\n </li>\n }\n </ul>\n <div class=\"row\">\n <div class=\"col-12\">\n @if (availableProducts && availableProducts.length === 0) {\n <pw-no-data [withImage]=\"true\" message=\"No products available under this category.\"\n >\n </pw-no-data>\n }\n </div>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:root{--first: rgb(23 105 225);--second: rgb(54 194 131);--third: rgb(255 171 0);--text: rgb(34 34 34);--tabs_bg: rgb(23 105 225);--tabs_sub_bg: rgb(70, 136, 236);--tabs_text: rgb(255 255 255);--titles: rgb(34 34 34);--sidebar_bg: rgb(0, 48, 63);--sidebar_text: rgb(255 255 255)}.card .card-body{position:relative}.card .card-body .bottom-text{bottom:15px;left:20px;position:absolute}.card .card-body .card-btn{bottom:15px;position:absolute}.card.shadow-md{height:100%}.card .primary{text-transform:uppercase}.trial-badge{bottom:15px;left:20px}.category-tabs{flex-wrap:nowrap;justify-content:safe center;max-width:100%;min-width:0;overflow-x:auto;scrollbar-width:thin}.category-tabs .toggle{flex:0 0 auto}.category-tabs .toggle input+label{white-space:nowrap}.category-tabs-row .previous i{top:0}.toggle{align-items:stretch;box-sizing:border-box;display:flex;flex-flow:row nowrap;font-size:0;justify-content:flex-start;margin:0}.toggle input{height:0;left:-9999px;position:absolute;width:0}.toggle input+label{background-color:#fff;border:solid 1px rgb(221,221,221);box-shadow:0 0 #fff0;box-sizing:border-box;display:inline-block;font-size:1rem;font-weight:600;line-height:140%;margin:0;padding:.75rem 2rem;position:relative;text-align:center;transition:border-color .15s ease-out,color .25s ease-out,background-color .15s ease-out,box-shadow .15s ease-out}.toggle input:hover+label{border-color:#213140}.toggle input:checked+label{background-color:var(--tabs_bg);border-color:var(--tabs_bg);box-shadow:0 0 10px #66b3fb80;color:var(--tabs_text);z-index:1}.toggle:first-of-type input+label{border-radius:4px 0 0 4px}.toggle:last-of-type input+label{border-radius:0 4px 4px 0}.toggle:first-of-type:last-of-type input+label{border-radius:4px}.shadow-md{height:100%;padding-bottom:50px!important}.fadeIn{animation-name:fadeIn}.animated{animation-duration:2s;animation-fill-mode:both}.card-btn{bottom:15px;position:absolute;right:20px}.card-footer{height:60px}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@media(max-width:800px){.toggle input+label{padding:.75rem 1rem}}.branding-color-1{color:var(--first)!important}\n"], dependencies: [{ kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type:
|
|
570
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: AddSubscriptionComponent, isStandalone: false, selector: "pw-add-subscription", usesInheritance: true, ngImport: i0, template: "@if (isLoaded && !selectedProduct) {\n <div\n class=\"mt-4\">\n <div class=\"d-flex align-items-start category-tabs-row\">\n <a aria-label=\"Navigate to Target\"\n [routerLink]=\"['/account/subscriptions']\"\n class=\"previous\"><i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i>\n </a>\n <div class=\"d-flex category-tabs\">\n @for (item of subscribedPermissionKeys; track item; let i = $index) {\n <div class=\"toggle\"\n >\n <input type=\"radio\"\n name=\"sizeBy\"\n value=\"option{{ i + 1 }}\"\n id=\"option{{ i + 1 }}\"\n (change)=\"onChangeCategory(item)\"\n [checked]=\"i === 0\" />\n <label for=\"option{{ i + 1 }}\">{{ item }}</label>\n </div>\n }\n </div>\n </div>\n <ul class=\"row animated fadeIn d-flex\">\n @for (product of availableProducts; track trackByProduct($index, product)) {\n <li\n class=\"col-sm-12 col-md-6 col-xl-4 my-3 mt-sm-2\">\n <div class=\"card\">\n <div class=\"card-content\">\n <div class=\"card-header\">\n <h4 class=\"text-bold-500 primary mb-3\">{{ product.name }}</h4>\n @if (product.price_per_unit) {\n @if (product?.purchased_units) {\n <h5\n class=\"my-3 branding-color-1\">\n Currently {{ product.currency | currencySymbol\n }}{{\n (\n (product.purchased_units * product.price_per_unit) /\n 100\n ) | number:'1.2-2'\n }} / {{ product.billing_frequency }}\n </h5>\n }\n <h5 class=\"my-3\">\n Min\n {{product.min_units > 1 ? (product.min_units + ' Seats'): (product.min_units + ' Seat')}}\n - {{ product.currency | currencySymbol\n }}{{\n ((product.min_units * product.price_per_unit) / 100) | number:'1.2-2'\n }} / {{ product.billing_frequency }}\n </h5>\n <h5 class=\"d-inline-block text-bold-600 mb-2\">\n {{ product.currency | currencySymbol\n }}{{ (product.price_per_unit / 100) | number:'1.2-2' }} / {{\n product.billing_frequency\n }} / seat\n </h5>\n } @else {\n <div class=\"d-inline-block text-bold-600 mb-2\">Free</div>\n }\n <p class=\"mb-2\"\n [innerHTML]=\"product?.description\"></p>\n </div>\n <div class=\"card-footer px-3\">\n @if (\n !product.is_subscribed &&\n !product.trial_subscription &&\n product.stripe_plan_id\n ) {\n <a aria-label=\"Navigate to Target\"\n (click)=\"onSelection(product)\"\n class=\"card-btn btn btn-raised me-1 btn-primary btn-sm\">\n {{ 'User.Subscriptions.Subscribe' | transloco }}\n </a>\n }\n @if (\n !product.is_subscribed &&\n product.trial_subscription &&\n product.stripe_plan_id\n ) {\n <div class=\"mt-3\"\n >\n <a aria-label=\"Navigate to Target\"\n (click)=\"onSelection(product)\"\n class=\"card-btn btn btn-raised me-1 btn-primary btn-sm\">\n {{ 'Button.Upgrade' | transloco }}\n </a>\n <span class=\"badge bg-secondary position-absolute trial-badge\">{{ 'User.Subscriptions.Trial' | transloco }}\n </span>\n </div>\n }\n @if (\n product.is_subscribed &&\n !product.trial_subscription &&\n !product.is_deleted\n ) {\n <span\n class=\"card-btn badge bg-default text-white\">\n {{ 'User.Subscriptions.Subscribed' | transloco }}\n </span>\n }\n @if (\n product.is_subscribed &&\n product.trial_subscription &&\n product.price_per_unit === 0 &&\n !product.is_deleted &&\n !product.stripe_plan_id\n ) {\n <span\n class=\"card-btn badge bg-default text-white\">\n Free\n </span>\n }\n @if (product.is_deleted) {\n <span\n class=\"card-btn badge bg-default text-white\">\n {{ 'User.Subscriptions.UnsubscribedButActive' | transloco }}\n </span>\n }\n </div>\n </div>\n </div>\n </li>\n }\n </ul>\n <div class=\"row\">\n <div class=\"col-12\">\n @if (availableProducts && availableProducts.length === 0) {\n <pw-no-data [withImage]=\"true\" message=\"No products available under this category.\"\n >\n </pw-no-data>\n }\n </div>\n </div>\n </div>\n}\n", styles: ["@charset \"UTF-8\";:root{--first: rgb(23 105 225);--second: rgb(54 194 131);--third: rgb(255 171 0);--text: rgb(34 34 34);--tabs_bg: rgb(23 105 225);--tabs_sub_bg: rgb(70, 136, 236);--tabs_text: rgb(255 255 255);--titles: rgb(34 34 34);--sidebar_bg: rgb(0, 48, 63);--sidebar_text: rgb(255 255 255)}.card .card-body{position:relative}.card .card-body .bottom-text{bottom:15px;left:20px;position:absolute}.card .card-body .card-btn{bottom:15px;position:absolute}.card.shadow-md{height:100%}.card .primary{text-transform:uppercase}.trial-badge{bottom:15px;left:20px}.category-tabs{flex-wrap:nowrap;justify-content:safe center;max-width:100%;min-width:0;overflow-x:auto;scrollbar-width:thin}.category-tabs .toggle{flex:0 0 auto}.category-tabs .toggle input+label{white-space:nowrap}.category-tabs-row .previous i{top:0}.toggle{align-items:stretch;box-sizing:border-box;display:flex;flex-flow:row nowrap;font-size:0;justify-content:flex-start;margin:0}.toggle input{height:0;left:-9999px;position:absolute;width:0}.toggle input+label{background-color:#fff;border:solid 1px rgb(221,221,221);box-shadow:0 0 #fff0;box-sizing:border-box;display:inline-block;font-size:1rem;font-weight:600;line-height:140%;margin:0;padding:.75rem 2rem;position:relative;text-align:center;transition:border-color .15s ease-out,color .25s ease-out,background-color .15s ease-out,box-shadow .15s ease-out}.toggle input:hover+label{border-color:#213140}.toggle input:checked+label{background-color:var(--tabs_bg);border-color:var(--tabs_bg);box-shadow:0 0 10px #66b3fb80;color:var(--tabs_text);z-index:1}.toggle:first-of-type input+label{border-radius:4px 0 0 4px}.toggle:last-of-type input+label{border-radius:0 4px 4px 0}.toggle:first-of-type:last-of-type input+label{border-radius:4px}.shadow-md{height:100%;padding-bottom:50px!important}.fadeIn{animation-name:fadeIn}.animated{animation-duration:2s;animation-fill-mode:both}.card-btn{bottom:15px;position:absolute;right:20px}.card-footer{height:60px}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@media(max-width:800px){.toggle input+label{padding:.75rem 1rem}}.branding-color-1{color:var(--first)!important}\n"], dependencies: [{ kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: i7.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "pipe", type: i5.DecimalPipe, name: "number" }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }, { kind: "pipe", type: i6$1.CurrencySymbolPipe, name: "currencySymbol" }] }); }
|
|
569
571
|
}
|
|
570
572
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: AddSubscriptionComponent, decorators: [{
|
|
571
573
|
type: Component,
|
|
@@ -605,6 +607,102 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
|
|
|
605
607
|
type: Output
|
|
606
608
|
}] } });
|
|
607
609
|
|
|
610
|
+
class ClearMaskedOnFocusDirective {
|
|
611
|
+
constructor(control) {
|
|
612
|
+
this.control = control;
|
|
613
|
+
}
|
|
614
|
+
onFocus(event) {
|
|
615
|
+
const input = event.target;
|
|
616
|
+
const value = input?.value ?? '';
|
|
617
|
+
if (/\*{3,}/.test(value)) {
|
|
618
|
+
this.control?.control?.setValue('');
|
|
619
|
+
input.value = '';
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ClearMaskedOnFocusDirective, deps: [{ token: i2.NgControl, optional: true, self: true }], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
623
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.6", type: ClearMaskedOnFocusDirective, isStandalone: false, selector: "input[pwClearMaskedOnFocus]", host: { listeners: { "focus": "onFocus($event)" } }, ngImport: i0 }); }
|
|
624
|
+
}
|
|
625
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: ClearMaskedOnFocusDirective, decorators: [{
|
|
626
|
+
type: Directive,
|
|
627
|
+
args: [{
|
|
628
|
+
selector: 'input[pwClearMaskedOnFocus]',
|
|
629
|
+
standalone: false
|
|
630
|
+
}]
|
|
631
|
+
}], ctorParameters: () => [{ type: i2.NgControl, decorators: [{
|
|
632
|
+
type: Optional
|
|
633
|
+
}, {
|
|
634
|
+
type: Self
|
|
635
|
+
}] }], propDecorators: { onFocus: [{
|
|
636
|
+
type: HostListener,
|
|
637
|
+
args: ['focus', ['$event']]
|
|
638
|
+
}] } });
|
|
639
|
+
|
|
640
|
+
const ACRONYMS = new Set([
|
|
641
|
+
'id',
|
|
642
|
+
'url',
|
|
643
|
+
'api',
|
|
644
|
+
'aws',
|
|
645
|
+
'smtp',
|
|
646
|
+
'ssl',
|
|
647
|
+
'tls',
|
|
648
|
+
'iam',
|
|
649
|
+
'sso',
|
|
650
|
+
'sdk',
|
|
651
|
+
'jwt',
|
|
652
|
+
'oauth'
|
|
653
|
+
]);
|
|
654
|
+
class SubscriptionNameByIdPipe {
|
|
655
|
+
transform(subs, id) {
|
|
656
|
+
if (!subs || id == null)
|
|
657
|
+
return '';
|
|
658
|
+
const found = subs.find(s => String(s.id) === String(id));
|
|
659
|
+
return (found?.organisation || found?.organization || found?.name || '');
|
|
660
|
+
}
|
|
661
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: SubscriptionNameByIdPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
662
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.6", ngImport: i0, type: SubscriptionNameByIdPipe, isStandalone: false, name: "subscriptionNameById" }); }
|
|
663
|
+
}
|
|
664
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: SubscriptionNameByIdPipe, decorators: [{
|
|
665
|
+
type: Pipe,
|
|
666
|
+
args: [{ name: 'subscriptionNameById', standalone: false }]
|
|
667
|
+
}] });
|
|
668
|
+
class CredentialAvatarHuePipe {
|
|
669
|
+
transform(value) {
|
|
670
|
+
if (!value)
|
|
671
|
+
return 215;
|
|
672
|
+
let hash = 0;
|
|
673
|
+
for (let i = 0; i < value.length; i++) {
|
|
674
|
+
hash = (hash * 31 + value.charCodeAt(i)) | 0;
|
|
675
|
+
}
|
|
676
|
+
return Math.abs(hash) % 360;
|
|
677
|
+
}
|
|
678
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: CredentialAvatarHuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
679
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.6", ngImport: i0, type: CredentialAvatarHuePipe, isStandalone: false, name: "credentialAvatarHue" }); }
|
|
680
|
+
}
|
|
681
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: CredentialAvatarHuePipe, decorators: [{
|
|
682
|
+
type: Pipe,
|
|
683
|
+
args: [{ name: 'credentialAvatarHue', standalone: false }]
|
|
684
|
+
}] });
|
|
685
|
+
class HumanizeCredentialNamePipe {
|
|
686
|
+
transform(value) {
|
|
687
|
+
if (!value)
|
|
688
|
+
return '';
|
|
689
|
+
return value
|
|
690
|
+
.replace(/[_-]+/g, ' ')
|
|
691
|
+
.split(' ')
|
|
692
|
+
.filter(Boolean)
|
|
693
|
+
.map(word => ACRONYMS.has(word.toLowerCase())
|
|
694
|
+
? word.toUpperCase()
|
|
695
|
+
: word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
|
696
|
+
.join(' ');
|
|
697
|
+
}
|
|
698
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: HumanizeCredentialNamePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
699
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.6", ngImport: i0, type: HumanizeCredentialNamePipe, isStandalone: false, name: "humanizeCredentialName" }); }
|
|
700
|
+
}
|
|
701
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: HumanizeCredentialNamePipe, decorators: [{
|
|
702
|
+
type: Pipe,
|
|
703
|
+
args: [{ name: 'humanizeCredentialName', standalone: false }]
|
|
704
|
+
}] });
|
|
705
|
+
|
|
608
706
|
class SubscriptionCredentialComponent extends AppBaseComponent {
|
|
609
707
|
constructor(fb, subscriptionService, injector, cdr) {
|
|
610
708
|
super(injector);
|
|
@@ -788,11 +886,11 @@ class SubscriptionCredentialComponent extends AppBaseComponent {
|
|
|
788
886
|
super.ngOnDestroy();
|
|
789
887
|
}
|
|
790
888
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: SubscriptionCredentialComponent, deps: [{ token: i2.UntypedFormBuilder }, { token: i1$2.SubscriptionService }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
791
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: SubscriptionCredentialComponent, isStandalone: false, selector: "pw-subscription-credential", viewQueries: [{ propertyName: "passwordValidationModalForRevealCredential", first: true, predicate: ["passwordValidationModalForRevealCredential"], descendants: true }, { propertyName: "passwordValidationModalForEditCredential", first: true, predicate: ["passwordValidationModalForEditCredential"], descendants: true }, { propertyName: "passwordValidationModalForAddCredential", first: true, predicate: ["passwordValidationModalForAddCredential"], descendants: true }], usesInheritance: true, ngImport: i0, template: "@if (showForm) {\n <div class=\"row\"\n >\n <div class=\"col-12 d-flex\">\n <a aria-label=\"Navigate to Target\"\n (click)=\"onCancel()\"\n (keydown.enter)=\"onCancel()\"\n class=\"previous\"><i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i></a>\n <h3 class=\"m-subheader__title m-subheader__title--separator\">\n <span>{{ data.length ? 'Edit' : 'Create new' }} Credential</span>\n </h3>\n </div>\n </div>\n }\n @if (showForm) {\n <div class=\"container-fluid pw-tab\">\n <div class=\"p-2 mt-3\">\n <form>\n <div class=\"row mb-3\">\n @if (!isEdit && showForm) {\n <div class=\"col-12 col-md-4\"\n >\n <div class=\"mb-3\">\n <span id=\"subscription-credential-select-label\" class=\"pw-label-style\">Credential <span class=\"text-danger required-icon\">*</span> </span>\n <p-select\n [attr.aria-labelledby]=\"'subscription-credential-select-label'\"\n [options]=\"uniqueCredential\"\n [placeholder]=\"'Select credential'\"\n optionLabel=\"name\"\n optionValue=\"name\"\n (onChange)=\"selectedOption($event)\">\n </p-select>\n </div>\n </div>\n }\n @if (credentialsSelect?.length) {\n <div class=\"col-12 col-md-4\"\n >\n <div class=\"card pb-2 pt-2 overflow-visible\">\n <div class=\"card-content\">\n <div class=\"card-header\">\n <form [formGroup]=\"form\"\n novalidate\n (ngSubmit)=\"saveCredentials()\">\n <div formArrayName=\"credentials\">\n @for (\n credential of credentialsGroup.controls; track\n credential; let i = $index) {\n <div>\n <div [formGroupName]=\"i\">\n <div class=\"mb-3\">\n <pw-input-container label=\"{{\n credential.get('field').value\n }}\"\n [class.info-circle]=\"\n credential.get('description').value\n \"\n name=\"value\"\n errorMsg=\"Please enter value\">\n @if (\n credential.get('description')\n .value\n ) {\n <span\n class=\"tooltiptext gradient-custom-branding\">{{\n credential.get('description')\n .value\n }}</span>\n }\n <input type=\"text\"\n class=\"form-control\"\n formControlName=\"value\"\n [ngClass]=\"{\n 'is-invalid':\n submitted &&\n credential.get('value')\n .invalid\n }\" id=\"input_value_1\" name=\"input_value_1\"/>\n </pw-input-container>\n </div>\n </div>\n </div>\n }\n </div>\n <div class=\"text-end mt-3\">\n <button type=\"submit\"\n [buttonBusy]=\"buttonBusy\"\n class=\"btn btn-primary\">\n {{ 'Button.Submit' | transloco }}\n </button>\n </div>\n </form>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n <div class=\"row\">\n <div class=\"col-12 text-end mt-3\">\n <button type=\"button\"\n class=\"btn btn-outline-default me-2\"\n (click)=\"onCancel()\"\n (keydown.enter)=\"onCancel()\" >\n {{ 'Button.Back' | transloco }}\n </button>\n </div>\n </div>\n </form>\n </div>\n </div>\n }\n\n @if (!showForm) {\n <div class=\"row\">\n <div class=\"col-12 d-flex\">\n <a aria-label=\"Navigate to Target\"\n (click)=\"back()\"\n class=\"previous\"><i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i></a>\n <h2 class=\"mt-3\">Credentials</h2>\n </div>\n <div class=\"col-12 col-md-12 text-end\">\n <button class=\"btn btn-sm btn-outline-primary\"\n (click)=\"openCredentialsForAdd()\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i> {{ 'Add Credential' }}\n </button>\n </div>\n </div>\n @if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n <div class=\"row my-4\">\n @for (credential of credentials; track credential) {\n <div class=\"col-12 col-md-6 col-xl-4 mt-3 credential-cards\"\n >\n <div class=\"card\">\n <h2 class=\"credential-field mt-3\">{{ credential.credential_name }}</h2>\n @for (subscriptionCredential of credential.credentials; track subscriptionCredential) {\n <div class=\"card-content\"\n >\n <div class=\"card-header\">\n <div>\n <strong class=\"d-block\">{{ subscriptionCredential.field }}:</strong>\n <input class=\"credential-value\"\n [type]=\"\n credentialName === credential.credential_name\n ? 'text'\n : 'password'\n \"\n readonly\n #input\n [value]=\"subscriptionCredential?.value\" id=\"input_text_5520\" name=\"input_text_5520\" />\n </div>\n </div>\n <div class=\"card-footer\">\n <div class=\"float-end px-2\">\n @if (credentialName !== credential.credential_name) {\n <button class=\"btn btn-outline-primary me-2\"\n (click)=\"revealCredentials(credential)\">\n {{\n 'User.Subscriptions.SubscriptionCredentials.RevealCredential'\n | transloco\n }}\n </button>\n }\n @if (credentialName === credential.credential_name) {\n <button class=\"btn btn-outline-primary me-2\"\n (click)=\"hideCredentials()\">\n {{\n 'User.Subscriptions.SubscriptionCredentials.HideCredential'\n | transloco\n }}\n </button>\n }\n <a class=\"me-2 my-1\"\n aria-label=\"Edit Credential\"\n (click)=\"openCredentialsForEdit(credential.credential_name)\"><i class=\"fa fa-edit edit-icon\" aria-hidden=\"true\"></i></a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n @if (allSubscriptionCredentials?.length === 0 && isLoaded) {\n <div\n class=\"clearboth\">\n <pw-no-data [withImage]=\"true\" [message]=\"'User.Subscriptions.SubscriptionCredentials.NoDataMessage' | transloco\">\n </pw-no-data>\n </div>\n }\n }\n <!-- password validation modal for reveal Credential -->\n <pw-password-validation #passwordValidationModalForRevealCredential\n (successEvent)=\"showCredentials()\">\n </pw-password-validation>\n <!-- password validation modal for Edit Credential -->\n <pw-password-validation #passwordValidationModalForEditCredential\n (successEvent)=\"editCredentials()\">\n </pw-password-validation>\n <!-- password validation modal for Add Credential -->\n <pw-password-validation #passwordValidationModalForAddCredential\n (successEvent)=\"showEditForm()\">\n </pw-password-validation>\n", styles: [".credential-field{text-align:center}.card .card-header{padding:0 24px}.credentials-field{border:0}.credential-value{border:0;width:100%}.overflow-visible{overflow:visible}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i5.PasswordValidationComponent, selector: "pw-password-validation", inputs: ["confirmMessage"], outputs: ["successEvent"] }, { kind: "component", type: i6$2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i5.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "controlId", "useAriaLabelledbyOnly", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "component", type: i5.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
889
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: SubscriptionCredentialComponent, isStandalone: false, selector: "pw-subscription-credential", viewQueries: [{ propertyName: "passwordValidationModalForRevealCredential", first: true, predicate: ["passwordValidationModalForRevealCredential"], descendants: true }, { propertyName: "passwordValidationModalForEditCredential", first: true, predicate: ["passwordValidationModalForEditCredential"], descendants: true }, { propertyName: "passwordValidationModalForAddCredential", first: true, predicate: ["passwordValidationModalForAddCredential"], descendants: true }], usesInheritance: true, ngImport: i0, template: "@let subName = ((userService.getUserState() | async)?.currentUser?.subscriptions | subscriptionNameById: subscriptionId);\n\n@if (showForm) {\n <div class=\"row\">\n <div class=\"col-12 d-flex\">\n <a aria-label=\"Navigate to Target\"\n (click)=\"onCancel()\"\n (keydown.enter)=\"onCancel()\"\n class=\"previous\">\n <i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i>\n </a>\n <h3 class=\"m-subheader__title m-subheader__title--separator\">\n <span>\n @if (subName) {\n {{ (isEdit ? 'User.Subscriptions.SubscriptionCredentials.EditTitle' : 'User.Subscriptions.SubscriptionCredentials.CreateTitle') | transloco: { name: subName } }}\n } @else {\n {{ (isEdit ? 'User.Subscriptions.SubscriptionCredentials.EditTitleFallback' : 'User.Subscriptions.SubscriptionCredentials.CreateTitleFallback') | transloco }}\n }\n </span>\n </h3>\n </div>\n </div>\n <p class=\"credential-page-subtitle text-muted mb-4\">\n @if (subName) {\n {{ 'User.Subscriptions.SubscriptionCredentials.FormSubtitle' | transloco: { name: subName } }}\n } @else {\n {{ 'User.Subscriptions.SubscriptionCredentials.FormSubtitleFallback' | transloco }}\n }\n </p>\n\n <section class=\"credential-form-shell\">\n @if (credentialsSelect?.length) {\n <div class=\"credential-form-band\"\n [style.--avatar-hue]=\"credentialsSelect[0].name | credentialAvatarHue\">\n <span class=\"credential-avatar\" aria-hidden=\"true\"\n [style.--avatar-hue]=\"credentialsSelect[0].name | credentialAvatarHue\">\n {{ (credentialsSelect[0].name | humanizeCredentialName).charAt(0) }}\n </span>\n <span class=\"credential-form-band-name\">\n {{ credentialsSelect[0].name | humanizeCredentialName }}\n </span>\n </div>\n }\n\n <form [formGroup]=\"form\" novalidate (ngSubmit)=\"saveCredentials()\" class=\"credential-form\">\n @if (!isEdit) {\n <div class=\"credential-form-row\">\n <pw-input-container\n [label]=\"'User.Subscriptions.SubscriptionCredentials.CredentialLabel' | transloco\"\n name=\"credentialType\">\n <p-select\n [options]=\"uniqueCredential\"\n [placeholder]=\"'User.Subscriptions.SubscriptionCredentials.CredentialPlaceholder' | transloco\"\n optionLabel=\"name\" optionValue=\"name\" appendTo=\"body\"\n (onChange)=\"selectedOption($event)\">\n </p-select>\n </pw-input-container>\n </div>\n }\n\n @if (credentialsSelect?.length) {\n <div formArrayName=\"credentials\" class=\"credential-form-fields\">\n @for (credential of credentialsGroup.controls; track credential; let i = $index) {\n <div [formGroupName]=\"i\" class=\"credential-form-row\">\n <pw-input-container\n [label]=\"credential.get('field').value | humanizeCredentialName\"\n [class.info-circle]=\"credential.get('description').value\"\n name=\"value\"\n [errorMsg]=\"'User.Subscriptions.SubscriptionCredentials.ValueError' | transloco\">\n @if (credential.get('description').value) {\n <span class=\"tooltiptext gradient-custom-branding\">{{ credential.get('description').value }}</span>\n }\n <input type=\"text\" class=\"form-control\" formControlName=\"value\" pwClearMaskedOnFocus\n [ngClass]=\"{ 'is-invalid': submitted && credential.get('value').invalid }\"\n [id]=\"'credential-value-' + i\" [name]=\"'credential-value-' + i\" />\n </pw-input-container>\n </div>\n }\n </div>\n }\n\n <div class=\"credential-form-actions\">\n <button type=\"button\" class=\"btn btn-outline-default\" (click)=\"onCancel()\" (keydown.enter)=\"onCancel()\">\n {{ 'Button.Back' | transloco }}\n </button>\n @if (credentialsSelect?.length) {\n <button type=\"submit\" [buttonBusy]=\"buttonBusy\" class=\"btn btn-primary\">\n {{ 'Button.Submit' | transloco }}\n </button>\n }\n </div>\n </form>\n </section>\n}\n\n@if (!showForm) {\n <div class=\"row\">\n <div class=\"col-12 d-flex\">\n <a aria-label=\"Navigate to Target\"\n (click)=\"back()\"\n (keydown.enter)=\"back()\"\n class=\"previous\">\n <i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i>\n </a>\n <h2 class=\"mt-3\">\n @if (subName) {\n {{ 'User.Subscriptions.SubscriptionCredentials.PageTitle' | transloco: { name: subName } }}\n } @else {\n {{ 'User.Subscriptions.SubscriptionCredentials.PageTitleFallback' | transloco }}\n }\n </h2>\n </div>\n <div class=\"col-12 col-md-12 text-end\">\n <button class=\"btn btn-sm btn-outline-primary\" (click)=\"openCredentialsForAdd()\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i>\n {{ 'User.Subscriptions.SubscriptionCredentials.AddButton' | transloco }}\n </button>\n </div>\n </div>\n <p class=\"credential-page-subtitle text-muted mb-4\">\n @if (subName) {\n {{ 'User.Subscriptions.SubscriptionCredentials.ListSubtitle' | transloco: { name: subName } }}\n } @else {\n {{ 'User.Subscriptions.SubscriptionCredentials.ListSubtitleFallback' | transloco }}\n }\n </p>\n\n <pw-loader [isVisible]=\"!isLoaded\"></pw-loader>\n\n @if (isLoaded) {\n @if (allSubscriptionCredentials?.length === 0) {\n <div class=\"credential-empty\">\n <pw-no-data [withImage]=\"true\"\n [message]=\"'User.Subscriptions.SubscriptionCredentials.NoDataMessage' | transloco\"></pw-no-data>\n </div>\n } @else {\n <ul class=\"credential-grid\">\n @for (credential of credentials; track credential.credential_name) {\n <li class=\"credential-card\">\n <header class=\"credential-card-header\"\n [style.--avatar-hue]=\"credential.credential_name | credentialAvatarHue\">\n <span class=\"credential-avatar\" aria-hidden=\"true\">\n {{ (credential.credential_name | humanizeCredentialName).charAt(0) }}\n </span>\n <h3 class=\"credential-card-title\">\n {{ credential.credential_name | humanizeCredentialName }}\n </h3>\n <button type=\"button\" class=\"credential-icon-btn\"\n [attr.aria-label]=\"'User.Subscriptions.SubscriptionCredentials.EditAriaLabel' | transloco\"\n (click)=\"openCredentialsForEdit(credential.credential_name)\">\n <i class=\"fa fa-pen\" aria-hidden=\"true\"></i>\n </button>\n </header>\n <dl class=\"credential-card-fields\">\n @for (entry of credential.credentials; track entry.id) {\n <div class=\"credential-card-row\">\n <dt>{{ entry.field | humanizeCredentialName }}</dt>\n <dd><code class=\"credential-card-value\">{{ entry?.value }}</code></dd>\n </div>\n }\n </dl>\n </li>\n }\n </ul>\n }\n }\n}\n\n<pw-password-validation #passwordValidationModalForEditCredential (successEvent)=\"editCredentials()\"></pw-password-validation>\n<pw-password-validation #passwordValidationModalForAddCredential (successEvent)=\"showEditForm()\"></pw-password-validation>\n", styles: [".credential-page-subtitle{margin-bottom:24px}.credential-grid{list-style:none;padding:0;margin:16px 0 0;width:100%;display:grid;gap:16px;grid-template-columns:repeat(auto-fill,minmax(360px,1fr))}.credential-card{background:#fff;border:1px solid #e2e5ea;border-radius:10px;display:flex;flex-direction:column;overflow:hidden;transition:border-color .15s ease-out}.credential-card:hover{border-color:#cfd4dc}.credential-card-header{display:flex;align-items:center;gap:12px;padding:14px 16px;background:hsl(var(--avatar-hue, 215),60%,97%);border-bottom:1px solid hsl(var(--avatar-hue, 215),40%,90%)}.credential-avatar{width:36px;height:36px;border-radius:8px;display:inline-flex;align-items:center;justify-content:center;font-size:15px;font-weight:700;line-height:1;color:hsl(var(--avatar-hue, 215),60%,28%);background:hsl(var(--avatar-hue, 215),70%,92%);border:1px solid hsl(var(--avatar-hue, 215),50%,82%);flex-shrink:0;text-transform:uppercase}.credential-card-header h3.credential-card-title{font-size:15px;font-weight:600;line-height:1;height:36px;color:#1a1d21;margin:0!important;padding:0!important;flex:1 1 auto;min-width:0;display:flex;align-items:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.credential-icon-btn{appearance:none;background:transparent;border:1px solid transparent;border-radius:6px;width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;color:#5a6473;cursor:pointer;transition:background-color .12s ease-out,color .12s ease-out,border-color .12s ease-out}.credential-icon-btn .fa{font-size:13px}.credential-icon-btn:hover,.credential-icon-btn:focus-visible{background-color:#fff;color:#1a1d21;border-color:#e2e5ea;outline:none}.credential-card-fields{margin:0;padding:4px 16px 12px;display:flex;flex-direction:column}.credential-card-row{display:grid;grid-template-columns:minmax(120px,1fr) minmax(0,2fr);align-items:center;gap:12px;padding:10px 0;border-bottom:1px dashed #eef0f3}.credential-card-row:last-child{border-bottom:0}.credential-card-row dt{font-size:11px;font-weight:500;color:#5a6473;letter-spacing:.05em;text-transform:uppercase;margin:0}.credential-card-row dd{margin:0;min-width:0;text-align:right}.credential-card-value{font-size:12.5px;font-weight:500;color:#5a6473;background:#f7f8fa;border:1px solid #e2e5ea;border-radius:4px;padding:3px 8px;display:inline-block;max-width:100%;word-break:break-all;line-height:1.5;-webkit-user-select:all;user-select:all}.credential-empty{padding:48px 0;text-align:center}.credential-form-shell{background:#fff;border:1px solid #e2e5ea;border-radius:10px;max-width:640px;overflow:hidden;margin-top:16px}.credential-form-band{display:flex;align-items:center;gap:12px;padding:14px 20px;background:hsl(var(--avatar-hue, 215),60%,97%);border-bottom:1px solid hsl(var(--avatar-hue, 215),40%,90%)}.credential-form-band .credential-form-band-name{font-size:15px;font-weight:600;line-height:1;color:hsl(var(--avatar-hue, 215),60%,22%);display:inline-flex;align-items:center;height:36px}.credential-form{padding:20px 24px 24px}.credential-form-fields{display:flex;flex-direction:column;gap:16px}.credential-form-row+.credential-form-fields{margin-top:16px;padding-top:16px;border-top:1px solid #e2e5ea}.credential-form-actions{margin-top:24px;padding-top:16px;border-top:1px solid #e2e5ea;display:flex;justify-content:flex-end;gap:8px}@media(max-width:575px){.credential-form{padding:16px}.credential-card-row{grid-template-columns:1fr;gap:4px}.credential-card-row dd{text-align:left}}\n"], dependencies: [{ kind: "component", type: i3.AppLoaderComponent, selector: "pw-loader", inputs: ["isVisible", "closeOnOutsideClick", "autoCloseTimeOut"] }, { kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i2.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "component", type: i7.PasswordValidationComponent, selector: "pw-password-validation", inputs: ["confirmMessage", "destructive"], outputs: ["successEvent"] }, { kind: "component", type: i7$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i7.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "controlId", "useAriaLabelledbyOnly", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "component", type: i7.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "directive", type: ClearMaskedOnFocusDirective, selector: "input[pwClearMaskedOnFocus]" }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }, { kind: "pipe", type: HumanizeCredentialNamePipe, name: "humanizeCredentialName" }, { kind: "pipe", type: CredentialAvatarHuePipe, name: "credentialAvatarHue" }, { kind: "pipe", type: SubscriptionNameByIdPipe, name: "subscriptionNameById" }] }); }
|
|
792
890
|
}
|
|
793
891
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: SubscriptionCredentialComponent, decorators: [{
|
|
794
892
|
type: Component,
|
|
795
|
-
args: [{ selector: 'pw-subscription-credential', standalone: false, template: "@if (showForm) {\n <div class=\"row\"\n >\n <div class=\"col-12 d-flex\">\n <a aria-label=\"Navigate to Target\"\n (click)=\"onCancel()\"\n (keydown.enter)=\"onCancel()\"\n class=\"previous\"><i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i></a>\n <h3 class=\"m-subheader__title m-subheader__title--separator\">\n <span>{{ data.length ? 'Edit' : 'Create new' }} Credential</span>\n </h3>\n </div>\n </div>\n }\n @if (showForm) {\n <div class=\"container-fluid pw-tab\">\n <div class=\"p-2 mt-3\">\n <form>\n <div class=\"row mb-3\">\n @if (!isEdit && showForm) {\n <div class=\"col-12 col-md-4\"\n >\n <div class=\"mb-3\">\n <span id=\"subscription-credential-select-label\" class=\"pw-label-style\">Credential <span class=\"text-danger required-icon\">*</span> </span>\n <p-select\n [attr.aria-labelledby]=\"'subscription-credential-select-label'\"\n [options]=\"uniqueCredential\"\n [placeholder]=\"'Select credential'\"\n optionLabel=\"name\"\n optionValue=\"name\"\n (onChange)=\"selectedOption($event)\">\n </p-select>\n </div>\n </div>\n }\n @if (credentialsSelect?.length) {\n <div class=\"col-12 col-md-4\"\n >\n <div class=\"card pb-2 pt-2 overflow-visible\">\n <div class=\"card-content\">\n <div class=\"card-header\">\n <form [formGroup]=\"form\"\n novalidate\n (ngSubmit)=\"saveCredentials()\">\n <div formArrayName=\"credentials\">\n @for (\n credential of credentialsGroup.controls; track\n credential; let i = $index) {\n <div>\n <div [formGroupName]=\"i\">\n <div class=\"mb-3\">\n <pw-input-container label=\"{{\n credential.get('field').value\n }}\"\n [class.info-circle]=\"\n credential.get('description').value\n \"\n name=\"value\"\n errorMsg=\"Please enter value\">\n @if (\n credential.get('description')\n .value\n ) {\n <span\n class=\"tooltiptext gradient-custom-branding\">{{\n credential.get('description')\n .value\n }}</span>\n }\n <input type=\"text\"\n class=\"form-control\"\n formControlName=\"value\"\n [ngClass]=\"{\n 'is-invalid':\n submitted &&\n credential.get('value')\n .invalid\n }\" id=\"input_value_1\" name=\"input_value_1\"/>\n </pw-input-container>\n </div>\n </div>\n </div>\n }\n </div>\n <div class=\"text-end mt-3\">\n <button type=\"submit\"\n [buttonBusy]=\"buttonBusy\"\n class=\"btn btn-primary\">\n {{ 'Button.Submit' | transloco }}\n </button>\n </div>\n </form>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n <div class=\"row\">\n <div class=\"col-12 text-end mt-3\">\n <button type=\"button\"\n class=\"btn btn-outline-default me-2\"\n (click)=\"onCancel()\"\n (keydown.enter)=\"onCancel()\" >\n {{ 'Button.Back' | transloco }}\n </button>\n </div>\n </div>\n </form>\n </div>\n </div>\n }\n\n @if (!showForm) {\n <div class=\"row\">\n <div class=\"col-12 d-flex\">\n <a aria-label=\"Navigate to Target\"\n (click)=\"back()\"\n class=\"previous\"><i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i></a>\n <h2 class=\"mt-3\">Credentials</h2>\n </div>\n <div class=\"col-12 col-md-12 text-end\">\n <button class=\"btn btn-sm btn-outline-primary\"\n (click)=\"openCredentialsForAdd()\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i> {{ 'Add Credential' }}\n </button>\n </div>\n </div>\n @if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n <div class=\"row my-4\">\n @for (credential of credentials; track credential) {\n <div class=\"col-12 col-md-6 col-xl-4 mt-3 credential-cards\"\n >\n <div class=\"card\">\n <h2 class=\"credential-field mt-3\">{{ credential.credential_name }}</h2>\n @for (subscriptionCredential of credential.credentials; track subscriptionCredential) {\n <div class=\"card-content\"\n >\n <div class=\"card-header\">\n <div>\n <strong class=\"d-block\">{{ subscriptionCredential.field }}:</strong>\n <input class=\"credential-value\"\n [type]=\"\n credentialName === credential.credential_name\n ? 'text'\n : 'password'\n \"\n readonly\n #input\n [value]=\"subscriptionCredential?.value\" id=\"input_text_5520\" name=\"input_text_5520\" />\n </div>\n </div>\n <div class=\"card-footer\">\n <div class=\"float-end px-2\">\n @if (credentialName !== credential.credential_name) {\n <button class=\"btn btn-outline-primary me-2\"\n (click)=\"revealCredentials(credential)\">\n {{\n 'User.Subscriptions.SubscriptionCredentials.RevealCredential'\n | transloco\n }}\n </button>\n }\n @if (credentialName === credential.credential_name) {\n <button class=\"btn btn-outline-primary me-2\"\n (click)=\"hideCredentials()\">\n {{\n 'User.Subscriptions.SubscriptionCredentials.HideCredential'\n | transloco\n }}\n </button>\n }\n <a class=\"me-2 my-1\"\n aria-label=\"Edit Credential\"\n (click)=\"openCredentialsForEdit(credential.credential_name)\"><i class=\"fa fa-edit edit-icon\" aria-hidden=\"true\"></i></a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n }\n </div>\n @if (allSubscriptionCredentials?.length === 0 && isLoaded) {\n <div\n class=\"clearboth\">\n <pw-no-data [withImage]=\"true\" [message]=\"'User.Subscriptions.SubscriptionCredentials.NoDataMessage' | transloco\">\n </pw-no-data>\n </div>\n }\n }\n <!-- password validation modal for reveal Credential -->\n <pw-password-validation #passwordValidationModalForRevealCredential\n (successEvent)=\"showCredentials()\">\n </pw-password-validation>\n <!-- password validation modal for Edit Credential -->\n <pw-password-validation #passwordValidationModalForEditCredential\n (successEvent)=\"editCredentials()\">\n </pw-password-validation>\n <!-- password validation modal for Add Credential -->\n <pw-password-validation #passwordValidationModalForAddCredential\n (successEvent)=\"showEditForm()\">\n </pw-password-validation>\n", styles: [".credential-field{text-align:center}.card .card-header{padding:0 24px}.credentials-field{border:0}.credential-value{border:0;width:100%}.overflow-visible{overflow:visible}\n"] }]
|
|
893
|
+
args: [{ selector: 'pw-subscription-credential', standalone: false, template: "@let subName = ((userService.getUserState() | async)?.currentUser?.subscriptions | subscriptionNameById: subscriptionId);\n\n@if (showForm) {\n <div class=\"row\">\n <div class=\"col-12 d-flex\">\n <a aria-label=\"Navigate to Target\"\n (click)=\"onCancel()\"\n (keydown.enter)=\"onCancel()\"\n class=\"previous\">\n <i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i>\n </a>\n <h3 class=\"m-subheader__title m-subheader__title--separator\">\n <span>\n @if (subName) {\n {{ (isEdit ? 'User.Subscriptions.SubscriptionCredentials.EditTitle' : 'User.Subscriptions.SubscriptionCredentials.CreateTitle') | transloco: { name: subName } }}\n } @else {\n {{ (isEdit ? 'User.Subscriptions.SubscriptionCredentials.EditTitleFallback' : 'User.Subscriptions.SubscriptionCredentials.CreateTitleFallback') | transloco }}\n }\n </span>\n </h3>\n </div>\n </div>\n <p class=\"credential-page-subtitle text-muted mb-4\">\n @if (subName) {\n {{ 'User.Subscriptions.SubscriptionCredentials.FormSubtitle' | transloco: { name: subName } }}\n } @else {\n {{ 'User.Subscriptions.SubscriptionCredentials.FormSubtitleFallback' | transloco }}\n }\n </p>\n\n <section class=\"credential-form-shell\">\n @if (credentialsSelect?.length) {\n <div class=\"credential-form-band\"\n [style.--avatar-hue]=\"credentialsSelect[0].name | credentialAvatarHue\">\n <span class=\"credential-avatar\" aria-hidden=\"true\"\n [style.--avatar-hue]=\"credentialsSelect[0].name | credentialAvatarHue\">\n {{ (credentialsSelect[0].name | humanizeCredentialName).charAt(0) }}\n </span>\n <span class=\"credential-form-band-name\">\n {{ credentialsSelect[0].name | humanizeCredentialName }}\n </span>\n </div>\n }\n\n <form [formGroup]=\"form\" novalidate (ngSubmit)=\"saveCredentials()\" class=\"credential-form\">\n @if (!isEdit) {\n <div class=\"credential-form-row\">\n <pw-input-container\n [label]=\"'User.Subscriptions.SubscriptionCredentials.CredentialLabel' | transloco\"\n name=\"credentialType\">\n <p-select\n [options]=\"uniqueCredential\"\n [placeholder]=\"'User.Subscriptions.SubscriptionCredentials.CredentialPlaceholder' | transloco\"\n optionLabel=\"name\" optionValue=\"name\" appendTo=\"body\"\n (onChange)=\"selectedOption($event)\">\n </p-select>\n </pw-input-container>\n </div>\n }\n\n @if (credentialsSelect?.length) {\n <div formArrayName=\"credentials\" class=\"credential-form-fields\">\n @for (credential of credentialsGroup.controls; track credential; let i = $index) {\n <div [formGroupName]=\"i\" class=\"credential-form-row\">\n <pw-input-container\n [label]=\"credential.get('field').value | humanizeCredentialName\"\n [class.info-circle]=\"credential.get('description').value\"\n name=\"value\"\n [errorMsg]=\"'User.Subscriptions.SubscriptionCredentials.ValueError' | transloco\">\n @if (credential.get('description').value) {\n <span class=\"tooltiptext gradient-custom-branding\">{{ credential.get('description').value }}</span>\n }\n <input type=\"text\" class=\"form-control\" formControlName=\"value\" pwClearMaskedOnFocus\n [ngClass]=\"{ 'is-invalid': submitted && credential.get('value').invalid }\"\n [id]=\"'credential-value-' + i\" [name]=\"'credential-value-' + i\" />\n </pw-input-container>\n </div>\n }\n </div>\n }\n\n <div class=\"credential-form-actions\">\n <button type=\"button\" class=\"btn btn-outline-default\" (click)=\"onCancel()\" (keydown.enter)=\"onCancel()\">\n {{ 'Button.Back' | transloco }}\n </button>\n @if (credentialsSelect?.length) {\n <button type=\"submit\" [buttonBusy]=\"buttonBusy\" class=\"btn btn-primary\">\n {{ 'Button.Submit' | transloco }}\n </button>\n }\n </div>\n </form>\n </section>\n}\n\n@if (!showForm) {\n <div class=\"row\">\n <div class=\"col-12 d-flex\">\n <a aria-label=\"Navigate to Target\"\n (click)=\"back()\"\n (keydown.enter)=\"back()\"\n class=\"previous\">\n <i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i>\n </a>\n <h2 class=\"mt-3\">\n @if (subName) {\n {{ 'User.Subscriptions.SubscriptionCredentials.PageTitle' | transloco: { name: subName } }}\n } @else {\n {{ 'User.Subscriptions.SubscriptionCredentials.PageTitleFallback' | transloco }}\n }\n </h2>\n </div>\n <div class=\"col-12 col-md-12 text-end\">\n <button class=\"btn btn-sm btn-outline-primary\" (click)=\"openCredentialsForAdd()\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i>\n {{ 'User.Subscriptions.SubscriptionCredentials.AddButton' | transloco }}\n </button>\n </div>\n </div>\n <p class=\"credential-page-subtitle text-muted mb-4\">\n @if (subName) {\n {{ 'User.Subscriptions.SubscriptionCredentials.ListSubtitle' | transloco: { name: subName } }}\n } @else {\n {{ 'User.Subscriptions.SubscriptionCredentials.ListSubtitleFallback' | transloco }}\n }\n </p>\n\n <pw-loader [isVisible]=\"!isLoaded\"></pw-loader>\n\n @if (isLoaded) {\n @if (allSubscriptionCredentials?.length === 0) {\n <div class=\"credential-empty\">\n <pw-no-data [withImage]=\"true\"\n [message]=\"'User.Subscriptions.SubscriptionCredentials.NoDataMessage' | transloco\"></pw-no-data>\n </div>\n } @else {\n <ul class=\"credential-grid\">\n @for (credential of credentials; track credential.credential_name) {\n <li class=\"credential-card\">\n <header class=\"credential-card-header\"\n [style.--avatar-hue]=\"credential.credential_name | credentialAvatarHue\">\n <span class=\"credential-avatar\" aria-hidden=\"true\">\n {{ (credential.credential_name | humanizeCredentialName).charAt(0) }}\n </span>\n <h3 class=\"credential-card-title\">\n {{ credential.credential_name | humanizeCredentialName }}\n </h3>\n <button type=\"button\" class=\"credential-icon-btn\"\n [attr.aria-label]=\"'User.Subscriptions.SubscriptionCredentials.EditAriaLabel' | transloco\"\n (click)=\"openCredentialsForEdit(credential.credential_name)\">\n <i class=\"fa fa-pen\" aria-hidden=\"true\"></i>\n </button>\n </header>\n <dl class=\"credential-card-fields\">\n @for (entry of credential.credentials; track entry.id) {\n <div class=\"credential-card-row\">\n <dt>{{ entry.field | humanizeCredentialName }}</dt>\n <dd><code class=\"credential-card-value\">{{ entry?.value }}</code></dd>\n </div>\n }\n </dl>\n </li>\n }\n </ul>\n }\n }\n}\n\n<pw-password-validation #passwordValidationModalForEditCredential (successEvent)=\"editCredentials()\"></pw-password-validation>\n<pw-password-validation #passwordValidationModalForAddCredential (successEvent)=\"showEditForm()\"></pw-password-validation>\n", styles: [".credential-page-subtitle{margin-bottom:24px}.credential-grid{list-style:none;padding:0;margin:16px 0 0;width:100%;display:grid;gap:16px;grid-template-columns:repeat(auto-fill,minmax(360px,1fr))}.credential-card{background:#fff;border:1px solid #e2e5ea;border-radius:10px;display:flex;flex-direction:column;overflow:hidden;transition:border-color .15s ease-out}.credential-card:hover{border-color:#cfd4dc}.credential-card-header{display:flex;align-items:center;gap:12px;padding:14px 16px;background:hsl(var(--avatar-hue, 215),60%,97%);border-bottom:1px solid hsl(var(--avatar-hue, 215),40%,90%)}.credential-avatar{width:36px;height:36px;border-radius:8px;display:inline-flex;align-items:center;justify-content:center;font-size:15px;font-weight:700;line-height:1;color:hsl(var(--avatar-hue, 215),60%,28%);background:hsl(var(--avatar-hue, 215),70%,92%);border:1px solid hsl(var(--avatar-hue, 215),50%,82%);flex-shrink:0;text-transform:uppercase}.credential-card-header h3.credential-card-title{font-size:15px;font-weight:600;line-height:1;height:36px;color:#1a1d21;margin:0!important;padding:0!important;flex:1 1 auto;min-width:0;display:flex;align-items:center;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.credential-icon-btn{appearance:none;background:transparent;border:1px solid transparent;border-radius:6px;width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;color:#5a6473;cursor:pointer;transition:background-color .12s ease-out,color .12s ease-out,border-color .12s ease-out}.credential-icon-btn .fa{font-size:13px}.credential-icon-btn:hover,.credential-icon-btn:focus-visible{background-color:#fff;color:#1a1d21;border-color:#e2e5ea;outline:none}.credential-card-fields{margin:0;padding:4px 16px 12px;display:flex;flex-direction:column}.credential-card-row{display:grid;grid-template-columns:minmax(120px,1fr) minmax(0,2fr);align-items:center;gap:12px;padding:10px 0;border-bottom:1px dashed #eef0f3}.credential-card-row:last-child{border-bottom:0}.credential-card-row dt{font-size:11px;font-weight:500;color:#5a6473;letter-spacing:.05em;text-transform:uppercase;margin:0}.credential-card-row dd{margin:0;min-width:0;text-align:right}.credential-card-value{font-size:12.5px;font-weight:500;color:#5a6473;background:#f7f8fa;border:1px solid #e2e5ea;border-radius:4px;padding:3px 8px;display:inline-block;max-width:100%;word-break:break-all;line-height:1.5;-webkit-user-select:all;user-select:all}.credential-empty{padding:48px 0;text-align:center}.credential-form-shell{background:#fff;border:1px solid #e2e5ea;border-radius:10px;max-width:640px;overflow:hidden;margin-top:16px}.credential-form-band{display:flex;align-items:center;gap:12px;padding:14px 20px;background:hsl(var(--avatar-hue, 215),60%,97%);border-bottom:1px solid hsl(var(--avatar-hue, 215),40%,90%)}.credential-form-band .credential-form-band-name{font-size:15px;font-weight:600;line-height:1;color:hsl(var(--avatar-hue, 215),60%,22%);display:inline-flex;align-items:center;height:36px}.credential-form{padding:20px 24px 24px}.credential-form-fields{display:flex;flex-direction:column;gap:16px}.credential-form-row+.credential-form-fields{margin-top:16px;padding-top:16px;border-top:1px solid #e2e5ea}.credential-form-actions{margin-top:24px;padding-top:16px;border-top:1px solid #e2e5ea;display:flex;justify-content:flex-end;gap:8px}@media(max-width:575px){.credential-form{padding:16px}.credential-card-row{grid-template-columns:1fr;gap:4px}.credential-card-row dd{text-align:left}}\n"] }]
|
|
796
894
|
}], ctorParameters: () => [{ type: i2.UntypedFormBuilder }, { type: i1$2.SubscriptionService }, { type: i0.Injector }, { type: i0.ChangeDetectorRef }], propDecorators: { passwordValidationModalForRevealCredential: [{
|
|
797
895
|
type: ViewChild,
|
|
798
896
|
args: ['passwordValidationModalForRevealCredential', { static: false }]
|
|
@@ -1029,7 +1127,7 @@ class UpdatePaymentDetailsComponent extends AppBaseComponent {
|
|
|
1029
1127
|
this.cdr.markForCheck();
|
|
1030
1128
|
}
|
|
1031
1129
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: UpdatePaymentDetailsComponent, deps: [{ token: i2.UntypedFormBuilder }, { token: i1$2.ScriptLoaderService }, { token: i1$2.ProductService }, { token: i1$2.SubscriptionService }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1032
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: UpdatePaymentDetailsComponent, isStandalone: false, selector: "pw-update-payment-details", viewQueries: [{ propertyName: "braintreeContainer", first: true, predicate: ["braintreeContainer"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"container-fluid\">\n <div class=\"card-block\">\n <div class=\"row\">\n <div class=\"col-lg-12 ps-0\">\n <a aria-label=\"Navigate to Target\"\n (click)=\"back()\"\n class=\"previous float-start\"><i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i></a>\n <h4 class=\"form-section my-3\">\n <i class=\"ft-edit\" aria-hidden=\"true\"></i>\n {{ 'User.Payments.UpdateTitle' | transloco }}\n </h4>\n </div>\n </div>\n\n <div class=\"row g-3 mt-1\">\n <!-- Primary payment method (Stripe) -->\n <div class=\"col-12 col-lg-6\">\n <div class=\"card payment-left p-3 h-100\">\n <div class=\"card-body\">\n <h5 class=\"section-title\">{{ 'User.Payments.Primary.Title' | transloco }}</h5>\n <p class=\"text-muted\">{{ 'User.Payments.Primary.Description' | transloco }}</p>\n\n @if (errorMsg) {\n <div class=\"alert alert-danger\">{{ errorMsg }}</div>\n }\n @if (!isChangePayment && cardDetails) {\n <pw-saved-card-details [data]=\"cardDetails\"\n (changeEvent)=\"onChange($event)\">\n </pw-saved-card-details>\n }\n\n @if (loading) {\n <div class=\"text-center\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n\n @if ((!cardDetails && !loading) || isChangePayment) {\n <form [formGroup]=\"form\" (ngSubmit)=\"onSave()\">\n <h4 class=\"title\">{{ 'User.Payments.Primary.NewCard' | transloco }}</h4>\n <div class=\"row\">\n <div class=\"col-md-9\">\n <div class=\"mb-3\">\n <label for=\"update-payment-card_number\">{{ 'User.Payments.CardNumber' | transloco }}</label>\n <input type=\"text\"\n id=\"update-payment-card_number\"\n class=\"form-control\"\n formControlName=\"card_number\"\n [placeholder]=\"'User.Payments.CardNumber' | transloco\"\n name=\"card_number\" />\n @if (form.get('card_number').touched && form.get('card_number').errors?.required) {\n <div class=\"danger\"><span>{{ 'User.Payments.Errors.CardNumberRequired' | transloco }}</span></div>\n }\n </div>\n </div>\n <div class=\"col-md-3\">\n <div class=\"mb-3\">\n <label for=\"update-payment-cvc\">{{ 'User.Payments.Cvc' | transloco }}</label>\n <input type=\"text\"\n id=\"update-payment-cvc\"\n class=\"form-control\"\n formControlName=\"cvc\"\n [placeholder]=\"'User.Payments.Cvc' | transloco\"\n name=\"cvc\" />\n @if (form.get('cvc').touched && form.get('cvc').errors?.required) {\n <div class=\"danger\"><span>{{ 'User.Payments.Errors.CvcRequired' | transloco }}</span></div>\n }\n </div>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-md-6\">\n <div class=\"mb-3\">\n <span class=\"sr-only\" id=\"update-payment-exp_month-label\" class=\"pw-label-style\">{{ 'User.Payments.ExpMonth' | transloco }}</span>\n <p-select\n [attr.aria-labelledby]=\"'update-payment-exp_month-label'\"\n [options]=\"months\"\n [appendTo]=\"'body'\"\n formControlName=\"exp_month\"\n [placeholder]=\"'User.Payments.ExpMonth' | transloco\"\n optionValue=\"value\"\n optionLabel=\"value\">\n </p-select>\n @if (form.get('exp_month').touched && form.get('exp_month').errors?.required) {\n <div class=\"danger\"><span>{{ 'User.Payments.Errors.ExpMonthRequired' | transloco }}</span></div>\n }\n </div>\n </div>\n <div class=\"col-md-6\">\n <div class=\"mb-3\">\n <span class=\"sr-only\" id=\"update-payment-exp_year-label\">{{ 'User.Payments.ExpYear' | transloco }}</span>\n <p-select\n [attr.aria-labelledby]=\"'update-payment-exp_year-label'\"\n [options]=\"years\"\n formControlName=\"exp_year\"\n [placeholder]=\"'User.Payments.ExpYear' | transloco\"\n optionValue=\"value\"\n [appendTo]=\"'body'\"\n optionLabel=\"value\">\n </p-select>\n @if (form.get('exp_year')?.touched && form.get('exp_year')?.errors?.['required']) {\n <div class=\"danger\"><span>{{ 'User.Payments.Errors.ExpYearRequired' | transloco }}</span></div>\n }\n </div>\n </div>\n <div class=\"col-12 text-center mt-4\">\n <img src=\"/assets/img/icons/powered_by_stripe_v2.png\"\n class=\"payment-provider\"\n alt=\"\" />\n </div>\n <div class=\"col-12 mt-4 text-end\">\n <button type=\"button\"\n (click)=\"cancel()\"\n class=\"btn btn-outline-default me-2\">\n {{ 'User.Payments.Cancel' | transloco }}\n </button>\n <button type=\"submit\"\n class=\"btn btn-primary\"\n [buttonBusy]=\"busy\">\n {{ 'User.Payments.Submit' | transloco }}\n </button>\n </div>\n </div>\n </form>\n }\n </div>\n </div>\n </div>\n\n <!-- Secondary payment method (Braintree) -->\n <div class=\"col-12 col-lg-6\">\n <div class=\"card payment-right p-3 h-100\">\n <div class=\"card-body\">\n <h5 class=\"section-title\">{{ 'User.Payments.Secondary.Title' | transloco }}</h5>\n <p class=\"alert alert-info\" [pTooltip]=\"'User.Payments.Secondary.Tooltip' | transloco\" tooltipPosition=\"top\" appendTo=\"body\">\n {{ 'User.Payments.Secondary.Callout' | transloco }}\n </p>\n\n @if (loading) {\n <div class=\"text-center\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n\n @if (secondaryCard && !showBraintreeForm) {\n <pw-saved-card-details [data]=\"secondaryCard\"\n (changeEvent)=\"startBraintreeFlow()\">\n </pw-saved-card-details>\n }\n\n @if (!secondaryCard && !showBraintreeForm && !loading) {\n <button type=\"button\"\n class=\"btn btn-primary\"\n (click)=\"startBraintreeFlow()\">\n {{ 'User.Payments.Secondary.AddCta' | transloco }}\n </button>\n }\n\n @if (showBraintreeForm) {\n <div #braintreeContainer class=\"braintree-dropin-container mt-3\"></div>\n <div class=\"col-12 mt-4 text-end\">\n <button type=\"button\"\n (click)=\"cancelBraintreeFlow()\"\n class=\"btn btn-outline-default me-2\">\n {{ 'User.Payments.Cancel' | transloco }}\n </button>\n <button type=\"button\"\n class=\"btn btn-primary\"\n [buttonBusy]=\"braintreeBusy\"\n (click)=\"submitBraintree()\">\n {{ 'User.Payments.Submit' | transloco }}\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n\n </div>\n</div>\n", styles: [".card-block .payment-left,.card-block .payment-right{border:1px solid rgb(204,204,204)}.card-block .payment-left h4,.card-block .payment-right h4{border-bottom:1px solid rgb(0,0,0);font-size:1rem;font-weight:600;margin:0 0 20px;padding:0 0 5px;text-transform:uppercase}.payment-provider{width:30%}@media(max-width:800px){.payment-provider{width:60%}}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i6$2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "directive", type: i11.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: SavedCardDetailsComponent, selector: "pw-saved-card-details", inputs: ["data", "isChangePayment", "showNewCard"], outputs: ["changeEvent"] }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
1130
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: UpdatePaymentDetailsComponent, isStandalone: false, selector: "pw-update-payment-details", viewQueries: [{ propertyName: "braintreeContainer", first: true, predicate: ["braintreeContainer"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"container-fluid\">\n <div class=\"card-block\">\n <div class=\"row\">\n <div class=\"col-lg-12 ps-0\">\n <a aria-label=\"Navigate to Target\"\n (click)=\"back()\"\n class=\"previous float-start\"><i class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i></a>\n <h4 class=\"form-section my-3\">\n <i class=\"ft-edit\" aria-hidden=\"true\"></i>\n {{ 'User.Payments.UpdateTitle' | transloco }}\n </h4>\n </div>\n </div>\n\n <div class=\"row g-3 mt-1\">\n <!-- Primary payment method (Stripe) -->\n <div class=\"col-12 col-lg-6\">\n <div class=\"card payment-left p-3 h-100\">\n <div class=\"card-body\">\n <h5 class=\"section-title\">{{ 'User.Payments.Primary.Title' | transloco }}</h5>\n <p class=\"text-muted\">{{ 'User.Payments.Primary.Description' | transloco }}</p>\n\n @if (errorMsg) {\n <div class=\"alert alert-danger\">{{ errorMsg }}</div>\n }\n @if (!isChangePayment && cardDetails) {\n <pw-saved-card-details [data]=\"cardDetails\"\n (changeEvent)=\"onChange($event)\">\n </pw-saved-card-details>\n }\n\n @if (loading) {\n <div class=\"text-center\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n\n @if ((!cardDetails && !loading) || isChangePayment) {\n <form [formGroup]=\"form\" (ngSubmit)=\"onSave()\">\n <h4 class=\"title\">{{ 'User.Payments.Primary.NewCard' | transloco }}</h4>\n <div class=\"row\">\n <div class=\"col-md-9\">\n <div class=\"mb-3\">\n <label for=\"update-payment-card_number\">{{ 'User.Payments.CardNumber' | transloco }}</label>\n <input type=\"text\"\n id=\"update-payment-card_number\"\n class=\"form-control\"\n formControlName=\"card_number\"\n [placeholder]=\"'User.Payments.CardNumber' | transloco\"\n name=\"card_number\" />\n @if (form.get('card_number').touched && form.get('card_number').errors?.required) {\n <div class=\"danger\"><span>{{ 'User.Payments.Errors.CardNumberRequired' | transloco }}</span></div>\n }\n </div>\n </div>\n <div class=\"col-md-3\">\n <div class=\"mb-3\">\n <label for=\"update-payment-cvc\">{{ 'User.Payments.Cvc' | transloco }}</label>\n <input type=\"text\"\n id=\"update-payment-cvc\"\n class=\"form-control\"\n formControlName=\"cvc\"\n [placeholder]=\"'User.Payments.Cvc' | transloco\"\n name=\"cvc\" />\n @if (form.get('cvc').touched && form.get('cvc').errors?.required) {\n <div class=\"danger\"><span>{{ 'User.Payments.Errors.CvcRequired' | transloco }}</span></div>\n }\n </div>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-md-6\">\n <div class=\"mb-3\">\n <span class=\"sr-only\" id=\"update-payment-exp_month-label\" class=\"pw-label-style\">{{ 'User.Payments.ExpMonth' | transloco }}</span>\n <p-select\n [attr.aria-labelledby]=\"'update-payment-exp_month-label'\"\n [options]=\"months\"\n [appendTo]=\"'body'\"\n formControlName=\"exp_month\"\n [placeholder]=\"'User.Payments.ExpMonth' | transloco\"\n optionValue=\"value\"\n optionLabel=\"value\">\n </p-select>\n @if (form.get('exp_month').touched && form.get('exp_month').errors?.required) {\n <div class=\"danger\"><span>{{ 'User.Payments.Errors.ExpMonthRequired' | transloco }}</span></div>\n }\n </div>\n </div>\n <div class=\"col-md-6\">\n <div class=\"mb-3\">\n <span class=\"sr-only\" id=\"update-payment-exp_year-label\">{{ 'User.Payments.ExpYear' | transloco }}</span>\n <p-select\n [attr.aria-labelledby]=\"'update-payment-exp_year-label'\"\n [options]=\"years\"\n formControlName=\"exp_year\"\n [placeholder]=\"'User.Payments.ExpYear' | transloco\"\n optionValue=\"value\"\n [appendTo]=\"'body'\"\n optionLabel=\"value\">\n </p-select>\n @if (form.get('exp_year')?.touched && form.get('exp_year')?.errors?.['required']) {\n <div class=\"danger\"><span>{{ 'User.Payments.Errors.ExpYearRequired' | transloco }}</span></div>\n }\n </div>\n </div>\n <div class=\"col-12 text-center mt-4\">\n <img src=\"/assets/img/icons/powered_by_stripe_v2.png\"\n class=\"payment-provider\"\n alt=\"\" />\n </div>\n <div class=\"col-12 mt-4 text-end\">\n <button type=\"button\"\n (click)=\"cancel()\"\n class=\"btn btn-outline-default me-2\">\n {{ 'User.Payments.Cancel' | transloco }}\n </button>\n <button type=\"submit\"\n class=\"btn btn-primary\"\n [buttonBusy]=\"busy\">\n {{ 'User.Payments.Submit' | transloco }}\n </button>\n </div>\n </div>\n </form>\n }\n </div>\n </div>\n </div>\n\n <!-- Secondary payment method (Braintree) -->\n <div class=\"col-12 col-lg-6\">\n <div class=\"card payment-right p-3 h-100\">\n <div class=\"card-body\">\n <h5 class=\"section-title\">{{ 'User.Payments.Secondary.Title' | transloco }}</h5>\n <p class=\"alert alert-info\" [pTooltip]=\"'User.Payments.Secondary.Tooltip' | transloco\" tooltipPosition=\"top\" appendTo=\"body\">\n {{ 'User.Payments.Secondary.Callout' | transloco }}\n </p>\n\n @if (loading) {\n <div class=\"text-center\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n\n @if (secondaryCard && !showBraintreeForm) {\n <pw-saved-card-details [data]=\"secondaryCard\"\n (changeEvent)=\"startBraintreeFlow()\">\n </pw-saved-card-details>\n }\n\n @if (!secondaryCard && !showBraintreeForm && !loading) {\n <button type=\"button\"\n class=\"btn btn-primary\"\n (click)=\"startBraintreeFlow()\">\n {{ 'User.Payments.Secondary.AddCta' | transloco }}\n </button>\n }\n\n @if (showBraintreeForm) {\n <div #braintreeContainer class=\"braintree-dropin-container mt-3\"></div>\n <div class=\"col-12 mt-4 text-end\">\n <button type=\"button\"\n (click)=\"cancelBraintreeFlow()\"\n class=\"btn btn-outline-default me-2\">\n {{ 'User.Payments.Cancel' | transloco }}\n </button>\n <button type=\"button\"\n class=\"btn btn-primary\"\n [buttonBusy]=\"braintreeBusy\"\n (click)=\"submitBraintree()\">\n {{ 'User.Payments.Submit' | transloco }}\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n\n </div>\n</div>\n", styles: [".card-block .payment-left,.card-block .payment-right{border:1px solid rgb(204,204,204)}.card-block .payment-left h4,.card-block .payment-right h4{border-bottom:1px solid rgb(0,0,0);font-size:1rem;font-weight:600;margin:0 0 20px;padding:0 0 5px;text-transform:uppercase}.payment-provider{width:30%}@media(max-width:800px){.payment-provider{width:60%}}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i7$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "directive", type: i11.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: SavedCardDetailsComponent, selector: "pw-saved-card-details", inputs: ["data", "isChangePayment", "showNewCard"], outputs: ["changeEvent"] }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
1033
1131
|
}
|
|
1034
1132
|
__decorate([
|
|
1035
1133
|
ValidateForm('form'),
|
|
@@ -1314,7 +1412,7 @@ class UpgradeSubscriptionComponent extends AppBaseComponent {
|
|
|
1314
1412
|
super.ngOnDestroy();
|
|
1315
1413
|
}
|
|
1316
1414
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: UpgradeSubscriptionComponent, deps: [{ token: i0.Injector }, { token: i1$2.ProductService }, { token: i2.UntypedFormBuilder }, { token: i1$1.NgbModal }, { token: i1$2.SubscriptionService }, { token: i4$2.Store }, { token: i1$2.ScriptLoaderService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1317
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: UpgradeSubscriptionComponent, isStandalone: false, selector: "pw-upgrade-subscription", viewQueries: [{ propertyName: "passwordValidationModal", first: true, predicate: ["passwordValidationModal"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<h4 class=\"form-section m-3\">\n <i class=\"ft-check-circle\" aria-hidden=\"true\"></i> {{ 'Button.Payment' | transloco }}\n</h4>\n<div class=\"card-block\">\n <!-- Show Payment Page when there is user.has_stripe_account===false -->\n <ng-container>\n <form class=\"form\"\n (ngSubmit)=\"attemptPurchase()\"\n [formGroup]=\"form\">\n <div class=\"row\">\n <div class=\"col-md-6\">\n <div class=\"form-body p-3 payment-left card pb-0\">\n <div class=\"card-body\">\n @if (product?.max_units > 1) {\n <div class=\"row\"\n >\n <div class=\"col-12\">\n <div class=\"mb-3\">\n <h4 class=\"title\">\n {{ 'User.Subscriptions.LicensesRequired' | transloco }}\n </h4>\n <div class=\"row btns-row\">\n <div class=\"col-md-4 col-8\">\n <pw-number-picker name=\"number-picker\"\n [(value)]=\"units\"\n [min]=\"subscription.min_units || product.min_units\"\n [max]=\"product.max_units\"\n step=\"1\"\n postfix=\"Units\"\n placeholder=\"Total Licenses\"\n [inputReadOnly]=\"false\"\n size=\"small\"\n pickStartAfter=\"500\"\n pickTimer=\"100\"\n [arrowKeys]=\"true\"\n (minReached)=\"onMinReached($event)\"\n (maxReached)=\"onMaxReached($event)\"\n (valueChange)=\"onUnitChange($event)\">\n </pw-number-picker>\n </div>\n </div>\n <div class=\"text-center\">\n <small class=\"form-text text-muted danger\">\n {{ unitError }}\n </small>\n </div>\n </div>\n <p>\n If you proceed, your credit card will be charged\n <strong>{{ product.currency }}\n {{ totalAmount | number:'1.2-2' }}</strong>\n </p>\n </div>\n </div>\n }\n <!-- Shows Saved Card: Shows when user has card details and not trying to update the card details -->\n @if (cardDetails) {\n <pw-saved-card-details [data]=\"cardDetails\"\n (changeEvent)=\"showNewCard = $event\"\n [showNewCard]=\"showNewCard\">\n </pw-saved-card-details>\n }\n <!-- Add New Payment Starts, opens up when user doesn't have stripe account or tries to change the\n card details -->\n @if ((user && !cardDetails) || (cardDetails && showNewCard)) {\n <h4 class=\"title\">\n {{ 'User.Subscriptions.NewCard' | transloco }}?\n </h4>\n <div class=\"row\">\n <div class=\"col-md-9\">\n <div class=\"mb-3\">\n <label for=\"upgrade-subscription-card_number\">{{\n 'User.Subscriptions.CardNumber' | transloco\n }}</label>\n <input type=\"text\"\n id=\"upgrade-subscription-card_number\"\n class=\"form-control\"\n formControlName=\"card_number\"\n placeholder=\"Card Number\"\n name=\"card_number\" />\n @if (\n form.get('card_number').touched &&\n form.get('card_number').errors?.required\n ) {\n <div class=\"danger\"\n >\n <span> Please enter card number. </span>\n </div>\n }\n </div>\n </div>\n <div class=\"col-md-3\">\n <div class=\"mb-3\">\n <label for=\"upgrade-subscription-cvc\">{{\n 'User.Subscriptions.CVC' | transloco\n }}</label>\n <input type=\"text\"\n id=\"upgrade-subscription-cvc\"\n class=\"form-control\"\n formControlName=\"cvc\"\n placeholder=\"CVC\"\n name=\"cvc\" />\n @if (\n form.get('cvc').touched &&\n form.get('cvc').errors?.required\n ) {\n <div class=\"danger\"\n >\n <span> Please enter cvc. </span>\n </div>\n }\n </div>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-md-6\">\n <div class=\"mb-3\">\n <span class=\"sr-only pw-label-style\" id=\"upgrade-subscription-exp_month-label\">Exp. Month</span>\n <p-select\n [attr.aria-labelledby]=\"'upgrade-subscription-exp_month-label'\"\n [options]=\"months\"\n formControlName=\"exp_month\"\n [placeholder]=\"'Exp. Month'\"\n optionValue=\"value\"\n [appendTo]=\"'body'\"\n optionLabel=\"value\">\n </p-select>\n @if (\n form.get('exp_month').touched &&\n form.get('exp_month').errors?.required\n ) {\n <div class=\"danger\"\n >\n <span> Please enter expiry month. </span>\n </div>\n }\n </div>\n </div>\n <div class=\"col-md-6\">\n <div class=\"mb-3\">\n <span class=\"sr-only\" id=\"upgrade-subscription-exp_year-label\">Exp. Year</span>\n <p-select\n [attr.aria-labelledby]=\"'upgrade-subscription-exp_year-label'\"\n [options]=\"years\"\n formControlName=\"exp_year\"\n [placeholder]=\"'Exp. Year'\"\n [appendTo]=\"'body'\"\n optionValue=\"value\"\n optionLabel=\"value\">\n </p-select>\n @if (\n form.get('exp_year').touched &&\n form.get('exp_year').errors?.required\n ) {\n <div class=\"danger\"\n >\n <span> Please enter expiry year. </span>\n </div>\n }\n </div>\n </div>\n @if (cardDetails) {\n <div class=\"col-12 mt-2\"\n >\n <a aria-label=\"Navigate to Target\"\n (click)=\"showNewCard = false; onDiscardToggle()\">Disregard and pay with current registered card</a>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Purchase Summary -->\n @if (product) {\n <div class=\"col-md-6\"\n >\n <div class=\"purchase-summary card p-3 payment-right\">\n <div class=\"card-body\">\n <h4 class=\"title\">{{ 'Label.PurchaseSummary' | transloco }}</h4>\n <div class=\"summary-row d-flex mb-2\">\n <div class=\"summary-left\">{{ 'Label.Plan' | transloco }}:</div>\n <div class=\"summary-right\">{{ product.name }}</div>\n </div>\n <div class=\"summary-row d-flex mb-2\">\n <div class=\"summary-left\">{{ 'Label.Price' | transloco }}:</div>\n <div class=\"summary-right\">\n {{ product.currency }}\n {{ (product.price_per_unit / 100) | number:'1.2-2' }}\n </div>\n </div>\n <div class=\"summary-row d-flex mb-2\">\n <div class=\"summary-left\">{{ 'Label.Seats' | transloco }}:</div>\n <div class=\"summary-right\">{{ form.get('units').value }}</div>\n </div>\n <div class=\"summary-row d-flex mb-2\">\n <div class=\"summary-left\">{{ 'Label.Total' | transloco }}:</div>\n <div class=\"summary-right\">\n {{ product.currency }} {{ totalAmount | number:'1.2-2' }}\n </div>\n </div>\n <div class=\"summary-row d-flex mb-2\">\n <div class=\"summary-left\">\n {{ 'Label.Recurrency' | transloco }}:\n </div>\n <div class=\"summary-right\">{{ product.billing_frequency }}</div>\n </div>\n </div>\n <div class=\"text-center\">\n <hr />\n <p>\n By subscribing you acknowledge and accept our terms of service and\n privacy policy\n </p>\n </div>\n </div>\n </div>\n }\n </div>\n <div class=\"row\">\n <div class=\"col-12 text-center mt-3\">\n <img src=\"/assets/img/icons/powered_by_stripe_v2.png\"\n class=\"payment-provider\"\n alt=\"\" />\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-12\">\n <div class=\"form-actions text-end\">\n <button type=\"button\"\n class=\"btn btn-raised btn-outline-default me-1\"\n [disabled]=\"isPurchaseAttempted\"\n routerLink=\"/account/subscriptions\">\n <i class=\"ft-x\" aria-hidden=\"true\"></i>{{ 'Button.Back' | transloco }}\n </button>\n <button type=\"submit\"\n class=\"btn btn-raised btn-primary\"\n [disabled]=\"isPurchaseAttempted\"\n [buttonBusy]=\"busy\">\n <i class=\"ft-check\" aria-hidden=\"true\"></i>\n {{ 'Button.Purchase' | transloco }}\n </button>\n </div>\n </div>\n </div>\n </form>\n </ng-container>\n</div>\n\n<pw-password-validation #passwordValidationModal\n (successEvent)=\"onValidatePassword($event)\">\n <div class=\"row\">\n <div class=\"col-12\">\n <p>\n If you proceed, your credit card will be charged\n @if (totalAmount) {\n <strong>{{ product.currency }} {{ totalAmount | number:'1.2-2' }}</strong>\n }\n </p>\n </div>\n </div>\n</pw-password-validation>\n", styles: [".payment-left,.payment-right{border:1px solid rgb(204,204,204);height:100%}.payment-left h4,.payment-right h4{border-bottom:1px solid rgb(0,0,0);font-size:1rem;font-weight:600;margin:0 0 20px;padding:0 0 5px;text-transform:uppercase}.payment-left .summary-row.total,.payment-right .summary-row.total{padding:10px 0 0 10px}.payment-left .summary-row .summary-left,.payment-right .summary-row .summary-left{font-weight:600}.payment-provider{width:20%}@media(max-width:800px){.payment-provider{width:60%}}.summary-left{-webkit-box-flex:1;color:#555;flex-grow:1;-ms-flex-positive:1;font-weight:200;text-align:left}.summary-left.plan{color:#c93f00;font-size:14px;margin:5px 0}.summary-right{-webkit-box-flex:1;-webkit-box-pack:end;color:#000;flex-grow:1;-ms-flex-pack:end;-ms-flex-positive:1;justify-content:flex-end;text-align:right}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i5.PasswordValidationComponent, selector: "pw-password-validation", inputs: ["confirmMessage"], outputs: ["successEvent"] }, { kind: "component", type: i6$2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i5.NumberPickerComponent, selector: "pw-number-picker", inputs: ["min", "showTooltip", "tooltipText", "max", "step", "value", "pickStartAfter", "pickTimer", "prefix", "postfix", "placeholder", "buttonsOrientation", "size", "customClass", "mouseWheel", "arrowKeys", "inputReadOnly", "showUpButton", "showDownButton", "inputId"], outputs: ["valueChange", "minReached", "maxReached", "pickStarted", "pickStopped", "pickUpStarted", "pickUpStopped", "pickDownStarted", "pickDownStopped"] }, { kind: "component", type: SavedCardDetailsComponent, selector: "pw-saved-card-details", inputs: ["data", "isChangePayment", "showNewCard"], outputs: ["changeEvent"] }, { kind: "pipe", type: i6.DecimalPipe, name: "number" }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
1415
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: UpgradeSubscriptionComponent, isStandalone: false, selector: "pw-upgrade-subscription", viewQueries: [{ propertyName: "passwordValidationModal", first: true, predicate: ["passwordValidationModal"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<h4 class=\"form-section m-3\">\n <i class=\"ft-check-circle\" aria-hidden=\"true\"></i> {{ 'Button.Payment' | transloco }}\n</h4>\n<div class=\"card-block\">\n <!-- Show Payment Page when there is user.has_stripe_account===false -->\n <ng-container>\n <form class=\"form\"\n (ngSubmit)=\"attemptPurchase()\"\n [formGroup]=\"form\">\n <div class=\"row\">\n <div class=\"col-md-6\">\n <div class=\"form-body p-3 payment-left card pb-0\">\n <div class=\"card-body\">\n @if (product?.max_units > 1) {\n <div class=\"row\"\n >\n <div class=\"col-12\">\n <div class=\"mb-3\">\n <h4 class=\"title\">\n {{ 'User.Subscriptions.LicensesRequired' | transloco }}\n </h4>\n <div class=\"row btns-row\">\n <div class=\"col-md-4 col-8\">\n <pw-number-picker name=\"number-picker\"\n [(value)]=\"units\"\n [min]=\"subscription.min_units || product.min_units\"\n [max]=\"product.max_units\"\n step=\"1\"\n postfix=\"Units\"\n placeholder=\"Total Licenses\"\n [inputReadOnly]=\"false\"\n size=\"small\"\n pickStartAfter=\"500\"\n pickTimer=\"100\"\n [arrowKeys]=\"true\"\n (minReached)=\"onMinReached($event)\"\n (maxReached)=\"onMaxReached($event)\"\n (valueChange)=\"onUnitChange($event)\">\n </pw-number-picker>\n </div>\n </div>\n <div class=\"text-center\">\n <small class=\"form-text text-muted danger\">\n {{ unitError }}\n </small>\n </div>\n </div>\n <p>\n If you proceed, your credit card will be charged\n <strong>{{ product.currency }}\n {{ totalAmount | number:'1.2-2' }}</strong>\n </p>\n </div>\n </div>\n }\n <!-- Shows Saved Card: Shows when user has card details and not trying to update the card details -->\n @if (cardDetails) {\n <pw-saved-card-details [data]=\"cardDetails\"\n (changeEvent)=\"showNewCard = $event\"\n [showNewCard]=\"showNewCard\">\n </pw-saved-card-details>\n }\n <!-- Add New Payment Starts, opens up when user doesn't have stripe account or tries to change the\n card details -->\n @if ((user && !cardDetails) || (cardDetails && showNewCard)) {\n <h4 class=\"title\">\n {{ 'User.Subscriptions.NewCard' | transloco }}?\n </h4>\n <div class=\"row\">\n <div class=\"col-md-9\">\n <div class=\"mb-3\">\n <label for=\"upgrade-subscription-card_number\">{{\n 'User.Subscriptions.CardNumber' | transloco\n }}</label>\n <input type=\"text\"\n id=\"upgrade-subscription-card_number\"\n class=\"form-control\"\n formControlName=\"card_number\"\n placeholder=\"Card Number\"\n name=\"card_number\" />\n @if (\n form.get('card_number').touched &&\n form.get('card_number').errors?.required\n ) {\n <div class=\"danger\"\n >\n <span> Please enter card number. </span>\n </div>\n }\n </div>\n </div>\n <div class=\"col-md-3\">\n <div class=\"mb-3\">\n <label for=\"upgrade-subscription-cvc\">{{\n 'User.Subscriptions.CVC' | transloco\n }}</label>\n <input type=\"text\"\n id=\"upgrade-subscription-cvc\"\n class=\"form-control\"\n formControlName=\"cvc\"\n placeholder=\"CVC\"\n name=\"cvc\" />\n @if (\n form.get('cvc').touched &&\n form.get('cvc').errors?.required\n ) {\n <div class=\"danger\"\n >\n <span> Please enter cvc. </span>\n </div>\n }\n </div>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-md-6\">\n <div class=\"mb-3\">\n <span class=\"sr-only pw-label-style\" id=\"upgrade-subscription-exp_month-label\">Exp. Month</span>\n <p-select\n [attr.aria-labelledby]=\"'upgrade-subscription-exp_month-label'\"\n [options]=\"months\"\n formControlName=\"exp_month\"\n [placeholder]=\"'Exp. Month'\"\n optionValue=\"value\"\n [appendTo]=\"'body'\"\n optionLabel=\"value\">\n </p-select>\n @if (\n form.get('exp_month').touched &&\n form.get('exp_month').errors?.required\n ) {\n <div class=\"danger\"\n >\n <span> Please enter expiry month. </span>\n </div>\n }\n </div>\n </div>\n <div class=\"col-md-6\">\n <div class=\"mb-3\">\n <span class=\"sr-only\" id=\"upgrade-subscription-exp_year-label\">Exp. Year</span>\n <p-select\n [attr.aria-labelledby]=\"'upgrade-subscription-exp_year-label'\"\n [options]=\"years\"\n formControlName=\"exp_year\"\n [placeholder]=\"'Exp. Year'\"\n [appendTo]=\"'body'\"\n optionValue=\"value\"\n optionLabel=\"value\">\n </p-select>\n @if (\n form.get('exp_year').touched &&\n form.get('exp_year').errors?.required\n ) {\n <div class=\"danger\"\n >\n <span> Please enter expiry year. </span>\n </div>\n }\n </div>\n </div>\n @if (cardDetails) {\n <div class=\"col-12 mt-2\"\n >\n <a aria-label=\"Navigate to Target\"\n (click)=\"showNewCard = false; onDiscardToggle()\">Disregard and pay with current registered card</a>\n </div>\n }\n </div>\n }\n </div>\n </div>\n </div>\n <!-- Purchase Summary -->\n @if (product) {\n <div class=\"col-md-6\"\n >\n <div class=\"purchase-summary card p-3 payment-right\">\n <div class=\"card-body\">\n <h4 class=\"title\">{{ 'Label.PurchaseSummary' | transloco }}</h4>\n <div class=\"summary-row d-flex mb-2\">\n <div class=\"summary-left\">{{ 'Label.Plan' | transloco }}:</div>\n <div class=\"summary-right\">{{ product.name }}</div>\n </div>\n <div class=\"summary-row d-flex mb-2\">\n <div class=\"summary-left\">{{ 'Label.Price' | transloco }}:</div>\n <div class=\"summary-right\">\n {{ product.currency }}\n {{ (product.price_per_unit / 100) | number:'1.2-2' }}\n </div>\n </div>\n <div class=\"summary-row d-flex mb-2\">\n <div class=\"summary-left\">{{ 'Label.Seats' | transloco }}:</div>\n <div class=\"summary-right\">{{ form.get('units').value }}</div>\n </div>\n <div class=\"summary-row d-flex mb-2\">\n <div class=\"summary-left\">{{ 'Label.Total' | transloco }}:</div>\n <div class=\"summary-right\">\n {{ product.currency }} {{ totalAmount | number:'1.2-2' }}\n </div>\n </div>\n <div class=\"summary-row d-flex mb-2\">\n <div class=\"summary-left\">\n {{ 'Label.Recurrency' | transloco }}:\n </div>\n <div class=\"summary-right\">{{ product.billing_frequency }}</div>\n </div>\n </div>\n <div class=\"text-center\">\n <hr />\n <p>\n By subscribing you acknowledge and accept our terms of service and\n privacy policy\n </p>\n </div>\n </div>\n </div>\n }\n </div>\n <div class=\"row\">\n <div class=\"col-12 text-center mt-3\">\n <img src=\"/assets/img/icons/powered_by_stripe_v2.png\"\n class=\"payment-provider\"\n alt=\"\" />\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-12\">\n <div class=\"form-actions text-end\">\n <button type=\"button\"\n class=\"btn btn-raised btn-outline-default me-1\"\n [disabled]=\"isPurchaseAttempted\"\n routerLink=\"/account/subscriptions\">\n <i class=\"ft-x\" aria-hidden=\"true\"></i>{{ 'Button.Back' | transloco }}\n </button>\n <button type=\"submit\"\n class=\"btn btn-raised btn-primary\"\n [disabled]=\"isPurchaseAttempted\"\n [buttonBusy]=\"busy\">\n <i class=\"ft-check\" aria-hidden=\"true\"></i>\n {{ 'Button.Purchase' | transloco }}\n </button>\n </div>\n </div>\n </div>\n </form>\n </ng-container>\n</div>\n\n<pw-password-validation #passwordValidationModal\n (successEvent)=\"onValidatePassword($event)\">\n <div class=\"row\">\n <div class=\"col-12\">\n <p>\n If you proceed, your credit card will be charged\n @if (totalAmount) {\n <strong>{{ product.currency }} {{ totalAmount | number:'1.2-2' }}</strong>\n }\n </p>\n </div>\n </div>\n</pw-password-validation>\n", styles: [".payment-left,.payment-right{border:1px solid rgb(204,204,204);height:100%}.payment-left h4,.payment-right h4{border-bottom:1px solid rgb(0,0,0);font-size:1rem;font-weight:600;margin:0 0 20px;padding:0 0 5px;text-transform:uppercase}.payment-left .summary-row.total,.payment-right .summary-row.total{padding:10px 0 0 10px}.payment-left .summary-row .summary-left,.payment-right .summary-row .summary-left{font-weight:600}.payment-provider{width:20%}@media(max-width:800px){.payment-provider{width:60%}}.summary-left{-webkit-box-flex:1;color:#555;flex-grow:1;-ms-flex-positive:1;font-weight:200;text-align:left}.summary-left.plan{color:#c93f00;font-size:14px;margin:5px 0}.summary-right{-webkit-box-flex:1;-webkit-box-pack:end;color:#000;flex-grow:1;-ms-flex-pack:end;-ms-flex-positive:1;justify-content:flex-end;text-align:right}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i7.PasswordValidationComponent, selector: "pw-password-validation", inputs: ["confirmMessage", "destructive"], outputs: ["successEvent"] }, { kind: "component", type: i7$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i7.NumberPickerComponent, selector: "pw-number-picker", inputs: ["min", "showTooltip", "tooltipText", "max", "step", "value", "pickStartAfter", "pickTimer", "prefix", "postfix", "placeholder", "buttonsOrientation", "size", "customClass", "mouseWheel", "arrowKeys", "inputReadOnly", "showUpButton", "showDownButton", "inputId"], outputs: ["valueChange", "minReached", "maxReached", "pickStarted", "pickStopped", "pickUpStarted", "pickUpStopped", "pickDownStarted", "pickDownStopped"] }, { kind: "component", type: SavedCardDetailsComponent, selector: "pw-saved-card-details", inputs: ["data", "isChangePayment", "showNewCard"], outputs: ["changeEvent"] }, { kind: "pipe", type: i5.DecimalPipe, name: "number" }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
1318
1416
|
}
|
|
1319
1417
|
__decorate([
|
|
1320
1418
|
ValidateForm('form'),
|
|
@@ -1587,7 +1685,7 @@ class UserSubscriptionDetailsComponent extends AppBaseComponent {
|
|
|
1587
1685
|
this.allowUpdate = false;
|
|
1588
1686
|
}
|
|
1589
1687
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: UserSubscriptionDetailsComponent, deps: [{ token: i2.UntypedFormBuilder }, { token: i1$2.GeoService }, { token: i1$1.NgbModal }, { token: i1$2.SubscriptionService }, { token: i4$2.Store }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1590
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: UserSubscriptionDetailsComponent, isStandalone: false, selector: "ng-component", viewQueries: [{ propertyName: "modal", first: true, predicate: ["modal"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<!-- edit Subscription details page -->\n<div class=\"row\">\n <div class=\"col-12\">\n <h3 class=\"my-3\">{{ subscription?.organisation || subscription?.contact_name }}</h3>\n </div>\n</div>\n\n@if (subscription) {\n <form [formGroup]=\"form\"\n (ngSubmit)=\"onSaveDetails()\"\n class=\"row mt-4\"\n >\n <!-- 1. Contact details -->\n <div class=\"col-12\">\n <h3>Contact details</h3>\n </div>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.ContactName' | transloco\"\n class=\"col-md-6\"\n label=\"Contact Name\"\n name=\"contact_name\"\n controlId=\"user-subscription-contact_name\"\n errorMsg=\"Please enter Contact Name\">\n <input type=\"text\"\n id=\"user-subscription-contact_name\"\n class=\"form-control\"\n formControlName=\"contact_name\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.ContactEmail' | transloco\"\n class=\"col-md-6\"\n label=\"Contact Email\"\n name=\"contact_email\"\n controlId=\"user-subscription-contact_email\"\n errorMsg=\"Please enter Contact Email\">\n <input type=\"text\"\n id=\"user-subscription-contact_email\"\n class=\"form-control\"\n formControlName=\"contact_email\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Organization' | transloco\"\n class=\"col-md-6\"\n label=\"Organisation\"\n name=\"organisation\"\n controlId=\"user-subscription-organisation\"\n errorMsg=\"Please enter organisation\">\n <input type=\"text\"\n id=\"user-subscription-organisation\"\n class=\"form-control\"\n formControlName=\"organisation\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Phone' | transloco\"\n class=\"col-md-6\"\n label=\"Contact Tel\"\n name=\"contact_tel\"\n controlId=\"user-subscription-contact_tel\"\n errorMsg=\"Please enter Contact Telephone Number\">\n <input type=\"text\"\n id=\"user-subscription-contact_tel\"\n class=\"form-control\"\n formControlName=\"contact_tel\" />\n </pw-input-container>\n @if (countries$ | async; as countries) {\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Country' | transloco\"\n class=\"col-md-6\"\n label=\"Country\"\n name=\"country_code\"\n controlId=\"user-subscription-country_code\"\n [useAriaLabelledbyOnly]=\"true\"\n [isLeftTooltip]=\"true\"\n errorMsg=\"Please select a country\">\n <p-select\n [attr.aria-labelledby]=\"'user-subscription-country_code-label'\"\n [options]=\"countries\"\n optionLabel=\"name\"\n optionValue=\"code\"\n formControlName=\"country_code\"\n placeholder=\"Select Country\">\n </p-select>\n </pw-input-container>\n }\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Address' | transloco\"\n class=\"col-md-6\"\n label=\"Address\"\n name=\"address\"\n controlId=\"user-subscription-address\"\n [useAriaLabelledbyOnly]=\"true\"\n errorMsg=\"Please enter address\">\n <input ngx-gp-autocomplete\n id=\"user-subscription-address\"\n name=\"address\"\n class=\"form-control\"\n [attr.aria-labelledby]=\"'user-subscription-address-label'\"\n #places=\"ngx-places\"\n formControlName=\"address\"\n (onAddressChange)=\"handleAddressChange($event)\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.VatNumber' | transloco\"\n class=\"col-md-6\"\n label=\"GST/VAT Number\"\n name=\"tax_id\"\n controlId=\"user-subscription-tax_id\"\n errorMsg=\"Please enter GST/VAT Number\">\n <input type=\"text\"\n id=\"user-subscription-tax_id\"\n class=\"form-control\"\n formControlName=\"tax_id\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.CompanyUrl' | transloco\"\n class=\"col-md-6\"\n label=\"Company URL\"\n name=\"company_url\"\n controlId=\"user-subscription-company_url\"\n errorMsg=\"Please enter company url\">\n <input type=\"text\"\n id=\"user-subscription-company_url\"\n class=\"form-control\"\n formControlName=\"company_url\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.InvoiceRecipientEmails' | transloco\"\n class=\"col-md-6\"\n label=\"Invoice Recipient Emails\"\n name=\"invoice_recipient_emails\"\n controlId=\"user-subscription-invoice_recipient_emails\"\n errorMsg=\"Please enter valid email addresses separated by commas\">\n <input type=\"text\"\n id=\"user-subscription-invoice_recipient_emails\"\n class=\"form-control\"\n formControlName=\"invoice_recipient_emails\"\n placeholder=\"email1@example.com,email2@example.com\" />\n </pw-input-container>\n\n <!-- 2. Branding / Logos -->\n <div class=\"col-12\">\n <div class=\"row branding-section\">\n <div class=\"col-12\">\n <h3>Branding</h3>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-md-6\">\n <div class=\"text-center mt-5\">\n <div class=\"image-container\">\n <h4 class=\"mb-2\">{{ 'User.Subscriptions.FullLogo' | transloco }}\n <span class=\"tooltip-wrap ms-1\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.FullLogo'|transloco\"\n [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\"\n alt=\"full logo\"\n class=\"image full-logo\"\n role=\"presentation\"\n (error)=\"fullLogoBroken = true\" />\n <div class=\"overlay mt-2\"\n (keydown.enter)=\"openModal(content)\"\n (click)=\"openModal(content)\">\n <div class=\"overlay-text\">\n <a aria-label=\"Navigate to Target\">{{ 'User.Profile.Change' | transloco }}</a>\n </div>\n </div>\n } @else {\n <div class=\"logo-dropzone full-dropzone\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Upload full logo\"\n (keydown.enter)=\"openModal(content)\"\n (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-center mt-5\">\n <div class=\"image-container\">\n <h4 class=\"mb-2\">Squared Logo\n <span class=\"tooltip-wrap ms-1\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.SquaredLogo'|transloco\"\n [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\"\n alt=\"Squared Presentation\"\n class=\"squared_logo\"\n role=\"presentation\"\n (error)=\"squaredLogoBroken = true\" />\n <div class=\"overlay mt-2\"\n (keydown.enter)=\"openModal(squaredLogoContent)\"\n (click)=\"openModal(squaredLogoContent)\">\n <div class=\"overlay-text\">\n <a aria-label=\"Navigate to Target\">{{ 'User.Profile.Change' | transloco }}</a>\n </div>\n </div>\n } @else {\n <div class=\"logo-dropzone squared-dropzone\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Upload squared logo\"\n (keydown.enter)=\"openModal(squaredLogoContent)\"\n (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 </div>\n\n <!-- 3. Social Media -->\n <ng-container *rbacAllow=\"'SubscriptionSuperAdmin'\">\n <div class=\"col-12\">\n <h3>Social Media</h3>\n <p>\n Any of the social media handles that you set here will appear in the footer of emails going out to your child subscriptions.\n </p>\n </div>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.FacebookHandle' | transloco\"\n class=\"col-md-6\"\n label=\"Facebook handle\"\n name=\"facebook_handle\"\n controlId=\"user-subscription-facebook_handle\"\n errorMsg=\"Please enter facebook id\">\n <input type=\"text\"\n id=\"user-subscription-facebook_handle\"\n class=\"form-control\"\n formControlName=\"facebook_handle\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.TwitterHandle' | transloco\"\n class=\"col-md-6\"\n label=\"Twitter handle\"\n name=\"twitter_handle\"\n controlId=\"user-subscription-twitter_handle\"\n errorMsg=\"Please enter twitter id\">\n <input type=\"text\"\n id=\"user-subscription-twitter_handle\"\n class=\"form-control\"\n formControlName=\"twitter_handle\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.LinkedinHandle' | transloco\"\n class=\"col-md-6\"\n label=\"Linkedin handle\"\n name=\"linkedin_handle\"\n controlId=\"user-subscription-linkedin_handle\"\n errorMsg=\"Please enter linkedin id\">\n <input type=\"text\"\n id=\"user-subscription-linkedin_handle\"\n class=\"form-control\"\n formControlName=\"linkedin_handle\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.RedditHandle' | transloco\"\n class=\"col-md-6\"\n label=\"Reddit handle\"\n name=\"reddit_handle\"\n controlId=\"user-subscription-reddit_handle\"\n errorMsg=\"Please enter reddit id\">\n <input type=\"text\"\n id=\"user-subscription-reddit_handle\"\n class=\"form-control\"\n formControlName=\"reddit_handle\" />\n </pw-input-container>\n </ng-container>\n\n <!-- 4. Seats -->\n <div class=\"col-12\">\n <div class=\"row seats-section\">\n <div class=\"col-12\">\n <h3>Seats</h3>\n <p>Changing the number of seats updates your subscription cost.</p>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-12\">\n @if (subscription?.trial_subscription && subscription?.calculated_price) {\n <small\n class=\"text-danger\">Upgrade to be able to update your purchased seats</small>\n }\n </div>\n </div>\n <div class=\"row btns-row align-items-center\">\n @if (subscription) {\n <div class=\"col-md-3 col-8\"\n >\n <label for=\"user-subscription-seats\" class=\"visually-hidden\">{{ 'User.Subscriptions.Tooltip.Seats' | transloco }}</label>\n <pw-number-picker [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Seats'|transloco\"\n inputId=\"user-subscription-seats\"\n name=\"number-picker\"\n [(value)]=\"units\"\n [min]=\"subscription?.min_units||subscription?.products[0].min_units\"\n [max]=\"subscription?.products[0].max_units\"\n step=\"1\"\n postfix=\"seats\"\n placeholder=\"Total Licences\"\n [inputReadOnly]=\"subscription?.products[0].trial_subscription\"\n [showUpButton]=\"!subscription?.products[0].trial_subscription\"\n [showDownButton]=\"!subscription?.products[0].trial_subscription\"\n size=\"small\"\n pickStartAfter=\"500\"\n pickTimer=\"100\"\n [arrowKeys]=\"true\"\n (minReached)=\"onMinReached($event)\"\n (maxReached)=\"onMaxReached($event)\"\n (valueChange)=\"onUnitChange($event)\">\n </pw-number-picker>\n </div>\n }\n\n @if (subscription) {\n <div class=\"col-md-3 col-4 p-1\"\n >\n @if (!subscription?.products[0].trial_subscription && allowUpdate) {\n <button type=\"button\"\n class=\"btn btn-primary\"\n (click)=\"updateUnits()\">\n {{ 'User.Subscriptions.UpdateUnits' | transloco }}\n </button>\n } @else {\n <div>\n @if (subscription?.products[0].trial_subscription) {\n <small class=\"text-muted\"\n >Update seats is available only to paid subscriptions</small>\n }\n </div>\n }\n </div>\n }\n\n @if (hasUnitChanged) {\n <div class=\"col-12 col-md-6\"\n >\n <table class=\"table table-borderless table-sm\"\n aria-describedby=\"Product details\">\n <thead>\n <tr>\n <th scope=\"true\">Product</th>\n <th scope=\"true\">Price per seat <span>({{subscription?.products[0]?.currency|currencySymbol}})</span></th>\n <th scope=\"true\">Seats</th>\n </tr>\n </thead>\n <tbody>\n @for (product of subscription.products; track trackByProduct($index, product)) {\n <tr>\n <td>{{ product.name }}</td>\n <td>{{ product.price_per_unit / 100 }}</td>\n <td>{{ units }}</td>\n </tr>\n }\n </tbody>\n </table>\n <p>\n If you proceed, the new cost for your subscription will be\n <strong>{{ totalAmount()| currency: subscription?.products[0]?.currency:'symbol-narrow'}}</strong>\n </p>\n </div>\n }\n </div>\n </div>\n\n <!-- 5. API & MCP Credentials -->\n @if (subscription?.api_hits_max > 0) {\n <div class=\"col-12\">\n <h3>{{ 'User.Subscriptions.APICredentials.Title' | transloco }}</h3>\n <p>\n These credentials authenticate both REST API and MCP (Model Context Protocol) requests, and must be used together with the user tokens defined on your Account page.\n </p>\n </div>\n <div class=\"col-md-6\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"user-subscription-api-token\">\n {{ 'User.Subscriptions.APICredentials.AccessToken' | transloco }}\n <span class=\"tooltip-wrap ms-1\"\n pTooltip=\"The subscription token has been discontinued in favour of the user token defined on your Account page.\"\n [appendTo]=\"'body'\"\n [tooltipPosition]=\"'top'\">\n <i class=\"far fa-info-circle text-muted\"></i>\n </span>\n </label>\n <div class=\"input-group\">\n <input type=\"text\"\n id=\"user-subscription-api-token\"\n name=\"api_token\"\n class=\"form-control\"\n [value]=\"showApiToken ? subscription?.api_access_token || ('User.Subscriptions.APICredentials.NoTokenAvailable' | transloco) : '*************************'\"\n readonly />\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"toggleApiTokenVisibility()\">\n {{ showApiToken ? ('User.Subscriptions.APICredentials.Hide' | transloco) : ('User.Subscriptions.APICredentials.View' | transloco) }}\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-md-6\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"user-subscription-api-client-id\">{{ 'User.Subscriptions.APICredentials.ClientId' | transloco }}</label>\n <div class=\"input-group\">\n <input type=\"text\"\n id=\"user-subscription-api-client-id\"\n name=\"api_client_id\"\n class=\"form-control\"\n [value]=\"showApiClientId ? subscription?.api_client_id || ('User.Subscriptions.APICredentials.NoClientIdAvailable' | transloco) : '*************************'\"\n readonly />\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"toggleApiClientIdVisibility()\">\n {{ showApiClientId ? ('User.Subscriptions.APICredentials.Hide' | transloco) : ('User.Subscriptions.APICredentials.View' | transloco) }}\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-12 mt-3\">\n <div class=\"d-flex align-items-center gap-3\">\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"refreshApiTokens()\"\n [disabled]=\"refreshingTokens\">\n <i class=\"fas fa-sync-alt me-2\" [class.fa-spin]=\"refreshingTokens\"></i>\n {{ refreshingTokens ? ('User.Subscriptions.APICredentials.Refreshing' | transloco) : ('User.Subscriptions.APICredentials.RefreshTokens' | transloco) }}\n </button>\n <div class=\"d-flex align-items-center gap-2\">\n @if (subscription?.api_hits !== null) {\n <span class=\"text-muted\">{{ 'User.Subscriptions.APICredentials.ApiHits' | transloco }}:</span>\n <span class=\"fw-bold\">{{ subscription.api_hits | number }}</span>\n }\n @if (subscription?.api_hits_max !== null) {\n <span class=\"text-muted\">{{ 'User.Subscriptions.APICredentials.ApiHitsMax' | transloco }}:</span>\n <span class=\"fw-bold\">{{ subscription.api_hits_max | number }}</span>\n }\n <!-- Show utilization percentage when both values exist -->\n @if (subscription?.api_hits !== null || subscription?.api_hits_max !== null) {\n <span class=\"text-muted ms-2\">(</span>\n <span class=\"fw-bold\" [ngClass]=\"{\n 'text-success': (subscription.api_hits / subscription.api_hits_max) <= 0.8,\n 'text-warning': (subscription.api_hits / subscription.api_hits_max) > 0.8 && (subscription.api_hits / subscription.api_hits_max) <= 0.9,\n 'text-danger': (subscription.api_hits / subscription.api_hits_max) > 0.9\n }\">\n {{ (subscription.api_hits / subscription.api_hits_max * 100) | number:'1.0-0' }}% consumed\n </span>\n <span class=\"text-muted\">)</span>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- 6. Security -->\n <div class=\"col-12 mt-5\">\n <h3>Security</h3>\n <p>\n While we'll add more security options in the future, please start by enforcing 2FA for all your subscription members.\n </p>\n </div>\n <div class=\"col-12 col-sm-3\">\n <pw-input-container label=\"Enforce 2FA\"\n [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Enforce2fa' | transloco\"\n name=\"enforce_2fa\"\n controlId=\"user-subscription-enforce_2fa\"\n [useAriaLabelledbyOnly]=\"true\">\n <ui-switch formControlName=\"enforce_2fa\"\n name=\"enforce_2fa\"\n [attr.aria-labelledby]=\"'user-subscription-enforce_2fa-label'\"> </ui-switch>\n </pw-input-container>\n </div>\n <div class=\"mb-3 col-12 text-end mt-3\">\n <button type=\"button\"\n class=\"btn btn-outline-default me-2\"\n routerLink=\"/account/subscriptions\">\n {{ 'Button.Cancel' | transloco }}\n </button>\n <button name=\"submit\"\n type=\"submit\"\n [buttonBusy]=\"busyButton\"\n class=\"btn btn-primary\">\n {{ 'Button.Submit' | transloco }}\n </button>\n </div>\n </form>\n}\n\n<ng-template #content\n 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\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile\n (imageSelectionEvent)=\"onImageSelection($event)\"\n aspectRatio=\"fullLogo\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n</ng-template>\n<ng-template #squaredLogoContent\n 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\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile\n (imageSelectionEvent)=\"uploadSquaredLogo($event)\"\n aspectRatio=\"auto\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n</ng-template>\n<pw-password-validation #modal\n(successEvent)=\"onPasswordValidation($event)\"> </pw-password-validation>\n", styles: [":host{display:block}:host>.row:first-of-type h3{color:var(--titles, #222);font-size:24px;font-weight:700;letter-spacing:-.01em;line-height:1.18}:host form .col-12>h3,:host .seats-section>.col-12>h3,:host .branding-section>.col-12>h3{border-top:1px solid #e2e5ea;color:var(--titles, #222);display:block;font-size:18px;font-weight:600;margin-top:32px;padding-top:24px}:host form>.col-12:first-child>h3{border-top:0;margin-top:0;padding-top:0}:host form .col-12>p,:host .seats-section>.col-12>p{color:#5a6473;font-size:15px;margin-bottom:16px}:host .row .text-center.mt-5{margin-top:16px!important;text-align:left!important}:host .image-container>h4{color:var(--titles, #222);font-size:14px;font-weight:600}: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}.sub-header{color:gray;font-size:20px;font-weight:600}@media only screen and (max-width:767px){.btns-row>[class*=col-]{flex:0 0 100%;max-width:100%}.btns-row .btn-primary{font-size:.8rem;margin-top:5px;padding:.375rem .5rem}}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "directive", type: i4.RbacAllowDirective, selector: "[rbacAllow]", inputs: ["rbacAllow"] }, { kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i6$1.NgxGpAutocompleteDirective, selector: "[ngx-gp-autocomplete]", inputs: ["options"], outputs: ["onAddressChange"], exportAs: ["ngx-places"] }, { kind: "component", type: i5.PasswordValidationComponent, selector: "pw-password-validation", inputs: ["confirmMessage"], outputs: ["successEvent"] }, { kind: "component", type: i6$2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i11$1.UiSwitchComponent, selector: "ui-switch", inputs: ["size", "color", "switchOffColor", "switchColor", "defaultBgColor", "defaultBoColor", "checkedLabel", "uncheckedLabel", "checkedTextColor", "uncheckedTextColor", "beforeChange", "ariaLabel", "checked", "disabled", "reverse", "loading"], outputs: ["change", "changeEvent", "valueChange"] }, { kind: "component", type: i5.NumberPickerComponent, selector: "pw-number-picker", inputs: ["min", "showTooltip", "tooltipText", "max", "step", "value", "pickStartAfter", "pickTimer", "prefix", "postfix", "placeholder", "buttonsOrientation", "size", "customClass", "mouseWheel", "arrowKeys", "inputReadOnly", "showUpButton", "showDownButton", "inputId"], outputs: ["valueChange", "minReached", "maxReached", "pickStarted", "pickStopped", "pickUpStarted", "pickUpStopped", "pickDownStarted", "pickDownStopped"] }, { kind: "component", type: i9.ProfileImageCropperComponent, selector: "pw-image-cropper", inputs: ["aspectRatio", "dynamicData"], outputs: ["imageSelectionEvent", "closeEvent", "fileChangeEvent"] }, { kind: "component", type: i5.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "controlId", "useAriaLabelledbyOnly", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "directive", type: i11.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.DecimalPipe, name: "number" }, { kind: "pipe", type: i6.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }, { kind: "pipe", type: i6$3.CurrencySymbolPipe, name: "currencySymbol" }] }); }
|
|
1688
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: UserSubscriptionDetailsComponent, isStandalone: false, selector: "ng-component", viewQueries: [{ propertyName: "modal", first: true, predicate: ["modal"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<!-- edit Subscription details page -->\n<div class=\"row\">\n <div class=\"col-12\">\n <h3 class=\"my-3\">{{ subscription?.organisation || subscription?.contact_name }}</h3>\n </div>\n</div>\n\n@if (subscription) {\n <form [formGroup]=\"form\"\n (ngSubmit)=\"onSaveDetails()\"\n class=\"row mt-4\"\n >\n <!-- 1. Contact details -->\n <div class=\"col-12\">\n <h3>Contact details</h3>\n </div>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.ContactName' | transloco\"\n class=\"col-md-6\"\n label=\"Contact Name\"\n name=\"contact_name\"\n controlId=\"user-subscription-contact_name\"\n errorMsg=\"Please enter Contact Name\">\n <input type=\"text\"\n id=\"user-subscription-contact_name\"\n class=\"form-control\"\n formControlName=\"contact_name\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.ContactEmail' | transloco\"\n class=\"col-md-6\"\n label=\"Contact Email\"\n name=\"contact_email\"\n controlId=\"user-subscription-contact_email\"\n errorMsg=\"Please enter Contact Email\">\n <input type=\"text\"\n id=\"user-subscription-contact_email\"\n class=\"form-control\"\n formControlName=\"contact_email\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Organization' | transloco\"\n class=\"col-md-6\"\n label=\"Organisation\"\n name=\"organisation\"\n controlId=\"user-subscription-organisation\"\n errorMsg=\"Please enter organisation\">\n <input type=\"text\"\n id=\"user-subscription-organisation\"\n class=\"form-control\"\n formControlName=\"organisation\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Phone' | transloco\"\n class=\"col-md-6\"\n label=\"Contact Tel\"\n name=\"contact_tel\"\n controlId=\"user-subscription-contact_tel\"\n errorMsg=\"Please enter Contact Telephone Number\">\n <input type=\"text\"\n id=\"user-subscription-contact_tel\"\n class=\"form-control\"\n formControlName=\"contact_tel\" />\n </pw-input-container>\n @if (countries$ | async; as countries) {\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Country' | transloco\"\n class=\"col-md-6\"\n label=\"Country\"\n name=\"country_code\"\n controlId=\"user-subscription-country_code\"\n [useAriaLabelledbyOnly]=\"true\"\n [isLeftTooltip]=\"true\"\n errorMsg=\"Please select a country\">\n <p-select\n [attr.aria-labelledby]=\"'user-subscription-country_code-label'\"\n [options]=\"countries\"\n optionLabel=\"name\"\n optionValue=\"code\"\n formControlName=\"country_code\"\n placeholder=\"Select Country\">\n </p-select>\n </pw-input-container>\n }\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Address' | transloco\"\n class=\"col-md-6\"\n label=\"Address\"\n name=\"address\"\n controlId=\"user-subscription-address\"\n [useAriaLabelledbyOnly]=\"true\"\n errorMsg=\"Please enter address\">\n <input ngx-gp-autocomplete\n id=\"user-subscription-address\"\n name=\"address\"\n class=\"form-control\"\n [attr.aria-labelledby]=\"'user-subscription-address-label'\"\n #places=\"ngx-places\"\n formControlName=\"address\"\n (onAddressChange)=\"handleAddressChange($event)\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.VatNumber' | transloco\"\n class=\"col-md-6\"\n label=\"GST/VAT Number\"\n name=\"tax_id\"\n controlId=\"user-subscription-tax_id\"\n errorMsg=\"Please enter GST/VAT Number\">\n <input type=\"text\"\n id=\"user-subscription-tax_id\"\n class=\"form-control\"\n formControlName=\"tax_id\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.CompanyUrl' | transloco\"\n class=\"col-md-6\"\n label=\"Company URL\"\n name=\"company_url\"\n controlId=\"user-subscription-company_url\"\n errorMsg=\"Please enter company url\">\n <input type=\"text\"\n id=\"user-subscription-company_url\"\n class=\"form-control\"\n formControlName=\"company_url\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.InvoiceRecipientEmails' | transloco\"\n class=\"col-md-6\"\n label=\"Invoice Recipient Emails\"\n name=\"invoice_recipient_emails\"\n controlId=\"user-subscription-invoice_recipient_emails\"\n errorMsg=\"Please enter valid email addresses separated by commas\">\n <input type=\"text\"\n id=\"user-subscription-invoice_recipient_emails\"\n class=\"form-control\"\n formControlName=\"invoice_recipient_emails\"\n placeholder=\"email1@example.com,email2@example.com\" />\n </pw-input-container>\n\n <!-- 2. Branding / Logos -->\n <div class=\"col-12\">\n <div class=\"row branding-section\">\n <div class=\"col-12\">\n <h3>Branding</h3>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-md-6\">\n <div class=\"text-center mt-5\">\n <div class=\"image-container\">\n <h4 class=\"mb-2\">{{ 'User.Subscriptions.FullLogo' | transloco }}\n <span class=\"tooltip-wrap ms-1\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.FullLogo'|transloco\"\n [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\"\n alt=\"full logo\"\n class=\"image full-logo\"\n role=\"presentation\"\n (error)=\"fullLogoBroken = true\" />\n <div class=\"overlay mt-2\"\n (keydown.enter)=\"openModal(content)\"\n (click)=\"openModal(content)\">\n <div class=\"overlay-text\">\n <a aria-label=\"Navigate to Target\">{{ 'User.Profile.Change' | transloco }}</a>\n </div>\n </div>\n } @else {\n <div class=\"logo-dropzone full-dropzone\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Upload full logo\"\n (keydown.enter)=\"openModal(content)\"\n (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-center mt-5\">\n <div class=\"image-container\">\n <h4 class=\"mb-2\">Squared Logo\n <span class=\"tooltip-wrap ms-1\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.SquaredLogo'|transloco\"\n [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\"\n alt=\"Squared Presentation\"\n class=\"squared_logo\"\n role=\"presentation\"\n (error)=\"squaredLogoBroken = true\" />\n <div class=\"overlay mt-2\"\n (keydown.enter)=\"openModal(squaredLogoContent)\"\n (click)=\"openModal(squaredLogoContent)\">\n <div class=\"overlay-text\">\n <a aria-label=\"Navigate to Target\">{{ 'User.Profile.Change' | transloco }}</a>\n </div>\n </div>\n } @else {\n <div class=\"logo-dropzone squared-dropzone\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Upload squared logo\"\n (keydown.enter)=\"openModal(squaredLogoContent)\"\n (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 </div>\n\n <!-- 3. Social Media -->\n <ng-container *rbacAllow=\"'SubscriptionSuperAdmin'\">\n <div class=\"col-12\">\n <h3>Social Media</h3>\n <p>\n Any of the social media handles that you set here will appear in the footer of emails going out to your child subscriptions.\n </p>\n </div>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.FacebookHandle' | transloco\"\n class=\"col-md-6\"\n label=\"Facebook handle\"\n name=\"facebook_handle\"\n controlId=\"user-subscription-facebook_handle\"\n errorMsg=\"Please enter facebook id\">\n <input type=\"text\"\n id=\"user-subscription-facebook_handle\"\n class=\"form-control\"\n formControlName=\"facebook_handle\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.TwitterHandle' | transloco\"\n class=\"col-md-6\"\n label=\"Twitter handle\"\n name=\"twitter_handle\"\n controlId=\"user-subscription-twitter_handle\"\n errorMsg=\"Please enter twitter id\">\n <input type=\"text\"\n id=\"user-subscription-twitter_handle\"\n class=\"form-control\"\n formControlName=\"twitter_handle\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.LinkedinHandle' | transloco\"\n class=\"col-md-6\"\n label=\"Linkedin handle\"\n name=\"linkedin_handle\"\n controlId=\"user-subscription-linkedin_handle\"\n errorMsg=\"Please enter linkedin id\">\n <input type=\"text\"\n id=\"user-subscription-linkedin_handle\"\n class=\"form-control\"\n formControlName=\"linkedin_handle\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.RedditHandle' | transloco\"\n class=\"col-md-6\"\n label=\"Reddit handle\"\n name=\"reddit_handle\"\n controlId=\"user-subscription-reddit_handle\"\n errorMsg=\"Please enter reddit id\">\n <input type=\"text\"\n id=\"user-subscription-reddit_handle\"\n class=\"form-control\"\n formControlName=\"reddit_handle\" />\n </pw-input-container>\n </ng-container>\n\n <!-- 4. Seats -->\n <div class=\"col-12\">\n <div class=\"row seats-section\">\n <div class=\"col-12\">\n <h3>Seats</h3>\n <p>Changing the number of seats updates your subscription cost.</p>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-12\">\n @if (subscription?.trial_subscription && subscription?.calculated_price) {\n <small\n class=\"text-danger\">Upgrade to be able to update your purchased seats</small>\n }\n </div>\n </div>\n <div class=\"row btns-row align-items-center\">\n @if (subscription) {\n <div class=\"col-md-3 col-8\"\n >\n <label for=\"user-subscription-seats\" class=\"visually-hidden\">{{ 'User.Subscriptions.Tooltip.Seats' | transloco }}</label>\n <pw-number-picker [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Seats'|transloco\"\n inputId=\"user-subscription-seats\"\n name=\"number-picker\"\n [(value)]=\"units\"\n [min]=\"subscription?.min_units||subscription?.products[0].min_units\"\n [max]=\"subscription?.products[0].max_units\"\n step=\"1\"\n postfix=\"seats\"\n placeholder=\"Total Licences\"\n [inputReadOnly]=\"subscription?.products[0].trial_subscription\"\n [showUpButton]=\"!subscription?.products[0].trial_subscription\"\n [showDownButton]=\"!subscription?.products[0].trial_subscription\"\n size=\"small\"\n pickStartAfter=\"500\"\n pickTimer=\"100\"\n [arrowKeys]=\"true\"\n (minReached)=\"onMinReached($event)\"\n (maxReached)=\"onMaxReached($event)\"\n (valueChange)=\"onUnitChange($event)\">\n </pw-number-picker>\n </div>\n }\n\n @if (subscription) {\n <div class=\"col-md-3 col-4 p-1\"\n >\n @if (!subscription?.products[0].trial_subscription && allowUpdate) {\n <button type=\"button\"\n class=\"btn btn-primary\"\n (click)=\"updateUnits()\">\n {{ 'User.Subscriptions.UpdateUnits' | transloco }}\n </button>\n } @else {\n <div>\n @if (subscription?.products[0].trial_subscription) {\n <small class=\"text-muted\"\n >Update seats is available only to paid subscriptions</small>\n }\n </div>\n }\n </div>\n }\n\n @if (hasUnitChanged) {\n <div class=\"col-12 col-md-6\"\n >\n <table class=\"table table-borderless table-sm\"\n aria-describedby=\"Product details\">\n <thead>\n <tr>\n <th scope=\"true\">Product</th>\n <th scope=\"true\">Price per seat <span>({{subscription?.products[0]?.currency|currencySymbol}})</span></th>\n <th scope=\"true\">Seats</th>\n </tr>\n </thead>\n <tbody>\n @for (product of subscription.products; track trackByProduct($index, product)) {\n <tr>\n <td>{{ product.name }}</td>\n <td>{{ product.price_per_unit / 100 }}</td>\n <td>{{ units }}</td>\n </tr>\n }\n </tbody>\n </table>\n <p>\n If you proceed, the new cost for your subscription will be\n <strong>{{ totalAmount()| currency: subscription?.products[0]?.currency:'symbol-narrow'}}</strong>\n </p>\n </div>\n }\n </div>\n </div>\n\n <!-- 5. API & MCP Credentials -->\n @if (subscription?.api_hits_max > 0) {\n <div class=\"col-12\">\n <h3>{{ 'User.Subscriptions.APICredentials.Title' | transloco }}</h3>\n <p>\n These credentials authenticate both REST API and MCP (Model Context Protocol) requests, and must be used together with the user tokens defined on your Account page.\n </p>\n </div>\n <div class=\"col-md-6\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"user-subscription-api-token\">\n {{ 'User.Subscriptions.APICredentials.AccessToken' | transloco }}\n <span class=\"tooltip-wrap ms-1\"\n pTooltip=\"The subscription token has been discontinued in favour of the user token defined on your Account page.\"\n [appendTo]=\"'body'\"\n [tooltipPosition]=\"'top'\">\n <i class=\"far fa-info-circle text-muted\"></i>\n </span>\n </label>\n <div class=\"input-group\">\n <input type=\"text\"\n id=\"user-subscription-api-token\"\n name=\"api_token\"\n class=\"form-control\"\n [value]=\"showApiToken ? subscription?.api_access_token || ('User.Subscriptions.APICredentials.NoTokenAvailable' | transloco) : '*************************'\"\n readonly />\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"toggleApiTokenVisibility()\">\n {{ showApiToken ? ('User.Subscriptions.APICredentials.Hide' | transloco) : ('User.Subscriptions.APICredentials.View' | transloco) }}\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-md-6\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"user-subscription-api-client-id\">{{ 'User.Subscriptions.APICredentials.ClientId' | transloco }}</label>\n <div class=\"input-group\">\n <input type=\"text\"\n id=\"user-subscription-api-client-id\"\n name=\"api_client_id\"\n class=\"form-control\"\n [value]=\"showApiClientId ? subscription?.api_client_id || ('User.Subscriptions.APICredentials.NoClientIdAvailable' | transloco) : '*************************'\"\n readonly />\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"toggleApiClientIdVisibility()\">\n {{ showApiClientId ? ('User.Subscriptions.APICredentials.Hide' | transloco) : ('User.Subscriptions.APICredentials.View' | transloco) }}\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-12 mt-3\">\n <div class=\"d-flex align-items-center gap-3\">\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"refreshApiTokens()\"\n [disabled]=\"refreshingTokens\">\n <i class=\"fas fa-sync-alt me-2\" [class.fa-spin]=\"refreshingTokens\"></i>\n {{ refreshingTokens ? ('User.Subscriptions.APICredentials.Refreshing' | transloco) : ('User.Subscriptions.APICredentials.RefreshTokens' | transloco) }}\n </button>\n <div class=\"d-flex align-items-center gap-2\">\n @if (subscription?.api_hits !== null) {\n <span class=\"text-muted\">{{ 'User.Subscriptions.APICredentials.ApiHits' | transloco }}:</span>\n <span class=\"fw-bold\">{{ subscription.api_hits | number }}</span>\n }\n @if (subscription?.api_hits_max !== null) {\n <span class=\"text-muted\">{{ 'User.Subscriptions.APICredentials.ApiHitsMax' | transloco }}:</span>\n <span class=\"fw-bold\">{{ subscription.api_hits_max | number }}</span>\n }\n <!-- Show utilization percentage when both values exist -->\n @if (subscription?.api_hits !== null || subscription?.api_hits_max !== null) {\n <span class=\"text-muted ms-2\">(</span>\n <span class=\"fw-bold\" [ngClass]=\"{\n 'text-success-muted': (subscription.api_hits / subscription.api_hits_max) <= 0.8,\n 'text-warning': (subscription.api_hits / subscription.api_hits_max) > 0.8 && (subscription.api_hits / subscription.api_hits_max) <= 0.9,\n 'text-danger': (subscription.api_hits / subscription.api_hits_max) > 0.9\n }\">\n {{ (subscription.api_hits / subscription.api_hits_max * 100) | number:'1.0-0' }}% consumed\n </span>\n <span class=\"text-muted\">)</span>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- 6. Security -->\n <div class=\"col-12 mt-5\">\n <h3>Security</h3>\n <p>\n While we'll add more security options in the future, please start by enforcing 2FA for all your subscription members.\n </p>\n </div>\n <div class=\"col-12 col-sm-3\">\n <pw-input-container label=\"Enforce 2FA\"\n [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Enforce2fa' | transloco\"\n name=\"enforce_2fa\"\n controlId=\"user-subscription-enforce_2fa\"\n [useAriaLabelledbyOnly]=\"true\">\n <ui-switch formControlName=\"enforce_2fa\"\n name=\"enforce_2fa\"\n [attr.aria-labelledby]=\"'user-subscription-enforce_2fa-label'\"> </ui-switch>\n </pw-input-container>\n </div>\n <div class=\"mb-3 col-12 text-end mt-3\">\n <button type=\"button\"\n class=\"btn btn-outline-default me-2\"\n routerLink=\"/account/subscriptions\">\n {{ 'Button.Cancel' | transloco }}\n </button>\n <button name=\"submit\"\n type=\"submit\"\n [buttonBusy]=\"busyButton\"\n class=\"btn btn-primary\">\n {{ 'Button.Submit' | transloco }}\n </button>\n </div>\n </form>\n}\n\n<ng-template #content\n 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\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile\n (imageSelectionEvent)=\"onImageSelection($event)\"\n aspectRatio=\"fullLogo\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n</ng-template>\n<ng-template #squaredLogoContent\n 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\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile\n (imageSelectionEvent)=\"uploadSquaredLogo($event)\"\n aspectRatio=\"auto\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n</ng-template>\n<pw-password-validation #modal\n(successEvent)=\"onPasswordValidation($event)\"> </pw-password-validation>\n", styles: [":host{display:block}:host>.row:first-of-type h3{color:var(--titles, #222);font-size:24px;font-weight:700;letter-spacing:-.01em;line-height:1.18}:host form .col-12>h3,:host .seats-section>.col-12>h3,:host .branding-section>.col-12>h3{border-top:1px solid #e2e5ea;color:var(--titles, #222);display:block;font-size:18px;font-weight:600;margin-top:32px;padding-top:24px}:host form>.col-12:first-child>h3{border-top:0;margin-top:0;padding-top:0}:host form .col-12>p,:host .seats-section>.col-12>p{color:#5a6473;font-size:15px;margin-bottom:16px}:host .row .text-center.mt-5{margin-top:16px!important;text-align:left!important}:host .image-container>h4{color:var(--titles, #222);font-size:14px;font-weight:600}: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}.sub-header{color:gray;font-size:20px;font-weight:600}@media only screen and (max-width:767px){.btns-row>[class*=col-]{flex:0 0 100%;max-width:100%}.btns-row .btn-primary{font-size:.8rem;margin-top:5px;padding:.375rem .5rem}}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "directive", type: i4.RbacAllowDirective, selector: "[rbacAllow]", inputs: ["rbacAllow"] }, { kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i6.NgxGpAutocompleteDirective, selector: "[ngx-gp-autocomplete]", inputs: ["options"], outputs: ["onAddressChange"], exportAs: ["ngx-places"] }, { kind: "component", type: i7.PasswordValidationComponent, selector: "pw-password-validation", inputs: ["confirmMessage", "destructive"], outputs: ["successEvent"] }, { kind: "component", type: i7$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i11$1.UiSwitchComponent, selector: "ui-switch", inputs: ["size", "color", "switchOffColor", "switchColor", "defaultBgColor", "defaultBoColor", "checkedLabel", "uncheckedLabel", "checkedTextColor", "uncheckedTextColor", "beforeChange", "ariaLabel", "checked", "disabled", "reverse", "loading"], outputs: ["change", "changeEvent", "valueChange"] }, { kind: "component", type: i7.NumberPickerComponent, selector: "pw-number-picker", inputs: ["min", "showTooltip", "tooltipText", "max", "step", "value", "pickStartAfter", "pickTimer", "prefix", "postfix", "placeholder", "buttonsOrientation", "size", "customClass", "mouseWheel", "arrowKeys", "inputReadOnly", "showUpButton", "showDownButton", "inputId"], outputs: ["valueChange", "minReached", "maxReached", "pickStarted", "pickStopped", "pickUpStarted", "pickUpStopped", "pickDownStarted", "pickDownStopped"] }, { kind: "component", type: i9.ProfileImageCropperComponent, selector: "pw-image-cropper", inputs: ["aspectRatio", "dynamicData"], outputs: ["imageSelectionEvent", "closeEvent", "fileChangeEvent"] }, { kind: "component", type: i7.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "controlId", "useAriaLabelledbyOnly", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "directive", type: i11.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.DecimalPipe, name: "number" }, { kind: "pipe", type: i5.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }, { kind: "pipe", type: i6$1.CurrencySymbolPipe, name: "currencySymbol" }] }); }
|
|
1591
1689
|
}
|
|
1592
1690
|
__decorate([
|
|
1593
1691
|
ValidateForm('form'),
|
|
@@ -1597,7 +1695,7 @@ __decorate([
|
|
|
1597
1695
|
], UserSubscriptionDetailsComponent.prototype, "onSaveDetails", null);
|
|
1598
1696
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: UserSubscriptionDetailsComponent, decorators: [{
|
|
1599
1697
|
type: Component,
|
|
1600
|
-
args: [{ standalone: false, template: "<!-- edit Subscription details page -->\n<div class=\"row\">\n <div class=\"col-12\">\n <h3 class=\"my-3\">{{ subscription?.organisation || subscription?.contact_name }}</h3>\n </div>\n</div>\n\n@if (subscription) {\n <form [formGroup]=\"form\"\n (ngSubmit)=\"onSaveDetails()\"\n class=\"row mt-4\"\n >\n <!-- 1. Contact details -->\n <div class=\"col-12\">\n <h3>Contact details</h3>\n </div>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.ContactName' | transloco\"\n class=\"col-md-6\"\n label=\"Contact Name\"\n name=\"contact_name\"\n controlId=\"user-subscription-contact_name\"\n errorMsg=\"Please enter Contact Name\">\n <input type=\"text\"\n id=\"user-subscription-contact_name\"\n class=\"form-control\"\n formControlName=\"contact_name\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.ContactEmail' | transloco\"\n class=\"col-md-6\"\n label=\"Contact Email\"\n name=\"contact_email\"\n controlId=\"user-subscription-contact_email\"\n errorMsg=\"Please enter Contact Email\">\n <input type=\"text\"\n id=\"user-subscription-contact_email\"\n class=\"form-control\"\n formControlName=\"contact_email\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Organization' | transloco\"\n class=\"col-md-6\"\n label=\"Organisation\"\n name=\"organisation\"\n controlId=\"user-subscription-organisation\"\n errorMsg=\"Please enter organisation\">\n <input type=\"text\"\n id=\"user-subscription-organisation\"\n class=\"form-control\"\n formControlName=\"organisation\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Phone' | transloco\"\n class=\"col-md-6\"\n label=\"Contact Tel\"\n name=\"contact_tel\"\n controlId=\"user-subscription-contact_tel\"\n errorMsg=\"Please enter Contact Telephone Number\">\n <input type=\"text\"\n id=\"user-subscription-contact_tel\"\n class=\"form-control\"\n formControlName=\"contact_tel\" />\n </pw-input-container>\n @if (countries$ | async; as countries) {\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Country' | transloco\"\n class=\"col-md-6\"\n label=\"Country\"\n name=\"country_code\"\n controlId=\"user-subscription-country_code\"\n [useAriaLabelledbyOnly]=\"true\"\n [isLeftTooltip]=\"true\"\n errorMsg=\"Please select a country\">\n <p-select\n [attr.aria-labelledby]=\"'user-subscription-country_code-label'\"\n [options]=\"countries\"\n optionLabel=\"name\"\n optionValue=\"code\"\n formControlName=\"country_code\"\n placeholder=\"Select Country\">\n </p-select>\n </pw-input-container>\n }\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Address' | transloco\"\n class=\"col-md-6\"\n label=\"Address\"\n name=\"address\"\n controlId=\"user-subscription-address\"\n [useAriaLabelledbyOnly]=\"true\"\n errorMsg=\"Please enter address\">\n <input ngx-gp-autocomplete\n id=\"user-subscription-address\"\n name=\"address\"\n class=\"form-control\"\n [attr.aria-labelledby]=\"'user-subscription-address-label'\"\n #places=\"ngx-places\"\n formControlName=\"address\"\n (onAddressChange)=\"handleAddressChange($event)\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.VatNumber' | transloco\"\n class=\"col-md-6\"\n label=\"GST/VAT Number\"\n name=\"tax_id\"\n controlId=\"user-subscription-tax_id\"\n errorMsg=\"Please enter GST/VAT Number\">\n <input type=\"text\"\n id=\"user-subscription-tax_id\"\n class=\"form-control\"\n formControlName=\"tax_id\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.CompanyUrl' | transloco\"\n class=\"col-md-6\"\n label=\"Company URL\"\n name=\"company_url\"\n controlId=\"user-subscription-company_url\"\n errorMsg=\"Please enter company url\">\n <input type=\"text\"\n id=\"user-subscription-company_url\"\n class=\"form-control\"\n formControlName=\"company_url\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.InvoiceRecipientEmails' | transloco\"\n class=\"col-md-6\"\n label=\"Invoice Recipient Emails\"\n name=\"invoice_recipient_emails\"\n controlId=\"user-subscription-invoice_recipient_emails\"\n errorMsg=\"Please enter valid email addresses separated by commas\">\n <input type=\"text\"\n id=\"user-subscription-invoice_recipient_emails\"\n class=\"form-control\"\n formControlName=\"invoice_recipient_emails\"\n placeholder=\"email1@example.com,email2@example.com\" />\n </pw-input-container>\n\n <!-- 2. Branding / Logos -->\n <div class=\"col-12\">\n <div class=\"row branding-section\">\n <div class=\"col-12\">\n <h3>Branding</h3>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-md-6\">\n <div class=\"text-center mt-5\">\n <div class=\"image-container\">\n <h4 class=\"mb-2\">{{ 'User.Subscriptions.FullLogo' | transloco }}\n <span class=\"tooltip-wrap ms-1\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.FullLogo'|transloco\"\n [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\"\n alt=\"full logo\"\n class=\"image full-logo\"\n role=\"presentation\"\n (error)=\"fullLogoBroken = true\" />\n <div class=\"overlay mt-2\"\n (keydown.enter)=\"openModal(content)\"\n (click)=\"openModal(content)\">\n <div class=\"overlay-text\">\n <a aria-label=\"Navigate to Target\">{{ 'User.Profile.Change' | transloco }}</a>\n </div>\n </div>\n } @else {\n <div class=\"logo-dropzone full-dropzone\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Upload full logo\"\n (keydown.enter)=\"openModal(content)\"\n (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-center mt-5\">\n <div class=\"image-container\">\n <h4 class=\"mb-2\">Squared Logo\n <span class=\"tooltip-wrap ms-1\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.SquaredLogo'|transloco\"\n [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\"\n alt=\"Squared Presentation\"\n class=\"squared_logo\"\n role=\"presentation\"\n (error)=\"squaredLogoBroken = true\" />\n <div class=\"overlay mt-2\"\n (keydown.enter)=\"openModal(squaredLogoContent)\"\n (click)=\"openModal(squaredLogoContent)\">\n <div class=\"overlay-text\">\n <a aria-label=\"Navigate to Target\">{{ 'User.Profile.Change' | transloco }}</a>\n </div>\n </div>\n } @else {\n <div class=\"logo-dropzone squared-dropzone\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Upload squared logo\"\n (keydown.enter)=\"openModal(squaredLogoContent)\"\n (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 </div>\n\n <!-- 3. Social Media -->\n <ng-container *rbacAllow=\"'SubscriptionSuperAdmin'\">\n <div class=\"col-12\">\n <h3>Social Media</h3>\n <p>\n Any of the social media handles that you set here will appear in the footer of emails going out to your child subscriptions.\n </p>\n </div>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.FacebookHandle' | transloco\"\n class=\"col-md-6\"\n label=\"Facebook handle\"\n name=\"facebook_handle\"\n controlId=\"user-subscription-facebook_handle\"\n errorMsg=\"Please enter facebook id\">\n <input type=\"text\"\n id=\"user-subscription-facebook_handle\"\n class=\"form-control\"\n formControlName=\"facebook_handle\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.TwitterHandle' | transloco\"\n class=\"col-md-6\"\n label=\"Twitter handle\"\n name=\"twitter_handle\"\n controlId=\"user-subscription-twitter_handle\"\n errorMsg=\"Please enter twitter id\">\n <input type=\"text\"\n id=\"user-subscription-twitter_handle\"\n class=\"form-control\"\n formControlName=\"twitter_handle\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.LinkedinHandle' | transloco\"\n class=\"col-md-6\"\n label=\"Linkedin handle\"\n name=\"linkedin_handle\"\n controlId=\"user-subscription-linkedin_handle\"\n errorMsg=\"Please enter linkedin id\">\n <input type=\"text\"\n id=\"user-subscription-linkedin_handle\"\n class=\"form-control\"\n formControlName=\"linkedin_handle\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.RedditHandle' | transloco\"\n class=\"col-md-6\"\n label=\"Reddit handle\"\n name=\"reddit_handle\"\n controlId=\"user-subscription-reddit_handle\"\n errorMsg=\"Please enter reddit id\">\n <input type=\"text\"\n id=\"user-subscription-reddit_handle\"\n class=\"form-control\"\n formControlName=\"reddit_handle\" />\n </pw-input-container>\n </ng-container>\n\n <!-- 4. Seats -->\n <div class=\"col-12\">\n <div class=\"row seats-section\">\n <div class=\"col-12\">\n <h3>Seats</h3>\n <p>Changing the number of seats updates your subscription cost.</p>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-12\">\n @if (subscription?.trial_subscription && subscription?.calculated_price) {\n <small\n class=\"text-danger\">Upgrade to be able to update your purchased seats</small>\n }\n </div>\n </div>\n <div class=\"row btns-row align-items-center\">\n @if (subscription) {\n <div class=\"col-md-3 col-8\"\n >\n <label for=\"user-subscription-seats\" class=\"visually-hidden\">{{ 'User.Subscriptions.Tooltip.Seats' | transloco }}</label>\n <pw-number-picker [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Seats'|transloco\"\n inputId=\"user-subscription-seats\"\n name=\"number-picker\"\n [(value)]=\"units\"\n [min]=\"subscription?.min_units||subscription?.products[0].min_units\"\n [max]=\"subscription?.products[0].max_units\"\n step=\"1\"\n postfix=\"seats\"\n placeholder=\"Total Licences\"\n [inputReadOnly]=\"subscription?.products[0].trial_subscription\"\n [showUpButton]=\"!subscription?.products[0].trial_subscription\"\n [showDownButton]=\"!subscription?.products[0].trial_subscription\"\n size=\"small\"\n pickStartAfter=\"500\"\n pickTimer=\"100\"\n [arrowKeys]=\"true\"\n (minReached)=\"onMinReached($event)\"\n (maxReached)=\"onMaxReached($event)\"\n (valueChange)=\"onUnitChange($event)\">\n </pw-number-picker>\n </div>\n }\n\n @if (subscription) {\n <div class=\"col-md-3 col-4 p-1\"\n >\n @if (!subscription?.products[0].trial_subscription && allowUpdate) {\n <button type=\"button\"\n class=\"btn btn-primary\"\n (click)=\"updateUnits()\">\n {{ 'User.Subscriptions.UpdateUnits' | transloco }}\n </button>\n } @else {\n <div>\n @if (subscription?.products[0].trial_subscription) {\n <small class=\"text-muted\"\n >Update seats is available only to paid subscriptions</small>\n }\n </div>\n }\n </div>\n }\n\n @if (hasUnitChanged) {\n <div class=\"col-12 col-md-6\"\n >\n <table class=\"table table-borderless table-sm\"\n aria-describedby=\"Product details\">\n <thead>\n <tr>\n <th scope=\"true\">Product</th>\n <th scope=\"true\">Price per seat <span>({{subscription?.products[0]?.currency|currencySymbol}})</span></th>\n <th scope=\"true\">Seats</th>\n </tr>\n </thead>\n <tbody>\n @for (product of subscription.products; track trackByProduct($index, product)) {\n <tr>\n <td>{{ product.name }}</td>\n <td>{{ product.price_per_unit / 100 }}</td>\n <td>{{ units }}</td>\n </tr>\n }\n </tbody>\n </table>\n <p>\n If you proceed, the new cost for your subscription will be\n <strong>{{ totalAmount()| currency: subscription?.products[0]?.currency:'symbol-narrow'}}</strong>\n </p>\n </div>\n }\n </div>\n </div>\n\n <!-- 5. API & MCP Credentials -->\n @if (subscription?.api_hits_max > 0) {\n <div class=\"col-12\">\n <h3>{{ 'User.Subscriptions.APICredentials.Title' | transloco }}</h3>\n <p>\n These credentials authenticate both REST API and MCP (Model Context Protocol) requests, and must be used together with the user tokens defined on your Account page.\n </p>\n </div>\n <div class=\"col-md-6\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"user-subscription-api-token\">\n {{ 'User.Subscriptions.APICredentials.AccessToken' | transloco }}\n <span class=\"tooltip-wrap ms-1\"\n pTooltip=\"The subscription token has been discontinued in favour of the user token defined on your Account page.\"\n [appendTo]=\"'body'\"\n [tooltipPosition]=\"'top'\">\n <i class=\"far fa-info-circle text-muted\"></i>\n </span>\n </label>\n <div class=\"input-group\">\n <input type=\"text\"\n id=\"user-subscription-api-token\"\n name=\"api_token\"\n class=\"form-control\"\n [value]=\"showApiToken ? subscription?.api_access_token || ('User.Subscriptions.APICredentials.NoTokenAvailable' | transloco) : '*************************'\"\n readonly />\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"toggleApiTokenVisibility()\">\n {{ showApiToken ? ('User.Subscriptions.APICredentials.Hide' | transloco) : ('User.Subscriptions.APICredentials.View' | transloco) }}\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-md-6\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"user-subscription-api-client-id\">{{ 'User.Subscriptions.APICredentials.ClientId' | transloco }}</label>\n <div class=\"input-group\">\n <input type=\"text\"\n id=\"user-subscription-api-client-id\"\n name=\"api_client_id\"\n class=\"form-control\"\n [value]=\"showApiClientId ? subscription?.api_client_id || ('User.Subscriptions.APICredentials.NoClientIdAvailable' | transloco) : '*************************'\"\n readonly />\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"toggleApiClientIdVisibility()\">\n {{ showApiClientId ? ('User.Subscriptions.APICredentials.Hide' | transloco) : ('User.Subscriptions.APICredentials.View' | transloco) }}\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-12 mt-3\">\n <div class=\"d-flex align-items-center gap-3\">\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"refreshApiTokens()\"\n [disabled]=\"refreshingTokens\">\n <i class=\"fas fa-sync-alt me-2\" [class.fa-spin]=\"refreshingTokens\"></i>\n {{ refreshingTokens ? ('User.Subscriptions.APICredentials.Refreshing' | transloco) : ('User.Subscriptions.APICredentials.RefreshTokens' | transloco) }}\n </button>\n <div class=\"d-flex align-items-center gap-2\">\n @if (subscription?.api_hits !== null) {\n <span class=\"text-muted\">{{ 'User.Subscriptions.APICredentials.ApiHits' | transloco }}:</span>\n <span class=\"fw-bold\">{{ subscription.api_hits | number }}</span>\n }\n @if (subscription?.api_hits_max !== null) {\n <span class=\"text-muted\">{{ 'User.Subscriptions.APICredentials.ApiHitsMax' | transloco }}:</span>\n <span class=\"fw-bold\">{{ subscription.api_hits_max | number }}</span>\n }\n <!-- Show utilization percentage when both values exist -->\n @if (subscription?.api_hits !== null || subscription?.api_hits_max !== null) {\n <span class=\"text-muted ms-2\">(</span>\n <span class=\"fw-bold\" [ngClass]=\"{\n 'text-success': (subscription.api_hits / subscription.api_hits_max) <= 0.8,\n 'text-warning': (subscription.api_hits / subscription.api_hits_max) > 0.8 && (subscription.api_hits / subscription.api_hits_max) <= 0.9,\n 'text-danger': (subscription.api_hits / subscription.api_hits_max) > 0.9\n }\">\n {{ (subscription.api_hits / subscription.api_hits_max * 100) | number:'1.0-0' }}% consumed\n </span>\n <span class=\"text-muted\">)</span>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- 6. Security -->\n <div class=\"col-12 mt-5\">\n <h3>Security</h3>\n <p>\n While we'll add more security options in the future, please start by enforcing 2FA for all your subscription members.\n </p>\n </div>\n <div class=\"col-12 col-sm-3\">\n <pw-input-container label=\"Enforce 2FA\"\n [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Enforce2fa' | transloco\"\n name=\"enforce_2fa\"\n controlId=\"user-subscription-enforce_2fa\"\n [useAriaLabelledbyOnly]=\"true\">\n <ui-switch formControlName=\"enforce_2fa\"\n name=\"enforce_2fa\"\n [attr.aria-labelledby]=\"'user-subscription-enforce_2fa-label'\"> </ui-switch>\n </pw-input-container>\n </div>\n <div class=\"mb-3 col-12 text-end mt-3\">\n <button type=\"button\"\n class=\"btn btn-outline-default me-2\"\n routerLink=\"/account/subscriptions\">\n {{ 'Button.Cancel' | transloco }}\n </button>\n <button name=\"submit\"\n type=\"submit\"\n [buttonBusy]=\"busyButton\"\n class=\"btn btn-primary\">\n {{ 'Button.Submit' | transloco }}\n </button>\n </div>\n </form>\n}\n\n<ng-template #content\n 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\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile\n (imageSelectionEvent)=\"onImageSelection($event)\"\n aspectRatio=\"fullLogo\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n</ng-template>\n<ng-template #squaredLogoContent\n 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\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile\n (imageSelectionEvent)=\"uploadSquaredLogo($event)\"\n aspectRatio=\"auto\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n</ng-template>\n<pw-password-validation #modal\n(successEvent)=\"onPasswordValidation($event)\"> </pw-password-validation>\n", styles: [":host{display:block}:host>.row:first-of-type h3{color:var(--titles, #222);font-size:24px;font-weight:700;letter-spacing:-.01em;line-height:1.18}:host form .col-12>h3,:host .seats-section>.col-12>h3,:host .branding-section>.col-12>h3{border-top:1px solid #e2e5ea;color:var(--titles, #222);display:block;font-size:18px;font-weight:600;margin-top:32px;padding-top:24px}:host form>.col-12:first-child>h3{border-top:0;margin-top:0;padding-top:0}:host form .col-12>p,:host .seats-section>.col-12>p{color:#5a6473;font-size:15px;margin-bottom:16px}:host .row .text-center.mt-5{margin-top:16px!important;text-align:left!important}:host .image-container>h4{color:var(--titles, #222);font-size:14px;font-weight:600}: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}.sub-header{color:gray;font-size:20px;font-weight:600}@media only screen and (max-width:767px){.btns-row>[class*=col-]{flex:0 0 100%;max-width:100%}.btns-row .btn-primary{font-size:.8rem;margin-top:5px;padding:.375rem .5rem}}\n"] }]
|
|
1698
|
+
args: [{ standalone: false, template: "<!-- edit Subscription details page -->\n<div class=\"row\">\n <div class=\"col-12\">\n <h3 class=\"my-3\">{{ subscription?.organisation || subscription?.contact_name }}</h3>\n </div>\n</div>\n\n@if (subscription) {\n <form [formGroup]=\"form\"\n (ngSubmit)=\"onSaveDetails()\"\n class=\"row mt-4\"\n >\n <!-- 1. Contact details -->\n <div class=\"col-12\">\n <h3>Contact details</h3>\n </div>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.ContactName' | transloco\"\n class=\"col-md-6\"\n label=\"Contact Name\"\n name=\"contact_name\"\n controlId=\"user-subscription-contact_name\"\n errorMsg=\"Please enter Contact Name\">\n <input type=\"text\"\n id=\"user-subscription-contact_name\"\n class=\"form-control\"\n formControlName=\"contact_name\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.ContactEmail' | transloco\"\n class=\"col-md-6\"\n label=\"Contact Email\"\n name=\"contact_email\"\n controlId=\"user-subscription-contact_email\"\n errorMsg=\"Please enter Contact Email\">\n <input type=\"text\"\n id=\"user-subscription-contact_email\"\n class=\"form-control\"\n formControlName=\"contact_email\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Organization' | transloco\"\n class=\"col-md-6\"\n label=\"Organisation\"\n name=\"organisation\"\n controlId=\"user-subscription-organisation\"\n errorMsg=\"Please enter organisation\">\n <input type=\"text\"\n id=\"user-subscription-organisation\"\n class=\"form-control\"\n formControlName=\"organisation\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Phone' | transloco\"\n class=\"col-md-6\"\n label=\"Contact Tel\"\n name=\"contact_tel\"\n controlId=\"user-subscription-contact_tel\"\n errorMsg=\"Please enter Contact Telephone Number\">\n <input type=\"text\"\n id=\"user-subscription-contact_tel\"\n class=\"form-control\"\n formControlName=\"contact_tel\" />\n </pw-input-container>\n @if (countries$ | async; as countries) {\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Country' | transloco\"\n class=\"col-md-6\"\n label=\"Country\"\n name=\"country_code\"\n controlId=\"user-subscription-country_code\"\n [useAriaLabelledbyOnly]=\"true\"\n [isLeftTooltip]=\"true\"\n errorMsg=\"Please select a country\">\n <p-select\n [attr.aria-labelledby]=\"'user-subscription-country_code-label'\"\n [options]=\"countries\"\n optionLabel=\"name\"\n optionValue=\"code\"\n formControlName=\"country_code\"\n placeholder=\"Select Country\">\n </p-select>\n </pw-input-container>\n }\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Address' | transloco\"\n class=\"col-md-6\"\n label=\"Address\"\n name=\"address\"\n controlId=\"user-subscription-address\"\n [useAriaLabelledbyOnly]=\"true\"\n errorMsg=\"Please enter address\">\n <input ngx-gp-autocomplete\n id=\"user-subscription-address\"\n name=\"address\"\n class=\"form-control\"\n [attr.aria-labelledby]=\"'user-subscription-address-label'\"\n #places=\"ngx-places\"\n formControlName=\"address\"\n (onAddressChange)=\"handleAddressChange($event)\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.VatNumber' | transloco\"\n class=\"col-md-6\"\n label=\"GST/VAT Number\"\n name=\"tax_id\"\n controlId=\"user-subscription-tax_id\"\n errorMsg=\"Please enter GST/VAT Number\">\n <input type=\"text\"\n id=\"user-subscription-tax_id\"\n class=\"form-control\"\n formControlName=\"tax_id\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.CompanyUrl' | transloco\"\n class=\"col-md-6\"\n label=\"Company URL\"\n name=\"company_url\"\n controlId=\"user-subscription-company_url\"\n errorMsg=\"Please enter company url\">\n <input type=\"text\"\n id=\"user-subscription-company_url\"\n class=\"form-control\"\n formControlName=\"company_url\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.InvoiceRecipientEmails' | transloco\"\n class=\"col-md-6\"\n label=\"Invoice Recipient Emails\"\n name=\"invoice_recipient_emails\"\n controlId=\"user-subscription-invoice_recipient_emails\"\n errorMsg=\"Please enter valid email addresses separated by commas\">\n <input type=\"text\"\n id=\"user-subscription-invoice_recipient_emails\"\n class=\"form-control\"\n formControlName=\"invoice_recipient_emails\"\n placeholder=\"email1@example.com,email2@example.com\" />\n </pw-input-container>\n\n <!-- 2. Branding / Logos -->\n <div class=\"col-12\">\n <div class=\"row branding-section\">\n <div class=\"col-12\">\n <h3>Branding</h3>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-md-6\">\n <div class=\"text-center mt-5\">\n <div class=\"image-container\">\n <h4 class=\"mb-2\">{{ 'User.Subscriptions.FullLogo' | transloco }}\n <span class=\"tooltip-wrap ms-1\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.FullLogo'|transloco\"\n [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\"\n alt=\"full logo\"\n class=\"image full-logo\"\n role=\"presentation\"\n (error)=\"fullLogoBroken = true\" />\n <div class=\"overlay mt-2\"\n (keydown.enter)=\"openModal(content)\"\n (click)=\"openModal(content)\">\n <div class=\"overlay-text\">\n <a aria-label=\"Navigate to Target\">{{ 'User.Profile.Change' | transloco }}</a>\n </div>\n </div>\n } @else {\n <div class=\"logo-dropzone full-dropzone\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Upload full logo\"\n (keydown.enter)=\"openModal(content)\"\n (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-center mt-5\">\n <div class=\"image-container\">\n <h4 class=\"mb-2\">Squared Logo\n <span class=\"tooltip-wrap ms-1\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.SquaredLogo'|transloco\"\n [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\"\n alt=\"Squared Presentation\"\n class=\"squared_logo\"\n role=\"presentation\"\n (error)=\"squaredLogoBroken = true\" />\n <div class=\"overlay mt-2\"\n (keydown.enter)=\"openModal(squaredLogoContent)\"\n (click)=\"openModal(squaredLogoContent)\">\n <div class=\"overlay-text\">\n <a aria-label=\"Navigate to Target\">{{ 'User.Profile.Change' | transloco }}</a>\n </div>\n </div>\n } @else {\n <div class=\"logo-dropzone squared-dropzone\"\n role=\"button\"\n tabindex=\"0\"\n aria-label=\"Upload squared logo\"\n (keydown.enter)=\"openModal(squaredLogoContent)\"\n (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 </div>\n\n <!-- 3. Social Media -->\n <ng-container *rbacAllow=\"'SubscriptionSuperAdmin'\">\n <div class=\"col-12\">\n <h3>Social Media</h3>\n <p>\n Any of the social media handles that you set here will appear in the footer of emails going out to your child subscriptions.\n </p>\n </div>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.FacebookHandle' | transloco\"\n class=\"col-md-6\"\n label=\"Facebook handle\"\n name=\"facebook_handle\"\n controlId=\"user-subscription-facebook_handle\"\n errorMsg=\"Please enter facebook id\">\n <input type=\"text\"\n id=\"user-subscription-facebook_handle\"\n class=\"form-control\"\n formControlName=\"facebook_handle\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.TwitterHandle' | transloco\"\n class=\"col-md-6\"\n label=\"Twitter handle\"\n name=\"twitter_handle\"\n controlId=\"user-subscription-twitter_handle\"\n errorMsg=\"Please enter twitter id\">\n <input type=\"text\"\n id=\"user-subscription-twitter_handle\"\n class=\"form-control\"\n formControlName=\"twitter_handle\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.LinkedinHandle' | transloco\"\n class=\"col-md-6\"\n label=\"Linkedin handle\"\n name=\"linkedin_handle\"\n controlId=\"user-subscription-linkedin_handle\"\n errorMsg=\"Please enter linkedin id\">\n <input type=\"text\"\n id=\"user-subscription-linkedin_handle\"\n class=\"form-control\"\n formControlName=\"linkedin_handle\" />\n </pw-input-container>\n <pw-input-container [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.RedditHandle' | transloco\"\n class=\"col-md-6\"\n label=\"Reddit handle\"\n name=\"reddit_handle\"\n controlId=\"user-subscription-reddit_handle\"\n errorMsg=\"Please enter reddit id\">\n <input type=\"text\"\n id=\"user-subscription-reddit_handle\"\n class=\"form-control\"\n formControlName=\"reddit_handle\" />\n </pw-input-container>\n </ng-container>\n\n <!-- 4. Seats -->\n <div class=\"col-12\">\n <div class=\"row seats-section\">\n <div class=\"col-12\">\n <h3>Seats</h3>\n <p>Changing the number of seats updates your subscription cost.</p>\n </div>\n </div>\n <div class=\"row\">\n <div class=\"col-12\">\n @if (subscription?.trial_subscription && subscription?.calculated_price) {\n <small\n class=\"text-danger\">Upgrade to be able to update your purchased seats</small>\n }\n </div>\n </div>\n <div class=\"row btns-row align-items-center\">\n @if (subscription) {\n <div class=\"col-md-3 col-8\"\n >\n <label for=\"user-subscription-seats\" class=\"visually-hidden\">{{ 'User.Subscriptions.Tooltip.Seats' | transloco }}</label>\n <pw-number-picker [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Seats'|transloco\"\n inputId=\"user-subscription-seats\"\n name=\"number-picker\"\n [(value)]=\"units\"\n [min]=\"subscription?.min_units||subscription?.products[0].min_units\"\n [max]=\"subscription?.products[0].max_units\"\n step=\"1\"\n postfix=\"seats\"\n placeholder=\"Total Licences\"\n [inputReadOnly]=\"subscription?.products[0].trial_subscription\"\n [showUpButton]=\"!subscription?.products[0].trial_subscription\"\n [showDownButton]=\"!subscription?.products[0].trial_subscription\"\n size=\"small\"\n pickStartAfter=\"500\"\n pickTimer=\"100\"\n [arrowKeys]=\"true\"\n (minReached)=\"onMinReached($event)\"\n (maxReached)=\"onMaxReached($event)\"\n (valueChange)=\"onUnitChange($event)\">\n </pw-number-picker>\n </div>\n }\n\n @if (subscription) {\n <div class=\"col-md-3 col-4 p-1\"\n >\n @if (!subscription?.products[0].trial_subscription && allowUpdate) {\n <button type=\"button\"\n class=\"btn btn-primary\"\n (click)=\"updateUnits()\">\n {{ 'User.Subscriptions.UpdateUnits' | transloco }}\n </button>\n } @else {\n <div>\n @if (subscription?.products[0].trial_subscription) {\n <small class=\"text-muted\"\n >Update seats is available only to paid subscriptions</small>\n }\n </div>\n }\n </div>\n }\n\n @if (hasUnitChanged) {\n <div class=\"col-12 col-md-6\"\n >\n <table class=\"table table-borderless table-sm\"\n aria-describedby=\"Product details\">\n <thead>\n <tr>\n <th scope=\"true\">Product</th>\n <th scope=\"true\">Price per seat <span>({{subscription?.products[0]?.currency|currencySymbol}})</span></th>\n <th scope=\"true\">Seats</th>\n </tr>\n </thead>\n <tbody>\n @for (product of subscription.products; track trackByProduct($index, product)) {\n <tr>\n <td>{{ product.name }}</td>\n <td>{{ product.price_per_unit / 100 }}</td>\n <td>{{ units }}</td>\n </tr>\n }\n </tbody>\n </table>\n <p>\n If you proceed, the new cost for your subscription will be\n <strong>{{ totalAmount()| currency: subscription?.products[0]?.currency:'symbol-narrow'}}</strong>\n </p>\n </div>\n }\n </div>\n </div>\n\n <!-- 5. API & MCP Credentials -->\n @if (subscription?.api_hits_max > 0) {\n <div class=\"col-12\">\n <h3>{{ 'User.Subscriptions.APICredentials.Title' | transloco }}</h3>\n <p>\n These credentials authenticate both REST API and MCP (Model Context Protocol) requests, and must be used together with the user tokens defined on your Account page.\n </p>\n </div>\n <div class=\"col-md-6\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"user-subscription-api-token\">\n {{ 'User.Subscriptions.APICredentials.AccessToken' | transloco }}\n <span class=\"tooltip-wrap ms-1\"\n pTooltip=\"The subscription token has been discontinued in favour of the user token defined on your Account page.\"\n [appendTo]=\"'body'\"\n [tooltipPosition]=\"'top'\">\n <i class=\"far fa-info-circle text-muted\"></i>\n </span>\n </label>\n <div class=\"input-group\">\n <input type=\"text\"\n id=\"user-subscription-api-token\"\n name=\"api_token\"\n class=\"form-control\"\n [value]=\"showApiToken ? subscription?.api_access_token || ('User.Subscriptions.APICredentials.NoTokenAvailable' | transloco) : '*************************'\"\n readonly />\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"toggleApiTokenVisibility()\">\n {{ showApiToken ? ('User.Subscriptions.APICredentials.Hide' | transloco) : ('User.Subscriptions.APICredentials.View' | transloco) }}\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-md-6\">\n <div class=\"form-group\">\n <label class=\"form-label\" for=\"user-subscription-api-client-id\">{{ 'User.Subscriptions.APICredentials.ClientId' | transloco }}</label>\n <div class=\"input-group\">\n <input type=\"text\"\n id=\"user-subscription-api-client-id\"\n name=\"api_client_id\"\n class=\"form-control\"\n [value]=\"showApiClientId ? subscription?.api_client_id || ('User.Subscriptions.APICredentials.NoClientIdAvailable' | transloco) : '*************************'\"\n readonly />\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"toggleApiClientIdVisibility()\">\n {{ showApiClientId ? ('User.Subscriptions.APICredentials.Hide' | transloco) : ('User.Subscriptions.APICredentials.View' | transloco) }}\n </button>\n </div>\n </div>\n </div>\n <div class=\"col-12 mt-3\">\n <div class=\"d-flex align-items-center gap-3\">\n <button type=\"button\"\n class=\"btn btn-outline-secondary\"\n (click)=\"refreshApiTokens()\"\n [disabled]=\"refreshingTokens\">\n <i class=\"fas fa-sync-alt me-2\" [class.fa-spin]=\"refreshingTokens\"></i>\n {{ refreshingTokens ? ('User.Subscriptions.APICredentials.Refreshing' | transloco) : ('User.Subscriptions.APICredentials.RefreshTokens' | transloco) }}\n </button>\n <div class=\"d-flex align-items-center gap-2\">\n @if (subscription?.api_hits !== null) {\n <span class=\"text-muted\">{{ 'User.Subscriptions.APICredentials.ApiHits' | transloco }}:</span>\n <span class=\"fw-bold\">{{ subscription.api_hits | number }}</span>\n }\n @if (subscription?.api_hits_max !== null) {\n <span class=\"text-muted\">{{ 'User.Subscriptions.APICredentials.ApiHitsMax' | transloco }}:</span>\n <span class=\"fw-bold\">{{ subscription.api_hits_max | number }}</span>\n }\n <!-- Show utilization percentage when both values exist -->\n @if (subscription?.api_hits !== null || subscription?.api_hits_max !== null) {\n <span class=\"text-muted ms-2\">(</span>\n <span class=\"fw-bold\" [ngClass]=\"{\n 'text-success-muted': (subscription.api_hits / subscription.api_hits_max) <= 0.8,\n 'text-warning': (subscription.api_hits / subscription.api_hits_max) > 0.8 && (subscription.api_hits / subscription.api_hits_max) <= 0.9,\n 'text-danger': (subscription.api_hits / subscription.api_hits_max) > 0.9\n }\">\n {{ (subscription.api_hits / subscription.api_hits_max * 100) | number:'1.0-0' }}% consumed\n </span>\n <span class=\"text-muted\">)</span>\n }\n </div>\n </div>\n </div>\n }\n\n <!-- 6. Security -->\n <div class=\"col-12 mt-5\">\n <h3>Security</h3>\n <p>\n While we'll add more security options in the future, please start by enforcing 2FA for all your subscription members.\n </p>\n </div>\n <div class=\"col-12 col-sm-3\">\n <pw-input-container label=\"Enforce 2FA\"\n [showTooltip]=\"true\"\n [tooltipText]=\"'User.Subscriptions.Tooltip.Enforce2fa' | transloco\"\n name=\"enforce_2fa\"\n controlId=\"user-subscription-enforce_2fa\"\n [useAriaLabelledbyOnly]=\"true\">\n <ui-switch formControlName=\"enforce_2fa\"\n name=\"enforce_2fa\"\n [attr.aria-labelledby]=\"'user-subscription-enforce_2fa-label'\"> </ui-switch>\n </pw-input-container>\n </div>\n <div class=\"mb-3 col-12 text-end mt-3\">\n <button type=\"button\"\n class=\"btn btn-outline-default me-2\"\n routerLink=\"/account/subscriptions\">\n {{ 'Button.Cancel' | transloco }}\n </button>\n <button name=\"submit\"\n type=\"submit\"\n [buttonBusy]=\"busyButton\"\n class=\"btn btn-primary\">\n {{ 'Button.Submit' | transloco }}\n </button>\n </div>\n </form>\n}\n\n<ng-template #content\n 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\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile\n (imageSelectionEvent)=\"onImageSelection($event)\"\n aspectRatio=\"fullLogo\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n</ng-template>\n<ng-template #squaredLogoContent\n 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\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <small> {{ 'User.Profile.PictureMessage' | transloco }}</small>\n <pw-image-cropper #profile\n (imageSelectionEvent)=\"uploadSquaredLogo($event)\"\n aspectRatio=\"auto\"\n (closeEvent)=\"onClose()\">\n </pw-image-cropper>\n </div>\n</ng-template>\n<pw-password-validation #modal\n(successEvent)=\"onPasswordValidation($event)\"> </pw-password-validation>\n", styles: [":host{display:block}:host>.row:first-of-type h3{color:var(--titles, #222);font-size:24px;font-weight:700;letter-spacing:-.01em;line-height:1.18}:host form .col-12>h3,:host .seats-section>.col-12>h3,:host .branding-section>.col-12>h3{border-top:1px solid #e2e5ea;color:var(--titles, #222);display:block;font-size:18px;font-weight:600;margin-top:32px;padding-top:24px}:host form>.col-12:first-child>h3{border-top:0;margin-top:0;padding-top:0}:host form .col-12>p,:host .seats-section>.col-12>p{color:#5a6473;font-size:15px;margin-bottom:16px}:host .row .text-center.mt-5{margin-top:16px!important;text-align:left!important}:host .image-container>h4{color:var(--titles, #222);font-size:14px;font-weight:600}: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}.sub-header{color:gray;font-size:20px;font-weight:600}@media only screen and (max-width:767px){.btns-row>[class*=col-]{flex:0 0 100%;max-width:100%}.btns-row .btn-primary{font-size:.8rem;margin-top:5px;padding:.375rem .5rem}}\n"] }]
|
|
1601
1699
|
}], ctorParameters: () => [{ type: i2.UntypedFormBuilder }, { type: i1$2.GeoService }, { type: i1$1.NgbModal }, { type: i1$2.SubscriptionService }, { type: i4$2.Store }, { type: i0.Injector }, { type: i0.ChangeDetectorRef }], propDecorators: { modal: [{
|
|
1602
1700
|
type: ViewChild,
|
|
1603
1701
|
args: ['modal', { static: true }]
|
|
@@ -1806,11 +1904,11 @@ class UserSubscriptionListComponent extends AppBaseComponent {
|
|
|
1806
1904
|
super.ngOnDestroy();
|
|
1807
1905
|
}
|
|
1808
1906
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: UserSubscriptionListComponent, deps: [{ token: i1$2.SubscriptionService }, { token: i2$1.AdminService }, { token: i1$1.NgbModal }, { token: i4$2.Store }, { token: i5$1.Clipboard }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1809
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: UserSubscriptionListComponent, isStandalone: false, selector: "pw-user-subscriptions-list", viewQueries: [{ propertyName: "menu", first: true, predicate: ["menuItems"], descendants: true }, { propertyName: "changeSubscriptionRef", first: true, predicate: AddSubscriptionComponent, descendants: true }, { propertyName: "passwordValidationModalForAccountDelete", first: true, predicate: ["passwordValidationModalForAccountDelete"], descendants: true }, { propertyName: "passwordValidationModalForKey", first: true, predicate: ["passwordValidationModalForKey"], descendants: true }, { propertyName: "passwordValidationForUnsubscribe", first: true, predicate: ["passwordValidationForUnsubscribe"], descendants: true }, { propertyName: "cancelSubscriptionModal", first: true, predicate: ["cancelSubscriptionModal"], descendants: true }], usesInheritance: true, ngImport: i0, template: "@if (!showTos) {\n <!-- Subscriptions Tab Content -->\n @if (!editing && !isAddNew) {\n <div class=\"row\">\n <div class=\"col-12\">\n <h2>Your Subscriptions</h2>\n <p>You'll find in this section the summary of your subscriptions.</p>\n </div>\n </div>\n }\n <!-- Subscribed Product Cards -->\n @if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n @if (\n !editing && !isAddNew && !isUpdatePayment && isLoaded && subscribedSubscriptions.length\n ) {\n <div class=\"row\"\n >\n @for (subscription of subscribedSubscriptions; track trackBySubscription($index, subscription)) {\n <div class=\"col-12 col-md-6 my-3\"\n >\n <div class=\"subscription-details mb-4\">\n <div class=\"subscription-summary d-flex flex-wrap justify-content-between align-items-start gap-2 mb-3\">\n <div class=\"subscription-summary__info\">\n <div>\n <strong>Organisation:</strong>\n {{ subscription.organisation ? subscription.organisation : subscription.contact_name }}\n </div>\n <div>\n <strong>{{ 'User.Subscriptions.TotalPriceExclTax' | transloco }}:</strong>\n @if (subscription.calculated_price) {\n {{ subscription.products[0]?.currency }} {{ subscription.calculated_price / 100 | number:'1.2-2' }}\n {{ subscription.products[0].trial_subscription ? '(After Trial)' : '' }}\n } @else {\n Free\n }\n </div>\n <div>\n <strong>{{ 'User.Subscriptions.SeatsInUse' | transloco }}:</strong>\n {{ subscription.units_in_use || 1 }} / {{ subscription.purchased_units }}\n @if (subscription.purchased_units) {\n <span class=\"seats-usage\"\n [style.--seats-pct]=\"(subscription.units_in_use || 1) / subscription.purchased_units\"></span>\n }\n </div>\n </div>\n <!-- Subscription-level actions (a subscription may hold multiple products) -->\n @if (\n (subscription.is_subscription_owner || subscription.is_subscription_admin) &&\n subscription.products?.length &&\n !subscription.products[0].deleted &&\n !subscription.products[0].dependency_products?.length\n ) {\n <div class=\"subscription-summary__actions d-flex flex-wrap align-items-center gap-2\">\n <a class=\"btn btn-outline-primary btn-sm\"\n aria-label=\"Navigate to Target\"\n [routerLink]=\"['../subscriptions', subscription.id]\">\n {{ 'Button.Edit' | transloco }}\n </a>\n @if (!subscription.products[0].expired && !subscription.products[0].trial_subscription) {\n <button [routerLink]=\"['../subscriptions', subscription.id, 'credential']\"\n class=\"btn btn-outline-secondary btn-sm\">\n {{ 'User.Subscriptions.Credentials' | transloco }}\n </button>\n }\n @if (!isUpdatePayment && subscription.stripe_customer_id) {\n <a class=\"btn btn-sm btn-outline-primary\"\n [routerLink]=\"['../subscriptions', subscription.id, 'product', subscription.products[0].id, 'update-payment']\">\n <i class=\"fa fa-edit me-1\" aria-hidden=\"true\"></i>{{ 'User.Subscriptions.UpdateCardDetails' | transloco }}</a>\n }\n <button class=\"btn btn-sm btn-outline-primary\"\n [routerLink]=\"'/account/subscriptions/add-new'\"\n [queryParams]=\"{ subscription_id: subscription.id }\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.ManageAllProducts' | transloco\"\n tooltipPosition=\"bottom\">\n <i class=\"fa fa-plus me-1\"></i>{{ 'User.Subscriptions.SeeAllProducts' | transloco }}\n </button>\n </div>\n }\n </div>\n <!-- Products list -->\n @for (\n product of subscription.products; track trackByProduct($index,\n product); let first = $first) {\n <div class=\"mb-3\">\n <div class=\"card subscription-products-cards\">\n <div class=\"card-content\">\n <div class=\"card-header\">\n <div>\n <h4 class=\"mb-3 text-bold-500 primary\">{{ product?.name }}</h4>\n <!-- Frequency -->\n <div>\n <div>\n <strong class=\"d-inline-block w-50\">{{\n 'User.Subscriptions.Frequency' | transloco\n }}:</strong>\n {{ product?.billing_frequency | uppercase }}\n </div>\n </div>\n <!-- Expiration -->\n <div [ngClass]=\"{ 'text-danger': product.expired }\">\n <strong class=\"d-inline-block w-50\">{{\n product.expired ? 'Expired' : 'Expiry Date'\n }}:</strong>\n {{ product.expires_at | dateFormat }}\n </div>\n <!-- Estimated Price -->\n <div [ngClass]=\"{ 'text-danger': product.expired }\">\n <strong class=\"d-inline-block w-50\">{{\n 'User.Subscriptions.PriceExclTax' | transloco\n }}:</strong>\n {{ product.currency }}\n {{ (product.calculated_price / 100) | number:'1.2-2' }}\n </div>\n <!-- Product API Key (Alpha-only) -->\n <ng-container *rbacAllow=\"'Pages.Alpha'\">\n @if (\n (product.stripe_plan_id && product.max_hits > 0) ||\n product.max_hits_trial > 0\n ) {\n <div class=\"d-flex align-items-center\">\n <strong class=\"d-inline-block w-50\">\n {{ 'User.Subscriptions.ApiKey' | transloco }}:\n <i class=\"far fa-info-circle ms-1 text-muted\"\n aria-hidden=\"true\"\n [ngbTooltip]=\"'User.Subscriptions.ApiKey.NotUsedHint' | transloco\"></i>\n </strong>\n <code class=\"text-truncate me-2\">{{ product.masked }}</code>\n <span class=\"ms-auto d-flex align-items-center flex-shrink-0\">\n <!-- Show Access Key -->\n <button class=\"btn\"\n ngbTooltip=\"Show Access Key\"\n (click)=\"showKey(product)\">\n <i class=\"fas fa-eye\" aria-hidden=\"true\"></i>\n </button>\n <!-- Copy To Clipboard -->\n <button class=\"btn\"\n ngbTooltip=\"Copy Key\">\n <i class=\"fal fa-copy\"\n aria-hidden=\"true\"\n (click)=\"onClipboardCopy(product.api_access_token)\"\n (keydown.enter)=\"onClipboardCopy(product.api_access_token)\"></i>\n </button>\n <!-- Update API Key -->\n @if (!product.expired && !product.deleted) {\n <button class=\"btn\"\n ngbTooltip=\"Change Key\"\n (click)=\"updateApiKey(subscription, product)\">\n <i class=\"fal fa-sync-alt\" aria-hidden=\"true\"></i>\n </button>\n }\n </span>\n </div>\n }\n </ng-container>\n </div>\n </div>\n <div class=\"card-footer px-3 d-flex flex-column gap-2\">\n <div class=\"footer-status d-flex flex-wrap align-items-center gap-2\">\n @if (product.deleted && !product.expired) {\n <span class=\"footer-note\">\n <i class=\"fa fa-info-circle me-2\" aria-hidden=\"true\"></i>{{ 'User.Subscriptions.OutdatedMessage' | transloco }}\n </span>\n }\n @if (product.deleted) {\n <span class=\"badge bg-danger\">Deleted</span>\n }\n @if (\n product.trial_subscription &&\n product.calculated_price\n ) {\n <span class=\"badge bg-warning\">Trial</span>\n }\n @if (product?.pause_collection && objectKeys(product?.pause_collection)?.length) {\n <span class=\"badge bg-grey\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.PausedCollection'|transloco\"\n tooltipPosition=\"top\">\n Paused collection\n </span>\n }\n @if (!product.calculated_price) {\n <span class=\"badge bg-success\">Free</span>\n }\n @if (!product?.deleted && !subscription.is_subscription_owner) {\n <span class=\"footer-note\">\n <i class=\"fa fa-info-circle me-2\" aria-hidden=\"true\"></i>Invited to use this product\n @if (subscription.is_subscription_admin) {\n <span class=\"badge bg-role-admin ms-1\">as an admin</span>\n }\n </span>\n }\n </div>\n @if (\n subscription.is_subscription_owner ||\n subscription.is_subscription_admin\n ) {\n <div class=\"footer-actions d-flex flex-wrap align-items-center justify-content-end gap-2\">\n <!-- Unsubscribe -->\n @if (\n subscription?.stripe_customer_id &&\n !product?.deleted &&\n !product?.trial_subscription\n ) {\n <button class=\"btn btn-outline-danger btn-sm\"\n (click)=\"attemptUnsubscribe(subscription, product.id)\">\n {{ 'User.Subscriptions.Unsubscribe' | transloco }}\n </button>\n }\n @if (product.stripe_plan_id && product.active) {\n <!-- Upgrade (single primary CTA) -->\n @if (product.trial_subscription && !product.deleted) {\n <button class=\"btn btn-primary btn-sm\"\n (click)=\"attemptUpgrade(subscription, product)\">\n {{ 'Button.Upgrade' | transloco }}\n </button>\n }\n <!-- Subscribe -->\n @if (subscription.expired && product.stripe_plan_id) {\n <button class=\"btn btn-primary btn-sm\"\n [routerLink]=\"'/account/subscriptions/add-new'\">\n {{ 'User.Subscriptions.Subscribe' | transloco }}\n </button>\n }\n }\n <!-- Privacy & Terms of Service (quiet link, not a button) -->\n @if (product?.product_privacy_service_id) {\n <button class=\"btn btn-link btn-sm p-0 footer-tos-link\"\n (click)=\"showPrivacyAndTos(product)\">\n {{\n 'User.Subscriptions.PrivacyAndTermsOfService'\n | transloco\n }}\n </button>\n }\n </div>\n }\n </div>\n </div>\n </div>\n @if (subscription.products.length === 0) {\n <div>\n <div class=\"card\">\n <div class=\"card-content\">\n <div class=\"card-header\">\n <p class=\"text-center\">\n No product available for this subscription\n </p>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (!editing && !isAddNew && !isUpdatePayment) {\n <div class=\"col-12\"\n >\n @if (subscribedSubscriptions.length === 0) {\n <pw-no-data [withImage]=\"true\" message=\"You don't have any subscription.\"\n >\n </pw-no-data>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n <!-- Danger zone (demoted account deletion) -->\n @if (!editing && !isAddNew && !isUpdatePayment && isLoaded) {\n <div class=\"row\">\n <div class=\"col-12\">\n <div class=\"danger-zone mt-4\">\n <button type=\"button\"\n class=\"btn btn-sm btn-outline-danger danger-zone__action\"\n (click)=\"showModalForAccountDeletion()\"\n [pTooltip]=\"'User.Account.Tooltip.DeleteAccount' | transloco\"\n tooltipPosition=\"top\">\n {{ 'User.Account.DeleteAccount' | transloco }}\n </button>\n </div>\n </div>\n </div>\n }\n <!--\n Add New Subscription\n -->\n <!-- <ng-template [ngIf]=\"isAddNew && !isUpdatePayment\">\n <pw-subscription-details></pw-subscription-details>\n</ng-template> -->\n<!--\nValidate Password For Account Delete\n-->\n<pw-password-validation #passwordValidationModalForAccountDelete\n (successEvent)=\"deleteUser($event)\">\n <div class=\"row\">\n <div class=\"col-12\">\n <p>{{ 'User.Account.Message.ActionCanNotUndone' | transloco }}</p>\n <p>{{ 'User.Account.Message.ConfirmPassword' | transloco }}</p>\n </div>\n </div>\n</pw-password-validation>\n<!--\nValidate Password For Display Key\n-->\n<pw-password-validation #passwordValidationModalForKey\n (successEvent)=\"displayApiKey()\">\n</pw-password-validation>\n<!--\nValidate Password For Unsubscribe\n-->\n<pw-password-validation #passwordValidationForUnsubscribe\n (successEvent)=\"onValidatePassword($event)\">\n <div class=\"row\">\n <div class=\"col-12\">\n <p>{{ 'User.Account.Message.ActionCanNotUndone' | transloco }}</p>\n <p>{{ 'User.Account.Message.ConfirmPassword' | transloco }}</p>\n </div>\n </div>\n</pw-password-validation>\n<!--\nCancel Subscription Modal\n-->\n<ng-template #cancelSubscriptionModal let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\">{{ 'User.Subscriptions.CancelSubscription.Title' | transloco }}</h4>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss(); reasonToCancel = '';\">\n </button>\n </div>\n <div class=\"modal-body\">\n <p>{{ 'User.Subscriptions.CancelSubscription.Message' | transloco }}</p>\n <div class=\"mb-3\">\n <label for=\"reasonToCancel\" class=\"form-label\">\n {{ 'User.Subscriptions.CancelSubscription.ReasonLabel' | transloco }} <span class=\"text-danger\">*</span>\n </label>\n <textarea\n id=\"reasonToCancel\"\n class=\"form-control\"\n rows=\"4\"\n [(ngModel)]=\"reasonToCancel\"\n [ngClass]=\"{'is-invalid': reasonToCancel && reasonToCancel.trim() === ''}\"\n placeholder=\"{{ 'User.Subscriptions.CancelSubscription.ReasonPlaceholder' | transloco }}\"></textarea>\n @if (reasonToCancel && reasonToCancel.trim() === '') {\n <div class=\"invalid-feedback\">\n {{ 'User.Subscriptions.Validation.ReasonRequired' | transloco }}\n </div>\n }\n </div>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\"\n class=\"btn btn-outline-default\"\n (click)=\"modal.dismiss(); reasonToCancel = '';\">\n {{ 'User.Subscriptions.CancelSubscription.KeepItForNow' | transloco }}\n </button>\n <button type=\"button\"\n class=\"btn btn-danger\"\n [disabled]=\"!reasonToCancel || reasonToCancel.trim() === ''\"\n (click)=\"onConfirmCancel(); modal.close()\">\n {{ 'User.Subscriptions.CancelSubscription.ConfirmButton' | transloco }}\n </button>\n </div>\n</ng-template>\n}\n\n@if (showTos) {\n <pw-privacy-and-tos [productId]=\"productId\"></pw-privacy-and-tos>\n}\n\n<router-outlet></router-outlet>\n", styles: [".btn-list{bottom:24px;left:0;padding:0 38px;right:0}.shadow-md{padding-bottom:70px!important}.bg-dark{border:0}.subscription-details{background:#fff;border:1px solid #e2e5ea;border-radius:12px;padding:16px 16px 6px;font-size:14px;font-variant-numeric:tabular-nums}.subscription-summary{border-bottom:1px solid #eef0f3;padding-bottom:12px}.seats-usage{display:inline-block;width:120px;height:6px;margin-left:8px;border-radius:999px;vertical-align:middle;overflow:hidden;background:linear-gradient(#5a6473,#5a6473) left/calc(var(--seats-pct, 0) * 100%) 100% no-repeat,#e2e5ea}.subscription-products-cards{padding-bottom:0!important}.subscription-products-cards .card-footer{position:static!important}.subscription-products-cards.card{background:#f7f8fa;border:1px solid #eef0f3;border-radius:8px;box-shadow:none!important;font-size:14px}.card-footer{background:transparent;border-top:1px solid #eef0f3}.card-footer .footer-note{color:#5a6473;font-size:.875rem}.card-footer .footer-tos-link{color:#5a6473;font-weight:500;text-decoration:underline}.card-footer .footer-tos-link:hover{color:var(--first)}.badge{font-weight:600;border-radius:4px}.badge.bg-success{background-color:#e6f4ec!important;color:#0f6b3a!important}.badge.bg-danger{background-color:#fbeae8!important;color:#c0392b!important}.badge.bg-warning{background-color:#fbf1e3!important;color:#8a5a00!important}.badge.bg-grey,.badge.bg-role-admin{background-color:#eef0f3!important;color:#5a6473!important}code{color:var(--text);min-width:0}.danger-zone{border-top:1px solid #e2e5ea;padding-top:16px;text-align:right}\n"], dependencies: [{ kind: "directive", type: i4.RbacAllowDirective, selector: "[rbacAllow]", inputs: ["rbacAllow"] }, { kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "component", type: i5.PasswordValidationComponent, selector: "pw-password-validation", inputs: ["confirmMessage"], outputs: ["successEvent"] }, { kind: "directive", type: i1$1.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i5.PrivacyAndTosComponent, selector: "pw-privacy-and-tos", inputs: ["productId"] }, { kind: "component", type: i5.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "directive", type: i11.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "pipe", type: i6.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i6.DecimalPipe, name: "number" }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }, { kind: "pipe", type: i6$3.DateFormatPipe, name: "dateFormat" }] }); }
|
|
1907
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: UserSubscriptionListComponent, isStandalone: false, selector: "pw-user-subscriptions-list", viewQueries: [{ propertyName: "menu", first: true, predicate: ["menuItems"], descendants: true }, { propertyName: "changeSubscriptionRef", first: true, predicate: AddSubscriptionComponent, descendants: true }, { propertyName: "passwordValidationModalForAccountDelete", first: true, predicate: ["passwordValidationModalForAccountDelete"], descendants: true }, { propertyName: "passwordValidationModalForKey", first: true, predicate: ["passwordValidationModalForKey"], descendants: true }, { propertyName: "passwordValidationForUnsubscribe", first: true, predicate: ["passwordValidationForUnsubscribe"], descendants: true }, { propertyName: "cancelSubscriptionModal", first: true, predicate: ["cancelSubscriptionModal"], descendants: true }], usesInheritance: true, ngImport: i0, template: "@if (!showTos) {\n <!-- Subscriptions Tab Content -->\n @if (!editing && !isAddNew) {\n <div class=\"row\">\n <div class=\"col-12\">\n <h2>Your Subscriptions</h2>\n <p>You'll find in this section the summary of your subscriptions.</p>\n </div>\n </div>\n }\n <!-- Subscribed Product Cards -->\n @if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n @if (\n !editing && !isAddNew && !isUpdatePayment && isLoaded && subscribedSubscriptions.length\n ) {\n <div class=\"row\"\n >\n @for (subscription of subscribedSubscriptions; track trackBySubscription($index, subscription)) {\n <div class=\"col-12 col-md-6 my-3\"\n >\n <div class=\"subscription-details mb-4\">\n <div class=\"subscription-summary d-flex flex-wrap justify-content-between align-items-start gap-2 mb-3\">\n <div class=\"subscription-summary__info\">\n <div>\n <strong>Organisation:</strong>\n {{ subscription.organisation ? subscription.organisation : subscription.contact_name }}\n </div>\n <div>\n <strong>{{ 'User.Subscriptions.TotalPriceExclTax' | transloco }}:</strong>\n @if (subscription.calculated_price) {\n {{ subscription.products[0]?.currency }} {{ subscription.calculated_price / 100 | number:'1.2-2' }}\n {{ subscription.products[0].trial_subscription ? '(After Trial)' : '' }}\n } @else {\n Free\n }\n </div>\n <div>\n <strong>{{ 'User.Subscriptions.SeatsInUse' | transloco }}:</strong>\n {{ subscription.units_in_use || 1 }} / {{ subscription.purchased_units }}\n @if (subscription.purchased_units) {\n <span class=\"seats-usage\"\n [style.--seats-pct]=\"(subscription.units_in_use || 1) / subscription.purchased_units\"></span>\n }\n </div>\n </div>\n <!-- Subscription-level actions (a subscription may hold multiple products) -->\n @if (\n (subscription.is_subscription_owner || subscription.is_subscription_admin) &&\n subscription.products?.length &&\n !subscription.products[0].deleted &&\n !subscription.products[0].dependency_products?.length\n ) {\n <div class=\"subscription-summary__actions d-flex flex-wrap align-items-center gap-2\">\n <a class=\"btn btn-outline-primary btn-sm\"\n aria-label=\"Navigate to Target\"\n [routerLink]=\"['../subscriptions', subscription.id]\">\n {{ 'Button.Edit' | transloco }}\n </a>\n @if (!subscription.products[0].expired && !subscription.products[0].trial_subscription) {\n <button [routerLink]=\"['../subscriptions', subscription.id, 'credential']\"\n class=\"btn btn-outline-secondary btn-sm\">\n {{ 'User.Subscriptions.Credentials' | transloco }}\n </button>\n }\n @if (!isUpdatePayment && subscription.stripe_customer_id) {\n <a class=\"btn btn-sm btn-outline-primary\"\n [routerLink]=\"['../subscriptions', subscription.id, 'product', subscription.products[0].id, 'update-payment']\">\n <i class=\"fa fa-edit me-1\" aria-hidden=\"true\"></i>{{ 'User.Subscriptions.UpdateCardDetails' | transloco }}</a>\n }\n <button class=\"btn btn-sm btn-outline-primary\"\n [routerLink]=\"'/account/subscriptions/add-new'\"\n [queryParams]=\"{ subscription_id: subscription.id }\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.ManageAllProducts' | transloco\"\n tooltipPosition=\"bottom\">\n <i class=\"fa fa-plus me-1\"></i>{{ 'User.Subscriptions.SeeAllProducts' | transloco }}\n </button>\n </div>\n }\n </div>\n <!-- Products list -->\n @for (\n product of subscription.products; track trackByProduct($index,\n product); let first = $first) {\n <div class=\"mb-3\">\n <div class=\"card subscription-products-cards\">\n <div class=\"card-content\">\n <div class=\"card-header\">\n <div>\n <h4 class=\"mb-3 text-bold-500 primary\">{{ product?.name }}</h4>\n <!-- Frequency -->\n <div>\n <div>\n <strong class=\"d-inline-block w-50\">{{\n 'User.Subscriptions.Frequency' | transloco\n }}:</strong>\n {{ product?.billing_frequency | uppercase }}\n </div>\n </div>\n <!-- Expiration -->\n <div [ngClass]=\"{ 'text-danger': product.expired }\">\n <strong class=\"d-inline-block w-50\">{{\n product.expired ? 'Expired' : 'Expiry Date'\n }}:</strong>\n {{ product.expires_at | dateFormat }}\n </div>\n <!-- Estimated Price -->\n <div [ngClass]=\"{ 'text-danger': product.expired }\">\n <strong class=\"d-inline-block w-50\">{{\n 'User.Subscriptions.PriceExclTax' | transloco\n }}:</strong>\n {{ product.currency }}\n {{ (product.calculated_price / 100) | number:'1.2-2' }}\n </div>\n <!-- Product API Key (Alpha-only) -->\n <ng-container *rbacAllow=\"'Pages.Alpha'\">\n @if (\n (product.stripe_plan_id && product.max_hits > 0) ||\n product.max_hits_trial > 0\n ) {\n <div class=\"d-flex align-items-center\">\n <strong class=\"d-inline-block w-50\">\n {{ 'User.Subscriptions.ApiKey' | transloco }}:\n <i class=\"far fa-info-circle ms-1 text-muted\"\n aria-hidden=\"true\"\n [ngbTooltip]=\"'User.Subscriptions.ApiKey.NotUsedHint' | transloco\"></i>\n </strong>\n <code class=\"text-truncate me-2\">{{ product.masked }}</code>\n <span class=\"ms-auto d-flex align-items-center flex-shrink-0\">\n <!-- Show Access Key -->\n <button class=\"btn\"\n ngbTooltip=\"Show Access Key\"\n (click)=\"showKey(product)\">\n <i class=\"fas fa-eye\" aria-hidden=\"true\"></i>\n </button>\n <!-- Copy To Clipboard -->\n <button class=\"btn\"\n ngbTooltip=\"Copy Key\">\n <i class=\"fal fa-copy\"\n aria-hidden=\"true\"\n (click)=\"onClipboardCopy(product.api_access_token)\"\n (keydown.enter)=\"onClipboardCopy(product.api_access_token)\"></i>\n </button>\n <!-- Update API Key -->\n @if (!product.expired && !product.deleted) {\n <button class=\"btn\"\n ngbTooltip=\"Change Key\"\n (click)=\"updateApiKey(subscription, product)\">\n <i class=\"fal fa-sync-alt\" aria-hidden=\"true\"></i>\n </button>\n }\n </span>\n </div>\n }\n </ng-container>\n </div>\n </div>\n <div class=\"card-footer px-3 d-flex flex-column gap-2\">\n <div class=\"footer-status d-flex flex-wrap align-items-center gap-2\">\n @if (product.deleted && !product.expired) {\n <span class=\"footer-note\">\n <i class=\"fa fa-info-circle me-2\" aria-hidden=\"true\"></i>{{ 'User.Subscriptions.OutdatedMessage' | transloco }}\n </span>\n }\n @if (product.deleted) {\n <span class=\"badge bg-danger\">Deleted</span>\n }\n @if (\n product.trial_subscription &&\n product.calculated_price\n ) {\n <span class=\"badge bg-warning\">Trial</span>\n }\n @if (product?.pause_collection && objectKeys(product?.pause_collection)?.length) {\n <span class=\"badge bg-grey\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.PausedCollection'|transloco\"\n tooltipPosition=\"top\">\n Paused collection\n </span>\n }\n @if (!product.calculated_price) {\n <span class=\"badge bg-success\">Free</span>\n }\n @if (!product?.deleted && !subscription.is_subscription_owner) {\n <span class=\"footer-note\">\n <i class=\"fa fa-info-circle me-2\" aria-hidden=\"true\"></i>Invited to use this product\n @if (subscription.is_subscription_admin) {\n <span class=\"badge bg-role-admin ms-1\">as an admin</span>\n }\n </span>\n }\n </div>\n @if (\n subscription.is_subscription_owner ||\n subscription.is_subscription_admin\n ) {\n <div class=\"footer-actions d-flex flex-wrap align-items-center justify-content-end gap-2\">\n <!-- Unsubscribe -->\n @if (\n subscription?.stripe_customer_id &&\n !product?.deleted &&\n !product?.trial_subscription\n ) {\n <button class=\"btn btn-outline-danger btn-sm\"\n (click)=\"attemptUnsubscribe(subscription, product.id)\">\n {{ 'User.Subscriptions.Unsubscribe' | transloco }}\n </button>\n }\n @if (product.stripe_plan_id && product.active) {\n <!-- Upgrade (single primary CTA) -->\n @if (product.trial_subscription && !product.deleted) {\n <button class=\"btn btn-primary btn-sm\"\n (click)=\"attemptUpgrade(subscription, product)\">\n {{ 'Button.Upgrade' | transloco }}\n </button>\n }\n <!-- Subscribe -->\n @if (subscription.expired && product.stripe_plan_id) {\n <button class=\"btn btn-primary btn-sm\"\n [routerLink]=\"'/account/subscriptions/add-new'\">\n {{ 'User.Subscriptions.Subscribe' | transloco }}\n </button>\n }\n }\n <!-- Privacy & Terms of Service (quiet link, not a button) -->\n @if (product?.product_privacy_service_id) {\n <button class=\"btn btn-link btn-sm p-0 footer-tos-link\"\n (click)=\"showPrivacyAndTos(product)\">\n {{\n 'User.Subscriptions.PrivacyAndTermsOfService'\n | transloco\n }}\n </button>\n }\n </div>\n }\n </div>\n </div>\n </div>\n @if (subscription.products.length === 0) {\n <div>\n <div class=\"card\">\n <div class=\"card-content\">\n <div class=\"card-header\">\n <p class=\"text-center\">\n No product available for this subscription\n </p>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (!editing && !isAddNew && !isUpdatePayment) {\n <div class=\"col-12\"\n >\n @if (subscribedSubscriptions.length === 0) {\n <pw-no-data [withImage]=\"true\" message=\"You don't have any subscription.\"\n >\n </pw-no-data>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n <!-- Danger zone (demoted account deletion) -->\n @if (!editing && !isAddNew && !isUpdatePayment && isLoaded) {\n <div class=\"row\">\n <div class=\"col-12\">\n <div class=\"danger-zone mt-4\">\n <button type=\"button\"\n class=\"btn btn-sm btn-outline-danger danger-zone__action\"\n (click)=\"showModalForAccountDeletion()\"\n [pTooltip]=\"'User.Account.Tooltip.DeleteAccount' | transloco\"\n tooltipPosition=\"top\">\n {{ 'User.Account.DeleteAccount' | transloco }}\n </button>\n </div>\n </div>\n </div>\n }\n <!--\n Add New Subscription\n -->\n <!-- <ng-template [ngIf]=\"isAddNew && !isUpdatePayment\">\n <pw-subscription-details></pw-subscription-details>\n</ng-template> -->\n<!--\nValidate Password For Account Delete\n-->\n<pw-password-validation #passwordValidationModalForAccountDelete\n [destructive]=\"true\"\n (successEvent)=\"deleteUser($event)\">\n</pw-password-validation>\n<!--\nValidate Password For Display Key\n-->\n<pw-password-validation #passwordValidationModalForKey\n (successEvent)=\"displayApiKey()\">\n</pw-password-validation>\n<!--\nValidate Password For Unsubscribe\n-->\n<pw-password-validation #passwordValidationForUnsubscribe\n [destructive]=\"true\"\n (successEvent)=\"onValidatePassword($event)\">\n</pw-password-validation>\n<!--\nCancel Subscription Modal\n-->\n<ng-template #cancelSubscriptionModal let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\">{{ 'User.Subscriptions.CancelSubscription.Title' | transloco }}</h4>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss(); reasonToCancel = '';\">\n </button>\n </div>\n <div class=\"modal-body\">\n <p>{{ 'User.Subscriptions.CancelSubscription.Message' | transloco }}</p>\n <div class=\"mb-3\">\n <label for=\"reasonToCancel\" class=\"form-label\">\n {{ 'User.Subscriptions.CancelSubscription.ReasonLabel' | transloco }} <span class=\"text-danger\">*</span>\n </label>\n <textarea\n id=\"reasonToCancel\"\n class=\"form-control\"\n rows=\"4\"\n [(ngModel)]=\"reasonToCancel\"\n [ngClass]=\"{'is-invalid': reasonToCancel && reasonToCancel.trim() === ''}\"\n placeholder=\"{{ 'User.Subscriptions.CancelSubscription.ReasonPlaceholder' | transloco }}\"></textarea>\n @if (reasonToCancel && reasonToCancel.trim() === '') {\n <div class=\"invalid-feedback\">\n {{ 'User.Subscriptions.Validation.ReasonRequired' | transloco }}\n </div>\n }\n </div>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\"\n class=\"btn btn-outline-default\"\n (click)=\"modal.dismiss(); reasonToCancel = '';\">\n {{ 'User.Subscriptions.CancelSubscription.KeepItForNow' | transloco }}\n </button>\n <button type=\"button\"\n class=\"btn btn-danger\"\n [disabled]=\"!reasonToCancel || reasonToCancel.trim() === ''\"\n (click)=\"onConfirmCancel(); modal.close()\">\n {{ 'User.Subscriptions.CancelSubscription.ConfirmButton' | transloco }}\n </button>\n </div>\n</ng-template>\n}\n\n@if (showTos) {\n <pw-privacy-and-tos [productId]=\"productId\"></pw-privacy-and-tos>\n}\n\n<router-outlet></router-outlet>\n", styles: [".btn-list{bottom:24px;left:0;padding:0 38px;right:0}.shadow-md{padding-bottom:70px!important}.bg-dark{border:0}.subscription-details{background:#fff;border:1px solid #e2e5ea;border-radius:12px;padding:16px 16px 6px;font-size:14px;font-variant-numeric:tabular-nums}.subscription-summary{border-bottom:1px solid #eef0f3;padding-bottom:12px}.seats-usage{display:inline-block;width:120px;height:6px;margin-left:8px;border-radius:999px;vertical-align:middle;overflow:hidden;background:linear-gradient(#5a6473,#5a6473) left/calc(var(--seats-pct, 0) * 100%) 100% no-repeat,#e2e5ea}.subscription-products-cards{padding-bottom:0!important}.subscription-products-cards .card-footer{position:static!important}.subscription-products-cards.card{background:#f7f8fa;border:1px solid #eef0f3;border-radius:8px;box-shadow:none!important;font-size:14px}.card-footer{background:transparent;border-top:1px solid #eef0f3}.card-footer .footer-note{color:#5a6473;font-size:.875rem}.card-footer .footer-tos-link{color:#5a6473;font-weight:500;text-decoration:underline}.card-footer .footer-tos-link:hover{color:var(--first)}.badge{font-weight:600;border-radius:4px}.badge.bg-success{background-color:#e6f4ec!important;color:#0f6b3a!important}.badge.bg-danger{background-color:#fbeae8!important;color:#c0392b!important}.badge.bg-warning{background-color:#fbf1e3!important;color:#8a5a00!important}.badge.bg-grey,.badge.bg-role-admin{background-color:#eef0f3!important;color:#5a6473!important}code{color:var(--text);min-width:0}.danger-zone{border-top:1px solid #e2e5ea;padding-top:16px;text-align:right}\n"], dependencies: [{ kind: "directive", type: i4.RbacAllowDirective, selector: "[rbacAllow]", inputs: ["rbacAllow"] }, { kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.RouterOutlet, selector: "router-outlet", inputs: ["name", "routerOutletData"], outputs: ["activate", "deactivate", "attach", "detach"], exportAs: ["outlet"] }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "component", type: i7.PasswordValidationComponent, selector: "pw-password-validation", inputs: ["confirmMessage", "destructive"], outputs: ["successEvent"] }, { kind: "directive", type: i1$1.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i7.PrivacyAndTosComponent, selector: "pw-privacy-and-tos", inputs: ["productId"] }, { kind: "component", type: i7.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "directive", type: i11.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "pipe", type: i5.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i5.DecimalPipe, name: "number" }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }, { kind: "pipe", type: i6$1.DateFormatPipe, name: "dateFormat" }] }); }
|
|
1810
1908
|
}
|
|
1811
1909
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: UserSubscriptionListComponent, decorators: [{
|
|
1812
1910
|
type: Component,
|
|
1813
|
-
args: [{ selector: 'pw-user-subscriptions-list', standalone: false, template: "@if (!showTos) {\n <!-- Subscriptions Tab Content -->\n @if (!editing && !isAddNew) {\n <div class=\"row\">\n <div class=\"col-12\">\n <h2>Your Subscriptions</h2>\n <p>You'll find in this section the summary of your subscriptions.</p>\n </div>\n </div>\n }\n <!-- Subscribed Product Cards -->\n @if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n @if (\n !editing && !isAddNew && !isUpdatePayment && isLoaded && subscribedSubscriptions.length\n ) {\n <div class=\"row\"\n >\n @for (subscription of subscribedSubscriptions; track trackBySubscription($index, subscription)) {\n <div class=\"col-12 col-md-6 my-3\"\n >\n <div class=\"subscription-details mb-4\">\n <div class=\"subscription-summary d-flex flex-wrap justify-content-between align-items-start gap-2 mb-3\">\n <div class=\"subscription-summary__info\">\n <div>\n <strong>Organisation:</strong>\n {{ subscription.organisation ? subscription.organisation : subscription.contact_name }}\n </div>\n <div>\n <strong>{{ 'User.Subscriptions.TotalPriceExclTax' | transloco }}:</strong>\n @if (subscription.calculated_price) {\n {{ subscription.products[0]?.currency }} {{ subscription.calculated_price / 100 | number:'1.2-2' }}\n {{ subscription.products[0].trial_subscription ? '(After Trial)' : '' }}\n } @else {\n Free\n }\n </div>\n <div>\n <strong>{{ 'User.Subscriptions.SeatsInUse' | transloco }}:</strong>\n {{ subscription.units_in_use || 1 }} / {{ subscription.purchased_units }}\n @if (subscription.purchased_units) {\n <span class=\"seats-usage\"\n [style.--seats-pct]=\"(subscription.units_in_use || 1) / subscription.purchased_units\"></span>\n }\n </div>\n </div>\n <!-- Subscription-level actions (a subscription may hold multiple products) -->\n @if (\n (subscription.is_subscription_owner || subscription.is_subscription_admin) &&\n subscription.products?.length &&\n !subscription.products[0].deleted &&\n !subscription.products[0].dependency_products?.length\n ) {\n <div class=\"subscription-summary__actions d-flex flex-wrap align-items-center gap-2\">\n <a class=\"btn btn-outline-primary btn-sm\"\n aria-label=\"Navigate to Target\"\n [routerLink]=\"['../subscriptions', subscription.id]\">\n {{ 'Button.Edit' | transloco }}\n </a>\n @if (!subscription.products[0].expired && !subscription.products[0].trial_subscription) {\n <button [routerLink]=\"['../subscriptions', subscription.id, 'credential']\"\n class=\"btn btn-outline-secondary btn-sm\">\n {{ 'User.Subscriptions.Credentials' | transloco }}\n </button>\n }\n @if (!isUpdatePayment && subscription.stripe_customer_id) {\n <a class=\"btn btn-sm btn-outline-primary\"\n [routerLink]=\"['../subscriptions', subscription.id, 'product', subscription.products[0].id, 'update-payment']\">\n <i class=\"fa fa-edit me-1\" aria-hidden=\"true\"></i>{{ 'User.Subscriptions.UpdateCardDetails' | transloco }}</a>\n }\n <button class=\"btn btn-sm btn-outline-primary\"\n [routerLink]=\"'/account/subscriptions/add-new'\"\n [queryParams]=\"{ subscription_id: subscription.id }\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.ManageAllProducts' | transloco\"\n tooltipPosition=\"bottom\">\n <i class=\"fa fa-plus me-1\"></i>{{ 'User.Subscriptions.SeeAllProducts' | transloco }}\n </button>\n </div>\n }\n </div>\n <!-- Products list -->\n @for (\n product of subscription.products; track trackByProduct($index,\n product); let first = $first) {\n <div class=\"mb-3\">\n <div class=\"card subscription-products-cards\">\n <div class=\"card-content\">\n <div class=\"card-header\">\n <div>\n <h4 class=\"mb-3 text-bold-500 primary\">{{ product?.name }}</h4>\n <!-- Frequency -->\n <div>\n <div>\n <strong class=\"d-inline-block w-50\">{{\n 'User.Subscriptions.Frequency' | transloco\n }}:</strong>\n {{ product?.billing_frequency | uppercase }}\n </div>\n </div>\n <!-- Expiration -->\n <div [ngClass]=\"{ 'text-danger': product.expired }\">\n <strong class=\"d-inline-block w-50\">{{\n product.expired ? 'Expired' : 'Expiry Date'\n }}:</strong>\n {{ product.expires_at | dateFormat }}\n </div>\n <!-- Estimated Price -->\n <div [ngClass]=\"{ 'text-danger': product.expired }\">\n <strong class=\"d-inline-block w-50\">{{\n 'User.Subscriptions.PriceExclTax' | transloco\n }}:</strong>\n {{ product.currency }}\n {{ (product.calculated_price / 100) | number:'1.2-2' }}\n </div>\n <!-- Product API Key (Alpha-only) -->\n <ng-container *rbacAllow=\"'Pages.Alpha'\">\n @if (\n (product.stripe_plan_id && product.max_hits > 0) ||\n product.max_hits_trial > 0\n ) {\n <div class=\"d-flex align-items-center\">\n <strong class=\"d-inline-block w-50\">\n {{ 'User.Subscriptions.ApiKey' | transloco }}:\n <i class=\"far fa-info-circle ms-1 text-muted\"\n aria-hidden=\"true\"\n [ngbTooltip]=\"'User.Subscriptions.ApiKey.NotUsedHint' | transloco\"></i>\n </strong>\n <code class=\"text-truncate me-2\">{{ product.masked }}</code>\n <span class=\"ms-auto d-flex align-items-center flex-shrink-0\">\n <!-- Show Access Key -->\n <button class=\"btn\"\n ngbTooltip=\"Show Access Key\"\n (click)=\"showKey(product)\">\n <i class=\"fas fa-eye\" aria-hidden=\"true\"></i>\n </button>\n <!-- Copy To Clipboard -->\n <button class=\"btn\"\n ngbTooltip=\"Copy Key\">\n <i class=\"fal fa-copy\"\n aria-hidden=\"true\"\n (click)=\"onClipboardCopy(product.api_access_token)\"\n (keydown.enter)=\"onClipboardCopy(product.api_access_token)\"></i>\n </button>\n <!-- Update API Key -->\n @if (!product.expired && !product.deleted) {\n <button class=\"btn\"\n ngbTooltip=\"Change Key\"\n (click)=\"updateApiKey(subscription, product)\">\n <i class=\"fal fa-sync-alt\" aria-hidden=\"true\"></i>\n </button>\n }\n </span>\n </div>\n }\n </ng-container>\n </div>\n </div>\n <div class=\"card-footer px-3 d-flex flex-column gap-2\">\n <div class=\"footer-status d-flex flex-wrap align-items-center gap-2\">\n @if (product.deleted && !product.expired) {\n <span class=\"footer-note\">\n <i class=\"fa fa-info-circle me-2\" aria-hidden=\"true\"></i>{{ 'User.Subscriptions.OutdatedMessage' | transloco }}\n </span>\n }\n @if (product.deleted) {\n <span class=\"badge bg-danger\">Deleted</span>\n }\n @if (\n product.trial_subscription &&\n product.calculated_price\n ) {\n <span class=\"badge bg-warning\">Trial</span>\n }\n @if (product?.pause_collection && objectKeys(product?.pause_collection)?.length) {\n <span class=\"badge bg-grey\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.PausedCollection'|transloco\"\n tooltipPosition=\"top\">\n Paused collection\n </span>\n }\n @if (!product.calculated_price) {\n <span class=\"badge bg-success\">Free</span>\n }\n @if (!product?.deleted && !subscription.is_subscription_owner) {\n <span class=\"footer-note\">\n <i class=\"fa fa-info-circle me-2\" aria-hidden=\"true\"></i>Invited to use this product\n @if (subscription.is_subscription_admin) {\n <span class=\"badge bg-role-admin ms-1\">as an admin</span>\n }\n </span>\n }\n </div>\n @if (\n subscription.is_subscription_owner ||\n subscription.is_subscription_admin\n ) {\n <div class=\"footer-actions d-flex flex-wrap align-items-center justify-content-end gap-2\">\n <!-- Unsubscribe -->\n @if (\n subscription?.stripe_customer_id &&\n !product?.deleted &&\n !product?.trial_subscription\n ) {\n <button class=\"btn btn-outline-danger btn-sm\"\n (click)=\"attemptUnsubscribe(subscription, product.id)\">\n {{ 'User.Subscriptions.Unsubscribe' | transloco }}\n </button>\n }\n @if (product.stripe_plan_id && product.active) {\n <!-- Upgrade (single primary CTA) -->\n @if (product.trial_subscription && !product.deleted) {\n <button class=\"btn btn-primary btn-sm\"\n (click)=\"attemptUpgrade(subscription, product)\">\n {{ 'Button.Upgrade' | transloco }}\n </button>\n }\n <!-- Subscribe -->\n @if (subscription.expired && product.stripe_plan_id) {\n <button class=\"btn btn-primary btn-sm\"\n [routerLink]=\"'/account/subscriptions/add-new'\">\n {{ 'User.Subscriptions.Subscribe' | transloco }}\n </button>\n }\n }\n <!-- Privacy & Terms of Service (quiet link, not a button) -->\n @if (product?.product_privacy_service_id) {\n <button class=\"btn btn-link btn-sm p-0 footer-tos-link\"\n (click)=\"showPrivacyAndTos(product)\">\n {{\n 'User.Subscriptions.PrivacyAndTermsOfService'\n | transloco\n }}\n </button>\n }\n </div>\n }\n </div>\n </div>\n </div>\n @if (subscription.products.length === 0) {\n <div>\n <div class=\"card\">\n <div class=\"card-content\">\n <div class=\"card-header\">\n <p class=\"text-center\">\n No product available for this subscription\n </p>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (!editing && !isAddNew && !isUpdatePayment) {\n <div class=\"col-12\"\n >\n @if (subscribedSubscriptions.length === 0) {\n <pw-no-data [withImage]=\"true\" message=\"You don't have any subscription.\"\n >\n </pw-no-data>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n <!-- Danger zone (demoted account deletion) -->\n @if (!editing && !isAddNew && !isUpdatePayment && isLoaded) {\n <div class=\"row\">\n <div class=\"col-12\">\n <div class=\"danger-zone mt-4\">\n <button type=\"button\"\n class=\"btn btn-sm btn-outline-danger danger-zone__action\"\n (click)=\"showModalForAccountDeletion()\"\n [pTooltip]=\"'User.Account.Tooltip.DeleteAccount' | transloco\"\n tooltipPosition=\"top\">\n {{ 'User.Account.DeleteAccount' | transloco }}\n </button>\n </div>\n </div>\n </div>\n }\n <!--\n Add New Subscription\n -->\n <!-- <ng-template [ngIf]=\"isAddNew && !isUpdatePayment\">\n <pw-subscription-details></pw-subscription-details>\n</ng-template> -->\n<!--\nValidate Password For Account Delete\n-->\n<pw-password-validation #passwordValidationModalForAccountDelete\n (successEvent)=\"deleteUser($event)\">\n <div class=\"row\">\n <div class=\"col-12\">\n <p>{{ 'User.Account.Message.ActionCanNotUndone' | transloco }}</p>\n <p>{{ 'User.Account.Message.ConfirmPassword' | transloco }}</p>\n </div>\n </div>\n</pw-password-validation>\n<!--\nValidate Password For Display Key\n-->\n<pw-password-validation #passwordValidationModalForKey\n (successEvent)=\"displayApiKey()\">\n</pw-password-validation>\n<!--\nValidate Password For Unsubscribe\n-->\n<pw-password-validation #passwordValidationForUnsubscribe\n (successEvent)=\"onValidatePassword($event)\">\n <div class=\"row\">\n <div class=\"col-12\">\n <p>{{ 'User.Account.Message.ActionCanNotUndone' | transloco }}</p>\n <p>{{ 'User.Account.Message.ConfirmPassword' | transloco }}</p>\n </div>\n </div>\n</pw-password-validation>\n<!--\nCancel Subscription Modal\n-->\n<ng-template #cancelSubscriptionModal let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\">{{ 'User.Subscriptions.CancelSubscription.Title' | transloco }}</h4>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss(); reasonToCancel = '';\">\n </button>\n </div>\n <div class=\"modal-body\">\n <p>{{ 'User.Subscriptions.CancelSubscription.Message' | transloco }}</p>\n <div class=\"mb-3\">\n <label for=\"reasonToCancel\" class=\"form-label\">\n {{ 'User.Subscriptions.CancelSubscription.ReasonLabel' | transloco }} <span class=\"text-danger\">*</span>\n </label>\n <textarea\n id=\"reasonToCancel\"\n class=\"form-control\"\n rows=\"4\"\n [(ngModel)]=\"reasonToCancel\"\n [ngClass]=\"{'is-invalid': reasonToCancel && reasonToCancel.trim() === ''}\"\n placeholder=\"{{ 'User.Subscriptions.CancelSubscription.ReasonPlaceholder' | transloco }}\"></textarea>\n @if (reasonToCancel && reasonToCancel.trim() === '') {\n <div class=\"invalid-feedback\">\n {{ 'User.Subscriptions.Validation.ReasonRequired' | transloco }}\n </div>\n }\n </div>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\"\n class=\"btn btn-outline-default\"\n (click)=\"modal.dismiss(); reasonToCancel = '';\">\n {{ 'User.Subscriptions.CancelSubscription.KeepItForNow' | transloco }}\n </button>\n <button type=\"button\"\n class=\"btn btn-danger\"\n [disabled]=\"!reasonToCancel || reasonToCancel.trim() === ''\"\n (click)=\"onConfirmCancel(); modal.close()\">\n {{ 'User.Subscriptions.CancelSubscription.ConfirmButton' | transloco }}\n </button>\n </div>\n</ng-template>\n}\n\n@if (showTos) {\n <pw-privacy-and-tos [productId]=\"productId\"></pw-privacy-and-tos>\n}\n\n<router-outlet></router-outlet>\n", styles: [".btn-list{bottom:24px;left:0;padding:0 38px;right:0}.shadow-md{padding-bottom:70px!important}.bg-dark{border:0}.subscription-details{background:#fff;border:1px solid #e2e5ea;border-radius:12px;padding:16px 16px 6px;font-size:14px;font-variant-numeric:tabular-nums}.subscription-summary{border-bottom:1px solid #eef0f3;padding-bottom:12px}.seats-usage{display:inline-block;width:120px;height:6px;margin-left:8px;border-radius:999px;vertical-align:middle;overflow:hidden;background:linear-gradient(#5a6473,#5a6473) left/calc(var(--seats-pct, 0) * 100%) 100% no-repeat,#e2e5ea}.subscription-products-cards{padding-bottom:0!important}.subscription-products-cards .card-footer{position:static!important}.subscription-products-cards.card{background:#f7f8fa;border:1px solid #eef0f3;border-radius:8px;box-shadow:none!important;font-size:14px}.card-footer{background:transparent;border-top:1px solid #eef0f3}.card-footer .footer-note{color:#5a6473;font-size:.875rem}.card-footer .footer-tos-link{color:#5a6473;font-weight:500;text-decoration:underline}.card-footer .footer-tos-link:hover{color:var(--first)}.badge{font-weight:600;border-radius:4px}.badge.bg-success{background-color:#e6f4ec!important;color:#0f6b3a!important}.badge.bg-danger{background-color:#fbeae8!important;color:#c0392b!important}.badge.bg-warning{background-color:#fbf1e3!important;color:#8a5a00!important}.badge.bg-grey,.badge.bg-role-admin{background-color:#eef0f3!important;color:#5a6473!important}code{color:var(--text);min-width:0}.danger-zone{border-top:1px solid #e2e5ea;padding-top:16px;text-align:right}\n"] }]
|
|
1911
|
+
args: [{ selector: 'pw-user-subscriptions-list', standalone: false, template: "@if (!showTos) {\n <!-- Subscriptions Tab Content -->\n @if (!editing && !isAddNew) {\n <div class=\"row\">\n <div class=\"col-12\">\n <h2>Your Subscriptions</h2>\n <p>You'll find in this section the summary of your subscriptions.</p>\n </div>\n </div>\n }\n <!-- Subscribed Product Cards -->\n @if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n @if (\n !editing && !isAddNew && !isUpdatePayment && isLoaded && subscribedSubscriptions.length\n ) {\n <div class=\"row\"\n >\n @for (subscription of subscribedSubscriptions; track trackBySubscription($index, subscription)) {\n <div class=\"col-12 col-md-6 my-3\"\n >\n <div class=\"subscription-details mb-4\">\n <div class=\"subscription-summary d-flex flex-wrap justify-content-between align-items-start gap-2 mb-3\">\n <div class=\"subscription-summary__info\">\n <div>\n <strong>Organisation:</strong>\n {{ subscription.organisation ? subscription.organisation : subscription.contact_name }}\n </div>\n <div>\n <strong>{{ 'User.Subscriptions.TotalPriceExclTax' | transloco }}:</strong>\n @if (subscription.calculated_price) {\n {{ subscription.products[0]?.currency }} {{ subscription.calculated_price / 100 | number:'1.2-2' }}\n {{ subscription.products[0].trial_subscription ? '(After Trial)' : '' }}\n } @else {\n Free\n }\n </div>\n <div>\n <strong>{{ 'User.Subscriptions.SeatsInUse' | transloco }}:</strong>\n {{ subscription.units_in_use || 1 }} / {{ subscription.purchased_units }}\n @if (subscription.purchased_units) {\n <span class=\"seats-usage\"\n [style.--seats-pct]=\"(subscription.units_in_use || 1) / subscription.purchased_units\"></span>\n }\n </div>\n </div>\n <!-- Subscription-level actions (a subscription may hold multiple products) -->\n @if (\n (subscription.is_subscription_owner || subscription.is_subscription_admin) &&\n subscription.products?.length &&\n !subscription.products[0].deleted &&\n !subscription.products[0].dependency_products?.length\n ) {\n <div class=\"subscription-summary__actions d-flex flex-wrap align-items-center gap-2\">\n <a class=\"btn btn-outline-primary btn-sm\"\n aria-label=\"Navigate to Target\"\n [routerLink]=\"['../subscriptions', subscription.id]\">\n {{ 'Button.Edit' | transloco }}\n </a>\n @if (!subscription.products[0].expired && !subscription.products[0].trial_subscription) {\n <button [routerLink]=\"['../subscriptions', subscription.id, 'credential']\"\n class=\"btn btn-outline-secondary btn-sm\">\n {{ 'User.Subscriptions.Credentials' | transloco }}\n </button>\n }\n @if (!isUpdatePayment && subscription.stripe_customer_id) {\n <a class=\"btn btn-sm btn-outline-primary\"\n [routerLink]=\"['../subscriptions', subscription.id, 'product', subscription.products[0].id, 'update-payment']\">\n <i class=\"fa fa-edit me-1\" aria-hidden=\"true\"></i>{{ 'User.Subscriptions.UpdateCardDetails' | transloco }}</a>\n }\n <button class=\"btn btn-sm btn-outline-primary\"\n [routerLink]=\"'/account/subscriptions/add-new'\"\n [queryParams]=\"{ subscription_id: subscription.id }\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.ManageAllProducts' | transloco\"\n tooltipPosition=\"bottom\">\n <i class=\"fa fa-plus me-1\"></i>{{ 'User.Subscriptions.SeeAllProducts' | transloco }}\n </button>\n </div>\n }\n </div>\n <!-- Products list -->\n @for (\n product of subscription.products; track trackByProduct($index,\n product); let first = $first) {\n <div class=\"mb-3\">\n <div class=\"card subscription-products-cards\">\n <div class=\"card-content\">\n <div class=\"card-header\">\n <div>\n <h4 class=\"mb-3 text-bold-500 primary\">{{ product?.name }}</h4>\n <!-- Frequency -->\n <div>\n <div>\n <strong class=\"d-inline-block w-50\">{{\n 'User.Subscriptions.Frequency' | transloco\n }}:</strong>\n {{ product?.billing_frequency | uppercase }}\n </div>\n </div>\n <!-- Expiration -->\n <div [ngClass]=\"{ 'text-danger': product.expired }\">\n <strong class=\"d-inline-block w-50\">{{\n product.expired ? 'Expired' : 'Expiry Date'\n }}:</strong>\n {{ product.expires_at | dateFormat }}\n </div>\n <!-- Estimated Price -->\n <div [ngClass]=\"{ 'text-danger': product.expired }\">\n <strong class=\"d-inline-block w-50\">{{\n 'User.Subscriptions.PriceExclTax' | transloco\n }}:</strong>\n {{ product.currency }}\n {{ (product.calculated_price / 100) | number:'1.2-2' }}\n </div>\n <!-- Product API Key (Alpha-only) -->\n <ng-container *rbacAllow=\"'Pages.Alpha'\">\n @if (\n (product.stripe_plan_id && product.max_hits > 0) ||\n product.max_hits_trial > 0\n ) {\n <div class=\"d-flex align-items-center\">\n <strong class=\"d-inline-block w-50\">\n {{ 'User.Subscriptions.ApiKey' | transloco }}:\n <i class=\"far fa-info-circle ms-1 text-muted\"\n aria-hidden=\"true\"\n [ngbTooltip]=\"'User.Subscriptions.ApiKey.NotUsedHint' | transloco\"></i>\n </strong>\n <code class=\"text-truncate me-2\">{{ product.masked }}</code>\n <span class=\"ms-auto d-flex align-items-center flex-shrink-0\">\n <!-- Show Access Key -->\n <button class=\"btn\"\n ngbTooltip=\"Show Access Key\"\n (click)=\"showKey(product)\">\n <i class=\"fas fa-eye\" aria-hidden=\"true\"></i>\n </button>\n <!-- Copy To Clipboard -->\n <button class=\"btn\"\n ngbTooltip=\"Copy Key\">\n <i class=\"fal fa-copy\"\n aria-hidden=\"true\"\n (click)=\"onClipboardCopy(product.api_access_token)\"\n (keydown.enter)=\"onClipboardCopy(product.api_access_token)\"></i>\n </button>\n <!-- Update API Key -->\n @if (!product.expired && !product.deleted) {\n <button class=\"btn\"\n ngbTooltip=\"Change Key\"\n (click)=\"updateApiKey(subscription, product)\">\n <i class=\"fal fa-sync-alt\" aria-hidden=\"true\"></i>\n </button>\n }\n </span>\n </div>\n }\n </ng-container>\n </div>\n </div>\n <div class=\"card-footer px-3 d-flex flex-column gap-2\">\n <div class=\"footer-status d-flex flex-wrap align-items-center gap-2\">\n @if (product.deleted && !product.expired) {\n <span class=\"footer-note\">\n <i class=\"fa fa-info-circle me-2\" aria-hidden=\"true\"></i>{{ 'User.Subscriptions.OutdatedMessage' | transloco }}\n </span>\n }\n @if (product.deleted) {\n <span class=\"badge bg-danger\">Deleted</span>\n }\n @if (\n product.trial_subscription &&\n product.calculated_price\n ) {\n <span class=\"badge bg-warning\">Trial</span>\n }\n @if (product?.pause_collection && objectKeys(product?.pause_collection)?.length) {\n <span class=\"badge bg-grey\"\n [pTooltip]=\"'User.Subscriptions.Tooltip.PausedCollection'|transloco\"\n tooltipPosition=\"top\">\n Paused collection\n </span>\n }\n @if (!product.calculated_price) {\n <span class=\"badge bg-success\">Free</span>\n }\n @if (!product?.deleted && !subscription.is_subscription_owner) {\n <span class=\"footer-note\">\n <i class=\"fa fa-info-circle me-2\" aria-hidden=\"true\"></i>Invited to use this product\n @if (subscription.is_subscription_admin) {\n <span class=\"badge bg-role-admin ms-1\">as an admin</span>\n }\n </span>\n }\n </div>\n @if (\n subscription.is_subscription_owner ||\n subscription.is_subscription_admin\n ) {\n <div class=\"footer-actions d-flex flex-wrap align-items-center justify-content-end gap-2\">\n <!-- Unsubscribe -->\n @if (\n subscription?.stripe_customer_id &&\n !product?.deleted &&\n !product?.trial_subscription\n ) {\n <button class=\"btn btn-outline-danger btn-sm\"\n (click)=\"attemptUnsubscribe(subscription, product.id)\">\n {{ 'User.Subscriptions.Unsubscribe' | transloco }}\n </button>\n }\n @if (product.stripe_plan_id && product.active) {\n <!-- Upgrade (single primary CTA) -->\n @if (product.trial_subscription && !product.deleted) {\n <button class=\"btn btn-primary btn-sm\"\n (click)=\"attemptUpgrade(subscription, product)\">\n {{ 'Button.Upgrade' | transloco }}\n </button>\n }\n <!-- Subscribe -->\n @if (subscription.expired && product.stripe_plan_id) {\n <button class=\"btn btn-primary btn-sm\"\n [routerLink]=\"'/account/subscriptions/add-new'\">\n {{ 'User.Subscriptions.Subscribe' | transloco }}\n </button>\n }\n }\n <!-- Privacy & Terms of Service (quiet link, not a button) -->\n @if (product?.product_privacy_service_id) {\n <button class=\"btn btn-link btn-sm p-0 footer-tos-link\"\n (click)=\"showPrivacyAndTos(product)\">\n {{\n 'User.Subscriptions.PrivacyAndTermsOfService'\n | transloco\n }}\n </button>\n }\n </div>\n }\n </div>\n </div>\n </div>\n @if (subscription.products.length === 0) {\n <div>\n <div class=\"card\">\n <div class=\"card-content\">\n <div class=\"card-header\">\n <p class=\"text-center\">\n No product available for this subscription\n </p>\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n }\n @if (!editing && !isAddNew && !isUpdatePayment) {\n <div class=\"col-12\"\n >\n @if (subscribedSubscriptions.length === 0) {\n <pw-no-data [withImage]=\"true\" message=\"You don't have any subscription.\"\n >\n </pw-no-data>\n }\n </div>\n }\n </div>\n </div>\n }\n </div>\n }\n <!-- Danger zone (demoted account deletion) -->\n @if (!editing && !isAddNew && !isUpdatePayment && isLoaded) {\n <div class=\"row\">\n <div class=\"col-12\">\n <div class=\"danger-zone mt-4\">\n <button type=\"button\"\n class=\"btn btn-sm btn-outline-danger danger-zone__action\"\n (click)=\"showModalForAccountDeletion()\"\n [pTooltip]=\"'User.Account.Tooltip.DeleteAccount' | transloco\"\n tooltipPosition=\"top\">\n {{ 'User.Account.DeleteAccount' | transloco }}\n </button>\n </div>\n </div>\n </div>\n }\n <!--\n Add New Subscription\n -->\n <!-- <ng-template [ngIf]=\"isAddNew && !isUpdatePayment\">\n <pw-subscription-details></pw-subscription-details>\n</ng-template> -->\n<!--\nValidate Password For Account Delete\n-->\n<pw-password-validation #passwordValidationModalForAccountDelete\n [destructive]=\"true\"\n (successEvent)=\"deleteUser($event)\">\n</pw-password-validation>\n<!--\nValidate Password For Display Key\n-->\n<pw-password-validation #passwordValidationModalForKey\n (successEvent)=\"displayApiKey()\">\n</pw-password-validation>\n<!--\nValidate Password For Unsubscribe\n-->\n<pw-password-validation #passwordValidationForUnsubscribe\n [destructive]=\"true\"\n (successEvent)=\"onValidatePassword($event)\">\n</pw-password-validation>\n<!--\nCancel Subscription Modal\n-->\n<ng-template #cancelSubscriptionModal let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\">{{ 'User.Subscriptions.CancelSubscription.Title' | transloco }}</h4>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss(); reasonToCancel = '';\">\n </button>\n </div>\n <div class=\"modal-body\">\n <p>{{ 'User.Subscriptions.CancelSubscription.Message' | transloco }}</p>\n <div class=\"mb-3\">\n <label for=\"reasonToCancel\" class=\"form-label\">\n {{ 'User.Subscriptions.CancelSubscription.ReasonLabel' | transloco }} <span class=\"text-danger\">*</span>\n </label>\n <textarea\n id=\"reasonToCancel\"\n class=\"form-control\"\n rows=\"4\"\n [(ngModel)]=\"reasonToCancel\"\n [ngClass]=\"{'is-invalid': reasonToCancel && reasonToCancel.trim() === ''}\"\n placeholder=\"{{ 'User.Subscriptions.CancelSubscription.ReasonPlaceholder' | transloco }}\"></textarea>\n @if (reasonToCancel && reasonToCancel.trim() === '') {\n <div class=\"invalid-feedback\">\n {{ 'User.Subscriptions.Validation.ReasonRequired' | transloco }}\n </div>\n }\n </div>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\"\n class=\"btn btn-outline-default\"\n (click)=\"modal.dismiss(); reasonToCancel = '';\">\n {{ 'User.Subscriptions.CancelSubscription.KeepItForNow' | transloco }}\n </button>\n <button type=\"button\"\n class=\"btn btn-danger\"\n [disabled]=\"!reasonToCancel || reasonToCancel.trim() === ''\"\n (click)=\"onConfirmCancel(); modal.close()\">\n {{ 'User.Subscriptions.CancelSubscription.ConfirmButton' | transloco }}\n </button>\n </div>\n</ng-template>\n}\n\n@if (showTos) {\n <pw-privacy-and-tos [productId]=\"productId\"></pw-privacy-and-tos>\n}\n\n<router-outlet></router-outlet>\n", styles: [".btn-list{bottom:24px;left:0;padding:0 38px;right:0}.shadow-md{padding-bottom:70px!important}.bg-dark{border:0}.subscription-details{background:#fff;border:1px solid #e2e5ea;border-radius:12px;padding:16px 16px 6px;font-size:14px;font-variant-numeric:tabular-nums}.subscription-summary{border-bottom:1px solid #eef0f3;padding-bottom:12px}.seats-usage{display:inline-block;width:120px;height:6px;margin-left:8px;border-radius:999px;vertical-align:middle;overflow:hidden;background:linear-gradient(#5a6473,#5a6473) left/calc(var(--seats-pct, 0) * 100%) 100% no-repeat,#e2e5ea}.subscription-products-cards{padding-bottom:0!important}.subscription-products-cards .card-footer{position:static!important}.subscription-products-cards.card{background:#f7f8fa;border:1px solid #eef0f3;border-radius:8px;box-shadow:none!important;font-size:14px}.card-footer{background:transparent;border-top:1px solid #eef0f3}.card-footer .footer-note{color:#5a6473;font-size:.875rem}.card-footer .footer-tos-link{color:#5a6473;font-weight:500;text-decoration:underline}.card-footer .footer-tos-link:hover{color:var(--first)}.badge{font-weight:600;border-radius:4px}.badge.bg-success{background-color:#e6f4ec!important;color:#0f6b3a!important}.badge.bg-danger{background-color:#fbeae8!important;color:#c0392b!important}.badge.bg-warning{background-color:#fbf1e3!important;color:#8a5a00!important}.badge.bg-grey,.badge.bg-role-admin{background-color:#eef0f3!important;color:#5a6473!important}code{color:var(--text);min-width:0}.danger-zone{border-top:1px solid #e2e5ea;padding-top:16px;text-align:right}\n"] }]
|
|
1814
1912
|
}], ctorParameters: () => [{ type: i1$2.SubscriptionService }, { type: i2$1.AdminService }, { type: i1$1.NgbModal }, { type: i4$2.Store }, { type: i5$1.Clipboard }, { type: i0.Injector }, { type: i0.ChangeDetectorRef }], propDecorators: { menu: [{
|
|
1815
1913
|
type: ViewChild,
|
|
1816
1914
|
args: ['menuItems', { static: false }]
|
|
@@ -1888,7 +1986,7 @@ class UserInvoiceComponent extends AppBaseComponent {
|
|
|
1888
1986
|
}
|
|
1889
1987
|
}
|
|
1890
1988
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: UserInvoiceComponent, deps: [{ token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1891
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: UserInvoiceComponent, isStandalone: false, selector: "pw-user-invoice", usesInheritance: true, ngImport: i0, template: "<div class=\"row\" [class.custom-disable-wrapper]=\"buttonBusy\">\n <div class=\"col-12 d-flex flex-wrap justify-content-between align-items-center\">\n <h2 class=\"card-title p-0 float-start\">Your Invoices</h2>\n </div>\n</div>\n\n@if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"></p-progressSpinner>\n </div>\n}\n<div class=\"row primeng-datatable-container actions-collapsed mt-0\" [class.custom-disable-wrapper]=\"buttonBusy\" [class.hideTable]=\"totalRecordsUnFiltered === 0\">\n <div class=\"col-12 px-0\">\n <p-table #tt\n [value]=\"invoices\"\n [paginator]=\"totalRecords !== 0\"\n [rows]=\"PAGE_SIZE\"\n [lazy]=\"true\"\n [totalRecords]=\"totalRecords\"\n (onLazyLoad)=\"onLazyLoad($event)\"\n >\n <ng-template pTemplate=\"caption\">\n <div class=\"search-filter justify-content-end\">\n <div class=\"text-end\">\n <label for=\"user-invoice-search\" class=\"visually-hidden\">Search Invoices</label>\n <p-iconfield iconPosition=\"left\">\n <p-inputicon><i class=\"fa fa-search\" aria-hidden=\"true\"></i></p-inputicon>\n <input id=\"user-invoice-search\"\n name=\"user-invoice-search\"\n [(ngModel)]=\"searchText\"\n (input)=\"tt.filterGlobal($event.target.value, 'contains')\"\n type=\"text\"\n pInputText\n placeholder=\"Search Invoices...\"\n data-cy=\"incident-search\" />\n </p-iconfield>\n </div>\n </div>\n </ng-template>\n\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"col\" pSortableColumn=\"date\">Invoice Date <p-sortIcon field=\"date\"></p-sortIcon></th>\n <th scope=\"col\" pSortableColumn=\"frequency\">Frequency <p-sortIcon field=\"frequency\"></p-sortIcon></th>\n <th scope=\"col\" pSortableColumn=\"seatsPurchased\">Seats Purchased <p-sortIcon field=\"seatsPurchased\"></p-sortIcon></th>\n <th scope=\"col\" pSortableColumn=\"subtotal\">Subtotal <p-sortIcon field=\"subtotal\"></p-sortIcon></th>\n <th scope=\"col\" pSortableColumn=\"total\">Total (incl. tax) <p-sortIcon field=\"total\"></p-sortIcon></th>\n <th scope=\"col\">Action</th>\n </tr>\n </ng-template>\n\n <ng-template pTemplate=\"body\" let-invoice>\n <tr>\n <td>{{ invoice.date | date:'dd-MMM-yyyy' }}</td>\n <td>\n <span class=\"badge\"\n [appDynamicBadge]=\"{\n itemsArray: invoiceFrequency,\n item: invoice.product.billing_frequency\n }\"\n color=\"blue-grey\">{{ invoice.product.billing_frequency }}</span>\n </td>\n <td>{{ invoice?.subscription_product?.purchased_units }}</td>\n <td>{{ (invoice.subtotal_in_cents / 100) | currency:invoice?.product?.currency }}</td>\n <td class=\"td-total\">{{ (invoice.total_in_cents / 100) | currency:invoice?.product?.currency }}</td>\n <td>\n @if (invoice?.file?.url) {\n <a class=\"btn btn-sm btn-primary\" [attr.href]=\"invoice.file.url\" target=\"_blank\" title=\"Download\">\n <i class=\"fa fa-download\"> Download</i>\n </a>\n } @else {\n <a class=\"btn btn-sm btn-primary\" [attr.href]=\"invoice?.stripe_invoice_pdf\" target=\"_blank\" title=\"Download\">\n <i class=\"fa fa-download\"> Download</i>\n </a>\n }\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (totalRecords === 0 && totalRecordsUnFiltered !== 0) {\n <div>\n <pw-no-data [withImage]=\"true\" [message]=\"'Search.NoDataMessage' | transloco\" [description]=\"'Search.NoDataDescription' | transloco\" >\n </pw-no-data>\n </div>\n }\n\n @if (totalRecords !== 0) {\n <pw-records-summary [showing]=\"tt?.value?.length ?? 0\" [total]=\"totalRecords\" />\n }\n\n </div>\n</div>\n@if (totalRecordsUnFiltered === 0 && isLoaded) {\n <pw-no-data [withImage]=\"true\" message=\"You don't have any invoice yet.\">\n </pw-no-data>\n}\n\n", styles: [".page-heading{background:#fcfcfc;border-bottom:1px solid rgba(0,0,0,.1);position:relative;width:100%}.page-heading:after{clear:both;content:\"\";display:table}.page-heading .page-heading__container{padding:15px 20px;position:relative}.page-heading .page-heading__container .title{color:#242437;font-size:15px;font-weight:500;line-height:20px;margin:3px 0 0;overflow:hidden;padding:0;text-overflow:ellipsis;width:95%}.card .card-container{position:absolute;right:20px;top:25px;z-index:1}.td-total{font-weight:700}.card-inner-container{background:#0000000d;border:1px dashed rgba(0,0,0,.1);border-radius:3px;margin-bottom:20px;padding:20px}.invoice-text{display:flex;font-size:13px;justify-content:space-between;margin:10px 0}.invoice-template{min-height:calc(100vh - 190px)}\n"], dependencies: [{ kind: "directive", type: i1$3.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "directive", type: i4.DynamicBadgeDirective, selector: "[appDynamicBadge]", inputs: ["appDynamicBadge", "color", "colorByName", "dataName"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "component", type: i4$3.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i5$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i4$3.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i4$3.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type:
|
|
1989
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: UserInvoiceComponent, isStandalone: false, selector: "pw-user-invoice", usesInheritance: true, ngImport: i0, template: "<div class=\"row\" [class.custom-disable-wrapper]=\"buttonBusy\">\n <div class=\"col-12 d-flex flex-wrap justify-content-between align-items-center\">\n <h2 class=\"card-title p-0 float-start\">Your Invoices</h2>\n </div>\n</div>\n\n@if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"></p-progressSpinner>\n </div>\n}\n<div class=\"row primeng-datatable-container actions-collapsed mt-0\" [class.custom-disable-wrapper]=\"buttonBusy\" [class.hideTable]=\"totalRecordsUnFiltered === 0\">\n <div class=\"col-12 px-0\">\n <p-table #tt\n [value]=\"invoices\"\n [paginator]=\"totalRecords !== 0\"\n [rows]=\"PAGE_SIZE\"\n [lazy]=\"true\"\n [totalRecords]=\"totalRecords\"\n (onLazyLoad)=\"onLazyLoad($event)\"\n >\n <ng-template pTemplate=\"caption\">\n <div class=\"search-filter justify-content-end\">\n <div class=\"text-end\">\n <label for=\"user-invoice-search\" class=\"visually-hidden\">Search Invoices</label>\n <p-iconfield iconPosition=\"left\">\n <p-inputicon><i class=\"fa fa-search\" aria-hidden=\"true\"></i></p-inputicon>\n <input id=\"user-invoice-search\"\n name=\"user-invoice-search\"\n [(ngModel)]=\"searchText\"\n (input)=\"tt.filterGlobal($event.target.value, 'contains')\"\n type=\"text\"\n pInputText\n placeholder=\"Search Invoices...\"\n data-cy=\"incident-search\" />\n </p-iconfield>\n </div>\n </div>\n </ng-template>\n\n <ng-template pTemplate=\"header\">\n <tr>\n <th scope=\"col\" pSortableColumn=\"date\">Invoice Date <p-sortIcon field=\"date\"></p-sortIcon></th>\n <th scope=\"col\" pSortableColumn=\"frequency\">Frequency <p-sortIcon field=\"frequency\"></p-sortIcon></th>\n <th scope=\"col\" pSortableColumn=\"seatsPurchased\">Seats Purchased <p-sortIcon field=\"seatsPurchased\"></p-sortIcon></th>\n <th scope=\"col\" pSortableColumn=\"subtotal\">Subtotal <p-sortIcon field=\"subtotal\"></p-sortIcon></th>\n <th scope=\"col\" pSortableColumn=\"total\">Total (incl. tax) <p-sortIcon field=\"total\"></p-sortIcon></th>\n <th scope=\"col\">Action</th>\n </tr>\n </ng-template>\n\n <ng-template pTemplate=\"body\" let-invoice>\n <tr>\n <td>{{ invoice.date | date:'dd-MMM-yyyy' }}</td>\n <td>\n <span class=\"badge\"\n [appDynamicBadge]=\"{\n itemsArray: invoiceFrequency,\n item: invoice.product.billing_frequency\n }\"\n color=\"blue-grey\">{{ invoice.product.billing_frequency }}</span>\n </td>\n <td>{{ invoice?.subscription_product?.purchased_units }}</td>\n <td>{{ (invoice.subtotal_in_cents / 100) | currency:invoice?.product?.currency }}</td>\n <td class=\"td-total\">{{ (invoice.total_in_cents / 100) | currency:invoice?.product?.currency }}</td>\n <td>\n @if (invoice?.file?.url) {\n <a class=\"btn btn-sm btn-primary\" [attr.href]=\"invoice.file.url\" target=\"_blank\" title=\"Download\">\n <i class=\"fa fa-download\"> Download</i>\n </a>\n } @else {\n <a class=\"btn btn-sm btn-primary\" [attr.href]=\"invoice?.stripe_invoice_pdf\" target=\"_blank\" title=\"Download\">\n <i class=\"fa fa-download\"> Download</i>\n </a>\n }\n </td>\n </tr>\n </ng-template>\n </p-table>\n @if (totalRecords === 0 && totalRecordsUnFiltered !== 0) {\n <div>\n <pw-no-data [withImage]=\"true\" [message]=\"'Search.NoDataMessage' | transloco\" [description]=\"'Search.NoDataDescription' | transloco\" >\n </pw-no-data>\n </div>\n }\n\n @if (totalRecords !== 0) {\n <pw-records-summary [showing]=\"tt?.value?.length ?? 0\" [total]=\"totalRecords\" />\n }\n\n </div>\n</div>\n@if (totalRecordsUnFiltered === 0 && isLoaded) {\n <pw-no-data [withImage]=\"true\" message=\"You don't have any invoice yet.\">\n </pw-no-data>\n}\n\n", styles: [".page-heading{background:#fcfcfc;border-bottom:1px solid rgba(0,0,0,.1);position:relative;width:100%}.page-heading:after{clear:both;content:\"\";display:table}.page-heading .page-heading__container{padding:15px 20px;position:relative}.page-heading .page-heading__container .title{color:#242437;font-size:15px;font-weight:500;line-height:20px;margin:3px 0 0;overflow:hidden;padding:0;text-overflow:ellipsis;width:95%}.card .card-container{position:absolute;right:20px;top:25px;z-index:1}.td-total{font-weight:700}.card-inner-container{background:#0000000d;border:1px dashed rgba(0,0,0,.1);border-radius:3px;margin-bottom:20px;padding:20px}.invoice-text{display:flex;font-size:13px;justify-content:space-between;margin:10px 0}.invoice-template{min-height:calc(100vh - 190px)}\n"], dependencies: [{ kind: "directive", type: i1$3.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "directive", type: i4.DynamicBadgeDirective, selector: "[appDynamicBadge]", inputs: ["appDynamicBadge", "color", "colorByName", "dataName"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "component", type: i4$3.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i5$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i4$3.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "component", type: i4$3.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i7.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "component", type: i7.RecordsSummaryComponent, selector: "pw-records-summary", inputs: ["showing", "total"] }, { kind: "pipe", type: i5.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i5.DatePipe, name: "date" }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
1892
1990
|
}
|
|
1893
1991
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: UserInvoiceComponent, decorators: [{
|
|
1894
1992
|
type: Component,
|
|
@@ -1967,7 +2065,7 @@ class CommunicationTabComponent extends AppBaseComponent {
|
|
|
1967
2065
|
// });
|
|
1968
2066
|
}
|
|
1969
2067
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: CommunicationTabComponent, deps: [{ token: i1$2.CommonService }, { token: i1$2.ProfileService }, { token: i4$2.Store }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
1970
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: CommunicationTabComponent, isStandalone: false, selector: "pw-communication-tab", usesInheritance: true, ngImport: i0, template: "<div class=\"communication-settings\">\n <h2>{{ 'User.Settings.Communications.Title' | transloco }}</h2>\n\n <p class=\"settings-intro\">{{ 'User.Settings.Communications.Intro1' | transloco }}</p>\n <p class=\"settings-intro\">{{ 'User.Settings.Communications.Intro2' | transloco }}</p>\n\n @if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n\n @if (isLoaded && subscriptions.length > 0) {\n <ul class=\"pref-list\">\n @for (item of subscriptions; track item; let idx = $index) {\n @if (item.visible || item.enabled) {\n <li class=\"pref-row\">\n <span class=\"pref-name\" [id]=\"'communication-tab-' + idx\">{{ item.name }}</span>\n <ui-switch [checked]=\"item.enabled\"\n [attr.aria-labelledby]=\"'communication-tab-' + idx\"\n (valueChange)=\"onValueChange(item, $event)\">\n </ui-switch>\n </li>\n }\n }\n </ul>\n }\n\n @if (isLoaded && subscriptions.length === 0) {\n <pw-no-data [withImage]=\"true\"\n [message]=\"'User.Settings.Communications.NoDataMessage' | transloco\">\n </pw-no-data>\n }\n</div>\n", styles: [":host{display:block}.communication-settings{max-width:800px}.settings-intro{color:#5a6473;font-size:14px;line-height:1.55;margin-bottom:.75rem}.pref-list{list-style:none;margin:1.75rem 0 0;padding:0;border-top:1px solid #e2e5ea}.pref-row{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 4px;border-bottom:1px solid #e2e5ea}.pref-name{flex:1 1 auto;min-width:0;color:var(--text, #222);font-size:14px;font-weight:500;line-height:1.4}\n"], dependencies: [{ kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: i11$1.UiSwitchComponent, selector: "ui-switch", inputs: ["size", "color", "switchOffColor", "switchColor", "defaultBgColor", "defaultBoColor", "checkedLabel", "uncheckedLabel", "checkedTextColor", "uncheckedTextColor", "beforeChange", "ariaLabel", "checked", "disabled", "reverse", "loading"], outputs: ["change", "changeEvent", "valueChange"] }, { kind: "component", type:
|
|
2068
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: CommunicationTabComponent, isStandalone: false, selector: "pw-communication-tab", usesInheritance: true, ngImport: i0, template: "<div class=\"communication-settings\">\n <h2>{{ 'User.Settings.Communications.Title' | transloco }}</h2>\n\n <p class=\"settings-intro\">{{ 'User.Settings.Communications.Intro1' | transloco }}</p>\n <p class=\"settings-intro\">{{ 'User.Settings.Communications.Intro2' | transloco }}</p>\n\n @if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\">\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n\n @if (isLoaded && subscriptions.length > 0) {\n <ul class=\"pref-list\">\n @for (item of subscriptions; track item; let idx = $index) {\n @if (item.visible || item.enabled) {\n <li class=\"pref-row\">\n <span class=\"pref-name\" [id]=\"'communication-tab-' + idx\">{{ item.name }}</span>\n <ui-switch [checked]=\"item.enabled\"\n [attr.aria-labelledby]=\"'communication-tab-' + idx\"\n (valueChange)=\"onValueChange(item, $event)\">\n </ui-switch>\n </li>\n }\n }\n </ul>\n }\n\n @if (isLoaded && subscriptions.length === 0) {\n <pw-no-data [withImage]=\"true\"\n [message]=\"'User.Settings.Communications.NoDataMessage' | transloco\">\n </pw-no-data>\n }\n</div>\n", styles: [":host{display:block}.communication-settings{max-width:800px}.settings-intro{color:#5a6473;font-size:14px;line-height:1.55;margin-bottom:.75rem}.pref-list{list-style:none;margin:1.75rem 0 0;padding:0;border-top:1px solid #e2e5ea}.pref-row{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 4px;border-bottom:1px solid #e2e5ea}.pref-name{flex:1 1 auto;min-width:0;color:var(--text, #222);font-size:14px;font-weight:500;line-height:1.4}\n"], dependencies: [{ kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: i11$1.UiSwitchComponent, selector: "ui-switch", inputs: ["size", "color", "switchOffColor", "switchColor", "defaultBgColor", "defaultBoColor", "checkedLabel", "uncheckedLabel", "checkedTextColor", "uncheckedTextColor", "beforeChange", "ariaLabel", "checked", "disabled", "reverse", "loading"], outputs: ["change", "changeEvent", "valueChange"] }, { kind: "component", type: i7.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
1971
2069
|
}
|
|
1972
2070
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: CommunicationTabComponent, decorators: [{
|
|
1973
2071
|
type: Component,
|
|
@@ -2036,7 +2134,7 @@ class OthersTabComponent extends AppBaseComponent {
|
|
|
2036
2134
|
super.ngOnDestroy();
|
|
2037
2135
|
}
|
|
2038
2136
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: OthersTabComponent, deps: [{ token: i1$2.CommonService }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2039
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: OthersTabComponent, isStandalone: false, selector: "pw-others-tab", usesInheritance: true, ngImport: i0, template: "<div class=\"row\">\n <div class=\"col-12\">\n <h2>Other</h2>\n </div>\n</div>\n@if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n}\n@if (isLoaded && globalConfigs?.length) {\n <div class=\"row mt-4 pt-1\"\n >\n <div class=\"col-md-6 col-sm-6\">\n @for (item of globalConfigs; track item; let idx = $index) {\n <div class=\"mb-3\">\n <div class=\"row\">\n <div class=\"col-md-10 col-sm-6\">\n <span class=\"pw-label-style\" [id]=\"'others-tab-' + idx\"> {{ item?.name }} </span>\n </div>\n <div class=\"col-md-2 col-sm-6\">\n <ui-switch [checked]=\"item.value === 'true'\"\n [attr.aria-labelledby]=\"'others-tab-' + idx\"\n (valueChange)=\"onValueChange(item, $event)\">\n </ui-switch>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n}\n\n@if (isLoaded && !globalConfigs?.length) {\n <div>\n <pw-no-data [withImage]=\"true\" [message]=\"'User.OtherSettings.NoDataMessage' | transloco\"> </pw-no-data>\n </div>\n}\n", dependencies: [{ kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: i11$1.UiSwitchComponent, selector: "ui-switch", inputs: ["size", "color", "switchOffColor", "switchColor", "defaultBgColor", "defaultBoColor", "checkedLabel", "uncheckedLabel", "checkedTextColor", "uncheckedTextColor", "beforeChange", "ariaLabel", "checked", "disabled", "reverse", "loading"], outputs: ["change", "changeEvent", "valueChange"] }, { kind: "component", type:
|
|
2137
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: OthersTabComponent, isStandalone: false, selector: "pw-others-tab", usesInheritance: true, ngImport: i0, template: "<div class=\"row\">\n <div class=\"col-12\">\n <h2>Other</h2>\n </div>\n</div>\n@if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n}\n@if (isLoaded && globalConfigs?.length) {\n <div class=\"row mt-4 pt-1\"\n >\n <div class=\"col-md-6 col-sm-6\">\n @for (item of globalConfigs; track item; let idx = $index) {\n <div class=\"mb-3\">\n <div class=\"row\">\n <div class=\"col-md-10 col-sm-6\">\n <span class=\"pw-label-style\" [id]=\"'others-tab-' + idx\"> {{ item?.name }} </span>\n </div>\n <div class=\"col-md-2 col-sm-6\">\n <ui-switch [checked]=\"item.value === 'true'\"\n [attr.aria-labelledby]=\"'others-tab-' + idx\"\n (valueChange)=\"onValueChange(item, $event)\">\n </ui-switch>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n}\n\n@if (isLoaded && !globalConfigs?.length) {\n <div>\n <pw-no-data [withImage]=\"true\" [message]=\"'User.OtherSettings.NoDataMessage' | transloco\"> </pw-no-data>\n </div>\n}\n", dependencies: [{ kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: i11$1.UiSwitchComponent, selector: "ui-switch", inputs: ["size", "color", "switchOffColor", "switchColor", "defaultBgColor", "defaultBoColor", "checkedLabel", "uncheckedLabel", "checkedTextColor", "uncheckedTextColor", "beforeChange", "ariaLabel", "checked", "disabled", "reverse", "loading"], outputs: ["change", "changeEvent", "valueChange"] }, { kind: "component", type: i7.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
2040
2138
|
}
|
|
2041
2139
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: OthersTabComponent, decorators: [{
|
|
2042
2140
|
type: Component,
|
|
@@ -2221,7 +2319,7 @@ class SettingsComponent {
|
|
|
2221
2319
|
this.activeItem = this.menu['activeItem'];
|
|
2222
2320
|
}
|
|
2223
2321
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: SettingsComponent, deps: [{ token: i1.Router }, { token: i1$2.PermissionService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2224
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.6", type: SettingsComponent, isStandalone: false, selector: "pw-settings", viewQueries: [{ propertyName: "menu", first: true, predicate: ["menuItems"], descendants: true, static: true }], ngImport: i0, template: "<pw-tabs [items]=\"items\"></pw-tabs>\n", dependencies: [{ kind: "component", type:
|
|
2322
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.6", type: SettingsComponent, isStandalone: false, selector: "pw-settings", viewQueries: [{ propertyName: "menu", first: true, predicate: ["menuItems"], descendants: true, static: true }], ngImport: i0, template: "<pw-tabs [items]=\"items\"></pw-tabs>\n", dependencies: [{ kind: "component", type: i7.PwTabsComponent, selector: "pw-tabs", inputs: ["items", "withSubscription"] }] }); }
|
|
2225
2323
|
}
|
|
2226
2324
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: SettingsComponent, decorators: [{
|
|
2227
2325
|
type: Component,
|
|
@@ -2258,7 +2356,7 @@ class SupportComponent extends AppBaseComponent {
|
|
|
2258
2356
|
});
|
|
2259
2357
|
}
|
|
2260
2358
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: SupportComponent, deps: [{ token: i0.Injector }, { token: i1$2.CommonService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2261
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: SupportComponent, isStandalone: false, selector: "pw-support", usesInheritance: true, ngImport: i0, template: "<div class=\"row m-3\">\n <div class=\"col-12 mb-3\">\n <div\n class=\"col-12 d-flex flex-wrap justify-content-between align-items-center mt-4\">\n <h2 class=\"card-title p-0 float-start\">Support Center</h2>\n <a routerLink=\"/support-details/add\"\n aria-label=\"Navigate to Target\"\n class=\"btn btn-sm btn-outline-primary float-end\"\n tabindex=\"0\"\n (keydown)=\"$event.key === 'Enter' && $event.target.click()\"\n aria-expanded=\"false\">\n <i class=\"fa fa-plus-circle\"\n aria-hidden=\"true\"></i>\n Create new support request\n </a>\n </div>\n </div>\n <div class=\"col-12 my-3\">\n <h3>Previous support requests</h3>\n <p>Please note that responses to your support requests are sent directly to your email. You can simply reply to those\n emails for further assistance.</p>\n </div>\n @if (isLoading) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n @if (supports?.length) {\n <div class=\"col-12 mb-3\">\n <p-accordion>\n @for (item of supports; track item; let i = $index) {\n <p-accordion-panel [value]=\"i\">\n <p-accordion-header>{{ item?.created_at | dateFormat }} ({{ item?.user_name }}) {{ item?.title }}</p-accordion-header>\n <p-accordion-content>\n <p>{{ item?.description }}</p>\n <a [href]=\"item?.attachment?.version_200x200?.url\"\n target=\"_blank\">\n @if (item?.attachment?.version_200x200?.url) {\n <img alt=\"version_200x200\"\n [src]=\"item?.attachment?.version_200x200?.url\"\n class=\"img-fluid\" />\n }</a>\n </p-accordion-content>\n </p-accordion-panel>\n }\n </p-accordion>\n </div>\n }\n @if (!supports?.length && isLoaded) {\n <div class=\"col-12\"\n >\n <pw-no-data [withImage]=\"true\" message=\"No support requests found\"> </pw-no-data>\n </div>\n }\n </div>\n", styles: [".contact-support{font-size:24px;font-weight:600}\n"], dependencies: [{ kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type:
|
|
2359
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: SupportComponent, isStandalone: false, selector: "pw-support", usesInheritance: true, ngImport: i0, template: "<div class=\"row m-3\">\n <div class=\"col-12 mb-3\">\n <div\n class=\"col-12 d-flex flex-wrap justify-content-between align-items-center mt-4\">\n <h2 class=\"card-title p-0 float-start\">Support Center</h2>\n <a routerLink=\"/support-details/add\"\n aria-label=\"Navigate to Target\"\n class=\"btn btn-sm btn-outline-primary float-end\"\n tabindex=\"0\"\n (keydown)=\"$event.key === 'Enter' && $event.target.click()\"\n aria-expanded=\"false\">\n <i class=\"fa fa-plus-circle\"\n aria-hidden=\"true\"></i>\n Create new support request\n </a>\n </div>\n </div>\n <div class=\"col-12 my-3\">\n <h3>Previous support requests</h3>\n <p>Please note that responses to your support requests are sent directly to your email. You can simply reply to those\n emails for further assistance.</p>\n </div>\n @if (isLoading) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n @if (supports?.length) {\n <div class=\"col-12 mb-3\">\n <p-accordion>\n @for (item of supports; track item; let i = $index) {\n <p-accordion-panel [value]=\"i\">\n <p-accordion-header>{{ item?.created_at | dateFormat }} ({{ item?.user_name }}) {{ item?.title }}</p-accordion-header>\n <p-accordion-content>\n <p>{{ item?.description }}</p>\n <a [href]=\"item?.attachment?.version_200x200?.url\"\n target=\"_blank\">\n @if (item?.attachment?.version_200x200?.url) {\n <img alt=\"version_200x200\"\n [src]=\"item?.attachment?.version_200x200?.url\"\n class=\"img-fluid\" />\n }</a>\n </p-accordion-content>\n </p-accordion-panel>\n }\n </p-accordion>\n </div>\n }\n @if (!supports?.length && isLoaded) {\n <div class=\"col-12\"\n >\n <pw-no-data [withImage]=\"true\" message=\"No support requests found\"> </pw-no-data>\n </div>\n }\n </div>\n", styles: [".contact-support{font-size:24px;font-weight:600}\n"], dependencies: [{ kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: i7.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "component", type: i2$2.Accordion, selector: "p-accordion", inputs: ["value", "multiple", "styleClass", "expandIcon", "collapseIcon", "selectOnFocus", "transitionOptions", "motionOptions"], outputs: ["valueChange", "onClose", "onOpen"] }, { kind: "component", type: i2$2.AccordionPanel, selector: "p-accordion-panel, p-accordionpanel", inputs: ["value", "disabled"], outputs: ["valueChange"] }, { kind: "component", type: i2$2.AccordionHeader, selector: "p-accordion-header, p-accordionheader" }, { kind: "component", type: i2$2.AccordionContent, selector: "p-accordion-content, p-accordioncontent" }, { kind: "pipe", type: i6$1.DateFormatPipe, name: "dateFormat" }] }); }
|
|
2262
2360
|
}
|
|
2263
2361
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: SupportComponent, decorators: [{
|
|
2264
2362
|
type: Component,
|
|
@@ -2357,7 +2455,7 @@ class SupportDetailsComponent extends AppBaseComponent {
|
|
|
2357
2455
|
HelperService.onUploadError(event, this.toast);
|
|
2358
2456
|
}
|
|
2359
2457
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: SupportDetailsComponent, deps: [{ token: i0.Injector }, { token: i1$2.CommonService }, { token: i1$2.AuthService }, { token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2360
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: SupportDetailsComponent, isStandalone: false, selector: "pw-support-details", usesInheritance: true, ngImport: i0, template: "<div class=\"container-fluid pw-tab overflow-hidden\">\n <div class=\"dashboard\">\n <div class=\"dashboard-body\">\n <div class=\"me-auto col-xs-6 mt-4\">\n <a aria-label=\"Navigate to Target\" (click)=\"back()\" class=\"previous\"><i\n class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i></a>\n <h3 class=\"mt-3\">{{ 'Label.NewSupport' | transloco }}</h3>\n </div>\n <div class=\"p-2 m-1 mt-3\">\n <form [formGroup]=\"form\"\n (ngSubmit)=\"onSave()\">\n <div class=\"row\">\n <div class=\"col-12\">\n <pw-input-container controlId=\"support-details-title\"\n label=\"title\"\n name=\"title\"\n errorMsg=\"Title is required\">\n <input type=\"text\"\n id=\"support-details-title\"\n class=\"form-control\"\n [placeholder]=\"'Support.Placeholder.Title' | transloco\"\n formControlName=\"title\" />\n </pw-input-container>\n </div>\n <div class=\"col-12\">\n <pw-input-container controlId=\"support-details-description\"\n label=\"Description\"\n errorMsg=\"description is required\"\n name=\"description\">\n <textarea rows=\"3\"\n id=\"support-details-description\"\n type=\"text\"\n class=\"form-control\"\n [placeholder]=\"'Support.Placeholder.Description' | transloco\"\n formControlName=\"description\"></textarea>\n </pw-input-container>\n </div>\n <div class=\"col-12\">\n <div class=\"mb-3 file-upload-support-details\">\n <span id=\"support-details-file-label\" class=\"pw-label-style\">Upload Picture</span>\n <p-fileUpload #forms\n [attr.aria-labelledby]=\"'support-details-file-label'\"\n name=\"myfile[]\"\n [customUpload]=\"true\"\n [showUploadButton]=\"false\"\n accept=\"image/*\"\n [disabled]=\"uploadedFiles && uploadedFiles.length > 0\"\n (onSelect)=\"onSelect($event)\"\n (onRemove)=\"onRemove($event)\"\n (onError)=\"onUploadError($event)\">\n <ng-template pTemplate=\"content\">\n @if (!uploadedFiles?.length) {\n <div class=\"drag-drop-text\">\n <p>You can drag and drop your file here</p>\n </div>\n }\n </ng-template>\n </p-fileUpload>\n </div>\n </div>\n @if (isLoading) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n <div class=\"col-12 text-end mt-3\">\n @if (isSubmitClicked) {\n <div class=\"support-details-captcha\">\n <ngx-recaptcha2 [ngModelOptions]=\"{ standalone: true }\"\n [siteKey]=\"siteKey\"\n size=\"normal\"\n [(ngModel)]=\"recaptcha\"\n (success)=\"handleSuccess($event)\">\n </ngx-recaptcha2>\n </div>\n }\n @if (!isSubmitClicked) {\n <button type=\"button\"\n class=\"btn btn-outline-default me-2\"\n (click)=\"back()\">\n {{ 'Button.Cancel' | transloco }}\n </button>\n <button type=\"submit\"\n class=\"btn btn-primary\" [disabled]=\"invalidFile\">\n {{ 'Button.Submit' | transloco }}\n </button>\n }\n </div>\n </div>\n </form>\n </div>\n </div>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";::ng-deep .file-upload-support-details .p-fileupload .p-fileupload-content{padding:4rem 1rem}::ng-deep .file-upload-support-details .p-fileupload-content .p-fileupload-files .p-fileupload-row>:first-child{display:none}.support-details-captcha{text-align:-webkit-right}:host .pw-label-style{display:block;height:18px;line-height:18px;margin-bottom:8px}.drag-drop-text{padding:20px;border:2px dashed #ccc;text-align:center;color:#aaa;margin-top:10px}::ng-deep .file-upload-support-details .p-fileupload .p-fileupload-content{padding:1rem}::ng-deep .file-upload-support-details .p-fileupload-content .p-fileupload-files .p-fileupload-row>:first-child{display:flex}\n"], dependencies: [{ kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i5$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type:
|
|
2458
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: SupportDetailsComponent, isStandalone: false, selector: "pw-support-details", usesInheritance: true, ngImport: i0, template: "<div class=\"container-fluid pw-tab overflow-hidden\">\n <div class=\"dashboard\">\n <div class=\"dashboard-body\">\n <div class=\"me-auto col-xs-6 mt-4\">\n <a aria-label=\"Navigate to Target\" (click)=\"back()\" class=\"previous\"><i\n class=\"fa fa-arrow-alt-circle-left\" aria-hidden=\"true\"></i></a>\n <h3 class=\"mt-3\">{{ 'Label.NewSupport' | transloco }}</h3>\n </div>\n <div class=\"p-2 m-1 mt-3\">\n <form [formGroup]=\"form\"\n (ngSubmit)=\"onSave()\">\n <div class=\"row\">\n <div class=\"col-12\">\n <pw-input-container controlId=\"support-details-title\"\n label=\"title\"\n name=\"title\"\n errorMsg=\"Title is required\">\n <input type=\"text\"\n id=\"support-details-title\"\n class=\"form-control\"\n [placeholder]=\"'Support.Placeholder.Title' | transloco\"\n formControlName=\"title\" />\n </pw-input-container>\n </div>\n <div class=\"col-12\">\n <pw-input-container controlId=\"support-details-description\"\n label=\"Description\"\n errorMsg=\"description is required\"\n name=\"description\">\n <textarea rows=\"3\"\n id=\"support-details-description\"\n type=\"text\"\n class=\"form-control\"\n [placeholder]=\"'Support.Placeholder.Description' | transloco\"\n formControlName=\"description\"></textarea>\n </pw-input-container>\n </div>\n <div class=\"col-12\">\n <div class=\"mb-3 file-upload-support-details\">\n <span id=\"support-details-file-label\" class=\"pw-label-style\">Upload Picture</span>\n <p-fileUpload #forms\n [attr.aria-labelledby]=\"'support-details-file-label'\"\n name=\"myfile[]\"\n [customUpload]=\"true\"\n [showUploadButton]=\"false\"\n accept=\"image/*\"\n [disabled]=\"uploadedFiles && uploadedFiles.length > 0\"\n (onSelect)=\"onSelect($event)\"\n (onRemove)=\"onRemove($event)\"\n (onError)=\"onUploadError($event)\">\n <ng-template pTemplate=\"content\">\n @if (!uploadedFiles?.length) {\n <div class=\"drag-drop-text\">\n <p>You can drag and drop your file here</p>\n </div>\n }\n </ng-template>\n </p-fileUpload>\n </div>\n </div>\n @if (isLoading) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n <div class=\"col-12 text-end mt-3\">\n @if (isSubmitClicked) {\n <div class=\"support-details-captcha\">\n <ngx-recaptcha2 [ngModelOptions]=\"{ standalone: true }\"\n [siteKey]=\"siteKey\"\n size=\"normal\"\n [(ngModel)]=\"recaptcha\"\n (success)=\"handleSuccess($event)\">\n </ngx-recaptcha2>\n </div>\n }\n @if (!isSubmitClicked) {\n <button type=\"button\"\n class=\"btn btn-outline-default me-2\"\n (click)=\"back()\">\n {{ 'Button.Cancel' | transloco }}\n </button>\n <button type=\"submit\"\n class=\"btn btn-primary\" [disabled]=\"invalidFile\">\n {{ 'Button.Submit' | transloco }}\n </button>\n }\n </div>\n </div>\n </form>\n </div>\n </div>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";::ng-deep .file-upload-support-details .p-fileupload .p-fileupload-content{padding:4rem 1rem}::ng-deep .file-upload-support-details .p-fileupload-content .p-fileupload-files .p-fileupload-row>:first-child{display:none}.support-details-captcha{text-align:-webkit-right}:host .pw-label-style{display:block;height:18px;line-height:18px;margin-bottom:8px}.drag-drop-text{padding:20px;border:2px dashed #ccc;text-align:center;color:#aaa;margin-top:10px}::ng-deep .file-upload-support-details .p-fileupload .p-fileupload-content{padding:1rem}::ng-deep .file-upload-support-details .p-fileupload-content .p-fileupload-files .p-fileupload-row>:first-child{display:flex}\n"], dependencies: [{ kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i5$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i7.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "controlId", "useAriaLabelledbyOnly", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "component", type: i6$2.ReCaptcha2Component, selector: "ngx-recaptcha2", inputs: ["theme", "size"] }, { kind: "component", type: i7$2.FileUpload, selector: "p-fileupload, p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "chooseButtonProps", "uploadButtonProps", "cancelButtonProps", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError", "onRemoveUploadedFile"] }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
2361
2459
|
}
|
|
2362
2460
|
__decorate([
|
|
2363
2461
|
ValidateForm('form'),
|
|
@@ -2457,7 +2555,7 @@ class EditPortfoliosComponent {
|
|
|
2457
2555
|
HelperService.onUploadError(event);
|
|
2458
2556
|
}
|
|
2459
2557
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: EditPortfoliosComponent, deps: [{ token: i1$1.NgbModal }, { token: i1$2.ProfileService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2460
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: EditPortfoliosComponent, isStandalone: false, selector: "pw-edit-portfolios", inputs: { id: "id", slug: "slug" }, outputs: { successEvent: "successEvent" }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, static: true }, { propertyName: "uploader", first: true, predicate: ["form"], descendants: true }], ngImport: i0, template: "<ng-template #content\n let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\"\n id=\"modal-basic-title\">Add/Edit Portfolio Item</h4>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n Add a cover image or a downloadable file for your portfolio item\n <p-fileUpload #form\n name=\"myfile[]\"\n [customUpload]=\"true\"\n [showUploadButton]=\"false\"\n accept=\"\"\n [disabled]=\"uploadedFiles && uploadedFiles.length > 0\"\n (onSelect)=\"onSelect($event)\"\n (onRemove)=\"onRemove($event)\"\n (onError)=\"onUploadError($event)\">\n <ng-template pTemplate=\"content\">\n @if (!uploadedFiles?.length) {\n <div class=\"drag-drop-text\">\n <p>You can drag and drop your file here</p>\n </div>\n }\n </ng-template>\n </p-fileUpload>\n <div class=\"ui-fileupload-content ui-widget-content ui-corner-bottom\">\n <div class=\"ui-fileupload-files\">\n <div class=\"\">\n <h5>Uploaded Pictures</h5>\n @for (image of projectPictures; track trackByImage($index, image)) {\n <div\n class=\"ui-fileupload-row d-inline-block\">\n <div>\n <img [src]=\"image?.picture?.version_50x50?.url\"\n alt=\"\"\n width=\"50\" />\n </div>\n <div class=\"pt-1 ps-1\">\n <button icon=\"pi pi-times\"\n type=\"button\"\n (click)=\"deleteProjectPicture(image.id)\"\n class=\"ui-button ui-widget ui-state-default ui-corner-all ui-button-icon-only\">\n <span class=\"ui-button-icon-left ui-clickable pi pi-times\"></span>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\"\n class=\"btn btn-outline-default\"\n (click)=\"modal.close()\">\n Cancel\n </button>\n <button type=\"button\"\n class=\"btn btn-primary\"\n [buttonBusy]=\"busy\"\n (click)=\"onSave(form)\">\n Save\n </button>\n </div>\n</ng-template>\n", styles: [".drag-drop-text{padding:20px;border:2px dashed #ccc;text-align:center;color:#aaa;margin-top:10px}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "directive", type: i5$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: i7.FileUpload, selector: "p-fileupload, p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "chooseButtonProps", "uploadButtonProps", "cancelButtonProps", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError", "onRemoveUploadedFile"] }] }); }
|
|
2558
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: EditPortfoliosComponent, isStandalone: false, selector: "pw-edit-portfolios", inputs: { id: "id", slug: "slug" }, outputs: { successEvent: "successEvent" }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, static: true }, { propertyName: "uploader", first: true, predicate: ["form"], descendants: true }], ngImport: i0, template: "<ng-template #content\n let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\"\n id=\"modal-basic-title\">Add/Edit Portfolio Item</h4>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n Add a cover image or a downloadable file for your portfolio item\n <p-fileUpload #form\n name=\"myfile[]\"\n [customUpload]=\"true\"\n [showUploadButton]=\"false\"\n accept=\"\"\n [disabled]=\"uploadedFiles && uploadedFiles.length > 0\"\n (onSelect)=\"onSelect($event)\"\n (onRemove)=\"onRemove($event)\"\n (onError)=\"onUploadError($event)\">\n <ng-template pTemplate=\"content\">\n @if (!uploadedFiles?.length) {\n <div class=\"drag-drop-text\">\n <p>You can drag and drop your file here</p>\n </div>\n }\n </ng-template>\n </p-fileUpload>\n <div class=\"ui-fileupload-content ui-widget-content ui-corner-bottom\">\n <div class=\"ui-fileupload-files\">\n <div class=\"\">\n <h5>Uploaded Pictures</h5>\n @for (image of projectPictures; track trackByImage($index, image)) {\n <div\n class=\"ui-fileupload-row d-inline-block\">\n <div>\n <img [src]=\"image?.picture?.version_50x50?.url\"\n alt=\"\"\n width=\"50\" />\n </div>\n <div class=\"pt-1 ps-1\">\n <button icon=\"pi pi-times\"\n type=\"button\"\n (click)=\"deleteProjectPicture(image.id)\"\n class=\"ui-button ui-widget ui-state-default ui-corner-all ui-button-icon-only\">\n <span class=\"ui-button-icon-left ui-clickable pi pi-times\"></span>\n </button>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\"\n class=\"btn btn-outline-default\"\n (click)=\"modal.close()\">\n Cancel\n </button>\n <button type=\"button\"\n class=\"btn btn-primary\"\n [buttonBusy]=\"busy\"\n (click)=\"onSave(form)\">\n Save\n </button>\n </div>\n</ng-template>\n", styles: [".drag-drop-text{padding:20px;border:2px dashed #ccc;text-align:center;color:#aaa;margin-top:10px}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "directive", type: i5$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: i7$2.FileUpload, selector: "p-fileupload, p-fileUpload", inputs: ["name", "url", "method", "multiple", "accept", "disabled", "auto", "withCredentials", "maxFileSize", "invalidFileSizeMessageSummary", "invalidFileSizeMessageDetail", "invalidFileTypeMessageSummary", "invalidFileTypeMessageDetail", "invalidFileLimitMessageDetail", "invalidFileLimitMessageSummary", "style", "styleClass", "previewWidth", "chooseLabel", "uploadLabel", "cancelLabel", "chooseIcon", "uploadIcon", "cancelIcon", "showUploadButton", "showCancelButton", "mode", "headers", "customUpload", "fileLimit", "uploadStyleClass", "cancelStyleClass", "removeStyleClass", "chooseStyleClass", "chooseButtonProps", "uploadButtonProps", "cancelButtonProps", "files"], outputs: ["onBeforeUpload", "onSend", "onUpload", "onError", "onClear", "onRemove", "onSelect", "onProgress", "uploadHandler", "onImageError", "onRemoveUploadedFile"] }] }); }
|
|
2461
2559
|
}
|
|
2462
2560
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: EditPortfoliosComponent, decorators: [{
|
|
2463
2561
|
type: Component,
|
|
@@ -2595,7 +2693,7 @@ class EditProjectModalComponent extends AppBaseComponent {
|
|
|
2595
2693
|
});
|
|
2596
2694
|
}
|
|
2597
2695
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: EditProjectModalComponent, deps: [{ token: i1$1.NgbModal }, { token: i2.UntypedFormBuilder }, { token: i1$2.ProfileService }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2598
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.6", type: EditProjectModalComponent, isStandalone: false, selector: "pw-edit-project-modal", outputs: { cancelEvent: "cancelEvent", saveEvent: "saveEvent" }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<ng-template #content\n let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\"\n id=\"modal-basic-title\">{{ title }}</h4>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <form [formGroup]=\"form\">\n <div class=\"row p-2\">\n <!-- Title -->\n <pw-input-container class=\"col-12\"\n controlId=\"edit-project-title\"\n label=\"Title\"\n name=\"title\"\n errorMsg=\"This field is required.\">\n <input type=\"text\"\n id=\"edit-project-title\"\n class=\"form-control\"\n formControlName=\"title\"\n [placeholder]=\"'User.Profile.Projects.Placeholder.Title' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f.title.errors }\" />\n </pw-input-container>\n <!-- Client Name -->\n <pw-input-container class=\"col-12\"\n controlId=\"edit-project-client_name\"\n label=\"Client Name\"\n name=\"client_name\"\n errorMsg=\"This field is required.\">\n <input type=\"text\"\n id=\"edit-project-client_name\"\n class=\"form-control\"\n formControlName=\"client_name\"\n [placeholder]=\"'User.Profile.Projects.Placeholder.ClientName' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f.client_name.errors }\" />\n </pw-input-container>\n <!-- Project Start Year -->\n <pw-input-container class=\"col-12 col-md-4\"\n controlId=\"edit-project-start_year\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Start\"\n name=\"start_year\"\n errorMsg=\"YYYY format date is required\">\n <p-select\n [attr.aria-labelledby]=\"'edit-project-start_year-label'\"\n (onShow)=\"getStartYear()\"\n formControlName=\"start_year\"\n [options]=\"startYears\"\n [placeholder]=\"'User.Profile.Projects.Placeholder.StartYear' | transloco\"\n (onChange)=\"getEndYears($event.value)\"\n [ngClass]=\"{ 'is-invalid': submitted && f.start_year.errors }\">\n </p-select>\n </pw-input-container>\n <!-- Project End Year -->\n <pw-input-container class=\"col-12 col-md-4\"\n controlId=\"edit-project-end_year\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"End\"\n name=\"end_year\"\n errorMsg=\"YYYY format date is required\">\n <p-select\n [attr.aria-labelledby]=\"'edit-project-end_year-label'\"\n formControlName=\"end_year\"\n [options]=\"endYears\"\n [placeholder]=\"'User.Profile.Projects.Placeholder.EndYear' | transloco\"\n (onChange)=\"getEndYears($event.value)\"\n [ngClass]=\"{ 'is-invalid': submitted && f.end_year.errors }\">\n </p-select>\n </pw-input-container>\n <!-- Total Weeks Worked -->\n <pw-input-container class=\"col-12 col-md-4\"\n controlId=\"edit-project-length\"\n label=\"Weeks worked\"\n name=\"length\"\n errorMsg=\"This field is required. (0-5000)\">\n <input type=\"number\"\n id=\"edit-project-length\"\n formControlName=\"length\"\n class=\"form-control\"\n [ngClass]=\"{ 'is-invalid': submitted && f.length.errors }\" />\n </pw-input-container>\n <!-- Description -->\n <pw-input-container class=\"col-12\"\n controlId=\"edit-project-description\"\n label=\"Description\"\n name=\"description\"\n errorMsg=\"This field is required.\">\n <textarea type=\"text\"\n id=\"edit-project-description\"\n class=\"form-control\"\n formControlName=\"description\"\n required\n [placeholder]=\"'User.Profile.Projects.Placeholder.Description' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f.description.errors }\"></textarea>\n </pw-input-container>\n </div>\n </form>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\"\n class=\"btn btn-outline-default\"\n (click)=\"modal.close()\">\n Cancel\n </button>\n <button type=\"submit\"\n [buttonBusy]=\"buttonBusy\"\n class=\"btn btn-primary\"\n (click)=\"onSaveDetail()\">Save</button>\n </div>\n</ng-template>\n", styles: [".ng-valid.is-invalid{background-image:none;border-color:inherit}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type:
|
|
2696
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.6", type: EditProjectModalComponent, isStandalone: false, selector: "pw-edit-project-modal", outputs: { cancelEvent: "cancelEvent", saveEvent: "saveEvent" }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<ng-template #content\n let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\"\n id=\"modal-basic-title\">{{ title }}</h4>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <form [formGroup]=\"form\">\n <div class=\"row p-2\">\n <!-- Title -->\n <pw-input-container class=\"col-12\"\n controlId=\"edit-project-title\"\n label=\"Title\"\n name=\"title\"\n errorMsg=\"This field is required.\">\n <input type=\"text\"\n id=\"edit-project-title\"\n class=\"form-control\"\n formControlName=\"title\"\n [placeholder]=\"'User.Profile.Projects.Placeholder.Title' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f.title.errors }\" />\n </pw-input-container>\n <!-- Client Name -->\n <pw-input-container class=\"col-12\"\n controlId=\"edit-project-client_name\"\n label=\"Client Name\"\n name=\"client_name\"\n errorMsg=\"This field is required.\">\n <input type=\"text\"\n id=\"edit-project-client_name\"\n class=\"form-control\"\n formControlName=\"client_name\"\n [placeholder]=\"'User.Profile.Projects.Placeholder.ClientName' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f.client_name.errors }\" />\n </pw-input-container>\n <!-- Project Start Year -->\n <pw-input-container class=\"col-12 col-md-4\"\n controlId=\"edit-project-start_year\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Start\"\n name=\"start_year\"\n errorMsg=\"YYYY format date is required\">\n <p-select\n [attr.aria-labelledby]=\"'edit-project-start_year-label'\"\n (onShow)=\"getStartYear()\"\n formControlName=\"start_year\"\n [options]=\"startYears\"\n [placeholder]=\"'User.Profile.Projects.Placeholder.StartYear' | transloco\"\n (onChange)=\"getEndYears($event.value)\"\n [ngClass]=\"{ 'is-invalid': submitted && f.start_year.errors }\">\n </p-select>\n </pw-input-container>\n <!-- Project End Year -->\n <pw-input-container class=\"col-12 col-md-4\"\n controlId=\"edit-project-end_year\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"End\"\n name=\"end_year\"\n errorMsg=\"YYYY format date is required\">\n <p-select\n [attr.aria-labelledby]=\"'edit-project-end_year-label'\"\n formControlName=\"end_year\"\n [options]=\"endYears\"\n [placeholder]=\"'User.Profile.Projects.Placeholder.EndYear' | transloco\"\n (onChange)=\"getEndYears($event.value)\"\n [ngClass]=\"{ 'is-invalid': submitted && f.end_year.errors }\">\n </p-select>\n </pw-input-container>\n <!-- Total Weeks Worked -->\n <pw-input-container class=\"col-12 col-md-4\"\n controlId=\"edit-project-length\"\n label=\"Weeks worked\"\n name=\"length\"\n errorMsg=\"This field is required. (0-5000)\">\n <input type=\"number\"\n id=\"edit-project-length\"\n formControlName=\"length\"\n class=\"form-control\"\n [ngClass]=\"{ 'is-invalid': submitted && f.length.errors }\" />\n </pw-input-container>\n <!-- Description -->\n <pw-input-container class=\"col-12\"\n controlId=\"edit-project-description\"\n label=\"Description\"\n name=\"description\"\n errorMsg=\"This field is required.\">\n <textarea type=\"text\"\n id=\"edit-project-description\"\n class=\"form-control\"\n formControlName=\"description\"\n required\n [placeholder]=\"'User.Profile.Projects.Placeholder.Description' | transloco\"\n [ngClass]=\"{ 'is-invalid': submitted && f.description.errors }\"></textarea>\n </pw-input-container>\n </div>\n </form>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\"\n class=\"btn btn-outline-default\"\n (click)=\"modal.close()\">\n Cancel\n </button>\n <button type=\"submit\"\n [buttonBusy]=\"buttonBusy\"\n class=\"btn btn-primary\"\n (click)=\"onSaveDetail()\">Save</button>\n </div>\n</ng-template>\n", styles: [".ng-valid.is-invalid{background-image:none;border-color:inherit}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i7$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i7.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "controlId", "useAriaLabelledbyOnly", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
2599
2697
|
}
|
|
2600
2698
|
__decorate([
|
|
2601
2699
|
ValidateForm('form'),
|
|
@@ -2703,7 +2801,7 @@ class EditQualificationsModalComponent extends AppBaseComponent {
|
|
|
2703
2801
|
});
|
|
2704
2802
|
}
|
|
2705
2803
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: EditQualificationsModalComponent, deps: [{ token: i1$1.NgbModal }, { token: i2.UntypedFormBuilder }, { token: i1$2.QualificationService }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2706
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.6", type: EditQualificationsModalComponent, isStandalone: false, selector: "pw-edit-qualifications-modal", outputs: { saveEvent: "saveEvent" }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<ng-template #content\n let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\"\n id=\"modal-basic-title\">{{ title }}</h4>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <form [formGroup]=\"form\">\n <div class=\"row p-2\">\n <pw-input-container class=\"col-12\"\n controlId=\"edit-qualifications-school\"\n label=\"School\"\n name=\"school\"\n errorMsg=\"This field is required.\">\n <input type=\"text\"\n id=\"edit-qualifications-school\"\n class=\"form-control\"\n [placeholder]=\"'User.Profile.Qualifications.Placeholder.School' | transloco\"\n formControlName=\"school\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-qualifications-started_on\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Dates Attended\"\n name=\"started_on\"\n errorMsg=\"This field is required.\">\n <div class=\"ui-fluid\">\n <p-datepicker inputId=\"edit-qualifications-started_on\" formControlName=\"started_on\"\n [attr.aria-labelledby]=\"'edit-qualifications-started_on-label'\"\n [monthNavigator]=\"true\"\n [yearNavigator]=\"true\"\n yearRange=\"1950:2020\"\n (onSelect)=\"onDateChange()\"\n [showIcon]=\"true\"\n placeholder=\"yyyy-mm-dd\"\n dateFormat=\"yy-mm-dd\">\n </p-datepicker>\n </div>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-qualifications-ended_on\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Dates Completed\"\n name=\"ended_on\"\n errorMsg=\"This field is required.\">\n <div class=\"ui-fluid\">\n <p-datepicker inputId=\"edit-qualifications-ended_on\" formControlName=\"ended_on\"\n [attr.aria-labelledby]=\"'edit-qualifications-ended_on-label'\"\n [monthNavigator]=\"true\"\n [yearNavigator]=\"true\"\n [showIcon]=\"true\"\n (onSelect)=\"onDateChange()\"\n [minDate]=\"minToDate\"\n placeholder=\"yyyy-mm-dd\"\n dateFormat=\"yy-mm-dd\"\n yearRange=\"1950:2025\"></p-datepicker>\n </div>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-qualifications-points\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Degree\"\n name=\"points\"\n errorMsg=\"This field is required.\">\n <p-select inputId=\"edit-qualifications-points\"\n [options]=\"qualifications\"\n [attr.aria-labelledby]=\"'edit-qualifications-points-label'\"\n [placeholder]=\"'User.Profile.Qualifications.Placeholder.Degree' | transloco\"\n formControlName=\"points\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-qualifications-course\"\n label=\"Course\"\n name=\"course\"\n errorMsg=\"This field is required.\">\n <input type=\"text\"\n id=\"edit-qualifications-course\"\n class=\"form-control\"\n [placeholder]=\"'User.Profile.Qualifications.Placeholder.Course' | transloco\"\n formControlName=\"course\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-12\"\n controlId=\"edit-qualifications-description\"\n label=\"Description\"\n name=\"description\">\n <textarea type=\"text\"\n id=\"edit-qualifications-description\"\n class=\"form-control\"\n [placeholder]=\"'User.Profile.Qualifications.Placeholder.Description' | transloco\"\n formControlName=\"description\"></textarea>\n </pw-input-container>\n </div>\n </form>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\"\n class=\"btn btn-outline-default\"\n (click)=\"modal.close()\">\n Cancel\n </button>\n <button type=\"submit\"\n [buttonBusy]=\"buttonBusy\"\n class=\"btn btn-primary\"\n (click)=\"onSaveDetail()\">Save</button>\n </div>\n</ng-template>\n\n<i\n class=\"fa fa-lg pi pi-plus-circle float-end mt-2 pt-1 pt-md-0 profile-icons\"\n data-cy=\"add-qualification\"\n (keydown.enter)=\"onOpen()\"\n aria-label=\"Add Qualification\"\n (click)=\"onOpen()\"\n aria-hidden=\"true\"\n></i>\n", styles: ["@charset \"UTF-8\";:root{--first: rgb(23 105 225);--second: rgb(54 194 131);--third: rgb(255 171 0);--text: rgb(34 34 34);--tabs_bg: rgb(23 105 225);--tabs_sub_bg: rgb(70, 136, 236);--tabs_text: rgb(255 255 255);--titles: rgb(34 34 34);--sidebar_bg: rgb(0, 48, 63);--sidebar_text: rgb(255 255 255)}.btn-add{cursor:pointer;font-size:24px}.profile-icons{color:var(--first)}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type:
|
|
2804
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.6", type: EditQualificationsModalComponent, isStandalone: false, selector: "pw-edit-qualifications-modal", outputs: { saveEvent: "saveEvent" }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<ng-template #content\n let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\"\n id=\"modal-basic-title\">{{ title }}</h4>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <form [formGroup]=\"form\">\n <div class=\"row p-2\">\n <pw-input-container class=\"col-12\"\n controlId=\"edit-qualifications-school\"\n label=\"School\"\n name=\"school\"\n errorMsg=\"This field is required.\">\n <input type=\"text\"\n id=\"edit-qualifications-school\"\n class=\"form-control\"\n [placeholder]=\"'User.Profile.Qualifications.Placeholder.School' | transloco\"\n formControlName=\"school\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-qualifications-started_on\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Dates Attended\"\n name=\"started_on\"\n errorMsg=\"This field is required.\">\n <div class=\"ui-fluid\">\n <p-datepicker inputId=\"edit-qualifications-started_on\" formControlName=\"started_on\"\n [attr.aria-labelledby]=\"'edit-qualifications-started_on-label'\"\n [monthNavigator]=\"true\"\n [yearNavigator]=\"true\"\n yearRange=\"1950:2020\"\n (onSelect)=\"onDateChange()\"\n [showIcon]=\"true\"\n placeholder=\"yyyy-mm-dd\"\n dateFormat=\"yy-mm-dd\">\n </p-datepicker>\n </div>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-qualifications-ended_on\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Dates Completed\"\n name=\"ended_on\"\n errorMsg=\"This field is required.\">\n <div class=\"ui-fluid\">\n <p-datepicker inputId=\"edit-qualifications-ended_on\" formControlName=\"ended_on\"\n [attr.aria-labelledby]=\"'edit-qualifications-ended_on-label'\"\n [monthNavigator]=\"true\"\n [yearNavigator]=\"true\"\n [showIcon]=\"true\"\n (onSelect)=\"onDateChange()\"\n [minDate]=\"minToDate\"\n placeholder=\"yyyy-mm-dd\"\n dateFormat=\"yy-mm-dd\"\n yearRange=\"1950:2025\"></p-datepicker>\n </div>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-qualifications-points\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Degree\"\n name=\"points\"\n errorMsg=\"This field is required.\">\n <p-select inputId=\"edit-qualifications-points\"\n [options]=\"qualifications\"\n [attr.aria-labelledby]=\"'edit-qualifications-points-label'\"\n [placeholder]=\"'User.Profile.Qualifications.Placeholder.Degree' | transloco\"\n formControlName=\"points\"></p-select>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-qualifications-course\"\n label=\"Course\"\n name=\"course\"\n errorMsg=\"This field is required.\">\n <input type=\"text\"\n id=\"edit-qualifications-course\"\n class=\"form-control\"\n [placeholder]=\"'User.Profile.Qualifications.Placeholder.Course' | transloco\"\n formControlName=\"course\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-12\"\n controlId=\"edit-qualifications-description\"\n label=\"Description\"\n name=\"description\">\n <textarea type=\"text\"\n id=\"edit-qualifications-description\"\n class=\"form-control\"\n [placeholder]=\"'User.Profile.Qualifications.Placeholder.Description' | transloco\"\n formControlName=\"description\"></textarea>\n </pw-input-container>\n </div>\n </form>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\"\n class=\"btn btn-outline-default\"\n (click)=\"modal.close()\">\n Cancel\n </button>\n <button type=\"submit\"\n [buttonBusy]=\"buttonBusy\"\n class=\"btn btn-primary\"\n (click)=\"onSaveDetail()\">Save</button>\n </div>\n</ng-template>\n\n<i\n class=\"fa fa-lg pi pi-plus-circle float-end mt-2 pt-1 pt-md-0 profile-icons\"\n data-cy=\"add-qualification\"\n (keydown.enter)=\"onOpen()\"\n aria-label=\"Add Qualification\"\n (click)=\"onOpen()\"\n aria-hidden=\"true\"\n></i>\n", styles: ["@charset \"UTF-8\";:root{--first: rgb(23 105 225);--second: rgb(54 194 131);--third: rgb(255 171 0);--text: rgb(34 34 34);--tabs_bg: rgb(23 105 225);--tabs_sub_bg: rgb(70, 136, 236);--tabs_text: rgb(255 255 255);--titles: rgb(34 34 34);--sidebar_bg: rgb(0, 48, 63);--sidebar_text: rgb(255 255 255)}.btn-add{cursor:pointer;font-size:24px}.profile-icons{color:var(--first)}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i7$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i7.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "controlId", "useAriaLabelledbyOnly", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "component", type: i7$3.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "styleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "readonlyInput", "shortYearCutoff", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "view", "defaultDate", "appendTo", "motionOptions"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
2707
2805
|
}
|
|
2708
2806
|
__decorate([
|
|
2709
2807
|
ValidateForm('form'),
|
|
@@ -2771,7 +2869,7 @@ class EditRecommendationModalComponent {
|
|
|
2771
2869
|
});
|
|
2772
2870
|
}
|
|
2773
2871
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: EditRecommendationModalComponent, deps: [{ token: i1$1.NgbModal }, { token: i2.UntypedFormBuilder }, { token: i1$2.ProfileService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2774
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.6", type: EditRecommendationModalComponent, isStandalone: false, selector: "pw-edit-recommendation-modal", inputs: { user: "user" }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, static: true }], ngImport: i0, template: "<ng-template #content\n let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\"\n id=\"modal-basic-title\">{{ title }}</h4>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <form [formGroup]=\"form\">\n <div class=\"row p-2\">\n <pw-input-container class=\"col-12 col-md-4\"\n controlId=\"edit-recommendation-quality\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Quality\"\n name=\"quality\"\n errorMsg=\"This field is required.\">\n <p-rating formControlName=\"quality\"\n [attr.aria-labelledby]=\"'edit-recommendation-quality-label'\"\n [cancel]=\"false\"></p-rating>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-4\"\n controlId=\"edit-recommendation-communication\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Communication\"\n name=\"communication\"\n errorMsg=\"This field is required.\">\n <p-rating formControlName=\"communication\"\n [attr.aria-labelledby]=\"'edit-recommendation-communication-label'\"\n [cancel]=\"false\"></p-rating>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-4\"\n controlId=\"edit-recommendation-time\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Time\"\n name=\"time\"\n errorMsg=\"This field is required.\">\n <p-rating formControlName=\"time\"\n [attr.aria-labelledby]=\"'edit-recommendation-time-label'\"\n [cancel]=\"false\"></p-rating>\n </pw-input-container>\n\n <pw-input-container class=\"col-12\"\n controlId=\"edit-recommendation-description\"\n label=\"Description\"\n name=\"description\"\n errorMsg=\"This field is required.\">\n <textarea type=\"text\"\n id=\"edit-recommendation-description\"\n class=\"form-control\"\n formControlName=\"description\"></textarea>\n </pw-input-container>\n </div>\n </form>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\"\n class=\"btn btn-outline-default\"\n (click)=\"modal.close()\">\n Cancel\n </button>\n <button type=\"submit\"\n [buttonBusy]=\"buttonBusy\"\n class=\"btn btn-primary\"\n (click)=\"onSaveDetail()\">Save</button>\n </div>\n</ng-template>\n\n<!-- <i class=\"fal fa-plus-circle fa-2x btn-link float-end btn-add\" (click)=\"onOpen()\" aria-hidden=\"true\"></i> -->\n", dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type:
|
|
2872
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.6", type: EditRecommendationModalComponent, isStandalone: false, selector: "pw-edit-recommendation-modal", inputs: { user: "user" }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, static: true }], ngImport: i0, template: "<ng-template #content\n let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\"\n id=\"modal-basic-title\">{{ title }}</h4>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <form [formGroup]=\"form\">\n <div class=\"row p-2\">\n <pw-input-container class=\"col-12 col-md-4\"\n controlId=\"edit-recommendation-quality\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Quality\"\n name=\"quality\"\n errorMsg=\"This field is required.\">\n <p-rating formControlName=\"quality\"\n [attr.aria-labelledby]=\"'edit-recommendation-quality-label'\"\n [cancel]=\"false\"></p-rating>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-4\"\n controlId=\"edit-recommendation-communication\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Communication\"\n name=\"communication\"\n errorMsg=\"This field is required.\">\n <p-rating formControlName=\"communication\"\n [attr.aria-labelledby]=\"'edit-recommendation-communication-label'\"\n [cancel]=\"false\"></p-rating>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-4\"\n controlId=\"edit-recommendation-time\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Time\"\n name=\"time\"\n errorMsg=\"This field is required.\">\n <p-rating formControlName=\"time\"\n [attr.aria-labelledby]=\"'edit-recommendation-time-label'\"\n [cancel]=\"false\"></p-rating>\n </pw-input-container>\n\n <pw-input-container class=\"col-12\"\n controlId=\"edit-recommendation-description\"\n label=\"Description\"\n name=\"description\"\n errorMsg=\"This field is required.\">\n <textarea type=\"text\"\n id=\"edit-recommendation-description\"\n class=\"form-control\"\n formControlName=\"description\"></textarea>\n </pw-input-container>\n </div>\n </form>\n </div>\n <div class=\"modal-footer\">\n <button type=\"button\"\n class=\"btn btn-outline-default\"\n (click)=\"modal.close()\">\n Cancel\n </button>\n <button type=\"submit\"\n [buttonBusy]=\"buttonBusy\"\n class=\"btn btn-primary\"\n (click)=\"onSaveDetail()\">Save</button>\n </div>\n</ng-template>\n\n<!-- <i class=\"fal fa-plus-circle fa-2x btn-link float-end btn-add\" (click)=\"onOpen()\" aria-hidden=\"true\"></i> -->\n", dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i7.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "controlId", "useAriaLabelledbyOnly", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "component", type: i6$3.Rating, selector: "p-rating", inputs: ["readonly", "stars", "iconOnClass", "iconOnStyle", "iconOffClass", "iconOffStyle", "autofocus"], outputs: ["onRate", "onFocus", "onBlur"] }] }); }
|
|
2775
2873
|
}
|
|
2776
2874
|
__decorate([
|
|
2777
2875
|
ValidateForm('form'),
|
|
@@ -3085,7 +3183,7 @@ class EditUserProfileModalComponent extends AppBaseComponent {
|
|
|
3085
3183
|
});
|
|
3086
3184
|
}
|
|
3087
3185
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: EditUserProfileModalComponent, deps: [{ token: i1$1.NgbModal }, { token: i2.UntypedFormBuilder }, { token: i1$2.ProfileService }, { token: i1$2.GeoService }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3088
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: EditUserProfileModalComponent, isStandalone: false, selector: "pw-edit-user-profile-modal", inputs: { slug: "slug", user: "user" }, outputs: { saveEvent: "saveEvent" }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, static: true }, { propertyName: "placesRef", first: true, predicate: ["ngxPlaces"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<ng-template #content\n let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\"\n id=\"modal-basic-title\">Edit Intro</h4>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <form [formGroup]=\"form\"\n (ngSubmit)=\"onSaveDetail()\">\n <div class=\"row\">\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-first-name\"\n label=\"First Name\"\n name=\"first_name\"\n errorMsg=\"Please enter first Name\">\n <input type=\"text\"\n class=\"form-control\"\n formControlName=\"first_name\"\n id=\"edit-intro-first-name\"\n [placeholder]=\"'User.Profile.Intro.Placeholder.FirstName' | transloco\"\n autocomplete=\"given-name\" name=\"input_first_name_1\"/>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-last-name\"\n label=\"Last Name\"\n name=\"last_name\"\n errorMsg=\"Please enter last Name\">\n <input type=\"text\"\n class=\"form-control\"\n formControlName=\"last_name\"\n id=\"edit-intro-last-name\"\n [placeholder]=\"'User.Profile.Intro.Placeholder.LastName' | transloco\"\n autocomplete=\"family-name\" name=\"input_last_name_2\"/>\n </pw-input-container>\n\n <pw-input-container class=\"col-12\"\n controlId=\"edit-intro-headline\"\n label=\"Headline\"\n name=\"headline\"\n errorMsg=\"Please enter headline\">\n <input type=\"text\"\n class=\"form-control\"\n formControlName=\"headline\"\n id=\"edit-intro-headline\"\n [placeholder]=\"'User.Profile.Intro.Placeholder.Headline' | transloco\" name=\"input_headline_3\"/>\n </pw-input-container>\n\n <pw-input-container class=\"col-12\"\n controlId=\"edit-intro-description\"\n label=\"About me\"\n name=\"description\"\n errorMsg=\"Please enter description\">\n <textarea class=\"form-control\"\n id=\"edit-intro-description\"\n name=\"description\"\n [placeholder]=\"'User.Profile.Intro.Placeholder.Description' | transloco\"\n formControlName=\"description\"></textarea>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-gender\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Gender\"\n name=\"gender\"\n errorMsg=\"Please enter Gender\">\n <p-selectButton [options]=\"[\n { label: 'Male', value: 'M' },\n { label: 'Female', value: 'F' }\n ]\"\n [attr.aria-labelledby]=\"'edit-intro-gender-label'\"\n formControlName=\"gender\"></p-selectButton>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-dob\"\n label=\"Date of Birth\"\n name=\"dob\"\n errorMsg=\"Please enter date of birth\">\n <div class=\"input-group\">\n <input class=\"form-control\"\n id=\"edit-intro-dob\"\n name=\"dob\"\n placeholder=\"yyyy-mm-dd\"\n formControlName=\"dob\"\n ngbDatepicker\n #d=\"ngbDatepicker\"\n [minDate]=\"{ year: 1950, month: 1, day: 1 }\"\n [maxDate]=\"{ year: 2018, month: 12, day: 31 }\"\n autocomplete=\"off\" />\n <button class=\"btn btn-primary\"\n type=\"button\"\n aria-label=\"Open date picker\"\n (click)=\"d.toggle()\">\n <i class=\"fa fa-calendar\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-phone\"\n label=\"Phone\"\n name=\"phone_number\"\n errorMsg=\"Please enter phone\">\n <input type=\"text\"\n class=\"form-control\"\n formControlName=\"phone_number\"\n id=\"edit-intro-phone\"\n name=\"phone_number\"\n [placeholder]=\"'User.Profile.Intro.Placeholder.Phone' | transloco\"\n autocomplete=\"tel\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-postcode\"\n label=\"Postcode\"\n name=\"postcode\"\n errorMsg=\"Please enter postcode\">\n <input type=\"text\"\n class=\"form-control\"\n formControlName=\"postcode\"\n id=\"edit-intro-postcode\"\n [placeholder]=\"'User.Profile.Intro.Placeholder.Postcode' | transloco\"\n autocomplete=\"postal-code\" name=\"input_postcode_6\"/>\n </pw-input-container>\n\n @if (countries$ | async; as countries) {\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-country\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Country\"\n name=\"country\"\n errorMsg=\"Please select a country\">\n <p-select\n [attr.aria-labelledby]=\"'edit-intro-country-label'\"\n [options]=\"countries\"\n optionLabel=\"name\"\n optionValue=\"code\"\n formControlName=\"country\"\n (onChange)=\"getRegion($event.value)\"\n [placeholder]=\"'User.Profile.SelectCountry' | transloco\">\n </p-select>\n </pw-input-container>\n }\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-state\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"State\"\n name=\"state\"\n errorMsg=\"Please select a state\">\n <p-select\n [attr.aria-labelledby]=\"'edit-intro-state-label'\"\n [options]=\"states\"\n optionLabel=\"name\"\n optionValue=\"code\"\n formControlName=\"state\"\n [placeholder]=\"'User.Profile.SelectState' | transloco\">\n </p-select>\n </pw-input-container>\n\n <!-- Location -->\n <pw-input-container label=\"Location\"\n class=\"col-12 col-md-6\"\n controlId=\"edit-intro-location\"\n [useAriaLabelledbyOnly]=\"true\"\n name=\"location\">\n <input ngx-gp-autocomplete\n id=\"edit-intro-location\"\n name=\"location\"\n class=\"form-control\"\n #places=\"ngx-places\"\n formControlName=\"location\"\n [placeholder]=\"'User.Profile.Intro.Placeholder.Location' | transloco\"\n [attr.aria-labelledby]=\"'edit-intro-location-label'\"\n (onAddressChange)=\"handleAddressChange($event)\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-website\"\n label=\"Website\"\n name=\"website_url\"\n errorMsg=\"Please enter Website\">\n <input type=\"text\"\n class=\"form-control\"\n formControlName=\"website_url\"\n id=\"edit-intro-website\"\n [placeholder]=\"'User.Profile.Intro.Placeholder.Website' | transloco\"\n autocomplete=\"url\" name=\"input_website_url_8\"/>\n </pw-input-container>\n </div>\n <div class=\"modal-footer\">\n <input type=\"button\"\n class=\"btn btn-outline-default me-2\"\n (click)=\"modal.close()\"\n value=\"Cancel\" id=\"input_field_9\" name=\"input_field_9\"/>\n <input type=\"submit\"\n [buttonBusy]=\"buttonBusy\"\n class=\"btn btn-primary\"\n value=\"Save Changes\" id=\"input_field_10\" name=\"input_field_10\"/>\n </div>\n </form>\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:root{--first: rgb(23 105 225);--second: rgb(54 194 131);--third: rgb(255 171 0);--text: rgb(34 34 34);--tabs_bg: rgb(23 105 225);--tabs_sub_bg: rgb(70, 136, 236);--tabs_text: rgb(255 255 255);--titles: rgb(34 34 34);--sidebar_bg: rgb(0, 48, 63);--sidebar_text: rgb(255 255 255)}::ng-deep .p-selectbutton .p-button{margin-right:1rem}::ng-deep body .p-selectbutton .p-button.p-highlight{background-color:var(--first)!important}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i6$1.NgxGpAutocompleteDirective, selector: "[ngx-gp-autocomplete]", inputs: ["options"], outputs: ["onAddressChange"], exportAs: ["ngx-places"] }, { kind: "component", type: i6$2.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i5.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "controlId", "useAriaLabelledbyOnly", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "component", type: i8$1.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }, { kind: "directive", type: i1$1.NgbInputDatepicker, selector: "input[ngbDatepicker]", inputs: ["autoClose", "contentTemplate", "datepickerClass", "dayTemplate", "dayTemplateData", "displayMonths", "firstDayOfWeek", "footerTemplate", "markDisabled", "minDate", "maxDate", "navigation", "outsideDays", "placement", "popperOptions", "restoreFocus", "showWeekNumbers", "startDate", "container", "positionTarget", "weekdays", "disabled"], outputs: ["dateSelect", "navigate", "closed"], exportAs: ["ngbDatepicker"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
3186
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: EditUserProfileModalComponent, isStandalone: false, selector: "pw-edit-user-profile-modal", inputs: { slug: "slug", user: "user" }, outputs: { saveEvent: "saveEvent" }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, static: true }, { propertyName: "placesRef", first: true, predicate: ["ngxPlaces"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<ng-template #content\n let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\"\n id=\"modal-basic-title\">Edit Intro</h4>\n <button type=\"button\"\n class=\"btn-close float-end\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss()\">\n\n </button>\n </div>\n <div class=\"modal-body\">\n <form [formGroup]=\"form\"\n (ngSubmit)=\"onSaveDetail()\">\n <div class=\"row\">\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-first-name\"\n label=\"First Name\"\n name=\"first_name\"\n errorMsg=\"Please enter first Name\">\n <input type=\"text\"\n class=\"form-control\"\n formControlName=\"first_name\"\n id=\"edit-intro-first-name\"\n [placeholder]=\"'User.Profile.Intro.Placeholder.FirstName' | transloco\"\n autocomplete=\"given-name\" name=\"input_first_name_1\"/>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-last-name\"\n label=\"Last Name\"\n name=\"last_name\"\n errorMsg=\"Please enter last Name\">\n <input type=\"text\"\n class=\"form-control\"\n formControlName=\"last_name\"\n id=\"edit-intro-last-name\"\n [placeholder]=\"'User.Profile.Intro.Placeholder.LastName' | transloco\"\n autocomplete=\"family-name\" name=\"input_last_name_2\"/>\n </pw-input-container>\n\n <pw-input-container class=\"col-12\"\n controlId=\"edit-intro-headline\"\n label=\"Headline\"\n name=\"headline\"\n errorMsg=\"Please enter headline\">\n <input type=\"text\"\n class=\"form-control\"\n formControlName=\"headline\"\n id=\"edit-intro-headline\"\n [placeholder]=\"'User.Profile.Intro.Placeholder.Headline' | transloco\" name=\"input_headline_3\"/>\n </pw-input-container>\n\n <pw-input-container class=\"col-12\"\n controlId=\"edit-intro-description\"\n label=\"About me\"\n name=\"description\"\n errorMsg=\"Please enter description\">\n <textarea class=\"form-control\"\n id=\"edit-intro-description\"\n name=\"description\"\n [placeholder]=\"'User.Profile.Intro.Placeholder.Description' | transloco\"\n formControlName=\"description\"></textarea>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-gender\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Gender\"\n name=\"gender\"\n errorMsg=\"Please enter Gender\">\n <p-selectButton [options]=\"[\n { label: 'Male', value: 'M' },\n { label: 'Female', value: 'F' }\n ]\"\n [attr.aria-labelledby]=\"'edit-intro-gender-label'\"\n formControlName=\"gender\"></p-selectButton>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-dob\"\n label=\"Date of Birth\"\n name=\"dob\"\n errorMsg=\"Please enter date of birth\">\n <div class=\"input-group\">\n <input class=\"form-control\"\n id=\"edit-intro-dob\"\n name=\"dob\"\n placeholder=\"yyyy-mm-dd\"\n formControlName=\"dob\"\n ngbDatepicker\n #d=\"ngbDatepicker\"\n [minDate]=\"{ year: 1950, month: 1, day: 1 }\"\n [maxDate]=\"{ year: 2018, month: 12, day: 31 }\"\n autocomplete=\"off\" />\n <button class=\"btn btn-primary\"\n type=\"button\"\n aria-label=\"Open date picker\"\n (click)=\"d.toggle()\">\n <i class=\"fa fa-calendar\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-phone\"\n label=\"Phone\"\n name=\"phone_number\"\n errorMsg=\"Please enter phone\">\n <input type=\"text\"\n class=\"form-control\"\n formControlName=\"phone_number\"\n id=\"edit-intro-phone\"\n name=\"phone_number\"\n [placeholder]=\"'User.Profile.Intro.Placeholder.Phone' | transloco\"\n autocomplete=\"tel\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-postcode\"\n label=\"Postcode\"\n name=\"postcode\"\n errorMsg=\"Please enter postcode\">\n <input type=\"text\"\n class=\"form-control\"\n formControlName=\"postcode\"\n id=\"edit-intro-postcode\"\n [placeholder]=\"'User.Profile.Intro.Placeholder.Postcode' | transloco\"\n autocomplete=\"postal-code\" name=\"input_postcode_6\"/>\n </pw-input-container>\n\n @if (countries$ | async; as countries) {\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-country\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"Country\"\n name=\"country\"\n errorMsg=\"Please select a country\">\n <p-select\n [attr.aria-labelledby]=\"'edit-intro-country-label'\"\n [options]=\"countries\"\n optionLabel=\"name\"\n optionValue=\"code\"\n formControlName=\"country\"\n (onChange)=\"getRegion($event.value)\"\n [placeholder]=\"'User.Profile.SelectCountry' | transloco\">\n </p-select>\n </pw-input-container>\n }\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-state\"\n [useAriaLabelledbyOnly]=\"true\"\n label=\"State\"\n name=\"state\"\n errorMsg=\"Please select a state\">\n <p-select\n [attr.aria-labelledby]=\"'edit-intro-state-label'\"\n [options]=\"states\"\n optionLabel=\"name\"\n optionValue=\"code\"\n formControlName=\"state\"\n [placeholder]=\"'User.Profile.SelectState' | transloco\">\n </p-select>\n </pw-input-container>\n\n <!-- Location -->\n <pw-input-container label=\"Location\"\n class=\"col-12 col-md-6\"\n controlId=\"edit-intro-location\"\n [useAriaLabelledbyOnly]=\"true\"\n name=\"location\">\n <input ngx-gp-autocomplete\n id=\"edit-intro-location\"\n name=\"location\"\n class=\"form-control\"\n #places=\"ngx-places\"\n formControlName=\"location\"\n [placeholder]=\"'User.Profile.Intro.Placeholder.Location' | transloco\"\n [attr.aria-labelledby]=\"'edit-intro-location-label'\"\n (onAddressChange)=\"handleAddressChange($event)\" />\n </pw-input-container>\n\n <pw-input-container class=\"col-12 col-md-6\"\n controlId=\"edit-intro-website\"\n label=\"Website\"\n name=\"website_url\"\n errorMsg=\"Please enter Website\">\n <input type=\"text\"\n class=\"form-control\"\n formControlName=\"website_url\"\n id=\"edit-intro-website\"\n [placeholder]=\"'User.Profile.Intro.Placeholder.Website' | transloco\"\n autocomplete=\"url\" name=\"input_website_url_8\"/>\n </pw-input-container>\n </div>\n <div class=\"modal-footer\">\n <input type=\"button\"\n class=\"btn btn-outline-default me-2\"\n (click)=\"modal.close()\"\n value=\"Cancel\" id=\"input_field_9\" name=\"input_field_9\"/>\n <input type=\"submit\"\n [buttonBusy]=\"buttonBusy\"\n class=\"btn btn-primary\"\n value=\"Save Changes\" id=\"input_field_10\" name=\"input_field_10\"/>\n </div>\n </form>\n </div>\n</ng-template>\n", styles: ["@charset \"UTF-8\";:root{--first: rgb(23 105 225);--second: rgb(54 194 131);--third: rgb(255 171 0);--text: rgb(34 34 34);--tabs_bg: rgb(23 105 225);--tabs_sub_bg: rgb(70, 136, 236);--tabs_text: rgb(255 255 255);--titles: rgb(34 34 34);--sidebar_bg: rgb(0, 48, 63);--sidebar_text: rgb(255 255 255)}::ng-deep .p-selectbutton .p-button{margin-right:1rem}::ng-deep body .p-selectbutton .p-button.p-highlight{background-color:var(--first)!important}\n"], dependencies: [{ kind: "directive", type: i4.ButtonBusyDirective, selector: "[buttonBusy]", inputs: ["buttonBusy", "busyText"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i6.NgxGpAutocompleteDirective, selector: "[ngx-gp-autocomplete]", inputs: ["options"], outputs: ["onAddressChange"], exportAs: ["ngx-places"] }, { kind: "component", type: i7$1.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "component", type: i7.InputContainerComponent, selector: "pw-input-container", inputs: ["name", "controlId", "useAriaLabelledbyOnly", "label", "labelClass", "tooltipPosition", "required", "errorMsg", "isReadOnly", "showTooltip", "tooltipText", "showTriangle", "afterLabel", "showAfterLabel", "showTriangleText", "isLeftTooltip"] }, { kind: "component", type: i8$1.SelectButton, selector: "p-selectButton, p-selectbutton, p-select-button", inputs: ["options", "optionLabel", "optionValue", "optionDisabled", "unselectable", "tabindex", "multiple", "allowEmpty", "styleClass", "ariaLabelledBy", "dataKey", "autofocus", "size", "fluid"], outputs: ["onOptionClick", "onChange"] }, { kind: "directive", type: i1$1.NgbInputDatepicker, selector: "input[ngbDatepicker]", inputs: ["autoClose", "contentTemplate", "datepickerClass", "dayTemplate", "dayTemplateData", "displayMonths", "firstDayOfWeek", "footerTemplate", "markDisabled", "minDate", "maxDate", "navigation", "outsideDays", "placement", "popperOptions", "restoreFocus", "showWeekNumbers", "startDate", "container", "positionTarget", "weekdays", "disabled"], outputs: ["dateSelect", "navigate", "closed"], exportAs: ["ngbDatepicker"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
3089
3187
|
}
|
|
3090
3188
|
__decorate([
|
|
3091
3189
|
ValidateForm('form'),
|
|
@@ -3218,7 +3316,7 @@ class UserAboutComponent extends AppBaseComponent {
|
|
|
3218
3316
|
}
|
|
3219
3317
|
}
|
|
3220
3318
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: UserAboutComponent, deps: [{ token: i1$2.ProfileService }, { token: i1$2.QualificationService }, { token: i1$2.TagService }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3221
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: UserAboutComponent, isStandalone: false, selector: "pw-user-about", inputs: { user: "user", isEdit: "isEdit" }, outputs: { saveEvent: "saveEvent" }, viewQueries: [{ propertyName: "modal", first: true, predicate: EditUserProfileModalComponent, descendants: true }, { propertyName: "qualificationModal", first: true, predicate: EditQualificationsModalComponent, descendants: true }, { propertyName: "skillsModal", first: true, predicate: EditSkillsModalComponent, descendants: true }, { propertyName: "socialModal", first: true, predicate: EditSocialLinksComponent, descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"about\">\n <!-- Personal Information -->\n <section class=\"about-section\" data-cy=\"personal-info\">\n <header class=\"about-section__head\">\n <span class=\"about-section__icon\"><i class=\"fa fa-user\" aria-hidden=\"true\"></i></span>\n <h2 class=\"about-section__title\">{{ 'User.Profile.About.PersonalInfo' | transloco }}</h2>\n @if (user && isEdit) {\n <button type=\"button\" class=\"about-section__edit\" (click)=\"onProfileOpen()\" [attr.aria-label]=\"'User.Profile.About.EditPersonalInfo' | transloco\">\n <i class=\"fa fa-pen\" aria-hidden=\"true\"></i>\n </button>\n }\n </header>\n <div class=\"about-bio\">\n <span class=\"about-field__label\">{{ 'User.Profile.About.AboutMe' | transloco }}</span>\n <p class=\"about-bio__text\" [class.is-empty]=\"!user_profile?.description\">\n {{ user_profile?.description || ('User.Profile.About.NoDescription' | transloco) }}\n </p>\n </div>\n <dl class=\"about-grid\">\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.Birthday' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!user_profile?.dob\">{{ (user_profile?.dob | dateFormat) || '\u2014' }}</dd>\n </div>\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.LivesIn' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!user_profile?.country\">{{ user_profile?.country || '\u2014' }}</dd>\n </div>\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.Gender' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!user_profile?.gender\">\n {{\n user_profile?.gender === 'M'\n ? ('User.Profile.About.Male' | transloco)\n : user_profile?.gender === 'F'\n ? ('User.Profile.About.Female' | transloco)\n : '\u2014'\n }}\n </dd>\n </div>\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.Email' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!user?.email\">\n @if (user?.email) {\n <a class=\"about-field__link\" [href]=\"'mailto:' + user.email\">{{ user.email }}</a>\n } @else {\n \u2014\n }\n </dd>\n </div>\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.PhoneNumber' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!user_profile?.phone_number\">{{ user_profile?.phone_number || '\u2014' }}</dd>\n </div>\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.Website' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!user_profile?.website_url\">\n @if (user_profile?.website_url) {\n <a class=\"about-field__link\" target=\"_blank\" rel=\"noopener noreferrer\" [href]=\"user_profile.website_url\">{{ user_profile.website_url }}</a>\n } @else {\n \u2014\n }\n </dd>\n </div>\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.Joined' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!user?.joined_at\">{{ (user?.joined_at | dateFormat) || '\u2014' }}</dd>\n </div>\n </dl>\n @if (user && isEdit) {\n <pw-edit-user-profile-modal [user]=\"user\" (saveEvent)=\"onProfileSaved($event)\" [slug]=\"user?.slug\"></pw-edit-user-profile-modal>\n }\n </section>\n\n <!-- Skills -->\n <section class=\"about-section\" data-cy=\"skills-info\">\n <header class=\"about-section__head\">\n <span class=\"about-section__icon\"><i class=\"fa fa-bolt\" aria-hidden=\"true\"></i></span>\n <h2 class=\"about-section__title\">{{ 'User.Profile.About.Skills' | transloco }}</h2>\n @if (isEdit) {\n <button type=\"button\" class=\"about-section__edit\" (click)=\"openSkills()\" [attr.aria-label]=\"'User.Profile.About.EditSkills' | transloco\">\n <i class=\"fa fa-pen\" aria-hidden=\"true\"></i>\n </button>\n }\n </header>\n @if (selectedSkills?.length) {\n <div class=\"about-skills\">\n @for (skill of selectedSkills; track skill) {\n <div class=\"about-skills__group\">\n <span class=\"about-skills__category\">{{ skill.category_name }}</span>\n <div class=\"about-tags\">\n @for (item of skill.tags; track item) {\n <span class=\"about-tag\">{{ item.name }}</span>\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <p class=\"about-empty\">{{ (isEdit ? 'User.Profile.About.NoSkillsEdit' : 'User.Profile.About.NoSkills') | transloco }}</p>\n }\n @if (isEdit) {\n <pw-edit-skills-modal [userId]=\"user?.id\" [slug]=\"user?.slug\" (saveEvent)=\"getUserDetails()\"></pw-edit-skills-modal>\n }\n </section>\n\n <!-- Educational Information -->\n <section class=\"about-section\" data-cy=\"educational-info\">\n <header class=\"about-section__head\">\n <span class=\"about-section__icon\"><i class=\"fa fa-graduation-cap\" aria-hidden=\"true\"></i></span>\n <h2 class=\"about-section__title\">{{ 'User.Profile.About.Education' | transloco }}</h2>\n @if (isEdit) {\n <button type=\"button\" class=\"about-section__edit\" (click)=\"qualificationModal.onOpen()\" [attr.aria-label]=\"'User.Profile.About.AddEducation' | transloco\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </button>\n }\n </header>\n @if (qualifications?.length) {\n <div class=\"about-edu\">\n @for (item of qualifications; track trackByQualification($index, item)) {\n <article class=\"about-edu__item\">\n <div class=\"about-edu__main\">\n <h4 class=\"about-edu__school\">{{ item?.school }}</h4>\n <dl class=\"about-grid about-grid--compact\">\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.Period' | transloco }}</dt>\n <dd class=\"about-field__value\">{{ item?.started_on }} \u2013 {{ item?.ended_on }}</dd>\n </div>\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.Degree' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!item?.degree\">{{ item?.degree || '\u2014' }}</dd>\n </div>\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.Course' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!item?.course\">{{ item?.course || '\u2014' }}</dd>\n </div>\n </dl>\n </div>\n @if (isEdit) {\n <div class=\"about-edu__actions\">\n <button type=\"button\" class=\"about-icon-btn\" [attr.aria-label]=\"'User.Profile.About.EditEducation' | transloco\" (click)=\"editQualification(item)\">\n <i class=\"fa fa-pen\" aria-hidden=\"true\"></i>\n </button>\n <button type=\"button\" class=\"about-icon-btn about-icon-btn--danger\" data-cy=\"delete-qualification\" [attr.aria-label]=\"'User.Profile.About.DeleteEducation' | transloco\" (click)=\"deleteQualification(item)\">\n <i class=\"fa fa-trash\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n </article>\n }\n </div>\n } @else {\n <p class=\"about-empty\">{{ 'User.Profile.About.NoEducation' | transloco }}</p>\n }\n @if (isEdit) {\n <pw-edit-qualifications-modal (saveEvent)=\"getUserDetails()\"></pw-edit-qualifications-modal>\n }\n </section>\n\n <!-- External Portfolio -->\n <section class=\"about-section\" data-cy=\"portfolio-info\">\n <header class=\"about-section__head\">\n <span class=\"about-section__icon\"><i class=\"fa fa-link\" aria-hidden=\"true\"></i></span>\n <h2 class=\"about-section__title\">{{ 'User.Profile.About.Portfolio' | transloco }}</h2>\n @if (isEdit) {\n <button type=\"button\" class=\"about-section__edit\" (click)=\"onOpenSocial()\" [attr.aria-label]=\"'User.Profile.About.EditPortfolio' | transloco\">\n <i class=\"fa fa-pen\" aria-hidden=\"true\"></i>\n </button>\n }\n </header>\n @if (noUserLinks) {\n <div class=\"about-social\">\n @for (link of objectKeys(userLinks); track link) {\n @if (userLinks[link]) {\n <a class=\"about-social__link\" target=\"_blank\" rel=\"noopener noreferrer\" [href]=\"userLinks[link]\" [attr.aria-label]=\"link\">\n <img src=\"assets/img/icons/social/{{ link }}.svg\" width=\"32\" height=\"32\" [alt]=\"link\" />\n </a>\n }\n }\n </div>\n } @else {\n <p class=\"about-empty\">{{ 'User.Profile.About.NoPortfolio' | transloco }}</p>\n }\n @if (user && isEdit) {\n <pw-edit-social-links [userId]=\"user.id\" [links]=\"userLinks\" (saveEvent)=\"onSaveUserLinks()\"></pw-edit-social-links>\n }\n </section>\n\n @if (loading) {\n <div class=\"w-100 text-center p-3\"><p-progressSpinner strokeWidth=\"2\"></p-progressSpinner></div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:root{--first: rgb(23 105 225);--second: rgb(54 194 131);--third: rgb(255 171 0);--text: rgb(34 34 34);--tabs_bg: rgb(23 105 225);--tabs_sub_bg: rgb(70, 136, 236);--tabs_text: rgb(255 255 255);--titles: rgb(34 34 34);--sidebar_bg: rgb(0, 48, 63);--sidebar_text: rgb(255 255 255)}.about{display:flex;flex-direction:column;gap:16px}.about-section{background:#fff;border:1px solid #e2e5ea;border-radius:8px;padding:20px 24px;float:none}.about-section ::ng-deep .pi-plus-circle{display:none}.about-section__head{display:flex;align-items:center;margin-bottom:18px;float:none}.about-section__icon{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;margin-right:12px;border-radius:8px;background:#f7f8fa;color:#5a6473;font-size:.95rem;flex-shrink:0}.about-section__title{margin:0!important;padding:0!important}.about-section__edit{margin-left:auto}.about-field__label,.about-skills__category{margin:0;font-size:1rem;font-weight:600;letter-spacing:.03em;text-transform:uppercase;color:#7c8696}.about-section__edit,.about-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:1px solid #e2e5ea;border-radius:7px;background:#fff;color:#5a6473;font-size:.9rem;cursor:pointer;transition:all .12s ease-out}.about-section__edit:hover,.about-icon-btn:hover{background:#f7f8fa;color:#1a1d21;border-color:#cfd4dc}.about-empty{margin:0;color:#7c8696;font-size:1.2rem}.about-bio{margin-bottom:22px}.about-bio__text{margin:6px 0 0;color:#1a1d21;font-size:1.25rem;line-height:1.55}.about-bio__text.is-empty{color:#7c8696;font-size:1.2rem}.about-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:20px 28px;margin:0}.about-grid--compact{gap:14px 24px}.about-field{display:flex;flex-direction:column;gap:5px;min-width:0}.about-field__value{margin:0;font-size:1.15rem;color:#1a1d21;word-break:break-word}.about-field__value.is-empty{color:#cfd4dc}.about-field__link{color:var(--first);text-decoration:none}.about-field__link:hover{text-decoration:underline}.about-skills{display:flex;flex-direction:column;gap:16px}.about-skills__group{display:flex;flex-direction:column;gap:8px}.about-tags{display:flex;flex-wrap:wrap;gap:8px}.about-tag{display:inline-flex;align-items:center;padding:5px 13px;border:1px solid #e2e5ea;border-radius:9999px;background:#eef0f3;color:#3d4654;font-size:1.05rem;font-weight:500;line-height:1.4}.about-edu{display:flex;flex-direction:column;gap:14px}.about-edu__item{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:16px;border:1px solid #e2e5ea;border-radius:8px;background:#f7f8fa}.about-edu__main{min-width:0;flex:1}.about-edu__school{margin:0 0 12px}.about-edu__actions{display:flex;gap:6px;flex-shrink:0}.about-icon-btn--danger:hover{color:#c0392b;border-color:#c0392b}.about-social{display:flex;flex-wrap:wrap;gap:14px}.about-social__link{display:inline-flex}\n"], dependencies: [{ kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: EditQualificationsModalComponent, selector: "pw-edit-qualifications-modal", outputs: ["saveEvent"] }, { kind: "component", type: EditSkillsModalComponent, selector: "pw-edit-skills-modal", inputs: ["userId", "slug", "entityType", "entityEntity"], outputs: ["saveEvent"] }, { kind: "component", type: EditSocialLinksComponent, selector: "pw-edit-social-links", inputs: ["links", "userId"], outputs: ["saveEvent"] }, { kind: "component", type: EditUserProfileModalComponent, selector: "pw-edit-user-profile-modal", inputs: ["slug", "user"], outputs: ["saveEvent"] }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }, { kind: "pipe", type: i6$3.DateFormatPipe, name: "dateFormat" }] }); }
|
|
3319
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: UserAboutComponent, isStandalone: false, selector: "pw-user-about", inputs: { user: "user", isEdit: "isEdit" }, outputs: { saveEvent: "saveEvent" }, viewQueries: [{ propertyName: "modal", first: true, predicate: EditUserProfileModalComponent, descendants: true }, { propertyName: "qualificationModal", first: true, predicate: EditQualificationsModalComponent, descendants: true }, { propertyName: "skillsModal", first: true, predicate: EditSkillsModalComponent, descendants: true }, { propertyName: "socialModal", first: true, predicate: EditSocialLinksComponent, descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"about\">\n <!-- Personal Information -->\n <section class=\"about-section\" data-cy=\"personal-info\">\n <header class=\"about-section__head\">\n <span class=\"about-section__icon\"><i class=\"fa fa-user\" aria-hidden=\"true\"></i></span>\n <h2 class=\"about-section__title\">{{ 'User.Profile.About.PersonalInfo' | transloco }}</h2>\n @if (user && isEdit) {\n <button type=\"button\" class=\"about-section__edit\" (click)=\"onProfileOpen()\" [attr.aria-label]=\"'User.Profile.About.EditPersonalInfo' | transloco\">\n <i class=\"fa fa-pen\" aria-hidden=\"true\"></i>\n </button>\n }\n </header>\n <div class=\"about-bio\">\n <span class=\"about-field__label\">{{ 'User.Profile.About.AboutMe' | transloco }}</span>\n <p class=\"about-bio__text\" [class.is-empty]=\"!user_profile?.description\">\n {{ user_profile?.description || ('User.Profile.About.NoDescription' | transloco) }}\n </p>\n </div>\n <dl class=\"about-grid\">\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.Birthday' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!user_profile?.dob\">{{ (user_profile?.dob | dateFormat) || '\u2014' }}</dd>\n </div>\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.LivesIn' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!user_profile?.country\">{{ user_profile?.country || '\u2014' }}</dd>\n </div>\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.Gender' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!user_profile?.gender\">\n {{\n user_profile?.gender === 'M'\n ? ('User.Profile.About.Male' | transloco)\n : user_profile?.gender === 'F'\n ? ('User.Profile.About.Female' | transloco)\n : '\u2014'\n }}\n </dd>\n </div>\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.Email' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!user?.email\">\n @if (user?.email) {\n <a class=\"about-field__link\" [href]=\"'mailto:' + user.email\">{{ user.email }}</a>\n } @else {\n \u2014\n }\n </dd>\n </div>\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.PhoneNumber' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!user_profile?.phone_number\">{{ user_profile?.phone_number || '\u2014' }}</dd>\n </div>\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.Website' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!user_profile?.website_url\">\n @if (user_profile?.website_url) {\n <a class=\"about-field__link\" target=\"_blank\" rel=\"noopener noreferrer\" [href]=\"user_profile.website_url\">{{ user_profile.website_url }}</a>\n } @else {\n \u2014\n }\n </dd>\n </div>\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.Joined' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!user?.joined_at\">{{ (user?.joined_at | dateFormat) || '\u2014' }}</dd>\n </div>\n </dl>\n @if (user && isEdit) {\n <pw-edit-user-profile-modal [user]=\"user\" (saveEvent)=\"onProfileSaved($event)\" [slug]=\"user?.slug\"></pw-edit-user-profile-modal>\n }\n </section>\n\n <!-- Skills -->\n <section class=\"about-section\" data-cy=\"skills-info\">\n <header class=\"about-section__head\">\n <span class=\"about-section__icon\"><i class=\"fa fa-bolt\" aria-hidden=\"true\"></i></span>\n <h2 class=\"about-section__title\">{{ 'User.Profile.About.Skills' | transloco }}</h2>\n @if (isEdit) {\n <button type=\"button\" class=\"about-section__edit\" (click)=\"openSkills()\" [attr.aria-label]=\"'User.Profile.About.EditSkills' | transloco\">\n <i class=\"fa fa-pen\" aria-hidden=\"true\"></i>\n </button>\n }\n </header>\n @if (selectedSkills?.length) {\n <div class=\"about-skills\">\n @for (skill of selectedSkills; track skill) {\n <div class=\"about-skills__group\">\n <span class=\"about-skills__category\">{{ skill.category_name }}</span>\n <div class=\"about-tags\">\n @for (item of skill.tags; track item) {\n <span class=\"about-tag\">{{ item.name }}</span>\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <p class=\"about-empty\">{{ (isEdit ? 'User.Profile.About.NoSkillsEdit' : 'User.Profile.About.NoSkills') | transloco }}</p>\n }\n @if (isEdit) {\n <pw-edit-skills-modal [userId]=\"user?.id\" [slug]=\"user?.slug\" (saveEvent)=\"getUserDetails()\"></pw-edit-skills-modal>\n }\n </section>\n\n <!-- Educational Information -->\n <section class=\"about-section\" data-cy=\"educational-info\">\n <header class=\"about-section__head\">\n <span class=\"about-section__icon\"><i class=\"fa fa-graduation-cap\" aria-hidden=\"true\"></i></span>\n <h2 class=\"about-section__title\">{{ 'User.Profile.About.Education' | transloco }}</h2>\n @if (isEdit) {\n <button type=\"button\" class=\"about-section__edit\" (click)=\"qualificationModal.onOpen()\" [attr.aria-label]=\"'User.Profile.About.AddEducation' | transloco\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </button>\n }\n </header>\n @if (qualifications?.length) {\n <div class=\"about-edu\">\n @for (item of qualifications; track trackByQualification($index, item)) {\n <article class=\"about-edu__item\">\n <div class=\"about-edu__main\">\n <h4 class=\"about-edu__school\">{{ item?.school }}</h4>\n <dl class=\"about-grid about-grid--compact\">\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.Period' | transloco }}</dt>\n <dd class=\"about-field__value\">{{ item?.started_on }} \u2013 {{ item?.ended_on }}</dd>\n </div>\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.Degree' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!item?.degree\">{{ item?.degree || '\u2014' }}</dd>\n </div>\n <div class=\"about-field\">\n <dt class=\"about-field__label\">{{ 'User.Profile.About.Course' | transloco }}</dt>\n <dd class=\"about-field__value\" [class.is-empty]=\"!item?.course\">{{ item?.course || '\u2014' }}</dd>\n </div>\n </dl>\n </div>\n @if (isEdit) {\n <div class=\"about-edu__actions\">\n <button type=\"button\" class=\"about-icon-btn\" [attr.aria-label]=\"'User.Profile.About.EditEducation' | transloco\" (click)=\"editQualification(item)\">\n <i class=\"fa fa-pen\" aria-hidden=\"true\"></i>\n </button>\n <button type=\"button\" class=\"about-icon-btn about-icon-btn--danger\" data-cy=\"delete-qualification\" [attr.aria-label]=\"'User.Profile.About.DeleteEducation' | transloco\" (click)=\"deleteQualification(item)\">\n <i class=\"fa fa-trash\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n </article>\n }\n </div>\n } @else {\n <p class=\"about-empty\">{{ 'User.Profile.About.NoEducation' | transloco }}</p>\n }\n @if (isEdit) {\n <pw-edit-qualifications-modal (saveEvent)=\"getUserDetails()\"></pw-edit-qualifications-modal>\n }\n </section>\n\n <!-- External Portfolio -->\n <section class=\"about-section\" data-cy=\"portfolio-info\">\n <header class=\"about-section__head\">\n <span class=\"about-section__icon\"><i class=\"fa fa-link\" aria-hidden=\"true\"></i></span>\n <h2 class=\"about-section__title\">{{ 'User.Profile.About.Portfolio' | transloco }}</h2>\n @if (isEdit) {\n <button type=\"button\" class=\"about-section__edit\" (click)=\"onOpenSocial()\" [attr.aria-label]=\"'User.Profile.About.EditPortfolio' | transloco\">\n <i class=\"fa fa-pen\" aria-hidden=\"true\"></i>\n </button>\n }\n </header>\n @if (noUserLinks) {\n <div class=\"about-social\">\n @for (link of objectKeys(userLinks); track link) {\n @if (userLinks[link]) {\n <a class=\"about-social__link\" target=\"_blank\" rel=\"noopener noreferrer\" [href]=\"userLinks[link]\" [attr.aria-label]=\"link\">\n <img src=\"assets/img/icons/social/{{ link }}.svg\" width=\"32\" height=\"32\" [alt]=\"link\" />\n </a>\n }\n }\n </div>\n } @else {\n <p class=\"about-empty\">{{ 'User.Profile.About.NoPortfolio' | transloco }}</p>\n }\n @if (user && isEdit) {\n <pw-edit-social-links [userId]=\"user.id\" [links]=\"userLinks\" (saveEvent)=\"onSaveUserLinks()\"></pw-edit-social-links>\n }\n </section>\n\n @if (loading) {\n <div class=\"w-100 text-center p-3\"><p-progressSpinner strokeWidth=\"2\"></p-progressSpinner></div>\n }\n</div>\n", styles: ["@charset \"UTF-8\";:root{--first: rgb(23 105 225);--second: rgb(54 194 131);--third: rgb(255 171 0);--text: rgb(34 34 34);--tabs_bg: rgb(23 105 225);--tabs_sub_bg: rgb(70, 136, 236);--tabs_text: rgb(255 255 255);--titles: rgb(34 34 34);--sidebar_bg: rgb(0, 48, 63);--sidebar_text: rgb(255 255 255)}.about{display:flex;flex-direction:column;gap:16px}.about-section{background:#fff;border:1px solid #e2e5ea;border-radius:8px;padding:20px 24px;float:none}.about-section ::ng-deep .pi-plus-circle{display:none}.about-section__head{display:flex;align-items:center;margin-bottom:18px;float:none}.about-section__icon{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;margin-right:12px;border-radius:8px;background:#f7f8fa;color:#5a6473;font-size:.95rem;flex-shrink:0}.about-section__title{margin:0!important;padding:0!important}.about-section__edit{margin-left:auto}.about-field__label,.about-skills__category{margin:0;font-size:1rem;font-weight:600;letter-spacing:.03em;text-transform:uppercase;color:#7c8696}.about-section__edit,.about-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:1px solid #e2e5ea;border-radius:7px;background:#fff;color:#5a6473;font-size:.9rem;cursor:pointer;transition:all .12s ease-out}.about-section__edit:hover,.about-icon-btn:hover{background:#f7f8fa;color:#1a1d21;border-color:#cfd4dc}.about-empty{margin:0;color:#7c8696;font-size:1.2rem}.about-bio{margin-bottom:22px}.about-bio__text{margin:6px 0 0;color:#1a1d21;font-size:1.25rem;line-height:1.55}.about-bio__text.is-empty{color:#7c8696;font-size:1.2rem}.about-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:20px 28px;margin:0}.about-grid--compact{gap:14px 24px}.about-field{display:flex;flex-direction:column;gap:5px;min-width:0}.about-field__value{margin:0;font-size:1.15rem;color:#1a1d21;word-break:break-word}.about-field__value.is-empty{color:#cfd4dc}.about-field__link{color:var(--first);text-decoration:none}.about-field__link:hover{text-decoration:underline}.about-skills{display:flex;flex-direction:column;gap:16px}.about-skills__group{display:flex;flex-direction:column;gap:8px}.about-tags{display:flex;flex-wrap:wrap;gap:8px}.about-tag{display:inline-flex;align-items:center;padding:5px 13px;border:1px solid #e2e5ea;border-radius:9999px;background:#eef0f3;color:#3d4654;font-size:1.05rem;font-weight:500;line-height:1.4}.about-edu{display:flex;flex-direction:column;gap:14px}.about-edu__item{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:16px;border:1px solid #e2e5ea;border-radius:8px;background:#f7f8fa}.about-edu__main{min-width:0;flex:1}.about-edu__school{margin:0 0 12px}.about-edu__actions{display:flex;gap:6px;flex-shrink:0}.about-icon-btn--danger:hover{color:#c0392b;border-color:#c0392b}.about-social{display:flex;flex-wrap:wrap;gap:14px}.about-social__link{display:inline-flex}\n"], dependencies: [{ kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: EditQualificationsModalComponent, selector: "pw-edit-qualifications-modal", outputs: ["saveEvent"] }, { kind: "component", type: EditSkillsModalComponent, selector: "pw-edit-skills-modal", inputs: ["userId", "slug", "entityType", "entityEntity"], outputs: ["saveEvent"] }, { kind: "component", type: EditSocialLinksComponent, selector: "pw-edit-social-links", inputs: ["links", "userId"], outputs: ["saveEvent"] }, { kind: "component", type: EditUserProfileModalComponent, selector: "pw-edit-user-profile-modal", inputs: ["slug", "user"], outputs: ["saveEvent"] }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }, { kind: "pipe", type: i6$1.DateFormatPipe, name: "dateFormat" }] }); }
|
|
3222
3320
|
}
|
|
3223
3321
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: UserAboutComponent, decorators: [{
|
|
3224
3322
|
type: Component,
|
|
@@ -3288,7 +3386,7 @@ class PortfoliosComponent {
|
|
|
3288
3386
|
}
|
|
3289
3387
|
}
|
|
3290
3388
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: PortfoliosComponent, deps: [{ token: i1$2.ProfileService }, { token: i1$1.NgbModal }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3291
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: PortfoliosComponent, isStandalone: false, selector: "pw-portfolios", inputs: { user: "user", isEdit: "isEdit" }, ngImport: i0, template: "<div class=\"row\">\n <div class=\"col-sm-12 mt-2\">\n <h2>User's Portfolio</h2>\n @if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n @if (projectPictures.length === 0 && isLoaded) {\n <pw-no-data [withImage]=\"true\" message=\"No portfolio listed yet - please consider adding some.\"\n ></pw-no-data>\n }\n <div class=\"card-body\">\n @if (projectPictures.length) {\n <div class=\"card-block\"\n >\n <div class=\"grid-hover\">\n <div class=\"row\">\n @for (picture of projectPictures; track trackByImage($index, picture)) {\n <div class=\"col-md-4 col-12 mb-2\"\n >\n <figure class=\"effect-marley\"\n (keydown.enter)=\"showFullImage(picture, content, $event)\"\n (click)=\"showFullImage(picture, content, $event)\">\n <img [src]=\"picture.picture.url\"\n alt=\"project pic\" />\n <figcaption>\n <h2>\n <span class=\"portfolio-header-text\">{{ picture.project_title }}</span>\n </h2>\n @if (isEdit) {\n <i\n class=\"fal fa-2x fa-times white\"\n id=\"delete-icon\"\n (click)=\"deletePicture(picture.id)\"\n (keydown.enter)=\"deletePicture(picture.id)\"\n aria-hidden=\"true\"\n ></i>\n }\n <p class=\"thumb-description\">\n {{ picture?.project_description }}\n </p>\n </figcaption>\n </figure>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n<ng-template #content\n let-modal>\n <div class=\"modal-img-popup\">\n <img alt=\"Selected Url\"\n [src]=\"selectedPicURL\"\n class=\"img-fluid\" />\n <button type=\"button\"\n class=\"close close-img\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss('Cross click')\">\n <span class=\"btn\">×</span>\n </button>\n </div>\n</ng-template>\n", styles: [".grid-hover figure{height:100%}.grid-hover figure figcaption:hover{background-color:#343a4066}.grid-hover figure figcaption h2{color:#fff}.thumb-description{color:#fff!important;height:154px;overflow:hidden;text-overflow:ellipsis;top:91px}.demo .modal-dialog{max-width:800px}.close-img{position:absolute}.close-img span{background-color:#4a4a4a;border:1px solid rgb(255,255,255);border-radius:50px;color:#fff;cursor:pointer;display:inline-block;font-size:1rem;height:40px;position:absolute;right:-30px;text-align:center;top:-30px;width:40px}@media screen and (max-width:767px){.grid-hover figure{max-width:100%;min-width:100%}}@media screen and (min-device-width:768px)and (max-device-width:1200px){.grid-hover figure{min-width:fit-content}}.portfolio-header-text{color:#fff!important}\n"], dependencies: [{ kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type:
|
|
3389
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: PortfoliosComponent, isStandalone: false, selector: "pw-portfolios", inputs: { user: "user", isEdit: "isEdit" }, ngImport: i0, template: "<div class=\"row\">\n <div class=\"col-sm-12 mt-2\">\n <h2>User's Portfolio</h2>\n @if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n @if (projectPictures.length === 0 && isLoaded) {\n <pw-no-data [withImage]=\"true\" message=\"No portfolio listed yet - please consider adding some.\"\n ></pw-no-data>\n }\n <div class=\"card-body\">\n @if (projectPictures.length) {\n <div class=\"card-block\"\n >\n <div class=\"grid-hover\">\n <div class=\"row\">\n @for (picture of projectPictures; track trackByImage($index, picture)) {\n <div class=\"col-md-4 col-12 mb-2\"\n >\n <figure class=\"effect-marley\"\n (keydown.enter)=\"showFullImage(picture, content, $event)\"\n (click)=\"showFullImage(picture, content, $event)\">\n <img [src]=\"picture.picture.url\"\n alt=\"project pic\" />\n <figcaption>\n <h2>\n <span class=\"portfolio-header-text\">{{ picture.project_title }}</span>\n </h2>\n @if (isEdit) {\n <i\n class=\"fal fa-2x fa-times white\"\n id=\"delete-icon\"\n (click)=\"deletePicture(picture.id)\"\n (keydown.enter)=\"deletePicture(picture.id)\"\n aria-hidden=\"true\"\n ></i>\n }\n <p class=\"thumb-description\">\n {{ picture?.project_description }}\n </p>\n </figcaption>\n </figure>\n </div>\n }\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n</div>\n<ng-template #content\n let-modal>\n <div class=\"modal-img-popup\">\n <img alt=\"Selected Url\"\n [src]=\"selectedPicURL\"\n class=\"img-fluid\" />\n <button type=\"button\"\n class=\"close close-img\"\n aria-label=\"Close\"\n (click)=\"modal.dismiss('Cross click')\">\n <span class=\"btn\">×</span>\n </button>\n </div>\n</ng-template>\n", styles: [".grid-hover figure{height:100%}.grid-hover figure figcaption:hover{background-color:#343a4066}.grid-hover figure figcaption h2{color:#fff}.thumb-description{color:#fff!important;height:154px;overflow:hidden;text-overflow:ellipsis;top:91px}.demo .modal-dialog{max-width:800px}.close-img{position:absolute}.close-img span{background-color:#4a4a4a;border:1px solid rgb(255,255,255);border-radius:50px;color:#fff;cursor:pointer;display:inline-block;font-size:1rem;height:40px;position:absolute;right:-30px;text-align:center;top:-30px;width:40px}@media screen and (max-width:767px){.grid-hover figure{max-width:100%;min-width:100%}}@media screen and (min-device-width:768px)and (max-device-width:1200px){.grid-hover figure{min-width:fit-content}}.portfolio-header-text{color:#fff!important}\n"], dependencies: [{ kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "component", type: i7.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }] }); }
|
|
3292
3390
|
}
|
|
3293
3391
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: PortfoliosComponent, decorators: [{
|
|
3294
3392
|
type: Component,
|
|
@@ -3365,7 +3463,7 @@ class UserProjectsComponent extends AppBaseComponent {
|
|
|
3365
3463
|
});
|
|
3366
3464
|
}
|
|
3367
3465
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: UserProjectsComponent, deps: [{ token: i1$2.ProfileService }, { token: i0.Injector }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3368
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: UserProjectsComponent, isStandalone: false, selector: "pw-user-projects", inputs: { user: "user", isEdit: "isEdit", slug: "slug" }, viewQueries: [{ propertyName: "projectModal", first: true, predicate: EditProjectModalComponent, descendants: true, static: true }, { propertyName: "skillModal", first: true, predicate: EditSkillsModalComponent, descendants: true }, { propertyName: "recommendationModal", first: true, predicate: EditRecommendationModalComponent, descendants: true, static: true }, { propertyName: "portfolios", first: true, predicate: EditPortfoliosComponent, descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"row\">\n <div class=\"col-sm-12 mt-2\">\n <h2>User's Projects</h2>\n @if (isEdit) {\n <div class=\"row\"\n >\n <div class=\"col-12\">\n <div class=\"content-header\">\n <button class=\"btn btn-primary float-end\"\n (click)=\"onEditProject(null)\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i> {{'Create Project' | transloco}}\n </button>\n </div>\n </div>\n </div>\n }\n @if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n @if (projects?.length) {\n <div id=\"timeline\"\n class=\"timeline-center timeline-wrapper\"\n >\n <ul class=\"timeline\">\n <li class=\"timeline-line\"></li>\n </ul>\n <ul class=\"timeline\">\n <li class=\"timeline-line\"></li>\n @for (\n project of projects; track trackByProject(i,\n project); let i = $index; let odd = $odd; let even = $even) {\n <li class=\"timeline-item\"\n [ngClass]=\"{ 'mt-5': odd }\"\n >\n <div class=\"timeline-badge\">\n <span class=\"bg-red bg-lighten-1\"\n data-bs-toggle=\"tooltip\"\n data-placement=\"right\"\n title=\"Portfolio project work\">\n <span class=\"timeline-year\"> {{ project.start_year }} </span>\n </span>\n </div>\n <div class=\"timeline-card card pb-0\">\n <div class=\"card-header\">\n <h4 class=\"mb-0 card-title\">\n <a>{{ project.title }}</a>\n </h4>\n <div class=\"card-subtitle text-muted mt-0\">\n <span class=\"font-small-3\">\n {{ project.start_year }} - {{ project.end_year }}</span>\n </div>\n </div>\n <div class=\"card-body project-card\">\n @if (project.project_pictures?.length) {\n <i\n class=\"fal fa-times\"\n (click)=\"deletePicture(project)\"\n (keydown.enter)=\"deletePicture(project)\"\n aria-hidden=\"true\"\n ></i>\n <img class=\"img-fluid project-picture\"\n [src]=\"project.project_pictures[0].picture.url\"\n alt=\"Project Cover\" />\n }\n <div class=\"card-body\">\n <div class=\"\">\n <p class=\"card-text\">{{ project.description }}</p>\n <div class=\"list-inline mb-1\">\n <!-- Skills -->\n @if (project.tags?.length) {\n <div>\n <div class=\"my-2\">\n <i class=\"fa fa-user-tag\" aria-hidden=\"true\"></i>\n Skills\n </div>\n @for (tag of project.tags; track tag) {\n <span class=\"badge bg-success me-2\">{{\n tag.name\n }}</span>\n }\n </div>\n }\n @if (project.project_recommendations?.length) {\n <div class=\"mt-2\"\n >\n <div class=\"my-2\">\n <i\n class=\"fa fa-clipboard-check me-2\"\n aria-hidden=\"true\"\n ></i>\n Recommendations\n </div>\n @for (\n recommendation of project.project_recommendations\n ; track\n recommendation) {\n <section class=\"mb-2\"\n >\n <div class=\"me-2\">\n Client: {{ recommendation?.client_name }}\n </div>\n <div class=\"me-2\">\n Message: {{ recommendation?.description }}\n </div>\n <div class=\"row recommendation\">\n <div class=\"col-4\">\n <span>Communication</span>\n <p-rating [(ngModel)]=\"\n recommendation.communication\n \"\n [cancel]=\"false\"\n [readonly]=\"true\">\n </p-rating>\n </div>\n <div class=\"col-4\">\n <span>Quality</span>\n <p-rating [(ngModel)]=\"recommendation.quality\"\n [cancel]=\"false\"\n [readonly]=\"true\">\n </p-rating>\n </div>\n <div class=\"col-4\">\n <span>Time</span>\n <p-rating [(ngModel)]=\"recommendation.time\"\n [cancel]=\"false\"\n [readonly]=\"true\">\n </p-rating>\n </div>\n </div>\n </section>\n }\n </div>\n }\n @if (isEdit) {\n <div class=\"text-end mt-3 d-flex justify-content-end project-actions\"\n >\n <!-- Project Edit -->\n <span class=\"btn btn-link pb-0 actions\"\n (keydown.enter)=\"onEditProject(project)\"\n (click)=\"onEditProject(project)\">\n Edit\n </span>\n <button class=\"btn btn-link pb-0 actions\"\n (click)=\"openSkills(project)\">\n Skills\n </button>\n <pw-edit-skills-modal [userId]=\"user?.id\"\n entityEntity=\"Project\"\n entityType=\"skills\"\n (saveEvent)=\"onSkillsSave()\"\n [slug]=\"project?.slug\">\n </pw-edit-skills-modal>\n <!-- Portfolios -->\n <button class=\"btn btn-link pb-0 actions\"\n (click)=\"openPortfolios(project.id)\">\n Photos\n </button>\n <pw-edit-portfolios [slug]=\"user?.slug\"\n [id]=\"project.id\"\n (successEvent)=\"getProjects()\">\n </pw-edit-portfolios>\n <span class=\"btn btn-link pb-0 delete-project actions\"\n (keydown.enter)=\"onDeleteProject(project)\"\n (click)=\"onDeleteProject(project)\">\n Delete\n </span>\n </div>\n }\n <!-- Recommendation -->\n @if (!isEdit) {\n <span class=\"pe-1 mt-3\"\n (click)=\"editRecommendation(project)\"\n (keydown.enter)=\"editRecommendation(project)\"\n >\n <a class=\"primary\"><span class=\"fa fa-commenting-o\"></span> Endorse\n </a></span>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n }\n </ul>\n </div>\n }\n @if (projects?.length === 0 && isLoaded) {\n<pw-no-data [withImage]=\"true\" [message]=\"\n isEdit\n ? ('User.Profile.Projects.NoProjects' | transloco)\n : ('User.Profile.Projects.NoUserProjects' | transloco)\n \"\n >\n </pw-no-data>\n }\n </div>\n</div>\n<pw-edit-project-modal (saveEvent)=\"onSaveProject($event)\"></pw-edit-project-modal>\n<pw-edit-recommendation-modal [user]=\"user\"></pw-edit-recommendation-modal>\n", styles: ["@charset \"UTF-8\";:root{--first: rgb(23 105 225);--second: rgb(54 194 131);--third: rgb(255 171 0);--text: rgb(34 34 34);--tabs_bg: rgb(23 105 225);--tabs_sub_bg: rgb(70, 136, 236);--tabs_text: rgb(255 255 255);--titles: rgb(34 34 34);--sidebar_bg: rgb(0, 48, 63);--sidebar_text: rgb(255 255 255)}.project-card{position:relative}.project-card i.fa-times{color:#fff;display:none;font-size:20px;position:absolute;right:39px;top:14px}.project-card:hover i.fa-times{display:inline}.timeline-card.card{min-height:auto;border:1px solid #e2e5ea;border-radius:10px;box-shadow:0 1px 2px #1018280f}.timeline-card.card .card-header{padding:14px 16px 6px}.timeline-card.card .badge.bg-success{border-radius:9999px;background-color:#e7f5ee!important;color:#1f7a47!important;border:1px solid #c9e9d6;font-weight:600}.timeline-card.card .card-body.project-card{padding:0 20px 1rem}.timeline-card.card .card-body.project-card .card-body{padding:20px 0 0}@media only screen and (max-width:767px){.timeline-center{margin-top:30px}.timeline-center .project-actions .btn{padding:.375rem .5rem}}.actions{color:var(--first)!important}.timeline-badge .bg-red.bg-lighten-1{background-color:#eef0f3!important}.timeline-badge .bg-red.bg-lighten-1 .timeline-year{color:#3d4654}\n"], dependencies: [{ kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i5.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "component", type: i6$5.Rating, selector: "p-rating", inputs: ["readonly", "stars", "iconOnClass", "iconOnStyle", "iconOffClass", "iconOffStyle", "autofocus"], outputs: ["onRate", "onFocus", "onBlur"] }, { kind: "component", type: EditPortfoliosComponent, selector: "pw-edit-portfolios", inputs: ["id", "slug"], outputs: ["successEvent"] }, { kind: "component", type: EditProjectModalComponent, selector: "pw-edit-project-modal", outputs: ["cancelEvent", "saveEvent"] }, { kind: "component", type: EditRecommendationModalComponent, selector: "pw-edit-recommendation-modal", inputs: ["user"] }, { kind: "component", type: EditSkillsModalComponent, selector: "pw-edit-skills-modal", inputs: ["userId", "slug", "entityType", "entityEntity"], outputs: ["saveEvent"] }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
3466
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: UserProjectsComponent, isStandalone: false, selector: "pw-user-projects", inputs: { user: "user", isEdit: "isEdit", slug: "slug" }, viewQueries: [{ propertyName: "projectModal", first: true, predicate: EditProjectModalComponent, descendants: true, static: true }, { propertyName: "skillModal", first: true, predicate: EditSkillsModalComponent, descendants: true }, { propertyName: "recommendationModal", first: true, predicate: EditRecommendationModalComponent, descendants: true, static: true }, { propertyName: "portfolios", first: true, predicate: EditPortfoliosComponent, descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"row\">\n <div class=\"col-sm-12 mt-2\">\n <h2>User's Projects</h2>\n @if (isEdit) {\n <div class=\"row\"\n >\n <div class=\"col-12\">\n <div class=\"content-header\">\n <button class=\"btn btn-primary float-end\"\n (click)=\"onEditProject(null)\">\n <i class=\"fa fa-plus-circle\" aria-hidden=\"true\"></i> {{'Create Project' | transloco}}\n </button>\n </div>\n </div>\n </div>\n }\n @if (!isLoaded) {\n <div class=\"w-100 text-center mt-3\"\n >\n <p-progressSpinner strokeWidth=\"2\"> </p-progressSpinner>\n </div>\n }\n @if (projects?.length) {\n <div id=\"timeline\"\n class=\"timeline-center timeline-wrapper\"\n >\n <ul class=\"timeline\">\n <li class=\"timeline-line\"></li>\n </ul>\n <ul class=\"timeline\">\n <li class=\"timeline-line\"></li>\n @for (\n project of projects; track trackByProject(i,\n project); let i = $index; let odd = $odd; let even = $even) {\n <li class=\"timeline-item\"\n [ngClass]=\"{ 'mt-5': odd }\"\n >\n <div class=\"timeline-badge\">\n <span class=\"bg-red bg-lighten-1\"\n data-bs-toggle=\"tooltip\"\n data-placement=\"right\"\n title=\"Portfolio project work\">\n <span class=\"timeline-year\"> {{ project.start_year }} </span>\n </span>\n </div>\n <div class=\"timeline-card card pb-0\">\n <div class=\"card-header\">\n <h4 class=\"mb-0 card-title\">\n <a>{{ project.title }}</a>\n </h4>\n <div class=\"card-subtitle text-muted mt-0\">\n <span class=\"font-small-3\">\n {{ project.start_year }} - {{ project.end_year }}</span>\n </div>\n </div>\n <div class=\"card-body project-card\">\n @if (project.project_pictures?.length) {\n <i\n class=\"fal fa-times\"\n (click)=\"deletePicture(project)\"\n (keydown.enter)=\"deletePicture(project)\"\n aria-hidden=\"true\"\n ></i>\n <img class=\"img-fluid project-picture\"\n [src]=\"project.project_pictures[0].picture.url\"\n alt=\"Project Cover\" />\n }\n <div class=\"card-body\">\n <div class=\"\">\n <p class=\"card-text\">{{ project.description }}</p>\n <div class=\"list-inline mb-1\">\n <!-- Skills -->\n @if (project.tags?.length) {\n <div>\n <div class=\"my-2\">\n <i class=\"fa fa-user-tag\" aria-hidden=\"true\"></i>\n Skills\n </div>\n @for (tag of project.tags; track tag) {\n <span class=\"badge bg-success me-2\">{{\n tag.name\n }}</span>\n }\n </div>\n }\n @if (project.project_recommendations?.length) {\n <div class=\"mt-2\"\n >\n <div class=\"my-2\">\n <i\n class=\"fa fa-clipboard-check me-2\"\n aria-hidden=\"true\"\n ></i>\n Recommendations\n </div>\n @for (\n recommendation of project.project_recommendations\n ; track\n recommendation) {\n <section class=\"mb-2\"\n >\n <div class=\"me-2\">\n Client: {{ recommendation?.client_name }}\n </div>\n <div class=\"me-2\">\n Message: {{ recommendation?.description }}\n </div>\n <div class=\"row recommendation\">\n <div class=\"col-4\">\n <span>Communication</span>\n <p-rating [(ngModel)]=\"\n recommendation.communication\n \"\n [cancel]=\"false\"\n [readonly]=\"true\">\n </p-rating>\n </div>\n <div class=\"col-4\">\n <span>Quality</span>\n <p-rating [(ngModel)]=\"recommendation.quality\"\n [cancel]=\"false\"\n [readonly]=\"true\">\n </p-rating>\n </div>\n <div class=\"col-4\">\n <span>Time</span>\n <p-rating [(ngModel)]=\"recommendation.time\"\n [cancel]=\"false\"\n [readonly]=\"true\">\n </p-rating>\n </div>\n </div>\n </section>\n }\n </div>\n }\n @if (isEdit) {\n <div class=\"text-end mt-3 d-flex justify-content-end project-actions\"\n >\n <!-- Project Edit -->\n <span class=\"btn btn-link pb-0 actions\"\n (keydown.enter)=\"onEditProject(project)\"\n (click)=\"onEditProject(project)\">\n Edit\n </span>\n <button class=\"btn btn-link pb-0 actions\"\n (click)=\"openSkills(project)\">\n Skills\n </button>\n <pw-edit-skills-modal [userId]=\"user?.id\"\n entityEntity=\"Project\"\n entityType=\"skills\"\n (saveEvent)=\"onSkillsSave()\"\n [slug]=\"project?.slug\">\n </pw-edit-skills-modal>\n <!-- Portfolios -->\n <button class=\"btn btn-link pb-0 actions\"\n (click)=\"openPortfolios(project.id)\">\n Photos\n </button>\n <pw-edit-portfolios [slug]=\"user?.slug\"\n [id]=\"project.id\"\n (successEvent)=\"getProjects()\">\n </pw-edit-portfolios>\n <span class=\"btn btn-link pb-0 delete-project actions\"\n (keydown.enter)=\"onDeleteProject(project)\"\n (click)=\"onDeleteProject(project)\">\n Delete\n </span>\n </div>\n }\n <!-- Recommendation -->\n @if (!isEdit) {\n <span class=\"pe-1 mt-3\"\n (click)=\"editRecommendation(project)\"\n (keydown.enter)=\"editRecommendation(project)\"\n >\n <a class=\"primary\"><span class=\"fa fa-commenting-o\"></span> Endorse\n </a></span>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n </li>\n }\n </ul>\n </div>\n }\n @if (projects?.length === 0 && isLoaded) {\n<pw-no-data [withImage]=\"true\" [message]=\"\n isEdit\n ? ('User.Profile.Projects.NoProjects' | transloco)\n : ('User.Profile.Projects.NoUserProjects' | transloco)\n \"\n >\n </pw-no-data>\n }\n </div>\n</div>\n<pw-edit-project-modal (saveEvent)=\"onSaveProject($event)\"></pw-edit-project-modal>\n<pw-edit-recommendation-modal [user]=\"user\"></pw-edit-recommendation-modal>\n", styles: ["@charset \"UTF-8\";:root{--first: rgb(23 105 225);--second: rgb(54 194 131);--third: rgb(255 171 0);--text: rgb(34 34 34);--tabs_bg: rgb(23 105 225);--tabs_sub_bg: rgb(70, 136, 236);--tabs_text: rgb(255 255 255);--titles: rgb(34 34 34);--sidebar_bg: rgb(0, 48, 63);--sidebar_text: rgb(255 255 255)}.project-card{position:relative}.project-card i.fa-times{color:#fff;display:none;font-size:20px;position:absolute;right:39px;top:14px}.project-card:hover i.fa-times{display:inline}.timeline-card.card{min-height:auto;border:1px solid #e2e5ea;border-radius:10px;box-shadow:0 1px 2px #1018280f}.timeline-card.card .card-header{padding:14px 16px 6px}.timeline-card.card .badge.bg-success{border-radius:9999px;background-color:#e7f5ee!important;color:#1f7a47!important;border:1px solid #c9e9d6;font-weight:600}.timeline-card.card .card-body.project-card{padding:0 20px 1rem}.timeline-card.card .card-body.project-card .card-body{padding:20px 0 0}@media only screen and (max-width:767px){.timeline-center{margin-top:30px}.timeline-center .project-actions .btn{padding:.375rem .5rem}}.actions{color:var(--first)!important}.timeline-badge .bg-red.bg-lighten-1{background-color:#eef0f3!important}.timeline-badge .bg-red.bg-lighten-1 .timeline-year{color:#3d4654}\n"], dependencies: [{ kind: "directive", type: i4.LazyImgDirective, selector: "img" }, { kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "component", type: i4$1.ProgressSpinner, selector: "p-progressSpinner, p-progress-spinner, p-progressspinner", inputs: ["styleClass", "strokeWidth", "fill", "animationDuration", "ariaLabel"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i7.NoDataComponent, selector: "pw-no-data", inputs: ["message", "description", "withImage"] }, { kind: "component", type: i6$3.Rating, selector: "p-rating", inputs: ["readonly", "stars", "iconOnClass", "iconOnStyle", "iconOffClass", "iconOffStyle", "autofocus"], outputs: ["onRate", "onFocus", "onBlur"] }, { kind: "component", type: EditPortfoliosComponent, selector: "pw-edit-portfolios", inputs: ["id", "slug"], outputs: ["successEvent"] }, { kind: "component", type: EditProjectModalComponent, selector: "pw-edit-project-modal", outputs: ["cancelEvent", "saveEvent"] }, { kind: "component", type: EditRecommendationModalComponent, selector: "pw-edit-recommendation-modal", inputs: ["user"] }, { kind: "component", type: EditSkillsModalComponent, selector: "pw-edit-skills-modal", inputs: ["userId", "slug", "entityType", "entityEntity"], outputs: ["saveEvent"] }, { kind: "pipe", type: i8.TranslocoPipe, name: "transloco" }] }); }
|
|
3369
3467
|
}
|
|
3370
3468
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: UserProjectsComponent, decorators: [{
|
|
3371
3469
|
type: Component,
|
|
@@ -3609,6 +3707,10 @@ class UserModuleModule {
|
|
|
3609
3707
|
AddSubscriptionComponent,
|
|
3610
3708
|
SavedCardDetailsComponent,
|
|
3611
3709
|
SubscriptionCredentialComponent,
|
|
3710
|
+
HumanizeCredentialNamePipe,
|
|
3711
|
+
CredentialAvatarHuePipe,
|
|
3712
|
+
SubscriptionNameByIdPipe,
|
|
3713
|
+
ClearMaskedOnFocusDirective,
|
|
3612
3714
|
UpdatePaymentDetailsComponent,
|
|
3613
3715
|
UpgradeSubscriptionComponent,
|
|
3614
3716
|
UserSubscriptionDetailsComponent,
|
|
@@ -3631,6 +3733,7 @@ class UserModuleModule {
|
|
|
3631
3733
|
UserProfilePageComponent,
|
|
3632
3734
|
UserProjectsComponent,
|
|
3633
3735
|
SupportDetailsComponent], imports: [InputTextModule,
|
|
3736
|
+
AppLoaderModule,
|
|
3634
3737
|
DirectivesModule,
|
|
3635
3738
|
CommonModule,
|
|
3636
3739
|
RouterModule,
|
|
@@ -3654,6 +3757,10 @@ class UserModuleModule {
|
|
|
3654
3757
|
AddSubscriptionComponent,
|
|
3655
3758
|
SavedCardDetailsComponent,
|
|
3656
3759
|
SubscriptionCredentialComponent,
|
|
3760
|
+
HumanizeCredentialNamePipe,
|
|
3761
|
+
CredentialAvatarHuePipe,
|
|
3762
|
+
SubscriptionNameByIdPipe,
|
|
3763
|
+
ClearMaskedOnFocusDirective,
|
|
3657
3764
|
UpdatePaymentDetailsComponent,
|
|
3658
3765
|
UpgradeSubscriptionComponent,
|
|
3659
3766
|
UserSubscriptionDetailsComponent,
|
|
@@ -3688,6 +3795,7 @@ class UserModuleModule {
|
|
|
3688
3795
|
deps: [AppConfigService]
|
|
3689
3796
|
}
|
|
3690
3797
|
], imports: [InputTextModule,
|
|
3798
|
+
AppLoaderModule,
|
|
3691
3799
|
DirectivesModule,
|
|
3692
3800
|
CommonModule,
|
|
3693
3801
|
RouterModule,
|
|
@@ -3709,6 +3817,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
|
|
|
3709
3817
|
AddSubscriptionComponent,
|
|
3710
3818
|
SavedCardDetailsComponent,
|
|
3711
3819
|
SubscriptionCredentialComponent,
|
|
3820
|
+
HumanizeCredentialNamePipe,
|
|
3821
|
+
CredentialAvatarHuePipe,
|
|
3822
|
+
SubscriptionNameByIdPipe,
|
|
3823
|
+
ClearMaskedOnFocusDirective,
|
|
3712
3824
|
UpdatePaymentDetailsComponent,
|
|
3713
3825
|
UpgradeSubscriptionComponent,
|
|
3714
3826
|
UserSubscriptionDetailsComponent,
|
|
@@ -3734,6 +3846,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
|
|
|
3734
3846
|
],
|
|
3735
3847
|
imports: [
|
|
3736
3848
|
InputTextModule,
|
|
3849
|
+
AppLoaderModule,
|
|
3737
3850
|
DirectivesModule,
|
|
3738
3851
|
CommonModule,
|
|
3739
3852
|
RouterModule,
|
|
@@ -3754,6 +3867,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
|
|
|
3754
3867
|
AddSubscriptionComponent,
|
|
3755
3868
|
SavedCardDetailsComponent,
|
|
3756
3869
|
SubscriptionCredentialComponent,
|
|
3870
|
+
HumanizeCredentialNamePipe,
|
|
3871
|
+
CredentialAvatarHuePipe,
|
|
3872
|
+
SubscriptionNameByIdPipe,
|
|
3873
|
+
ClearMaskedOnFocusDirective,
|
|
3757
3874
|
UpdatePaymentDetailsComponent,
|
|
3758
3875
|
UpgradeSubscriptionComponent,
|
|
3759
3876
|
UserSubscriptionDetailsComponent,
|
|
@@ -3796,5 +3913,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
|
|
|
3796
3913
|
* Generated bundle index. Do not edit.
|
|
3797
3914
|
*/
|
|
3798
3915
|
|
|
3799
|
-
export { AccountComponent, AccountDetailsComponent, AddSubscriptionComponent, CommunicationTabComponent, EditPortfoliosComponent, EditProjectModalComponent, EditQualificationsModalComponent, EditRecommendationModalComponent, EditSkillsModalComponent, EditSocialLinksComponent, EditUserProfileModalComponent, OthersTabComponent, PortfoliosComponent, SavedCardDetailsComponent, SecurityTabComponent, SettingsComponent, SubscriptionCredentialComponent, SupportComponent, SupportDetailsComponent, UpdatePaymentDetailsComponent, UpgradeSubscriptionComponent, UserAboutComponent, UserInvoiceComponent, UserModuleModule, UserProfilePageComponent, UserProjectsComponent, UserSubscriptionDetailsComponent, UserSubscriptionListComponent };
|
|
3916
|
+
export { AccountComponent, AccountDetailsComponent, AddSubscriptionComponent, ClearMaskedOnFocusDirective, CommunicationTabComponent, CredentialAvatarHuePipe, EditPortfoliosComponent, EditProjectModalComponent, EditQualificationsModalComponent, EditRecommendationModalComponent, EditSkillsModalComponent, EditSocialLinksComponent, EditUserProfileModalComponent, HumanizeCredentialNamePipe, OthersTabComponent, PortfoliosComponent, SavedCardDetailsComponent, SecurityTabComponent, SettingsComponent, SubscriptionCredentialComponent, SubscriptionNameByIdPipe, SupportComponent, SupportDetailsComponent, UpdatePaymentDetailsComponent, UpgradeSubscriptionComponent, UserAboutComponent, UserInvoiceComponent, UserModuleModule, UserProfilePageComponent, UserProjectsComponent, UserSubscriptionDetailsComponent, UserSubscriptionListComponent };
|
|
3800
3917
|
//# sourceMappingURL=posiwise-user-module.mjs.map
|