UNPKG

@spartacus/storefront

Version:

Spartacus Storefront is a package that you can include in your application, which allows you to add default storefront features.

94 lines 26.8 kB
import { ChangeDetectionStrategy, Component, ViewChild, } from '@angular/core'; import { Validators } from '@angular/forms'; import { distinctUntilChanged, filter, map, switchMap, tap, } from 'rxjs/operators'; import { CustomFormValidators } from '../../../../shared/index'; import * as i0 from "@angular/core"; import * as i1 from "@spartacus/core"; import * as i2 from "../../current-product.service"; import * as i3 from "@angular/forms"; import * as i4 from "../../../../shared/components/star-rating/star-rating.component"; import * as i5 from "../../../../shared/components/form/form-errors/form-errors.component"; import * as i6 from "@angular/common"; export class ProductReviewsComponent { constructor(reviewService, currentProductService, fb, cd) { this.reviewService = reviewService; this.currentProductService = currentProductService; this.fb = fb; this.cd = cd; this.isWritingReview = false; // TODO: configurable this.initialMaxListItems = 5; this.product$ = this.currentProductService.getProduct(); this.reviews$ = this.product$.pipe(filter((p) => !!p), map((p) => p.code), distinctUntilChanged(), switchMap((productCode) => this.reviewService.getByProductCode(productCode)), tap(() => { this.resetReviewForm(); this.maxListItems = this.initialMaxListItems; })); } initiateWriteReview() { this.isWritingReview = true; this.cd.detectChanges(); if (this.titleInput && this.titleInput.nativeElement) { this.titleInput.nativeElement.focus(); } } cancelWriteReview() { this.isWritingReview = false; this.resetReviewForm(); this.cd.detectChanges(); if (this.writeReviewButton && this.writeReviewButton.nativeElement) { this.writeReviewButton.nativeElement.focus(); } } setRating(rating) { this.reviewForm.controls.rating.setValue(rating); } submitReview(product) { if (this.reviewForm.valid) { this.addReview(product); } else { this.reviewForm.markAllAsTouched(); } } addReview(product) { const reviewFormControls = this.reviewForm.controls; const review = { headline: reviewFormControls.title.value, comment: reviewFormControls.comment.value, rating: reviewFormControls.rating.value, alias: reviewFormControls.reviewerName.value, }; this.reviewService.add(product.code, review); this.isWritingReview = false; this.resetReviewForm(); this.cd.detectChanges(); if (this.writeReviewButton && this.writeReviewButton.nativeElement) { this.writeReviewButton.nativeElement.focus(); } } resetReviewForm() { this.reviewForm = this.fb.group({ title: ['', Validators.required], comment: ['', Validators.required], rating: [null, CustomFormValidators.starRatingEmpty], reviewerName: '', }); } } ProductReviewsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: ProductReviewsComponent, deps: [{ token: i1.ProductReviewService }, { token: i2.CurrentProductService }, { token: i3.FormBuilder }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); ProductReviewsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.0.5", type: ProductReviewsComponent, selector: "cx-product-reviews", viewQueries: [{ propertyName: "titleInput", first: true, predicate: ["titleInput"], descendants: true }, { propertyName: "writeReviewButton", first: true, predicate: ["writeReviewButton"], descendants: true }], ngImport: i0, template: "<div class=\"container\" *ngIf=\"product$ | async as product\">\n <h2>\n {{ 'productDetails.reviews' | cxTranslate }} ({{ product.numberOfReviews }})\n </h2>\n <ng-container *ngIf=\"!isWritingReview; else writeReview\">\n <div class=\"header\">\n <h3>{{ 'productReview.overallRating' | cxTranslate }}</h3>\n <button\n #writeReviewButton\n class=\"btn btn-primary\"\n (click)=\"initiateWriteReview()\"\n >\n {{ 'productReview.writeReview' | cxTranslate }}\n </button>\n <cx-star-rating\n *ngIf=\"product.averageRating\"\n class=\"rating\"\n [rating]=\"product.averageRating\"\n ></cx-star-rating>\n <div class=\"rating\" *ngIf=\"!product.averageRating\">\n {{ 'productDetails.noReviews' | cxTranslate }}\n </div>\n </div>\n\n <ng-container *ngIf=\"!isWritingReview; else writeReview\">\n <ng-container *ngIf=\"reviews$ | async as reviews\">\n <div\n class=\"review\"\n tabindex=\"0\"\n *ngFor=\"let review of reviews | slice: 0:maxListItems\"\n >\n <div class=\"title\">{{ review.headline }}</div>\n <cx-star-rating [rating]=\"review.rating\"></cx-star-rating>\n <div class=\"name\">\n {{ review.alias ? review.alias : review.principal?.name }}\n </div>\n <div class=\"date\">{{ review.date | cxDate }}</div>\n <div class=\"text\">{{ review.comment }}</div>\n </div>\n <div *ngIf=\"reviews.length > initialMaxListItems\">\n <button\n class=\"btn btn-primary\"\n (click)=\"maxListItems = reviews.length\"\n *ngIf=\"maxListItems === initialMaxListItems\"\n >\n {{ 'productReview.more' | cxTranslate }}\n </button>\n <button\n class=\"btn btn-primary\"\n (click)=\"maxListItems = initialMaxListItems\"\n *ngIf=\"maxListItems !== initialMaxListItems\"\n >\n {{ 'productReview.less' | cxTranslate }}\n </button>\n </div>\n </ng-container>\n </ng-container>\n </ng-container>\n\n <ng-template #writeReview>\n <form (ngSubmit)=\"submitReview(product)\" [formGroup]=\"reviewForm\">\n <div class=\"form-group\">\n <label>\n <span class=\"label-content\">{{\n 'productReview.reviewTitle' | cxTranslate\n }}</span>\n <input\n aria-required=\"true\"\n #titleInput\n type=\"text\"\n class=\"form-control\"\n formControlName=\"title\"\n />\n <cx-form-errors\n aria-live=\"assertive\"\n aria-atomic=\"true\"\n [control]=\"reviewForm.get('title')\"\n ></cx-form-errors>\n </label>\n </div>\n <div class=\"form-group\">\n <label>\n <span class=\"label-content\">{{\n 'productReview.writeYourComments' | cxTranslate\n }}</span>\n <textarea\n aria-required=\"true\"\n class=\"form-control\"\n rows=\"3\"\n formControlName=\"comment\"\n ></textarea>\n <cx-form-errors\n aria-live=\"assertive\"\n aria-atomic=\"true\"\n [control]=\"reviewForm.get('comment')\"\n ></cx-form-errors>\n </label>\n </div>\n <div class=\"form-group\">\n <label>\n <span class=\"label-content\">{{\n 'productReview.rating' | cxTranslate\n }}</span>\n <input\n aria-required=\"true\"\n type=\"number\"\n formControlName=\"rating\"\n class=\"rating-input\"\n />\n <cx-star-rating\n (change)=\"setRating($event)\"\n [disabled]=\"false\"\n ></cx-star-rating>\n <cx-form-errors\n aria-live=\"assertive\"\n aria-atomic=\"true\"\n [control]=\"reviewForm.get('rating')\"\n ></cx-form-errors>\n </label>\n </div>\n <div class=\"form-group\">\n <label>\n <span class=\"label-content\">{{\n 'productReview.reviewerName' | cxTranslate\n }}</span>\n <input\n type=\"text\"\n class=\"form-control\"\n formControlName=\"reviewerName\"\n />\n </label>\n </div>\n <div class=\"form-group row\">\n <div class=\"col-12 col-md-4\">\n <button\n type=\"button\"\n class=\"btn btn-block btn-secondary\"\n (click)=\"cancelWriteReview()\"\n >\n {{ 'common.cancel' | cxTranslate }}\n </button>\n </div>\n <div class=\"col-12 col-md-4\">\n <button type=\"submit\" class=\"btn btn-block btn-primary\">\n {{ 'common.submit' | cxTranslate }}\n </button>\n </div>\n </div>\n </form>\n </ng-template>\n</div>\n", components: [{ type: i4.StarRatingComponent, selector: "cx-star-rating", inputs: ["disabled", "rating"], outputs: ["change"] }, { type: i5.FormErrorsComponent, selector: "cx-form-errors", inputs: ["prefix", "translationParams", "control"] }], directives: [{ type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i3.FormControlName, selector: "[formControlName]", inputs: ["disabled", "formControlName", "ngModel"], outputs: ["ngModelChange"] }, { type: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }], pipes: { "async": i6.AsyncPipe, "cxTranslate": i1.TranslatePipe, "slice": i6.SlicePipe, "cxDate": i1.CxDatePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.0.5", ngImport: i0, type: ProductReviewsComponent, decorators: [{ type: Component, args: [{ selector: 'cx-product-reviews', templateUrl: './product-reviews.component.html', changeDetection: ChangeDetectionStrategy.OnPush, }] }], ctorParameters: function () { return [{ type: i1.ProductReviewService }, { type: i2.CurrentProductService }, { type: i3.FormBuilder }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { titleInput: [{ type: ViewChild, args: ['titleInput', { static: false }] }], writeReviewButton: [{ type: ViewChild, args: ['writeReviewButton', { static: false }] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZHVjdC1yZXZpZXdzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3N0b3JlZnJvbnRsaWIvY21zLWNvbXBvbmVudHMvcHJvZHVjdC9wcm9kdWN0LXRhYnMvcHJvZHVjdC1yZXZpZXdzL3Byb2R1Y3QtcmV2aWV3cy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zdG9yZWZyb250bGliL2Ntcy1jb21wb25lbnRzL3Byb2R1Y3QvcHJvZHVjdC10YWJzL3Byb2R1Y3QtcmV2aWV3cy9wcm9kdWN0LXJldmlld3MuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsU0FBUyxHQUdWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBMEIsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFHcEUsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixNQUFNLEVBQ04sR0FBRyxFQUNILFNBQVMsRUFDVCxHQUFHLEdBQ0osTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7Ozs7Ozs7QUFPaEUsTUFBTSxPQUFPLHVCQUF1QjtJQTJCbEMsWUFDWSxhQUFtQyxFQUNuQyxxQkFBNEMsRUFDOUMsRUFBZSxFQUNiLEVBQXFCO1FBSHJCLGtCQUFhLEdBQWIsYUFBYSxDQUFzQjtRQUNuQywwQkFBcUIsR0FBckIscUJBQXFCLENBQXVCO1FBQzlDLE9BQUUsR0FBRixFQUFFLENBQWE7UUFDYixPQUFFLEdBQUYsRUFBRSxDQUFtQjtRQTFCakMsb0JBQWUsR0FBRyxLQUFLLENBQUM7UUFFeEIscUJBQXFCO1FBQ3JCLHdCQUFtQixHQUFHLENBQUMsQ0FBQztRQUl4QixhQUFRLEdBQXdCLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxV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Q0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDO1lBQzlCLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsUUFBUSxDQUFDO1lBQ2hDLE9BQU8sRUFBRSxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsUUFBUSxDQUFDO1lBQ2xDLE1BQU0sRUFBRSxDQUFDLElBQUksRUFBRSxvQkFBb0IsQ0FBQyxlQUFlLENBQUM7WUFDcEQsWUFBWSxFQUFFLEVBQUU7U0FDakIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7b0hBL0ZVLHVCQUF1Qjt3R0FBdkIsdUJBQXVCLDZRQ3pCcEMsbzZKQXVKQTsyRkQ5SGEsdUJBQXVCO2tCQUxuQyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxvQkFBb0I7b0JBQzlCLFdBQVcsRUFBRSxrQ0FBa0M7b0JBQy9DLGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO2lCQUNoRDt5TUFFNkMsVUFBVTtzQkFBckQsU0FBUzt1QkFBQyxZQUFZLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFO2dCQUUxQyxpQkFBaUI7c0JBRGhCLFNBQVM7dUJBQUMsbUJBQW1CLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgVmlld0NoaWxkLFxuICBFbGVtZW50UmVmLFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtQnVpbGRlciwgRm9ybUdyb3VwLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgUHJvZHVjdCwgUHJvZHVjdFJldmlld1NlcnZpY2UsIFJldmlldyB9IGZyb20gJ0BzcGFydGFjdXMvY29yZSc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge1xuICBkaXN0aW5jdFVudGlsQ2hhbmdlZCxcbiAgZmlsdGVyLFxuICBtYXAsXG4gIHN3aXRjaE1hcCxcbiAgdGFwLFxufSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBDdXJyZW50UHJvZHVjdFNlcnZpY2UgfSBmcm9tICcuLi8uLi9jdXJyZW50LXByb2R1Y3Quc2VydmljZSc7XG5pbXBvcnQgeyBDdXN0b21Gb3JtVmFsaWRhdG9ycyB9IGZyb20gJy4uLy4uLy4uLy4uL3NoYXJlZC9pbmRleCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2N4LXByb2R1Y3QtcmV2aWV3cycsXG4gIHRlbXBsYXRlVXJsOiAnLi9wcm9kdWN0LXJldmlld3MuY29tcG9uZW50Lmh0bWwnLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgUHJvZHVjdFJldmlld3NDb21wb25lbnQge1xuICBAVmlld0NoaWxkKCd0aXRsZUlucHV0JywgeyBzdGF0aWM6IGZhbHNlIH0pIHRpdGxlSW5wdXQ6IEVsZW1lbnRSZWY7XG4gIEBWaWV3Q2hpbGQoJ3dyaXRlUmV2aWV3QnV0dG9uJywgeyBzdGF0aWM6IGZhbHNlIH0pXG4gIHdyaXRlUmV2aWV3QnV0dG9uOiBFbGVtZW50UmVmO1xuXG4gIGlzV3JpdGluZ1JldmlldyA9IGZhbHNlO1xuXG4gIC8vIFRPRE86IGNvbmZpZ3VyYWJsZVxuICBpbml0aWFsTWF4TGlzdEl0ZW1zID0gNTtcbiAgbWF4TGlzdEl0ZW1zOiBudW1iZXI7XG4gIHJldmlld0Zvcm06IEZvcm1Hcm91cDtcblxuICBwcm9kdWN0JDogT2JzZXJ2YWJsZTxQcm9kdWN0PiA9IHRoaXMuY3VycmVudFByb2R1Y3RTZXJ2aWNlLmdldFByb2R1Y3QoKTtcblxuICByZXZpZXdzJDogT2JzZXJ2YWJsZTxSZXZpZXdbXT4gPSB0aGlzLnByb2R1Y3QkLnBpcGUoXG4gICAgZmlsdGVyKChwKSA9PiAhIXApLFxuICAgIG1hcCgocCkgPT4gcC5jb2RlKSxcbiAgICBkaXN0aW5jdFVudGlsQ2hhbmdlZCgpLFxuICAgIHN3aXRjaE1hcCgocHJvZHVjdENvZGUpID0+XG4gICAgICB0aGlzLnJldmlld1NlcnZpY2UuZ2V0QnlQcm9kdWN0Q29kZShwcm9kdWN0Q29kZSlcbiAgICApLFxuICAgIHRhcCgoKSA9PiB7XG4gICAgICB0aGlzLnJlc2V0UmV2aWV3Rm9ybSgpO1xuICAgICAgdGhpcy5tYXhMaXN0SXRlbXMgPSB0aGlzLmluaXRpYWxNYXhMaXN0SXRlbXM7XG4gICAgfSlcbiAgKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgcmV2aWV3U2VydmljZTogUHJvZHVjdFJldmlld1NlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGN1cnJlbnRQcm9kdWN0U2VydmljZTogQ3VycmVudFByb2R1Y3RTZXJ2aWNlLFxuICAgIHByaXZhdGUgZmI6IEZvcm1CdWlsZGVyLFxuICAgIHByb3RlY3RlZCBjZDogQ2hhbmdlRGV0ZWN0b3JSZWZcbiAgKSB7fVxuXG4gIGluaXRpYXRlV3JpdGVSZXZpZXcoKTogdm9pZCB7XG4gICAgdGhpcy5pc1dyaXRpbmdSZXZpZXcgPSB0cnVlO1xuXG4gICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG5cbiAgICBpZiAodGhpcy50aXRsZUlucHV0ICYmIHRoaXMudGl0bGVJbnB1dC5uYXRpdmVFbGVtZW50KSB7XG4gICAgICB0aGlzLnRpdGxlSW5wdXQubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICAgIH1cbiAgfVxuXG4gIGNhbmNlbFdyaXRlUmV2aWV3KCk6IHZvaWQge1xuICAgIHRoaXMuaXNXcml0aW5nUmV2aWV3ID0gZmFsc2U7XG4gICAgdGhpcy5yZXNldFJldmlld0Zvcm0oKTtcblxuICAgIHRoaXMuY2QuZGV0ZWN0Q2hhbmdlcygpO1xuXG4gICAgaWYgKHRoaXMud3JpdGVSZXZpZXdCdXR0b24gJiYgdGhpcy53cml0ZVJldmlld0J1dHRvbi5uYXRpdmVFbGVtZW50KSB7XG4gICAgICB0aGlzLndyaXRlUmV2aWV3QnV0dG9uLm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgICB9XG4gIH1cblxuICBzZXRSYXRpbmcocmF0aW5nOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLnJldmlld0Zvcm0uY29udHJvbHMucmF0aW5nLnNldFZhbHVlKHJhdGluZyk7XG4gIH1cblxuICBzdWJtaXRSZXZpZXcocHJvZHVjdDogUHJvZHVjdCkge1xuICAgIGlmICh0aGlzLnJldmlld0Zvcm0udmFsaWQpIHtcbiAgICAgIHRoaXMuYWRkUmV2aWV3KHByb2R1Y3QpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJldmlld0Zvcm0ubWFya0FsbEFzVG91Y2hlZCgpO1xuICAgIH1cbiAgfVxuXG4gIGFkZFJldmlldyhwcm9kdWN0OiBQcm9kdWN0KTogdm9pZCB7XG4gICAgY29uc3QgcmV2aWV3Rm9ybUNvbnRyb2xzID0gdGhpcy5yZXZpZXdGb3JtLmNvbnRyb2xzO1xuICAgIGNvbnN0IHJldmlldzogUmV2aWV3ID0ge1xuICAgICAgaGVhZGxpbmU6IHJldmlld0Zvcm1Db250cm9scy50aXRsZS52YWx1ZSxcbiAgICAgIGNvbW1lbnQ6IHJldmlld0Zvcm1Db250cm9scy5jb21tZW50LnZhbHVlLFxuICAgICAgcmF0aW5nOiByZXZpZXdGb3JtQ29udHJvbHMucmF0aW5nLnZhbHVlLFxuICAgICAgYWxpYXM6IHJldmlld0Zvcm1Db250cm9scy5yZXZpZXdlck5hbWUudmFsdWUsXG4gICAgfTtcblxuICAgIHRoaXMucmV2aWV3U2VydmljZS5hZGQocHJvZHVjdC5jb2RlLCByZXZpZXcpO1xuXG4gICAgdGhpcy5pc1dyaXRpbmdSZXZpZXcgPSBmYWxzZTtcbiAgICB0aGlzLnJlc2V0UmV2aWV3Rm9ybSgpO1xuXG4gICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG5cbiAgICBpZiAodGhpcy53cml0ZVJldmlld0J1dHRvbiAmJiB0aGlzLndyaXRlUmV2aWV3QnV0dG9uLm5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgIHRoaXMud3JpdGVSZXZpZXdCdXR0b24ubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVzZXRSZXZpZXdGb3JtKCk6IHZvaWQge1xuICAgIHRoaXMucmV2aWV3Rm9ybSA9IHRoaXMuZmIuZ3JvdXAoe1xuICAgICAgdGl0bGU6IFsnJywgVmFsaWRhdG9ycy5yZXF1aXJlZF0sXG4gICAgICBjb21tZW50OiBbJycsIFZhbGlkYXRvcnMucmVxdWlyZWRdLFxuICAgICAgcmF0aW5nOiBbbnVsbCwgQ3VzdG9tRm9ybVZhbGlkYXRvcnMuc3RhclJhdGluZ0VtcHR5XSxcbiAgICAgIHJldmlld2VyTmFtZTogJycsXG4gICAgfSk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJjb250YWluZXJcIiAqbmdJZj1cInByb2R1Y3QkIHwgYXN5bmMgYXMgcHJvZHVjdFwiPlxuICA8aDI+XG4gICAge3sgJ3Byb2R1Y3REZXRhaWxzLnJldmlld3MnIHwgY3hUcmFuc2xhdGUgfX0gKHt7IHByb2R1Y3QubnVtYmVyT2ZSZXZpZXdzIH19KVxuICA8L2gyPlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWlzV3JpdGluZ1JldmlldzsgZWxzZSB3cml0ZVJldmlld1wiPlxuICAgIDxkaXYgY2xhc3M9XCJoZWFkZXJcIj5cbiAgICAgIDxoMz57eyAncHJvZHVjdFJldmlldy5vdmVyYWxsUmF0aW5nJyB8IGN4VHJhbnNsYXRlIH19PC9oMz5cbiAgICAgIDxidXR0b25cbiAgICAgICAgI3dyaXRlUmV2aWV3QnV0dG9uXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5XCJcbiAgICAgICAgKGNsaWNrKT1cImluaXRpYXRlV3JpdGVSZXZpZXcoKVwiXG4gICAgICA+XG4gICAgICAgIHt7ICdwcm9kdWN0UmV2aWV3LndyaXRlUmV2aWV3JyB8IGN4VHJhbnNsYXRlIH19XG4gICAgICA8L2J1dHRvbj5cbiAgICAgIDxjeC1zdGFyLXJhdGluZ1xuICAgICAgICAqbmdJZj1cInByb2R1Y3QuYXZlcmFnZVJhdGluZ1wiXG4gICAgICAgIGNsYXNzPVwicmF0aW5nXCJcbiAgICAgICAgW3JhdGluZ109XCJwcm9kdWN0LmF2ZXJhZ2VSYXRpbmdcIlxuICAgICAgPjwvY3gtc3Rhci1yYXRpbmc+XG4gICAgICA8ZGl2IGNsYXNzPVwicmF0aW5nXCIgKm5nSWY9XCIhcHJvZHVjdC5hdmVyYWdlUmF0aW5nXCI+XG4gICAgICAgIHt7ICdwcm9kdWN0RGV0YWlscy5ub1Jldmlld3MnIHwgY3hUcmFuc2xhdGUgfX1cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFpc1dyaXRpbmdSZXZpZXc7IGVsc2Ugd3JpdGVSZXZpZXdcIj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJyZXZpZXdzJCB8IGFzeW5jIGFzIHJldmlld3NcIj5cbiAgICAgICAgPGRpdlxuICAgICAgICAgIGNsYXNzPVwicmV2aWV3XCJcbiAgICAgICAgICB0YWJpbmRleD1cIjBcIlxuICAgICAgICAgICpuZ0Zvcj1cImxldCByZXZpZXcgb2YgcmV2aWV3cyB8IHNsaWNlOiAwOm1heExpc3RJdGVtc1wiXG4gICAgICAgID5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwidGl0bGVcIj57eyByZXZpZXcuaGVhZGxpbmUgfX08L2Rpdj5cbiAgICAgICAgICA8Y3gtc3Rhci1yYXRpbmcgW3JhdGluZ109XCJyZXZpZXcucmF0aW5nXCI+PC9jeC1zdGFyLXJhdGluZz5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwibmFtZVwiPlxuICAgICAgICAgICAge3sgcmV2aWV3LmFsaWFzID8gcmV2aWV3LmFsaWFzIDogcmV2aWV3LnByaW5jaXBhbD8ubmFtZSB9fVxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJkYXRlXCI+e3sgcmV2aWV3LmRhdGUgfCBjeERhdGUgfX08L2Rpdj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwidGV4dFwiPnt7IHJldmlldy5jb21tZW50IH19PC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2ICpuZ0lmPVwicmV2aWV3cy5sZW5ndGggPiBpbml0aWFsTWF4TGlzdEl0ZW1zXCI+XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnlcIlxuICAgICAgICAgICAgKGNsaWNrKT1cIm1heExpc3RJdGVtcyA9IHJldmlld3MubGVuZ3RoXCJcbiAgICAgICAgICAgICpuZ0lmPVwibWF4TGlzdEl0ZW1zID09PSBpbml0aWFsTWF4TGlzdEl0ZW1zXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICB7eyAncHJvZHVjdFJldmlldy5tb3JlJyB8IGN4VHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnlcIlxuICAgICAgICAgICAgKGNsaWNrKT1cIm1heExpc3RJdGVtcyA9IGluaXRpYWxNYXhMaXN0SXRlbXNcIlxuICAgICAgICAgICAgKm5nSWY9XCJtYXhMaXN0SXRlbXMgIT09IGluaXRpYWxNYXhMaXN0SXRlbXNcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIHt7ICdwcm9kdWN0UmV2aWV3Lmxlc3MnIHwgY3hUcmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgPC9uZy1jb250YWluZXI+XG5cbiAgPG5nLXRlbXBsYXRlICN3cml0ZVJldmlldz5cbiAgICA8Zm9ybSAobmdTdWJtaXQpPVwic3VibWl0UmV2aWV3KHByb2R1Y3QpXCIgW2Zvcm1Hcm91cF09XCJyZXZpZXdGb3JtXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgICA8bGFiZWw+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJsYWJlbC1jb250ZW50XCI+e3tcbiAgICAgICAgICAgICdwcm9kdWN0UmV2aWV3LnJldmlld1RpdGxlJyB8IGN4VHJhbnNsYXRlXG4gICAgICAgICAgfX08L3NwYW4+XG4gICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICBhcmlhLXJlcXVpcmVkPVwidHJ1ZVwiXG4gICAgICAgICAgICAjdGl0bGVJbnB1dFxuICAgICAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwidGl0bGVcIlxuICAgICAgICAgIC8+XG4gICAgICAgICAgPGN4LWZvcm0tZXJyb3JzXG4gICAgICAgICAgICBhcmlhLWxpdmU9XCJhc3NlcnRpdmVcIlxuICAgICAgICAgICAgYXJpYS1hdG9taWM9XCJ0cnVlXCJcbiAgICAgICAgICAgIFtjb250cm9sXT1cInJldmlld0Zvcm0uZ2V0KCd0aXRsZScpXCJcbiAgICAgICAgICA+PC9jeC1mb3JtLWVycm9ycz5cbiAgICAgICAgPC9sYWJlbD5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgICAgPGxhYmVsPlxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwibGFiZWwtY29udGVudFwiPnt7XG4gICAgICAgICAgICAncHJvZHVjdFJldmlldy53cml0ZVlvdXJDb21tZW50cycgfCBjeFRyYW5zbGF0ZVxuICAgICAgICAgIH19PC9zcGFuPlxuICAgICAgICAgIDx0ZXh0YXJlYVxuICAgICAgICAgICAgYXJpYS1yZXF1aXJlZD1cInRydWVcIlxuICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgICAgICAgcm93cz1cIjNcIlxuICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiY29tbWVudFwiXG4gICAgICAgICAgPjwvdGV4dGFyZWE+XG4gICAgICAgICAgPGN4LWZvcm0tZXJyb3JzXG4gICAgICAgICAgICBhcmlhLWxpdmU9XCJhc3NlcnRpdmVcIlxuICAgICAgICAgICAgYXJpYS1hdG9taWM9XCJ0cnVlXCJcbiAgICAgICAgICAgIFtjb250cm9sXT1cInJldmlld0Zvcm0uZ2V0KCdjb21tZW50JylcIlxuICAgICAgICAgID48L2N4LWZvcm0tZXJyb3JzPlxuICAgICAgICA8L2xhYmVsPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgICA8bGFiZWw+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJsYWJlbC1jb250ZW50XCI+e3tcbiAgICAgICAgICAgICdwcm9kdWN0UmV2aWV3LnJhdGluZycgfCBjeFRyYW5zbGF0ZVxuICAgICAgICAgIH19PC9zcGFuPlxuICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgYXJpYS1yZXF1aXJlZD1cInRydWVcIlxuICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXG4gICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyYXRpbmdcIlxuICAgICAgICAgICAgY2xhc3M9XCJyYXRpbmctaW5wdXRcIlxuICAgICAgICAgIC8+XG4gICAgICAgICAgPGN4LXN0YXItcmF0aW5nXG4gICAgICAgICAgICAoY2hhbmdlKT1cInNldFJhdGluZygkZXZlbnQpXCJcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCJmYWxzZVwiXG4gICAgICAgICAgPjwvY3gtc3Rhci1yYXRpbmc+XG4gICAgICAgICAgPGN4LWZvcm0tZXJyb3JzXG4gICAgICAgICAgICBhcmlhLWxpdmU9XCJhc3NlcnRpdmVcIlxuICAgICAgICAgICAgYXJpYS1hdG9taWM9XCJ0cnVlXCJcbiAgICAgICAgICAgIFtjb250cm9sXT1cInJldmlld0Zvcm0uZ2V0KCdyYXRpbmcnKVwiXG4gICAgICAgICAgPjwvY3gtZm9ybS1lcnJvcnM+XG4gICAgICAgIDwvbGFiZWw+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICAgIDxsYWJlbD5cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cImxhYmVsLWNvbnRlbnRcIj57e1xuICAgICAgICAgICAgJ3Byb2R1Y3RSZXZpZXcucmV2aWV3ZXJOYW1lJyB8IGN4VHJhbnNsYXRlXG4gICAgICAgICAgfX08L3NwYW4+XG4gICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZXZpZXdlck5hbWVcIlxuICAgICAgICAgIC8+XG4gICAgICAgIDwvbGFiZWw+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwIHJvd1wiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIGNvbC1tZC00XCI+XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICBjbGFzcz1cImJ0biBidG4tYmxvY2sgYnRuLXNlY29uZGFyeVwiXG4gICAgICAgICAgICAoY2xpY2spPVwiY2FuY2VsV3JpdGVSZXZpZXcoKVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAge3sgJ2NvbW1vbi5jYW5jZWwnIHwgY3hUcmFuc2xhdGUgfX1cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtMTIgY29sLW1kLTRcIj5cbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJzdWJtaXRcIiBjbGFzcz1cImJ0biBidG4tYmxvY2sgYnRuLXByaW1hcnlcIj5cbiAgICAgICAgICAgIHt7ICdjb21tb24uc3VibWl0JyB8IGN4VHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9mb3JtPlxuICA8L25nLXRlbXBsYXRlPlxuPC9kaXY+XG4iXX0=