@veloceapps/sdk 3.1.18 → 3.1.19

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.
Files changed (35) hide show
  1. package/bundles/veloce-sdk-core.umd.js +212 -68
  2. package/bundles/veloce-sdk-core.umd.js.map +1 -1
  3. package/bundles/veloce-sdk-runtime.umd.js +5 -6
  4. package/bundles/veloce-sdk-runtime.umd.js.map +1 -1
  5. package/bundles/veloce-sdk.umd.js +52 -38
  6. package/bundles/veloce-sdk.umd.js.map +1 -1
  7. package/core/modules/flow-configuration/services/flow-configuration.service.d.ts +11 -17
  8. package/core/services/quote-draft.service.d.ts +41 -7
  9. package/esm2015/core/modules/configuration/services/configuration.service.js +3 -3
  10. package/esm2015/core/modules/flow-configuration/services/flow-configuration.service.js +43 -49
  11. package/esm2015/core/services/quote-draft.service.js +138 -22
  12. package/esm2015/runtime/components/ui-runtime/runtime.component.js +2 -2
  13. package/esm2015/runtime/execution/directives/section-script.directive.js +2 -2
  14. package/esm2015/runtime/services/cart.service.js +2 -3
  15. package/esm2015/runtime/services/section.service.js +1 -1
  16. package/esm2015/src/components/header/header.component.js +23 -19
  17. package/esm2015/src/components/header/header.types.js +1 -1
  18. package/esm2015/src/pages/legacy-product/legacy-product.component.js +4 -4
  19. package/esm2015/src/pages/product/product.component.js +8 -5
  20. package/esm2015/src/resolvers/flow.resolver.js +8 -4
  21. package/esm2015/src/resolvers/quote.resolver.js +4 -11
  22. package/esm2015/src/services/flow.service.js +6 -5
  23. package/fesm2015/veloce-sdk-core.js +177 -66
  24. package/fesm2015/veloce-sdk-core.js.map +1 -1
  25. package/fesm2015/veloce-sdk-runtime.js +3 -4
  26. package/fesm2015/veloce-sdk-runtime.js.map +1 -1
  27. package/fesm2015/veloce-sdk.js +44 -39
  28. package/fesm2015/veloce-sdk.js.map +1 -1
  29. package/package.json +1 -1
  30. package/runtime/services/cart.service.d.ts +1 -1
  31. package/src/components/header/header.component.d.ts +5 -2
  32. package/src/components/header/header.types.d.ts +0 -1
  33. package/src/pages/product/product.component.d.ts +1 -0
  34. package/src/resolvers/flow.resolver.d.ts +3 -1
  35. package/src/resolvers/quote.resolver.d.ts +0 -1
@@ -406,6 +406,8 @@ 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$;
409
411
  this.status$ = this.contextService.resolve$().pipe(map(context => { var _a; return (_a = context.properties.Status) !== null && _a !== void 0 ? _a : ''; }));
410
412
  this.isEditMode$ = this.quoteDraftService.isEditMode$();
411
413
  this.products$ = this.flowConfiguration.get().pipe(map(lineItems => this.generateProducts(lineItems)));
