projects/congarevenuecloud/elements/src/lib/constraint-rule/constraint-rule-sidebar/constraint-rule-sidebar.component.ts
This component is a work in progress.
Constraint rule sidebar is used to show a list of all the constraint rule messages that have been applied to the current cart.
import { ConstraintRuleModule } from '@congarevenuecloud/elements';
import { ModalModule } from 'ngx-bootstrap/modal';
@NgModule({
imports: [ConstraintRuleModule, ModalModule, ...]
})
export class AppModule {}
```typescript
import { ConstraintRuleSidebarComponent } from '@congarevenuecloud/elements';
import { BsModalService } from 'ngx-bootstrap/modal';
constructor(private bsModalService: BsModalService) {}
showSidebar() { this.bsModalService.show(ConstraintRuleSidebarComponent, { backdrop: false, class: 'constraintRuleSidebar' }); }
Example :
OnInit
OnDestroy
encapsulation | ViewEncapsulation.None |
selector | apt-constraint-rule-sidebar |
styleUrls | ./constraint-rule-sidebar.component.scss |
templateUrl | ./constraint-rule-sidebar.component.html |
Properties |
|
Methods |
constructor(bsModalRef: BsModalRef, constraintRuleMessageService: ConstraintRuleMessageService, productConfigurationService: ProductConfigurationService)
|
||||||||||||
Parameters :
|
isItemSelected | ||||||||
isItemSelected(product: Product)
|
||||||||
The method is work in progress. Method responsible to disable/enable the products in the sidebar to add/remove based on the rule configured and product selection.
Parameters :
Returns :
boolean
boolean value is returned. |
Public bsModalRef |
Type : BsModalRef
|
showProductConfig |
Type : boolean
|
Default value : false
|
Flag used to specify if this component is showing product level constraint rules. If false this component will show cart level configuration rules. |
<ng-container *ngIf="showRules$ | async">
<ng-container *ngIf="ruleDetailGroups$ | async as ruleDetailGroups">
<div class="modal-header bg-white py-2 border-0">
<h5 class="modal-title pull-left font-weight-bold">{{ "CONSTRAINT_SIDE_MENU.VALIDATION_MESSAGES" | translate }}</h5>
<button type="button" class="close pull-left" aria-label="Close">
<span aria-hidden="true" (click)="bsModalRef.hide()">×</span>
</button>
</div>
<div class="modal-body bg-white p-0">
<!-- Errors -->
<div *ngIf="ruleDetailGroups.errors.length > 0" class="card border-0">
<div class="card-header border-bottom-0 border-top">
<i class="fas fa-minus-circle text-danger mr-2"></i> <span>
{{ (ruleDetailGroups.errors.length > 1 ? "CONSTRAINT_SIDE_MENU.NUM_OF_ERRORS.PLURAL" : "CONSTRAINT_SIDE_MENU.NUM_OF_ERRORS.ONE") | translate: {amount: ruleDetailGroups.errors.length} }}
</span>
</div>
<ng-container *ngFor="let error of ruleDetailGroups.errors; let i = index">
<ng-container [ngSwitch]="error.actionType">
<!-- Inclusions -->
<ng-container *ngSwitchCase="'Inclusion'">
<div class="card-body bg-white py-2 flex-column" [class.border-top]="i > 0">
<ng-container *ngIf="error.messageHtml !== null;">
<div [innerHtml]="error.messageHtml"></div>
</ng-container>
<ng-container *ngFor="let item of error.actionItems">
<div class="py-3">
<a class="pt-2" href="javascript:void(0)"
[routerLink]="['/products/', item.product.Id]">{{item.product.Name}}</a>
<div class="d-flex py-2 align-items-center justify-content-between">
<small class="font-weight-bold">{{item.chargeType}}</small>
<small class="font-weight-bold">
<apt-price [record]="item.product" [type]="'list'"></apt-price>
</small>
</div>
<div class="d-flex align-items-center justify-content-end">
<label [for]="item.product.Name + i" class="mr-2 mb-0">{{ "COMMON.QTY" | translate }}</label>
<input class="form-control mr-2 w-25" [id]="item.product.Name + i" type="number" min="1"
[(ngModel)]="quantityControlValues[item.product.Name + i]" placeholder="1">
<div class="input-group-append">
<button *ngIf="!showProductConfig" class="btn btn-outline-primary"
(click)="handleAddToCart(error, item.product, quantityControlValues[item.product.Name + i], item.product.Name + i)"
[ladda]="loading[item.product.Name + i]"
data-style="zoom-in">{{ "COMMON.ADD_TO_CART" | translate }}</button>
<button *ngIf="showProductConfig" class="btn btn-outline-primary"
[disabled]="isItemSelected(item.product)"
(click)="handleAddToConfiguration(item.product, quantityControlValues[item.product.Name + i], item.product.Name + i, error.targetBundleNumber)"
[ladda]="loading[item.product.Name + i]"
data-style="zoom-in">{{ "COMMON.ADD" | translate }}</button>
</div>
</div>
</div>
</ng-container>
</div>
<div class="card-footer bg-white border-0 py-2">
</div>
</ng-container>
<!-- Exclusions -->
<ng-container *ngSwitchCase="'Exclusion'">
<div class="card-body bg-white py-2 flex-column" [class.border-top]="i > 0">
<ng-container *ngIf="error.messageHtml !== null;">
<span [innerHtml]="error.messageHtml"></span>
</ng-container>
<ng-container *ngFor="let item of error.actionItems">
<div class="py-3">
<a class="pt-2" href="javascript:void(0)"
[routerLink]="['/products/', item.product.Id]">{{item.product.Name}}</a>
<div class="d-flex py-2 align-items-center justify-content-between">
<small class="font-weight-bold">{{item.chargeType}}</small>
<small class="font-weight-bold">
<apt-price [record]="item.product" [type]="'list'"></apt-price>
</small>
</div>
<div class="d-flex align-items-center justify-content-end">
<label [for]="item.product.Name + i" class="mr-2 mb-0">{{ "COMMON.QTY" | translate }}</label>
<input class="form-control mr-2 w-25" [id]="item.product.Name + i" type="number" min="1"
[(ngModel)]="quantityControlValues[item.product.Name + i]" placeholder="1">
<div class="input-group-append">
<button *ngIf="!showProductConfig" class="btn btn-outline-danger"
(click)="handleDeleteFromCart(error, item.product, item.product?.Name + i)"
[ladda]="loading[item.product?.Name + i]"
data-style="zoom-in">{{ "CONSTRAINT_SIDE_MENU.REMOVE_FROM_CART" | translate }}</button>
<button *ngIf="showProductConfig" class="btn btn-outline-danger"
[disabled]="!isItemSelected(item.product, 'remove')"
(click)="handleRemoveFromBundle(item.product, error.triggeringProducts[0], item.product?.Name + i)"
[ladda]="loading[item.product?.Name + i]"
data-style="zoom-in">{{ "COMMON.REMOVE" | translate }}</button>
</div>
</div>
</div>
</ng-container>
</div>
<div class="card-footer bg-white border-0 py-2">
</div>
</ng-container>
<!-- Validation -->
<ng-container *ngSwitchCase="'Validation'">
<div class="card-body bg-white py-2 d-flex-column" [class.border-top]="i > 0">
<ng-container *ngIf="error.messageHtml !== null;">
<div [innerHtml]="error.messageHtml"></div>
</ng-container>
</div>
</ng-container>
<!-- Recommendation -->
<ng-container *ngSwitchCase="'Recommendation'">
<div class="card-body bg-white py-2 d-flex-column" [class.border-top]="i > 0">
<ng-container *ngIf="error.messageHtml !== null;">
<div [innerHtml]="error.messageHtml"></div>
</ng-container>
</div>
</ng-container>
<!-- Replacement -->
<ng-container *ngSwitchCase="'Replacement'">
<div class="card-body bg-white py-2 d-flex-column" [class.border-top]="i > 0">
<ng-container *ngIf="error.messageHtml !== null;">
<div [innerHtml]="error.messageHtml"></div>
</ng-container>
</div>
</ng-container>
</ng-container>
</ng-container>
</div>
<!-- Warnings -->
<div *ngIf="ruleDetailGroups.warnings.length > 0" class="card border-0">
<div class="card-header border-bottom-0 border-top">
<i class="fas fa-exclamation-triangle text-warning mr-2"></i> <span>
{{ (ruleDetailGroups.warnings.length > 1 ? "CONSTRAINT_SIDE_MENU.NUM_OF_WARNINGS.PLURAL" : "CONSTRAINT_SIDE_MENU.NUM_OF_WARNINGS.ONE") | translate: {amount: ruleDetailGroups.warnings.length} }}</span>
</div>
<ng-container *ngFor="let warning of ruleDetailGroups.warnings; let i = index">
<ng-container [ngSwitch]="warning.actionType">
<!-- Inclusion -->
<ng-container *ngSwitchCase="'Inclusion'">
<div class="card-body bg-white py-2 flex-column" [class.border-top]="i > 0">
<ng-container *ngIf="warning.messageHtml !== null;">
<div [innerHtml]="warning.messageHtml"></div>
</ng-container>
<ng-container *ngFor="let item of warning.actionItems">
<div class="py-3">
<a class="pt-2" href="javascript:void(0)"
[routerLink]="['/products/', item.product.Id]">{{item.product.Name}}</a>
<div class="d-flex py-2 align-items-center justify-content-between">
<small class="font-weight-bold">{{item.chargeType}}</small>
<small class="font-weight-bold">
<apt-price [record]="item.product" [type]="'list'"></apt-price>
</small>
</div>
<div class="d-flex align-items-center justify-content-end">
<label [for]="item.product.Name + i" class="mr-2 mb-0">{{ "COMMON.QTY" | translate }}</label>
<input class="form-control mr-2 w-25" [id]="item.product.Name + i" type="number" min="1"
[(ngModel)]="quantityControlValues[item.product.Name + i]" placeholder="1">
<div class="input-group-append">
<button *ngIf="!showProductConfig" class="btn btn-outline-primary"
(click)="handleAddToCart(warning, item.product, quantityControlValues[item.product.Name + i], item.product.Name + i)"
[ladda]="loading[item.product.Name + i]"
data-style="zoom-in">{{ "COMMON.ADD_TO_CART" | translate }}</button>
<button *ngIf="showProductConfig" class="btn btn-outline-primary"
[disabled]="isItemSelected(item.product)"
(click)="handleAddToConfiguration(item.product, quantityControlValues[item.product.Name + i], item.product.Name + i, warning.targetBundleNumber)"
[ladda]="loading[item.product.Name + i]"
data-style="zoom-in">{{ "COMMON.ADD" | translate }}</button>
</div>
</div>
</div>
</ng-container>
</div>
<div class="card-footer bg-white border-0 py-2">
</div>
</ng-container>
<!-- Exclusion -->
<ng-container *ngSwitchCase="'Exclusion'">
<div class="card-body bg-white py-2 flex-column" [class.border-top]="i > 0">
<ng-container *ngIf="warning.messageHtml !== null;">
<span [innerHtml]="warning.messageHtml"></span>
</ng-container>
<ng-container *ngFor="let item of warning.actionItems">
<div class="py-3">
<a class="pt-2" href="javascript:void(0)"
[routerLink]="['/products/', item.product.Id]">{{item.product.Name}}</a>
<div class="d-flex py-2 align-items-center justify-content-between">
<small class="font-weight-bold">{{item.chargeType}}</small>
<small class="font-weight-bold">
<apt-price [record]="item.product" [type]="'list'"></apt-price>
</small>
</div>
<div class="d-flex align-items-center justify-content-end">
<label [for]="item.product.Name + i" class="mr-2 mb-0">{{ "COMMON.QTY" | translate }}</label>
<input class="form-control mr-2 w-25" [id]="item.product.Name + i" type="number" min="1"
[(ngModel)]="quantityControlValues[item.product.Name + i]" placeholder="1">
<div class="input-group-append">
<button *ngIf="!showProductConfig" class="btn btn-outline-danger"
(click)="handleDeleteFromCart(warning, item.product, item.product?.Name + i)"
[ladda]="loading[item.product?.Name + i]"
data-style="zoom-in">{{ "CONSTRAINT_SIDE_MENU.REMOVE_FROM_CART" | translate }}</button>
<button *ngIf="showProductConfig" class="btn btn-outline-danger"
[disabled]="!isItemSelected(item.product, 'remove')"
(click)="handleRemoveFromBundle(item.product, warning.triggeringProducts[0], item.product?.Name + i)"
[ladda]="loading[item.product?.Name + i]"
data-style="zoom-in">{{ "COMMON.REMOVE" | translate }}</button>
</div>
</div>
</div>
</ng-container>
</div>
<div class="card-footer bg-white border-0 py-2">
</div>
</ng-container>
<!-- Validation -->
<ng-container *ngSwitchCase="'Validation'">
<div class="card-body bg-white py-2 d-flex-column" [class.border-top]="i > 0">
<ng-container *ngIf="warning.messageHtml !== null;">
<div [innerHtml]="warning.messageHtml"></div>
</ng-container>
</div>
</ng-container>
<!-- Recommendation -->
<ng-container *ngSwitchCase="'Recommendation'">
<div class="card-body bg-white py-2 d-flex-column" [class.border-top]="i > 0">
<ng-container *ngIf="warning.messageHtml !== null;">
<div [innerHtml]="warning.messageHtml"></div>
</ng-container>
</div>
</ng-container>
<!-- Replacement -->
<ng-container *ngSwitchCase="'Replacement'">
<div class="card-body bg-white py-2 d-flex-column" [class.border-top]="i > 0">
<ng-container *ngIf="warning.messageHtml !== null;">
<div [innerHtml]="warning.messageHtml"></div>
</ng-container>
</div>
</ng-container>
</ng-container>
</ng-container>
</div>
<!-- Info Messages -->
<!-- <div *ngIf="ruleDetailGroups.info.length > 0" class="card border-0">
<div class="card-header border-bottom-0 border-top">
<i class="fas fa-info-circle"></i> <span> {{ruleDetailGroups.info.length}}</span> {{ruleDetailGroups.info.length > 1 ? 'Information Messages' : 'Information Message'}}
</div>
<ng-container *ngFor="let info of data.infoMessages; let i = index">
<div class="card-body bg-white py-2" [class.border-top]="i > 0">
<strong>{{info.includedProduct.name}}</strong> is included with product <a href="javascript:void(0)">{{info.product.name}}</a>.
</div>
<div class="card-footer bg-white border-0 py-2">
<div class="d-flex justify-content-end">
<button class="btn btn-outline-danger">Delete All</button>
</div>
</div>
</ng-container>
</div> -->
<!-- Success Messages -->
<div *ngIf="ruleDetailGroups.success.length > 0" class="card border-0">
<div class="card-header border-bottom-0 border-top">
<i class="fas fa-info-circle"></i> <span>
{{ (ruleDetailGroups.success.length > 1 ? "CONSTRAINT_SIDE_MENU.NUM_OF_INFO_MESSAGES.PLURAL" : "CONSTRAINT_SIDE_MENU.NUM_OF_INFO_MESSAGES.ONE") | translate: {amount: ruleDetailGroups.success.length} }}</span>
</div>
<ng-container *ngFor="let success of ruleDetailGroups.success; let i = index">
<div class="card-body bg-white py-2" [class.border-top]="i > 0">
<ng-container *ngIf="success.message !== null;">
<span [innerHtml]="success.message"></span>
</ng-container>
</div>
</ng-container>
</div>
</div>
</ng-container>
</ng-container>
./constraint-rule-sidebar.component.scss
.modal.show {
div.constraintRuleSidebar.modal-dialog {
background-color: white;
right: -1px;
top: 0px;
}
}
.modal {
div.constraintRuleSidebar.modal-dialog {
position: absolute;
transition: right 300ms;
margin: -1px 0px 0px 0px;
right: -20rem;
width: 20rem;
.modal-content{
height: 100vh;
overflow-y: auto;
}
}
}