@veloceapps/sdk 3.1.17-1 → 3.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -6
- package/bundles/veloce-sdk-core.umd.js +68 -212
- package/bundles/veloce-sdk-core.umd.js.map +1 -1
- package/bundles/veloce-sdk-runtime.umd.js +6 -5
- package/bundles/veloce-sdk-runtime.umd.js.map +1 -1
- package/bundles/veloce-sdk.umd.js +35 -42
- package/bundles/veloce-sdk.umd.js.map +1 -1
- package/core/modules/flow-configuration/services/flow-configuration.service.d.ts +17 -11
- package/core/services/quote-draft.service.d.ts +7 -41
- package/esm2015/core/modules/configuration/services/configuration.service.js +3 -3
- package/esm2015/core/modules/flow-configuration/services/flow-configuration.service.js +49 -43
- package/esm2015/core/services/quote-draft.service.js +22 -138
- package/esm2015/runtime/components/ui-runtime/runtime.component.js +2 -2
- package/esm2015/runtime/execution/directives/section-script.directive.js +2 -2
- package/esm2015/runtime/services/cart.service.js +3 -2
- package/esm2015/runtime/services/section.service.js +1 -1
- package/esm2015/src/components/header/header.component.js +19 -23
- package/esm2015/src/components/header/header.types.js +1 -1
- package/esm2015/src/pages/legacy-product/legacy-product.component.js +4 -4
- package/esm2015/src/pages/product/product.component.js +5 -8
- package/esm2015/src/resolvers/quote.resolver.js +11 -4
- package/esm2015/src/services/flow.service.js +5 -6
- package/fesm2015/veloce-sdk-core.js +66 -177
- package/fesm2015/veloce-sdk-core.js.map +1 -1
- package/fesm2015/veloce-sdk-runtime.js +4 -3
- package/fesm2015/veloce-sdk-runtime.js.map +1 -1
- package/fesm2015/veloce-sdk.js +36 -38
- package/fesm2015/veloce-sdk.js.map +1 -1
- package/package.json +1 -1
- package/runtime/services/cart.service.d.ts +1 -1
- package/src/components/header/header.component.d.ts +2 -5
- package/src/components/header/header.types.d.ts +1 -0
- package/src/pages/product/product.component.d.ts +0 -1
- package/src/resolvers/quote.resolver.d.ts +1 -0
package/fesm2015/veloce-sdk.js
CHANGED
@@ -406,8 +406,6 @@ class FlowHeaderComponent {
|
|
406
406
|
this.mode = ctx.mode;
|
407
407
|
this.objectName = ctx.mode.toLowerCase();
|
408
408
|
this.contextProperties = ctx.properties;
|
409
|
-
this.assetPriceLists = this.quoteDraftService.assetPriceLists;
|
410
|
-
this.activePriceList$ = this.quoteDraftService.activePriceList$;
|
411
409
|
this.status$ = this.contextService.resolve$().pipe(map(context => { var _a; return (_a = context.properties.Status) !== null && _a !== void 0 ? _a : ''; }));
|
412
410
|
this.isEditMode$ = this.quoteDraftService.isEditMode$();
|
413
411
|
this.products$ = this.flowConfiguration.get().pipe(map(lineItems => this.generateProducts(lineItems)));
|
@@ -428,10 +426,10 @@ class FlowHeaderComponent {
|
|
428
426
|
get isQuoteMode() {
|
429
427
|
return this.mode === ConfigurationContextMode.QUOTE;
|
430
428
|
}
|
431
|
-
back(
|
432
|
-
const
|
433
|
-
if (
|
434
|
-
window.VELO_BACK_FN.apply(null, [
|
429
|
+
back() {
|
430
|
+
const objectId = this.contextService.resolve().headerId;
|
431
|
+
if (objectId) {
|
432
|
+
window.VELO_BACK_FN.apply(null, [objectId]);
|
435
433
|
}
|
436
434
|
}
|
437
435
|
getSalesforceObjectLink(objectId) {
|
@@ -465,16 +463,18 @@ class FlowHeaderComponent {
|
|
465
463
|
this.dialogService.showEmptyCartDialog().subscribe();
|
466
464
|
return;
|
467
465
|
}
|
468
|
-
const quoteDraft = this.quoteDraftService.
|
466
|
+
const quoteDraft = this.quoteDraftService.quoteSnapshot;
|
469
467
|
if (!quoteDraft) {
|
470
468
|
return;
|
471
469
|
}
|
472
470
|
this.isSaveInProgress$.next(true);
|
473
471
|
this.quoteApiService
|
474
472
|
.upsertQuote(quoteDraft)
|
475
|
-
.pipe(tap((
|
476
|
-
|
477
|
-
this.
|
473
|
+
.pipe(tap(() => {
|
474
|
+
// navigate back to quote on successful save
|
475
|
+
if (this.mode === ConfigurationContextMode.QUOTE) {
|
476
|
+
this.back();
|
477
|
+
}
|
478
478
|
}), finalize(() => this.isSaveInProgress$.next(false)))
|
479
479
|
.subscribe();
|
480
480
|
}
|
@@ -487,22 +487,16 @@ class FlowHeaderComponent {
|
|
487
487
|
this.dialogService.showAccountSubmitFailureDialog();
|
488
488
|
return;
|
489
489
|
}
|
490
|
-
const quoteDraft = this.quoteDraftService.
|
490
|
+
const quoteDraft = this.quoteDraftService.quoteSnapshot;
|
491
491
|
if (!quoteDraft) {
|
492
492
|
return;
|
493
493
|
}
|
494
494
|
this.isSubmitInProgress$.next(true);
|
495
495
|
this.quoteApiService
|
496
496
|
.submitQuote(quoteDraft)
|
497
|
-
.pipe(switchMap(() => this.quoteApiService.getQuoteDraft(quoteDraft.quoteId)), tap(updatedQuoteDraft => {
|
498
|
-
this.contextService.update({ properties: updatedQuoteDraft.context.properties });
|
499
|
-
this.quoteDraftService.hasUnsavedChanges = false;
|
500
|
-
}), finalize(() => this.isSubmitInProgress$.next(false)), takeUntil(this.destroyed$))
|
497
|
+
.pipe(switchMap(() => this.quoteApiService.getQuoteDraft(quoteDraft.quoteId)), tap(updatedQuoteDraft => this.contextService.update({ properties: updatedQuoteDraft.context.properties })), finalize(() => this.isSubmitInProgress$.next(false)), takeUntil(this.destroyed$))
|
501
498
|
.subscribe();
|
502
499
|
}
|
503
|
-
selectPriceList(priceListId) {
|
504
|
-
this.quoteDraftService.updateActivePriceList(priceListId);
|
505
|
-
}
|
506
500
|
queryName$(objectName, id) {
|
507
501
|
if (!id) {
|
508
502
|
return of('');
|
@@ -515,17 +509,19 @@ class FlowHeaderComponent {
|
|
515
509
|
return this.sfApiService.query(searchRequest, objectName).pipe(map(result => { var _a, _b; return (_b = (_a = result[0]) === null || _a === void 0 ? void 0 : _a.Name) !== null && _b !== void 0 ? _b : ''; }), takeUntil(this.destroyed$));
|
516
510
|
}
|
517
511
|
populateObjectDetails() {
|
518
|
-
var _a;
|
512
|
+
var _a, _b;
|
519
513
|
const accountId = this.isAccountMode ? this.contextProperties.Id : this.contextProperties.AccountId;
|
520
514
|
const opportunityId = this.contextProperties.OpportunityId;
|
521
515
|
const quoteId = this.isQuoteMode ? this.contextProperties.Id : undefined;
|
522
516
|
const quoteName = this.isQuoteMode ? this.contextProperties.Name : undefined;
|
523
517
|
const quoteNumber = this.isQuoteMode ? (_a = this.contextProperties.QuoteNumber) === null || _a === void 0 ? void 0 : _a.replace(/^0+/, '') : undefined;
|
518
|
+
const priceListName = (_b = this.quoteDraftService.quotePriceList) === null || _b === void 0 ? void 0 : _b.name;
|
524
519
|
this.objectDetails$.next(Object.assign(Object.assign({}, this.objectDetails$.value), { accountId,
|
525
520
|
opportunityId,
|
526
521
|
quoteId,
|
527
522
|
quoteName,
|
528
|
-
quoteNumber
|
523
|
+
quoteNumber,
|
524
|
+
priceListName }));
|
529
525
|
this.queryName$('Account', accountId).subscribe(accountName => this.objectDetails$.next(Object.assign(Object.assign({}, this.objectDetails$.value), { accountName })));
|
530
526
|
this.queryName$('Opportunity', opportunityId).subscribe(opportunityName => this.objectDetails$.next(Object.assign(Object.assign({}, this.objectDetails$.value), { opportunityName })));
|
531
527
|
}
|
@@ -562,7 +558,7 @@ class FlowHeaderComponent {
|
|
562
558
|
}
|
563
559
|
}
|
564
560
|
FlowHeaderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: FlowHeaderComponent, deps: [{ token: i2$1.ContextService }, { token: i2$1.QuoteDraftService }, { token: i1$2.QuoteApiService }, { token: i1$2.SalesforceApiService }, { token: i2$1.FlowConfigurationService }, { token: FlowRouterService }, { token: FlowDialogService }], target: i0.ɵɵFactoryTarget.Component });
|
565
|
-
FlowHeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.15", type: FlowHeaderComponent, selector: "vl-flow-header", ngImport: i0, template: "<div class=\"flow-info\" *vlLet=\"objectDetails$ | async as details\">\n <nav class=\"nav-item nav-back\" (click)=\"back()\">\n <i class=\"nav-icon vl-icon vl-icon-arrow-left\"></i>\n\n <span> Back </span>\n <span *ngIf=\"objectName\" class=\"object-name\"> To {{ objectName }}</span>\n </nav>\n\n <ng-container *ngIf=\"isAccountMode\">\n <span class=\"dot-separator\"></span>\n\n <span>Account name</span>\n\n <nav class=\"account-name\" [pTooltip]=\"contextProperties.Name ?? ''\" tooltipPosition=\"bottom\" [showDelay]=\"1000\">\n <a target=\"_blank\" [href]=\"getSalesforceObjectLink(contextProperties.Id)\">{{ contextProperties.Name }}</a>\n </nav>\n </ng-container>\n\n <ng-container *ngIf=\"isQuoteMode\">\n <span class=\"dot-separator\"></span>\n\n <span>Quote #{{ details.quoteNumber }}</span>\n\n <span class=\"dot-separator\"></span>\n\n <nav class=\"nav-item\" (click)=\"quoteDetails.toggle($event)\">\n <span>{{ status$ | async }}</span>\n\n <i *ngIf=\"!quoteDetails.overlayVisible\" class=\"vl-icon vl-icon-chevron-down icon-with-margin\"></i>\n <i *ngIf=\"quoteDetails.overlayVisible\" class=\"vl-icon vl-icon-chevron-up icon-with-margin\"></i>\n </nav>\n\n <p-overlayPanel styleClass=\"navigation-settings-overlay flow-header-overlay center\" #quoteDetails>\n <ng-template pTemplate>\n <div class=\"flow-header-overlay__wrapper\">\n <h2 class=\"flow-header-overlay__title\">\n <span>Quote Information</span>\n <i class=\"vl-icon vl-icon-close close-icon\" (click)=\"quoteDetails.hide()\"></i>\n </h2>\n\n <ul class=\"info-list\">\n <li class=\"info-list__row\">\n <span>Account Name:</span>\n <a target=\"_blank\" [href]=\"getSalesforceObjectLink(details.accountId)\">{{ details.accountName }}</a>\n </li>\n <li class=\"info-list__row\">\n <span>Opportunity Name:</span>\n <a target=\"_blank\" [href]=\"getSalesforceObjectLink(details.opportunityId)\">{{\n details.opportunityName\n }}</a>\n </li>\n <li class=\"info-list__row\">\n <span>Quote Name:</span>\n <a target=\"_blank\" [href]=\"getSalesforceObjectLink(details.quoteId)\">{{ details.quoteName }}</a>\n </li>\n </ul>\n </div>\n </ng-template>\n </p-overlayPanel>\n </ng-container>\n</div>\n\n<div class=\"flow-navigation\">\n <nav class=\"nav-item\" [ngClass]=\"{ active: isCatalogRoute$ | async }\" (click)=\"navigateToCatalog()\">Catalog</nav>\n <nav class=\"nav-item disabled\" [ngClass]=\"{ active: isConfigurationRoute$ | async }\">Configurator</nav>\n <ng-container *vlLet=\"products$ | async as products\">\n <nav class=\"nav-item\" [ngClass]=\"{ active: isCartRoute$ | async }\" (click)=\"navigateToShoppingCart()\">\n Shopping Cart ({{ products.length }})\n </nav>\n\n <nav class=\"nav-popover-toggle active\" (click)=\"cart?.overlayPanel?.toggle($event)\">\n <i *ngIf=\"!cart?.overlayPanel?.overlayVisible\" class=\"vl-icon vl-icon-chevron-down icon-with-margin\"></i>\n <i *ngIf=\"cart?.overlayPanel?.overlayVisible\" class=\"vl-icon vl-icon-chevron-up icon-with-margin\"></i>\n </nav>\n\n <vl-cart-preview #cart [products]=\"products\"></vl-cart-preview>\n </ng-container>\n</div>\n\n<div class=\"flow-controls\" *vlLet=\"objectDetails$ | async as details\">\n <ng-container *vlLet=\"activePriceList$ | async as priceList\">\n <ng-container *ngIf=\"isAccountMode ?? assetPriceLists.length > 1\">\n <nav class=\"nav-item\" (click)=\"priceListsOverlay?.toggle($event)\">\n <span>{{ priceList.name }}</span>\n <i *ngIf=\"!priceListsOverlay?.overlayVisible\" class=\"vl-icon vl-icon-chevron-down icon-with-margin\"></i>\n <i *ngIf=\"priceListsOverlay?.overlayVisible\" class=\"vl-icon vl-icon-chevron-up icon-with-margin\"></i>\n </nav>\n\n <p-overlayPanel styleClass=\"price-list-overlay\" #priceListsOverlay>\n <ng-template pTemplate>\n <span\n *ngFor=\"let option of assetPriceLists\"\n class=\"price-list-option\"\n [class.active]=\"priceList.id === option.id\"\n (click)=\"selectPriceList(option.id); priceListsOverlay.hide()\"\n >{{ option.name }}</span\n >\n </ng-template>\n </p-overlayPanel>\n </ng-container>\n\n <ng-container *ngIf=\"isQuoteMode\">\n <span>{{ priceList.name }}</span>\n </ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"isQuoteMode\">\n <span *ngIf=\"contextProperties.StartDate\">{{ contextProperties.StartDate | date: 'MM.dd.yyyy' }}</span>\n\n <span class=\"slash-separator\"></span>\n\n <span>MRR: <span class=\"font-semibold\">$0.00</span></span>\n <span>NRR: <span class=\"font-semibold\">$0.00</span></span>\n </ng-container>\n\n <ng-container *vlLet=\"isCartRoute$ | async as isCartRoute\">\n <p-button\n styleClass=\"p-button-outlined\"\n label=\"Generate Doc\"\n [disabled]=\"!isCartRoute\"\n tooltipPosition=\"bottom\"\n [showDelay]=\"300\"\n [pTooltip]=\"isCartRoute ? '' : disabledActionButtonTooltip\"\n ></p-button>\n\n <p-button\n *vlLet=\"isSaveInProgress$ | async as isSaveInProgress\"\n class=\"save-button\"\n styleClass=\"p-button-outlined\"\n [label]=\"isSaveInProgress ? 'Saving' : 'Save to Quote'\"\n (onClick)=\"saveButtonClickHandler()\"\n [loading]=\"isSaveInProgress\"\n ></p-button>\n\n <p-button\n *vlLet=\"isSubmitInProgress$ | async as isSubmitInProgress\"\n class=\"submit-button\"\n styleClass=\"p-button\"\n [label]=\"isSubmitInProgress ? 'Submitting' : 'Submit For Approval'\"\n [disabled]=\"!isCartRoute\"\n tooltipPosition=\"bottom\"\n [showDelay]=\"300\"\n [pTooltip]=\"isCartRoute ? '' : disabledActionButtonTooltip\"\n (onClick)=\"submitButtonClickHandler()\"\n [loading]=\"isSubmitInProgress\"\n ></p-button>\n </ng-container>\n</div>\n", styles: [":host{display:flex;align-items:center;height:48px;width:100%;background-color:var(--vl-primary-color);color:#fff;padding:0 32px;flex-shrink:0}::ng-deep .p-overlaypanel.flow-header-overlay .p-overlaypanel-content{background-color:#fff;padding:16px}::ng-deep .p-overlaypanel.flow-header-overlay.left:before{left:6px!important}::ng-deep .p-overlaypanel.flow-header-overlay.right:before{right:6px!important}::ng-deep .p-overlaypanel.flow-header-overlay.left .p-overlaypanel-content{margin-left:-16px}::ng-deep .p-overlaypanel.flow-header-overlay.right .p-overlaypanel-content{margin-right:-16px}::ng-deep .p-overlaypanel.flow-header-overlay:before{background-color:#fff}::ng-deep .p-overlaypanel.price-list-overlay .p-overlaypanel-content{border-radius:5px;border-color:var(--vl-border-color);padding:0;display:flex;flex-direction:column;max-height:140px;overflow:auto}:host ::ng-deep .p-button{padding:5px 15px;font-size:12px}:host ::ng-deep .p-button{color:var(--vl-primary-color);background-color:#fff;border-color:#fff}:host ::ng-deep .p-button:enabled:hover{background-color:var(--vl-primary-color);color:#fff;border-color:#fff}:host ::ng-deep .p-button.p-button-outlined{background-color:var(--vl-primary-color);color:#fff;border-color:#fff}:host ::ng-deep .p-button.p-button-outlined:enabled:hover{color:var(--vl-primary-color);background-color:#fff;border-color:#fff}:host ::ng-deep .p-button .p-button-label{white-space:nowrap}:host ::ng-deep .save-button .p-button{width:120px}:host ::ng-deep .submit-button .p-button{width:160px}.vl-icon{display:inline-block}.flow-info{flex-shrink:0;display:flex;grid-gap:8px;gap:8px;align-items:center}.flow-info .nav-popover-toggle{margin-left:-8px}.flow-info .object-name{text-transform:capitalize}.flow-info .nav-back{font-weight:bold}.flow-info .nav-item:not(.disabled):hover,.flow-info .nav-popover-toggle:not(.disabled):hover{opacity:.6}nav{display:flex;align-items:center;cursor:pointer;padding:4px 0}nav.disabled{opacity:.6;cursor:default}nav .nav-icon{margin-right:10px}nav .icon-with-margin{margin:0 4px}nav a{color:#fff}nav.account-name{margin-left:4px;display:block;max-width:200px;overflow:hidden;text-overflow:ellipsis}nav.nav-popover-toggle{width:24px;display:flex;justify-content:center}nav.nav-popover-toggle i{pointer-events:none;margin:0}nav i{pointer-events:none}.dot-separator:after{content:\"\";display:block;width:4px;height:4px;border-radius:50%;background:#fff}.slash-separator:after{content:\"\";display:block;background:#fff;width:1px;height:16px}.flow-header-overlay__wrapper{width:360px}.flow-header-overlay__wrapper .close-icon{cursor:pointer}.flow-header-overlay__wrapper .info-list{list-style:none;padding:0;font-size:12px}.flow-header-overlay__wrapper .info-list__row{padding:8px 0;display:flex;justify-content:space-between}.flow-header-overlay__title{display:flex;justify-content:space-between;align-items:center;margin:0 0 24px}.flow-navigation{flex-grow:1;display:flex;grid-gap:16px;gap:16px;justify-content:center;font-weight:600}.flow-navigation .cart-nav-container{display:flex}.flow-navigation .nav-popover-toggle{margin-left:-14px}.flow-navigation .nav-item,.flow-navigation .nav-popover-toggle{opacity:.6}.flow-navigation .nav-item.active,.flow-navigation .nav-item:not(.disabled):hover,.flow-navigation .nav-popover-toggle.active,.flow-navigation .nav-popover-toggle:not(.disabled):hover{opacity:1}.price-list-option{padding:8px;color:var(--vl-primary-color);cursor:pointer}.price-list-option.active,.price-list-option:hover{background:var(--vl-secondary-nav-bg)}.flow-controls{flex-shrink:0;display:flex;align-items:center;grid-gap:8px;gap:8px}\n"], components: [{ type: i3.OverlayPanel, selector: "p-overlayPanel", inputs: ["dismissable", "showCloseIcon", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { type: CartPreviewComponent, selector: "vl-cart-preview", inputs: ["products"] }, { type: i2.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "style", "styleClass", "badgeClass"], outputs: ["onClick", "onFocus", "onBlur"] }], directives: [{ type: i3$1.LetDirective, selector: "[vlLet]", inputs: ["vlLet"] }, { type: i9.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i10.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { type: i2$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { type: i9.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i9.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "async": i9.AsyncPipe, "date": i9.DatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
561
|
+
FlowHeaderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.15", type: FlowHeaderComponent, selector: "vl-flow-header", ngImport: i0, template: "<div class=\"flow-info\" *vlLet=\"objectDetails$ | async as details\">\n <nav class=\"nav-item nav-back\" (click)=\"back()\">\n <i class=\"nav-icon vl-icon vl-icon-arrow-left\"></i>\n\n <span> Back </span>\n <span *ngIf=\"objectName\" class=\"object-name\"> To {{ objectName }}</span>\n </nav>\n\n <ng-container *ngIf=\"isAccountMode\">\n <span class=\"dot-separator\"></span>\n\n <span>Account name</span>\n\n <nav class=\"account-name\" [pTooltip]=\"contextProperties.Name ?? ''\" tooltipPosition=\"bottom\" [showDelay]=\"1000\">\n <a target=\"_blank\" [href]=\"getSalesforceObjectLink(contextProperties.Id)\">{{ contextProperties.Name }}</a>\n </nav>\n </ng-container>\n\n <ng-container *ngIf=\"isQuoteMode\">\n <span class=\"dot-separator\"></span>\n\n <span>Quote #{{ details.quoteNumber }}</span>\n\n <span class=\"dot-separator\"></span>\n\n <nav class=\"nav-item\" (click)=\"quoteDetails.toggle($event)\">\n <span>{{ status$ | async }}</span>\n\n <i *ngIf=\"!quoteDetails.overlayVisible\" class=\"vl-icon vl-icon-chevron-down icon-with-margin\"></i>\n <i *ngIf=\"quoteDetails.overlayVisible\" class=\"vl-icon vl-icon-chevron-up icon-with-margin\"></i>\n </nav>\n\n <p-overlayPanel styleClass=\"navigation-settings-overlay flow-header-overlay center\" #quoteDetails>\n <ng-template pTemplate>\n <div class=\"flow-header-overlay__wrapper\">\n <h2 class=\"flow-header-overlay__title\">\n <span>Quote Information</span>\n <i class=\"vl-icon vl-icon-close close-icon\" (click)=\"quoteDetails.hide()\"></i>\n </h2>\n\n <ul class=\"info-list\">\n <li class=\"info-list__row\">\n <span>Account Name:</span>\n <a target=\"_blank\" [href]=\"getSalesforceObjectLink(details.accountId)\">{{ details.accountName }}</a>\n </li>\n <li class=\"info-list__row\">\n <span>Opportunity Name:</span>\n <a target=\"_blank\" [href]=\"getSalesforceObjectLink(details.opportunityId)\">{{\n details.opportunityName\n }}</a>\n </li>\n <li class=\"info-list__row\">\n <span>Quote Name:</span>\n <a target=\"_blank\" [href]=\"getSalesforceObjectLink(details.quoteId)\">{{ details.quoteName }}</a>\n </li>\n </ul>\n </div>\n </ng-template>\n </p-overlayPanel>\n </ng-container>\n</div>\n\n<div class=\"flow-navigation\">\n <nav class=\"nav-item\" [ngClass]=\"{ active: isCatalogRoute$ | async }\" (click)=\"navigateToCatalog()\">Catalog</nav>\n <nav class=\"nav-item disabled\" [ngClass]=\"{ active: isConfigurationRoute$ | async }\">Configurator</nav>\n <ng-container *vlLet=\"products$ | async as products\">\n <nav class=\"nav-item\" [ngClass]=\"{ active: isCartRoute$ | async }\" (click)=\"navigateToShoppingCart()\">\n Shopping Cart ({{ products.length }})\n </nav>\n\n <nav class=\"nav-popover-toggle active\" (click)=\"cart?.overlayPanel?.toggle($event)\">\n <i *ngIf=\"!cart?.overlayPanel?.overlayVisible\" class=\"vl-icon vl-icon-chevron-down icon-with-margin\"></i>\n <i *ngIf=\"cart?.overlayPanel?.overlayVisible\" class=\"vl-icon vl-icon-chevron-up icon-with-margin\"></i>\n </nav>\n\n <vl-cart-preview #cart [products]=\"products\"></vl-cart-preview>\n </ng-container>\n</div>\n\n<div class=\"flow-controls\" *vlLet=\"objectDetails$ | async as details\">\n <ng-container *ngIf=\"isQuoteMode\">\n <span *ngIf=\"details.priceListName\">{{ details.priceListName }}</span>\n <span *ngIf=\"contextProperties.StartDate\">{{ contextProperties.StartDate | date: 'MM.dd.yyyy' }}</span>\n\n <span class=\"slash-separator\"></span>\n\n <span>MRR: <span class=\"font-semibold\">$0.00</span></span>\n <span>NRR: <span class=\"font-semibold\">$0.00</span></span>\n </ng-container>\n\n <ng-container *vlLet=\"isCartRoute$ | async as isCartRoute\">\n <p-button\n styleClass=\"p-button-outlined\"\n label=\"Generate Doc\"\n [disabled]=\"!isCartRoute\"\n tooltipPosition=\"bottom\"\n [showDelay]=\"300\"\n [pTooltip]=\"isCartRoute ? '' : disabledActionButtonTooltip\"\n ></p-button>\n\n <p-button\n *vlLet=\"isSaveInProgress$ | async as isSaveInProgress\"\n class=\"save-button\"\n styleClass=\"p-button-outlined\"\n [label]=\"isSaveInProgress ? 'Saving' : 'Save to Quote'\"\n (onClick)=\"saveButtonClickHandler()\"\n [loading]=\"isSaveInProgress\"\n ></p-button>\n\n <p-button\n *vlLet=\"isSubmitInProgress$ | async as isSubmitInProgress\"\n class=\"submit-button\"\n styleClass=\"p-button\"\n [label]=\"isSubmitInProgress ? 'Submitting' : 'Submit For Approval'\"\n [disabled]=\"!isCartRoute\"\n tooltipPosition=\"bottom\"\n [showDelay]=\"300\"\n [pTooltip]=\"isCartRoute ? '' : disabledActionButtonTooltip\"\n (onClick)=\"submitButtonClickHandler()\"\n [loading]=\"isSubmitInProgress\"\n ></p-button>\n </ng-container>\n</div>\n", styles: [":host{display:flex;align-items:center;height:48px;width:100%;background-color:var(--vl-primary-color);color:#fff;padding:0 32px;flex-shrink:0}::ng-deep .p-overlaypanel.flow-header-overlay .p-overlaypanel-content{background-color:#fff;padding:16px}::ng-deep .p-overlaypanel.flow-header-overlay.left:before{left:6px!important}::ng-deep .p-overlaypanel.flow-header-overlay.right:before{right:6px!important}::ng-deep .p-overlaypanel.flow-header-overlay.left .p-overlaypanel-content{margin-left:-16px}::ng-deep .p-overlaypanel.flow-header-overlay.right .p-overlaypanel-content{margin-right:-16px}::ng-deep .p-overlaypanel.flow-header-overlay:before{background-color:#fff}:host ::ng-deep .p-button{padding:5px 15px;font-size:12px}:host ::ng-deep .p-button{color:var(--vl-primary-color);background-color:#fff;border-color:#fff}:host ::ng-deep .p-button:enabled:hover{background-color:var(--vl-primary-color);color:#fff;border-color:#fff}:host ::ng-deep .p-button.p-button-outlined{background-color:var(--vl-primary-color);color:#fff;border-color:#fff}:host ::ng-deep .p-button.p-button-outlined:enabled:hover{color:var(--vl-primary-color);background-color:#fff;border-color:#fff}:host ::ng-deep .p-button .p-button-label{white-space:nowrap}:host ::ng-deep .save-button .p-button{width:120px}:host ::ng-deep .submit-button .p-button{width:160px}.vl-icon{display:inline-block}.flow-info{flex-shrink:0;display:flex;grid-gap:8px;gap:8px;align-items:center}.flow-info .nav-popover-toggle{margin-left:-8px}.flow-info .object-name{text-transform:capitalize}.flow-info .nav-back{font-weight:bold}.flow-info .nav-item:not(.disabled):hover,.flow-info .nav-popover-toggle:not(.disabled):hover{opacity:.6}nav{display:flex;align-items:center;cursor:pointer;padding:4px 0}nav.disabled{opacity:.6;cursor:default}nav .nav-icon{margin-right:10px}nav .icon-with-margin{margin:0 4px}nav a{color:#fff}nav.account-name{margin-left:4px;display:block;max-width:200px;overflow:hidden;text-overflow:ellipsis}nav.nav-popover-toggle{width:24px;display:flex;justify-content:center}nav.nav-popover-toggle i{pointer-events:none;margin:0}nav i{pointer-events:none}.dot-separator:after{content:\"\";display:block;width:4px;height:4px;border-radius:50%;background:#fff}.slash-separator:after{content:\"\";display:block;background:#fff;width:1px;height:16px}.flow-header-overlay__wrapper{width:360px}.flow-header-overlay__wrapper .close-icon{cursor:pointer}.flow-header-overlay__wrapper .info-list{list-style:none;padding:0;font-size:12px}.flow-header-overlay__wrapper .info-list__row{padding:8px 0;display:flex;justify-content:space-between}.flow-header-overlay__title{display:flex;justify-content:space-between;align-items:center;margin:0 0 24px}.flow-navigation{flex-grow:1;display:flex;grid-gap:16px;gap:16px;justify-content:center;font-weight:600}.flow-navigation .cart-nav-container{display:flex}.flow-navigation .nav-popover-toggle{margin-left:-14px}.flow-navigation .nav-item,.flow-navigation .nav-popover-toggle{opacity:.6}.flow-navigation .nav-item.active,.flow-navigation .nav-item:not(.disabled):hover,.flow-navigation .nav-popover-toggle.active,.flow-navigation .nav-popover-toggle:not(.disabled):hover{opacity:1}.flow-controls{flex-shrink:0;display:flex;align-items:center;grid-gap:8px;gap:8px}\n"], components: [{ type: i3.OverlayPanel, selector: "p-overlayPanel", inputs: ["dismissable", "showCloseIcon", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { type: CartPreviewComponent, selector: "vl-cart-preview", inputs: ["products"] }, { type: i2.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "style", "styleClass", "badgeClass"], outputs: ["onClick", "onFocus", "onBlur"] }], directives: [{ type: i3$1.LetDirective, selector: "[vlLet]", inputs: ["vlLet"] }, { type: i9.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i10.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { type: i2$2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { type: i9.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], pipes: { "async": i9.AsyncPipe, "date": i9.DatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
566
562
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: FlowHeaderComponent, decorators: [{
|
567
563
|
type: Component,
|
568
564
|
args: [{
|
@@ -600,8 +596,8 @@ class FlowService {
|
|
600
596
|
this.integrationState
|
601
597
|
.listen$(FlowAction.FLOW_CONFIGURE_PRODUCT)
|
602
598
|
.pipe(takeUntil(this.cleanup$), tap(payload => {
|
603
|
-
var _a, _b;
|
604
|
-
const productId = (_a = payload.productId) !== null && _a !== void 0 ? _a : (_b = this.quoteDraftService.currentState.find(li => li.id === payload.lineItemId)) === null ||
|
599
|
+
var _a, _b, _c;
|
600
|
+
const productId = (_a = payload.productId) !== null && _a !== void 0 ? _a : (_c = (_b = this.quoteDraftService.quoteSnapshot) === null || _b === void 0 ? void 0 : _b.currentState.find(li => li.id === payload.lineItemId)) === null || _c === void 0 ? void 0 : _c.productId;
|
605
601
|
if (productId) {
|
606
602
|
this.flowRouterService.navigateToProductConfiguration(productId, payload.lineItemId);
|
607
603
|
}
|
@@ -621,7 +617,7 @@ class FlowService {
|
|
621
617
|
if (!lineItem) {
|
622
618
|
return of(undefined);
|
623
619
|
}
|
624
|
-
const currentState = this.
|
620
|
+
const currentState = this.flowConfigurationService.getSnapshot();
|
625
621
|
const isNewLineItem = currentState.every(li => li.id !== lineItem.id);
|
626
622
|
let updatedState;
|
627
623
|
if (isNewLineItem) {
|
@@ -630,8 +626,7 @@ class FlowService {
|
|
630
626
|
else {
|
631
627
|
updatedState = currentState.map(li => (li.id === lineItem.id ? lineItem : li));
|
632
628
|
}
|
633
|
-
this.
|
634
|
-
return this.flowConfigurationService.calculate$();
|
629
|
+
return this.flowConfigurationService.calculate$(updatedState);
|
635
630
|
}), tap(() => {
|
636
631
|
this.configurationService.hasUnsavedChanges = false;
|
637
632
|
this.flowRouterService.navigateToShoppingCart();
|
@@ -1049,7 +1044,7 @@ class LegacyProductComponent {
|
|
1049
1044
|
this.destroyed$ = new Subject();
|
1050
1045
|
}
|
1051
1046
|
ngOnInit() {
|
1052
|
-
this.quoteDraftService.
|
1047
|
+
this.quoteDraftService.quote$
|
1053
1048
|
.pipe(first(), takeUntil$1(this.destroyed$))
|
1054
1049
|
.subscribe(quote => this.init(quote, this.route.snapshot.queryParams));
|
1055
1050
|
this.runtimeService.onSolutionStopEvent.pipe(take(1)).subscribe(lineItem => this.onSolutionStop(lineItem));
|
@@ -1065,7 +1060,7 @@ class LegacyProductComponent {
|
|
1065
1060
|
lineItem.actionCode = (_a = lineItem.actionCode) !== null && _a !== void 0 ? _a : 'ADD';
|
1066
1061
|
}
|
1067
1062
|
onSolutionCancel() {
|
1068
|
-
this.quoteDraftService.
|
1063
|
+
this.quoteDraftService.quote$.pipe(first(), takeUntil$1(this.destroyed$)).subscribe(quote => {
|
1069
1064
|
window['VELO_BACK_FN'].apply(null, [quote.quoteId]);
|
1070
1065
|
});
|
1071
1066
|
}
|
@@ -1078,7 +1073,7 @@ class LegacyProductComponent {
|
|
1078
1073
|
this.runtimeService.updateRuntime(states);
|
1079
1074
|
}
|
1080
1075
|
onSolutionStop(lineItem) {
|
1081
|
-
this.quoteDraftService.
|
1076
|
+
this.quoteDraftService.quote$.pipe(first(), takeUntil$1(this.destroyed$)).subscribe(quote => {
|
1082
1077
|
const quoteToUpsert = Object.assign(Object.assign({}, quote), { context: this.contextService.resolve(), currentState: [...(this.currentStateService.currentState || []).filter(li => li.id !== lineItem.id), lineItem] });
|
1083
1078
|
this.quoteApiService
|
1084
1079
|
.upsertQuote(quoteToUpsert)
|
@@ -1183,7 +1178,7 @@ class ProductComponent {
|
|
1183
1178
|
this.state$ = new BehaviorSubject({ loading: true, failure: false });
|
1184
1179
|
}
|
1185
1180
|
ngOnInit() {
|
1186
|
-
this.quoteDraftService.
|
1181
|
+
this.quoteDraftService.quote$.pipe(first$1(), takeUntil(this.destroy$)).subscribe(quote => this.init(quote));
|
1187
1182
|
}
|
1188
1183
|
ngOnDestroy() {
|
1189
1184
|
this.destroy$.next();
|
@@ -1209,15 +1204,14 @@ class ProductComponent {
|
|
1209
1204
|
return;
|
1210
1205
|
}
|
1211
1206
|
const lineItemId = this.getLineItemId(quote, productId, contextProperties.lineItemId);
|
1212
|
-
const currentStateItem = quote.currentState
|
1207
|
+
const currentStateItem = EntityUtil.findById(lineItemId, quote.currentState);
|
1208
|
+
const { offeringId } = currentStateItem !== null && currentStateItem !== void 0 ? currentStateItem : {};
|
1213
1209
|
if (currentStateItem) {
|
1214
1210
|
this.configurationService.updateCurrentStates({
|
1215
1211
|
configurableRamp: currentStateItem,
|
1216
1212
|
currentState: quote.currentState,
|
1217
|
-
asset: this.getAsset(quote, currentStateItem),
|
1218
1213
|
});
|
1219
1214
|
}
|
1220
|
-
const { offeringId } = currentStateItem !== null && currentStateItem !== void 0 ? currentStateItem : {};
|
1221
1215
|
this.runtimeService
|
1222
1216
|
.init({ productId, offeringId })
|
1223
1217
|
.pipe(tap(context => (this.uiDefinition = context === null || context === void 0 ? void 0 : context.uiDefinition)), switchMap(() => this.customize(productId)), switchMap(() => this.configurationService.configure()), tap(() => this.state$.next({ loading: false, failure: false })), catchError(error => {
|
@@ -1239,9 +1233,6 @@ class ProductComponent {
|
|
1239
1233
|
}
|
1240
1234
|
return id;
|
1241
1235
|
}
|
1242
|
-
getAsset(quote, lineItem) {
|
1243
|
-
return quote.initialState.find(a => a.id === lineItem.openOrderLineItemId || a.id === lineItem.assetId);
|
1244
|
-
}
|
1245
1236
|
}
|
1246
1237
|
ProductComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: ProductComponent, deps: [{ token: i2$1.ContextService }, { token: i2$1.ConfigurationRuntimeService }, { token: i2$1.ConfigurationService }, { token: i2$1.QuoteDraftService }, { token: i2$2.MessageService }, { token: FLOW_CUSTOMIZATION, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
1247
1238
|
ProductComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.15", type: ProductComponent, selector: "vl-flow-product", ngImport: i0, template: "<ng-container *ngIf=\"state$ | async as state\">\n <vl-loader *ngIf=\"state.loading; else content\" [label]=\"'Loading UI'\"></vl-loader>\n\n <ng-template #content>\n <ng-container *ngIf=\"!state.failure\">\n <vl-cms-preview [uiDefinition]=\"uiDefinition\"></vl-cms-preview>\n </ng-container>\n </ng-template>\n</ng-container>\n", styles: [""], components: [{ type: i3$1.LoaderComponent, selector: "vl-loader", inputs: ["label", "overlayVisible"] }, { type: i4.PreviewComponent, selector: "vl-cms-preview", inputs: ["modelId", "uiDefinition", "clearState"] }], directives: [{ type: i9.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "async": i9.AsyncPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
@@ -1496,14 +1487,21 @@ class QuoteResolver {
|
|
1496
1487
|
const parentUrl = this.routerService.getFlowRootPath(route);
|
1497
1488
|
return from(this.router.navigate([parentUrl, '404'], { state: { message } }));
|
1498
1489
|
}
|
1490
|
+
initFlow$() {
|
1491
|
+
if (this.quoteDraftService.isStandalone) {
|
1492
|
+
return of(undefined);
|
1493
|
+
}
|
1494
|
+
return this.flowConfiguration.initialize$();
|
1495
|
+
}
|
1499
1496
|
resolve(route) {
|
1500
1497
|
const { headerId } = this.contextService.resolve();
|
1501
|
-
const quote = this.quoteDraftService.
|
1498
|
+
const quote = this.quoteDraftService.quoteSnapshot;
|
1502
1499
|
if (quote && quote.quoteId === headerId) {
|
1503
1500
|
return of(true);
|
1504
1501
|
}
|
1505
1502
|
const { queryParams } = route;
|
1506
|
-
|
1503
|
+
this.contextService.update({ properties: queryParams });
|
1504
|
+
return this.quoteDraftService.init(headerId, queryParams).pipe(switchMap(() => this.initFlow$()), catchError(e => {
|
1507
1505
|
const message = e instanceof HttpErrorResponse ? e.error.message : e;
|
1508
1506
|
return this.handleError(route, message);
|
1509
1507
|
}));
|