@@ -426,10 +428,10 @@ class FlowHeaderComponent {
426
428
  get isQuoteMode() {
427
429
  return this.mode === ConfigurationContextMode.QUOTE;
428
430
  }
429
- back() {
430
- const objectId = this.contextService.resolve().headerId;
431
- if (objectId) {
432
- window.VELO_BACK_FN.apply(null, [objectId]);
431
+ back(objectId) {
432
+ const targetId = objectId !== null && objectId !== void 0 ? objectId : this.contextService.resolve().headerId;
433
+ if (targetId) {
434
+ window.VELO_BACK_FN.apply(null, [targetId]);
433
435
  }
434
436
  }
435
437
  getSalesforceObjectLink(objectId) {
@@ -463,18 +465,16 @@ class FlowHeaderComponent {
463
465
  this.dialogService.showEmptyCartDialog().subscribe();
464
466
  return;
465
467
  }
466
- const quoteDraft = this.quoteDraftService.quoteSnapshot;
468
+ const quoteDraft = this.quoteDraftService.quoteDraft;
467
469
  if (!quoteDraft) {
468
470
  return;
469
471
  }
470
472
  this.isSaveInProgress$.next(true);
471
473
  this.quoteApiService
472
474
  .upsertQuote(quoteDraft)
473
- .pipe(tap(() => {
474
- // navigate back to quote on successful save
475
- if (this.mode === ConfigurationContextMode.QUOTE) {
476
- this.back();
477
- }
475
+ .pipe(tap(({ quoteId }) => {
476
+ this.quoteDraftService.hasUnsavedChanges = false;
477
+ this.back(quoteId);
478
478
  }), finalize(() => this.isSaveInProgress$.next(false)))
479
479
  .subscribe();
480
480
  }
@@ -487,16 +487,22 @@ class FlowHeaderComponent {
487
487
  this.dialogService.showAccountSubmitFailureDialog();
488
488
  return;
489
489
  }
490
- const quoteDraft = this.quoteDraftService.quoteSnapshot;
490
+ const quoteDraft = this.quoteDraftService.quoteDraft;
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 => this.contextService.update({ properties: updatedQuoteDraft.context.properties })), finalize(() => this.isSubmitInProgress$.next(false)), takeUntil(this.destroyed$))
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$))
498
501
  .subscribe();
499
502
  }
503
+ selectPriceList(priceListId) {
504
+ this.quoteDraftService.updateActivePriceList(priceListId);
505
+ }
500
506
  queryName$(objectName, id) {
501
507
  if (!id) {
502
508
  return of('');
@@ -509,19 +515,17 @@ class FlowHeaderComponent {
509
515
  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$));
510
516
  }
511
517
  populateObjectDetails() {
512
- var _a, _b;
518
+ var _a;
513
519
  const accountId = this.isAccountMode ? this.contextProperties.Id : this.contextProperties.AccountId;
514
520
  const opportunityId = this.contextProperties.OpportunityId;
515
521
  const quoteId = this.isQuoteMode ? this.contextProperties.Id : undefined;
516
522
  const quoteName = this.isQuoteMode ? this.contextProperties.Name : undefined;
517
523
  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;
519
524
  this.objectDetails$.next(Object.assign(Object.assign({}, this.objectDetails$.value), { accountId,
520
525
  opportunityId,
521
526
  quoteId,
522
527
  quoteName,
523
- quoteNumber,
524
- priceListName }));
528
+ quoteNumber }));
525
529
  this.queryName$('Account', accountId).subscribe(accountName => this.objectDetails$.next(Object.assign(Object.assign({}, this.objectDetails$.value), { accountName })));
526
530
  this.queryName$('Opportunity', opportunityId).subscribe(opportunityName => this.objectDetails$.next(Object.assign(Object.assign({}, this.objectDetails$.value), { opportunityName })));
527
531
  }
@@ -558,7 +562,7 @@ class FlowHeaderComponent {
558
562
  }
559
563
  }
