UNPKG

ng-smart-on-fhir

Version:

[![SRDC](https://www.srdc.com.tr/wp-content/uploads/2014/12/srdc-wp.png)](https://srdc.com.tr/en)

91 lines 30.2 kB
import { Component, Inject } from '@angular/core'; import * as i0 from "@angular/core"; import * as i1 from "../../services/smart-auth.service"; import * as i2 from "../../services/smart-on-fhir.service"; import * as i3 from "@angular/router"; import * as i4 from "@angular/common"; import * as i5 from "@angular/forms"; import * as i6 from "../qr-reader/qr-reader.component"; export class LoginComponent { get patientQuery() { return this._patientQuery; } set patientQuery(value) { this._patientQuery = value; this.searchPatients(); } hasPreviousPage() { return this.page > 1; } hasNextPage() { return this.page < (this.total / 10); } constructor(config, auth, sof, router) { this.config = config; this.auth = auth; this.sof = sof; this.router = router; // for Smart Health Card QR scanner this.scanning = false; // patient selection for public clients this.patientSelection = false; this.patientsLoading = false; this.patients = []; this.total = 0; this.page = 1; this._patientQuery = ''; } async login(config) { if (config.isPublic) { this.client = this.auth.publicClient(config.iss); this.searchPatients(); this.patientSelection = true; this.selectedClient = config; } else { this.auth.login(config); } } /** * Public client patient selection * @param patient */ selectPatient(patient) { if (this.selectedClient) { this.auth.login(this.selectedClient, patient); this.router.navigate(['/']); } } // public client patient search methods next() { this.page += 1; this.searchPatients(); } prev() { this.page = this.page > 1 ? this.page - 1 : 1; this.searchPatients(); } async searchPatients() { this.patientsLoading = true; let query = 'Patient?_count=10&_page=' + this.page; if (this.patientQuery?.trim()) { query += '&' + this.patientQuery.trim().split(' ').map(name => 'name:contains=' + name).join('&'); } const bundle = await this.client?.request(query); if (bundle) { this.patients = bundle.entry?.map(entry => entry.resource) .filter(res => !!res) || []; this.total = bundle.total || 0; if ((this.page - 1) * 10 > this.total) { this.page = 1; } } else { this.patients = []; this.total = 0; this.page = 1; } this.patientsLoading = false; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LoginComponent, deps: [{ token: 'sofConfig' }, { token: i1.SmartAuthService }, { token: i2.SmartOnFhirService }, { token: i3.Router }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: LoginComponent, selector: "sof-login", ngImport: i0, template: "<div class=\"sof-height-100vh\">\r\n @if (config.logo || config.title) {\r\n <div class=\"logo-n-title\">\r\n @if (config.logo) {\r\n <img [src]=\"config.logo\" class=\"logo\">\r\n }\r\n @if (config.title) {\r\n <div class=\"title sof-text-light\" [style.width]=\"config.title.length / 2 + 'em'\">{{ config.title }}</div>\r\n }\r\n </div>\r\n }\r\n <div class=\"login-container sof-primary-background sof-login-background\">\r\n <div class=\"sof-shadow sof-no-border sof-card sof-width-25 sof-margin-auto\">\r\n <div class=\"sof-card-header sof-login-card-header\"><h4>Login via...</h4></div>\r\n <div class=\"sof-card-body sof-text-center sof-light-background\">\r\n @if (!scanning && !patientSelection) {\r\n <!-- <h4>Login With:</h4>-->\r\n @for (client of config?.loginClients; track $index) {\r\n @if (client.image) {\r\n <a (click)=\"login(client)\" style=\"cursor:pointer;\" class=\"sof-login-client-w-image image\">\r\n <img [src]=\"client.image\">\r\n </a>\r\n } @else {\r\n <button class=\"sof-button sof-text-bold\" [class.sof-button-light]=\"!client.background\" [class.sof-text-dark]=\"!client.color\"\r\n [ngStyle]=\"{background: client.background}\" (click)=\"login(client)\">\r\n <div class=\"text-content\" [ngStyle]=\"{color: client.color}\">{{client.label}}</div>\r\n </button>\r\n }\r\n }\r\n @for (client of config?.launchClients; track $index) {\r\n @if (client.image) {\r\n <a [href]=\"client.url\" class=\"image sof-button sof-button-light\" style=\"cursor:pointer;\">\r\n <img [src]=\"client.image\">\r\n </a>\r\n }\r\n }\r\n @for (client of config?.launchClients; track $index) {\r\n @if (!client.image) {\r\n <a class=\"sof-button sof-button-secondary sof-button-login sof-text-bold\" [href]=\"client.url\">{{client.label}}</a>\r\n }\r\n }\r\n @if (config?.shcLoginEnabled) {\r\n <!-- <span class=\"mt-5\">or</span>-->\r\n <a class=\"sof-button sof-button-secondary\" (click)=\"scanning = true\">\r\n <i class=\"sof-icon sof-icon-qr-code\"></i> SMART Health Card\r\n </a>\r\n }\r\n } @else if (scanning) {\r\n <sof-qr-reader #reader></sof-qr-reader>\r\n @if (reader.error) {\r\n <div class=\"sof-alert sof-alert-danger\">\r\n {{ reader.error }}\r\n </div>\r\n }\r\n <button class=\"sof-button sof-button-danger\" (click)=\"scanning = false\">Cancel</button>\r\n } @else if (patientSelection) {\r\n <div class=\"sof-width-100\" style=\"max-height: 50vh; overflow-y: auto\">\r\n <table class=\"sof-table\">\r\n <tbody>\r\n <tr>\r\n <td>\r\n <button class=\"sof-button sof-button-danger sof-mr-1\" (click)=\"patientSelection = false\">Cancel</button>\r\n <button class=\"sof-button sof-button-primary sof-mr-1\" [class.disabled]=\"!hasPreviousPage()\" (click)=\"prev()\"><i class=\"sof-icon sof-icon-caret-left\"></i></button>\r\n <input class=\"sof-form-control\" style=\"display: inline-block; width: auto\" placeholder=\"Search\" [(ngModel)]=\"patientQuery\">\r\n <button class=\"sof-button sof-button-primary sof-ml-1\" [class.disabled]=\"!hasNextPage()\" (click)=\"next()\"><i class=\"sof-icon sof-icon-caret-right\"></i></button>\r\n </td>\r\n </tr>\r\n @if(patientsLoading) {\r\n <tr><td>\r\n <div class=\"sof-spinner\" role=\"status\">\r\n <span class=\"sof-hidden\">Loading...</span>\r\n </div>\r\n </td></tr>\r\n } @else {\r\n @for (patient of patients; track patient.id) {\r\n <tr style=\"cursor: pointer\" (click)=\"selectPatient(patient)\"><td>{{patient.name?.at(0)?.given}} {{patient.name?.at(0)?.family}}</td></tr>\r\n }\r\n <tr><td class=\"sof-text-bold sof-text-gray\" style=\"font-size: .75em\">{{(page - 1) * patients.length}} - {{page * patients.length}}/{{total}}</td></tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".login-container{margin:-1rem!important;width:calc(100% + 2rem)!important;height:calc(100% + 2rem)!important}.login-container>.sof-card{min-width:500px;position:relative;top:50%;transform:translateY(-50%);min-height:500px}.login-container>.sof-card .sof-card-body{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-around;gap:1em;align-items:stretch}.login-container>.sof-card .sof-card-body>a.image{display:flex;justify-content:space-around;align-items:center}.login-container>.sof-card .sof-card-body>a.image img{width:150px}.login-container>.sof-card .sof-card-body>button .text-content{width:150px;white-space:wrap}.login-container>.sof-card .sof-card-body>a:not(.image){width:100%;display:flex;text-align:center;align-items:center;justify-content:center;gap:.5em}.logo-n-title{position:fixed;left:2em;top:2em;width:calc(100vw - 4em);display:flex;gap:1em}.logo-n-title .logo{width:150px}.logo-n-title .title{max-width:calc(85vw - 150px);font-size:2em;font-weight:700;border-left:.1em solid;padding-left:.4em;display:flex;align-items:center;white-space:break-spaces}\n"], dependencies: [{ kind: "directive", type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i6.QrReaderComponent, selector: "sof-qr-reader" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: LoginComponent, decorators: [{ type: Component, args: [{ selector: 'sof-login', template: "<div class=\"sof-height-100vh\">\r\n @if (config.logo || config.title) {\r\n <div class=\"logo-n-title\">\r\n @if (config.logo) {\r\n <img [src]=\"config.logo\" class=\"logo\">\r\n }\r\n @if (config.title) {\r\n <div class=\"title sof-text-light\" [style.width]=\"config.title.length / 2 + 'em'\">{{ config.title }}</div>\r\n }\r\n </div>\r\n }\r\n <div class=\"login-container sof-primary-background sof-login-background\">\r\n <div class=\"sof-shadow sof-no-border sof-card sof-width-25 sof-margin-auto\">\r\n <div class=\"sof-card-header sof-login-card-header\"><h4>Login via...</h4></div>\r\n <div class=\"sof-card-body sof-text-center sof-light-background\">\r\n @if (!scanning && !patientSelection) {\r\n <!-- <h4>Login With:</h4>-->\r\n @for (client of config?.loginClients; track $index) {\r\n @if (client.image) {\r\n <a (click)=\"login(client)\" style=\"cursor:pointer;\" class=\"sof-login-client-w-image image\">\r\n <img [src]=\"client.image\">\r\n </a>\r\n } @else {\r\n <button class=\"sof-button sof-text-bold\" [class.sof-button-light]=\"!client.background\" [class.sof-text-dark]=\"!client.color\"\r\n [ngStyle]=\"{background: client.background}\" (click)=\"login(client)\">\r\n <div class=\"text-content\" [ngStyle]=\"{color: client.color}\">{{client.label}}</div>\r\n </button>\r\n }\r\n }\r\n @for (client of config?.launchClients; track $index) {\r\n @if (client.image) {\r\n <a [href]=\"client.url\" class=\"image sof-button sof-button-light\" style=\"cursor:pointer;\">\r\n <img [src]=\"client.image\">\r\n </a>\r\n }\r\n }\r\n @for (client of config?.launchClients; track $index) {\r\n @if (!client.image) {\r\n <a class=\"sof-button sof-button-secondary sof-button-login sof-text-bold\" [href]=\"client.url\">{{client.label}}</a>\r\n }\r\n }\r\n @if (config?.shcLoginEnabled) {\r\n <!-- <span class=\"mt-5\">or</span>-->\r\n <a class=\"sof-button sof-button-secondary\" (click)=\"scanning = true\">\r\n <i class=\"sof-icon sof-icon-qr-code\"></i> SMART Health Card\r\n </a>\r\n }\r\n } @else if (scanning) {\r\n <sof-qr-reader #reader></sof-qr-reader>\r\n @if (reader.error) {\r\n <div class=\"sof-alert sof-alert-danger\">\r\n {{ reader.error }}\r\n </div>\r\n }\r\n <button class=\"sof-button sof-button-danger\" (click)=\"scanning = false\">Cancel</button>\r\n } @else if (patientSelection) {\r\n <div class=\"sof-width-100\" style=\"max-height: 50vh; overflow-y: auto\">\r\n <table class=\"sof-table\">\r\n <tbody>\r\n <tr>\r\n <td>\r\n <button class=\"sof-button sof-button-danger sof-mr-1\" (click)=\"patientSelection = false\">Cancel</button>\r\n <button class=\"sof-button sof-button-primary sof-mr-1\" [class.disabled]=\"!hasPreviousPage()\" (click)=\"prev()\"><i class=\"sof-icon sof-icon-caret-left\"></i></button>\r\n <input class=\"sof-form-control\" style=\"display: inline-block; width: auto\" placeholder=\"Search\" [(ngModel)]=\"patientQuery\">\r\n <button class=\"sof-button sof-button-primary sof-ml-1\" [class.disabled]=\"!hasNextPage()\" (click)=\"next()\"><i class=\"sof-icon sof-icon-caret-right\"></i></button>\r\n </td>\r\n </tr>\r\n @if(patientsLoading) {\r\n <tr><td>\r\n <div class=\"sof-spinner\" role=\"status\">\r\n <span class=\"sof-hidden\">Loading...</span>\r\n </div>\r\n </td></tr>\r\n } @else {\r\n @for (patient of patients; track patient.id) {\r\n <tr style=\"cursor: pointer\" (click)=\"selectPatient(patient)\"><td>{{patient.name?.at(0)?.given}} {{patient.name?.at(0)?.family}}</td></tr>\r\n }\r\n <tr><td class=\"sof-text-bold sof-text-gray\" style=\"font-size: .75em\">{{(page - 1) * patients.length}} - {{page * patients.length}}/{{total}}</td></tr>\r\n }\r\n </tbody>\r\n </table>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".login-container{margin:-1rem!important;width:calc(100% + 2rem)!important;height:calc(100% + 2rem)!important}.login-container>.sof-card{min-width:500px;position:relative;top:50%;transform:translateY(-50%);min-height:500px}.login-container>.sof-card .sof-card-body{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-around;gap:1em;align-items:stretch}.login-container>.sof-card .sof-card-body>a.image{display:flex;justify-content:space-around;align-items:center}.login-container>.sof-card .sof-card-body>a.image img{width:150px}.login-container>.sof-card .sof-card-body>button .text-content{width:150px;white-space:wrap}.login-container>.sof-card .sof-card-body>a:not(.image){width:100%;display:flex;text-align:center;align-items:center;justify-content:center;gap:.5em}.logo-n-title{position:fixed;left:2em;top:2em;width:calc(100vw - 4em);display:flex;gap:1em}.logo-n-title .logo{width:150px}.logo-n-title .title{max-width:calc(85vw - 150px);font-size:2em;font-weight:700;border-left:.1em solid;padding-left:.4em;display:flex;align-items:center;white-space:break-spaces}\n"] }] }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Inject, args: ['sofConfig'] }] }, { type: i1.SmartAuthService }, { type: i2.SmartOnFhirService }, { type: i3.Router }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9naW4uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc21hcnQtb24tZmhpci9zcmMvbGliL2NvbXBvbmVudHMvbG9naW4vbG9naW4uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc21hcnQtb24tZmhpci9zcmMvbGliL2NvbXBvbmVudHMvbG9naW4vbG9naW4uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUMsTUFBTSxlQUFlLENBQUM7Ozs7Ozs7O0FBYWhELE1BQU0sT0FBTyxjQUFjO0lBY3pCLElBQUksWUFBWSxLQUFhLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7SUFDekQsSUFBSSxZQUFZLENBQUMsS0FBYTtRQUM1QixJQUFJLENBQUMsYUFBYSxHQUFHLEtBQUssQ0FBQztRQUMzQixJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7SUFDeEIsQ0FBQztJQUNELGVBQWUsS0FBYyxPQUFPLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFBLENBQUMsQ0FBQztJQUNuRCxXQUFXLEtBQWMsT0FBTyxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUMsQ0FBQSxDQUFDLENBQUM7SUFFL0QsWUFBd0MsTUFBeUIsRUFBVSxJQUFzQixFQUM3RSxHQUF1QixFQUFVLE1BQWM7UUFEM0IsV0FBTSxHQUFOLE1BQU0sQ0FBbUI7UUFBVSxTQUFJLEdBQUosSUFBSSxDQUFrQjtRQUM3RSxRQUFHLEdBQUgsR0FBRyxDQUFvQjtRQUFVLFdBQU0sR0FBTixNQUFNLENBQVE7UUFyQm5FLG1DQUFtQztRQUNuQyxhQUFRLEdBQVksS0FBSyxDQUFDO1FBRTFCLHVDQUF1QztRQUN2QyxxQkFBZ0IsR0FBWSxLQUFLLENBQUM7UUFDbEMsb0JBQWUsR0FBWSxLQUFLLENBQUM7UUFFakMsYUFBUSxHQUFvQixFQUFFLENBQUM7UUFDL0IsVUFBSyxHQUFXLENBQUMsQ0FBQztRQUNsQixTQUFJLEdBQVcsQ0FBQyxDQUFDO1FBQ1Qsa0JBQWEsR0FBVyxFQUFFLENBQUM7SUFZbkMsQ0FBQztJQUVELEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBeUI7UUFDbkMsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDcEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUE7WUFDaEQsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFBO1lBQ3JCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7WUFDN0IsSUFBSSxDQUFDLGNBQWMsR0FBRyxNQUFNLENBQUM7UUFDL0IsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUN6QixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILGFBQWEsQ0FBQyxPQUFzQjtRQUNsQyxJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLE9BQU8sQ0FBQyxDQUFBO1lBQzdDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQTtRQUM3QixDQUFDO0lBQ0gsQ0FBQztJQUVELHVDQUF1QztJQUN2QyxJQUFJLEtBQUssSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2pELElBQUk7UUFDRixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzlDLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUN4QixDQUFDO0lBQ0QsS0FBSyxDQUFDLGNBQWM7UUFDbEIsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUM7UUFDNUIsSUFBSSxLQUFLLEdBQUcsMEJBQTBCLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztRQUNuRCxJQUFJLElBQUksQ0FBQyxZQUFZLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUFDLEtBQUssSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBQUMsQ0FBQztRQUNwSSxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUE4QixLQUFLLENBQUMsQ0FBQTtRQUM3RSxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ1gsSUFBSSxDQUFDLFFBQVEsR0FBb0IsTUFBTSxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDO2lCQUN4RSxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFBO1lBQzdCLElBQUksQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssSUFBSSxDQUFDLENBQUM7WUFDL0IsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDdEMsSUFBSSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUE7WUFDZixDQUFDO1FBQ0gsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsUUFBUSxHQUFHLEVBQUUsQ0FBQTtZQUNsQixJQUFJLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztZQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO1FBQ2hCLENBQUM7UUFDRCxJQUFJLENBQUMsZUFBZSxHQUFHLEtBQUssQ0FBQztJQUMvQixDQUFDOytHQXhFVSxjQUFjLGtCQXNCTCxXQUFXO21HQXRCcEIsY0FBYyxpRENiM0IsbWhKQXVGQTs7NEZEMUVhLGNBQWM7a0JBTDFCLFNBQVM7K0JBQ0UsV0FBVzs7MEJBMEJSLE1BQU07MkJBQUMsV0FBVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7Q29tcG9uZW50LCBJbmplY3R9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge0xvZ2luQ2xpZW50Q29uZmlnfSBmcm9tIFwiLi4vLi4vbW9kZWwvbG9naW4tY2xpZW50LmNvbmZpZ1wiO1xyXG5pbXBvcnQge1NtYXJ0T25GaGlyQ29uZmlnfSBmcm9tIFwiLi4vLi4vbW9kZWwvc21hcnQtb24tZmhpci5jb25maWdcIjtcclxuaW1wb3J0IHtTbWFydEF1dGhTZXJ2aWNlfSBmcm9tIFwiLi4vLi4vc2VydmljZXMvc21hcnQtYXV0aC5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7U21hcnRPbkZoaXJTZXJ2aWNlfSBmcm9tIFwiLi4vLi4vc2VydmljZXMvc21hcnQtb24tZmhpci5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7Um91dGVyfSBmcm9tIFwiQGFuZ3VsYXIvcm91dGVyXCI7XHJcbmltcG9ydCBDbGllbnQgZnJvbSBcImZoaXJjbGllbnQvbGliL0NsaWVudFwiO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdzb2YtbG9naW4nLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9sb2dpbi5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmw6ICcuL2xvZ2luLmNvbXBvbmVudC5zY3NzJ1xyXG59KVxyXG5leHBvcnQgY2xhc3MgTG9naW5Db21wb25lbnQge1xyXG5cclxuICAvLyBmb3IgU21hcnQgSGVhbHRoIENhcmQgUVIgc2Nhbm5lclxyXG4gIHNjYW5uaW5nOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8vIHBhdGllbnQgc2VsZWN0aW9uIGZvciBwdWJsaWMgY2xpZW50c1xyXG4gIHBhdGllbnRTZWxlY3Rpb246IGJvb2xlYW4gPSBmYWxzZTtcclxuICBwYXRpZW50c0xvYWRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBzZWxlY3RlZENsaWVudDogTG9naW5DbGllbnRDb25maWd8dW5kZWZpbmVkO1xyXG4gIHBhdGllbnRzOiBmaGlyNC5QYXRpZW50W10gPSBbXTtcclxuICB0b3RhbDogbnVtYmVyID0gMDtcclxuICBwYWdlOiBudW1iZXIgPSAxO1xyXG4gIHByaXZhdGUgX3BhdGllbnRRdWVyeTogc3RyaW5nID0gJyc7XHJcbiAgcHJpdmF0ZSBjbGllbnQ6IENsaWVudHx1bmRlZmluZWQ7XHJcbiAgZ2V0IHBhdGllbnRRdWVyeSgpOiBzdHJpbmcgeyByZXR1cm4gdGhpcy5fcGF0aWVudFF1ZXJ5OyB9XHJcbiAgc2V0IHBhdGllbnRRdWVyeSh2YWx1ZTogc3RyaW5nKSB7XHJcbiAgICB0aGlzLl9wYXRpZW50UXVlcnkgPSB2YWx1ZTtcclxuICAgIHRoaXMuc2VhcmNoUGF0aWVudHMoKTtcclxuICB9XHJcbiAgaGFzUHJldmlvdXNQYWdlKCk6IGJvb2xlYW4geyByZXR1cm4gdGhpcy5wYWdlID4gMSB9XHJcbiAgaGFzTmV4dFBhZ2UoKTogYm9vbGVhbiB7IHJldHVybiB0aGlzLnBhZ2UgPCAodGhpcy50b3RhbCAvIDEwKSB9XHJcblxyXG4gIGNvbnN0cnVjdG9yKEBJbmplY3QoJ3NvZkNvbmZpZycpIHB1YmxpYyBjb25maWc6IFNtYXJ0T25GaGlyQ29uZmlnLCBwcml2YXRlIGF1dGg6IFNtYXJ0QXV0aFNlcnZpY2UsXHJcbiAgICAgICAgICAgICAgcHJpdmF0ZSBzb2Y6IFNtYXJ0T25GaGlyU2VydmljZSwgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlcikge1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgbG9naW4oY29uZmlnOiBMb2dpbkNsaWVudENvbmZpZykge1xyXG4gICAgaWYgKGNvbmZpZy5pc1B1YmxpYykge1xyXG4gICAgICB0aGlzLmNsaWVudCA9IHRoaXMuYXV0aC5wdWJsaWNDbGllbnQoY29uZmlnLmlzcylcclxuICAgICAgdGhpcy5zZWFyY2hQYXRpZW50cygpXHJcbiAgICAgIHRoaXMucGF0aWVudFNlbGVjdGlvbiA9IHRydWU7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRDbGllbnQgPSBjb25maWc7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmF1dGgubG9naW4oY29uZmlnKVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUHVibGljIGNsaWVudCBwYXRpZW50IHNlbGVjdGlvblxyXG4gICAqIEBwYXJhbSBwYXRpZW50XHJcbiAgICovXHJcbiAgc2VsZWN0UGF0aWVudChwYXRpZW50OiBmaGlyNC5QYXRpZW50KSB7XHJcbiAgICBpZiAodGhpcy5zZWxlY3RlZENsaWVudCkge1xyXG4gICAgICB0aGlzLmF1dGgubG9naW4odGhpcy5zZWxlY3RlZENsaWVudCwgcGF0aWVudClcclxuICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoWycvJ10pXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLyBwdWJsaWMgY2xpZW50IHBhdGllbnQgc2VhcmNoIG1ldGhvZHNcclxuICBuZXh0KCkgeyB0aGlzLnBhZ2UgKz0gMTsgdGhpcy5zZWFyY2hQYXRpZW50cygpOyB9XHJcbiAgcHJldigpIHtcclxuICAgIHRoaXMucGFnZSA9IHRoaXMucGFnZSA+IDEgPyB0aGlzLnBhZ2UgLSAxIDogMTtcclxuICAgIHRoaXMuc2VhcmNoUGF0aWVudHMoKTtcclxuICB9XHJcbiAgYXN5bmMgc2VhcmNoUGF0aWVudHMoKSB7XHJcbiAgICB0aGlzLnBhdGllbnRzTG9hZGluZyA9IHRydWU7XHJcbiAgICBsZXQgcXVlcnkgPSAnUGF0aWVudD9fY291bnQ9MTAmX3BhZ2U9JyArIHRoaXMucGFnZTtcclxuICAgIGlmICh0aGlzLnBhdGllbnRRdWVyeT8udHJpbSgpKSB7IHF1ZXJ5ICs9ICcmJyArIHRoaXMucGF0aWVudFF1ZXJ5LnRyaW0oKS5zcGxpdCgnICcpLm1hcChuYW1lID0+ICduYW1lOmNvbnRhaW5zPScgKyBuYW1lKS5qb2luKCcmJykgfVxyXG4gICAgY29uc3QgYnVuZGxlID0gYXdhaXQgdGhpcy5jbGllbnQ/LnJlcXVlc3Q8ZmhpcjQuQnVuZGxlPGZoaXI0LlBhdGllbnQ+PihxdWVyeSlcclxuICAgIGlmIChidW5kbGUpIHtcclxuICAgICAgdGhpcy5wYXRpZW50cyA9IDxmaGlyNC5QYXRpZW50W10+YnVuZGxlLmVudHJ5Py5tYXAoZW50cnkgPT4gZW50cnkucmVzb3VyY2UpXHJcbiAgICAgICAgLmZpbHRlcihyZXMgPT4gISFyZXMpIHx8IFtdXHJcbiAgICAgIHRoaXMudG90YWwgPSBidW5kbGUudG90YWwgfHwgMDtcclxuICAgICAgaWYgKCh0aGlzLnBhZ2UgLSAxKSAqIDEwID4gdGhpcy50b3RhbCkge1xyXG4gICAgICAgIHRoaXMucGFnZSA9IDFcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5wYXRpZW50cyA9IFtdXHJcbiAgICAgIHRoaXMudG90YWwgPSAwO1xyXG4gICAgICB0aGlzLnBhZ2UgPSAxO1xyXG4gICAgfVxyXG4gICAgdGhpcy5wYXRpZW50c0xvYWRpbmcgPSBmYWxzZTtcclxuICB9XHJcbn1cclxuIiwiPGRpdiBjbGFzcz1cInNvZi1oZWlnaHQtMTAwdmhcIj5cclxuICBAaWYgKGNvbmZpZy5sb2dvIHx8IGNvbmZpZy50aXRsZSkge1xyXG4gICAgPGRpdiBjbGFzcz1cImxvZ28tbi10aXRsZVwiPlxyXG4gICAgICBAaWYgKGNvbmZpZy5sb2dvKSB7XHJcbiAgICAgICAgPGltZyBbc3JjXT1cImNvbmZpZy5sb2dvXCIgY2xhc3M9XCJsb2dvXCI+XHJcbiAgICAgIH1cclxuICAgICAgQGlmIChjb25maWcudGl0bGUpIHtcclxuICAgICAgICA8ZGl2IGNsYXNzPVwidGl0bGUgc29mLXRleHQtbGlnaHRcIiBbc3R5bGUud2lkdGhdPVwiY29uZmlnLnRpdGxlLmxlbmd0aCAvIDIgKyAnZW0nXCI+e3sgY29uZmlnLnRpdGxlIH19PC9kaXY+XHJcbiAgICAgIH1cclxuICAgIDwvZGl2PlxyXG4gIH1cclxuICA8ZGl2IGNsYXNzPVwibG9naW4tY29udGFpbmVyIHNvZi1wcmltYXJ5LWJhY2tncm91bmQgc29mLWxvZ2luLWJhY2tncm91bmRcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJzb2Ytc2hhZG93IHNvZi1uby1ib3JkZXIgc29mLWNhcmQgc29mLXdpZHRoLTI1IHNvZi1tYXJnaW4tYXV0b1wiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwic29mLWNhcmQtaGVhZGVyIHNvZi1sb2dpbi1jYXJkLWhlYWRlclwiPjxoND5Mb2dpbiB2aWEuLi48L2g0PjwvZGl2PlxyXG4gICAgICA8ZGl2IGNsYXNzPVwic29mLWNhcmQtYm9keSBzb2YtdGV4dC1jZW50ZXIgc29mLWxpZ2h0LWJhY2tncm91bmRcIj5cclxuICAgICAgICBAaWYgKCFzY2FubmluZyAmJiAhcGF0aWVudFNlbGVjdGlvbikge1xyXG4gICAgICAgICAgPCEtLSAgICA8aDQ+TG9naW4gV2l0aDo8L2g0Pi0tPlxyXG4gICAgICAgICAgQGZvciAoY2xpZW50IG9mIGNvbmZpZz8ubG9naW5DbGllbnRzOyB0cmFjayAkaW5kZXgpIHtcclxuICAgICAgICAgICAgQGlmIChjbGllbnQuaW1hZ2UpIHtcclxuICAgICAgICAgICAgICA8YSAoY2xpY2spPVwibG9naW4oY2xpZW50KVwiIHN0eWxlPVwiY3Vyc29yOnBvaW50ZXI7XCIgY2xhc3M9XCJzb2YtbG9naW4tY2xpZW50LXctaW1hZ2UgaW1hZ2VcIj5cclxuICAgICAgICAgICAgICAgIDxpbWcgW3NyY109XCJjbGllbnQuaW1hZ2VcIj5cclxuICAgICAgICAgICAgICA8L2E+XHJcbiAgICAgICAgICAgIH0gQGVsc2Uge1xyXG4gICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJzb2YtYnV0dG9uIHNvZi10ZXh0LWJvbGRcIiBbY2xhc3Muc29mLWJ1dHRvbi1saWdodF09XCIhY2xpZW50LmJhY2tncm91bmRcIiBbY2xhc3Muc29mLXRleHQtZGFya109XCIhY2xpZW50LmNvbG9yXCJcclxuICAgICAgICAgICAgICAgICAgICAgIFtuZ1N0eWxlXT1cIntiYWNrZ3JvdW5kOiBjbGllbnQuYmFja2dyb3VuZH1cIiAoY2xpY2spPVwibG9naW4oY2xpZW50KVwiPlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRleHQtY29udGVudFwiIFtuZ1N0eWxlXT1cIntjb2xvcjogY2xpZW50LmNvbG9yfVwiPnt7Y2xpZW50LmxhYmVsfX08L2Rpdj5cclxuICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgQGZvciAoY2xpZW50IG9mIGNvbmZpZz8ubGF1bmNoQ2xpZW50czsgdHJhY2sgJGluZGV4KSB7XHJcbiAgICAgICAgICAgIEBpZiAoY2xpZW50LmltYWdlKSB7XHJcbiAgICAgICAgICAgICAgPGEgW2hyZWZdPVwiY2xpZW50LnVybFwiIGNsYXNzPVwiaW1hZ2Ugc29mLWJ1dHRvbiBzb2YtYnV0dG9uLWxpZ2h0XCIgc3R5bGU9XCJjdXJzb3I6cG9pbnRlcjtcIj5cclxuICAgICAgICAgICAgICAgIDxpbWcgW3NyY109XCJjbGllbnQuaW1hZ2VcIj5cclxuICAgICAgICAgICAgICA8L2E+XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICAgIEBmb3IgKGNsaWVudCBvZiBjb25maWc/LmxhdW5jaENsaWVudHM7IHRyYWNrICRpbmRleCkge1xyXG4gICAgICAgICAgICBAaWYgKCFjbGllbnQuaW1hZ2UpIHtcclxuICAgICAgICAgICAgICA8YSBjbGFzcz1cInNvZi1idXR0b24gc29mLWJ1dHRvbi1zZWNvbmRhcnkgc29mLWJ1dHRvbi1sb2dpbiBzb2YtdGV4dC1ib2xkXCIgW2hyZWZdPVwiY2xpZW50LnVybFwiPnt7Y2xpZW50LmxhYmVsfX08L2E+XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICAgIEBpZiAoY29uZmlnPy5zaGNMb2dpbkVuYWJsZWQpIHtcclxuICAgICAgICAgICAgPCEtLSAgICAgICAgICA8c3BhbiBjbGFzcz1cIm10LTVcIj5vcjwvc3Bhbj4tLT5cclxuICAgICAgICAgICAgPGEgY2xhc3M9XCJzb2YtYnV0dG9uIHNvZi1idXR0b24tc2Vjb25kYXJ5XCIgKGNsaWNrKT1cInNjYW5uaW5nID0gdHJ1ZVwiPlxyXG4gICAgICAgICAgICAgIDxpIGNsYXNzPVwic29mLWljb24gc29mLWljb24tcXItY29kZVwiPjwvaT4gU01BUlQgSGVhbHRoIENhcmRcclxuICAgICAgICAgICAgPC9hPlxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0gQGVsc2UgaWYgKHNjYW5uaW5nKSB7XHJcbiAgICAgICAgICA8c29mLXFyLXJlYWRlciAjcmVhZGVyPjwvc29mLXFyLXJlYWRlcj5cclxuICAgICAgICAgIEBpZiAocmVhZGVyLmVycm9yKSB7XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzb2YtYWxlcnQgc29mLWFsZXJ0LWRhbmdlclwiPlxyXG4gICAgICAgICAgICAgIHt7IHJlYWRlci5lcnJvciB9fVxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgIH1cclxuICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJzb2YtYnV0dG9uIHNvZi1idXR0b24tZGFuZ2VyXCIgKGNsaWNrKT1cInNjYW5uaW5nID0gZmFsc2VcIj5DYW5jZWw8L2J1dHRvbj5cclxuICAgICAgICB9IEBlbHNlIGlmIChwYXRpZW50U2VsZWN0aW9uKSB7XHJcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwic29mLXdpZHRoLTEwMFwiIHN0eWxlPVwibWF4LWhlaWdodDogNTB2aDsgb3ZlcmZsb3cteTogYXV0b1wiPlxyXG4gICAgICAgICAgICA8dGFibGUgY2xhc3M9XCJzb2YtdGFibGVcIj5cclxuICAgICAgICAgICAgICA8dGJvZHk+XHJcbiAgICAgICAgICAgICAgPHRyPlxyXG4gICAgICAgICAgICAgICAgPHRkPlxyXG4gICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwic29mLWJ1dHRvbiBzb2YtYnV0dG9uLWRhbmdlciBzb2YtbXItMVwiIChjbGljayk9XCJwYXRpZW50U2VsZWN0aW9uID0gZmFsc2VcIj5DYW5jZWw8L2J1dHRvbj5cclxuICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cInNvZi1idXR0b24gc29mLWJ1dHRvbi1wcmltYXJ5IHNvZi1tci0xXCIgW2NsYXNzLmRpc2FibGVkXT1cIiFoYXNQcmV2aW91c1BhZ2UoKVwiIChjbGljayk9XCJwcmV2KClcIj48aSBjbGFzcz1cInNvZi1pY29uIHNvZi1pY29uLWNhcmV0LWxlZnRcIj48L2k+PC9idXR0b24+XHJcbiAgICAgICAgICAgICAgICAgIDxpbnB1dCBjbGFzcz1cInNvZi1mb3JtLWNvbnRyb2xcIiBzdHlsZT1cImRpc3BsYXk6IGlubGluZS1ibG9jazsgd2lkdGg6IGF1dG9cIiBwbGFjZWhvbGRlcj1cIlNlYXJjaFwiIFsobmdNb2RlbCldPVwicGF0aWVudFF1ZXJ5XCI+XHJcbiAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJzb2YtYnV0dG9uIHNvZi1idXR0b24tcHJpbWFyeSBzb2YtbWwtMVwiIFtjbGFzcy5kaXNhYmxlZF09XCIhaGFzTmV4dFBhZ2UoKVwiIChjbGljayk9XCJuZXh0KClcIj48aSBjbGFzcz1cInNvZi1pY29uIHNvZi1pY29uLWNhcmV0LXJpZ2h0XCI+PC9pPjwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgICAgIEBpZihwYXRpZW50c0xvYWRpbmcpIHtcclxuICAgICAgICAgICAgICAgIDx0cj48dGQ+XHJcbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzb2Ytc3Bpbm5lclwiIHJvbGU9XCJzdGF0dXNcIj5cclxuICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInNvZi1oaWRkZW5cIj5Mb2FkaW5nLi4uPC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgIDwvdGQ+PC90cj5cclxuICAgICAgICAgICAgICB9IEBlbHNlIHtcclxuICAgICAgICAgICAgICAgIEBmb3IgKHBhdGllbnQgb2YgcGF0aWVudHM7IHRyYWNrIHBhdGllbnQuaWQpIHtcclxuICAgICAgICAgICAgICAgICAgPHRyIHN0eWxlPVwiY3Vyc29yOiBwb2ludGVyXCIgKGNsaWNrKT1cInNlbGVjdFBhdGllbnQocGF0aWVudClcIj48dGQ+e3twYXRpZW50Lm5hbWU/LmF0KDApPy5naXZlbn19IHt7cGF0aWVudC5uYW1lPy5hdCgwKT8uZmFtaWx5fX08L3RkPjwvdHI+XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICA8dHI+PHRkIGNsYXNzPVwic29mLXRleHQtYm9sZCBzb2YtdGV4dC1ncmF5XCIgc3R5bGU9XCJmb250LXNpemU6IC43NWVtXCI+e3socGFnZSAtIDEpICogcGF0aWVudHMubGVuZ3RofX0gLSB7e3BhZ2UgKiBwYXRpZW50cy5sZW5ndGh9fS97e3RvdGFsfX08L3RkPjwvdHI+XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIDwvdGJvZHk+XHJcbiAgICAgICAgICAgIDwvdGFibGU+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICB9XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcbjwvZGl2PlxyXG4iXX0=