UNPKG

@progress/telerik-angular-native-report-viewer

Version:

Progress® Telerik® Native Report Viewer for Angular

104 lines 32.9 kB
import { Component, Input, ViewEncapsulation } from '@angular/core'; import { xIcon } from '@progress/kendo-svg-icons'; import * as i0 from "@angular/core"; import * as i1 from "../reporting-angular-viewer.service"; import * as i2 from "@angular/common"; import * as i3 from "@progress/kendo-angular-dialog"; import * as i4 from "@progress/kendo-angular-buttons"; import * as i5 from "@progress/kendo-angular-conversational-ui"; import * as i6 from "@progress/kendo-angular-utils"; export class AiPromptComponent { constructor(renderer, el, service) { this.renderer = renderer; this.el = el; this.service = service; this.windowTop = 80; this.xIcon = xIcon; this.activeView = 0; this.showConsent = true; this.requireConsent = true; this.allowCustomPrompts = true; this.idCounter = 0; } ngOnInit() { const reportElemWidth = this.service.reportWidth; this.windowWidth = 500; this.windowLeft = reportElemWidth - (this.windowWidth + 20); const aiConfigurationOptions = this.service.controller.getAiConfigurationOptions(); this.requireConsent = aiConfigurationOptions.requireConsent; this.allowCustomPrompts = aiConfigurationOptions.allowCustomPrompts; this.showConsent = this.requireConsent && this.service.controller.loadFromSessionStorage("trvAiConsent") !== "true"; this.onActiveViewChange(this.activeView); } toggle(isOpened) { this.service.isAiPromptWindowOpen = isOpened; } onWidthChange(width) { this.service.windowWidth = width; } onHeightChange(height) { this.service.windowHeight = height; } onPromptRequest(event) { const generateButtonEl = this.el.nativeElement.querySelector('.k-prompt-footer .k-actions .k-button'); generateButtonEl && this.renderer.addClass(generateButtonEl, 'k-disabled'); this.service.controller.getAIResponse(event.prompt) .then(response => { this.promptOutputs.unshift(this.createPromptOutputFromResponse(response, event)); generateButtonEl && this.renderer.removeClass(generateButtonEl, 'k-disabled'); this.activeView = 1; }).catch(error => { this.promptOutputs.unshift(this.createPromptOutputFromResponse(error?._responseJSON, event)); generateButtonEl && this.renderer.removeClass(generateButtonEl, 'k-disabled'); this.activeView = 1; }); } onActiveViewChange(viewId) { // The Kendo event is triggered before the new AI prompt view is rendered so the textarea doesn't exist // Wrap the call in setTimeout in order to have the textarea element present before setting the disabled class if (viewId === 0 && !this.allowCustomPrompts) { setTimeout(() => { let textAreaPlaceholder = 'Enter your prompt'; const textAreaEl = this.el.nativeElement.querySelector('.k-textarea textarea'); if (!(this.predefinedPrompts && this.predefinedPrompts.length > 0)) { const aiPromptGenerateButton = this.el.nativeElement.querySelector('.k-prompt-footer'); aiPromptGenerateButton && this.renderer.addClass(aiPromptGenerateButton, 'k-disabled'); textAreaPlaceholder = 'Custom prompts are disabled and there are no predefined prompts configured. Please allow custom prompts or add predefined prompts to use the AI feature.'; } else { textAreaPlaceholder = 'Custom prompts are disabled, please select one of the suggestions below'; } if (textAreaEl) { this.renderer.addClass(textAreaEl, 'k-disabled'); this.renderer.setAttribute(textAreaEl, 'placeholder', textAreaPlaceholder); } }, 50); } } consentCancel() { this.toggle(false); } async consentAccept() { this.showConsent = false; this.service.controller.saveToSessionStorage('trvAiConsent', 'true'); } createPromptOutputFromResponse(response, promptData) { return { id: this.idCounter++, output: response, prompt: promptData.prompt, isRetry: promptData.isRetry, }; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AiPromptComponent, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i1.ReportingAngularViewerService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AiPromptComponent, selector: "aiprompt-window", inputs: { promptOutputs: "promptOutputs", predefinedPrompts: "predefinedPrompts" }, ngImport: i0, template: "<kendo-window kendoDragTargetContainer\n dragHandle=\".k-prompt-header\"\n dragTargetFilter=\".trv-ai-prompt-dialog\"\n cursorStyle=\"default\"\n title=\"Before you start with AI\"\n (close)=\"toggle(false)\"\n class=\"trv-ai-prompt-dialog\"\n [(top)]=\"windowTop\"\n [(left)]=\"windowLeft\"\n [width]=\"windowWidth\"\n (widthChange)=\"onWidthChange($event)\"\n (heightChange)=\"onHeightChange($event)\">\n <div class=\"trv-window k-window-content\">\n <div *ngIf=\"showConsent\" class=\"trv-ai-consent-dialog\">\n <div class=\"trv-ai-consent-content\">\n The AI will process what you write here. This might include personal or sensitive information you choose to share. \n By clicking Consent, you agree to let the system process and use your input to generate responses. Your data won\u2019t be used for anything else.\n </div>\n <div class=\"trv-ai-consent-actions k-actions k-actions-end\">\n <button class=\"k-button k-button-md k-rounded-md k-button-solid k-button-solid-primary\"\n (click)=\"consentAccept()\"\n ariaLabel=\"AI Prompt Consent Accept\"\n title=\"AI Prompt Consent Accept\">Consent</button>\n <button class=\"k-button k-button-md k-rounded-md k-button-solid k-button-solid-base\"\n (click)=\"consentCancel()\"\n ariaLabel=\"AI Prompt Consent Cancel\"\n title=\"AI Prompt Consent Cancel\">Cancel</button>\n </div>\n </div>\n\n <kendo-aiprompt *ngIf=\"!showConsent\"\n [(activeView)]=\"activeView\"\n [promptOutputs]=\"promptOutputs\"\n [promptSuggestions]=\"predefinedPrompts\"\n (promptRequest)=\"onPromptRequest($event)\"\n (activeViewChange)=\"onActiveViewChange($event)\">\n <kendo-aiprompt-prompt-view></kendo-aiprompt-prompt-view>\n <kendo-aiprompt-output-view></kendo-aiprompt-output-view>\n <ng-template kendoAIPromptToolbarActionsTemplate>\n <span class=\"k-spacer\"></span>\n <button kendoButton\n [svgIcon]=\"xIcon\"\n fillMode=\"flat\"\n rounded=\"full\"\n (click)=\"toggle(false)\">\n </button>\n </ng-template>\n </kendo-aiprompt>\n </div>\n</kendo-window>", styles: [".trv-ai-prompt-dialog{min-width:400px;min-height:50px;max-height:800px}.trv-ai-prompt-dialog .k-window-content{padding:0}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-window-titlebar{display:none}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-header{border-color:var(--kendo-color-border, rgba(0, 0, 0, .08));color:var(--kendo-color-on-app-surface, #424242);background-color:var(--kendo-color-surface-alt, #ffffff)}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-header button.k-button{color:inherit}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-content{min-height:106px;border-color:var(--kendo-color-border, rgba(0, 0, 0, .08));color:var(--kendo-color-on-app-surface, #424242);background-color:var(--kendo-color-surface, #fafafa)}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-content .k-prompt-view{padding:20px;display:flex;flex-direction:column;flex:1 1 auto;gap:var(--kendo-spacing-4, 1rem)}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-content .k-prompt-view button.k-button{color:inherit}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-content .k-prompt-view textarea.k-input-inner{height:100px}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-footer button{border-radius:var(--kendo-border-radius-md, .25rem)}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-suggestion{border-color:var(--kendo-color-border, rgba(0, 0, 0, .08));color:var(--kendo-color-on-app-surface, #424242);background-color:var(--kendo-color-app-surface, #ffffff);box-shadow:var(--kendo-elevation-1, 0 2px 3px rgba(0, 0, 0, .04), 0 4px 16px rgba(0, 0, 0, .12));border-width:1px;border-style:solid;border-radius:var(--kendo-border-radius-md, .25rem);padding-block:var(--kendo-spacing-2, .5rem);padding-inline:var(--kendo-spacing-2, .5rem);cursor:pointer}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-expander{display:flex;flex-direction:column;flex:1;align-items:flex-start;gap:var(--kendo-spacing-2, .5rem)}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-expander .k-prompt-expander-content{display:flex;flex-flow:column;flex:0 0 auto;gap:var(--kendo-spacing-2, .5rem);align-self:stretch}.trv-ai-prompt-dialog:has(.trv-ai-consent-dialog) .k-window-titlebar{min-height:23px;background-color:unset}.trv-ai-prompt-dialog:has(.trv-ai-consent-dialog) .k-window-titlebar [kendowindowminimizeaction],.trv-ai-prompt-dialog:has(.trv-ai-consent-dialog) .k-window-titlebar [kendowindowmaximizeaction]{display:none!important}.trv-ai-prompt-dialog:has(.trv-ai-consent-dialog) .trv-ai-consent-content{min-height:102px;padding:16px;border-color:var(--kendo-color-border, rgba(0, 0, 0, .08));color:var(--kendo-color-on-app-surface, #424242);background-color:var(--kendo-color-surface, #fafafa)}.trv-ai-prompt-dialog:has(.trv-ai-consent-dialog) .trv-ai-consent-actions{justify-content:flex-start}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.WindowComponent, selector: "kendo-window", inputs: ["autoFocusedElement", "title", "draggable", "resizable", "themeColor", "keepContent", "state", "minWidth", "minHeight", "width", "height", "top", "left"], outputs: ["dragStart", "dragEnd", "resizeStart", "resizeEnd", "close", "widthChange", "heightChange", "topChange", "leftChange", "stateChange"], exportAs: ["kendoWindow"] }, { kind: "component", type: i4.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "component", type: i5.AIPromptComponent, selector: "kendo-aiprompt", inputs: ["activeView", "promptCommands", "promptSuggestions", "promptOutputs", "showOutputRating"], outputs: ["activeViewChange", "promptRequest", "commandExecute", "outputCopy", "outputRatingChange"], exportAs: ["kendoAIPrompt"] }, { kind: "component", type: i5.PromptViewComponent, selector: "kendo-aiprompt-prompt-view" }, { kind: "component", type: i5.OutputViewComponent, selector: "kendo-aiprompt-output-view" }, { kind: "directive", type: i5.AIPromptToolbarActionsDirective, selector: "[kendoAIPromptToolbarActionsTemplate]" }, { kind: "directive", type: i6.DragTargetContainerDirective, selector: "[kendoDragTargetContainer]", inputs: ["hint", "dragTargetFilter", "dragHandle", "dragDelay", "threshold", "dragTargetId", "dragData", "dragDisabled", "mode"], outputs: ["onDragReady", "onPress", "onDragStart", "onDrag", "onRelease", "onDragEnd"], exportAs: ["kendoDragTargetContainer"] }], encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AiPromptComponent, decorators: [{ type: Component, args: [{ selector: 'aiprompt-window', encapsulation: ViewEncapsulation.None, template: "<kendo-window kendoDragTargetContainer\n dragHandle=\".k-prompt-header\"\n dragTargetFilter=\".trv-ai-prompt-dialog\"\n cursorStyle=\"default\"\n title=\"Before you start with AI\"\n (close)=\"toggle(false)\"\n class=\"trv-ai-prompt-dialog\"\n [(top)]=\"windowTop\"\n [(left)]=\"windowLeft\"\n [width]=\"windowWidth\"\n (widthChange)=\"onWidthChange($event)\"\n (heightChange)=\"onHeightChange($event)\">\n <div class=\"trv-window k-window-content\">\n <div *ngIf=\"showConsent\" class=\"trv-ai-consent-dialog\">\n <div class=\"trv-ai-consent-content\">\n The AI will process what you write here. This might include personal or sensitive information you choose to share. \n By clicking Consent, you agree to let the system process and use your input to generate responses. Your data won\u2019t be used for anything else.\n </div>\n <div class=\"trv-ai-consent-actions k-actions k-actions-end\">\n <button class=\"k-button k-button-md k-rounded-md k-button-solid k-button-solid-primary\"\n (click)=\"consentAccept()\"\n ariaLabel=\"AI Prompt Consent Accept\"\n title=\"AI Prompt Consent Accept\">Consent</button>\n <button class=\"k-button k-button-md k-rounded-md k-button-solid k-button-solid-base\"\n (click)=\"consentCancel()\"\n ariaLabel=\"AI Prompt Consent Cancel\"\n title=\"AI Prompt Consent Cancel\">Cancel</button>\n </div>\n </div>\n\n <kendo-aiprompt *ngIf=\"!showConsent\"\n [(activeView)]=\"activeView\"\n [promptOutputs]=\"promptOutputs\"\n [promptSuggestions]=\"predefinedPrompts\"\n (promptRequest)=\"onPromptRequest($event)\"\n (activeViewChange)=\"onActiveViewChange($event)\">\n <kendo-aiprompt-prompt-view></kendo-aiprompt-prompt-view>\n <kendo-aiprompt-output-view></kendo-aiprompt-output-view>\n <ng-template kendoAIPromptToolbarActionsTemplate>\n <span class=\"k-spacer\"></span>\n <button kendoButton\n [svgIcon]=\"xIcon\"\n fillMode=\"flat\"\n rounded=\"full\"\n (click)=\"toggle(false)\">\n </button>\n </ng-template>\n </kendo-aiprompt>\n </div>\n</kendo-window>", styles: [".trv-ai-prompt-dialog{min-width:400px;min-height:50px;max-height:800px}.trv-ai-prompt-dialog .k-window-content{padding:0}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-window-titlebar{display:none}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-header{border-color:var(--kendo-color-border, rgba(0, 0, 0, .08));color:var(--kendo-color-on-app-surface, #424242);background-color:var(--kendo-color-surface-alt, #ffffff)}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-header button.k-button{color:inherit}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-content{min-height:106px;border-color:var(--kendo-color-border, rgba(0, 0, 0, .08));color:var(--kendo-color-on-app-surface, #424242);background-color:var(--kendo-color-surface, #fafafa)}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-content .k-prompt-view{padding:20px;display:flex;flex-direction:column;flex:1 1 auto;gap:var(--kendo-spacing-4, 1rem)}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-content .k-prompt-view button.k-button{color:inherit}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-content .k-prompt-view textarea.k-input-inner{height:100px}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-footer button{border-radius:var(--kendo-border-radius-md, .25rem)}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-suggestion{border-color:var(--kendo-color-border, rgba(0, 0, 0, .08));color:var(--kendo-color-on-app-surface, #424242);background-color:var(--kendo-color-app-surface, #ffffff);box-shadow:var(--kendo-elevation-1, 0 2px 3px rgba(0, 0, 0, .04), 0 4px 16px rgba(0, 0, 0, .12));border-width:1px;border-style:solid;border-radius:var(--kendo-border-radius-md, .25rem);padding-block:var(--kendo-spacing-2, .5rem);padding-inline:var(--kendo-spacing-2, .5rem);cursor:pointer}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-expander{display:flex;flex-direction:column;flex:1;align-items:flex-start;gap:var(--kendo-spacing-2, .5rem)}.trv-ai-prompt-dialog:not(:has(.trv-ai-consent-dialog)) .k-prompt-expander .k-prompt-expander-content{display:flex;flex-flow:column;flex:0 0 auto;gap:var(--kendo-spacing-2, .5rem);align-self:stretch}.trv-ai-prompt-dialog:has(.trv-ai-consent-dialog) .k-window-titlebar{min-height:23px;background-color:unset}.trv-ai-prompt-dialog:has(.trv-ai-consent-dialog) .k-window-titlebar [kendowindowminimizeaction],.trv-ai-prompt-dialog:has(.trv-ai-consent-dialog) .k-window-titlebar [kendowindowmaximizeaction]{display:none!important}.trv-ai-prompt-dialog:has(.trv-ai-consent-dialog) .trv-ai-consent-content{min-height:102px;padding:16px;border-color:var(--kendo-color-border, rgba(0, 0, 0, .08));color:var(--kendo-color-on-app-surface, #424242);background-color:var(--kendo-color-surface, #fafafa)}.trv-ai-prompt-dialog:has(.trv-ai-consent-dialog) .trv-ai-consent-actions{justify-content:flex-start}\n"] }] }], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i1.ReportingAngularViewerService }]; }, propDecorators: { promptOutputs: [{ type: Input }], predefinedPrompts: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWlwcm9tcHQtd2luZG93LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvYWlwcm9tcHQvYWlwcm9tcHQtd2luZG93LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uL3NyYy9saWIvYWlwcm9tcHQvYWlwcm9tcHQtd2luZG93LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQWMsS0FBSyxFQUFxQixpQkFBaUIsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUduRyxPQUFPLEVBQVcsS0FBSyxFQUFFLE1BQU0sMkJBQTJCLENBQUM7Ozs7Ozs7O0FBUTNELE1BQU0sT0FBTyxpQkFBaUI7SUFlMUIsWUFBMkIsUUFBbUIsRUFBVSxFQUFjLEVBQVUsT0FBc0M7UUFBM0YsYUFBUSxHQUFSLFFBQVEsQ0FBVztRQUFVLE9BQUUsR0FBRixFQUFFLENBQVk7UUFBVSxZQUFPLEdBQVAsT0FBTyxDQUErQjtRQVgvRyxjQUFTLEdBQVcsRUFBRSxDQUFDO1FBSXZCLFVBQUssR0FBWSxLQUFLLENBQUM7UUFDdkIsZUFBVSxHQUFXLENBQUMsQ0FBQztRQUN2QixnQkFBVyxHQUFHLElBQUksQ0FBQztRQUNuQixtQkFBYyxHQUFHLElBQUksQ0FBQztRQUN0Qix1QkFBa0IsR0FBRyxJQUFJLENBQUM7UUFDekIsY0FBUyxHQUFHLENBQUMsQ0FBQztJQUVtRyxDQUFDO0lBRTFILFFBQVE7UUFDSixNQUFNLGVBQWUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQztRQUNqRCxJQUFJLENBQUMsV0FBVyxHQUFHLEdBQUcsQ0FBQztRQUN2QixJQUFJLENBQUMsVUFBVSxHQUFHLGVBQWUsR0FBRyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFFNUQsTUFBTSxzQkFBc0IsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyx5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MEosQ0FBQztpQkFDcEw7cUJBQU07b0JBQ0gsbUJBQW1CLEdBQUcseUVBQXlFLENBQUM7aUJBQ25HO2dCQUVELElBQUksVUFBVSxFQUFFO29CQUNaLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLFVBQVUsRUFBRSxZQUFZLENBQUMsQ0FBQTtvQkFDaEQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsVUFBVSxFQUFFLGFBQWEsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO2lCQUM5RTtZQUNMLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQTtTQUNUO0lBQ0wsQ0FBQztJQUVNLGFBQWE7UUFDaEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN2QixDQUFDO0lBRU0sS0FBSyxDQUFDLGFBQWE7UUFDdEIsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUM7UUFDekIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsb0JBQW9CLENBQUMsY0FBYyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3pFLENBQUM7SUFFTyw4QkFBOEIsQ0FBQyxRQUFnQixFQUFFLFVBQThCO1FBQ25GLE9BQU87WUFDSCxFQUFFLEVBQUUsSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNwQixNQUFNLEVBQUUsUUFBUTtZQUNoQixNQUFNLEVBQUUsVUFBVSxDQUFDLE1BQU07WUFDekIsT0FBTyxFQUFFLFVBQVUsQ0FBQyxPQUFPO1NBQzlCLENBQUM7SUFDTixDQUFDOytHQWpHUSxpQkFBaUI7bUdBQWpCLGlCQUFpQiwySUNYOUIsNjVFQWlEZTs7NEZEdENGLGlCQUFpQjtrQkFON0IsU0FBUzsrQkFDSSxpQkFBaUIsaUJBR1osaUJBQWlCLENBQUMsSUFBSTtxS0FHNUIsYUFBYTtzQkFBckIsS0FBSztnQkFDRyxpQkFBaUI7c0JBQXpCLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEVsZW1lbnRSZWYsIElucHV0LCBPbkluaXQsIFJlbmRlcmVyMiwgVmlld0VuY2Fwc3VsYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFJlcG9ydGluZ0FuZ3VsYXJWaWV3ZXJTZXJ2aWNlIH0gZnJvbSAnLi4vcmVwb3J0aW5nLWFuZ3VsYXItdmlld2VyLnNlcnZpY2UnO1xuaW1wb3J0IHsgUHJvbXB0T3V0cHV0LCBQcm9tcHRSZXF1ZXN0RXZlbnQgfSBmcm9tIFwiQHByb2dyZXNzL2tlbmRvLWFuZ3VsYXItY29udmVyc2F0aW9uYWwtdWlcIjtcbmltcG9ydCB7IFNWR0ljb24sIHhJY29uIH0gZnJvbSAnQHByb2dyZXNzL2tlbmRvLXN2Zy1pY29ucyc7XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnYWlwcm9tcHQtd2luZG93JyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vYWlwcm9tcHQtd2luZG93LmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9haXByb21wdC13aW5kb3cuY29tcG9uZW50LnNjc3MnXSxcbiAgICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lXG59KVxuZXhwb3J0IGNsYXNzIEFpUHJvbXB0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgICBASW5wdXQoKSBwcm9tcHRPdXRwdXRzOiBBcnJheTxQcm9tcHRPdXRwdXQ+O1xuICAgIEBJbnB1dCgpIHByZWRlZmluZWRQcm9tcHRzOiBBcnJheTxzdHJpbmc+O1xuXG4gICAgcHVibGljIHdpbmRvd1RvcDogbnVtYmVyID0gODA7XG4gICAgcHVibGljIHdpbmRvd0xlZnQhOiBudW1iZXI7XG4gICAgcHVibGljIHdpbmRvd1dpZHRoITogbnVtYmVyO1xuXG4gICAgcHVibGljIHhJY29uOiBTVkdJY29uID0geEljb247XG4gICAgcHVibGljIGFjdGl2ZVZpZXc6IG51bWJlciA9IDA7XG4gICAgcHVibGljIHNob3dDb25zZW50ID0gdHJ1ZTtcbiAgICBwdWJsaWMgcmVxdWlyZUNvbnNlbnQgPSB0cnVlO1xuICAgIHB1YmxpYyBhbGxvd0N1c3RvbVByb21wdHMgPSB0cnVlO1xuICAgIHByaXZhdGUgaWRDb3VudGVyID0gMDtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlbmRlcmVyOiBSZW5kZXJlcjIsIHByaXZhdGUgZWw6IEVsZW1lbnRSZWYsIHByaXZhdGUgc2VydmljZTogUmVwb3J0aW5nQW5ndWxhclZpZXdlclNlcnZpY2UpIHt9XG4gICAgXG4gICAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHJlcG9ydEVsZW1XaWR0aCA9IHRoaXMuc2VydmljZS5yZXBvcnRXaWR0aDtcbiAgICAgICAgdGhpcy53aW5kb3dXaWR0aCA9IDUwMDtcbiAgICAgICAgdGhpcy53aW5kb3dMZWZ0ID0gcmVwb3J0RWxlbVdpZHRoIC0gKHRoaXMud2luZG93V2lkdGggKyAyMCk7XG5cbiAgICAgICAgY29uc3QgYWlDb25maWd1cmF0aW9uT3B0aW9ucyA9IHRoaXMuc2VydmljZS5jb250cm9sbGVyLmdldEFpQ29uZmlndXJhdGlvbk9wdGlvbnMoKTtcbiAgICAgICAgdGhpcy5yZXF1aXJlQ29uc2VudCA9IGFpQ29uZmlndXJhdGlvbk9wdGlvbnMucmVxdWlyZUNvbnNlbnQ7XG4gICAgICAgIHRoaXMuYWxsb3dDdXN0b21Qcm9tcHRzID0gYWlDb25maWd1cmF0aW9uT3B0aW9ucy5hbGxvd0N1c3RvbVByb21wdHM7XG5cbiAgICAgICAgdGhpcy5zaG93Q29uc2VudCA9IHRoaXMucmVxdWlyZUNvbnNlbnQgJiYgdGhpcy5zZXJ2aWNlLmNvbnRyb2xsZXIubG9hZEZyb21TZXNzaW9uU3RvcmFnZShcInRydkFpQ29uc2VudFwiKSAhPT0gXCJ0cnVlXCI7XG5cbiAgICAgICAgdGhpcy5vbkFjdGl2ZVZpZXdDaGFuZ2UodGhpcy5hY3RpdmVWaWV3KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgdG9nZ2xlKGlzT3BlbmVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2VydmljZS5pc0FpUHJvbXB0V2luZG93T3BlbiA9IGlzT3BlbmVkO1xuICAgIH1cblxuICAgIHB1YmxpYyBvbldpZHRoQ2hhbmdlKHdpZHRoOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zZXJ2aWNlLndpbmRvd1dpZHRoID0gd2lkdGg7XG4gICAgfVxuXG4gICAgcHVibGljIG9uSGVpZ2h0Q2hhbmdlKGhlaWdodDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2VydmljZS53aW5kb3dIZWlnaHQgPSBoZWlnaHQ7XG4gICAgfVxuXG4gICAgcHVibGljIG9uUHJvbXB0UmVxdWVzdChldmVudDogUHJvbXB0UmVxdWVzdEV2ZW50KTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGdlbmVyYXRlQnV0dG9uRWwgPSB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcignLmstcHJvbXB0LWZvb3RlciAuay1hY3Rpb25zIC5rLWJ1dHRvbicpO1xuICAgICAgICBnZW5lcmF0ZUJ1dHRvbkVsICYmIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3MoZ2VuZXJhdGVCdXR0b25FbCwgJ2stZGlzYWJsZWQnKTtcbiAgICAgICAgdGhpcy5zZXJ2aWNlLmNvbnRyb2xsZXIuZ2V0QUlSZXNwb25zZShldmVudC5wcm9tcHQpXG4gICAgICAgICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9tcHRPdXRwdXRzLnVuc2hpZnQodGhpcy5jcmVhdGVQcm9tcHRPdXRwdXRGcm9tUmVzcG9uc2UocmVzcG9uc2UsIGV2ZW50KSk7XG4gICAgICAgICAgICAgICAgZ2VuZXJhdGVCdXR0b25FbCAmJiB0aGlzLnJlbmRlcmVyLnJlbW92ZUNsYXNzKGdlbmVyYXRlQnV0dG9uRWwsICdrLWRpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVWaWV3ID0gMTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnByb21wdE91dHB1dHMudW5zaGlmdCh0aGlzLmNyZWF0ZVByb21wdE91dHB1dEZyb21SZXNwb25zZShlcnJvcj8uX3Jlc3BvbnNlSlNPTiwgZXZlbnQpKTtcbiAgICAgICAgICAgICAgICBnZW5lcmF0ZUJ1dHRvbkVsICYmIHRoaXMucmVuZGVyZXIucmVtb3ZlQ2xhc3MoZ2VuZXJhdGVCdXR0b25FbCwgJ2stZGlzYWJsZWQnKTtcbiAgICAgICAgICAgICAgICB0aGlzLmFjdGl2ZVZpZXcgPSAxO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIG9uQWN0aXZlVmlld0NoYW5nZSh2aWV3SWQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICAvLyBUaGUgS2VuZG8gZXZlbnQgaXMgdHJpZ2dlcmVkIGJlZm9yZSB0aGUgbmV3IEFJIHByb21wdCB2aWV3IGlzIHJlbmRlcmVkIHNvIHRoZSB0ZXh0YXJlYSBkb2Vzbid0IGV4aXN0XG4gICAgICAgIC8vIFdyYXAgdGhlIGNhbGwgaW4gc2V0VGltZW91dCBpbiBvcmRlciB0byBoYXZlIHRoZSB0ZXh0YXJlYSBlbGVtZW50IHByZXNlbnQgYmVmb3JlIHNldHRpbmcgdGhlIGRpc2FibGVkIGNsYXNzXG4gICAgICAgIGlmICh2aWV3SWQgPT09IDAgJiYgIXRoaXMuYWxsb3dDdXN0b21Qcm9tcHRzKSB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHsgIFxuICAgICAgICAgICAgICAgIGxldCB0ZXh0QXJlYVBsYWNlaG9sZGVyID0gJ0VudGVyIHlvdXIgcHJvbXB0JzsgICAgXG4gICAgICAgICAgICAgICAgY29uc3QgdGV4dEFyZWFFbCA9IHRoaXMuZWwubmF0aXZlRWxlbWVudC5xdWVyeVNlbGVjdG9yKCcuay10ZXh0YXJlYSB0ZXh0YXJlYScpO1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMucHJlZGVmaW5lZFByb21wdHMgJiYgdGhpcy5wcmVkZWZpbmVkUHJvbXB0cy5sZW5ndGggPiAwKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBhaVByb21wdEdlbmVyYXRlQnV0dG9uID0gdGhpcy5lbC5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJy5rLXByb21wdC1mb290ZXInKTtcbiAgICAgICAgICAgICAgICAgICAgYWlQcm9tcHRHZW5lcmF0ZUJ1dHRvbiAmJiB0aGlzLnJlbmRlcmVyLmFkZENsYXNzKGFpUHJvbXB0R2VuZXJhdGVCdXR0b24sICdrLWRpc2FibGVkJyk7XG4gICAgICAgICAgICAgICAgICAgIHRleHRBcmVhUGxhY2Vob2xkZXIgPSAnQ3VzdG9tIHByb21wdHMgYXJlIGRpc2FibGVkIGFuZCB0aGVyZSBhcmUgbm8gcHJlZGVmaW5lZCBwcm9tcHRzIGNvbmZpZ3VyZWQuIFBsZWFzZSBhbGxvdyBjdXN0b20gcHJvbXB0cyBvciBhZGQgcHJlZGVmaW5lZCBwcm9tcHRzIHRvIHVzZSB0aGUgQUkgZmVhdHVyZS4nO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRleHRBcmVhUGxhY2Vob2xkZXIgPSAnQ3VzdG9tIHByb21wdHMgYXJlIGRpc2FibGVkLCBwbGVhc2Ugc2VsZWN0IG9uZSBvZiB0aGUgc3VnZ2VzdGlvbnMgYmVsb3cnO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0ZXh0QXJlYUVsKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuYWRkQ2xhc3ModGV4dEFyZWFFbCwgJ2stZGlzYWJsZWQnKVxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcmVyLnNldEF0dHJpYnV0ZSh0ZXh0QXJlYUVsLCAncGxhY2Vob2xkZXInLCB0ZXh0QXJlYVBsYWNlaG9sZGVyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LCA1MClcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBjb25zZW50Q2FuY2VsKCkge1xuICAgICAgICB0aGlzLnRvZ2dsZShmYWxzZSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGNvbnNlbnRBY2NlcHQoKSB7XG4gICAgICAgIHRoaXMuc2hvd0NvbnNlbnQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5zZXJ2aWNlLmNvbnRyb2xsZXIuc2F2ZVRvU2Vzc2lvblN0b3JhZ2UoJ3RydkFpQ29uc2VudCcsICd0cnVlJyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjcmVhdGVQcm9tcHRPdXRwdXRGcm9tUmVzcG9uc2UocmVzcG9uc2U6IHN0cmluZywgcHJvbXB0RGF0YTogUHJvbXB0UmVxdWVzdEV2ZW50KSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBpZDogdGhpcy5pZENvdW50ZXIrKyxcbiAgICAgICAgICAgIG91dHB1dDogcmVzcG9uc2UsXG4gICAgICAgICAgICBwcm9tcHQ6IHByb21wdERhdGEucHJvbXB0LFxuICAgICAgICAgICAgaXNSZXRyeTogcHJvbXB0RGF0YS5pc1JldHJ5LFxuICAgICAgICB9OyBcbiAgICB9XG59XG4iLCI8a2VuZG8td2luZG93IGtlbmRvRHJhZ1RhcmdldENvbnRhaW5lclxuICAgIGRyYWdIYW5kbGU9XCIuay1wcm9tcHQtaGVhZGVyXCJcbiAgICBkcmFnVGFyZ2V0RmlsdGVyPVwiLnRydi1haS1wcm9tcHQtZGlhbG9nXCJcbiAgICBjdXJzb3JTdHlsZT1cImRlZmF1bHRcIlxuICAgIHRpdGxlPVwiQmVmb3JlIHlvdSBzdGFydCB3aXRoIEFJXCJcbiAgICAoY2xvc2UpPVwidG9nZ2xlKGZhbHNlKVwiXG4gICAgY2xhc3M9XCJ0cnYtYWktcHJvbXB0LWRpYWxvZ1wiXG4gICAgWyh0b3ApXT1cIndpbmRvd1RvcFwiXG4gICAgWyhsZWZ0KV09XCJ3aW5kb3dMZWZ0XCJcbiAgICBbd2lkdGhdPVwid2luZG93V2lkdGhcIlxuICAgICh3aWR0aENoYW5nZSk9XCJvbldpZHRoQ2hhbmdlKCRldmVudClcIlxuICAgIChoZWlnaHRDaGFuZ2UpPVwib25IZWlnaHRDaGFuZ2UoJGV2ZW50KVwiPlxuICAgIDxkaXYgY2xhc3M9XCJ0cnYtd2luZG93IGstd2luZG93LWNvbnRlbnRcIj5cbiAgICAgICAgPGRpdiAqbmdJZj1cInNob3dDb25zZW50XCIgY2xhc3M9XCJ0cnYtYWktY29uc2VudC1kaWFsb2dcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0cnYtYWktY29uc2VudC1jb250ZW50XCI+XG4gICAgICAgICAgICAgICAgVGhlIEFJIHdpbGwgcHJvY2VzcyB3aGF0IHlvdSB3cml0ZSBoZXJlLiBUaGlzIG1pZ2h0IGluY2x1ZGUgcGVyc29uYWwgb3Igc2Vuc2l0aXZlIGluZm9ybWF0aW9uIHlvdSBjaG9vc2UgdG8gc2hhcmUuIFxuICAgICAgICAgICAgICAgIEJ5IGNsaWNraW5nIENvbnNlbnQsIHlvdSBhZ3JlZSB0byBsZXQgdGhlIHN5c3RlbSBwcm9jZXNzIGFuZCB1c2UgeW91ciBpbnB1dCB0byBnZW5lcmF0ZSByZXNwb25zZXMuIFlvdXIgZGF0YSB3b27igJl0IGJlIHVzZWQgZm9yIGFueXRoaW5nIGVsc2UuXG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0cnYtYWktY29uc2VudC1hY3Rpb25zIGstYWN0aW9ucyBrLWFjdGlvbnMtZW5kXCI+XG4gICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImstYnV0dG9uIGstYnV0dG9uLW1kIGstcm91bmRlZC1tZCBrLWJ1dHRvbi1zb2xpZCBrLWJ1dHRvbi1zb2xpZC1wcmltYXJ5XCJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImNvbnNlbnRBY2NlcHQoKVwiXG4gICAgICAgICAgICAgICAgICAgIGFyaWFMYWJlbD1cIkFJIFByb21wdCBDb25zZW50IEFjY2VwdFwiXG4gICAgICAgICAgICAgICAgICAgIHRpdGxlPVwiQUkgUHJvbXB0IENvbnNlbnQgQWNjZXB0XCI+Q29uc2VudDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJrLWJ1dHRvbiBrLWJ1dHRvbi1tZCBrLXJvdW5kZWQtbWQgay1idXR0b24tc29saWQgay1idXR0b24tc29saWQtYmFzZVwiXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJjb25zZW50Q2FuY2VsKClcIlxuICAgICAgICAgICAgICAgICAgICBhcmlhTGFiZWw9XCJBSSBQcm9tcHQgQ29uc2VudCBDYW5jZWxcIlxuICAgICAgICAgICAgICAgICAgICB0aXRsZT1cIkFJIFByb21wdCBDb25zZW50IENhbmNlbFwiPkNhbmNlbDwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxrZW5kby1haXByb21wdCAqbmdJZj1cIiFzaG93Q29uc2VudFwiXG4gICAgICAgIFsoYWN0aXZlVmlldyldPVwiYWN0aXZlVmlld1wiXG4gICAgICAgIFtwcm9tcHRPdXRwdXRzXT1cInByb21wdE91dHB1dHNcIlxuICAgICAgICBbcHJvbXB0U3VnZ2VzdGlvbnNdPVwicHJlZGVmaW5lZFByb21wdHNcIlxuICAgICAgICAocHJvbXB0UmVxdWVzdCk9XCJvblByb21wdFJlcXVlc3QoJGV2ZW50KVwiXG4gICAgICAgIChhY3RpdmVWaWV3Q2hhbmdlKT1cIm9uQWN0aXZlVmlld0NoYW5nZSgkZXZlbnQpXCI+XG4gICAgICAgICAgICA8a2VuZG8tYWlwcm9tcHQtcHJvbXB0LXZpZXc+PC9rZW5kby1haXByb21wdC1wcm9tcHQtdmlldz5cbiAgICAgICAgICAgIDxrZW5kby1haXByb21wdC1vdXRwdXQtdmlldz48L2tlbmRvLWFpcHJvbXB0LW91dHB1dC12aWV3PlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlIGtlbmRvQUlQcm9tcHRUb29sYmFyQWN0aW9uc1RlbXBsYXRlPlxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiay1zcGFjZXJcIj48L3NwYW4+XG4gICAgICAgICAgICAgICAgPGJ1dHRvbiBrZW5kb0J1dHRvblxuICAgICAgICAgICAgICAgIFtzdmdJY29uXT1cInhJY29uXCJcbiAgICAgICAgICAgICAgICBmaWxsTW9kZT1cImZsYXRcIlxuICAgICAgICAgICAgICAgIHJvdW5kZWQ9XCJmdWxsXCJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwidG9nZ2xlKGZhbHNlKVwiPlxuICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPC9rZW5kby1haXByb21wdD5cbiAgICA8L2Rpdj5cbjwva2VuZG8td2luZG93PiJdfQ==