560
564
  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 });
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\">&nbsp;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 });
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\">&nbsp;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)\">\n <span>{{ details.accountName }}</span>\n </a>\n </li>\n <li class=\"info-list__row\">\n <span>Opportunity Name:</span>\n <a target=\"_blank\" [href]=\"getSalesforceObjectLink(details.opportunityId)\">\n <span>{{ details.opportunityName }}</span>\n </a>\n </li>\n <li class=\"info-list__row\">\n <span>Quote Name:</span>\n <a target=\"_blank\" [href]=\"getSalesforceObjectLink(details.quoteId)\">\n <span>{{ details.quoteName }}</span>\n </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__wrapper .info-list__row a{text-align:right}.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 });
562
566
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: FlowHeaderComponent, decorators: [{
563
567
  type: Component,
564
568
  args: [{
@@ -596,8 +600,8 @@ class FlowService {
596
600
  this.integrationState
597
601
  .listen$(FlowAction.FLOW_CONFIGURE_PRODUCT)
598
602
  .pipe(takeUntil(this.cleanup$), tap(payload => {
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;
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 || _b === void 0 ? void 0 : _b.productId;
601
605
  if (productId) {
602
606
  this.flowRouterService.navigateToProductConfiguration(productId, payload.lineItemId);
603
607
  }
@@ -617,7 +621,7 @@ class FlowService {
617
621
  if (!lineItem) {
618
622
  return of(undefined);
619
623
  }
620
- const currentState = this.flowConfigurationService.getSnapshot();
624
+ const currentState = this.quoteDraftService.currentState;
621
625
  const isNewLineItem = currentState.every(li => li.id !== lineItem.id);
622
626
  let updatedState;
623
627
  if (isNewLineItem) {
@@ -626,7 +630,8 @@ class FlowService {
626
630
  else {
627
631
  updatedState = currentState.map(li => (li.id === lineItem.id ? lineItem : li));
628
632
  }
629
- return this.flowConfigurationService.calculate$(updatedState);
633
+ this.quoteDraftService.setCurrentLineItemState(updatedState);
634
+ return this.flowConfigurationService.calculate$();
630
635
  }), tap(() => {
631
636
  this.configurationService.hasUnsavedChanges = false;
632
637
  this.flowRouterService.navigateToShoppingCart();
@@ -1044,7 +1049,7 @@ class LegacyProductComponent {
1044
1049
  this.destroyed$ = new Subject();
1045
1050
  }
1046
1051
  ngOnInit() {
1047
- this.quoteDraftService.quote$
1052
+ this.quoteDraftService.quoteDraft$
1048
1053
  .pipe(first(), takeUntil$1(this.destroyed$))
1049
1054
  .subscribe(quote => this.init(quote, this.route.snapshot.queryParams));
1050
1055
  this.runtimeService.onSolutionStopEvent.pipe(take(1)).subscribe(lineItem => this.onSolutionStop(lineItem));
@@ -1060,7 +1065,7 @@ class LegacyProductComponent {
1060
1065
  lineItem.actionCode = (_a = lineItem.actionCode) !== null && _a !== void 0 ? _a : 'ADD';
1061
1066
  }
1062
1067
  onSolutionCancel() {
1063
- this.quoteDraftService.quote$.pipe(first(), takeUntil$1(this.destroyed$)).subscribe(quote => {
1068
+ this.quoteDraftService.quoteDraft$.pipe(first(), takeUntil$1(this.destroyed$)).subscribe(quote => {
1064
1069
  window['VELO_BACK_FN'].apply(null, [quote.quoteId]);
1065
1070
  });
1066
1071
  }
@@ -1073,7 +1078,7 @@ class LegacyProductComponent {
1073
1078
  this.runtimeService.updateRuntime(states);
1074
1079
  }
1075
1080
  onSolutionStop(lineItem) {
1076
- this.quoteDraftService.quote$.pipe(first(), takeUntil$1(this.destroyed$)).subscribe(quote => {
1081
+ this.quoteDraftService.quoteDraft$.pipe(first(), takeUntil$1(this.destroyed$)).subscribe(quote => {
1077
1082
  const quoteToUpsert = Object.assign(Object.assign({}, quote), { context: this.contextService.resolve(), currentState: [...(this.currentStateService.currentState || []).filter(li => li.id !== lineItem.id), lineItem] });
1078
1083
  this.quoteApiService
1079
1084
  .upsertQuote(quoteToUpsert)
@@ -1178,7 +1183,7 @@ class ProductComponent {
1178
1183
  this.state$ = new BehaviorSubject({ loading: true, failure: false });
1179
1184
  }
1180
1185
  ngOnInit() {
1181
- this.quoteDraftService.quote$.pipe(first$1(), takeUntil(this.destroy$)).subscribe(quote => this.init(quote));
1186
+ this.quoteDraftService.quoteDraft$.pipe(first$1(), takeUntil(this.destroy$)).subscribe(quote => this.init(quote));
1182
1187
  }
1183
1188
  ngOnDestroy() {
1184
1189
  this.destroy$.next();
@@ -1204,14 +1209,15 @@ class ProductComponent {
1204
1209
  return;
1205
1210
  }
1206
1211
  const lineItemId = this.getLineItemId(quote, productId, contextProperties.lineItemId);
1207
- const currentStateItem = EntityUtil.findById(lineItemId, quote.currentState);
1208
- const { offeringId } = currentStateItem !== null && currentStateItem !== void 0 ? currentStateItem : {};
1212
+ const currentStateItem = quote.currentState.find(({ id }) => id === lineItemId);
1209
1213
  if (currentStateItem) {
1210
1214
  this.configurationService.updateCurrentStates({
1211
1215
  configurableRamp: currentStateItem,
1212
1216
  currentState: quote.currentState,
1217
+ asset: this.getAsset(quote, currentStateItem),
1213
1218
  });
1214
1219
  }
1220
+ const { offeringId } = currentStateItem !== null && currentStateItem !== void 0 ? currentStateItem : {};
1215
1221
  this.runtimeService
1216
1222
  .init({ productId, offeringId })
1217
1223
  .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 => {
@@ -1233,6 +1239,9 @@ class ProductComponent {
1233
1239
  }
1234
1240
  return id;
1235
1241
  }
1242
+ getAsset(quote, lineItem) {
1243
+ return quote.initialState.find(a => a.id === lineItem.openOrderLineItemId || a.id === lineItem.assetId);
1244
+ }
1236
1245
  }
1237
1246
  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 });
1238
1247
  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 });
@@ -1425,10 +1434,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImpo
1425
1434
  }] });
1426
1435
 
1427
1436
  class FlowResolver {
1428
- constructor(router, flowsApiService, routerService) {
1437
+ constructor(router, flowsApiService, routerService, contextService) {
1429
1438
  this.router = router;
1430
1439
  this.flowsApiService = flowsApiService;
1431
1440
  this.routerService = routerService;
1441
+ this.contextService = contextService;
1432
1442
  }
1433
1443
  handleError(route, message, queryParams) {
1434
1444
  const parentUrl = this.routerService.getFlowRootPath(route);
@@ -1453,6 +1463,8 @@ class FlowResolver {
1453
1463
  const { queryParams: flowQueryParams, entryPath } = properties;
1454
1464
  const isProductFlow = entryPath.includes('/product');
1455
1465
  const mergedParams = Object.assign(Object.assign(Object.assign({}, queryParams), flowQueryParams), Object.assign({}, (isProductFlow && { standalone: true })));
1466
+ const contextProperties = Object.entries(mergedParams).reduce((trunk, [key, value]) => (Object.assign(Object.assign({}, trunk), { [key]: String(value) })), {});
1467
+ this.contextService.update({ properties: contextProperties });
1456
1468
  const parentUrl = this.routerService.getFlowRootPath(route);
1457
1469
  const entryUrl = String(entryPath !== null && entryPath !== void 0 ? entryPath : '')
1458
1470
  .split('/')
@@ -1469,11 +1481,11 @@ class FlowResolver {
1469
1481
  }));
1470
1482
  }
1471
1483
  }
1472
- FlowResolver.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: FlowResolver, deps: [{ token: i1$1.Router }, { token: i1$2.FlowsApiService }, { token: FlowRouterService }], target: i0.ɵɵFactoryTarget.Injectable });
1484
+ FlowResolver.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: FlowResolver, deps: [{ token: i1$1.Router }, { token: i1$2.FlowsApiService }, { token: FlowRouterService }, { token: i2$1.ContextService }], target: i0.ɵɵFactoryTarget.Injectable });
1473
1485
  FlowResolver.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: FlowResolver });
1474
1486
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.15", ngImport: i0, type: FlowResolver, decorators: [{
1475
1487
  type: Injectable
1476
- }], ctorParameters: function () { return [{ type: i1$1.Router }, { type: i1$2.FlowsApiService }, { type: FlowRouterService }]; } });
1488
+ }], ctorParameters: function () { return [{ type: i1$1.Router }, { type: i1$2.FlowsApiService }, { type: FlowRouterService }, { type: i2$1.ContextService }]; } });
1477
1489
 
