{"version":3,"sources":["libs/conversation/core/src/lib/channels/conversation-facebook.service.ts","libs/conversation/core/src/lib/channels/conversation-sms.service.ts","libs/conversation/core/src/lib/channels/conversation-platform.service.ts","libs/conversation/core/src/lib/firebase.config.ts","libs/conversation/core/src/lib/conversation-core.module.ts","libs/ai-knowledge/src/lib/ai-knowledge.module.ts","libs/ai-knowledge/src/lib/delete-custom-knowledge/delete-custom-knowledge.component.ts","libs/ai-knowledge/src/lib/delete-custom-knowledge/delete-custom-knowledge.component.html","libs/ai-knowledge/src/lib/knowledge-source-management/knowledge-source-management.component.ts","libs/ai-knowledge/src/lib/knowledge-source-management/knowledge-source-management.component.html","apps/partner-center-client/src/app/access-denied/access-denied.component.ts","apps/partner-center-client/src/app/access-denied/access-denied.component.html","apps/partner-center-client/src/app/accounts/account-delete.component.ts","apps/partner-center-client/src/app/activation/core/analytics/utils.ts","apps/partner-center-client/src/app/activation/core/analytics/activation-analytics.service.ts","apps/partner-center-client/src/app/activation/shared/shared-activation.module.ts","apps/partner-center-client/src/app/accounts/account-add-to-list.component.ts","apps/partner-center-client/src/app/accounts/change-plan-dialog/change-plan-dialog.module.ts","apps/partner-center-client/src/app/accounts/account.module.ts","apps/partner-center-client/src/app/pop-up-cta-check.ts","apps/partner-center-client/src/app/app-nav-item.component.ts","apps/partner-center-client/src/app/app-nav-item.component.html","libs/email-ui/email-activity/src/activity-table/activity-table.service.ts","libs/email-ui/email-activity/src/activity-table/activity-table.component.ts","libs/email-ui/email-activity/src/activity-table/activity-table.component.html","apps/partner-center-client/src/app/users/user/preview-welcome-email-dialog.component.ts","apps/partner-center-client/src/app/bulk-import/map-change-dialog.component.ts","apps/partner-center-client/src/app/bulk-import/map-change-dialog.component.html","apps/partner-center-client/src/app/bulk-import/bulk-import-mapping-row.component.ts","apps/partner-center-client/src/app/bulk-import/bulk-import-mapping-row.component.html","apps/partner-center-client/src/app/bulk-import/bulk-import-mapper.component.ts","apps/partner-center-client/src/app/bulk-import/bulk-import-mapper.component.html","apps/partner-center-client/src/app/bulk-import/bulk-import.component.ts","apps/partner-center-client/src/app/bulk-import/bulk-import.component.html","apps/partner-center-client/src/app/campaigns/account-selector/campaign-account-selector.component.ts","apps/partner-center-client/src/app/campaigns/account-selector/campaign-account-selector.component.html","apps/partner-center-client/src/app/common/variable-menu/variable-menu-item-selector/variable-menu-item-selector.component.ts","apps/partner-center-client/src/app/common/variable-menu/variable-menu-item-selector/variable-menu-item-selector.component.html","apps/partner-center-client/src/app/common/variable-menu/variable-menu.service.ts","apps/partner-center-client/src/app/common/variable-menu/variable-menu-dialog/variable-menu-dialog.component.ts","apps/partner-center-client/src/app/common/variable-menu/variable-menu-dialog/variable-menu-dialog.component.html","apps/partner-center-client/src/app/core/guards/inbox-modal.guard.ts","apps/partner-center-client/src/app/partner/company-profile-api.service.ts","apps/partner-center-client/src/app/partner/company-profile.component.ts","apps/partner-center-client/src/app/partner/company-profile.component.html","apps/partner-center-client/src/app/partner/partner.module.ts","apps/partner-center-client/src/app/customize-design/customize-exec-report/customize-exec-report.service.ts","apps/partner-center-client/src/app/customize-design/customize-exec-report/customize-exec-report.component.ts","apps/partner-center-client/src/app/customize-design/customize-exec-report/customize-exec-report.component.html","apps/partner-center-client/src/app/core/user-branding.service.ts","apps/partner-center-client/src/app/customize-design/customize-partner/forms/customize-api.service.ts","apps/partner-center-client/src/app/customize-design/customize-partner/forms/brand-color/brand-color.component.ts","apps/partner-center-client/src/app/customize-design/customize-partner/forms/brand-color/brand-color.component.html","apps/partner-center-client/src/app/customize-design/customize-partner/forms/customize-api-file-uploader.service.ts","apps/partner-center-client/src/app/customize-design/customize-partner/forms/customize-image-upload/customize-image-upload.component.ts","apps/partner-center-client/src/app/customize-design/customize-partner/forms/customize-image-upload/customize-image-upload.component.html","apps/partner-center-client/src/app/customize-design/customize-partner/forms/product-names/product-names.component.ts","apps/partner-center-client/src/app/customize-design/customize-partner/forms/product-names/product-names.component.html","apps/partner-center-client/src/app/customize-design/customize-partner/forms/exit-link/exit-link.component.ts","apps/partner-center-client/src/app/customize-design/customize-partner/forms/exit-link/exit-link.component.html","apps/partner-center-client/src/app/customize-design/customize-partner/forms/product-settings/product-settings.component.ts","apps/partner-center-client/src/app/customize-design/customize-partner/forms/product-settings/product-settings.component.html","node_modules/@vendasta/listing-sync-pro/fesm2020/vendasta-listing-sync-pro.mjs","apps/partner-center-client/src/app/customize-design/customize-partner/forms/lsp-wrapper.service.ts","apps/partner-center-client/src/app/customize-design/customize-partner/forms/listing-sources/listing-sources.component.ts","apps/partner-center-client/src/app/customize-design/customize-partner/forms/listing-sources/listing-sources.component.html","apps/partner-center-client/src/app/customize-design/customize-partner/forms/sales-snapshot-settings/sales-snapshot-settings.component.ts","apps/partner-center-client/src/app/customize-design/customize-partner/forms/sales-snapshot-settings/sales-snapshot-settings.component.html","apps/partner-center-client/src/app/customize-design/customize-partner/customize-partner.component.ts","apps/partner-center-client/src/app/customize-design/customize-partner/customize-partner.component.html","apps/partner-center-client/src/app/customize-design/order-config/preview-email-dialog/preview-email-dialog.component.ts","apps/partner-center-client/src/app/customize-design/order-config/preview-email-dialog/preview-email-dialog.component.html","apps/partner-center-client/src/app/customize-design/order-config/automation-name-display/automation-name-display.component.ts","apps/partner-center-client/src/app/customize-design/order-config/automation-name-display/automation-name-display.component.html","apps/partner-center-client/src/app/customize-design/order-config/order-config.ts","apps/partner-center-client/src/app/customize-design/order-config/restore-warning-dialog/restore-warning-dialog.component.ts","apps/partner-center-client/src/app/customize-design/order-config/restore-warning-dialog/restore-warning-dialog.component.html","apps/partner-center-client/src/app/customize-design/order-setup/order-setup.service.ts","apps/partner-center-client/src/app/customize-design/order-setup/order-setup.component.ts","apps/partner-center-client/src/app/customize-design/order-setup/order-setup.component.html","apps/partner-center-client/src/app/customize-design/order-config/order-config.component.ts","apps/partner-center-client/src/app/customize-design/order-config/order-config.component.html","apps/partner-center-client/src/app/customize-design/sales-orders-decline-reasons/dialog/declined-reason-dialog.component.ts","apps/partner-center-client/src/app/customize-design/sales-orders-decline-reasons/dialog/declined-reason-dialog.component.html","apps/partner-center-client/src/app/customize-design/sales-orders-decline-reasons/sales-orders-decline-reasons.component.ts","apps/partner-center-client/src/app/customize-design/sales-orders-decline-reasons/sales-orders-decline-reasons.component.html","apps/partner-center-client/src/app/customize-design/sales-orders-decline-reasons/sales-orders-decline-reasons.module.ts","apps/partner-center-client/src/app/customize-design/customize-design.module.ts","apps/partner-center-client/src/app/email-builder-sandbox/email-builder-sandbox.component.ts","apps/partner-center-client/src/app/email-builder-sandbox/email-builder-sandbox.component.html","libs/email-ui/domain-authorization/src/domain-cache.service.ts","libs/email-ui/domain-authorization/src/domain-info-card/dependencies.ts","libs/email-ui/domain-authorization/src/domain-status-icon/domain-status-icon.component.ts","libs/email-ui/domain-authorization/src/domain-status-icon/domain-status-icon.component.html","libs/email-ui/domain-authorization/src/domain-records-table/domain-records-table.component.ts","libs/email-ui/domain-authorization/src/domain-records-table/domain-records-table.component.html","libs/email-ui/domain-authorization/src/domain-info-card/domain-info-card.component.ts","libs/email-ui/domain-authorization/src/domain-info-card/domain-info-card.component.html","libs/email-ui/domain-authorization/src/sender-info-card/sender-info-form/default.ts","libs/email-ui/domain-authorization/src/domains/can-add-domain.pipe.ts","libs/email-ui/domain-authorization/src/domains/domains.component.ts","libs/email-ui/domain-authorization/src/domains/domains.component.html","libs/email-ui/domain-authorization/src/new-domain-dialog/new-domain-dialog.component.ts","libs/email-ui/domain-authorization/src/new-domain-dialog/new-domain-dialog.component.html","libs/email-ui/domain-authorization/src/sender-info-card/dependencies.ts","libs/email-ui/email-form-validators/src/validators.ts","libs/email-ui/domain-authorization/src/domains-dialog/domain-status-and-name/domain-status-and-name.component.ts","libs/email-ui/domain-authorization/src/domains-dialog/domain-status-and-name/domain-status-and-name.component.html","libs/email-ui/domain-authorization/src/domains-dialog/domains-dialog.component.ts","libs/email-ui/domain-authorization/src/domains-dialog/domains-dialog.component.html","libs/email-ui/domain-authorization/src/sender-info-card/sender-info-form/selected-domain.ts","libs/email-ui/email-username-input/email-username-input.component.ts","libs/email-ui/email-username-input/email-username-input.component.html","libs/email-ui/domain-authorization/src/sender-info-card/sender-info-form/sender-info-form.component.ts","libs/email-ui/domain-authorization/src/sender-info-card/sender-info-form/sender-info-form.component.html","libs/email-ui/domain-authorization/src/sender-info-card/sender-info-card.component.ts","libs/email-ui/domain-authorization/src/sender-info-card/sender-info-card.component.html","libs/email-ui/domain-authorization/src/domain-authorization.component.ts","libs/email-ui/domain-authorization/src/domain-authorization.component.html","libs/email-ui/domain-authorization/src/domain-status-icon/domain-status-icon.module.ts","libs/email-ui/domain-authorization/src/domain-records-table/domain-records-table.module.ts","libs/email-ui/domain-authorization/src/domain-info-card/domain-info-card.module.ts","libs/email-ui/domain-authorization/src/new-domain-dialog/new-domain-dialog.module.ts","libs/email-ui/domain-authorization/src/domains/domains.module.ts","libs/email-ui/email-username-input/email-username-input.module.ts","libs/email-ui/domain-authorization/src/domain-info-dialog/domain-info-dialog.module.ts","libs/email-ui/domain-authorization/src/domains-dialog/domains-dialog.module.ts","libs/email-ui/domain-authorization/src/sender-info-card/sender-info-card.module.ts","libs/email-ui/domain-authorization/src/domain-authorization.module.ts","apps/partner-center-client/src/app/email-settings-v2/email-settings.component.ts","apps/partner-center-client/src/app/email-settings-v2/email-settings.component.html","node_modules/@vendasta/help-center/fesm2020/vendasta-help-center.mjs","apps/partner-center-client/src/app/help-center/help-case-card/help-center-cases.ts","apps/partner-center-client/src/app/help-center/help-side-drawer/help-side-drawer-template-ref.service.ts","apps/partner-center-client/src/app/help-center/help-side-drawer/help-closing-side-drawer/help-closing-side-drawer.component.ts","apps/partner-center-client/src/app/help-center/help-side-drawer/help-closing-side-drawer/help-closing-side-drawer.component.html","apps/partner-center-client/src/app/help-center/help-case-card/help-case-card.component.ts","apps/partner-center-client/src/app/help-center/help-case-card/help-case-card.component.html","apps/partner-center-client/src/app/help-center/help-search-card/help-center-articles.ts","apps/partner-center-client/src/app/help-center/help-search-card/help-search-card.component.ts","apps/partner-center-client/src/app/help-center/help-search-card/help-search-card.component.html","apps/partner-center-client/src/app/help-center/help-center.component.ts","apps/partner-center-client/src/app/help-center/help-center.component.html","apps/partner-center-client/src/app/local-login/local-login.component.ts","apps/partner-center-client/src/app/local-login/local-login.component.html","apps/partner-center-client/src/app/local-login/local-login.module.ts","apps/partner-center-client/src/app/page-not-found/page-not-found.component.ts","apps/partner-center-client/src/app/page-not-found/page-not-found.component.html","apps/partner-center-client/src/app/pipeline/view-router.ts","apps/partner-center-client/src/app/product-order-form-proxy/product-order-form-proxy.component.ts","apps/partner-center-client/src/app/terms-of-service/terms-of-service.service.ts","apps/partner-center-client/src/app/terms-of-service/terms-of-service.component.ts","apps/partner-center-client/src/app/terms-of-service/terms-of-service.component.html","apps/partner-center-client/src/app/terms-of-service/terms-of-service.module.ts","apps/partner-center-client/src/app/app-routing.module.ts","apps/partner-center-client/src/app/app.component.ts","apps/partner-center-client/src/app/app.component.html","apps/partner-center-client/src/lib/wootric.ts","apps/partner-center-client/src/app/core/url.service.ts","apps/partner-center-client/src/app/omni-search/omni-search.service.ts","apps/partner-center-client/src/app/omni-search/omni-app-icon.component.ts","apps/partner-center-client/src/app/omni-search/omni-app-icon.component.html","apps/partner-center-client/src/app/omni-search/account-group-searcher.component.ts","apps/partner-center-client/src/app/omni-search/account-group-searcher.component.html","apps/partner-center-client/src/app/omni-search/omni-search.component.ts","apps/partner-center-client/src/app/omni-search/partner-overview.component.ts","apps/partner-center-client/src/app/omni-search/partner-overview.component.html","apps/partner-center-client/src/app/omni-search/partner-switcher.component.ts","apps/partner-center-client/src/app/omni-search/partner-switcher.component.html","apps/partner-center-client/src/app/omni-search/user-switcher.component.ts","apps/partner-center-client/src/app/omni-search/user-switcher.component.html","apps/partner-center-client/src/app/common/level-badge/level-badge-store.service.ts","apps/partner-center-client/src/app/common/level-badge/level-badge.component.ts","apps/partner-center-client/src/app/common/level-badge/level-badge.component.html","apps/partner-center-client/src/app/common/level-badge/trial-badge.component.ts","apps/partner-center-client/src/app/common/level-badge/trial-badge.component.html","apps/partner-center-client/src/app/whitelabel/logo/logo.component.ts","apps/partner-center-client/src/app/whitelabel/logo/logo.component.html","apps/partner-center-client/src/app/trial-banner/trial-banner/trial-banner.component.ts","apps/partner-center-client/src/app/trial-banner/trial-banner/trial-banner.component.html","apps/partner-center-client/src/app/help-center/help-side-drawer/help-side-drawer-container/help-side-drawer-container.component.ts","apps/partner-center-client/src/app/help-center/help-side-drawer/help-side-drawer-container/help-side-drawer-container.component.html","node_modules/ngx-material-file-input/fesm2020/ngx-material-file-input.mjs","apps/partner-center-client/src/app/bulk-import/bulk-import.module.ts","apps/partner-center-client/src/app/common/level-badge/level-badge.module.ts","apps/partner-center-client/src/app/common/fec/fec-menu/menu.service.ts","apps/partner-center-client/src/app/common/fec/fec-menu/menu.module.ts","apps/partner-center-client/src/app/common/fec/fec-nav/navigation.module.ts","apps/partner-center-client/src/app/common/variable-menu/variable-menu-dialog/variable-menu-mat-dialog.component.ts","apps/partner-center-client/src/app/core/url-serializer.service.ts","apps/partner-center-client/src/app/email-settings-v2/email-settings-v2.module.ts","libs/email-ui/sender-info-reset/src/sender-info-reset.service.ts","libs/email-ui/sender-info-reset/src/sender-info-reset.module.ts","apps/partner-center-client/src/app/common/copycat/copycate.module.ts","apps/partner-center-client/src/app/email-settings/shared/domain-records-table/domain-records-table.module.ts","apps/partner-center-client/src/app/email-settings/shared/domain-records.module.ts","apps/partner-center-client/src/app/email-settings/pending-domain/pending-domain.module.ts","apps/partner-center-client/src/app/email-settings/campaign-settings.module.ts","apps/partner-center-client/src/app/trial-banner/trial-banner.module.ts","apps/partner-center-client/src/app/help-center/help-side-drawer/help-side-drawer.module.ts","apps/partner-center-client/src/app/help-center/help-center.module.ts","apps/partner-center-client/src/app/inbox/conversation-partner-center.service.ts","apps/partner-center-client/src/app/inbox/external-providers.ts","apps/partner-center-client/src/app/inbox/providers.ts","apps/partner-center-client/src/app/marketing/base-template-editing/app-listing.service.ts","apps/partner-center-client/src/app/marketing/base-template-editing/template-editor-page/partner-logo.ts","apps/partner-center-client/src/app/reporting/providers.ts","apps/partner-center-client/src/app/users/user-bulk-actions/bulk-notifications-change/bulk-notifications-change.component.ts","apps/partner-center-client/src/app/users/user-bulk-actions/bulk-notifications-change/bulk-notifications-change.component.html","apps/partner-center-client/src/app/users/user-bulk-actions/bulk-tab-access-change/bulk-tab-access-change.component.ts","apps/partner-center-client/src/app/users/user-bulk-actions/bulk-tab-access-change/bulk-tab-access-change.component.html","apps/partner-center-client/src/app/users/user-bulk-actions/user-bulk-actions.module.ts","apps/partner-center-client/src/app/whitelabel/whitelabel.module.ts","libs/partner-center-client/billing/static/src/lib/core/billing-core.module.ts","apps/partner-center-client/src/app/billing/billing-provider/billing-provider.module.ts","apps/partner-center-client/src/app/ai-knowledge/providers.ts","apps/partner-center-client/src/app/app.module.ts","apps/partner-center-client/src/main.ts"],"sourcesContent":["import { inject, Injectable } from '@angular/core';\nimport { ConversationChannel } from '@vendasta/conversation';\nimport { Observable, of } from 'rxjs';\nimport { ConversationDetail } from '../interface/conversation.interface';\nimport { AlertOptions, ConversationChannelService } from './conversation-channel.abstract';\nimport { Router } from '@angular/router';\n\n@Injectable()\nexport class ConversationFacebookService extends ConversationChannelService {\n private router = inject(Router);\n\n getChatComposerAlert(\n _partnerId: string,\n _accountGroupId: string,\n conversationDetail?: ConversationDetail,\n channels?: ConversationChannel[],\n ): Observable {\n if (\n conversationDetail?.conversation.channel === ConversationChannel.CONVERSATION_CHANNEL_FACEBOOK &&\n channels?.length === 0\n ) {\n return of({\n title: 'INBOX.SETTINGS.FACEBOOK_MESSENGER.ERRORS.CANNOT_SEND_MESSAGE',\n description: 'INBOX.SETTINGS.FACEBOOK_MESSENGER.ERRORS.CANNOT_SEND_MESSAGE_DESCRIPTION',\n action: {\n title: 'INBOX.SENDER.CLOSE_CONVERSATION',\n callback: () => this.router.navigate([`/account/location/${_accountGroupId}/inbox`]),\n },\n });\n }\n return of(null);\n }\n}\n","import { inject, Injectable } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { RegistrationStage, SmsRegistrationService } from '@galaxy/sms';\nimport { combineLatest, map, Observable } from 'rxjs';\nimport { InboxService } from '../inbox.service';\nimport { ConversationDetail } from '../interface/conversation.interface';\nimport { CONVERSATION_COUNTRY_TOKEN, CONVERSATION_SMS_ENABLED_TOKEN } from '../tokens';\nimport { AlertOptions, ConversationChannelService } from './conversation-channel.abstract';\n\n@Injectable()\nexport class ConversationSMSService extends ConversationChannelService {\n private router = inject(Router);\n private readonly smsRegistrationService = inject(SmsRegistrationService);\n private readonly inboxService = inject(InboxService);\n private readonly country$ = inject(CONVERSATION_COUNTRY_TOKEN);\n private readonly smsEnabled$ = inject(CONVERSATION_SMS_ENABLED_TOKEN);\n\n getChatComposerAlert(\n partnerId: string,\n accountGroupId: string,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n conversationDetail?: ConversationDetail,\n ): Observable {\n const stage$ = this.smsRegistrationService.registrationStage$;\n const SMSNumber$ = this.inboxService.SMSNumber$;\n return combineLatest([this.country$, this.smsEnabled$, stage$, SMSNumber$]).pipe(\n map(([accountGroupCountry, smsEnabled, stage, smsNumber]) => {\n const country = accountGroupCountry?.toLowerCase() || '';\n if (!smsEnabled) {\n return this.getSMSMessageEnabledError();\n }\n if (!smsNumber) {\n return this.getSMSMPhoneNumberError();\n }\n if (country != 'us' && smsNumber) {\n return null;\n }\n return stage !== RegistrationStage.RegistrationComplete ? this.getSMSRegistrationError(accountGroupId) : null;\n }),\n );\n }\n\n private getSMSRegistrationError(accountGroupId: string): AlertOptions {\n return {\n title: 'INBOX.SETTINGS.SMS_MESSAGES.COMPOSER_A2P_REGISTRATION_REQUIRED.TITLE',\n description: 'INBOX.SETTINGS.SMS_MESSAGES.COMPOSER_A2P_REGISTRATION_REQUIRED.DESCRIPTION',\n action: {\n title: 'INBOX.SETTINGS.SMS_MESSAGES.COMPOSER_A2P_REGISTRATION_REQUIRED.ACTION_TITLE',\n callback: () => this.router.navigate([`/account/location/${accountGroupId}/settings/inbox/sms-registration`]),\n },\n };\n }\n\n private getSMSMessageEnabledError(): AlertOptions {\n return {\n title: 'INBOX.SETTINGS.SMS_MESSAGES.NOT_ENABLED.TITLE',\n description: 'INBOX.SETTINGS.SMS_MESSAGES.NOT_ENABLED.DESCRIPTION',\n };\n }\n\n private getSMSMPhoneNumberError(): AlertOptions {\n return {\n title: 'INBOX.SETTINGS.SMS_MESSAGES.NO_PHONE_NUMBER.TITLE',\n description: 'INBOX.SETTINGS.SMS_MESSAGES.NO_PHONE_NUMBER.DESCRIPTION',\n };\n }\n}\n","import { Injectable, inject } from '@angular/core';\nimport { TranslateService } from '@ngx-translate/core';\nimport { ConversationChannel, ParticipantType } from '@vendasta/conversation';\nimport { Observable, map, of } from 'rxjs';\nimport { InboxService } from '../inbox.service';\nimport { ConversationDetail } from '../interface/conversation.interface';\nimport { CONVERSATION_COUNTRY_TOKEN } from '../tokens';\nimport { AlertOptions, ConversationChannelService } from './conversation-channel.abstract';\nimport { smsNotAvailableError } from './alert-helpers';\n\n@Injectable()\nexport class ConversationPlatformService extends ConversationChannelService {\n private readonly translationService = inject(TranslateService);\n private readonly inboxService = inject(InboxService);\n private readonly country$ = inject(CONVERSATION_COUNTRY_TOKEN);\n\n getChatComposerAlert(\n partnerId: string,\n accountGroupId: string,\n conversationDetail: ConversationDetail,\n ): Observable {\n if (conversationDetail.conversation.channel !== ConversationChannel.CONVERSATION_CHANNEL_INTERNAL) return of(null);\n // for business app form submission contacts conversations are created in either email or sms channel\n // but just in case exit early\n if (this.inboxService.isBusinessApp) return of(null);\n\n // for partners there should only one customer in one specific platform conversation (i.e. from form submission)\n const customerParticipant = conversationDetail?.participants?.find(\n (participant) => participant.participantType === ParticipantType.PARTICIPANT_TYPE_CUSTOMER,\n );\n if (!customerParticipant || (!customerParticipant.phoneNumber && !customerParticipant.email)) return of(null);\n\n return this.country$.pipe(\n map((country) => {\n return smsNotAvailableError(\n customerParticipant.phoneNumber,\n customerParticipant.email,\n country,\n this.translationService,\n );\n }),\n );\n }\n}\n","export const firebaseConfig = {\n apiKey: 'AIzaSyAmrv372h8otvJv6mBdHZzywPn5d6h6oPc',\n authDomain: 'inbox-291119.firebaseapp.com',\n databaseURL: 'https://inbox-291119.firebaseio.com',\n projectId: 'inbox-291119',\n storageBucket: 'inbox-291119.appspot.com',\n messagingSenderId: '133184929067',\n appId: '1:133184929067:web:aa3e2d0c6ccf993462596e',\n measurementId: 'G-MQLC4B4Q53',\n};\n","import { inject, InjectionToken, ModuleWithProviders, NgModule } from '@angular/core';\nimport { getApp, initializeApp, provideFirebaseApp } from '@angular/fire/app';\nimport { getFirestore, provideFirestore } from '@angular/fire/firestore';\nimport { Environment, EnvironmentService } from '@galaxy/core';\nimport { ConversationChannel, GlobalParticipantType, InboxApiService, PlatformLocation } from '@vendasta/conversation';\nimport { combineLatest, isObservable, map, Observable, of, switchMap } from 'rxjs';\nimport { catchError, shareReplay } from 'rxjs/operators';\nimport { ConversationChannelService } from './channels/conversation-channel.abstract';\nimport { ConversationFacebookService } from './channels/conversation-facebook.service';\nimport { ConversationGoogleService } from './channels/conversation-google.service';\nimport { ConversationSMSService } from './channels/conversation-sms.service';\nimport { ConversationWebchatService } from './channels/conversation-webchat.service';\nimport { ConversationPlatformService } from './channels/conversation-platform.service';\nimport { ConversationService } from './conversation.service';\nimport { firebaseConfig } from './firebase.config';\nimport { FirestoreService } from './firestore.service';\nimport { InboxNavigationService } from './inbox-navigation.service';\nimport { InboxNotificationService } from './inbox-notification.service';\nimport { InboxService } from './inbox.service';\nimport { ConversationConfig } from './interface/config.interface';\nimport { RouteConfig } from './interface/routes.interface';\nimport { ListingService } from './listing.service';\nimport { ParticipantService } from './participant.service';\nimport { TemplateService } from './template.service';\nimport {\n ACCOUNT_GROUP_ID_TOKEN,\n COMPANY_NAME_TOKEN,\n CONVERSATION_CHANNEL_SERVICE_TOKEN,\n CONVERSATION_CONFIG_TOKEN,\n CONVERSATION_CONVERSATION_CHANNELS_ENABLED_TOKEN,\n CONVERSATION_COUNTRY_TOKEN,\n CONVERSATION_FACEBOOK_MESSENGER_AVAILABLE_TOKEN,\n CONVERSATION_GEOGRAPHICAL_STATE_TOKEN,\n CONVERSATION_GOOGLE_BUSINESS_MESSAGES_AVAILABLE_TOKEN,\n CONVERSATION_IMAGE_SERVICE_TOKEN,\n CONVERSATION_INSTAGRAM_MESSAGES_AVAILABLE_TOKEN,\n CONVERSATION_PLATFORM_LOCATION_TOKEN,\n CONVERSATION_ROUTES_TOKEN,\n CONVERSATION_SMS_ENABLED_TOKEN,\n CONVERSATION_WEB_CHAT_ENABLED_TOKEN,\n FEATURE_FLAG_TOKEN,\n GROUP_ID_TOKEN,\n InboxImageService,\n MARKET_ID_TOKEN,\n PARTNER_BRAND_NAME_TOKEN,\n PARTNER_ID_TOKEN,\n StubInboxImageService,\n USER_ID_TOKEN,\n} from './tokens';\nimport { ViewService } from './view.service';\n\nconst SERVICE_PROVIDERS = [\n ViewService,\n ParticipantService,\n ConversationService,\n FirestoreService,\n InboxService,\n InboxNavigationService,\n ListingService,\n InboxNotificationService,\n ConversationGoogleService,\n ConversationFacebookService,\n ConversationSMSService,\n ConversationWebchatService,\n ConversationPlatformService,\n TemplateService,\n];\n\n@NgModule({\n imports: [\n provideFirebaseApp(() => initializeApp(firebaseConfig, 'inbox')),\n provideFirestore(() => getFirestore(getApp('inbox'))),\n ],\n})\nexport class ConversationCoreModule {\n static forRoot(c: { config: InjectionToken }): ModuleWithProviders {\n const result = {\n ngModule: ConversationCoreModule,\n providers: [\n ...SERVICE_PROVIDERS,\n { provide: USER_ID_TOKEN, deps: [CONVERSATION_CONFIG_TOKEN], useFactory: userIdFactory },\n { provide: ACCOUNT_GROUP_ID_TOKEN, deps: [CONVERSATION_CONFIG_TOKEN], useFactory: accountGroupIdFactory },\n {\n provide: CONVERSATION_COUNTRY_TOKEN,\n deps: [CONVERSATION_CONFIG_TOKEN],\n useFactory: countryFactory,\n },\n {\n provide: CONVERSATION_GEOGRAPHICAL_STATE_TOKEN,\n deps: [CONVERSATION_CONFIG_TOKEN],\n useFactory: geographicalState,\n },\n { provide: PARTNER_ID_TOKEN, deps: [CONVERSATION_CONFIG_TOKEN], useFactory: partnerIdFactory },\n { provide: PARTNER_BRAND_NAME_TOKEN, deps: [CONVERSATION_CONFIG_TOKEN], useFactory: partnerBrandNameFactory },\n { provide: MARKET_ID_TOKEN, deps: [CONVERSATION_CONFIG_TOKEN], useFactory: marketIdFactory },\n { provide: COMPANY_NAME_TOKEN, deps: [CONVERSATION_CONFIG_TOKEN], useFactory: companyNameFactory },\n {\n provide: CONVERSATION_PLATFORM_LOCATION_TOKEN,\n deps: [CONVERSATION_CONFIG_TOKEN],\n useFactory: platformLocationFactory,\n },\n {\n provide: CONVERSATION_CONVERSATION_CHANNELS_ENABLED_TOKEN,\n deps: [CONVERSATION_CONFIG_TOKEN],\n useFactory: conversationChannelsEnabledFactory,\n },\n {\n provide: FEATURE_FLAG_TOKEN,\n deps: [CONVERSATION_CONFIG_TOKEN],\n useFactory: featureFlagFactory,\n },\n {\n provide: CONVERSATION_IMAGE_SERVICE_TOKEN,\n deps: [CONVERSATION_CONFIG_TOKEN],\n useFactory: inboxImageServiceFactory,\n },\n { provide: CONVERSATION_ROUTES_TOKEN, deps: [CONVERSATION_CONFIG_TOKEN], useFactory: routesFactory },\n {\n provide: CONVERSATION_GOOGLE_BUSINESS_MESSAGES_AVAILABLE_TOKEN,\n deps: [CONVERSATION_CONFIG_TOKEN],\n useFactory: googleBusinessMessagesAvailableFactory,\n },\n {\n provide: CONVERSATION_FACEBOOK_MESSENGER_AVAILABLE_TOKEN,\n deps: [CONVERSATION_CONFIG_TOKEN],\n useFactory: facebookMessengerEnabledFactory,\n },\n {\n provide: CONVERSATION_INSTAGRAM_MESSAGES_AVAILABLE_TOKEN,\n deps: [CONVERSATION_CONFIG_TOKEN],\n useFactory: instagramMessagesEnabledFactory,\n },\n {\n provide: CONVERSATION_SMS_ENABLED_TOKEN,\n deps: [CONVERSATION_CONFIG_TOKEN],\n useFactory: smsEnabledFactory,\n },\n {\n provide: CONVERSATION_WEB_CHAT_ENABLED_TOKEN,\n deps: [CONVERSATION_CONFIG_TOKEN],\n useFactory: webchatEnabledFactory,\n },\n { provide: CONVERSATION_CONFIG_TOKEN, useExisting: c.config },\n { provide: CONVERSATION_CHANNEL_SERVICE_TOKEN, useFactory: abstractConversationChannelServiceFactory },\n {\n provide: GROUP_ID_TOKEN,\n deps: [CONVERSATION_CONFIG_TOKEN],\n useFactory: groupIdFactory,\n },\n ],\n };\n return result;\n }\n}\n\nfunction userIdFactory(config: ConversationConfig): Observable {\n return isObservable(config.userId$) ? config.userId$ : of(config.userId$);\n}\n\nfunction accountGroupIdFactory(config: ConversationConfig): Observable {\n return isObservable(config.accountGroupId$) ? config.accountGroupId$ : of(config.accountGroupId$);\n}\n\nfunction countryFactory(config: ConversationConfig): Observable {\n return isObservable(config.country$) ? config.country$ : of(config.country$);\n}\n\nfunction geographicalState(config: ConversationConfig): Observable {\n return isObservable(config.geographicalState$) ? config.geographicalState$ : of(config.geographicalState$);\n}\n\nfunction partnerIdFactory(config: ConversationConfig): Observable {\n return isObservable(config.partnerId$) ? config.partnerId$ : of(config.partnerId$);\n}\n\nfunction partnerBrandNameFactory(config: ConversationConfig): Observable {\n return isObservable(config.partnerBrandName$) ? config.partnerBrandName$ : of(config.partnerBrandName$);\n}\n\nfunction companyNameFactory(config: ConversationConfig): Observable {\n return isObservable(config.companyName$) ? config.companyName$ : of(config.companyName$);\n}\n\nfunction platformLocationFactory(config: ConversationConfig): PlatformLocation {\n return config.platformLocation;\n}\n\nfunction conversationChannelsEnabledFactory(\n config: ConversationConfig,\n): Observable {\n return isObservable(config.conversationChannelsEnabled$)\n ? config.conversationChannelsEnabled$\n : of(config.conversationChannelsEnabled$);\n}\n\nfunction routesFactory(config: ConversationConfig): Observable {\n return isObservable(config.routes$) ? config.routes$ : of(config.routes$);\n}\n\nfunction featureFlagFactory(config: ConversationConfig): Observable {\n if (!config.featureFlag$) {\n return of(false);\n }\n return config.featureFlag$;\n}\n\nfunction inboxImageServiceFactory(config: ConversationConfig): InboxImageService {\n return config.inboxImageService || inject(StubInboxImageService);\n}\n\nfunction marketIdFactory(config: ConversationConfig): Observable {\n return isObservable(config.marketId$) ? config.marketId$ : of(config.marketId$);\n}\n\nfunction smsEnabledFactory(config: ConversationConfig): Observable {\n const inboxApiService = inject(InboxApiService);\n const isEnabled$ = isObservable(config.smsEnabled$) ? config.smsEnabled$ : of(config.smsEnabled$);\n return combineLatest([config.accountGroupId$, isEnabled$]).pipe(\n switchMap(([agid, isEnabled]) => {\n if (!isEnabled || !agid) {\n return of({ configuration: { smsEnabled: false } });\n }\n return inboxApiService.getConfiguration({\n subjectParticipant: {\n participantType: GlobalParticipantType.GLOBAL_PARTICIPANT_TYPE_ACCOUNT_GROUP,\n internalParticipantId: agid,\n },\n });\n }),\n map((config): boolean => config.configuration.smsEnabled),\n shareReplay({ refCount: true, bufferSize: 1 }),\n catchError(() => of(false)),\n );\n}\n\nfunction webchatEnabledFactory(config: ConversationConfig): Observable {\n const isEnabled$ = isObservable(config.webChatEnabled$) ? config.webChatEnabled$ : of(false);\n\n return isEnabled$.pipe(\n shareReplay({ refCount: true, bufferSize: 1 }),\n catchError(() => of(false)),\n );\n}\n\nfunction facebookMessengerEnabledFactory(config: ConversationConfig): Observable {\n const inboxApiService = inject(InboxApiService);\n const enableable$ = isObservable(config.facebookMessengerSupported$)\n ? config.facebookMessengerSupported$\n : of(config.facebookMessengerSupported$);\n\n return combineLatest([config.accountGroupId$, enableable$]).pipe(\n switchMap(([agid, enableable]) => {\n if (!enableable || !agid) {\n return of({ configuration: { facebookMessengerEnabled: false } });\n }\n return inboxApiService.getConfiguration({\n subjectParticipant: {\n participantType: GlobalParticipantType.GLOBAL_PARTICIPANT_TYPE_ACCOUNT_GROUP,\n internalParticipantId: agid,\n },\n });\n }),\n map((config): boolean => config.configuration.facebookMessengerEnabled),\n shareReplay({ refCount: true, bufferSize: 1 }),\n catchError(() => of(false)),\n );\n}\n\nfunction instagramMessagesEnabledFactory(config: ConversationConfig): Observable {\n const inboxApiService = inject(InboxApiService);\n const enableable$ = isObservable(config.instagramMessagesSupported$)\n ? config.instagramMessagesSupported$\n : of(config.instagramMessagesSupported$);\n\n // TODO(BREW-577): update this to use `instagramMessagesEnabled` once the\n // Configuration API is updated to include that\n return combineLatest([config.accountGroupId$, enableable$]).pipe(\n switchMap(([agid, enableable]) => {\n if (!enableable || !agid) {\n return of({ configuration: { facebookMessengerEnabled: false } });\n }\n return inboxApiService.getConfiguration({\n subjectParticipant: {\n participantType: GlobalParticipantType.GLOBAL_PARTICIPANT_TYPE_ACCOUNT_GROUP,\n internalParticipantId: agid,\n },\n });\n }),\n map((config): boolean => config.configuration.facebookMessengerEnabled),\n shareReplay({ refCount: true, bufferSize: 1 }),\n catchError(() => of(false)),\n );\n}\n\nfunction googleBusinessMessagesAvailableFactory(config: ConversationConfig): Observable {\n const inboxService = inject(InboxApiService);\n const environmentService = inject(EnvironmentService);\n const enableable$ = isObservable(config.googleBusinessMessagesSupported$)\n ? config.googleBusinessMessagesSupported$\n : of(config.googleBusinessMessagesSupported$);\n\n return combineLatest([config.accountGroupId$, enableable$]).pipe(\n switchMap(([agid, enableable]) => {\n if (!enableable || environmentService.getEnvironment() !== Environment.PROD || !agid) {\n return of({ configuration: { googleBusinessMessagesEnabled: false } });\n }\n return inboxService.getConfiguration({\n subjectParticipant: {\n participantType: GlobalParticipantType.GLOBAL_PARTICIPANT_TYPE_ACCOUNT_GROUP,\n internalParticipantId: agid,\n },\n });\n }),\n map((config): boolean => config.configuration.googleBusinessMessagesEnabled),\n shareReplay({ refCount: true, bufferSize: 1 }),\n catchError(() => of(false)),\n );\n}\n\nfunction abstractConversationChannelServiceFactory(): Map {\n const conversationGoogleService = inject(ConversationGoogleService);\n const conversationWebChatService = inject(ConversationWebchatService);\n const conversationFacebookService = inject(ConversationFacebookService);\n const conversationPlatformService = inject(ConversationPlatformService);\n let conversationSMSService: ConversationSMSService;\n\n const channelMap = new Map([\n [ConversationChannel.CONVERSATION_CHANNEL_GOOGLE_BUSINESS_COMMUNICATIONS, conversationGoogleService],\n [ConversationChannel.CONVERSATION_CHANNEL_WEB_CHAT, conversationWebChatService],\n [ConversationChannel.CONVERSATION_CHANNEL_FACEBOOK, conversationFacebookService],\n [ConversationChannel.CONVERSATION_CHANNEL_INTERNAL, conversationPlatformService],\n ]);\n\n try {\n conversationSMSService = inject(ConversationSMSService);\n channelMap.set(ConversationChannel.CONVERSATION_CHANNEL_SMS, conversationSMSService);\n } catch (e) {\n channelMap.set(ConversationChannel.CONVERSATION_CHANNEL_SMS, undefined);\n console.debug('ConversationSMSService could not be injected.', e);\n }\n\n return channelMap;\n}\n\nfunction groupIdFactory(config: ConversationConfig): Observable {\n return isObservable(config.groupId$) ? config.groupId$ : of(config.groupId$);\n}\n","import { InjectionToken, ModuleWithProviders, NgModule } from '@angular/core';\nimport { AiKnowledgeConfig, RouteCommand } from './interface/config.interface';\nimport { AiKnowledgeService } from './ai-knowledge.service';\nimport {\n ACCOUNT_GROUP_ID_TOKEN,\n AI_KNOWLEDGE_CONFIG_TOKEN,\n BUSINESS_PROFILE_URL_TOKEN,\n INBOX_SETTINGS_ROUTE_TOKEN,\n MANAGE_KNOWLEDGE_URL_TOKEN,\n MARKET_ID_TOKEN,\n PARTNER_ID_TOKEN,\n SHOW_BUSINESS_PROFILE_SOURCE_TOKEN,\n} from './tokens';\nimport { isObservable, Observable, of } from 'rxjs';\n\n@NgModule()\nexport class AiKnowledgeModule {\n static forRoot(c: { config: InjectionToken }): ModuleWithProviders {\n const result = {\n ngModule: AiKnowledgeModule,\n providers: [\n AiKnowledgeService,\n { provide: AI_KNOWLEDGE_CONFIG_TOKEN, useExisting: c.config },\n { provide: ACCOUNT_GROUP_ID_TOKEN, deps: [AI_KNOWLEDGE_CONFIG_TOKEN], useFactory: accountGroupIdFactory },\n { provide: MARKET_ID_TOKEN, deps: [AI_KNOWLEDGE_CONFIG_TOKEN], useFactory: marketIdFactory },\n { provide: PARTNER_ID_TOKEN, deps: [AI_KNOWLEDGE_CONFIG_TOKEN], useFactory: partnerIdFactory },\n {\n provide: MANAGE_KNOWLEDGE_URL_TOKEN,\n deps: [AI_KNOWLEDGE_CONFIG_TOKEN],\n useFactory: manageKnowledgeUrlFactory,\n },\n {\n provide: BUSINESS_PROFILE_URL_TOKEN,\n deps: [AI_KNOWLEDGE_CONFIG_TOKEN],\n useFactory: businessProfileUrlFactory,\n },\n {\n provide: SHOW_BUSINESS_PROFILE_SOURCE_TOKEN,\n deps: [AI_KNOWLEDGE_CONFIG_TOKEN],\n useFactory: showBusinessProfileSourceFactory,\n },\n {\n provide: INBOX_SETTINGS_ROUTE_TOKEN,\n deps: [AI_KNOWLEDGE_CONFIG_TOKEN],\n useFactory: inboxSettingsRouteFactory,\n },\n ],\n };\n return result;\n }\n}\n\nfunction accountGroupIdFactory(config: AiKnowledgeConfig): Observable {\n return isObservable(config.accountGroupId$) ? config.accountGroupId$ : of(config.accountGroupId$);\n}\n\nfunction marketIdFactory(config: AiKnowledgeConfig): Observable {\n return isObservable(config.marketId$) ? config.marketId$ : of(config.marketId$);\n}\n\nfunction partnerIdFactory(config: AiKnowledgeConfig): Observable {\n return isObservable(config.partnerId$) ? config.partnerId$ : of(config.partnerId$);\n}\n\nfunction manageKnowledgeUrlFactory(config: AiKnowledgeConfig): Observable {\n return isObservable(config.manageKnowledgeUrl$) ? config.manageKnowledgeUrl$ : of(config.manageKnowledgeUrl$);\n}\n\nfunction businessProfileUrlFactory(config: AiKnowledgeConfig): Observable {\n return isObservable(config.businessProfileUrl$) ? config.businessProfileUrl$ : of(config.businessProfileUrl$);\n}\n\nfunction showBusinessProfileSourceFactory(config: AiKnowledgeConfig): Observable {\n return isObservable(config.showBusinessProfileSource$)\n ? config.showBusinessProfileSource$\n : of(config.showBusinessProfileSource$);\n}\n\nfunction inboxSettingsRouteFactory(config: AiKnowledgeConfig): Observable {\n return isObservable(config.inboxSettingsRoute$) ? config.inboxSettingsRoute$ : of(config.inboxSettingsRoute$);\n}\n","import { CommonModule } from '@angular/common';\nimport { Component, inject, Inject } from '@angular/core';\nimport { MatButtonModule } from '@angular/material/button';\nimport { TranslateModule } from '@ngx-translate/core';\nimport { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';\nimport { GalaxyFormFieldModule } from '@vendasta/galaxy/form-field';\nimport { MatOptionModule } from '@angular/material/core';\nimport { AiKnowledgeService } from '../ai-knowledge.service';\nimport { AppsForKnowledgeSourceComponent } from '../apps-for-knowledge-source/apps-for-knowledge-source.component';\nimport { AiKnowledgeI18nModule } from '../assets/i18n/ai-knowledge-i18n.module';\n\nexport interface DeleteCustomKnowledgeData {\n knowledgeSourceId: string;\n}\n\n@Component({\n selector: 'ai-knowledge-delete-custom-knowledge-dialog',\n standalone: true,\n imports: [\n CommonModule,\n TranslateModule,\n AiKnowledgeI18nModule,\n MatButtonModule,\n MatDialogModule,\n GalaxyFormFieldModule,\n MatOptionModule,\n AppsForKnowledgeSourceComponent,\n ],\n providers: [AiKnowledgeService],\n templateUrl: './delete-custom-knowledge.component.html',\n})\nexport class DeleteCustomKnowledgeComponent {\n private readonly knowledgeService = inject(AiKnowledgeService);\n\n constructor(\n public dialogRef: MatDialogRef,\n @Inject(MAT_DIALOG_DATA) public data: DeleteCustomKnowledgeData,\n ) {}\n\n cancel(): void {\n this.dialogRef.close();\n }\n\n async delete(): Promise {\n await this.knowledgeService.deleteKnowledgeSource(this.data.knowledgeSourceId);\n this.dialogRef.close(true);\n }\n}\n","

{{ 'DELETE_KNOWLEDGE.TITLE' | translate }}

\n\n \n\n\n \n \n\n","import { CommonModule } from '@angular/common';\nimport { Component, inject, Input, OnInit, signal } from '@angular/core';\nimport { MatButtonModule } from '@angular/material/button';\nimport { TranslateModule, TranslateService } from '@ngx-translate/core';\nimport { KnowledgeSource, KnowledgeSourceConfigType } from '@vendasta/embeddings';\nimport { AiKnowledgeService } from '../ai-knowledge.service';\nimport { MatIconModule } from '@angular/material/icon';\nimport { ActivatedRoute, Router, RouterModule } from '@angular/router';\nimport { MatListModule } from '@angular/material/list';\nimport { KnowledgeEditorComponent } from '../knowledge-editor/knowledge-editor.component';\nimport { MatDialog, MatDialogConfig, MatDialogModule } from '@angular/material/dialog';\nimport { firstValueFrom, map } from 'rxjs';\nimport { DeleteCustomKnowledgeComponent } from '../delete-custom-knowledge/delete-custom-knowledge.component';\nimport { LearnMoreBusinessProfileComponent } from '../learn-more-business-profile/learn-more-business-profile.component';\nimport { MatCardModule } from '@angular/material/card';\nimport { GalaxyPageModule } from '@vendasta/galaxy/page';\nimport { KnowledgeListComponent } from '../knowledge-list/knowledge-list.component';\nimport { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';\nimport { SHOW_BUSINESS_PROFILE_SOURCE_TOKEN } from '../tokens';\nimport { AiKnowledgeI18nModule } from '../assets/i18n/ai-knowledge-i18n.module';\nimport { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';\nimport { OpenConfirmationModalService } from '@vendasta/galaxy/confirmation-modal';\n\n@Component({\n selector: 'ai-knowledge-knowledge-source-management',\n standalone: true,\n imports: [\n CommonModule,\n TranslateModule,\n AiKnowledgeI18nModule,\n GalaxyPageModule,\n MatButtonModule,\n MatIconModule,\n RouterModule,\n MatListModule,\n MatCardModule,\n KnowledgeEditorComponent,\n DeleteCustomKnowledgeComponent,\n LearnMoreBusinessProfileComponent,\n MatDialogModule,\n KnowledgeListComponent,\n ],\n providers: [AiKnowledgeService],\n templateUrl: './knowledge-source-management.component.html',\n styleUrls: ['./knowledge-source-management.component.scss'],\n})\nexport class KnowledgeSourceManagementComponent implements OnInit {\n @Input() previousPageTitle?: string;\n @Input() previousPageUrl?: string;\n DIALOG_WIDTH = '660px';\n private readonly dialog = inject(MatDialog);\n private readonly bpObserver = inject(BreakpointObserver);\n private readonly activeRoute = inject(ActivatedRoute);\n\n readonly knowledgeSources = signal([]);\n private readonly showBusinessProfileSource = toSignal(inject(SHOW_BUSINESS_PROFILE_SOURCE_TOKEN));\n private knowledgeService = inject(AiKnowledgeService);\n confirmationModal = inject(OpenConfirmationModalService);\n private readonly translateService = inject(TranslateService);\n router = inject(Router);\n\n readonly isLoading = signal(true);\n\n async ngOnInit(): Promise {\n await this.refreshSources();\n const editSourceParam = this.activeRoute.snapshot.queryParamMap.get('editSource');\n if (editSourceParam) {\n const [sourceId, option] = this.sourceIdAndOptionFromEditSourceParam(editSourceParam);\n const source = this.knowledgeSources().find((s) => s.id == sourceId);\n if (source) {\n await this.editKnowledgeSource(source, option);\n }\n }\n if (this.activeRoute.snapshot.queryParamMap.get('addSource')) {\n await this.addNewKnowledgeSource();\n }\n }\n\n sourceIdAndOptionFromEditSourceParam(editSourceParam: string): [string, string] {\n const colonIndex = editSourceParam.indexOf(':');\n if (colonIndex === -1) {\n return [editSourceParam, ''];\n } else {\n return [editSourceParam.substring(0, colonIndex), editSourceParam.substring(colonIndex + 1)];\n }\n }\n\n async refreshSources(): Promise {\n this.isLoading.set(true);\n const result = await this.knowledgeService.listKnowledgeSources([\n KnowledgeSourceConfigType.KNOWLEDGE_SOURCE_CONFIG_TYPE_CUSTOM_DATA,\n KnowledgeSourceConfigType.KNOWLEDGE_SOURCE_CONFIG_TYPE_WEBSITE_SCRAPE,\n ]);\n const knowledgeSources = result.knowledgeSources || [];\n if (this.showBusinessProfileSource()) {\n // manually insert business profile source because it may not exist yet\n const businessProfileSource = this.knowledgeService.buildBusinessProfileKnowledgeSource();\n if (businessProfileSource) {\n knowledgeSources.unshift(businessProfileSource);\n }\n }\n this.knowledgeSources.set(knowledgeSources);\n this.isLoading.set(false);\n }\n\n async addNewKnowledgeSource(): Promise {\n const conf: MatDialogConfig = {\n width: this.DIALOG_WIDTH,\n };\n\n const isSmallScreen = this.bpObserver.isMatched(Breakpoints.XSmall);\n if (isSmallScreen) {\n conf.maxWidth = '100vw';\n conf.maxHeight = '100vh';\n }\n const result = await firstValueFrom(this.dialog.open(KnowledgeEditorComponent, conf).afterClosed());\n if (result) {\n this.openSuggestInboxSettingsModal();\n }\n await this.refreshSources();\n }\n\n openSuggestInboxSettingsModal() {\n this.confirmationModal\n .openModal({\n title: this.translateService.instant('INBOX_SETTINGS.PROMPT'),\n message: this.translateService.instant('INBOX_SETTINGS.DESCRIPTION'),\n confirmButtonText: this.translateService.instant('INBOX_SETTINGS.GO_TO'),\n cancelButtonText: this.translateService.instant('COMMON.CLOSE'),\n })\n .subscribe((userDidAction) => {\n if (userDidAction) {\n this.router.navigate(this.knowledgeService.buildInboxSettingsRoute());\n }\n });\n }\n\n async editKnowledgeSource(source: KnowledgeSource, option?: string): Promise {\n if (source?.config?.businessProfileConfig?.accountGroupId) {\n this.dialog.open(LearnMoreBusinessProfileComponent, {\n width: this.DIALOG_WIDTH,\n });\n return;\n }\n const conf: MatDialogConfig = {\n width: this.DIALOG_WIDTH,\n data: { knowledgeSourceKey: { knowledgeSourceId: source?.id, namespace: source?.namespace }, stepOption: option },\n };\n\n const isSmallScreen = this.bpObserver.isMatched(Breakpoints.XSmall);\n if (isSmallScreen) {\n conf.maxWidth = '100vw';\n conf.maxHeight = '100vh';\n }\n\n const editor = this.dialog.open(KnowledgeEditorComponent, conf);\n editor.componentInstance.stepChange\n .pipe(\n takeUntilDestroyed(editor.componentInstance.destroyRef),\n map((stepOption) => this.setEditSourceQueryParam(source?.id, stepOption)),\n )\n .subscribe();\n\n const result = await firstValueFrom(editor.afterClosed());\n this.setEditSourceQueryParam(null);\n if (result) {\n source = await this.knowledgeService.getKnowledgeSource(source?.id, source?.namespace, true);\n if (!source?.knowledgeBaseKeys || source?.knowledgeBaseKeys?.length === 0) {\n this.openSuggestInboxSettingsModal();\n }\n }\n await this.refreshSources();\n }\n\n async deleteKnowledgeSource(source: KnowledgeSource): Promise {\n const result = await firstValueFrom(\n this.dialog\n .open(DeleteCustomKnowledgeComponent, {\n width: this.DIALOG_WIDTH,\n data: { knowledgeSourceId: source.id },\n })\n .afterClosed(),\n );\n if (result) {\n await this.refreshSources();\n }\n }\n\n setEditSourceQueryParam(editSource: string | null, option?: string): void {\n if (option) {\n editSource = editSource + ':' + option;\n }\n const queryParams = { editSource: editSource };\n this.router.navigate([], {\n relativeTo: this.activeRoute,\n queryParams,\n queryParamsHandling: 'merge',\n });\n }\n}\n","\n \n \n \n \n {{ 'AI_KNOWLEDGE_BASE' | translate }}\n \n\n \n
\n \n \n {{ 'MANAGE_KNOWLEDGE' | translate }}\n \n \n
\n {{ 'MANAGE_KNOWLEDGE_DESCRIPTION' | translate }}\n \n \n\n
\n \n
\n
\n
\n
\n
\n
\n
\n","import { Component } from '@angular/core';\n\n@Component({\n selector: 'app-access-denied',\n templateUrl: './access-denied.component.html',\n styleUrls: ['./access-denied.component.scss'],\n})\nexport class AccessDeniedComponent {}\n","

{{ 'ACCESS_DENIED.ACCESS_DENIED' | translate }}

\n

{{ 'ACCESS_DENIED.ACCESS_DENIED_INFO' | translate }}

\n

{{ 'ACCESS_DENIED.GO_BACK' | translate }}

\n","import { Component, OnInit } from '@angular/core';\nimport { MatDialog } from '@angular/material/dialog';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { AccountGroupService, ProjectionFilter } from '@galaxy/account-group';\nimport { switchMap, take } from 'rxjs/operators';\nimport { DeleteAccountDialogComponent } from '../manage_accounts/dialogs/delete-account-dialog.component';\n\n@Component({\n template: '',\n})\nexport class AccountDeleteComponent implements OnInit {\n constructor(\n private readonly route: ActivatedRoute,\n private readonly router: Router,\n private accountGroupService: AccountGroupService,\n private readonly dialog: MatDialog,\n ) {}\n\n ngOnInit(): void {\n this.accountGroupService\n .get(this.route.snapshot.params.accountGroupId, new ProjectionFilter({ napData: true }))\n .pipe(\n switchMap((accountGroup) => {\n this.dialog.closeAll();\n const ref = this.dialog.open(DeleteAccountDialogComponent, { width: '620px', data: { accountGroup } });\n return ref.afterClosed();\n }),\n take(1),\n )\n .subscribe((deleted) => {\n if (deleted && this.shouldRedirectToManageAccounts()) {\n this.router.navigateByUrl('/manage-accounts');\n } else {\n this.router.navigate([{ outlets: { action: null } }]);\n }\n });\n }\n\n /**\n * Returns true if the url contains the final segment \"redirect\" false if it does not. This redirect segment indicates\n * that once the delete is complete, it should redirect to the manage accounts page.\n */\n private shouldRedirectToManageAccounts(): boolean {\n const segments = this.route.snapshot.url;\n return segments.length > 0 && segments[segments.length - 1].path === 'redirect';\n }\n}\n","import { ResellerItem } from '@vendasta/store';\nimport { AnalyticsItem, AnalyticsTransaction } from '../../../analytics/interface';\nimport { PurchaseCost } from '../../../core/billing/purchase-cost';\nimport { ActivationResult } from '../activate-app/interface';\n\nexport function filterMapByIds(selectedIds: string[], m: Map): Map {\n if (!selectedIds || selectedIds.length === 0 || !m || m.size === 0) {\n return new Map();\n }\n return selectedIds.reduce((currMap, id) => {\n const item = m.get(id);\n if (item) {\n currMap.set(id, item);\n }\n return currMap;\n }, new Map());\n}\n\nexport function convertResellerItemsAndPricingMapToAnalyticsItems(\n pricingMap: Map,\n resellerItemMap: Map,\n activatedItemMap: Map,\n): AnalyticsItem[] {\n return Array.from(activatedItemMap.keys()).reduce((acc, id) => {\n const quantity = activatedItemMap.get(id);\n if (quantity <= 0) {\n return acc;\n }\n const resellerItem = resellerItemMap.get(id);\n const pricing = resellerItem ? pricingMap.get(resellerItem.billingId) : null;\n const analyticsItem = buildAnalyticsItem(pricing, quantity, resellerItem);\n acc.push(analyticsItem);\n return acc;\n }, []);\n}\n\nexport function buildTransaction(\n transactionId: string,\n partnerId: string,\n marketId: string,\n analyticsItems: AnalyticsItem[],\n): AnalyticsTransaction {\n const totalRevenue = (analyticsItems || []).reduce((total, item) => {\n if (item.quantity > 0) {\n total = total + item.price * item.quantity;\n }\n return total;\n }, 0);\n return {\n transactionId: transactionId,\n revenue: totalRevenue,\n affiliation: `${partnerId},${marketId}`,\n } as AnalyticsTransaction;\n}\n\n/* generate random uuidv4 */\nexport function uuidv4(): string {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n // tslint:disable-next-line:no-bitwise\n const r = (Math.random() * 16) | 0,\n // tslint:disable-next-line:no-bitwise\n v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\nexport function convertActivationResultsToQuantityMap(activationResults: ActivationResult[]): Map {\n return (activationResults || []).reduce((m, curr) => {\n const currentCount = m.get(curr.appId) || 0;\n m.set(curr.appId, currentCount + 1);\n return m;\n }, new Map());\n}\n\nfunction buildAnalyticsItem(pricing: PurchaseCost, quantity: number, resellerItem: ResellerItem): AnalyticsItem {\n resellerItem = resellerItem || ({} as ResellerItem);\n if (!pricing) {\n if (resellerItem && resellerItem.isCustom) {\n pricing = new PurchaseCost();\n pricing.totalCost = resellerItem.price * quantity;\n pricing.currency = resellerItem.currency;\n } else {\n pricing = { totalCost: 0, currency: 'USD' } as PurchaseCost;\n }\n }\n return {\n name: resellerItem.name || 'NO NAME',\n id: resellerItem.billingId || 'NO SKU',\n category: (resellerItem.lmiCategories || []).reduce((s, cat) => (s ? `${s},${cat}` : `${cat}`), ''),\n price: pricing.totalCost ? pricing.totalCost / quantity : 0,\n currency: pricing.currency || 'USD',\n quantity: quantity,\n };\n}\n","import { Injectable } from '@angular/core';\nimport { ProductAnalyticsService } from '@vendasta/product-analytics';\nimport { ResellerItem } from '@vendasta/store';\nimport { combineLatest, Observable } from 'rxjs';\nimport { first, map } from 'rxjs/operators';\nimport { AnalyticsService } from '../../../analytics';\nimport { PurchaseCost } from '../../../core/billing/purchase-cost';\nimport { resellerArrayToMap } from '../../../core/reseller';\nimport { ResellerItemService } from '../../../core/reseller/reseller-item.service';\nimport { ActivationResult } from '../activate-app/interface';\nimport { ActivationParamService } from '../activation-param.service';\nimport { ActivationPricingService } from '../activation-pricing.service';\nimport {\n buildTransaction,\n convertActivationResultsToQuantityMap,\n convertResellerItemsAndPricingMapToAnalyticsItems,\n filterMapByIds,\n uuidv4,\n} from './utils';\n\n@Injectable()\nexport class ActivationAnalyticsService {\n // this is a map of sku to purchase cost\n private purchaseCostMap$: Observable>;\n private resellerItemMap$: Observable>;\n private resellerItems$: Observable;\n private partnerId$: Observable;\n private marketId$: Observable;\n\n constructor(\n private resellerItemService: ResellerItemService,\n private activationPricingService: ActivationPricingService,\n private analyticsService: AnalyticsService,\n private activationParamService: ActivationParamService,\n private productAnalytics: ProductAnalyticsService,\n ) {\n this.resellerItems$ = this.resellerItemService.getActivatablePartnerData();\n this.resellerItemMap$ = this.resellerItems$.pipe(map((ris) => resellerArrayToMap(ris)));\n this.partnerId$ = this.activationParamService.partnerId$;\n this.marketId$ = this.activationParamService.marketId$;\n }\n\n trackActivationTransactions(activationResults: ActivationResult[]): Observable {\n const randomTransactionId$ = combineLatest([this.partnerId$, this.marketId$]).pipe(\n map(([partnerId, marketId]) => {\n const uniqueTransactionId = uuidv4();\n return `${partnerId}-${marketId}-${uniqueTransactionId}`;\n }),\n );\n const analyticsItems = combineLatest([this.purchaseCostMap$, this.resellerItemMap$]).pipe(\n first(),\n map(([purchaseCostMap, resellerItemMap]) => {\n const activatedItemIds = activationResults.map((r) => r.appId);\n const activatedResellerMap = filterMapByIds(activatedItemIds, resellerItemMap);\n const activatedItemMap = convertActivationResultsToQuantityMap(activationResults);\n return convertResellerItemsAndPricingMapToAnalyticsItems(\n purchaseCostMap,\n activatedResellerMap,\n activatedItemMap,\n );\n }),\n );\n\n const transaction = combineLatest([this.partnerId$, this.marketId$, analyticsItems, randomTransactionId$]).pipe(\n first(),\n map(([partnerId, marketId, analyticsItemsInput, transactionId]) => {\n return buildTransaction(transactionId, partnerId, marketId, analyticsItemsInput);\n }),\n );\n\n return combineLatest([transaction, analyticsItems]).pipe(\n first(),\n map(([analyticsTransaction, analyticsItemsInput]) => {\n this.analyticsService.trackEcommerceTransaction(analyticsTransaction, analyticsItemsInput);\n }),\n );\n }\n}\n","import { NgModule } from '@angular/core';\nimport {\n ActivationPricingServiceInterfaceToken,\n ActivationServiceInterfaceToken,\n} from '../../common/app-selection/paginated-app-activation-table/tokens';\nimport { VbcHostService } from '../../vbc/vbc.host.service';\nimport { getHostName } from '../activation.module';\nimport { ActivateAppApiService } from '../core/activate-app/activate-app-api.service';\nimport { ActivateAppService } from '../core/activate-app/activate-app.service';\nimport { ActivationParamService } from '../core/activation-param.service';\nimport { ActivationPricingService } from '../core/activation-pricing.service';\nimport { ActivationService } from '../core/activation.service';\nimport { ActivationAnalyticsService } from '../core/analytics/activation-analytics.service';\nimport { VBC_HOST } from '../core/injection-tokens';\n\n@NgModule({\n imports: [],\n exports: [],\n providers: [\n ActivationService,\n { provide: ActivationServiceInterfaceToken, useExisting: ActivationService },\n ActivateAppService,\n ActivationPricingService,\n { provide: ActivationPricingServiceInterfaceToken, useExisting: ActivationPricingService },\n ActivationParamService,\n { provide: VBC_HOST, deps: [VbcHostService], useFactory: getHostName },\n ActivateAppApiService,\n ActivationAnalyticsService,\n VbcHostService,\n ],\n})\nexport class SharedActivationModule {}\n","import { Component, OnInit } from '@angular/core';\nimport { MatDialog, MatDialogRef } from '@angular/material/dialog';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { AccountGroup, AccountGroupService, ProjectionFilter } from '@galaxy/account-group';\nimport { take } from 'rxjs/operators';\nimport { ActionListsApiService, ActionListsStoreService } from '../action-lists';\nimport { CreateListDialog } from '../action-lists/actions';\nimport { AddToListDialogComponent } from '../manage_accounts/dialogs/add-to-list-dialog.component';\n\n@Component({\n template: '',\n})\nexport class AccountAddToListComponent implements OnInit {\n constructor(\n public dialogRef: MatDialogRef,\n private readonly route: ActivatedRoute,\n private readonly router: Router,\n private accountGroupService: AccountGroupService,\n private readonly dialog: MatDialog,\n private actionListsApiService: ActionListsApiService,\n private actionListsStoreService: ActionListsStoreService,\n ) {}\n\n ngOnInit(): void {\n this.actionListsStoreService.initializeStore(1000);\n this.accountGroupService\n .get(this.route.snapshot.params.accountGroupId, new ProjectionFilter({ napData: true }))\n .pipe(take(1))\n .subscribe((accountGroup) => {\n this.openAddToListDialog(accountGroup);\n });\n }\n\n private showCreateListDialogAndAddAccount(accountGroup: AccountGroup): void {\n this.dialog.closeAll();\n const createDialog = this.dialog.open(CreateListDialog, {\n width: '620px',\n });\n createDialog\n .afterClosed()\n .pipe(take(1))\n .subscribe((listName) => {\n if (listName) {\n this.actionListsApiService.createActionList(listName).subscribe(() => {\n this.actionListsApiService.addAccountToActionList(listName, accountGroup.accountGroupId);\n });\n }\n this.router.navigate([{ outlets: { action: null } }]);\n });\n }\n\n private openAddToListDialog(accountGroup: AccountGroup): void {\n this.dialog.closeAll();\n const addToListDialogRef = this.dialog.open(AddToListDialogComponent, {\n width: '620px',\n });\n addToListDialogRef.componentInstance.accountGroup = accountGroup;\n addToListDialogRef\n .afterClosed()\n .pipe(take(1))\n .subscribe((result) => {\n if (result === false) {\n this.showCreateListDialogAndAddAccount(accountGroup);\n } else {\n this.router.navigate([{ outlets: { action: null } }]);\n }\n });\n }\n}\n","import { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatCheckboxModule } from '@angular/material/checkbox';\nimport { MatDialogModule } from '@angular/material/dialog';\nimport { MatProgressSpinnerModule } from '@angular/material/progress-spinner';\nimport { MatRadioModule } from '@angular/material/radio';\nimport { TranslateModule } from '@ngx-translate/core';\nimport { ChangePlanDialogComponent } from './change-plan-dialog.component';\nimport { ChangePlanService } from './change-plan-service';\n\n@NgModule({\n imports: [\n CommonModule,\n MatRadioModule,\n MatDialogModule,\n MatCheckboxModule,\n MatButtonModule,\n FormsModule,\n MatProgressSpinnerModule,\n TranslateModule,\n ],\n declarations: [ChangePlanDialogComponent],\n providers: [ChangePlanService],\n})\nexport class ChangePlanDialogModule {}\n","import { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\nimport { FormsModule, ReactiveFormsModule } from '@angular/forms';\nimport { MatAutocompleteModule } from '@angular/material/autocomplete';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatButtonToggleModule } from '@angular/material/button-toggle';\nimport { MatCardModule } from '@angular/material/card';\nimport { MatCheckboxModule } from '@angular/material/checkbox';\nimport { MatChipsModule } from '@angular/material/chips';\nimport { MatDialogModule } from '@angular/material/dialog';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatInputModule } from '@angular/material/input';\nimport { MatListModule } from '@angular/material/list';\nimport { MatMenuModule } from '@angular/material/menu';\nimport { MatProgressBarModule } from '@angular/material/progress-bar';\nimport { MatProgressSpinnerModule } from '@angular/material/progress-spinner';\nimport { MatRadioModule } from '@angular/material/radio';\nimport { MatSelectModule } from '@angular/material/select';\nimport { MatTabsModule } from '@angular/material/tabs';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { RouterModule } from '@angular/router';\nimport { TranslateModule } from '@ngx-translate/core';\nimport { AccountsService } from '@vendasta/accounts/legacy';\nimport { BillingUiModule } from '@vendasta/billing-ui';\nimport { VaFormsModule } from '@vendasta/forms';\nimport { GalaxyAlertModule } from '@vendasta/galaxy/alert';\nimport { GalaxyButtonLoadingIndicatorModule } from '@vendasta/galaxy/button-loading-indicator';\nimport { GalaxyFormFieldModule } from '@vendasta/galaxy/form-field';\nimport { GalaxyInputModule } from '@vendasta/galaxy/input';\nimport { GalaxyPipesModule } from '@vendasta/galaxy/pipes';\nimport { StencilsModule } from '@vendasta/store';\nimport { IconComponent, VaListModule, VaStatusBannerModule } from '@vendasta/uikit';\nimport { ActivationSettingsApiService } from '../activation/activation-settings-api.service';\nimport { ProductOrderFormStoreService } from '../activation/core/product-order-form.store.service';\nimport { SharedActivationModule } from '../activation/shared/shared-activation.module';\nimport { UnifiedTOSService } from '../core/tos-unified.service';\nimport { CampaignService } from '../marketing/campaign.service';\nimport { UserService, UsersModule } from '../users';\nimport { AccountAddToListComponent } from './account-add-to-list.component';\nimport { AccountDeleteComponent } from './account-delete.component';\nimport { AccountSelectorDialogComponent } from './account-selector-dialog/account-selector-dialog.component';\nimport { ActiveCampaignChangeEditionDialogComponent } from './active-campaign-change-edition-dialog/ac-change-edition-dialog.component';\nimport { CampaignDialogItemStoreService } from './campaign-dialog-item-store.service';\nimport { CampaignDialogItemComponent } from './campaign-dialog-item.component';\nimport { CampaignDialogStoreService } from './campaign-dialog-store.service';\nimport { CampaignsDialogComponent } from './campaigns-dialog.component';\nimport { ChangeEditionDialogComponent } from './change-edition-dialog.component';\nimport { ChangeEditionDialogService } from './change-edition-dialog.service';\nimport { ChangePlanDialogModule } from './change-plan-dialog';\nimport { ChangePlanService } from './change-plan-dialog/change-plan-service';\nimport { DeactivateDependentProductDialogComponent } from './deactivate-dependent-product-dialog/deactivate-dependent-product-dialog.component';\nimport { DeactivateDialogComponent } from './deactivate-dialog/deactivate-dialog.component';\nimport { DeactivateImmediatelyDialogComponent } from './deactivate-immediately-dialog.component';\nimport { OrderFormSubmissionDialogComponent } from './order-form-submission-dialog.component';\nimport { RequestSpendChangeDialogComponent } from './request-spend-change-dialog/request-spend-change-dialog.component';\n\n@NgModule({\n imports: [\n CommonModule,\n FormsModule,\n VaListModule,\n ReactiveFormsModule,\n MatProgressSpinnerModule,\n MatButtonModule,\n MatCardModule,\n MatIconModule,\n MatIconModule,\n VaFormsModule,\n MatMenuModule,\n MatSelectModule,\n MatDialogModule,\n MatFormFieldModule,\n MatInputModule,\n MatCheckboxModule,\n MatListModule,\n MatTooltipModule,\n MatChipsModule,\n MatProgressBarModule,\n MatButtonToggleModule,\n MatTabsModule,\n StencilsModule,\n ChangePlanDialogModule,\n MatRadioModule,\n TranslateModule,\n SharedActivationModule,\n MatAutocompleteModule,\n VaStatusBannerModule,\n GalaxyAlertModule,\n GalaxyFormFieldModule,\n GalaxyPipesModule,\n RouterModule,\n GalaxyInputModule,\n UsersModule,\n GalaxyButtonLoadingIndicatorModule,\n BillingUiModule,\n IconComponent,\n ],\n exports: [],\n declarations: [\n CampaignsDialogComponent,\n OrderFormSubmissionDialogComponent,\n DeactivateDialogComponent,\n DeactivateDependentProductDialogComponent,\n DeactivateImmediatelyDialogComponent,\n RequestSpendChangeDialogComponent,\n CampaignDialogItemComponent,\n ChangeEditionDialogComponent,\n ActiveCampaignChangeEditionDialogComponent,\n AccountDeleteComponent,\n AccountAddToListComponent,\n AccountSelectorDialogComponent,\n ],\n providers: [\n { provide: 'AccountsServiceInterface', useExisting: AccountsService },\n UserService,\n CampaignService,\n UnifiedTOSService,\n ChangePlanService,\n CampaignDialogStoreService,\n CampaignDialogItemStoreService,\n ChangeEditionDialogService,\n AccountsService,\n ProductOrderFormStoreService,\n ActivationSettingsApiService,\n ],\n})\nexport class AccountsModule {}\n","import { MenuItem } from './common/fec/fec-menu/menu-item';\nimport { Feature } from './core/access';\n\nconst popUpMapping = new Map([\n ['open-ssc', Feature.salesAndSuccessCenterAccess],\n ['open-meetings', Feature.salesAndSuccessCenterAccess],\n ['open-task-manager', Feature.concierge],\n]);\n\nexport function popUpShouldRedirectToCTA(item: MenuItem): boolean {\n return item.locked && popUpMapping.has(item.menuId);\n}\n\nfunction getFeatureForPopUp(key: string): Feature {\n return popUpMapping.get(key);\n}\n\nexport function getCallToActionUrl(item: MenuItem): string {\n const feature = getFeatureForPopUp(item.menuId);\n return `/restricted/${feature}`;\n}\n","import { ConnectedPosition } from '@angular/cdk/overlay';\nimport { Component, EventEmitter, Inject, inject, Input, OnInit, Output } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { PopoverPositions } from '@vendasta/galaxy/popover';\nimport { Observable } from 'rxjs';\nimport { AppConfigService } from './app-config.service';\nimport { MenuItem } from './common/fec/fec-menu/menu-item';\nimport { getCallToActionUrl, popUpShouldRedirectToCTA } from './pop-up-cta-check';\n\nenum NavLinkType {\n NAVLINK = 0,\n SUBNAV = 1,\n DISABLED = 2,\n LOCKED = 3,\n POPOUT = 4,\n BETA = 5,\n NEW = 6,\n}\n\n@Component({\n selector: 'app-nav-item',\n templateUrl: './app-nav-item.component.html',\n styleUrls: ['./app-nav-item.component.scss'],\n})\nexport class AppNavItemComponent implements OnInit {\n @Input() activeMenuId: string;\n @Input() item: MenuItem;\n @Output() clicked: EventEmitter = new EventEmitter();\n\n private readonly router = inject(Router);\n private readonly configService = inject(AppConfigService);\n\n public shouldExpandMenu = false;\n hasDirectLink: boolean;\n linkIsHandledInComponent: boolean;\n clickWillRedirectToCTA = false;\n\n readonly navLinkTypes = NavLinkType;\n navType: NavLinkType = NavLinkType.NAVLINK;\n\n readonly positions: ConnectedPosition[] = [{ ...PopoverPositions.Right }, { ...PopoverPositions.Bottom }];\n tooltip = `NAV_ITEMS.DEFAULT_DISABLED_TOOLTIP`;\n\n constructor(@Inject('PARTNER_ID') readonly partnerId$: Observable) {}\n\n ngOnInit(): void {\n if (this.item.nestedItems) {\n const activeItems = this.item.nestedItems.filter((item) => this.activeMenuId.startsWith(item.menuId));\n this.shouldExpandMenu = activeItems.length > 0;\n }\n this.clickWillRedirectToCTA = popUpShouldRedirectToCTA(this.item);\n this.hasDirectLink = this.item.url && !this.item.ngRoute && !this.clickWillRedirectToCTA;\n this.linkIsHandledInComponent = (this.item.url && this.item.ngRoute) || this.clickWillRedirectToCTA;\n this.navType = this.getNavType();\n }\n\n onClick($event: Event): void {\n if (this.navType === NavLinkType.DISABLED) {\n $event.preventDefault();\n return;\n }\n\n this.clicked.emit($event);\n }\n\n navTabClicked($event: Event, item: MenuItem): void {\n if (this.navType === NavLinkType.DISABLED) {\n $event.preventDefault();\n return;\n }\n\n if (!item.popOut) {\n this.router.navigate([item.url]);\n }\n\n if (this.clickWillRedirectToCTA) {\n if (this.navType === NavLinkType.LOCKED) {\n $event.preventDefault();\n }\n this.handleLockedPopUpClick(item);\n }\n }\n\n private handleLockedPopUpClick(item: MenuItem): void {\n const ctaUrl = getCallToActionUrl(item);\n this.router.navigate([ctaUrl], { queryParams: { page: item.menuId } });\n }\n\n private getNavType(): NavLinkType {\n if (this.item.menuId === 'open-ssc' || this.item.menuId === 'open-meetings') {\n if (this.configService.config.isSuperAdmin) {\n this.tooltip = `NAV_ITEMS.SALES.SALES_POPOUTS_DISABLED_TOOLTIP`;\n return NavLinkType.DISABLED;\n }\n }\n\n if (this.item.locked) {\n return NavLinkType.LOCKED;\n }\n\n if (this.item.popOut) {\n return NavLinkType.POPOUT;\n }\n\n if (this.item.rightIcon) {\n return NavLinkType.SUBNAV;\n }\n\n if (this.item.badge === 'NAVIGATION_ITEM_BADGE_NEW') {\n return NavLinkType.NEW;\n }\n\n if (this.item.badge === 'NAVIGATION_ITEM_BADGE_BETA') {\n return NavLinkType.BETA;\n }\n }\n}\n","\n \n \n {{ item.label | translate }}\n \n \n \n\n \n \n {{ item.subsectionHeader | translate }}\n \n \n\n \n \n {{ item.label | translate }}\n \n \n \n\n \n \n {{ item.label | translate }}\n \n \n \n\n\n 0\">\n \n {{ item.label | translate }}\n \n \n \n \n\n\n\n\n \n error_outline\n \n arrow_circle_up\n open_in_new\n chevron_right\n \n {{ 'COMMON.BETA' | translate }}\n \n \n {{ 'COMMON.NEW' | translate }}\n \n\n","import { Params } from '@angular/router';\nimport { EmailEventService, EventType, SenderType } from '@vendasta/email';\nimport { EmailEvent } from '@vendasta/email/lib/_internal/objects/email-event';\nimport { PagedListRequestInterface, PagedResponseInterface, PaginatedAPIInterface } from '@vendasta/galaxy/table';\nimport { Observable, combineLatest } from 'rxjs';\nimport { catchError, map, switchMap } from 'rxjs/operators';\n\ninterface ParameterServiceInterface {\n partnerId$: Observable;\n url: Params;\n}\n\nexport class ParameterService implements ParameterServiceInterface {\n readonly partnerId$: Observable;\n readonly url: Params;\n\n constructor(partnerID$: Observable, url: Params) {\n this.partnerId$ = partnerID$;\n this.url = url;\n }\n}\n\nexport class ActivityTableDataService implements PaginatedAPIInterface {\n constructor(\n private parameterService: ParameterServiceInterface,\n private emailEventService: EmailEventService,\n private filters$: Observable,\n ) {}\n\n get(r: PagedListRequestInterface): Observable> {\n return combineLatest([this.parameterService.partnerId$, this.filters$]).pipe(\n switchMap(([pid, filters]) => {\n return this.emailEventService\n .listEventsForAttribute(\n {\n type: SenderType.SENDER_TYPE_PARTNER,\n id: pid,\n },\n {\n key: this.parameterService.url.attributeKey,\n value: this.parameterService.url.attributeValue,\n },\n filters,\n r.pagingOptions.cursor,\n r.pagingOptions.pageSize,\n )\n .pipe(\n map((r) => {\n return {\n data: r.events,\n pagingMetadata: {\n nextCursor: r?.cursor,\n hasMore: r?.hasMore,\n },\n };\n }),\n );\n }),\n catchError(() => []),\n );\n }\n}\n","import { Component, Inject, OnInit, OnDestroy } from '@angular/core';\nimport { Observable, Subscription } from 'rxjs';\nimport { EmailEventService, EventType } from '@vendasta/email';\nimport { ActivatedRoute } from '@angular/router';\nimport { GalaxyDataSource, GalaxyTableModule } from '@vendasta/galaxy/table';\nimport { EmailEvent } from '@vendasta/email/lib/_internal/objects/email-event';\nimport { GalaxyColumnDef } from '@vendasta/galaxy/table/src/table.interface';\nimport { TranslateModule, TranslateService } from '@ngx-translate/core';\nimport { DateFormat } from '@vendasta/galaxy/utility/date-utils';\nimport { ActivityTableDataService, ParameterService } from './activity-table.service';\nimport { CheckboxFilterControl, FilterGroup, FilterModule, SidebarState } from '@vendasta/va-filter2';\nimport { CommonModule } from '@angular/common';\nimport { GalaxyPageModule } from '@vendasta/galaxy/page';\nimport { GalaxyEmptyStateModule } from '@vendasta/galaxy/empty-state';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatTableModule } from '@angular/material/table';\nimport { GalaxyPipesModule } from '@vendasta/galaxy/pipes';\nimport { shareReplay, startWith, map } from 'rxjs/operators';\nimport { SENDER_ID_TOKEN } from '../../../email-activity/src/dependencies';\n\n@Component({\n standalone: true,\n imports: [\n CommonModule,\n TranslateModule,\n GalaxyPageModule,\n GalaxyTableModule,\n GalaxyEmptyStateModule,\n FilterModule,\n MatIconModule,\n MatTableModule,\n GalaxyPipesModule,\n ],\n providers: [EmailEventService],\n templateUrl: './activity-table.component.html',\n styles: [\n `\n :host {\n display: block;\n }\n `,\n ],\n})\nexport class ActivityTableComponent implements OnInit, OnDestroy {\n dataSource: GalaxyDataSource;\n readonly columns: GalaxyColumnDef[] = [\n {\n id: 'eventType',\n title: this.translateService.instant('EMAIL_ACTIVITY.EVENT_TYPE'),\n },\n {\n id: 'eventTime',\n title: this.translateService.instant('EMAIL_ACTIVITY.EVENT_TIME'),\n },\n ];\n readonly dateFormat = DateFormat.medium;\n readonly sidebarState = SidebarState.OPEN;\n filterGroup: FilterGroup;\n filters$: Observable;\n private subscriptions: Subscription[] = [];\n\n constructor(\n private readonly translateService: TranslateService,\n @Inject(SENDER_ID_TOKEN) readonly senderId$: Observable,\n private emailEventService: EmailEventService,\n private route: ActivatedRoute,\n ) {}\n\n ngOnInit(): void {\n this.filterGroup = new FilterGroup('').addSection(\n 'Event type',\n this.getEventTypeList().map((eventType) => {\n return new CheckboxFilterControl(eventType, eventType, false, {\n appliedValueMapper: (name: string) => ({ name, label: name }),\n });\n }),\n );\n this.subscriptions.push(\n this.route.queryParams.subscribe((params) => {\n this.filterGroup.initValue({\n [params.eventType]: true,\n });\n }),\n );\n\n this.filters$ = this.filterGroup.valueChanges.pipe(\n startWith(this.filterGroup.value),\n map((group) => {\n const filterTypes = [];\n if (group.Processed) {\n filterTypes.push(EventType.PROCESSED);\n }\n if (group.Delivered) {\n filterTypes.push(EventType.DELIVERED);\n }\n if (group.Opened) {\n filterTypes.push(EventType.OPENED);\n }\n if (group.Clicked) {\n filterTypes.push(EventType.CLICKED);\n }\n if (group.Bounced) {\n filterTypes.push(EventType.BOUNCED);\n }\n if (group.Deferred) {\n filterTypes.push(EventType.DEFERRED);\n }\n if (group.Dropped) {\n filterTypes.push(EventType.DROPPED);\n }\n if (group.Spamreport) {\n filterTypes.push(EventType.SPAMREPORT);\n }\n if (group.Unsubscribed) {\n filterTypes.push(EventType.UNSUBSCRIBED);\n }\n if (group.Resubscribed) {\n filterTypes.push(EventType.RESUBSCRIBED);\n }\n return filterTypes;\n }),\n shareReplay(1),\n );\n const paramsService = new ParameterService(this.senderId$, this.route.snapshot.params);\n const service = new ActivityTableDataService(paramsService, this.emailEventService, this.filters$);\n this.dataSource = new GalaxyDataSource(service);\n }\n\n getEventTypeList(): string[] {\n return Object.keys(EventType)\n .reduce((arr, key) => {\n if (!arr.includes(key)) {\n arr.push(EventType[key]);\n }\n return arr;\n }, [])\n .map((eventType) => eventType.charAt(0) + eventType.slice(1).toLowerCase());\n }\n\n getDisplayTypeFromEnum(value: EventType): string {\n switch (value) {\n case EventType.PROCESSED:\n return 'Processed';\n case EventType.DELIVERED:\n return 'Delivered';\n case EventType.OPENED:\n return 'Opened';\n case EventType.CLICKED:\n return 'Clicked';\n case EventType.BOUNCED:\n return 'Bounced';\n case EventType.DEFERRED:\n return 'Deferred';\n case EventType.DROPPED:\n return 'Dropped';\n case EventType.SPAMREPORT:\n return 'Spamreport';\n case EventType.UNSUBSCRIBED:\n return 'Unsubscribed';\n case EventType.RESUBSCRIBED:\n return 'Resubscribed';\n }\n }\n\n ngOnDestroy(): void {\n this.subscriptions.forEach((s) => s.unsubscribe());\n }\n}\n","\n \n {{ 'EMAIL_ACTIVITY.TITLE' | translate }}\n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n\n \n
{{ 'EMAIL_ACTIVITY.EVENT_TYPE' | translate }}\n {{ getDisplayTypeFromEnum(element.eventType) }}\n {{ 'EMAIL_ACTIVITY.EVENT_TIME' | translate }}\n {{ element.eventTime | glxyDate : dateFormat }}\n
\n \n \n done_all\n \n

{{ 'EMAIL_ACTIVITY.NO_EVENTS' | translate }}

\n
\n
\n \n \n
\n","import { Component } from '@angular/core';\n\n@Component({\n template: `\n

Preview Welcome Email

\n
\n The text between the braces {{ '{}' }} is dynamic. The braces and text will be replaced with information related\n to your company and the email recipient.\n
\n \n \n \n \n \n \n `,\n styleUrls: ['../../common/dialog.component.scss', './preview-welcome-email-dialog.component.scss'],\n})\nexport class PreviewWelcomeEmailComponent {}\n","import { Component, Inject } from '@angular/core';\nimport { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';\n\n@Component({\n templateUrl: 'map-change-dialog.component.html',\n styleUrls: ['map-change-dialog.component.scss'],\n})\nexport class MapChangeDialogComponent {\n constructor(\n public dialog: MatDialogRef,\n @Inject(MAT_DIALOG_DATA) public data: MapDialogData,\n ) {}\n\n cancel(): void {\n this.dialog.close(false);\n }\n}\n\nexport interface MapDialogData {\n fieldName: string;\n headerRow?: string;\n}\n","\n\n

\n \n \n

\n
\n\n \n \n\n","import { Component, Inject, Input, OnInit, ViewEncapsulation } from '@angular/core';\nimport { UntypedFormControl } from '@angular/forms';\nimport { MatDialog } from '@angular/material/dialog';\n// eslint-disable-next-line @nx/enforce-module-boundaries\nimport { FieldSchema } from '@vendasta/auxiliary-data-components';\nimport { Observable } from 'rxjs';\nimport { debounceTime, filter, map, shareReplay, switchMap, take, tap, withLatestFrom } from 'rxjs/operators';\nimport { FieldSelectedForEditService as CustomFieldEditorNotificationsService } from '../auxiliary-data/columns/field-selected-for-edit.service';\nimport { BulkImportMappingService, fieldType } from './bulk-import-mapping.service';\nimport { doNotImportOptionId, FieldMappingOption, fieldOptions } from './header-mapping.options';\nimport { MapChangeDialogComponent } from './map-change-dialog.component';\n\n@Component({\n selector: 'app-bulk-import-mapper-row',\n templateUrl: 'bulk-import-mapping-row.component.html',\n styleUrls: ['./bulk-import-mapping-row.component.scss'],\n encapsulation: ViewEncapsulation.None,\n})\nexport class BulkImportMappingRowComponent implements OnInit {\n @Input() headerRow: string;\n options = fieldOptions;\n\n oldSelectionId: string = null;\n doNotImportOptionId = doNotImportOptionId;\n searchOptionsControl = new UntypedFormControl();\n filteredOptions$: Observable;\n filteredCustomFieldOptions$: Observable;\n readonly createCustomFieldOption = new CreateCustomField();\n\n constructor(\n @Inject('PARTNER_ID') readonly partnerId$: Observable,\n private mappingService: BulkImportMappingService,\n public dialog: MatDialog,\n private readonly customFieldEditorNotificationsService: CustomFieldEditorNotificationsService,\n ) {}\n\n private get selectedKey(): string {\n return this.searchOptionsControl.value ? this.searchOptionsControl.value.id : null;\n }\n\n setDoNotImport(): void {\n const oldColumn = this.mappingService.columnThatsMappedToField(this.oldSelectionId);\n this.mappingService.removeFromMap(oldColumn);\n this.setControlValue(doNotImportOptionId);\n }\n\n onSelectionChange(selection: FieldMappingOption | CreateCustomField): void {\n if ('createCustomField' in selection && selection.createCustomField) {\n this.customFieldEditorNotificationsService.createNewFieldClicked();\n this.customFieldEditorNotificationsService.fieldCreated$$\n .pipe(\n take(1),\n switchMap((newField: FieldSchema) => this.mappingService.getCustomFieldIdByName(newField.fieldName)),\n tap((newFieldId: string) => {\n this.updateMapping(newFieldId, 'custom');\n this.setControlValue(newFieldId);\n }),\n )\n .subscribe();\n return;\n }\n\n let ft: fieldType = 'standard';\n if ('isCustomFieldOption' in selection && selection.isCustomFieldOption) {\n ft = 'custom';\n }\n if (!('id' in selection)) {\n console.error('did not receive ID for field-mapping');\n return;\n }\n const fieldId: string = selection.id;\n const currentMappedHeader = this.mappingService.columnThatsMappedToField(fieldId);\n if (currentMappedHeader && currentMappedHeader !== this.headerRow) {\n this.openDialog(fieldId, currentMappedHeader, ft);\n } else {\n this.updateMapping(fieldId, ft);\n this.setControlValue(fieldId);\n }\n }\n\n nameDisplayFn(objectWithAName: { name: string }): string {\n return objectWithAName ? objectWithAName.name : undefined;\n }\n\n private setControlValue(fieldId: string): void {\n if (fieldId === doNotImportOptionId) {\n this.oldSelectionId = fieldId;\n } else if (fieldId !== this.oldSelectionId) {\n this.oldSelectionId = this.selectedKey ? this.selectedKey : fieldId;\n }\n const matchedStandardOptions: FieldMappingOption[] = this.options.filter((option) => option.id === fieldId);\n if (matchedStandardOptions.length > 0) {\n this.searchOptionsControl.setValue(matchedStandardOptions[0]);\n return;\n }\n\n this.mappingService.customFieldOptions$\n .pipe(\n take(1),\n tap((options: FieldMappingOption[]) => {\n const matched = options.filter((option) => option.id === fieldId);\n if (matched.length > 0) {\n this.searchOptionsControl.setValue(matched[0]);\n }\n }),\n )\n .subscribe();\n }\n\n ngOnInit(): void {\n const searchText$ = this.searchOptionsControl.valueChanges.pipe(\n debounceTime(100),\n filter((value) => value !== null && value !== undefined),\n map((value) => (typeof value === 'string' ? value : value.name)),\n );\n\n const staticOptions$ = searchText$.pipe(map((value) => this._filterOptions(value)));\n this.filteredOptions$ = staticOptions$;\n this.filteredCustomFieldOptions$ = searchText$.pipe(\n withLatestFrom(this.mappingService.customFieldOptions$),\n map(([searchText, customFieldOptions]) => {\n if (!searchText) {\n return customFieldOptions;\n }\n return customFieldOptions.filter((option) => this.optionMatchesSearch(option.name, searchText));\n }),\n shareReplay({ refCount: false, bufferSize: 1 }),\n );\n\n this.mappingService\n .autoMatch(this.headerRow)\n .pipe(\n take(1),\n tap((autoMatchedKey) => this.setControlValue(autoMatchedKey)),\n )\n .subscribe();\n }\n\n private optionMatchesSearch(option: string, search: string): boolean {\n return option.toLowerCase().includes(search.toLowerCase());\n }\n\n openDialog(newFieldChoice: string, currentMappedHeader: string, ft: fieldType): void {\n const dialogRef = this.dialog.open(MapChangeDialogComponent, {\n width: '400px',\n data: {\n headerRow: currentMappedHeader,\n fieldName: newFieldChoice,\n },\n });\n\n dialogRef.afterClosed().subscribe((result) => {\n if (result) {\n this.updateMapping(newFieldChoice, ft);\n this.setControlValue(newFieldChoice);\n } else {\n this.setControlValue(this.oldSelectionId);\n }\n });\n }\n\n private updateMapping(newFieldChoice: string, ft: fieldType): void {\n this.mappingService.addToMap(this.headerRow, newFieldChoice, ft);\n }\n\n _filterOptions(value: string): FieldMappingOption[] {\n if (!value) {\n return this.options;\n }\n const filterValue = value.toLowerCase();\n return this.options.filter((option) => this.optionMatchesSearch(option.name, filterValue));\n }\n\n onFocusout(): void {\n if (!this.selectedKey) {\n this.setControlValue(this.oldSelectionId);\n }\n }\n}\n\nclass CreateCustomField {\n readonly createCustomField: boolean = true;\n}\n","
\n \n \n \n \n \n {{ option.name }}\n \n \n \n \n {{ option.name }}\n \n \n \n {{ 'USERS.BULK_IMPORT.IMPORT_MAPPER.CREATE_NEW_CUSTOM_FIELD' | translate }}\n \n \n \n \n \n \n clear\n \n
\n","import { Component, Input, OnInit } from '@angular/core';\nimport { async } from '@angular/core/testing';\nimport { MatStepper } from '@angular/material/stepper';\nimport { Observable, Subscription } from 'rxjs';\nimport { map } from 'rxjs/operators';\nimport { BulkImportService, ErrorRowInterface } from './bulk-import.service';\nimport { fieldOptions } from './header-mapping.options';\n\n@Component({\n selector: 'app-bulk-import-mapper',\n templateUrl: './bulk-import-mapper.component.html',\n styleUrls: ['./bulk-import-mapper.component.scss'],\n})\nexport class BulkImportMapperComponent implements OnInit {\n readonly displayedColumns = ['header-row', 'first-row', 'mapping'];\n readonly options = fieldOptions;\n @Input() pageStepper: MatStepper;\n\n subscriptions: Subscription[] = [];\n show = 10;\n proceedWithErrors = false;\n uploading$: Observable;\n dataSource: any;\n errorMessage$: any;\n errors$: Observable;\n\n constructor(private bulkImportService: BulkImportService) {}\n ngOnInit(): void {\n this.uploading$ = this.bulkImportService.uploading$;\n this.dataSource = this.bulkImportService.dataSource;\n this.errorMessage$ = this.bulkImportService.errorMessage$$.asObservable();\n this.errors$ = this.bulkImportService.errors$.pipe(\n map((errors) => {\n return errors.map((err) => {\n if (!this.isString(err.column)) {\n err.column = err.column.length > 1 ? err.column[0] + ' - ' + err.column[err.column.length - 1] : err.column;\n }\n return err;\n });\n }),\n );\n }\n\n uploadFileAndMapping(): void {\n this.bulkImportService.uploadFileAndMapping(this.pageStepper, this.proceedWithErrors);\n }\n increaseShow(): void {\n this.show += 10;\n }\n isString(val: any): boolean {\n return typeof val === 'string';\n }\n\n protected readonly async = async;\n}\n","\n \n \n \n {{ 'USERS.BULK_IMPORT.IMPORT_MAPPER.COLUMNS' | translate }}\n \n \n \n {{ 'USERS.BULK_IMPORT.IMPORT_MAPPER.COLUMNS' | translate }}\n \n {{ col.headerRow }}\n \n \n \n \n {{ 'USERS.BULK_IMPORT.IMPORT_MAPPER.FIRST_ROW' | translate }}\n \n \n \n {{ 'USERS.BULK_IMPORT.IMPORT_MAPPER.FIRST_ROW' | translate }}\n \n {{ col.firstRow }}\n \n \n \n \n {{ 'USERS.BULK_IMPORT.IMPORT_MAPPER.MAP_TO' | translate }}\n \n \n \n \n \n \n \n \n\n\n\n
\n \n {{ 'USERS.BULK_IMPORT.IMPORT_MAPPER.ERRORS_ON_FOLLOWING_ROWS' | translate }}\n \n
\n \n \n {{ 'USERS.BULK_IMPORT.IMPORT_MAPPER.ROW_NUMBER' | translate: { rowNumber: error.row } }}\n ({{ error.column }}) {{ error.message }}\n \n \n \n {{ 'USERS.BULK_IMPORT.IMPORT_MAPPER.SHOW_MORE' | translate }}\n \n
\n \n {{ 'USERS.BULK_IMPORT.IMPORT_MAPPER.SKIP_ROWS_WITH_ERRORS' | translate }}\n \n
\n \n {{ 'USERS.BULK_IMPORT.IMPORT_MAPPER.DOWNLOAD_CSV_WITH_INCOMPLETE_ACCOUNTS' | translate }}\n \n
\n *{{ 'COMMON.REQUIRED' | translate }}\n
\n 0\" href=\"/manage-accounts/import-list/business-categories-csv\" target=\"_blank\">\n save_alt\n \n {{ 'USERS.BULK_IMPORT.DOWNLOAD_BUSINESS_CATEGORIES' | translate }}\n \n \n
\n\n
\n \n \n {{ 'COMMON.ACTION_LABELS.BACK' | translate }}\n \n \n \n {{ 'COMMON.ACTION_LABELS.NEXT' | translate }}\n \n \n \n
\n","import { AfterViewInit, Component, Inject, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';\nimport {\n AbstractControl,\n FormGroupDirective,\n NgForm,\n UntypedFormBuilder,\n UntypedFormControl,\n UntypedFormGroup,\n Validators,\n} from '@angular/forms';\nimport { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';\nimport { ErrorStateMatcher } from '@angular/material/core';\nimport { MatDialog } from '@angular/material/dialog';\nimport { MatStepper } from '@angular/material/stepper';\nimport { Router } from '@angular/router';\nimport { FeatureFlagService } from '@vendasta/businesses';\nimport { Market } from '@vendasta/businesses/easy-account-create';\nimport { ProductAnalyticsService } from '@vendasta/product-analytics';\nimport { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs';\nimport { map, shareReplay, startWith, switchMap, take, tap } from 'rxjs/operators';\nimport { ActionListsStoreService } from '../action-lists';\nimport { ActionList } from '../action-lists/action-list';\nimport { FieldSelectedForEditService as CreateOrEditCustomFieldService } from '../auxiliary-data/columns/field-selected-for-edit.service';\nimport { WELCOME_EMAIL_LOCALES } from '../constants';\nimport { AccessService, Feature, StubAccessService } from '../core/access';\nimport { MarketsService } from '../core/markets/markets.service';\nimport { DynamicOpenCloseTemplateRefService } from '../side-drawer/dynamic-open-close-template-ref.service';\nimport { PreviewWelcomeEmailComponent } from '../users/user/preview-welcome-email-dialog.component';\nimport { VConfigService } from '../vconfig/vconfig.service';\nimport { BulkImportMappingService } from './bulk-import-mapping.service';\nimport { BulkImportService } from './bulk-import.service';\n\n@Component({\n templateUrl: './bulk-import.component.html',\n styleUrls: ['./bulk-import.component.scss'],\n})\nexport class BulkImportComponent implements OnInit, AfterViewInit, OnDestroy {\n secondFormGroup: UntypedFormGroup;\n fileTypes = ['text/csv'];\n marketUiESM: MyErrorStateMatcher;\n filteredMarkets$: Observable;\n marketSearchTerm$$: BehaviorSubject = new BehaviorSubject('');\n listSearchTerm$$: BehaviorSubject = new BehaviorSubject('');\n selectFirstMarket = false;\n hasAccessToMarkets$: Observable;\n marketUiFormControl: UntypedFormControl;\n fileFormControl: UntypedFormControl;\n listFormControl: UntypedFormControl;\n filteredLists$: Observable;\n selectFirstActionList: boolean;\n subscriptions: Subscription[] = [];\n accessibleMarkets: string[] = [];\n totalRows$: Observable;\n marketName: string;\n listName: string;\n fileName: string;\n errorRows: any = [];\n show = 10;\n listText = `To an existing list named:`;\n fileForm: UntypedFormGroup;\n marketListForm: UntypedFormGroup;\n listSelected = false;\n marketMatcher: MyErrorStateMatcher;\n listMatcher: MyErrorStateMatcher;\n @ViewChild('stepper', { static: true })\n pageStepper: MatStepper;\n processing: boolean;\n processingErrorMessage: string = null;\n loading = false;\n netRows$: Observable;\n marketAndListText = 'Choose List';\n overwriteBlank = true;\n partnerBusinessCenterName$: Observable;\n permissionsFlag: boolean;\n notificationsFlag: boolean;\n welcomeEmailFlag: boolean;\n emailLanguage: string;\n welcomeMessage: string;\n emailLanguages = WELCOME_EMAIL_LOCALES;\n englishSelection: string;\n vbcConfigKey = 'vbc_product_name';\n @ViewChild('customFieldEditor', { static: true }) customFieldEditor: TemplateRef;\n\n constructor(\n private formBuilder: UntypedFormBuilder,\n public dialog: MatDialog,\n private marketService: MarketsService,\n private actionListsStoreService: ActionListsStoreService,\n private bulkImportService: BulkImportService,\n private mappingService: BulkImportMappingService,\n @Inject(StubAccessService) private accessService: AccessService,\n @Inject('PARTNER_ID') private readonly partnerId$: Observable,\n @Inject('MARKET_ID') private readonly marketId$: Observable,\n private feature: FeatureFlagService,\n private router: Router,\n private vConfigService: VConfigService,\n private readonly createOrEditCustomFieldService: CreateOrEditCustomFieldService,\n private readonly dynamicOpenCloseService: DynamicOpenCloseTemplateRefService,\n private readonly trackingService: ProductAnalyticsService,\n ) {}\n\n get filename(): string {\n if (this.bulkImportService.file) {\n return this.bulkImportService.file.name;\n }\n return '';\n }\n\n ngOnInit(): void {\n this.subscriptions.push(\n this.createOrEditCustomFieldService.createClicked$\n .pipe(tap(() => this.dynamicOpenCloseService.open('customFieldEditor')))\n .subscribe(),\n );\n this.actionListsStoreService.initializeStore(1000);\n this.marketUiFormControl = new UntypedFormControl('');\n this.fileFormControl = new UntypedFormControl('', [Validators.required]);\n this.listFormControl = new UntypedFormControl('', [Validators.required]);\n this.secondFormGroup = this.formBuilder.group({\n secondCtrl: ['', Validators.required],\n });\n\n this.fileForm = this.formBuilder.group({\n file: ['', Validators.required],\n fileHasErrors: [false],\n });\n\n this.marketListForm = this.formBuilder.group({\n marketId: [null, Validators.required],\n actionListId: [null, Validators.required],\n actionListName: [''],\n useExistingList: [true],\n });\n\n this.hasAccessToMarkets$ = this.accessService.hasAccessToFeature(Feature.markets).pipe(\n tap((hasAccess) => {\n hasAccess ? (this.marketAndListText = 'Choose Market and List') : (this.marketAndListText = 'Choose List');\n this.marketUiFormControl.setValidators(hasAccess ? [Validators.required] : []);\n }),\n );\n\n this.filteredMarkets$ = combineLatest([\n this.marketSearchTerm$$.asObservable().pipe(startWith('')),\n this.marketService.markets.pipe(startWith([])),\n ]).pipe(\n map(([searchTerm, markets]: [string, Market[]]) =>\n markets.filter((market) => {\n this.selectFirstMarket = !!searchTerm;\n if (market) {\n return market.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1;\n }\n return false;\n }),\n ),\n );\n\n this.filteredLists$ = combineLatest([\n this.listSearchTerm$$.asObservable().pipe(startWith('')),\n this.actionListsStoreService.actionLists$.pipe(startWith([])),\n ]).pipe(\n map(([searchTerm, actionLists]: [string, ActionList[]]) => {\n if (actionLists) {\n return actionLists.filter((actionList) => {\n this.selectFirstActionList = !!searchTerm;\n if (actionList && typeof searchTerm === 'string') {\n return actionList.name.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1;\n }\n return false;\n });\n }\n }),\n startWith([]),\n );\n\n this.marketUiESM = new CustomErrorStateMatcher(\n this.marketListForm.controls.marketId,\n (formControl: AbstractControl) => !formControl.value && formControl.touched,\n );\n this.subscriptions.push(\n this.marketService.markets\n .pipe(\n map((markets) => {\n this.accessibleMarkets = markets.map((market) => market.market_id);\n }),\n )\n .subscribe(),\n );\n\n this.subscriptions.push(\n combineLatest([this.marketService.currentMarket$, this.hasAccessToMarkets$])\n .pipe(\n tap(([market, marketAccess]) => {\n if (marketAccess === false || this.accessibleMarkets.length === 1) {\n this.marketListForm.patchValue({ marketId: market });\n }\n }),\n )\n .subscribe(),\n );\n this.marketMatcher = new MyErrorStateMatcher();\n this.listMatcher = new MyErrorStateMatcher();\n this.permissionsFlag = true;\n this.notificationsFlag = true;\n this.welcomeEmailFlag = false;\n this.welcomeMessage = '';\n this.emailLanguage = this.emailLanguages[0].id;\n this.englishSelection = this.emailLanguage;\n\n this.partnerBusinessCenterName$ = this.partnerId$.pipe(\n switchMap((partnerId) => {\n return this.vConfigService.getConfigurations(partnerId, [this.vbcConfigKey]);\n }),\n map((config) => config.vbc_product_name),\n shareReplay(1),\n );\n }\n\n ngAfterViewInit(): void {\n this.dynamicOpenCloseService.registerTemplate('customFieldEditor', this.customFieldEditor);\n }\n\n ngOnDestroy(): void {\n this.subscriptions.forEach((s) => s.unsubscribe());\n }\n\n fileOnChange(event: any): void {\n this.trackingService.trackEvent(\n `BulkImport:clicked-upload-file-bulk-import`,\n 'BulkImport',\n `clicked-upload-file-bulk-import`,\n );\n this.errorRows = [];\n if (!event.target.files) {\n return;\n }\n this.processing = true;\n this.processingErrorMessage = null;\n this.mappingService.resetMapping();\n this.bulkImportService.file = event.target.files[0];\n this.bulkImportService\n .processFile()\n .pipe(take(1))\n .subscribe({\n next: () => {\n this.processing = false;\n this.pageStepper.next();\n },\n error: (error) => {\n this.processing = false;\n this.processingErrorMessage = error;\n },\n });\n }\n\n nameDisplayFn(objectWithAName: { name: string }): string {\n return objectWithAName ? objectWithAName.name : undefined;\n }\n\n selectMarket(event: MatAutocompleteSelectedEvent): void {\n this.marketListForm.controls.marketId.setValue(event.option.value);\n this.marketName = this.marketListForm.controls.marketId.value.name;\n }\n\n selectList(event: MatAutocompleteSelectedEvent): void {\n this.listSelected = true;\n this.marketListForm.controls.useExistingList.setValue(true);\n this.marketListForm.controls.actionListId.setValue(event.option.value);\n this.listName = this.marketListForm.controls.actionListId.value.name;\n }\n\n updateSearchTerm(subject$$: BehaviorSubject, term: string): void {\n subject$$.next(term);\n }\n\n displayFn(actionList?: ActionList): string | undefined {\n return actionList ? actionList.name : undefined;\n }\n\n downloadTemplate(): void {\n window.open('/manage-accounts/import-list/csv-template/', '_blank');\n }\n\n downloadBusinessCategories(): void {\n window.open('/manage-accounts/import-list/business-categories-csv', '_blank');\n }\n\n increaseShow(): void {\n this.show += 10;\n }\n\n goToFinalStep(): void {\n this.netRows$ = combineLatest([this.bulkImportService.totalRows$, this.bulkImportService.errorRows$]).pipe(\n map(([totalRows, errorRows]) => {\n return totalRows - errorRows;\n }),\n );\n this.marketUiFormControl.markAsTouched();\n this.listFormControl.markAsTouched();\n this.setListName();\n }\n\n clearInput(event: any, input: any): void {\n this.show = 10;\n this.errorRows = [];\n input.value = '';\n }\n\n setListName(): void {\n if (this.marketListForm.controls.useExistingList.value && this.marketListForm.controls.actionListId.value) {\n this.listName = this.marketListForm.controls.actionListId.value.name;\n } else {\n this.listName = this.marketListForm.controls.actionListName.value;\n }\n }\n\n selectExistingList(): void {\n if (!this.marketListForm.controls.useExistingList.value) {\n this.marketListForm.controls.actionListId.setValidators([Validators.required]);\n this.listName = '';\n this.marketListForm.controls.actionListId.setValue('');\n this.marketListForm.controls.actionListName.clearValidators();\n this.marketListForm.controls.actionListName.updateValueAndValidity({ onlySelf: true });\n this.listText = `To an existing list named:`;\n }\n }\n\n createNewList(): void {\n this.marketListForm.controls.actionListName.setValidators([Validators.required]);\n this.listFormControl.setValue('');\n this.marketListForm.controls.actionListName.setValue(null);\n this.marketListForm.controls.actionListId.clearValidators();\n this.marketListForm.controls.actionListId.updateValueAndValidity({ onlySelf: true });\n this.listText = `To a new list named:`;\n }\n\n goToFieldMapping(): void {\n if (this.processingErrorMessage === null) {\n this.fileForm.controls.file.markAsTouched();\n this.fileForm.controls.fileHasErrors.markAsTouched();\n this.pageStepper.next();\n }\n }\n\n startListImport(): void {\n this.loading = true;\n this.bulkImportService\n .startListImport(\n this.bulkImportService.sessionId,\n this.listName,\n this.marketListForm.controls.marketId.value.market_id,\n this.overwriteBlank,\n this.permissionsFlag,\n this.notificationsFlag,\n this.welcomeEmailFlag,\n this.emailLanguage,\n this.welcomeMessage,\n )\n .subscribe((response) => {\n this.loading = false;\n this.router.navigate(['action-lists', response.data.actionListId, 'history']);\n });\n }\n\n openPreview(): void {\n this.dialog.open(PreviewWelcomeEmailComponent, { width: '600px' });\n }\n}\n\nexport class MyErrorStateMatcher implements ErrorStateMatcher {\n isErrorState(control: UntypedFormControl | null, form: FormGroupDirective | NgForm | null): boolean {\n const isSubmitted = form && form.submitted;\n return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));\n }\n}\n\nexport class CustomErrorStateMatcher implements ErrorStateMatcher {\n hasError: (formControl: AbstractControl) => boolean;\n formControl: AbstractControl;\n\n constructor(formControl: AbstractControl, hasError: (formControl: AbstractControl) => boolean) {\n this.formControl = formControl;\n this.hasError = hasError;\n }\n\n isErrorState(): boolean {\n return this.hasError.call(this, this.formControl);\n }\n}\n","\n \n \n \n {{ 'USERS.BULK_IMPORT.IMPORT_WIZARD' | translate }}\n \n \n \n \n \n \n \n \n
\n \n {{ 'USERS.BULK_IMPORT.UPLOAD_CSV_OF_ACCOUNTS' | translate }}\n \n
\n {{ 'USERS.BULK_IMPORT.UPLOAD_EXISTING_CUSTOMER_DATA' | translate }}\n
\n
\n {{ 'USERS.BULK_IMPORT.ADD_UP_TO_15_COLUMNS' | translate }}\n
\n
\n {{ 'USERS.BULK_IMPORT.REQUIRED_FIELDS' | translate }}\n CompanyName\n {{ 'STORE.AND' | translate }}\n Zip\n .\n
\n {{ 'USERS.BULK_IMPORT.MAXIMUM_FILE_SIZE' | translate }}\n 4MB\n .\n
\n
\n
\n attach_file\n \n \n clear\n \n \n {{ 'COMMON.THIS_FIELD_REQUIRED' | translate }}\n \n
\n \n \n
\n {{ 'USERS.BULK_IMPORT.AVAILABLE_FILES' | translate }}\n
\n \n\n
\n \n {{ 'COMMON.ACTION_LABELS.NEXT' | translate }}\n \n
\n \n
\n \n
\n \n \n \n \n
\n \n
\n \n
\n
\n \n
\n
\n \n {{\n 'USERS.BULK_IMPORT.ALLOW_ACCESS_TO_BUSINESS_APP'\n | translate : { businessAppName: partnerBusinessCenterName$ | async }\n }}\n \n
\n {{ 'USERS.BULK_IMPORT.CONFIGURE_PERMISSIONS_FOR_EACH_USER' | translate }}\n
\n
\n
\n
\n \n
\n \n {{ 'USERS.BULK_IMPORT.TURN_ON_ALL_NOTIFICATIONS' | translate }}\n \n
\n
\n \n
\n
\n \n
\n
\n \n {{ 'USERS.BULK_IMPORT.SEND_WELCOME_EMAIL' | translate }}\n\n \n {{ 'COMMON.ACTION_LABELS.PREVIEW' | translate }}\n \n \n
\n
\n
\n \n \n {{ 'USERS.BULK_IMPORT.DEFAULT_EMAIL_LANGUAGE' | translate }}\n \n \n \n {{ language.name }}\n \n \n \n {{ 'USERS.BULK_IMPORT.WELCOME_EMAIL_LANGUAGE' | translate }}\n \n \n
\n
\n \n \n {{ 'USERS.BULK_IMPORT.WELCOME_MESSAGE' | translate }}\n \n \n \n
\n
\n
\n
\n
\n
\n \n {{ 'COMMON.ACTION_LABELS.BACK' | translate }}\n \n \n {{ 'COMMON.ACTION_LABELS.NEXT' | translate }}\n \n
\n
\n \n
\n {{ marketAndListText }}\n
\n
\n \n {{ 'USERS.BULK_IMPORT.SELECT_MARKET_FOR_IMPORT' | translate }}\n \n
\n \n \n \n \n {{ market.name }}\n \n \n arrow_drop_down\n \n {{ 'USERS.BULK_IMPORT.MARKET_IS_REQUIRED' | translate }}\n \n \n
\n
\n \n {{ 'USERS.BULK_IMPORT.USE_OR_CREATE_NEW_LIST' | translate }}\n \n
\n \n \n {{ 'USERS.BULK_IMPORT.SELECT_EXISTING_LIST' | translate }}\n \n
\n \n \n \n \n {{ list.name }}\n \n \n arrow_drop_down\n \n {{ 'USERS.BULK_IMPORT.SELECT_OR_CREATE_LIST' | translate }}\n \n \n
\n \n {{ 'USERS.BULK_IMPORT.CREATE_NEW_LIST' | translate }}\n \n
\n \n \n \n {{ 'USERS.BULK_IMPORT.SELECT_OR_CREATE_LIST' | translate }}\n \n \n
\n
\n\n
\n \n {{ 'COMMON.ACTION_LABELS.BACK' | translate }}\n \n \n {{ 'COMMON.ACTION_LABELS.NEXT' | translate }}\n \n
\n
\n
\n \n \n {{ 'USERS.BULK_IMPORT.REVIEW_IMPORT' | translate }}\n \n
\n
\n
\n insert_drive_file\n {{ filename }}\n
\n
\n
\n {{ listName }}\n
\n
\n
\n
\n {{ marketName }}\n
\n
\n
\n
\n {{ 'USERS.BULK_IMPORT.HOW_TO_TREAT_EMPTY_CELLS' | translate }}\n
\n
\n \n {{ 'USERS.BULK_IMPORT.ATTEMPT_TO_FILL_EMPTY_CELLS' | translate }}\n \n
\n
\n \n
\n
\n \n {{ 'COMMON.ACTION_LABELS.BACK' | translate }}\n \n \n \n \n {{ 'COMMON.ACTION_LABELS.FINISH' | translate }}\n \n \n
\n
\n
\n
\n
\n
\n\n \n \n \n
\n","import { CommonModule } from '@angular/common';\nimport { Component, Inject, OnInit } from '@angular/core';\nimport { ReactiveFormsModule, UntypedFormControl } from '@angular/forms';\nimport { AccountGroup, AccountGroupService, ProjectionFilter } from '@galaxy/account-group';\nimport { GalaxyFormFieldModule } from '@vendasta/galaxy/form-field';\nimport { GalaxyInputModule } from '@vendasta/galaxy/input';\n// eslint-disable-next-line @nx/enforce-module-boundaries\nimport {\n PREVIEW_DATA_TYPE,\n PreviewDataProvider,\n RecipientTypes,\n stepDataForPartnerEmail,\n} from '@galaxy/campaign/dependencies';\nimport { TranslateModule } from '@ngx-translate/core';\nimport { BehaviorSubject, Observable, combineLatest, firstValueFrom } from 'rxjs';\nimport { map, take } from 'rxjs/operators';\nimport { MarketsService } from '../../core/markets/markets.service';\nimport { MatOptionModule } from '@angular/material/core';\nimport { MatAutocompleteModule } from '@angular/material/autocomplete';\nimport { MatFormFieldModule } from '@angular/material/form-field';\n\nconst PAGE_SIZE = 20;\n\n@Component({\n templateUrl: './campaign-account-selector.component.html',\n standalone: true,\n imports: [\n CommonModule, //\n GalaxyInputModule,\n GalaxyFormFieldModule,\n MatAutocompleteModule,\n MatOptionModule,\n ReactiveFormsModule,\n TranslateModule,\n MatFormFieldModule,\n ],\n})\nexport class CampaignAccountSelectorComponent implements PreviewDataProvider, OnInit {\n data$: PREVIEW_DATA_TYPE;\n\n accountGroupSelect: UntypedFormControl = new UntypedFormControl();\n readonly accountGroups$: Observable;\n selectedAccountGroup: AccountGroup;\n searchTerm$$: BehaviorSubject = new BehaviorSubject('');\n private accessibleMarkets: string[] | undefined;\n\n constructor(\n @Inject('USER_ID') uid$: Observable,\n private readonly accountGroupService: AccountGroupService,\n private readonly marketsService: MarketsService,\n ) {\n this.accountGroups$ = this.accountGroupService.accountGroups;\n this.data$ = combineLatest([this.accountGroupSelect.valueChanges, uid$]).pipe(\n map(([ag, uid]: [AccountGroup, string]) =>\n stepDataForPartnerEmail(ag.accountGroupId, RecipientTypes.IAMUser, uid),\n ),\n );\n }\n\n async ngOnInit(): Promise {\n const markets = await firstValueFrom(this.marketsService.markets);\n this.accessibleMarkets = markets.map((m) => m.market_id);\n await firstValueFrom(\n this.accountGroupService.lookup(\n new ProjectionFilter({\n napData: true,\n }),\n this.accessibleMarkets,\n '',\n undefined,\n PAGE_SIZE,\n ),\n );\n }\n\n selectAccount(accountGroup?: AccountGroup): void {\n if (!accountGroup) {\n this.accountGroupSelect.setValue(null);\n this.selectedAccountGroup = null;\n return;\n }\n this.selectedAccountGroup = accountGroup;\n }\n\n displayFn(accountGroup?: AccountGroup): string | undefined {\n return accountGroup ? accountGroup.napData.companyName : 'Generic account';\n }\n\n updateSearchTerm(event: Event): void {\n this.selectedAccountGroup = null;\n const searchValue = (event.target as HTMLInputElement).value;\n this.searchTerm$$.next(searchValue);\n this.search(searchValue);\n }\n\n search(searchValue: string): void {\n this.accountGroupService\n .lookup(\n new ProjectionFilter({\n napData: true,\n }),\n this.accessibleMarkets,\n searchValue,\n undefined,\n PAGE_SIZE,\n )\n .pipe(take(1));\n }\n}\n","\n \n {{ 'CAMPAIGN_GENERIC.TEST_EMAIL.PREVIEW_AS' | translate }}\n \n \n \n \n {{ 'CAMPAIGN_GENERIC.TEST_EMAIL.GENERIC_ACCOUNT' | translate }}\n \n \n \n
{{ accountGroup.napData.companyName }}
\n \n
\n {{ accountGroup.napData.address }}\n
\n
\n
\n
\n \n
\n","import { AsyncPipe, NgForOf, NgIf } from '@angular/common';\nimport { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';\nimport { async } from '@angular/core/testing';\nimport { FormControl, ReactiveFormsModule } from '@angular/forms';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatSelectModule } from '@angular/material/select';\nimport { TranslateModule } from '@ngx-translate/core';\nimport { GalaxyEmptyStateModule } from '@vendasta/galaxy/empty-state';\nimport { GalaxyFormFieldModule } from '@vendasta/galaxy/form-field';\nimport { of, Subscription } from 'rxjs';\nimport { map, switchMap } from 'rxjs/operators';\nimport { VariableMenuItem } from '../variable-menu.service';\n\n@Component({\n standalone: true,\n imports: [\n GalaxyFormFieldModule,\n MatSelectModule,\n TranslateModule,\n ReactiveFormsModule,\n AsyncPipe,\n NgForOf,\n NgIf,\n GalaxyEmptyStateModule,\n MatButtonModule,\n MatIconModule,\n ],\n selector: 'app-variable-menu-item-selector',\n templateUrl: './variable-menu-item-selector.component.html',\n styleUrls: ['./variable-menu-item-selector.component.scss'],\n})\nexport class VariableMenuItemSelectorComponent implements OnInit, OnDestroy {\n @Input() items: VariableMenuItem[];\n @Input() parentTextKey: string;\n @Output() variableMenuItemSelected = new EventEmitter();\n\n formControl: FormControl = new FormControl(null);\n private subscriptions: Subscription[] = [];\n\n ngOnInit(): void {\n this.subscriptions.push(\n this.formControl.valueChanges\n .pipe(\n switchMap((variableMenuItem) => {\n return variableMenuItem.subItems$ || of([]);\n }),\n map((subItems) => {\n // Check if it's a leaf node\n if (subItems.length == 0) {\n this.variableMenuItemSelected.emit(this.formControl.value);\n }\n }),\n )\n .subscribe(),\n );\n }\n\n ngOnDestroy(): void {\n this.subscriptions.forEach((subscription) => {\n subscription.unsubscribe();\n });\n }\n\n childComponentVariableMenuItemSelected(variableMenuItem: VariableMenuItem): void {\n this.variableMenuItemSelected.emit(variableMenuItem);\n }\n\n protected readonly async = async;\n}\n","
\n \n \n search_off\n \n \n {{ 'HTML_EDITOR.DYNAMIC_CONTENT.NO_DATA_FOUND' | translate }}\n \n

\n {{ 'HTML_EDITOR.DYNAMIC_CONTENT.NO_DATA_FOUND_DESCRIPTION' | translate }}\n

\n
\n
\n
0\">\n \n {{ parentTextKey | translate }}\n \n \n {{ item.textKey | translate }}\n \n \n \n \n 0\">\n \n \n \n
\n","import { Injectable } from '@angular/core';\nimport { MarketplaceAppService } from '@vendasta/marketplace-packages';\nimport {\n ListSubstitutionParametersRequestFiltersInterface,\n SubstitutionParameter,\n TemplatesService,\n} from '@vendasta/templates';\nimport { Observable } from 'rxjs';\nimport { map, shareReplay } from 'rxjs/operators';\nimport { BUSINESS_CUSTOM_DATA, SALESPERSON_CUSTOM_DATA } from './variable-menu-dialog/variable-menu-dialog.component';\n// eslint-disable-next-line @nx/enforce-module-boundaries\nimport { SchemaService } from '@vendasta/auxiliary-data-components';\nimport { SubstitutionParameterOptionsInterface } from '@vendasta/templates/lib/_internal/interfaces/substitution.interface';\n\nexport interface Option {\n title: string;\n value: string;\n}\n\nexport interface VariablesFilters {\n includeHtml?: boolean;\n dontIncludeDefaultCategories?: boolean;\n includeDeprecated?: boolean;\n // forRequiredOptions should be used for filtering out variables you don't have tue required data to render with but\n // it currently is not used, unfortunately\n forRequiredOptions?: SubstitutionParameterOptionsInterface;\n}\n\ninterface VariableMenuItemSettings {\n requiredParams: string[];\n // By default the replacement tag is surrounded by '{{' and '}}' so that templates µs can interpolate them. This\n // flag turns that off\n shouldNotSurroundWithCurlyBraces?: boolean;\n}\n\nexport interface VariableMenuCategory {\n textKey: string;\n subItems$: Observable;\n settings?: VariableMenuItemSettings;\n}\n\nexport interface VariableMenuItem {\n textKey: string;\n // VariableMenuItems either have a replacement tag (if they are a leaf) or subItems if they are just part of a branch\n replacementTag: string;\n subItems$?: Observable;\n settings?: VariableMenuItemSettings; //Not sure if settings is requried on the VariableMenuItem or just the category\n}\n\n@Injectable({\n providedIn: 'root',\n})\nexport class VariableMenuService {\n allSubstitutionParameters$: Observable = this.templatesService\n .listSubstitutionParameters({ includeHtml: true })\n .pipe(shareReplay(1));\n\n private buildVariables(\n partnerId: string,\n marketId: string,\n filters: ListSubstitutionParametersRequestFiltersInterface,\n ): VariableMenuCategory[] {\n return [\n {\n textKey: 'HTML_EDITOR.DYNAMIC_CONTENT.ACCOUNT_DETAILS',\n subItems$: this.filterAllSubstitionParametersToSupportedReplacementTags(\n [\n 'businessName',\n 'businessWebsite',\n 'customerIdentifier',\n 'accountIdentifier',\n 'companyIdentifier',\n 'businessPhoneNumber',\n 'businessCountry',\n 'businessState',\n 'businessStreetAddress',\n 'businessStreetAddress2',\n 'businessCity',\n 'businessPostalCode',\n 'businessOrigin',\n 'businessCategoryIds',\n 'businessEmail',\n ],\n filters,\n ),\n },\n {\n textKey: 'HTML_EDITOR.DYNAMIC_CONTENT.PARTNER_DETAILS',\n subItems$: this.filterAllSubstitionParametersToSupportedReplacementTags(\n [\n 'partnerName',\n 'partnerWebsite',\n 'partnerEmail',\n 'partnerPhone',\n 'partnerStreetAddress',\n 'partnerStreetAddress2',\n 'partnerCity',\n 'partnerState',\n 'partnerCountry',\n 'partnerPostalCode',\n ],\n filters,\n ),\n },\n {\n textKey: 'HTML_EDITOR.DYNAMIC_CONTENT.ORDER_DETAILS',\n subItems$: this.filterAllSubstitionParametersToSupportedReplacementTags(\n [\n 'orderId',\n 'orderLineItems',\n 'status',\n 'orderBusinessName',\n 'expiryDate',\n 'contractStartDate',\n 'userContact',\n ],\n filters,\n ),\n settings: {\n requiredParams: ['isOrderAutomation'],\n },\n },\n {\n textKey: 'HTML_EDITOR.DYNAMIC_CONTENT.ORDER_SALESPERSON_DETAILS.TITLE',\n subItems$: this.filterAllSubstitionParametersToSupportedReplacementTags(\n [\n 'salesPersonInformation',\n 'orderSalesPersonFirstName',\n 'orderSalesPersonLastName',\n 'orderSalesPersonPhoneNumber',\n 'orderSalesPersonEmail',\n 'orderSalesPersonJobTitle',\n 'orderSalesPersonPhoto',\n 'salesPersonId',\n ],\n filters,\n ),\n settings: {\n requiredParams: ['isOrderAutomation'],\n },\n },\n {\n textKey: 'HTML_EDITOR.DYNAMIC_CONTENT.SALESPERSON_DETAILS',\n subItems$: this.filterAllSubstitionParametersToSupportedReplacementTags(\n [\n 'salesPersonContactCard',\n 'salesPersonFirstName',\n 'salesPersonLastName',\n 'salesPersonEmail',\n 'salesPersonPhoneNumber',\n 'salesPersonJobTitle',\n 'salesPersonLoginUrl',\n ],\n filters,\n ),\n },\n {\n textKey: 'HTML_EDITOR.DYNAMIC_CONTENT.BUSINESS_APP_DETAILS',\n subItems$: this.filterAllSubstitionParametersToSupportedReplacementTags(\n ['businessAppName', 'businessAppUrl', 'businessAppStoreUrl', 'businessAppPreviewUrl'],\n filters,\n ),\n },\n {\n textKey: 'HTML_EDITOR.DYNAMIC_CONTENT.PRODUCT_DETAILS.TITLE',\n subItems$: this.filterAllSubstitionParametersToSupportedReplacementTags(['productName'], filters).pipe(\n map((subItems) => {\n if ((subItems || []).length > 0) {\n subItems[0].subItems$ = this.marketplacePackagesService.getAllActivatableApps(partnerId, marketId).pipe(\n shareReplay(1),\n map((apps) => {\n return apps.map((app) => ({\n replacementTag: \"productName['\" + app.appId + \"']\",\n textKey: app.name,\n }));\n }),\n );\n }\n return subItems;\n }),\n ),\n settings: {\n requiredParams: ['partnerId', 'marketId'],\n },\n },\n {\n textKey: 'HTML_EDITOR.DYNAMIC_CONTENT.CUSTOM_DATA_DETAILS.TITLE',\n subItems$: this.filterAllSubstitionParametersToSupportedReplacementTags(\n [SALESPERSON_CUSTOM_DATA, BUSINESS_CUSTOM_DATA],\n filters,\n ).pipe(\n map((menuItems) => {\n if ((menuItems || []).length > 0) {\n menuItems.map((menuItem) => {\n if (menuItem.replacementTag === SALESPERSON_CUSTOM_DATA) {\n menuItem.subItems$ = this.schemaService.listFieldSchemas('user', partnerId, false, '', 100).pipe(\n map((response) => response.fieldSchemas),\n map((fieldSchemas) =>\n fieldSchemas.map((schema) => ({\n textKey: schema.fieldName,\n replacementTag: SALESPERSON_CUSTOM_DATA + \"['\" + schema.fieldId + \"']\",\n })),\n ),\n );\n }\n if (menuItem.replacementTag === BUSINESS_CUSTOM_DATA) {\n menuItem.subItems$ = this.schemaService.listFieldSchemas('business', partnerId, false, '', 100).pipe(\n map((response) => response.fieldSchemas),\n map((fieldSchemas) =>\n fieldSchemas.map((schema) => ({\n textKey: schema.fieldName,\n replacementTag: BUSINESS_CUSTOM_DATA + \"['\" + schema.fieldId + \"']\",\n })),\n ),\n );\n }\n });\n }\n return menuItems;\n }),\n ),\n settings: {\n requiredParams: ['partnerId'],\n },\n },\n ];\n }\n\n constructor(\n private readonly templatesService: TemplatesService,\n private readonly marketplacePackagesService: MarketplaceAppService,\n private readonly schemaService: SchemaService,\n ) {}\n\n public getVariables(\n partnerId: string,\n marketId: string,\n filters: VariablesFilters,\n extraMenuItems: VariableMenuItem[] = [],\n ): VariableMenuItem[] {\n const variables = this.buildVariables(partnerId, marketId, filters);\n let variablesFromCategories: VariableMenuItem[] = variables.map((v) => ({\n textKey: v.textKey,\n settings: v.settings,\n replacementTag: '', // This is the top level category so it doesn't have a replacement tag\n subItems$: v.subItems$,\n }));\n if (filters.dontIncludeDefaultCategories) {\n variablesFromCategories = [];\n }\n return variablesFromCategories.concat(extraMenuItems);\n }\n\n private variableMenuItemFromSubstitutionParameter(s: SubstitutionParameter): VariableMenuItem {\n return {\n replacementTag: s.replacementTag,\n textKey: s.displayName,\n };\n }\n\n private filterAllSubstitionParametersToSupportedReplacementTags(\n supportedReplacementTags: string[],\n filters: ListSubstitutionParametersRequestFiltersInterface,\n ): Observable {\n return this.allSubstitutionParameters$.pipe(\n map((params) => {\n const filteredParams = params.filter((p) => {\n return !(!filters.includeHtml && p.isHtml);\n });\n return filteredParams\n .filter((p) => supportedReplacementTags.some((t) => t === p.replacementTag))\n .sort(function (a, b): number {\n return (\n supportedReplacementTags.indexOf(a.replacementTag) - supportedReplacementTags.indexOf(b.replacementTag)\n );\n })\n .map(this.variableMenuItemFromSubstitutionParameter);\n }),\n );\n }\n}\n","import { AsyncPipe, NgIf } from '@angular/common';\nimport { Component, EventEmitter, Input, Output } from '@angular/core';\nimport { async } from '@angular/core/testing';\nimport { MatButtonModule } from '@angular/material/button';\nimport { ActivatedRoute } from '@angular/router';\nimport { TranslateModule } from '@ngx-translate/core';\nimport { SubstitutionParameterOptionsInterface } from '@vendasta/templates';\nimport { CookieService } from 'ngx-cookie-service';\nimport { combineLatest, Observable, of } from 'rxjs';\nimport { map, shareReplay } from 'rxjs/operators';\nimport { VariableMenuItemSelectorComponent } from '../variable-menu-item-selector/variable-menu-item-selector.component';\nimport { VariableMenuItem, VariableMenuService } from '../variable-menu.service';\n\nexport const SALESPERSON_CUSTOM_DATA = 'salesPersonCustomData';\nexport const BUSINESS_CUSTOM_DATA = 'businessCustomData';\n\n@Component({\n standalone: true,\n imports: [VariableMenuItemSelectorComponent, AsyncPipe, TranslateModule, MatButtonModule, NgIf],\n selector: 'app-variable-menu-dialog',\n templateUrl: './variable-menu-dialog.component.html',\n styleUrls: ['./variable-menu-dialog.component.scss'],\n})\n// VariableMenuDialogComponent is used both as a regular component as well as in an iFrame. This is because it is used\n// with a TinyMCE editor and the only way for it to render angular components is through an iframe.\n// Because of this the input parameters can either come in via @Input's or via query params\nexport class VariableMenuDialogComponent {\n @Input() emitEventsInsteadOfTakingAction = false;\n @Input() partnerId = '';\n @Input() marketId = '';\n @Input() isOrderAutomation = false;\n @Input() extraMenuItems: VariableMenuItem[] = [];\n @Input() supportedSubstitutionOptions: SubstitutionParameterOptionsInterface = null;\n @Input() dontIncludeDefaultCategories = false;\n @Output() formResult: EventEmitter = new EventEmitter();\n\n chosenVariableMenutItem: VariableMenuItem = null;\n\n includeHtml$: Observable = this.route.queryParamMap.pipe(\n map((params) => {\n return !!params.get('includeHtml');\n }),\n );\n\n partnerId$: Observable = this.route.queryParamMap.pipe(\n map((params) => {\n if (params.get('partnerId')) {\n this.partnerId = params.get('partnerId');\n }\n return this.partnerId;\n }),\n );\n\n marketId$: Observable = this.route.queryParamMap.pipe(\n map((params) => {\n if (params.get('marketId')) {\n this.marketId = params.get('marketId');\n }\n return this.marketId;\n }),\n );\n\n extraMenuItems$: Observable = this.route.queryParamMap.pipe(\n map((params) => {\n return params.get('extraMenuItemsCookieString');\n }),\n map((cookieId) => {\n if (cookieId) {\n const payload = this.cookieService.get(cookieId);\n if (payload) {\n // Observables can't be json stringified so they are serilizaed as raw values and need to be changed back to\n // observables so the rest of the code doesn't have to worry about this\n return this.convertNonObservablesSubItemsToObservables(JSON.parse(payload));\n }\n }\n return this.extraMenuItems;\n }),\n );\n\n variables$: Observable = combineLatest([\n this.includeHtml$,\n this.extraMenuItems$,\n this.partnerId$,\n this.marketId$,\n ]).pipe(\n map(([includeHtml, extraMenuItems, partnerId, marketId]) => {\n return this.variableMenuService.getVariables(\n partnerId,\n marketId,\n {\n includeHtml: includeHtml,\n forRequiredOptions: this.supportedSubstitutionOptions,\n dontIncludeDefaultCategories: this.dontIncludeDefaultCategories,\n },\n extraMenuItems,\n );\n }),\n map((vars) => {\n return vars.filter((v) => {\n if (v?.settings?.requiredParams) {\n return v.settings.requiredParams.reduce((prev, curr, i, arr) => {\n // If there is a required parameter, get the value from the properties of this instance of\n // VariableMenuDialogComponent to see if it will be provided\n return prev && !!this[arr[i]];\n }, true);\n } else {\n return true;\n }\n });\n }),\n shareReplay(1),\n );\n\n constructor(\n private readonly variableMenuService: VariableMenuService,\n private readonly route: ActivatedRoute,\n private readonly cookieService: CookieService,\n ) {}\n\n private convertNonObservablesSubItemsToObservables(toConvert: VariableMenuItem[]): VariableMenuItem[] {\n return toConvert.map((item) => {\n item.subItems$ = of(this.convertNonObservablesSubItemsToObservables(item.subItems$ as any));\n return item;\n });\n }\n\n add(): void {\n const content = this.chosenVariableMenutItem?.settings?.shouldNotSurroundWithCurlyBraces\n ? this.chosenVariableMenutItem.replacementTag\n : '{{ ' + this.chosenVariableMenutItem.replacementTag + ' }}';\n if (this.emitEventsInsteadOfTakingAction) {\n this.formResult.emit(content);\n } else {\n window.parent.postMessage({\n mceAction: 'insertContent',\n content: content,\n });\n this.close();\n }\n }\n\n close(): void {\n if (this.emitEventsInsteadOfTakingAction) {\n this.formResult.emit(null);\n } else {\n window.parent.postMessage({ mceAction: 'close' });\n }\n }\n\n variableMenuItemSelected(variableMenuItem: VariableMenuItem): void {\n this.chosenVariableMenutItem = variableMenuItem;\n }\n\n protected readonly async = async;\n}\n","
\n
\n \n \n \n
\n
\n
\n \n \n
\n
\n
\n","import { Injectable } from '@angular/core';\nimport { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';\n// eslint-disable-next-line @nx/enforce-module-boundaries\nimport { InboxNavigationService } from '@galaxy/conversation/core';\n\n@Injectable()\nexport class InboxModalGuard {\n constructor(\n private router: Router,\n private inboxNav: InboxNavigationService,\n ) {}\n\n async canActivate(route: ActivatedRouteSnapshot, _state: RouterStateSnapshot): Promise {\n this.router.navigate(['dashboard']).then(() => this.inboxNav.gotoConversationID(route.params['id']));\n return false;\n }\n}\n","import { Injectable } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport { ApiService } from '../api-service/api.service';\nimport { PartnerMailingRequest } from './partner';\n\n@Injectable({ providedIn: 'root' })\nexport class CompanyProfileApiService {\n private updateUrl = `/api/v3/partner/updateMailingAddress/`;\n\n constructor(private apiService: ApiService) {}\n\n public updatePartnerMailingAddress(partner: PartnerMailingRequest): Observable {\n return this.apiService.post(this.updateUrl, partner);\n }\n}\n","import { Component, Inject, OnDestroy, OnInit } from '@angular/core';\nimport { UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';\nimport { TranslateService } from '@ngx-translate/core';\nimport { AddressAPIService } from '@vendasta/address';\nimport { SelectInputOptionInterface } from '@vendasta/galaxy/input';\nimport { SnackbarService } from '@vendasta/galaxy/snackbar-service';\nimport { BehaviorSubject, Observable, Subject, Subscription } from 'rxjs';\nimport {\n catchError,\n distinctUntilChanged,\n filter,\n map,\n publishReplay,\n refCount,\n switchMap,\n take,\n takeUntil,\n tap,\n} from 'rxjs/operators';\nimport { AppConfigService } from '../app-config.service';\nimport { PartnerService } from '../core/partner.service';\nimport { CompanyProfileService } from './company-profile.service';\nimport { PartnerMailingAddressResponse } from './partner';\n\n@Component({\n templateUrl: 'company-profile.component.html',\n styleUrls: ['company-profile.component.scss'],\n})\nexport class CompanyProfileComponent implements OnInit, OnDestroy {\n updateCompanyFormGroup: UntypedFormGroup;\n partnerId: string;\n hasMailingInformation = false;\n isUpdatingProfile = false;\n loading = true;\n private subscriptions: Subscription[] = [];\n partnerMailingAddressInfo$: Observable;\n partnerName: string;\n\n countryOptions$: Observable;\n stateProvOptions$$ = new BehaviorSubject([]);\n private readonly onDestroy = new Subject();\n\n constructor(\n @Inject('PARTNER_ID') private readonly partnerId$: Observable,\n private companyProfileService: CompanyProfileService,\n private translate: TranslateService,\n private snackbarService: SnackbarService,\n private partnerService: PartnerService,\n private readonly configService: AppConfigService,\n private readonly addressService: AddressAPIService,\n ) {}\n\n ngOnInit(): void {\n this.subscriptions.push(\n this.partnerId$\n .pipe(\n switchMap((pid) => {\n this.partnerId = pid;\n return this.partnerService.getPartnerByPartnerId(pid);\n }),\n )\n .subscribe((partner) => {\n this.partnerName = partner.name;\n this.companyProfileService.loadCompanyProfileData(this.partnerId);\n }),\n );\n\n this.partnerMailingAddressInfo$ = this.companyProfileService.partnerMailingInformation$.pipe(\n tap((partnerMailingAddress) => {\n this.setUpForm(partnerMailingAddress);\n }),\n );\n\n this.countryOptions$ = this.addressService.listAllCountryOptions().pipe(\n take(1),\n map((countries) => {\n if (!countries) {\n return [];\n }\n return countries.sort((a, b) => {\n const nameA = a.name.toUpperCase();\n const nameB = b.name.toUpperCase();\n if (nameA < nameB) {\n return -1;\n }\n if (nameA > nameB) {\n return 1;\n }\n return 0;\n });\n }),\n map((countries) =>\n countries.map((country) => ({\n value: country?.code || '',\n label: country?.name || '',\n })),\n ),\n publishReplay(1),\n refCount(),\n );\n }\n\n private updateStateProvWithCountry(state: string): void {\n this.updateCompanyFormGroup.controls.country.valueChanges\n .pipe(\n takeUntil(this.onDestroy),\n filter((country) => !!country),\n distinctUntilChanged(),\n tap((country) => this.setCountry(country, state)),\n )\n .subscribe();\n }\n\n private setCountry(country: string, state: string): void {\n this.addressService\n .getCountryConfiguration(country, undefined)\n .pipe(\n map((countryConfig) =>\n countryConfig?.zones?.map((zone) => ({\n value: zone?.code || '',\n label: zone?.name || '',\n })),\n ),\n catchError(() => []),\n tap((stateProvs: SelectInputOptionInterface[]) => this.stateProvOptions$$.next(stateProvs)),\n tap((stateProvs: SelectInputOptionInterface[]) => {\n if (!!stateProvs && stateProvs.findIndex((sp) => sp.value === state) > 0) {\n this.updateCompanyFormGroup.setControl('stateProv', new UntypedFormControl(state));\n } else {\n this.updateCompanyFormGroup.setControl('stateProv', new UntypedFormControl(null));\n }\n }),\n take(1),\n )\n .subscribe();\n }\n\n updateCompanyProfile(): void {\n if (this.updateCompanyFormGroup.invalid) {\n this.snackbarService.errorSnack(this.translate.instant('COMPANY_PROFILE.INVALID_FORM'));\n return;\n }\n\n if (this.updateCompanyFormGroup.valid) {\n this.partnerName = this.updateCompanyFormGroup.controls.company_name.value;\n\n this.isUpdatingProfile = true;\n\n const companyProfileFormValues = {\n partnerId: this.partnerId,\n mailingCompanyName: this.updateCompanyFormGroup.controls.company_name.value,\n mailingAddress: this.updateCompanyFormGroup.controls.address.value,\n mailingAddress2: this.updateCompanyFormGroup.controls.additionalAddressLine.value,\n mailingCity: this.updateCompanyFormGroup.controls.city.value,\n mailingState: this.updateCompanyFormGroup.controls.stateProv.value || '',\n mailingCountry: this.updateCompanyFormGroup.controls.country.value,\n mailingPostalCode: this.updateCompanyFormGroup.controls.postalCode.value,\n mailingPhoneNumber: this.updateCompanyFormGroup.controls.phone_number.value,\n mailingWebsiteAddress: this.updateCompanyFormGroup.controls.website_address.value,\n mailingEmailAddress: this.updateCompanyFormGroup.controls.email_address.value,\n };\n this.companyProfileService\n .updatePartnerMailingAddress(companyProfileFormValues)\n .pipe(take(1))\n .subscribe((success) => {\n if (success) {\n window.setTimeout(() => {\n this.companyProfileService.forceLoadCompanyProfileData(this.partnerId);\n this.configService.load(this.partnerId);\n this.isUpdatingProfile = false;\n this.snackbarService.successSnack(this.translate.instant('COMPANY_PROFILE.UPDATE_SUCCESS'));\n }, 3000);\n } else {\n this.snackbarService.errorSnack(this.translate.instant('COMPANY_PROFILE.UPDATE_ERROR'));\n }\n });\n }\n }\n\n ngOnDestroy(): void {\n this.subscriptions.forEach((subscription) => {\n subscription.unsubscribe();\n });\n this.onDestroy.complete();\n }\n\n setUpForm(partnerMailingAddress: PartnerMailingAddressResponse): void {\n this.updateCompanyFormGroup = new UntypedFormGroup({\n company_name: new UntypedFormControl(\n this.partnerName || this.configService.config.partnerName || '',\n Validators.required,\n ),\n phone_number: new UntypedFormControl(partnerMailingAddress?.mailing_phone_number || ''),\n website_address: new UntypedFormControl(partnerMailingAddress?.mailing_website_address || ''),\n email_address: new UntypedFormControl(partnerMailingAddress?.mailing_email_address || ''),\n country: new UntypedFormControl(partnerMailingAddress?.mailing_country || ''),\n address: new UntypedFormControl(partnerMailingAddress?.mailing_address || ''),\n additionalAddressLine: new UntypedFormControl(partnerMailingAddress?.mailing_address_2 || ''),\n city: new UntypedFormControl(partnerMailingAddress?.mailing_city || ''),\n postalCode: new UntypedFormControl(partnerMailingAddress?.mailing_postal_code || ''),\n });\n this.updateStateProvWithCountry(partnerMailingAddress?.mailing_state || '');\n }\n}\n","\n \n \n {{ 'COMPANY_PROFILE.TITLE' | translate }}\n \n \n \n \n \n
\n \n \n
\n \n \n \n \n \n
\n \n {{ 'COMPANY_PROFILE.ADDRESS_TITLE' | translate }}\n \n
\n 0\"\n [formControl]=\"updateCompanyFormGroup.controls['country']\"\n [label]=\"'COMMON.ADDRESS.COUNTRY'\"\n [options]=\"countryOptions$ | async\"\n [required]=\"true\"\n >\n \n \n 0\"\n [formControl]=\"updateCompanyFormGroup.controls['stateProv']\"\n [label]=\"'COMMON.ADDRESS.STATE_PROV'\"\n [options]=\"stateProvOptions$$ | async\"\n [required]=\"true\"\n >\n \n \n \n \n
\n \n
\n \n
\n
\n \n \n \n
\n
\n
\n","import { CommonModule } from '@angular/common';\nimport { NgModule } from '@angular/core';\nimport { ReactiveFormsModule } from '@angular/forms';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatCardModule } from '@angular/material/card';\nimport { MatCheckboxModule } from '@angular/material/checkbox';\nimport { MatOptionModule } from '@angular/material/core';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatInputModule } from '@angular/material/input';\nimport { MatProgressSpinnerModule } from '@angular/material/progress-spinner';\nimport { MatRadioModule } from '@angular/material/radio';\nimport { MatSelectModule } from '@angular/material/select';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { RouterModule } from '@angular/router';\nimport { LexiconModule } from '@galaxy/lexicon';\nimport { TranslateModule } from '@ngx-translate/core';\nimport { AddressFormModule } from '@vendasta/businesses';\nimport { GalaxyWrapModule } from '@vendasta/galaxy/galaxy-wrap';\nimport { GalaxyInputModule } from '@vendasta/galaxy/input';\nimport { GalaxyPageModule } from '@vendasta/galaxy/page';\nimport { WEBLATE_COMPONENT_NAME } from '@vendasta/store';\nimport baseTranslation from '../../assets/i18n/en_devel.json';\nimport { CompanyProfileApiService } from './company-profile-api.service';\nimport { CompanyProfileComponent } from './company-profile.component';\nimport { CompanyProfileService } from './company-profile.service';\n\n@NgModule({\n imports: [\n MatCardModule,\n MatInputModule,\n MatButtonModule,\n MatCheckboxModule,\n MatTooltipModule,\n CommonModule,\n ReactiveFormsModule,\n MatRadioModule,\n MatOptionModule,\n MatSelectModule,\n MatProgressSpinnerModule,\n MatIconModule,\n RouterModule,\n GalaxyPageModule,\n TranslateModule,\n LexiconModule.forChild({\n componentName: WEBLATE_COMPONENT_NAME,\n baseTranslation: baseTranslation,\n }),\n GalaxyWrapModule,\n AddressFormModule,\n GalaxyInputModule,\n ],\n exports: [CompanyProfileComponent],\n declarations: [CompanyProfileComponent],\n providers: [CompanyProfileService, CompanyProfileApiService],\n})\nexport class PartnerModule {}\n","import { Injectable } from '@angular/core';\nimport { Category, ExecutiveReportService, ReportConfig } from '@vendasta/executive-report';\nimport { SnackbarService } from '@vendasta/galaxy/snackbar-service';\nimport { BehaviorSubject, Observable, ReplaySubject } from 'rxjs';\nimport { PartnerService } from '../../core/partner.service';\n\n@Injectable({ providedIn: 'root' })\nexport class CustomizeExecReportService {\n private enabledCategories$$: ReplaySubject> = new ReplaySubject>(1);\n private isSavingCategories$$: BehaviorSubject = new BehaviorSubject(false);\n\n constructor(\n private execReportSDK: ExecutiveReportService,\n private snackbarService: SnackbarService,\n private partnerService: PartnerService,\n ) {}\n\n getEnabledExecReportCategories(partnerId: string, marketId: string): void {\n this.execReportSDK\n .getReportConfig(partnerId, marketId)\n .subscribe((data: ReportConfig) => this.enabledCategories$$.next(data.enabledCategories));\n }\n\n setConfigReportCategories(partnerId: string, marketId: string, newCategories: Array): void {\n this.isSavingCategories$$.next(true);\n const market = marketId ? marketId : 'default';\n\n if (this.userHasWritePermissions(marketId)) {\n const config = new ReportConfig({ enabledCategories: newCategories });\n this.execReportSDK.saveReportConfig(partnerId, marketId, config).subscribe(\n () => {\n this.enabledCategories$$.next(newCategories);\n this.snackbarService.successSnack(`Applied changes to ${market} market`);\n },\n () => {\n this.isSavingCategories$$.next(false);\n this.snackbarService.errorSnack(`Failed to set configuration for ${market} market`);\n },\n () => this.isSavingCategories$$.next(false),\n );\n } else {\n this.isSavingCategories$$.next(false);\n this.snackbarService.errorSnack(`You do not have the permissions to configure ${market} market`);\n }\n }\n\n get enabledCategories$(): Observable> {\n return this.enabledCategories$$.asObservable();\n }\n\n get isSavingCategories$(): Observable {\n return this.isSavingCategories$$.asObservable();\n }\n\n private userHasWritePermissions(marketId: string): boolean {\n if (!this.partnerService.CanCustomizeWhitelabel) {\n return false;\n }\n\n return marketId && this.partnerService.MarketAccess.length > 0\n ? this.partnerService.MarketAccess.some((id) => id === marketId)\n : true;\n }\n}\n","import { Component, Inject, OnInit } from '@angular/core';\nimport { ActivatedRoute, Params } from '@angular/router';\nimport { Category } from '@vendasta/executive-report';\nimport { Breadcrumbs } from '@vendasta/uikit';\nimport { combineLatest, Observable } from 'rxjs';\nimport { map } from 'rxjs/operators';\nimport { PartnerService } from '../../core/partner.service';\nimport { CustomizeExecReportService } from './customize-exec-report.service';\n\n@Component({\n selector: 'app-customize-exec-report',\n templateUrl: './customize-exec-report.component.html',\n styleUrls: ['./customize-exec-report.component.scss'],\n})\nexport class CustomizeExecReportComponent implements OnInit {\n navSectionElement: any;\n partnerId: string;\n marketId: string;\n categoryOrder$: Observable;\n isReordering$: Observable = new Observable(null);\n breadcrumbs: Breadcrumbs[];\n categoriesEnum = Category;\n\n constructor(\n private execReportService: CustomizeExecReportService,\n private partnerService: PartnerService,\n @Inject('PARTNER_ID') private readonly partnerId$: Observable,\n private route: ActivatedRoute,\n ) {}\n\n ngOnInit(): void {\n combineLatest([this.partnerId$, this.route.params])\n .pipe(\n map(([partnerId, params]: [string, Params]) => {\n this.marketId = params.marketId;\n this.execReportService.getEnabledExecReportCategories(partnerId, params.marketId);\n }),\n )\n .subscribe();\n\n this.partnerId = this.partnerService.partnerId;\n this.categoryOrder$ = this.execReportService.enabledCategories$;\n this.isReordering$ = this.execReportService.isSavingCategories$;\n this.breadcrumbs = this.buildBreadcrumbs();\n }\n\n private buildBreadcrumbs(): Breadcrumbs[] {\n let baseUrl = '/customize-design';\n let baseBack2Message = 'Back to Customize Settings';\n if (this.marketId) {\n baseUrl += `/markets/${this.marketId}`;\n baseBack2Message += ` (${this.marketId})`;\n }\n return [{ url: baseUrl, text: baseBack2Message }, { text: 'Executive Report' }];\n }\n\n isBefore(a: any, b: any): boolean {\n if (a.parentNode === b.parentNode) {\n for (let cur = a; cur; cur = cur.previousSibling) {\n if (cur === b) {\n return true;\n }\n }\n }\n return false;\n }\n\n dragEnter($event: any): void {\n const target: any = $event.currentTarget;\n if (this.isBefore(this.navSectionElement, target)) {\n target.parentNode.insertBefore(this.navSectionElement, target); // insert before\n } else {\n target.parentNode.insertBefore(this.navSectionElement, target.nextSibling); //insert after\n }\n }\n\n dragStart($event: any): void {\n this.navSectionElement = $event.currentTarget;\n $event.dataTransfer.effectAllowed = 'move';\n }\n\n dragEnd($event: any): void {\n const target: any = $event.currentTarget;\n const elements: any = Array.from(target.parentNode.childNodes);\n const firstLevelChildren = elements.filter((child: any) => child.nodeType === 1);\n const categories: Category[] = firstLevelChildren.map((x: any) => +x.dataset.category); // unary op: str to int\n this.execReportService.setConfigReportCategories(this.partnerId, this.marketId, categories);\n }\n}\n","\n
\n \n \n \n \n \n drag_handle\n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.LISTINGS' | translate }}\n \n \n \n \n \n drag_handle\n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.REPUTATION' | translate }}\n \n \n \n \n \n drag_handle\n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.WEBSITE' | translate }}\n \n \n \n \n \n drag_handle\n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.SOCIAL' | translate }}\n \n \n \n \n \n drag_handle\n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.ADVERTISING' | translate }}\n \n \n \n \n \n drag_handle\n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.SEO' | translate }}\n \n \n \n \n \n drag_handle\n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.CONTENT_AND_EXPERIENCE' | translate }}\n \n \n \n \n \n\n
\n \n \n \n \n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.LISTINGS' | translate }}\n \n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.LISTINGS_DESCRIPTION' | translate }}\n \n \n \n \n \n \n \n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.REPUTATION' | translate }}\n \n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.REPUTATION_DESCRIPTION' | translate }}\n \n \n \n \n \n \n \n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.WEBSITE' | translate }}\n \n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.WEBSITE_DESCRIPTION' | translate }}\n \n \n \n \n \n \n \n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.SOCIAL' | translate }}\n \n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.SOCIAL_DESCRIPTION' | translate }}\n \n \n \n \n \n \n \n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.ADVERTISING' | translate }}\n \n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.ADVERTISING_DESCRIPTION' | translate }}\n \n \n \n \n \n \n \n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.SEO' | translate }}\n \n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.SEO_DESCRIPTION' | translate }}\n \n \n \n \n \n \n \n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.CONTENT_AND_EXPERIENCE' | translate }}\n \n \n {{ 'ADMINISTRATION.EXECUTIVE_REPORT.CONTENT_AND_EXPERIENCE_DESCRIPTION' | translate }}\n \n \n \n \n \n
\n
\n\n \n \n \n
\n","import { Inject, Injectable, OnDestroy } from '@angular/core';\nimport { BrandingAppInterface, BrandingV2Interface, BrandingV2Service, UITheme } from '@galaxy/partner';\nimport { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs';\nimport { distinctUntilChanged, filter, map, publishReplay, refCount, switchMap } from 'rxjs/operators';\nimport { Market } from './markets/market';\nimport { MarketsService } from './markets/markets.service';\n\n// BrandingAndApps combines v1 and v2 branding, where `apps` is from v1\nexport interface BrandingAndApps {\n faviconUrl?: string;\n shortcutIconUrl?: string;\n logoUrl?: string;\n uiTheme?: UITheme;\n primaryColor?: string;\n name?: string;\n apps?: {\n [key: string]: BrandingAppInterface;\n };\n}\n\n// uiThemeToEnum converts legacy string theme to brandingV2 enum\nexport function uiThemeToEnum(uiTheme: string): UITheme {\n if (uiTheme === 'light') {\n return UITheme.UI_THEME_LIGHT;\n }\n return UITheme.UI_THEME_DARK;\n}\n\n// uiThemeFromEnum converts brandingV2 enum to legacy string theme\nexport function uiThemeFromEnum(uiTheme: UITheme): string {\n if (uiTheme === UITheme.UI_THEME_LIGHT) {\n return 'light';\n }\n return 'dark';\n}\n\n/*\n UserBrandingService contains the branding information for the current user based on the selectedMarket.\n This changes the logo and UiTheme shown in Partner Center depending on the market the user has access to, etc.\n*/\n\n@Injectable({ providedIn: 'root' })\nexport class UserBrandingService implements OnDestroy {\n private branding$$: BehaviorSubject = new BehaviorSubject(null);\n public branding$: Observable = this.branding$$.asObservable().pipe(\n filter((b) => !!b),\n publishReplay(1),\n refCount(),\n );\n\n private readonly subscription: Subscription;\n\n constructor(\n @Inject('PARTNER_ID') private partnerId$: Observable,\n private marketsService: MarketsService,\n private brandingV2Service: BrandingV2Service,\n ) {\n const selectedMarket$: Observable = this.marketsService.markets$\n .pipe(map((markets) => (markets.length === 1 ? markets[0] : null)))\n .pipe(distinctUntilChanged());\n\n this.subscription = combineLatest([this.partnerId$, selectedMarket$])\n .pipe(switchMap(([partnerId, market]) => this.brandingV2Service.getBranding(partnerId, market?.market_id)))\n .subscribe((branding) => this.branding$$.next(branding));\n }\n\n public setLogoUrl(logoUrl: string): void {\n if (logoUrl?.endsWith('=s58')) {\n // Uploading logo via AA returns with sizing config appended to url. Remove it as it makes it look small.\n logoUrl = logoUrl.replace('=s58', '');\n }\n this.branding$$.next({ ...this.branding$$.getValue(), logoUrl: logoUrl });\n }\n\n public setUiTheme(uiTheme: UITheme): void {\n this.branding$$.next({ ...this.branding$$.getValue(), uiTheme: uiTheme });\n }\n\n ngOnDestroy(): void {\n if (this.subscription) {\n this.subscription.unsubscribe();\n }\n }\n}\n","import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';\nimport { Injectable } from '@angular/core';\nimport { Observable } from 'rxjs';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class CustomizeApiService {\n constructor(private api: HttpClient) {}\n\n setPrimaryColor(color: string, uiTheme: string): Observable {\n const url = '/customize-design/set-primary-color/';\n const body = new HttpParams().set('primary_color', color).set('ui_theme', uiTheme);\n\n return this.api.post(url, body.toString(), {\n withCredentials: true,\n responseType: 'json',\n headers: new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' }),\n });\n }\n\n getUploadUrl(): Observable {\n const url = '/customize-design/generate-upload-url/';\n\n // This endpoint just writes the string to the response, so have to accept text here.\n return this.api.get(url, { responseType: 'text' });\n }\n\n deleteResource(partnerId: string, category: string): Observable {\n const url = `/_res/delete/${partnerId}/${category}/`;\n\n return this.api.post(url, null);\n }\n\n saveProductNames(businessCenterName = '', nationalBrandsName = ''): Observable {\n const url = `/customize-design/product-names/`;\n const body = new HttpParams()\n .set('vbc_product_name_form-product_id', 'VBC')\n .set('vbc_product_name_form-product_name', businessCenterName)\n .set('nb_product_name_form-product_id', 'NB')\n .set('nb_product_name_form-product_name', nationalBrandsName)\n .set('business_directory_product_name_form-product_id', 'BD');\n\n return this.api.post(url, body.toString(), {\n headers: new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' }),\n });\n }\n\n saveExitLink(linkText: string, customUrl: string, logoutUrl: string, selectedLink: string): Observable {\n const url = `/customize-design/exit-link/`;\n const body = new HttpParams()\n .set('exit_link_text', linkText)\n .set('exit_link_url', customUrl)\n .set('logout_link', logoutUrl)\n .set('customize_url_flag', selectedLink);\n\n return this.api.post(url, body.toString(), {\n headers: new HttpHeaders({ 'Content-Type': 'application/x-www-form-urlencoded' }),\n });\n }\n}\n","import { Component, Input, OnInit } from '@angular/core';\nimport { UntypedFormBuilder, Validators } from '@angular/forms';\nimport { UITheme } from '@galaxy/partner';\nimport { TranslateService } from '@ngx-translate/core';\nimport { SnackbarService } from '@vendasta/galaxy/snackbar-service';\nimport { uiThemeFromEnum, uiThemeToEnum, UserBrandingService } from '../../../../core/user-branding.service';\nimport { CustomizeApiService } from '../customize-api.service';\n\n@Component({\n selector: 'app-brand-color',\n templateUrl: './brand-color.component.html',\n styleUrls: ['./brand-color.component.scss'],\n})\nexport class BrandColorComponent implements OnInit {\n brandingForm = this.formBuilder.group({\n brandColor: ['#', Validators.pattern(/^[#]\\S+/)],\n uiTheme: [0],\n });\n\n @Input()\n uiTheme: UITheme;\n\n @Input()\n primaryColor: string;\n\n constructor(\n private formBuilder: UntypedFormBuilder,\n private customizeApiService: CustomizeApiService,\n private userBrandingService: UserBrandingService,\n private snackbarService: SnackbarService,\n private translations: TranslateService,\n ) {}\n\n ngOnInit(): void {\n this.brandingForm.patchValue({\n brandColor: '#' + this.primaryColor,\n uiTheme: uiThemeFromEnum(this.uiTheme),\n });\n }\n\n submitForm(): void {\n const color = this.brandingForm.value.brandColor.slice(1);\n const theme = this.brandingForm.value.uiTheme === 1 ? 'light' : 'dark';\n this.customizeApiService.setPrimaryColor(color, theme).subscribe(\n () => {\n this.userBrandingService.setUiTheme(uiThemeToEnum(theme));\n this.snackbarService.successSnack(this.translations.instant('CUSTOMIZE_PARTNER.COLOR.FORM_SUCCESS'));\n },\n (err) => {\n console.error(err);\n // raise snack alert\n let message;\n if (err.status === 500) {\n message = this.translations.instant('CUSTOMIZE_PARTNER.COLOR.FORM_ERROR_UNKNOWN');\n }\n this.snackbarService.errorSnack(message);\n },\n );\n }\n}\n","
\n
\n
\n \n \n \n {{ 'CUSTOMIZE_PARTNER.COLOR.MISSING_HASH_ERROR' | translate }}\n \n \n \n
\n \n \n {{ 'CUSTOMIZE_PARTNER.COLOR.THEME_FIELD_TITLE' | translate }}\n \n \n \n {{ 'CUSTOMIZE_PARTNER.COLOR.THEME_DARK' | translate }}\n \n \n {{ 'CUSTOMIZE_PARTNER.COLOR.THEME_LIGHT' | translate }}\n \n \n \n
\n\n \n
\n","import { HttpClient } from '@angular/common/http';\nimport { Injectable } from '@angular/core';\nimport { FileUploaderInterface, FileUploadInfo } from '@vendasta/forms';\nimport { Observable } from 'rxjs';\nimport { map } from 'rxjs/operators';\n\n/**\n * CustomizeApiFileUploaderService\n *\n * This is a service specifically for uploading files to the blobstore upload handler in AA. It sets a pid and category\n * on each file uploaded so that they can be attached to that partner/market. Make sure to call setUploadParams before\n * uploading a file.\n */\n@Injectable()\nexport class CustomizeApiFileUploaderService implements FileUploaderInterface {\n url: string;\n partnerId: string;\n category: string;\n\n constructor(private http: HttpClient) {}\n\n setUploadParams(url: string, partnerId: string, category: string): void {\n this.url = url;\n this.partnerId = partnerId;\n this.category = category;\n }\n\n uploadFile(file: File): Observable {\n const body = new FormData();\n body.append('file', file);\n body.append('pid', this.partnerId);\n body.append('category', this.category);\n return this.http.post(this.url, body, { withCredentials: true, responseType: 'text' }).pipe(\n map((url) => ({\n url,\n name: this.category,\n })),\n );\n }\n}\n","import { Component, Input, OnInit } from '@angular/core';\nimport { UntypedFormControl } from '@angular/forms';\nimport { TranslateService } from '@ngx-translate/core';\nimport { SnackbarService } from '@vendasta/galaxy/snackbar-service';\nimport { Observable } from 'rxjs';\nimport { tap } from 'rxjs/operators';\nimport { CustomizeApiFileUploaderService } from '../customize-api-file-uploader.service';\nimport { CustomizeApiService } from '../customize-api.service';\n\n@Component({\n selector: 'app-customize-image-upload',\n templateUrl: './customize-image-upload.component.html',\n styleUrls: ['./customize-image-upload.component.scss'],\n // Provide a copy of this service to each component that gets instantiated.\n // This way it can set upload params per component.\n providers: [CustomizeApiFileUploaderService],\n})\nexport class CustomizeImageUploadComponent implements OnInit {\n uploadUrl$: Observable;\n\n @Input()\n currentImageUrl: string;\n @Input()\n partnerId: string;\n @Input()\n category: string;\n\n imageUrl = new UntypedFormControl('');\n\n constructor(\n private customizeApi: CustomizeApiService,\n public customizeFileUploader: CustomizeApiFileUploaderService,\n private snackbarService: SnackbarService,\n private translateService: TranslateService,\n ) {}\n\n ngOnInit(): void {\n this.uploadUrl$ = this.customizeApi\n .getUploadUrl()\n .pipe(tap((url) => this.customizeFileUploader.setUploadParams(url, this.partnerId, this.category)));\n if (this.currentImageUrl) {\n this.imageUrl.patchValue(this.currentImageUrl);\n }\n this.imageUrl.valueChanges.subscribe(console.log);\n }\n\n deleteImage(): void {\n // If blob is deleted, clear the input so they can upload a new image.\n this.customizeApi.deleteResource(this.partnerId, this.category).subscribe(\n () => {\n this.imageUrl.patchValue('');\n this.snackbarService.successSnack(\n this.translateService.instant('CUSTOMIZE_PARTNER.FILE_UPLOADS.SUBMIT_MESSAGES.DELETE_SUCCESS'),\n );\n },\n (err) => {\n console.error(err);\n this.snackbarService.errorSnack(\n this.translateService.instant('CUSTOMIZE_PARTNER.FILE_UPLOADS.SUBMIT_MESSAGES.DELETE_FAILURE'),\n );\n },\n );\n }\n}\n","\n\n\n\n {{ 'COMMON.ACTION_LABELS.DELETE' | translate }}\n\n","import { Component, Input, OnInit } from '@angular/core';\nimport { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';\nimport { BrandingAppInterface } from '@galaxy/partner';\nimport { TranslateService } from '@ngx-translate/core';\nimport { SnackbarService } from '@vendasta/galaxy/snackbar-service';\nimport { CustomizeApiService } from '../customize-api.service';\n\n@Component({\n selector: 'app-product-names',\n templateUrl: './product-names.component.html',\n styleUrls: ['./product-names.component.scss'],\n})\nexport class ProductNamesComponent implements OnInit {\n @Input()\n appNames: {\n [key: string]: BrandingAppInterface;\n };\n\n namesGroup: UntypedFormGroup;\n\n constructor(\n private customizeApi: CustomizeApiService,\n private formBuilder: UntypedFormBuilder,\n private snackbarService: SnackbarService,\n private translations: TranslateService,\n ) {}\n\n ngOnInit(): void {\n // Set them to empty string if they are the default name already.\n this.namesGroup = this.formBuilder.group({\n bcName: [this.appNames.VBC.name === 'Business App' ? '' : this.appNames.VBC.name],\n nbName: [this.appNames.NB.name === 'Brand Analytics' ? '' : this.appNames.NB.name],\n });\n }\n\n saveNames(): void {\n this.customizeApi\n .saveProductNames(this.namesGroup.get('bcName').value, this.namesGroup.get('nbName').value)\n .subscribe(\n () =>\n this.snackbarService.successSnack(this.translations.instant('CUSTOMIZE_PARTNER.PRODUCT_NAMES.FORM_SUCCESS')),\n (err) => {\n console.error(err);\n this.snackbarService.errorSnack(this.translations.instant('CUSTOMIZE_PARTNER.PRODUCT_NAMES.FORM_FAILURE'));\n },\n );\n }\n\n restoreDefault(): void {\n if (!confirm(this.translations.instant('CUSTOMIZE_PARTNER.SHARED.RESTORE_DEFAULT_CONFIRMATION'))) {\n return;\n }\n this.namesGroup.patchValue({\n bcName: '',\n nbName: '',\n });\n this.saveNames();\n }\n}\n","
\n {{ 'CUSTOMIZE_PARTNER.PRODUCT_NAMES.WARNING_MESSAGE' | translate }}\n \n {{ 'CUSTOMIZE_PARTNER.PRODUCT_NAMES.WARNING_LINK_MESSAGE' | translate }}\n \n .\n
\n\n
\n
\n \n \n
\n \n \n
\n","import { Component, OnInit } from '@angular/core';\nimport { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';\nimport { TranslateService } from '@ngx-translate/core';\nimport { SnackbarService } from '@vendasta/galaxy/snackbar-service';\nimport { CustomizeApiService } from '../customize-api.service';\n\n@Component({\n selector: 'app-exit-link',\n templateUrl: './exit-link.component.html',\n styleUrls: ['./exit-link.component.scss'],\n})\nexport class ExitLinkComponent implements OnInit {\n exitLinkGroup: UntypedFormGroup;\n\n constructor(\n private customizeApi: CustomizeApiService,\n private formBuilder: UntypedFormBuilder,\n private snackbarService: SnackbarService,\n private translations: TranslateService,\n ) {}\n\n ngOnInit(): void {\n this.exitLinkGroup = this.formBuilder.group({\n linkText: '',\n customUrl: '',\n logoutUrl: '',\n selectedLink: 'default',\n });\n }\n\n save(): void {\n this.customizeApi\n .saveExitLink(\n this.exitLinkGroup.get(['linkText']).value,\n this.exitLinkGroup.get(['customUrl']).value,\n this.exitLinkGroup.get(['logoutUrl']).value,\n this.exitLinkGroup.get(['selectedLink']).value,\n )\n .subscribe(\n () => this.snackbarService.successSnack(this.translations.instant('CUSTOMIZE_PARTNER.EXIT_LINK.FORM_SUCCESS')),\n (err) => {\n console.error(err);\n this.snackbarService.errorSnack(this.translations.instant('CUSTOMIZE_PARTNER.EXIT_LINK.FORM_FAILURE'));\n },\n );\n }\n\n restoreDefault(): void {\n if (!confirm(this.translations.instant('CUSTOMIZE_PARTNER.SHARED.RESTORE_DEFAULT_CONFIRMATION'))) {\n return;\n }\n }\n}\n","