1478
1490
  class QuoteResolver {
1479
1491
  constructor(router, quoteDraftService, routerService, contextService, flowConfiguration) {
@@ -1487,21 +1499,14 @@ class QuoteResolver {
1487
1499
  const parentUrl = this.routerService.getFlowRootPath(route);
1488
1500
  return from(this.router.navigate([parentUrl, '404'], { state: { message } }));
1489
1501
  }
1490
- initFlow$() {
1491
- if (this.quoteDraftService.isStandalone) {
1492
- return of(undefined);
1493
- }
1494
- return this.flowConfiguration.initialize$();
1495
- }
1496
1502
  resolve(route) {
1497
1503
  const { headerId } = this.contextService.resolve();
1498
- const quote = this.quoteDraftService.quoteSnapshot;
1504
+ const quote = this.quoteDraftService.quoteDraft;
1499
1505
  if (quote && quote.quoteId === headerId) {
1500
1506
  return of(true);
1501
1507
  }
1502
1508
  const { queryParams } = route;
1503
- this.contextService.update({ properties: queryParams });
1504
- return this.quoteDraftService.init(headerId, queryParams).pipe(switchMap(() => this.initFlow$()), catchError(e => {
1509
+ return this.quoteDraftService.init(headerId, queryParams).pipe(catchError(e => {
1505
1510
  const message = e instanceof HttpErrorResponse ? e.error.message : e;
1506
1511
  return this.handleError(route, message);
1507
1512
  }));