tango-app-ui-ticket-user 3.5.3 → 3.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -182,10 +182,10 @@ export class PreinstallationInfoComponent {
|
|
|
182
182
|
this.router.navigate(['/tickets/users'], { queryParams: { type: 'installation' } });
|
|
183
183
|
}
|
|
184
184
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PreinstallationInfoComponent, deps: [{ token: i1.ActivatedRoute }, { token: i1.Router }, { token: i2.TicketsService }, { token: i3.ToastService }], target: i0.ɵɵFactoryTarget.Component });
|
|
185
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PreinstallationInfoComponent, selector: "lib-preinstallation-info", ngImport: i0, template: "<div class=\"container-fluid p-5 preinstall-page\">\n\n <!-- Header -->\n <div class=\"card mb-5\">\n <div class=\"card-body d-flex flex-wrap align-items-center justify-content-between gap-4 py-4\">\n <div class=\"d-flex align-items-center gap-4\">\n <button type=\"button\" class=\"btn btn-sm btn-light back-btn\" (click)=\"back()\" aria-label=\"Back to workspace\">\n <i class=\"bi bi-arrow-left\"></i>\n </button>\n <div>\n <div class=\"d-flex align-items-center gap-3\">\n <h4 class=\"mb-0\">{{ ticketInfo?.ticketId || ticketId }}</h4>\n <span class=\"badge state-badge\" [ngClass]=\"'state-' + placementState\">\n {{\n placementState === 'waitingLayout' ? 'Waiting for layout' :\n placementState === 'processing' ? 'Auto placement in progress' :\n placementState === 'failed' ? 'Placement failed' :\n placementState === 'open' ? 'Ready for placement review' :\n placementState === 'approvalPending' ? 'Waiting for approval' :\n placementState === 'approved' ? 'Approved' :\n placementState === 'unavailable' ? 'Status unavailable' : 'Loading'\n }}\n </span>\n </div>\n <div class=\"text-muted fs-7 mt-1\">\n Pre-Installation, camera placement\n <span *ngIf=\"ticketInfo?.basicDetails?.storeName\">, {{ ticketInfo?.basicDetails?.storeName }}</span>\n <span>, Floor {{ floorNumber }}</span>\n </div>\n </div>\n </div>\n <div class=\"d-flex align-items-center gap-3\">\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"refresh()\">\n <i class=\"bi bi-arrow-clockwise me-1\" [class.spinning]=\"reloading || cctvLoading\"></i>Refresh\n </button>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"loading\" class=\"text-center py-10 text-muted\">Loading ticket...</div>\n\n <div *ngIf=\"!loading && ticketInfo\" class=\"row g-5\">\n\n <!-- Placement state / action panel -->\n <div class=\"col-12 col-lg-7\">\n <div class=\"card h-100\">\n <div class=\"card-body\">\n <div class=\"card-head mb-4\">\n <h5 class=\"mb-0\">Camera placement</h5>\n <!-- The imported drawing itself, for the internal team to inspect in\n CAD when the engine cannot handle it or before editing. -->\n <a *ngIf=\"sourceDxfUrl\" [href]=\"sourceDxfUrl\" target=\"_blank\" rel=\"noopener\"\n class=\"btn btn-sm btn-light row-btn\" [ngbTooltip]=\"sourceDxfName\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M12 3v12m0 0 4-4m-4 4-4-4M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <span class=\"ms-1\">Download source DXF</span>\n </a>\n </div>\n\n <div [ngSwitch]=\"placementState\" class=\"state-panel\">\n\n <div *ngSwitchCase=\"'waitingLayout'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">Waiting for the CAD layout.</p>\n <p class=\"text-muted mb-0\">The store's floor drawing has not been imported yet. Auto placement starts right after the CAD import.</p>\n </div>\n\n <div *ngSwitchCase=\"'processing'\" class=\"state-box\">\n <div class=\"d-flex align-items-center gap-3 mb-1\">\n <span class=\"spinner-border spinner-border-sm text-primary\" role=\"status\" aria-hidden=\"true\"></span>\n <p class=\"mb-0 fw-semibold\">Auto camera placement is running.</p>\n </div>\n <p class=\"text-muted mb-3\">The DXF editor unlocks when placement completes. Use Refresh to check again. Meanwhile you can look at the source drawing.</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"openPreview()\">\n <i class=\"bi bi-eye me-1\"></i>View source drawing\n </button>\n </div>\n\n <div *ngSwitchCase=\"'failed'\" class=\"state-box state-box-danger\">\n <p class=\"mb-1 fw-semibold\">Auto placement failed.</p>\n <p class=\"text-muted mb-3\">{{ placement?.errorMsg || cctvRow?.errorMsg || 'The placement engine reported a failure.' }}</p>\n <!-- Retry hidden until the autoPlace Lambda exists (LAMBDAURL.autoPlace is empty).\n Re-enable by removing this comment; retryPlacement() is still wired in the component.\n <button type=\"button\" class=\"btn btn-sm btn-primary row-btn\" [disabled]=\"retrying\" (click)=\"retryPlacement()\">\n <span *ngIf=\"retrying\" class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>\n {{ retrying ? 'Retrying...' : 'Retry auto placement' }}\n </button>\n -->\n </div>\n\n <div *ngSwitchCase=\"'open'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">The drawing is ready for camera review.</p>\n <p class=\"text-muted mb-3\">\n Adjust the auto-placed cameras in the DXF editor, then submit for approval.\n <span *ngIf=\"cctvRow?.isRework\" class=\"text-warning fw-semibold\">This floor was sent back for rework.</span>\n </p>\n <button type=\"button\" class=\"btn btn-sm btn-primary row-btn\" (click)=\"openEditor()\">\n <i class=\"bi bi-pencil-square me-1\"></i>Open DXF editor\n </button>\n </div>\n\n <div *ngSwitchCase=\"'approvalPending'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">Submitted, waiting for approval.</p>\n <p class=\"text-muted mb-3\">The approval team reviews it from the onboard table. You can still view the drawing.</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"openEditor()\">\n <i class=\"bi bi-eye me-1\"></i>View drawing\n </button>\n </div>\n\n <div *ngSwitchCase=\"'approved'\" class=\"state-box state-box-success\">\n <p class=\"mb-1 fw-semibold\">Camera placement approved.</p>\n <p class=\"text-muted mb-0\">This ticket is closed. The installation ticket takes over once every floor of the store is approved.</p>\n </div>\n\n <div *ngSwitchCase=\"'unavailable'\" class=\"state-box state-box-danger\">\n <p class=\"mb-1 fw-semibold\">Placement status unavailable.</p>\n <p class=\"text-muted mb-3\">{{ cctvError }}</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"loadCctvDetail()\">Try again</button>\n </div>\n\n <div *ngSwitchDefault class=\"state-box\">\n <p class=\"text-muted mb-0\">Loading placement status...</p>\n </div>\n </div>\n\n <!-- Version timeline -->\n <div *ngIf=\"versions.length\" class=\"mt-6\">\n <h6 class=\"text-muted mb-3\">Drawing versions</h6>\n <div class=\"version-list\">\n <div class=\"version-row d-flex align-items-center justify-content-between\" *ngFor=\"let file of versions\">\n <div>\n <span class=\"fw-semibold\">v{{ file.version }}</span>\n <span class=\"text-muted ms-2 fs-7\">{{ file.kind === 'auto' ? 'Auto placement' : file.kind === 'approver' ? 'Approver edit' : 'Internal edit' }}</span>\n <span class=\"text-muted ms-2 fs-7\" *ngIf=\"file.cameraCount != null\">{{ file.cameraCount }} cameras</span>\n </div>\n <div class=\"d-flex align-items-center gap-3\">\n <span class=\"text-muted fs-7\">{{ file.uploadedAt | date: 'dd MMM, y HH:mm' }}</span>\n <a *ngIf=\"fileUrls[file.key]\" [href]=\"fileUrls[file.key]\" target=\"_blank\" rel=\"noopener\" class=\"btn btn-sm btn-light row-btn\">\n <i class=\"bi bi-download\"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Ticket info + activity -->\n <div class=\"col-12 col-lg-5\">\n <div class=\"card mb-5\">\n <div class=\"card-body\">\n <h5 class=\"mb-4\">Ticket details</h5>\n <div class=\"detail-grid\">\n <div class=\"detail-row\"><span class=\"text-muted\">Store</span><span>{{ ticketInfo?.basicDetails?.storeName || '-' }} ({{ ticketInfo?.basicDetails?.storeId || storeId }})</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Brand</span><span>{{ ticketInfo?.basicDetails?.clientName || '-' }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Floor</span><span>Floor {{ floorNumber }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Ticket status</span><span class=\"text-capitalize\">{{ ticketInfo?.status || '-' }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Created</span><span>{{ ticketInfo?.createdAt | date: 'dd MMM, y HH:mm' }}</span></div>\n <div class=\"detail-row\" *ngIf=\"cctvRow?.assigneeName\"><span class=\"text-muted\">Assignee</span><span>{{ cctvRow?.assigneeName }}</span></div>\n <div class=\"detail-row\" *ngIf=\"cctvRow?.reworkCount\"><span class=\"text-muted\">Rework count</span><span>{{ cctvRow?.reworkCount }}</span></div>\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-body\">\n <h5 class=\"mb-4\">Activity</h5>\n <div *ngIf=\"!activity.length\" class=\"text-muted fs-7\">No activity yet.</div>\n <div class=\"activity-list\">\n <div class=\"activity-row\" *ngFor=\"let entry of activity\">\n <div class=\"activity-dot\" aria-hidden=\"true\"></div>\n <div class=\"flex-grow-1\">\n <div class=\"d-flex justify-content-between gap-3\">\n <span class=\"fw-semibold fs-7\">{{ entry.description || entry.actionType }}</span>\n <span class=\"text-muted fs-8 text-nowrap\">{{ entry.timeStamp | date: 'dd MMM, HH:mm' }}</span>\n </div>\n <div class=\"text-muted fs-8\" *ngIf=\"entry.comment\">{{ entry.comment }}</div>\n <div class=\"text-muted fs-8\" *ngIf=\"entry.IdentifiedBy && entry.IdentifiedBy !== 'Tango'\">by {{ entry.IdentifiedBy }}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".preinstall-page .back-btn,.preinstall-page .card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.preinstall-page .back-btn .row-btn,.preinstall-page .card-head .row-btn{display:inline-flex;align-items:center;white-space:nowrap}.preinstall-page .row-btn{height:40px;display:inline-flex;align-items:center}.preinstall-page .state-badge{padding:6px 12px;font-weight:600;border-radius:999px}.preinstall-page .state-badge.state-waitingLayout,.preinstall-page .state-badge.state-loading,.preinstall-page .state-badge.state-unavailable{background:#f1f3f5;color:#5e6278}.preinstall-page .state-badge.state-processing{background:#eef6ff;color:#1b84ff}.preinstall-page .state-badge.state-failed{background:#fff5f8;color:#f1416c}.preinstall-page .state-badge.state-open{background:#e8fff3;color:#17c653}.preinstall-page .state-badge.state-approvalPending{background:#fff8dd;color:#f6c000}.preinstall-page .state-badge.state-approved{background:#e8fff3;color:#17c653}.preinstall-page .state-panel .state-box{border:1px solid #e9ecef;border-radius:8px;padding:16px 20px;opacity:0;transform:translateY(4px);animation:preinstallFade .25s ease forwards}.preinstall-page .state-panel .state-box.state-box-danger{border-color:#ffd6e1;background:#fff9fb}.preinstall-page .state-panel .state-box.state-box-success{border-color:#c8f2d8;background:#f6fffa}.preinstall-page .version-list .version-row{padding:10px 0;border-bottom:1px dashed #e9ecef}.preinstall-page .version-list .version-row:last-child{border-bottom:none}.preinstall-page .detail-grid .detail-row{display:flex;justify-content:space-between;gap:12px;padding:7px 0;border-bottom:1px dashed #f1f3f5;font-size:13px}.preinstall-page .detail-grid .detail-row:last-child{border-bottom:none}.preinstall-page .activity-list{max-height:420px;overflow-y:auto}.preinstall-page .activity-list .activity-row{display:flex;gap:10px;padding:8px 0}.preinstall-page .activity-list .activity-row .activity-dot{width:8px;height:8px;border-radius:50%;background:#1b84ff;margin-top:6px;flex-shrink:0}@keyframes preinstallFade{to{opacity:1;transform:translateY(0)}}@media (prefers-reduced-motion: reduce){.preinstall-page .state-panel .state-box{animation:none;opacity:1;transform:none}}.preinstall-page .bi-arrow-clockwise{display:inline-block;line-height:1}.preinstall-page .bi-arrow-clockwise:before{display:inline-block;transform-origin:50% 50%}.preinstall-page .bi-arrow-clockwise.spinning:before{animation:preinstallSpin .8s linear infinite}@keyframes preinstallSpin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion: reduce){.preinstall-page .bi-arrow-clockwise.spinning:before{animation:none}}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i4.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i5.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "pipe", type: i4.DatePipe, name: "date" }] });
|
|
185
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PreinstallationInfoComponent, selector: "lib-preinstallation-info", ngImport: i0, template: "<div class=\"container-fluid p-5 preinstall-page\">\n\n <!-- Header -->\n <div class=\"card mb-5\">\n <div class=\"card-body d-flex flex-wrap align-items-center justify-content-between gap-4 py-4\">\n <div class=\"d-flex align-items-center gap-4\">\n <button type=\"button\" class=\"btn btn-sm btn-light back-btn\" (click)=\"back()\" aria-label=\"Back to workspace\">\n <i class=\"bi bi-arrow-left\"></i>\n </button>\n <div>\n <div class=\"d-flex align-items-center gap-3\">\n <h4 class=\"mb-0\">{{ ticketInfo?.ticketId || ticketId }}</h4>\n <span class=\"badge state-badge\" [ngClass]=\"'state-' + placementState\">\n {{\n placementState === 'waitingLayout' ? 'Waiting for layout' :\n placementState === 'processing' ? 'Auto placement in progress' :\n placementState === 'failed' ? 'Placement failed' :\n placementState === 'open' ? 'Ready for placement review' :\n placementState === 'approvalPending' ? 'Waiting for approval' :\n placementState === 'approved' ? 'Approved' :\n placementState === 'unavailable' ? 'Status unavailable' : 'Loading'\n }}\n </span>\n </div>\n <div class=\"text-muted fs-7 mt-1\">\n Pre-Installation, camera placement\n <span *ngIf=\"ticketInfo?.basicDetails?.storeName\">, {{ ticketInfo?.basicDetails?.storeName }}</span>\n <span>, Floor {{ floorNumber }}</span>\n </div>\n </div>\n </div>\n <div class=\"d-flex align-items-center gap-3\">\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"refresh()\">\n <i class=\"bi bi-arrow-clockwise me-1\" [class.spinning]=\"reloading || cctvLoading\"></i>Refresh\n </button>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"loading\" class=\"text-center py-10 text-muted\">Loading ticket...</div>\n\n <div *ngIf=\"!loading && ticketInfo\" class=\"row g-5\">\n\n <!-- Placement state / action panel -->\n <div class=\"col-12 col-lg-7\">\n <div class=\"card h-100\">\n <div class=\"card-body\">\n <div class=\"card-head mb-4\">\n <h5 class=\"mb-0\">Camera placement</h5>\n <!-- The imported drawing itself, for the internal team to inspect in\n CAD when the engine cannot handle it or before editing. -->\n <a *ngIf=\"sourceDxfUrl\" [href]=\"sourceDxfUrl\" target=\"_blank\" rel=\"noopener\"\n class=\"btn btn-sm btn-light row-btn\" [ngbTooltip]=\"sourceDxfName\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M12 3v12m0 0 4-4m-4 4-4-4M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <span class=\"ms-1\">Download source DXF</span>\n </a>\n </div>\n\n <div [ngSwitch]=\"placementState\" class=\"state-panel\">\n\n <div *ngSwitchCase=\"'waitingLayout'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">Waiting for the CAD layout.</p>\n <p class=\"text-muted mb-0\">The store's floor drawing has not been imported yet. Auto placement starts right after the CAD import.</p>\n </div>\n\n <div *ngSwitchCase=\"'processing'\" class=\"state-box\">\n <div class=\"d-flex align-items-center gap-3 mb-1\">\n <span class=\"spinner-border spinner-border-sm text-primary\" role=\"status\" aria-hidden=\"true\"></span>\n <p class=\"mb-0 fw-semibold\">Auto camera placement is running.</p>\n </div>\n <p class=\"text-muted mb-3\">The DXF editor unlocks when placement completes. Use Refresh to check again. Meanwhile you can look at the source drawing.</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"openPreview()\">\n <i class=\"bi bi-eye me-1\"></i>View source drawing\n </button>\n </div>\n\n <div *ngSwitchCase=\"'failed'\" class=\"state-box state-box-danger\">\n <p class=\"mb-1 fw-semibold\">Auto placement failed.</p>\n <p class=\"text-muted mb-3\">{{ placement?.errorMsg || cctvRow?.errorMsg || 'The placement engine reported a failure.' }}</p>\n <!-- Retry hidden until the autoPlace Lambda exists (LAMBDAURL.autoPlace is empty).\n Re-enable by removing this comment; retryPlacement() is still wired in the component.\n <button type=\"button\" class=\"btn btn-sm btn-primary row-btn\" [disabled]=\"retrying\" (click)=\"retryPlacement()\">\n <span *ngIf=\"retrying\" class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>\n {{ retrying ? 'Retrying...' : 'Retry auto placement' }}\n </button>\n -->\n </div>\n\n <div *ngSwitchCase=\"'open'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">The drawing is ready for camera review.</p>\n <p class=\"text-muted mb-3\">\n Adjust the auto-placed cameras in the DXF editor, then submit for approval.\n <span *ngIf=\"cctvRow?.isRework\" class=\"text-warning fw-semibold\">This floor was sent back for rework.</span>\n </p>\n <button type=\"button\" class=\"btn btn-sm btn-primary row-btn\" (click)=\"openEditor()\">\n <i class=\"bi bi-pencil-square me-1\"></i>Open DXF editor\n </button>\n </div>\n\n <div *ngSwitchCase=\"'approvalPending'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">Submitted, waiting for approval.</p>\n <p class=\"text-muted mb-3\">The approval team reviews it from the onboard table. You can still view the drawing.</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"openEditor()\">\n <i class=\"bi bi-eye me-1\"></i>View drawing\n </button>\n </div>\n\n <div *ngSwitchCase=\"'approved'\" class=\"state-box state-box-success\">\n <p class=\"mb-1 fw-semibold\">Camera placement approved.</p>\n <p class=\"text-muted mb-0\">This ticket is closed. The installation ticket takes over once every floor of the store is approved.</p>\n </div>\n\n <div *ngSwitchCase=\"'unavailable'\" class=\"state-box state-box-danger\">\n <p class=\"mb-1 fw-semibold\">Placement status unavailable.</p>\n <p class=\"text-muted mb-3\">{{ cctvError }}</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"loadCctvDetail()\">Try again</button>\n </div>\n\n <div *ngSwitchDefault class=\"state-box\">\n <p class=\"text-muted mb-0\">Loading placement status...</p>\n </div>\n </div>\n\n <!-- Version timeline -->\n <div *ngIf=\"versions.length\" class=\"mt-6\">\n <h6 class=\"text-muted mb-3\">Drawing versions</h6>\n <div class=\"version-list\">\n <div class=\"version-row d-flex align-items-center justify-content-between\" *ngFor=\"let file of versions\">\n <div>\n <span class=\"fw-semibold\">v{{ file.version }}</span>\n <span class=\"text-muted ms-2 fs-7\">{{ file.kind === 'auto' ? 'Auto placement' : file.kind === 'approver' ? 'Approver edit' : 'Internal edit' }}</span>\n <span class=\"text-muted ms-2 fs-7\" *ngIf=\"file.cameraCount != null\">{{ file.cameraCount }} cameras</span>\n </div>\n <div class=\"d-flex align-items-center gap-3\">\n <span class=\"text-muted fs-7\">{{ file.uploadedAt | date: 'dd MMM, y h:mm a' }}</span>\n <a *ngIf=\"fileUrls[file.key]\" [href]=\"fileUrls[file.key]\" target=\"_blank\" rel=\"noopener\" class=\"btn btn-sm btn-light row-btn\">\n <i class=\"bi bi-download\"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Ticket info + activity -->\n <div class=\"col-12 col-lg-5\">\n <div class=\"card mb-5\">\n <div class=\"card-body\">\n <h5 class=\"mb-4\">Ticket details</h5>\n <div class=\"detail-grid\">\n <div class=\"detail-row\"><span class=\"text-muted\">Store</span><span>{{ ticketInfo?.basicDetails?.storeName || '-' }} ({{ ticketInfo?.basicDetails?.storeId || storeId }})</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Brand</span><span>{{ ticketInfo?.basicDetails?.clientName || '-' }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Floor</span><span>Floor {{ floorNumber }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Ticket status</span><span class=\"text-capitalize\">{{ ticketInfo?.status || '-' }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Created</span><span>{{ ticketInfo?.createdAt | date: 'dd MMM, y h:mm a' }}</span></div>\n <div class=\"detail-row\" *ngIf=\"cctvRow?.assigneeName\"><span class=\"text-muted\">Assignee</span><span>{{ cctvRow?.assigneeName }}</span></div>\n <div class=\"detail-row\" *ngIf=\"cctvRow?.reworkCount\"><span class=\"text-muted\">Rework count</span><span>{{ cctvRow?.reworkCount }}</span></div>\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-body\">\n <h5 class=\"mb-4\">Activity</h5>\n <div *ngIf=\"!activity.length\" class=\"text-muted fs-7\">No activity yet.</div>\n <div class=\"activity-list\">\n <div class=\"activity-row\" *ngFor=\"let entry of activity\">\n <div class=\"activity-dot\" aria-hidden=\"true\"></div>\n <div class=\"flex-grow-1\">\n <div class=\"d-flex justify-content-between gap-3\">\n <span class=\"fw-semibold fs-7\">{{ entry.description || entry.actionType }}</span>\n <span class=\"text-muted fs-8 text-nowrap\">{{ entry.timeStamp | date: 'dd MMM, h:mm a' }}</span>\n </div>\n <div class=\"text-muted fs-8\" *ngIf=\"entry.comment\">{{ entry.comment }}</div>\n <div class=\"text-muted fs-8\" *ngIf=\"entry.IdentifiedBy && entry.IdentifiedBy !== 'Tango'\">by {{ entry.IdentifiedBy }}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".preinstall-page .back-btn,.preinstall-page .card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.preinstall-page .back-btn .row-btn,.preinstall-page .card-head .row-btn{display:inline-flex;align-items:center;white-space:nowrap}.preinstall-page .row-btn{height:40px;display:inline-flex;align-items:center}.preinstall-page .state-badge{padding:6px 12px;font-weight:600;border-radius:999px}.preinstall-page .state-badge.state-waitingLayout,.preinstall-page .state-badge.state-loading,.preinstall-page .state-badge.state-unavailable{background:#f1f3f5;color:#5e6278}.preinstall-page .state-badge.state-processing{background:#eef6ff;color:#1b84ff}.preinstall-page .state-badge.state-failed{background:#fff5f8;color:#f1416c}.preinstall-page .state-badge.state-open{background:#e8fff3;color:#17c653}.preinstall-page .state-badge.state-approvalPending{background:#fff8dd;color:#f6c000}.preinstall-page .state-badge.state-approved{background:#e8fff3;color:#17c653}.preinstall-page .state-panel .state-box{border:1px solid #e9ecef;border-radius:8px;padding:16px 20px;opacity:0;transform:translateY(4px);animation:preinstallFade .25s ease forwards}.preinstall-page .state-panel .state-box.state-box-danger{border-color:#ffd6e1;background:#fff9fb}.preinstall-page .state-panel .state-box.state-box-success{border-color:#c8f2d8;background:#f6fffa}.preinstall-page .version-list .version-row{padding:10px 0;border-bottom:1px dashed #e9ecef}.preinstall-page .version-list .version-row:last-child{border-bottom:none}.preinstall-page .detail-grid .detail-row{display:flex;justify-content:space-between;gap:12px;padding:7px 0;border-bottom:1px dashed #f1f3f5;font-size:13px}.preinstall-page .detail-grid .detail-row:last-child{border-bottom:none}.preinstall-page .activity-list{max-height:420px;overflow-y:auto}.preinstall-page .activity-list .activity-row{display:flex;gap:10px;padding:8px 0}.preinstall-page .activity-list .activity-row .activity-dot{width:8px;height:8px;border-radius:50%;background:#1b84ff;margin-top:6px;flex-shrink:0}@keyframes preinstallFade{to{opacity:1;transform:translateY(0)}}@media (prefers-reduced-motion: reduce){.preinstall-page .state-panel .state-box{animation:none;opacity:1;transform:none}}.preinstall-page .bi-arrow-clockwise{display:inline-block;line-height:1}.preinstall-page .bi-arrow-clockwise:before{display:inline-block;transform-origin:50% 50%}.preinstall-page .bi-arrow-clockwise.spinning:before{animation:preinstallSpin .8s linear infinite}@keyframes preinstallSpin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion: reduce){.preinstall-page .bi-arrow-clockwise.spinning:before{animation:none}}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i4.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i5.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "pipe", type: i4.DatePipe, name: "date" }] });
|
|
186
186
|
}
|
|
187
187
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PreinstallationInfoComponent, decorators: [{
|
|
188
188
|
type: Component,
|
|
189
|
-
args: [{ selector: 'lib-preinstallation-info', template: "<div class=\"container-fluid p-5 preinstall-page\">\n\n <!-- Header -->\n <div class=\"card mb-5\">\n <div class=\"card-body d-flex flex-wrap align-items-center justify-content-between gap-4 py-4\">\n <div class=\"d-flex align-items-center gap-4\">\n <button type=\"button\" class=\"btn btn-sm btn-light back-btn\" (click)=\"back()\" aria-label=\"Back to workspace\">\n <i class=\"bi bi-arrow-left\"></i>\n </button>\n <div>\n <div class=\"d-flex align-items-center gap-3\">\n <h4 class=\"mb-0\">{{ ticketInfo?.ticketId || ticketId }}</h4>\n <span class=\"badge state-badge\" [ngClass]=\"'state-' + placementState\">\n {{\n placementState === 'waitingLayout' ? 'Waiting for layout' :\n placementState === 'processing' ? 'Auto placement in progress' :\n placementState === 'failed' ? 'Placement failed' :\n placementState === 'open' ? 'Ready for placement review' :\n placementState === 'approvalPending' ? 'Waiting for approval' :\n placementState === 'approved' ? 'Approved' :\n placementState === 'unavailable' ? 'Status unavailable' : 'Loading'\n }}\n </span>\n </div>\n <div class=\"text-muted fs-7 mt-1\">\n Pre-Installation, camera placement\n <span *ngIf=\"ticketInfo?.basicDetails?.storeName\">, {{ ticketInfo?.basicDetails?.storeName }}</span>\n <span>, Floor {{ floorNumber }}</span>\n </div>\n </div>\n </div>\n <div class=\"d-flex align-items-center gap-3\">\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"refresh()\">\n <i class=\"bi bi-arrow-clockwise me-1\" [class.spinning]=\"reloading || cctvLoading\"></i>Refresh\n </button>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"loading\" class=\"text-center py-10 text-muted\">Loading ticket...</div>\n\n <div *ngIf=\"!loading && ticketInfo\" class=\"row g-5\">\n\n <!-- Placement state / action panel -->\n <div class=\"col-12 col-lg-7\">\n <div class=\"card h-100\">\n <div class=\"card-body\">\n <div class=\"card-head mb-4\">\n <h5 class=\"mb-0\">Camera placement</h5>\n <!-- The imported drawing itself, for the internal team to inspect in\n CAD when the engine cannot handle it or before editing. -->\n <a *ngIf=\"sourceDxfUrl\" [href]=\"sourceDxfUrl\" target=\"_blank\" rel=\"noopener\"\n class=\"btn btn-sm btn-light row-btn\" [ngbTooltip]=\"sourceDxfName\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M12 3v12m0 0 4-4m-4 4-4-4M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <span class=\"ms-1\">Download source DXF</span>\n </a>\n </div>\n\n <div [ngSwitch]=\"placementState\" class=\"state-panel\">\n\n <div *ngSwitchCase=\"'waitingLayout'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">Waiting for the CAD layout.</p>\n <p class=\"text-muted mb-0\">The store's floor drawing has not been imported yet. Auto placement starts right after the CAD import.</p>\n </div>\n\n <div *ngSwitchCase=\"'processing'\" class=\"state-box\">\n <div class=\"d-flex align-items-center gap-3 mb-1\">\n <span class=\"spinner-border spinner-border-sm text-primary\" role=\"status\" aria-hidden=\"true\"></span>\n <p class=\"mb-0 fw-semibold\">Auto camera placement is running.</p>\n </div>\n <p class=\"text-muted mb-3\">The DXF editor unlocks when placement completes. Use Refresh to check again. Meanwhile you can look at the source drawing.</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"openPreview()\">\n <i class=\"bi bi-eye me-1\"></i>View source drawing\n </button>\n </div>\n\n <div *ngSwitchCase=\"'failed'\" class=\"state-box state-box-danger\">\n <p class=\"mb-1 fw-semibold\">Auto placement failed.</p>\n <p class=\"text-muted mb-3\">{{ placement?.errorMsg || cctvRow?.errorMsg || 'The placement engine reported a failure.' }}</p>\n <!-- Retry hidden until the autoPlace Lambda exists (LAMBDAURL.autoPlace is empty).\n Re-enable by removing this comment; retryPlacement() is still wired in the component.\n <button type=\"button\" class=\"btn btn-sm btn-primary row-btn\" [disabled]=\"retrying\" (click)=\"retryPlacement()\">\n <span *ngIf=\"retrying\" class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>\n {{ retrying ? 'Retrying...' : 'Retry auto placement' }}\n </button>\n -->\n </div>\n\n <div *ngSwitchCase=\"'open'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">The drawing is ready for camera review.</p>\n <p class=\"text-muted mb-3\">\n Adjust the auto-placed cameras in the DXF editor, then submit for approval.\n <span *ngIf=\"cctvRow?.isRework\" class=\"text-warning fw-semibold\">This floor was sent back for rework.</span>\n </p>\n <button type=\"button\" class=\"btn btn-sm btn-primary row-btn\" (click)=\"openEditor()\">\n <i class=\"bi bi-pencil-square me-1\"></i>Open DXF editor\n </button>\n </div>\n\n <div *ngSwitchCase=\"'approvalPending'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">Submitted, waiting for approval.</p>\n <p class=\"text-muted mb-3\">The approval team reviews it from the onboard table. You can still view the drawing.</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"openEditor()\">\n <i class=\"bi bi-eye me-1\"></i>View drawing\n </button>\n </div>\n\n <div *ngSwitchCase=\"'approved'\" class=\"state-box state-box-success\">\n <p class=\"mb-1 fw-semibold\">Camera placement approved.</p>\n <p class=\"text-muted mb-0\">This ticket is closed. The installation ticket takes over once every floor of the store is approved.</p>\n </div>\n\n <div *ngSwitchCase=\"'unavailable'\" class=\"state-box state-box-danger\">\n <p class=\"mb-1 fw-semibold\">Placement status unavailable.</p>\n <p class=\"text-muted mb-3\">{{ cctvError }}</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"loadCctvDetail()\">Try again</button>\n </div>\n\n <div *ngSwitchDefault class=\"state-box\">\n <p class=\"text-muted mb-0\">Loading placement status...</p>\n </div>\n </div>\n\n <!-- Version timeline -->\n <div *ngIf=\"versions.length\" class=\"mt-6\">\n <h6 class=\"text-muted mb-3\">Drawing versions</h6>\n <div class=\"version-list\">\n <div class=\"version-row d-flex align-items-center justify-content-between\" *ngFor=\"let file of versions\">\n <div>\n <span class=\"fw-semibold\">v{{ file.version }}</span>\n <span class=\"text-muted ms-2 fs-7\">{{ file.kind === 'auto' ? 'Auto placement' : file.kind === 'approver' ? 'Approver edit' : 'Internal edit' }}</span>\n <span class=\"text-muted ms-2 fs-7\" *ngIf=\"file.cameraCount != null\">{{ file.cameraCount }} cameras</span>\n </div>\n <div class=\"d-flex align-items-center gap-3\">\n <span class=\"text-muted fs-7\">{{ file.uploadedAt | date: 'dd MMM, y HH:mm' }}</span>\n <a *ngIf=\"fileUrls[file.key]\" [href]=\"fileUrls[file.key]\" target=\"_blank\" rel=\"noopener\" class=\"btn btn-sm btn-light row-btn\">\n <i class=\"bi bi-download\"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Ticket info + activity -->\n <div class=\"col-12 col-lg-5\">\n <div class=\"card mb-5\">\n <div class=\"card-body\">\n <h5 class=\"mb-4\">Ticket details</h5>\n <div class=\"detail-grid\">\n <div class=\"detail-row\"><span class=\"text-muted\">Store</span><span>{{ ticketInfo?.basicDetails?.storeName || '-' }} ({{ ticketInfo?.basicDetails?.storeId || storeId }})</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Brand</span><span>{{ ticketInfo?.basicDetails?.clientName || '-' }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Floor</span><span>Floor {{ floorNumber }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Ticket status</span><span class=\"text-capitalize\">{{ ticketInfo?.status || '-' }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Created</span><span>{{ ticketInfo?.createdAt | date: 'dd MMM, y HH:mm' }}</span></div>\n <div class=\"detail-row\" *ngIf=\"cctvRow?.assigneeName\"><span class=\"text-muted\">Assignee</span><span>{{ cctvRow?.assigneeName }}</span></div>\n <div class=\"detail-row\" *ngIf=\"cctvRow?.reworkCount\"><span class=\"text-muted\">Rework count</span><span>{{ cctvRow?.reworkCount }}</span></div>\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-body\">\n <h5 class=\"mb-4\">Activity</h5>\n <div *ngIf=\"!activity.length\" class=\"text-muted fs-7\">No activity yet.</div>\n <div class=\"activity-list\">\n <div class=\"activity-row\" *ngFor=\"let entry of activity\">\n <div class=\"activity-dot\" aria-hidden=\"true\"></div>\n <div class=\"flex-grow-1\">\n <div class=\"d-flex justify-content-between gap-3\">\n <span class=\"fw-semibold fs-7\">{{ entry.description || entry.actionType }}</span>\n <span class=\"text-muted fs-8 text-nowrap\">{{ entry.timeStamp | date: 'dd MMM, HH:mm' }}</span>\n </div>\n <div class=\"text-muted fs-8\" *ngIf=\"entry.comment\">{{ entry.comment }}</div>\n <div class=\"text-muted fs-8\" *ngIf=\"entry.IdentifiedBy && entry.IdentifiedBy !== 'Tango'\">by {{ entry.IdentifiedBy }}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".preinstall-page .back-btn,.preinstall-page .card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.preinstall-page .back-btn .row-btn,.preinstall-page .card-head .row-btn{display:inline-flex;align-items:center;white-space:nowrap}.preinstall-page .row-btn{height:40px;display:inline-flex;align-items:center}.preinstall-page .state-badge{padding:6px 12px;font-weight:600;border-radius:999px}.preinstall-page .state-badge.state-waitingLayout,.preinstall-page .state-badge.state-loading,.preinstall-page .state-badge.state-unavailable{background:#f1f3f5;color:#5e6278}.preinstall-page .state-badge.state-processing{background:#eef6ff;color:#1b84ff}.preinstall-page .state-badge.state-failed{background:#fff5f8;color:#f1416c}.preinstall-page .state-badge.state-open{background:#e8fff3;color:#17c653}.preinstall-page .state-badge.state-approvalPending{background:#fff8dd;color:#f6c000}.preinstall-page .state-badge.state-approved{background:#e8fff3;color:#17c653}.preinstall-page .state-panel .state-box{border:1px solid #e9ecef;border-radius:8px;padding:16px 20px;opacity:0;transform:translateY(4px);animation:preinstallFade .25s ease forwards}.preinstall-page .state-panel .state-box.state-box-danger{border-color:#ffd6e1;background:#fff9fb}.preinstall-page .state-panel .state-box.state-box-success{border-color:#c8f2d8;background:#f6fffa}.preinstall-page .version-list .version-row{padding:10px 0;border-bottom:1px dashed #e9ecef}.preinstall-page .version-list .version-row:last-child{border-bottom:none}.preinstall-page .detail-grid .detail-row{display:flex;justify-content:space-between;gap:12px;padding:7px 0;border-bottom:1px dashed #f1f3f5;font-size:13px}.preinstall-page .detail-grid .detail-row:last-child{border-bottom:none}.preinstall-page .activity-list{max-height:420px;overflow-y:auto}.preinstall-page .activity-list .activity-row{display:flex;gap:10px;padding:8px 0}.preinstall-page .activity-list .activity-row .activity-dot{width:8px;height:8px;border-radius:50%;background:#1b84ff;margin-top:6px;flex-shrink:0}@keyframes preinstallFade{to{opacity:1;transform:translateY(0)}}@media (prefers-reduced-motion: reduce){.preinstall-page .state-panel .state-box{animation:none;opacity:1;transform:none}}.preinstall-page .bi-arrow-clockwise{display:inline-block;line-height:1}.preinstall-page .bi-arrow-clockwise:before{display:inline-block;transform-origin:50% 50%}.preinstall-page .bi-arrow-clockwise.spinning:before{animation:preinstallSpin .8s linear infinite}@keyframes preinstallSpin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion: reduce){.preinstall-page .bi-arrow-clockwise.spinning:before{animation:none}}\n"] }]
|
|
189
|
+
args: [{ selector: 'lib-preinstallation-info', template: "<div class=\"container-fluid p-5 preinstall-page\">\n\n <!-- Header -->\n <div class=\"card mb-5\">\n <div class=\"card-body d-flex flex-wrap align-items-center justify-content-between gap-4 py-4\">\n <div class=\"d-flex align-items-center gap-4\">\n <button type=\"button\" class=\"btn btn-sm btn-light back-btn\" (click)=\"back()\" aria-label=\"Back to workspace\">\n <i class=\"bi bi-arrow-left\"></i>\n </button>\n <div>\n <div class=\"d-flex align-items-center gap-3\">\n <h4 class=\"mb-0\">{{ ticketInfo?.ticketId || ticketId }}</h4>\n <span class=\"badge state-badge\" [ngClass]=\"'state-' + placementState\">\n {{\n placementState === 'waitingLayout' ? 'Waiting for layout' :\n placementState === 'processing' ? 'Auto placement in progress' :\n placementState === 'failed' ? 'Placement failed' :\n placementState === 'open' ? 'Ready for placement review' :\n placementState === 'approvalPending' ? 'Waiting for approval' :\n placementState === 'approved' ? 'Approved' :\n placementState === 'unavailable' ? 'Status unavailable' : 'Loading'\n }}\n </span>\n </div>\n <div class=\"text-muted fs-7 mt-1\">\n Pre-Installation, camera placement\n <span *ngIf=\"ticketInfo?.basicDetails?.storeName\">, {{ ticketInfo?.basicDetails?.storeName }}</span>\n <span>, Floor {{ floorNumber }}</span>\n </div>\n </div>\n </div>\n <div class=\"d-flex align-items-center gap-3\">\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"refresh()\">\n <i class=\"bi bi-arrow-clockwise me-1\" [class.spinning]=\"reloading || cctvLoading\"></i>Refresh\n </button>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"loading\" class=\"text-center py-10 text-muted\">Loading ticket...</div>\n\n <div *ngIf=\"!loading && ticketInfo\" class=\"row g-5\">\n\n <!-- Placement state / action panel -->\n <div class=\"col-12 col-lg-7\">\n <div class=\"card h-100\">\n <div class=\"card-body\">\n <div class=\"card-head mb-4\">\n <h5 class=\"mb-0\">Camera placement</h5>\n <!-- The imported drawing itself, for the internal team to inspect in\n CAD when the engine cannot handle it or before editing. -->\n <a *ngIf=\"sourceDxfUrl\" [href]=\"sourceDxfUrl\" target=\"_blank\" rel=\"noopener\"\n class=\"btn btn-sm btn-light row-btn\" [ngbTooltip]=\"sourceDxfName\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M12 3v12m0 0 4-4m-4 4-4-4M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <span class=\"ms-1\">Download source DXF</span>\n </a>\n </div>\n\n <div [ngSwitch]=\"placementState\" class=\"state-panel\">\n\n <div *ngSwitchCase=\"'waitingLayout'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">Waiting for the CAD layout.</p>\n <p class=\"text-muted mb-0\">The store's floor drawing has not been imported yet. Auto placement starts right after the CAD import.</p>\n </div>\n\n <div *ngSwitchCase=\"'processing'\" class=\"state-box\">\n <div class=\"d-flex align-items-center gap-3 mb-1\">\n <span class=\"spinner-border spinner-border-sm text-primary\" role=\"status\" aria-hidden=\"true\"></span>\n <p class=\"mb-0 fw-semibold\">Auto camera placement is running.</p>\n </div>\n <p class=\"text-muted mb-3\">The DXF editor unlocks when placement completes. Use Refresh to check again. Meanwhile you can look at the source drawing.</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"openPreview()\">\n <i class=\"bi bi-eye me-1\"></i>View source drawing\n </button>\n </div>\n\n <div *ngSwitchCase=\"'failed'\" class=\"state-box state-box-danger\">\n <p class=\"mb-1 fw-semibold\">Auto placement failed.</p>\n <p class=\"text-muted mb-3\">{{ placement?.errorMsg || cctvRow?.errorMsg || 'The placement engine reported a failure.' }}</p>\n <!-- Retry hidden until the autoPlace Lambda exists (LAMBDAURL.autoPlace is empty).\n Re-enable by removing this comment; retryPlacement() is still wired in the component.\n <button type=\"button\" class=\"btn btn-sm btn-primary row-btn\" [disabled]=\"retrying\" (click)=\"retryPlacement()\">\n <span *ngIf=\"retrying\" class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>\n {{ retrying ? 'Retrying...' : 'Retry auto placement' }}\n </button>\n -->\n </div>\n\n <div *ngSwitchCase=\"'open'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">The drawing is ready for camera review.</p>\n <p class=\"text-muted mb-3\">\n Adjust the auto-placed cameras in the DXF editor, then submit for approval.\n <span *ngIf=\"cctvRow?.isRework\" class=\"text-warning fw-semibold\">This floor was sent back for rework.</span>\n </p>\n <button type=\"button\" class=\"btn btn-sm btn-primary row-btn\" (click)=\"openEditor()\">\n <i class=\"bi bi-pencil-square me-1\"></i>Open DXF editor\n </button>\n </div>\n\n <div *ngSwitchCase=\"'approvalPending'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">Submitted, waiting for approval.</p>\n <p class=\"text-muted mb-3\">The approval team reviews it from the onboard table. You can still view the drawing.</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"openEditor()\">\n <i class=\"bi bi-eye me-1\"></i>View drawing\n </button>\n </div>\n\n <div *ngSwitchCase=\"'approved'\" class=\"state-box state-box-success\">\n <p class=\"mb-1 fw-semibold\">Camera placement approved.</p>\n <p class=\"text-muted mb-0\">This ticket is closed. The installation ticket takes over once every floor of the store is approved.</p>\n </div>\n\n <div *ngSwitchCase=\"'unavailable'\" class=\"state-box state-box-danger\">\n <p class=\"mb-1 fw-semibold\">Placement status unavailable.</p>\n <p class=\"text-muted mb-3\">{{ cctvError }}</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"loadCctvDetail()\">Try again</button>\n </div>\n\n <div *ngSwitchDefault class=\"state-box\">\n <p class=\"text-muted mb-0\">Loading placement status...</p>\n </div>\n </div>\n\n <!-- Version timeline -->\n <div *ngIf=\"versions.length\" class=\"mt-6\">\n <h6 class=\"text-muted mb-3\">Drawing versions</h6>\n <div class=\"version-list\">\n <div class=\"version-row d-flex align-items-center justify-content-between\" *ngFor=\"let file of versions\">\n <div>\n <span class=\"fw-semibold\">v{{ file.version }}</span>\n <span class=\"text-muted ms-2 fs-7\">{{ file.kind === 'auto' ? 'Auto placement' : file.kind === 'approver' ? 'Approver edit' : 'Internal edit' }}</span>\n <span class=\"text-muted ms-2 fs-7\" *ngIf=\"file.cameraCount != null\">{{ file.cameraCount }} cameras</span>\n </div>\n <div class=\"d-flex align-items-center gap-3\">\n <span class=\"text-muted fs-7\">{{ file.uploadedAt | date: 'dd MMM, y h:mm a' }}</span>\n <a *ngIf=\"fileUrls[file.key]\" [href]=\"fileUrls[file.key]\" target=\"_blank\" rel=\"noopener\" class=\"btn btn-sm btn-light row-btn\">\n <i class=\"bi bi-download\"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Ticket info + activity -->\n <div class=\"col-12 col-lg-5\">\n <div class=\"card mb-5\">\n <div class=\"card-body\">\n <h5 class=\"mb-4\">Ticket details</h5>\n <div class=\"detail-grid\">\n <div class=\"detail-row\"><span class=\"text-muted\">Store</span><span>{{ ticketInfo?.basicDetails?.storeName || '-' }} ({{ ticketInfo?.basicDetails?.storeId || storeId }})</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Brand</span><span>{{ ticketInfo?.basicDetails?.clientName || '-' }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Floor</span><span>Floor {{ floorNumber }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Ticket status</span><span class=\"text-capitalize\">{{ ticketInfo?.status || '-' }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Created</span><span>{{ ticketInfo?.createdAt | date: 'dd MMM, y h:mm a' }}</span></div>\n <div class=\"detail-row\" *ngIf=\"cctvRow?.assigneeName\"><span class=\"text-muted\">Assignee</span><span>{{ cctvRow?.assigneeName }}</span></div>\n <div class=\"detail-row\" *ngIf=\"cctvRow?.reworkCount\"><span class=\"text-muted\">Rework count</span><span>{{ cctvRow?.reworkCount }}</span></div>\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-body\">\n <h5 class=\"mb-4\">Activity</h5>\n <div *ngIf=\"!activity.length\" class=\"text-muted fs-7\">No activity yet.</div>\n <div class=\"activity-list\">\n <div class=\"activity-row\" *ngFor=\"let entry of activity\">\n <div class=\"activity-dot\" aria-hidden=\"true\"></div>\n <div class=\"flex-grow-1\">\n <div class=\"d-flex justify-content-between gap-3\">\n <span class=\"fw-semibold fs-7\">{{ entry.description || entry.actionType }}</span>\n <span class=\"text-muted fs-8 text-nowrap\">{{ entry.timeStamp | date: 'dd MMM, h:mm a' }}</span>\n </div>\n <div class=\"text-muted fs-8\" *ngIf=\"entry.comment\">{{ entry.comment }}</div>\n <div class=\"text-muted fs-8\" *ngIf=\"entry.IdentifiedBy && entry.IdentifiedBy !== 'Tango'\">by {{ entry.IdentifiedBy }}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".preinstall-page .back-btn,.preinstall-page .card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.preinstall-page .back-btn .row-btn,.preinstall-page .card-head .row-btn{display:inline-flex;align-items:center;white-space:nowrap}.preinstall-page .row-btn{height:40px;display:inline-flex;align-items:center}.preinstall-page .state-badge{padding:6px 12px;font-weight:600;border-radius:999px}.preinstall-page .state-badge.state-waitingLayout,.preinstall-page .state-badge.state-loading,.preinstall-page .state-badge.state-unavailable{background:#f1f3f5;color:#5e6278}.preinstall-page .state-badge.state-processing{background:#eef6ff;color:#1b84ff}.preinstall-page .state-badge.state-failed{background:#fff5f8;color:#f1416c}.preinstall-page .state-badge.state-open{background:#e8fff3;color:#17c653}.preinstall-page .state-badge.state-approvalPending{background:#fff8dd;color:#f6c000}.preinstall-page .state-badge.state-approved{background:#e8fff3;color:#17c653}.preinstall-page .state-panel .state-box{border:1px solid #e9ecef;border-radius:8px;padding:16px 20px;opacity:0;transform:translateY(4px);animation:preinstallFade .25s ease forwards}.preinstall-page .state-panel .state-box.state-box-danger{border-color:#ffd6e1;background:#fff9fb}.preinstall-page .state-panel .state-box.state-box-success{border-color:#c8f2d8;background:#f6fffa}.preinstall-page .version-list .version-row{padding:10px 0;border-bottom:1px dashed #e9ecef}.preinstall-page .version-list .version-row:last-child{border-bottom:none}.preinstall-page .detail-grid .detail-row{display:flex;justify-content:space-between;gap:12px;padding:7px 0;border-bottom:1px dashed #f1f3f5;font-size:13px}.preinstall-page .detail-grid .detail-row:last-child{border-bottom:none}.preinstall-page .activity-list{max-height:420px;overflow-y:auto}.preinstall-page .activity-list .activity-row{display:flex;gap:10px;padding:8px 0}.preinstall-page .activity-list .activity-row .activity-dot{width:8px;height:8px;border-radius:50%;background:#1b84ff;margin-top:6px;flex-shrink:0}@keyframes preinstallFade{to{opacity:1;transform:translateY(0)}}@media (prefers-reduced-motion: reduce){.preinstall-page .state-panel .state-box{animation:none;opacity:1;transform:none}}.preinstall-page .bi-arrow-clockwise{display:inline-block;line-height:1}.preinstall-page .bi-arrow-clockwise:before{display:inline-block;transform-origin:50% 50%}.preinstall-page .bi-arrow-clockwise.spinning:before{animation:preinstallSpin .8s linear infinite}@keyframes preinstallSpin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion: reduce){.preinstall-page .bi-arrow-clockwise.spinning:before{animation:none}}\n"] }]
|
|
190
190
|
}], ctorParameters: () => [{ type: i1.ActivatedRoute }, { type: i1.Router }, { type: i2.TicketsService }, { type: i3.ToastService }] });
|
|
191
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJlaW5zdGFsbGF0aW9uLWluZm8uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFuZ28tdGlja2V0LXVzZXIvc3JjL2xpYi9jb21wb25lbnRzL3ByZWluc3RhbGxhdGlvbi1pbmZvL3ByZWluc3RhbGxhdGlvbi1pbmZvLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RhbmdvLXRpY2tldC11c2VyL3NyYy9saWIvY29tcG9uZW50cy9wcmVpbnN0YWxsYXRpb24taW5mby9wcmVpbnN0YWxsYXRpb24taW5mby5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFxQixNQUFNLGVBQWUsQ0FBQztBQUU3RCxPQUFPLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQzs7Ozs7OztBQUkxQzs7Ozs7Ozs7Ozs7O0dBWUc7QUFNSCxNQUFNLE9BQU8sNEJBQTRCO0lBbUI3QjtJQUNBO0lBQ0E7SUFDQTtJQXJCVixRQUFRLENBQWdCO0lBQ3hCLE9BQU8sQ0FBZ0I7SUFDdkIsVUFBVSxDQUFNO0lBQ2hCLE9BQU8sQ0FBTTtJQUNiLFNBQVMsQ0FBTTtJQUNmLHlEQUF5RDtJQUN6RCxTQUFTLEdBQVEsSUFBSSxDQUFDO0lBQ3RCLFFBQVEsR0FBUSxFQUFFLENBQUM7SUFDbkIsT0FBTyxHQUFZLElBQUksQ0FBQztJQUN4QixXQUFXLEdBQVksS0FBSyxDQUFDO0lBQzdCLDRFQUE0RTtJQUM1RSxTQUFTLEdBQVksS0FBSyxDQUFDO0lBQzNCLFNBQVMsR0FBVyxFQUFFLENBQUM7SUFDdkIsUUFBUSxHQUFZLEtBQUssQ0FBQztJQUVULFFBQVEsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO0lBRTFDLFlBQ1UsS0FBcUIsRUFDckIsTUFBYyxFQUNkLE9BQXVCLEVBQ3ZCLFlBQTBCO1FBSDFCLFVBQUss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VyxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRTtTQUN2RCxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsSUFBSTtRQUNGLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxFQUFFLFdBQVcsRUFBRSxFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDdEYsQ0FBQzt3R0F6S1UsNEJBQTRCOzRGQUE1Qiw0QkFBNEIsZ0VDeEJ6QyxreVZBNExBOzs0RkRwS2EsNEJBQTRCO2tCQUx4QyxTQUFTOytCQUNFLDBCQUEwQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgT25EZXN0cm95LCBPbkluaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlLCBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgU3ViamVjdCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBUb2FzdFNlcnZpY2UgfSBmcm9tICd0YW5nby1hcHAtdWktc2hhcmVkJztcbmltcG9ydCB7IFRpY2tldHNTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvdGlja2V0LWluZnJhLnNlcnZpY2UnO1xuXG4vKipcbiAqIFByZS1JbnN0YWxsYXRpb24gdGlja2V0IGRldGFpbCBwYWdlICh3b3Jrc3BhY2UgZW50cnkgZm9yIFRFX1BSRSB0aWNrZXRzKS5cbiAqIFNhbWUgcm9sZSBhcyBJbnN0YWxsYXRpb25Db21wb25lbnQgZm9yIFRFX0lOUyB0aWNrZXRzOiB0aGUgdGlja2V0IGhlYWRlciArXG4gKiBhY3Rpdml0eSB0cmFpbCBjb21lIGZyb20gdGhlIHRpY2tldHMgQVBJLCB0aGUgTElWRSBjYW1lcmEtcGxhY2VtZW50IHN0YXRlXG4gKiBjb21lcyBmcm9tIHRoZSBzdG9yZS1idWlsZGVyIENDVFYgcm93LCBhbmQgdGhlIHBhZ2UgZ2F0ZXMgdGhlIG5leHQgc3RlcDpcbiAqICAgYXV0b1BsYWNlbWVudCAgLT4gXCJBdXRvIHBsYWNlbWVudCBpbiBwcm9ncmVzc1wiLCBlZGl0b3IgbG9ja2VkLCBzb3VyY2UgcHJldmlld1xuICogICBmYWlsZWQgICAgICAgICAtPiBmYWlsdXJlIHJlYXNvbiArIFJldHJ5XG4gKiAgIG9wZW4gICAgICAgICAgIC0+IFwiT3BlbiBEWEYgZWRpdG9yXCIgKGFzc2lnbmVlIGdhdGVkIHNlcnZlci1zaWRlKVxuICogICBhcHByb3ZhbFBlbmRpbmctPiB3YWl0aW5nIGZvciBhcHByb3ZhbCwgZHJhd2luZyB2aWV3YWJsZVxuICogICBhcHByb3ZlZCAgICAgICAtPiBkb25lICh0aWNrZXQgY2xvc2VzIHZpYSB0aGUgYXBwcm92ZSBob29rKVxuICogTG9hZGluZyB0aGUgQ0NUViBkZXRhaWwgYWxzbyB0cmlnZ2VycyB0aGUgc2VydmVyLXNpZGUgT1MgcmVjb25jaWxlLCBzbyB0aGlzXG4gKiBwYWdlIGtlZXBzIHRoZSByb3cgZnJlc2gsIHRoZSBqb2IgdGhlIENDVFYgdGFibGUgdXNlZCB0byBkby5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbGliLXByZWluc3RhbGxhdGlvbi1pbmZvJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3ByZWluc3RhbGxhdGlvbi1pbmZvLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmw6ICcuL3ByZWluc3RhbGxhdGlvbi1pbmZvLmNvbXBvbmVudC5zY3NzJyxcbn0pXG5leHBvcnQgY2xhc3MgUHJlaW5zdGFsbGF0aW9uSW5mb0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgdGlja2V0SWQ6IHN0cmluZyB8IG51bGw7XG4gIHN0b3JlSWQ6IHN0cmluZyB8IG51bGw7XG4gIHRpY2tldEluZm86IGFueTtcbiAgY2N0dlJvdzogYW55O1xuICBjY3R2Rmxvb3I6IGFueTtcbiAgLyoqIGxpdmUgcGxhY2VtZW50IHN0YXRlIHN0cmFpZ2h0IG9mZiB0aGUgc3RhdHVzIGluZGV4ICovXG4gIHBsYWNlbWVudDogYW55ID0gbnVsbDtcbiAgZmlsZVVybHM6IGFueSA9IHt9O1xuICBsb2FkaW5nOiBib29sZWFuID0gdHJ1ZTtcbiAgY2N0dkxvYWRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcbiAgLyoqIFJlZnJlc2ggY2xpY2tlZCBhbmQgdGhlIHRpY2tldCByZWxvYWQgaXMgc3RpbGwgaW4gZmxpZ2h0IChpY29uIHR1cm5zKSAqL1xuICByZWxvYWRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcbiAgY2N0dkVycm9yOiBzdHJpbmcgPSAnJztcbiAgcmV0cnlpbmc6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3kkID0gbmV3IFN1YmplY3QoKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICBwcml2YXRlIHJvdXRlcjogUm91dGVyLFxuICAgIHByaXZhdGUgc2VydmljZTogVGlja2V0c1NlcnZpY2UsXG4gICAgcHJpdmF0ZSB0b2FzdFNlcnZpY2U6IFRvYXN0U2VydmljZSxcbiAgKSB7XG4gICAgdGhpcy50aWNrZXRJZCA9IHRoaXMucm91dGUuc25hcHNob3QucGFyYW1NYXAuZ2V0KCd0aWNrZXRJZCcpO1xuICAgIHRoaXMuc3RvcmVJZCA9IHRoaXMucm91dGUuc25hcHNob3QucGFyYW1NYXAuZ2V0KCdzdG9yZUlkJyk7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLnZpZXdUaWNrZXQoKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuZGVzdHJveSQubmV4dCh0cnVlKTtcbiAgICB0aGlzLmRlc3Ryb3kkLmNvbXBsZXRlKCk7XG4gIH1cblxuICBnZXQgZmxvb3JJZCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnRpY2tldEluZm8/LnByZUluc3RhbGxhdGlvbj8uZmxvb3JJZCB8fCAnJztcbiAgfVxuXG4gIGdldCBmbG9vck51bWJlcigpOiBhbnkge1xuICAgIHJldHVybiB0aGlzLnRpY2tldEluZm8/LnByZUluc3RhbGxhdGlvbj8uZmxvb3JOdW1iZXIgfHwgJy0nO1xuICB9XG5cbiAgLyoqIFByZXNpZ25lZCBsaW5rIHRvIHRoZSBpbXBvcnRlZCBkcmF3aW5nICh2MSksIGZyb20gdGhlIGRldGFpbCBjYWxsJ3MgdXJsIG1hcC4gKi9cbiAgZ2V0IHNvdXJjZUR4ZlVybCgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICBjb25zdCBrZXkgPSB0aGlzLmNjdHZSb3c/LnNvdXJjZUtleTtcbiAgICByZXR1cm4ga2V5ID8gdGhpcy5maWxlVXJscz8uW2tleV0gfHwgbnVsbCA6IG51bGw7XG4gIH1cblxuICBnZXQgc291cmNlRHhmTmFtZSgpOiBzdHJpbmcge1xuICAgIGNvbnN0IGtleTogc3RyaW5nID0gdGhpcy5jY3R2Um93Py5zb3VyY2VLZXkgfHwgJyc7XG4gICAgcmV0dXJuIGtleS5zcGxpdCgnLycpLnBvcCgpIHx8ICdzb3VyY2UuZHhmJztcbiAgfVxuXG4gIC8vIFRoZSBwYWdlJ3Mgc2luZ2xlIHN0YXRlIHN3aXRjaCwgZGVyaXZlZCBmcm9tIHRpY2tldCArIGxpdmUgQ0NUViByb3cuXG4gIGdldCBwbGFjZW1lbnRTdGF0ZSgpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLnRpY2tldEluZm8/LnN0YXR1cyA9PT0gJ2Nsb3NlZCcpIHJldHVybiAnYXBwcm92ZWQnO1xuICAgIGlmICghdGhpcy5mbG9vcklkKSByZXR1cm4gJ3dhaXRpbmdMYXlvdXQnO1xuICAgIGlmICghdGhpcy5jY3R2Um93KSByZXR1cm4gdGhpcy5jY3R2RXJyb3IgPyAndW5hdmFpbGFibGUnIDogJ2xvYWRpbmcnO1xuXG4gICAgLy8gVGhlIHN0YXR1cyBpbmRleCBvd25zIHRoZSBwbGFjZW1lbnQgaGFsZjogcXVldWVkIGFuZCBydW5uaW5nIGJvdGggcmVhZFxuICAgIC8vIGFzIFwiaW4gcHJvZ3Jlc3NcIiwgYW5kIGEgZmFpbHVyZSBjYXJyaWVzIGl0cyByZWFzb24uIE9uY2UgdGhlIHBsYWNlbWVudFxuICAgIC8vIGlzIGRvbmUgdGhlIHdvcmtmbG93IHJvdyB0YWtlcyBvdmVyIChvcGVuIHwgYXBwcm92YWxQZW5kaW5nIHwgYXBwcm92ZWQpLlxuICAgIGNvbnN0IGpvYlN0YXR1cyA9IHRoaXMucGxhY2VtZW50Py5zdGF0dXM7XG4gICAgaWYgKGpvYlN0YXR1cyA9PT0gJ3BlbmRpbmcnIHx8IGpvYlN0YXR1cyA9PT0gJ3Byb2Nlc3NpbmcnKSByZXR1cm4gJ3Byb2Nlc3NpbmcnO1xuICAgIGlmIChqb2JTdGF0dXMgPT09ICdmYWlsZWQnKSByZXR1cm4gJ2ZhaWxlZCc7XG4gICAgaWYgKHRoaXMuY2N0dlJvdy5zdGF0dXMgPT09ICdhdXRvUGxhY2VtZW50JykgcmV0dXJuICdwcm9jZXNzaW5nJztcbiAgICByZXR1cm4gdGhpcy5jY3R2Um93LnN0YXR1cztcbiAgfVxuXG4gIGdldCB2ZXJzaW9ucygpOiBhbnlbXSB7XG4gICAgY29uc3QgZmlsZXMgPSBBcnJheS5pc0FycmF5KHRoaXMuY2N0dlJvdz8uZmlsZXMpID8gWy4uLnRoaXMuY2N0dlJvdy5maWxlc10gOiBbXTtcbiAgICByZXR1cm4gZmlsZXMuc29ydCgoYSwgYikgPT4gKGI/LnZlcnNpb24gPz8gMCkgLSAoYT8udmVyc2lvbiA/PyAwKSk7XG4gIH1cblxuICBnZXQgYWN0aXZpdHkoKTogYW55W10ge1xuICAgIGNvbnN0IGxpc3QgPSBBcnJheS5pc0FycmF5KHRoaXMudGlja2V0SW5mbz8udGlja2V0QWN0aXZpdHkpID8gWy4uLnRoaXMudGlja2V0SW5mby50aWNrZXRBY3Rpdml0eV0gOiBbXTtcbiAgICByZXR1cm4gbGlzdC5yZXZlcnNlKCk7XG4gIH1cblxuICB2aWV3VGlja2V0KCk6IHZvaWQge1xuICAgIHRoaXMuc2VydmljZS52aWV3VGlja2V0KHsgdGlja2V0SWQ6IHRoaXMudGlja2V0SWQgfSlcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcbiAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICBuZXh0OiAocmVzOiBhbnkpID0+IHtcbiAgICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICB0aGlzLnJlbG9hZGluZyA9IGZhbHNlO1xuICAgICAgICAgIGlmIChyZXMgJiYgcmVzLmNvZGUgPT0gMjAwKSB7XG4gICAgICAgICAgICB0aGlzLnRpY2tldEluZm8gPSByZXMuZGF0YTtcbiAgICAgICAgICAgIGlmICh0aGlzLmZsb29ySWQpIHtcbiAgICAgICAgICAgICAgdGhpcy5sb2FkQ2N0dkRldGFpbCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3I6ICgpID0+IHtcbiAgICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICB0aGlzLnJlbG9hZGluZyA9IGZhbHNlO1xuICAgICAgICAgIHRoaXMudG9hc3RTZXJ2aWNlLmdldEVycm9yVG9hc3QoJ1VuYWJsZSB0byBsb2FkIHRoZSB0aWNrZXQuJyk7XG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgfVxuXG4gIGxvYWRDY3R2RGV0YWlsKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5mbG9vcklkKSByZXR1cm47XG4gICAgdGhpcy5jY3R2TG9hZGluZyA9IHRydWU7XG4gICAgdGhpcy5jY3R2RXJyb3IgPSAnJztcbiAgICB0aGlzLnNlcnZpY2UuZ2V0Q2N0dkRldGFpbCh0aGlzLmZsb29ySWQpXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXG4gICAgICAuc3Vic2NyaWJlKHtcbiAgICAgICAgbmV4dDogKHJlczogYW55KSA9PiB7XG4gICAgICAgICAgdGhpcy5jY3R2TG9hZGluZyA9IGZhbHNlO1xuICAgICAgICAgIHRoaXMuY2N0dlJvdyA9IHJlcz8uZGF0YT8ucm93IHx8IG51bGw7XG4gICAgICAgICAgdGhpcy5jY3R2Rmxvb3IgPSByZXM/LmRhdGE/LmZsb29yIHx8IG51bGw7XG4gICAgICAgICAgdGhpcy5maWxlVXJscyA9IHJlcz8uZGF0YT8udXJscyB8fCB7fTtcbiAgICAgICAgICB0aGlzLnBsYWNlbWVudCA9IHJlcz8uZGF0YT8ucGxhY2VtZW50IHx8IG51bGw7XG4gICAgICAgIH0sXG4gICAgICAgIGVycm9yOiAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5jY3R2TG9hZGluZyA9IGZhbHNlO1xuICAgICAgICAgIHRoaXMuY2N0dkVycm9yID0gJ1VuYWJsZSB0byBsb2FkIHRoZSBjYW1lcmEgcGxhY2VtZW50IHN0YXR1cy4nO1xuICAgICAgICB9LFxuICAgICAgfSk7XG4gIH1cblxuICByZWZyZXNoKCk6IHZvaWQge1xuICAgIHRoaXMucmVsb2FkaW5nID0gdHJ1ZTtcbiAgICB0aGlzLnZpZXdUaWNrZXQoKTtcbiAgfVxuXG4gIHJldHJ5UGxhY2VtZW50KCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5mbG9vcklkIHx8IHRoaXMucmV0cnlpbmcpIHJldHVybjtcbiAgICB0aGlzLnJldHJ5aW5nID0gdHJ1ZTtcbiAgICB0aGlzLnNlcnZpY2UuY2N0dlJldHJ5KHsgZmxvb3JJZDogdGhpcy5mbG9vcklkIH0pXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXG4gICAgICAuc3Vic2NyaWJlKHtcbiAgICAgICAgbmV4dDogKHJlczogYW55KSA9PiB7XG4gICAgICAgICAgdGhpcy5yZXRyeWluZyA9IGZhbHNlO1xuICAgICAgICAgIHRoaXMudG9hc3RTZXJ2aWNlLmdldFN1Y2Nlc3NUb2FzdChcbiAgICAgICAgICAgIHJlcz8uZGF0YT8uc3RhcnRlZE5vdyA/XG4gICAgICAgICAgICAgICdBdXRvIHBsYWNlbWVudCBpcyBydW5uaW5nIGFnYWluLicgOlxuICAgICAgICAgICAgICAnUXVldWVkIGZvciBhdXRvIHBsYWNlbWVudC4gSXQgd2lsbCBzdGFydCBvbiB0aGUgbmV4dCBydW4uJyxcbiAgICAgICAgICApO1xuICAgICAgICAgIHRoaXMubG9hZENjdHZEZXRhaWwoKTtcbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3I6ICgpID0+IHtcbiAgICAgICAgICB0aGlzLnJldHJ5aW5nID0gZmFsc2U7XG4gICAgICAgICAgdGhpcy50b2FzdFNlcnZpY2UuZ2V0RXJyb3JUb2FzdCgnVW5hYmxlIHRvIHJldHJ5LiBQbGVhc2UgdHJ5IGFnYWluLicpO1xuICAgICAgICB9LFxuICAgICAgfSk7XG4gIH1cblxuICBvcGVuRWRpdG9yKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5mbG9vcklkKSByZXR1cm47XG4gICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoWycvbWFuYWdlL3BsYW5vZ3JhbS9jY3R2LWVkaXRvciddLCB7XG4gICAgICBxdWVyeVBhcmFtczogeyBmbG9vcklkOiB0aGlzLmZsb29ySWQsIG1vZGU6ICdlZGl0JyB9LFxuICAgIH0pO1xuICB9XG5cbiAgLyoqIFRoZSBzb3VyY2UgZHJhd2luZywgcmVhZC1vbmx5LCB3aGlsZSBhdXRvIHBsYWNlbWVudCBpcyBzdGlsbCBydW5uaW5nLiAqL1xuICBvcGVuUHJldmlldygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuZmxvb3JJZCkgcmV0dXJuO1xuICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnL21hbmFnZS9wbGFub2dyYW0vY2N0di1wcmV2aWV3J10sIHtcbiAgICAgIHF1ZXJ5UGFyYW1zOiB7IGZsb29ySWQ6IHRoaXMuZmxvb3JJZCwgZnJvbTogJ3RpY2tldCcgfSxcbiAgICB9KTtcbiAgfVxuXG4gIGJhY2soKTogdm9pZCB7XG4gICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoWycvdGlja2V0cy91c2VycyddLCB7IHF1ZXJ5UGFyYW1zOiB7IHR5cGU6ICdpbnN0YWxsYXRpb24nIH0gfSk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJjb250YWluZXItZmx1aWQgcC01IHByZWluc3RhbGwtcGFnZVwiPlxuXG4gIDwhLS0gSGVhZGVyIC0tPlxuICA8ZGl2IGNsYXNzPVwiY2FyZCBtYi01XCI+XG4gICAgPGRpdiBjbGFzcz1cImNhcmQtYm9keSBkLWZsZXggZmxleC13cmFwIGFsaWduLWl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBnYXAtNCBweS00XCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBnYXAtNFwiPlxuICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tc20gYnRuLWxpZ2h0IGJhY2stYnRuXCIgKGNsaWNrKT1cImJhY2soKVwiIGFyaWEtbGFiZWw9XCJCYWNrIHRvIHdvcmtzcGFjZVwiPlxuICAgICAgICAgIDxpIGNsYXNzPVwiYmkgYmktYXJyb3ctbGVmdFwiPjwvaT5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxkaXY+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIgZ2FwLTNcIj5cbiAgICAgICAgICAgIDxoNCBjbGFzcz1cIm1iLTBcIj57eyB0aWNrZXRJbmZvPy50aWNrZXRJZCB8fCB0aWNrZXRJZCB9fTwvaDQ+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImJhZGdlIHN0YXRlLWJhZGdlXCIgW25nQ2xhc3NdPVwiJ3N0YXRlLScgKyBwbGFjZW1lbnRTdGF0ZVwiPlxuICAgICAgICAgICAgICB7e1xuICAgICAgICAgICAgICAgIHBsYWNlbWVudFN0YXRlID09PSAnd2FpdGluZ0xheW91dCcgPyAnV2FpdGluZyBmb3IgbGF5b3V0JyA6XG4gICAgICAgICAgICAgICAgcGxhY2VtZW50U3RhdGUgPT09ICdwcm9jZXNzaW5nJyA/ICdBdXRvIHBsYWNlbWVudCBpbiBwcm9ncmVzcycgOlxuICAgICAgICAgICAgICAgIHBsYWNlbWVudFN0YXRlID09PSAnZmFpbGVkJyA/ICdQbGFjZW1lbnQgZmFpbGVkJyA6XG4gICAgICAgICAgICAgICAgcGxhY2VtZW50U3RhdGUgPT09ICdvcGVuJyA/ICdSZWFkeSBmb3IgcGxhY2VtZW50IHJldmlldycgOlxuICAgICAgICAgICAgICAgIHBsYWNlbWVudFN0YXRlID09PSAnYXBwcm92YWxQZW5kaW5nJyA/ICdXYWl0aW5nIGZvciBhcHByb3ZhbCcgOlxuICAgICAgICAgICAgICAgIHBsYWNlbWVudFN0YXRlID09PSAnYXBwcm92ZWQnID8gJ0FwcHJvdmVkJyA6XG4gICAgICAgICAgICAgICAgcGxhY2VtZW50U3RhdGUgPT09ICd1bmF2YWlsYWJsZScgPyAnU3RhdHVzIHVuYXZhaWxhYmxlJyA6ICdMb2FkaW5nJ1xuICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LW11dGVkIGZzLTcgbXQtMVwiPlxuICAgICAgICAgICAgUHJlLUluc3RhbGxhdGlvbiwgY2FtZXJhIHBsYWNlbWVudFxuICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJ0aWNrZXRJbmZvPy5iYXNpY0RldGFpbHM/LnN0b3JlTmFtZVwiPiwge3sgdGlja2V0SW5mbz8uYmFzaWNEZXRhaWxzPy5zdG9yZU5hbWUgfX08L3NwYW4+XG4gICAgICAgICAgICA8c3Bhbj4sIEZsb29yIHt7IGZsb29yTnVtYmVyIH19PC9zcGFuPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIgZ2FwLTNcIj5cbiAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1saWdodCByb3ctYnRuXCIgKGNsaWNrKT1cInJlZnJlc2goKVwiPlxuICAgICAgICAgIDxpIGNsYXNzPVwiYmkgYmktYXJyb3ctY2xvY2t3aXNlIG1lLTFcIiBbY2xhc3Muc3Bpbm5pbmddPVwicmVsb2FkaW5nIHx8IGNjdHZMb2FkaW5nXCI+PC9pPlJlZnJlc2hcbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG5cbiAgPGRpdiAqbmdJZj1cImxvYWRpbmdcIiBjbGFzcz1cInRleHQtY2VudGVyIHB5LTEwIHRleHQtbXV0ZWRcIj5Mb2FkaW5nIHRpY2tldC4uLjwvZGl2PlxuXG4gIDxkaXYgKm5nSWY9XCIhbG9hZGluZyAmJiB0aWNrZXRJbmZvXCIgY2xhc3M9XCJyb3cgZy01XCI+XG5cbiAgICA8IS0tIFBsYWNlbWVudCBzdGF0ZSAvIGFjdGlvbiBwYW5lbCAtLT5cbiAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIGNvbC1sZy03XCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiY2FyZCBoLTEwMFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2FyZC1ib2R5XCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNhcmQtaGVhZCBtYi00XCI+XG4gICAgICAgICAgICA8aDUgY2xhc3M9XCJtYi0wXCI+Q2FtZXJhIHBsYWNlbWVudDwvaDU+XG4gICAgICAgICAgICA8IS0tIFRoZSBpbXBvcnRlZCBkcmF3aW5nIGl0c2VsZiwgZm9yIHRoZSBpbnRlcm5hbCB0ZWFtIHRvIGluc3BlY3QgaW5cbiAgICAgICAgICAgICAgICAgQ0FEIHdoZW4gdGhlIGVuZ2luZSBjYW5ub3QgaGFuZGxlIGl0IG9yIGJlZm9yZSBlZGl0aW5nLiAtLT5cbiAgICAgICAgICAgIDxhICpuZ0lmPVwic291cmNlRHhmVXJsXCIgW2hyZWZdPVwic291cmNlRHhmVXJsXCIgdGFyZ2V0PVwiX2JsYW5rXCIgcmVsPVwibm9vcGVuZXJcIlxuICAgICAgICAgICAgICBjbGFzcz1cImJ0biBidG4tc20gYnRuLWxpZ2h0IHJvdy1idG5cIiBbbmdiVG9vbHRpcF09XCJzb3VyY2VEeGZOYW1lXCI+XG4gICAgICAgICAgICAgIDxzdmcgd2lkdGg9XCIxNlwiIGhlaWdodD1cIjE2XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiIGZpbGw9XCJub25lXCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPlxuICAgICAgICAgICAgICAgIDxwYXRoIGQ9XCJNMTIgM3YxMm0wIDAgNC00bS00IDQtNC00TTQgMTd2MmEyIDIgMCAwIDAgMiAyaDEyYTIgMiAwIDAgMCAyLTJ2LTJcIlxuICAgICAgICAgICAgICAgICAgc3Ryb2tlPVwiY3VycmVudENvbG9yXCIgc3Ryb2tlLXdpZHRoPVwiMS44XCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIgLz5cbiAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibXMtMVwiPkRvd25sb2FkIHNvdXJjZSBEWEY8L3NwYW4+XG4gICAgICAgICAgICA8L2E+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8ZGl2IFtuZ1N3aXRjaF09XCJwbGFjZW1lbnRTdGF0ZVwiIGNsYXNzPVwic3RhdGUtcGFuZWxcIj5cblxuICAgICAgICAgICAgPGRpdiAqbmdTd2l0Y2hDYXNlPVwiJ3dhaXRpbmdMYXlvdXQnXCIgY2xhc3M9XCJzdGF0ZS1ib3hcIj5cbiAgICAgICAgICAgICAgPHAgY2xhc3M9XCJtYi0xIGZ3LXNlbWlib2xkXCI+V2FpdGluZyBmb3IgdGhlIENBRCBsYXlvdXQuPC9wPlxuICAgICAgICAgICAgICA8cCBjbGFzcz1cInRleHQtbXV0ZWQgbWItMFwiPlRoZSBzdG9yZSdzIGZsb29yIGRyYXdpbmcgaGFzIG5vdCBiZWVuIGltcG9ydGVkIHlldC4gQXV0byBwbGFjZW1lbnQgc3RhcnRzIHJpZ2h0IGFmdGVyIHRoZSBDQUQgaW1wb3J0LjwvcD5cbiAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICA8ZGl2ICpuZ1N3aXRjaENhc2U9XCIncHJvY2Vzc2luZydcIiBjbGFzcz1cInN0YXRlLWJveFwiPlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBnYXAtMyBtYi0xXCI+XG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzcGlubmVyLWJvcmRlciBzcGlubmVyLWJvcmRlci1zbSB0ZXh0LXByaW1hcnlcIiByb2xlPVwic3RhdHVzXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9zcGFuPlxuICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwibWItMCBmdy1zZW1pYm9sZFwiPkF1dG8gY2FtZXJhIHBsYWNlbWVudCBpcyBydW5uaW5nLjwvcD5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwidGV4dC1tdXRlZCBtYi0zXCI+VGhlIERYRiBlZGl0b3IgdW5sb2NrcyB3aGVuIHBsYWNlbWVudCBjb21wbGV0ZXMuIFVzZSBSZWZyZXNoIHRvIGNoZWNrIGFnYWluLiBNZWFud2hpbGUgeW91IGNhbiBsb29rIGF0IHRoZSBzb3VyY2UgZHJhd2luZy48L3A+XG4gICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1zbSBidG4tbGlnaHQgcm93LWJ0blwiIChjbGljayk9XCJvcGVuUHJldmlldygpXCI+XG4gICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJiaSBiaS1leWUgbWUtMVwiPjwvaT5WaWV3IHNvdXJjZSBkcmF3aW5nXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIidmYWlsZWQnXCIgY2xhc3M9XCJzdGF0ZS1ib3ggc3RhdGUtYm94LWRhbmdlclwiPlxuICAgICAgICAgICAgICA8cCBjbGFzcz1cIm1iLTEgZnctc2VtaWJvbGRcIj5BdXRvIHBsYWNlbWVudCBmYWlsZWQuPC9wPlxuICAgICAgICAgICAgICA8cCBjbGFzcz1cInRleHQtbXV0ZWQgbWItM1wiPnt7IHBsYWNlbWVudD8uZXJyb3JNc2cgfHwgY2N0dlJvdz8uZXJyb3JNc2cgfHwgJ1RoZSBwbGFjZW1lbnQgZW5naW5lIHJlcG9ydGVkIGEgZmFpbHVyZS4nIH19PC9wPlxuICAgICAgICAgICAgICA8IS0tIFJldHJ5IGhpZGRlbiB1bnRpbCB0aGUgYXV0b1BsYWNlIExhbWJkYSBleGlzdHMgKExBTUJEQVVSTC5hdXRvUGxhY2UgaXMgZW1wdHkpLlxuICAgICAgICAgICAgICAgICAgIFJlLWVuYWJsZSBieSByZW1vdmluZyB0aGlzIGNvbW1lbnQ7IHJldHJ5UGxhY2VtZW50KCkgaXMgc3RpbGwgd2lyZWQgaW4gdGhlIGNvbXBvbmVudC5cbiAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1wcmltYXJ5IHJvdy1idG5cIiBbZGlzYWJsZWRdPVwicmV0cnlpbmdcIiAoY2xpY2spPVwicmV0cnlQbGFjZW1lbnQoKVwiPlxuICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwicmV0cnlpbmdcIiBjbGFzcz1cInNwaW5uZXItYm9yZGVyIHNwaW5uZXItYm9yZGVyLXNtIG1lLTJcIiByb2xlPVwic3RhdHVzXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9zcGFuPlxuICAgICAgICAgICAgICAgIHt7IHJldHJ5aW5nID8gJ1JldHJ5aW5nLi4uJyA6ICdSZXRyeSBhdXRvIHBsYWNlbWVudCcgfX1cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgIC0tPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIidvcGVuJ1wiIGNsYXNzPVwic3RhdGUtYm94XCI+XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwibWItMSBmdy1zZW1pYm9sZFwiPlRoZSBkcmF3aW5nIGlzIHJlYWR5IGZvciBjYW1lcmEgcmV2aWV3LjwvcD5cbiAgICAgICAgICAgICAgPHAgY2xhc3M9XCJ0ZXh0LW11dGVkIG1iLTNcIj5cbiAgICAgICAgICAgICAgICBBZGp1c3QgdGhlIGF1dG8tcGxhY2VkIGNhbWVyYXMgaW4gdGhlIERYRiBlZGl0b3IsIHRoZW4gc3VibWl0IGZvciBhcHByb3ZhbC5cbiAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cImNjdHZSb3c/LmlzUmV3b3JrXCIgY2xhc3M9XCJ0ZXh0LXdhcm5pbmcgZnctc2VtaWJvbGRcIj5UaGlzIGZsb29yIHdhcyBzZW50IGJhY2sgZm9yIHJld29yay48L3NwYW4+XG4gICAgICAgICAgICAgIDwvcD5cbiAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1wcmltYXJ5IHJvdy1idG5cIiAoY2xpY2spPVwib3BlbkVkaXRvcigpXCI+XG4gICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJiaSBiaS1wZW5jaWwtc3F1YXJlIG1lLTFcIj48L2k+T3BlbiBEWEYgZWRpdG9yXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIidhcHByb3ZhbFBlbmRpbmcnXCIgY2xhc3M9XCJzdGF0ZS1ib3hcIj5cbiAgICAgICAgICAgICAgPHAgY2xhc3M9XCJtYi0xIGZ3LXNlbWlib2xkXCI+U3VibWl0dGVkLCB3YWl0aW5nIGZvciBhcHByb3ZhbC48L3A+XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwidGV4dC1tdXRlZCBtYi0zXCI+VGhlIGFwcHJvdmFsIHRlYW0gcmV2aWV3cyBpdCBmcm9tIHRoZSBvbmJvYXJkIHRhYmxlLiBZb3UgY2FuIHN0aWxsIHZpZXcgdGhlIGRyYXdpbmcuPC9wPlxuICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tc20gYnRuLWxpZ2h0IHJvdy1idG5cIiAoY2xpY2spPVwib3BlbkVkaXRvcigpXCI+XG4gICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJiaSBiaS1leWUgbWUtMVwiPjwvaT5WaWV3IGRyYXdpbmdcbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPGRpdiAqbmdTd2l0Y2hDYXNlPVwiJ2FwcHJvdmVkJ1wiIGNsYXNzPVwic3RhdGUtYm94IHN0YXRlLWJveC1zdWNjZXNzXCI+XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwibWItMSBmdy1zZW1pYm9sZFwiPkNhbWVyYSBwbGFjZW1lbnQgYXBwcm92ZWQuPC9wPlxuICAgICAgICAgICAgICA8cCBjbGFzcz1cInRleHQtbXV0ZWQgbWItMFwiPlRoaXMgdGlja2V0IGlzIGNsb3NlZC4gVGhlIGluc3RhbGxhdGlvbiB0aWNrZXQgdGFrZXMgb3ZlciBvbmNlIGV2ZXJ5IGZsb29yIG9mIHRoZSBzdG9yZSBpcyBhcHByb3ZlZC48L3A+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPGRpdiAqbmdTd2l0Y2hDYXNlPVwiJ3VuYXZhaWxhYmxlJ1wiIGNsYXNzPVwic3RhdGUtYm94IHN0YXRlLWJveC1kYW5nZXJcIj5cbiAgICAgICAgICAgICAgPHAgY2xhc3M9XCJtYi0xIGZ3LXNlbWlib2xkXCI+UGxhY2VtZW50IHN0YXR1cyB1bmF2YWlsYWJsZS48L3A+XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwidGV4dC1tdXRlZCBtYi0zXCI+e3sgY2N0dkVycm9yIH19PC9wPlxuICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tc20gYnRuLWxpZ2h0IHJvdy1idG5cIiAoY2xpY2spPVwibG9hZENjdHZEZXRhaWwoKVwiPlRyeSBhZ2FpbjwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIDxkaXYgKm5nU3dpdGNoRGVmYXVsdCBjbGFzcz1cInN0YXRlLWJveFwiPlxuICAgICAgICAgICAgICA8cCBjbGFzcz1cInRleHQtbXV0ZWQgbWItMFwiPkxvYWRpbmcgcGxhY2VtZW50IHN0YXR1cy4uLjwvcD5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPCEtLSBWZXJzaW9uIHRpbWVsaW5lIC0tPlxuICAgICAgICAgIDxkaXYgKm5nSWY9XCJ2ZXJzaW9ucy5sZW5ndGhcIiBjbGFzcz1cIm10LTZcIj5cbiAgICAgICAgICAgIDxoNiBjbGFzcz1cInRleHQtbXV0ZWQgbWItM1wiPkRyYXdpbmcgdmVyc2lvbnM8L2g2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInZlcnNpb24tbGlzdFwiPlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidmVyc2lvbi1yb3cgZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlblwiICpuZ0Zvcj1cImxldCBmaWxlIG9mIHZlcnNpb25zXCI+XG4gICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZnctc2VtaWJvbGRcIj52e3sgZmlsZS52ZXJzaW9uIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkIG1zLTIgZnMtN1wiPnt7IGZpbGUua2luZCA9PT0gJ2F1dG8nID8gJ0F1dG8gcGxhY2VtZW50JyA6IGZpbGUua2luZCA9PT0gJ2FwcHJvdmVyJyA/ICdBcHByb3ZlciBlZGl0JyA6ICdJbnRlcm5hbCBlZGl0JyB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1tdXRlZCBtcy0yIGZzLTdcIiAqbmdJZj1cImZpbGUuY2FtZXJhQ291bnQgIT0gbnVsbFwiPnt7IGZpbGUuY2FtZXJhQ291bnQgfX0gY2FtZXJhczwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBnYXAtM1wiPlxuICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkIGZzLTdcIj57eyBmaWxlLnVwbG9hZGVkQXQgfCBkYXRlOiAnZGQgTU1NLCB5IEhIOm1tJyB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgIDxhICpuZ0lmPVwiZmlsZVVybHNbZmlsZS5rZXldXCIgW2hyZWZdPVwiZmlsZVVybHNbZmlsZS5rZXldXCIgdGFyZ2V0PVwiX2JsYW5rXCIgcmVsPVwibm9vcGVuZXJcIiBjbGFzcz1cImJ0biBidG4tc20gYnRuLWxpZ2h0IHJvdy1idG5cIj5cbiAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJiaSBiaS1kb3dubG9hZFwiPjwvaT5cbiAgICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cblxuICAgIDwhLS0gVGlja2V0IGluZm8gKyBhY3Rpdml0eSAtLT5cbiAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIGNvbC1sZy01XCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiY2FyZCBtYi01XCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjYXJkLWJvZHlcIj5cbiAgICAgICAgICA8aDUgY2xhc3M9XCJtYi00XCI+VGlja2V0IGRldGFpbHM8L2g1PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJkZXRhaWwtZ3JpZFwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRldGFpbC1yb3dcIj48c3BhbiBjbGFzcz1cInRleHQtbXV0ZWRcIj5TdG9yZTwvc3Bhbj48c3Bhbj57eyB0aWNrZXRJbmZvPy5iYXNpY0RldGFpbHM/LnN0b3JlTmFtZSB8fCAnLScgfX0gKHt7IHRpY2tldEluZm8/LmJhc2ljRGV0YWlscz8uc3RvcmVJZCB8fCBzdG9yZUlkIH19KTwvc3Bhbj48L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkZXRhaWwtcm93XCI+PHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkXCI+QnJhbmQ8L3NwYW4+PHNwYW4+e3sgdGlja2V0SW5mbz8uYmFzaWNEZXRhaWxzPy5jbGllbnROYW1lIHx8ICctJyB9fTwvc3Bhbj48L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkZXRhaWwtcm93XCI+PHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkXCI+Rmxvb3I8L3NwYW4+PHNwYW4+Rmxvb3Ige3sgZmxvb3JOdW1iZXIgfX08L3NwYW4+PC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGV0YWlsLXJvd1wiPjxzcGFuIGNsYXNzPVwidGV4dC1tdXRlZFwiPlRpY2tldCBzdGF0dXM8L3NwYW4+PHNwYW4gY2xhc3M9XCJ0ZXh0LWNhcGl0YWxpemVcIj57eyB0aWNrZXRJbmZvPy5zdGF0dXMgfHwgJy0nIH19PC9zcGFuPjwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRldGFpbC1yb3dcIj48c3BhbiBjbGFzcz1cInRleHQtbXV0ZWRcIj5DcmVhdGVkPC9zcGFuPjxzcGFuPnt7IHRpY2tldEluZm8/LmNyZWF0ZWRBdCB8IGRhdGU6ICdkZCBNTU0sIHkgSEg6bW0nIH19PC9zcGFuPjwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRldGFpbC1yb3dcIiAqbmdJZj1cImNjdHZSb3c/LmFzc2lnbmVlTmFtZVwiPjxzcGFuIGNsYXNzPVwidGV4dC1tdXRlZFwiPkFzc2lnbmVlPC9zcGFuPjxzcGFuPnt7IGNjdHZSb3c/LmFzc2lnbmVlTmFtZSB9fTwvc3Bhbj48L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkZXRhaWwtcm93XCIgKm5nSWY9XCJjY3R2Um93Py5yZXdvcmtDb3VudFwiPjxzcGFuIGNsYXNzPVwidGV4dC1tdXRlZFwiPlJld29yayBjb3VudDwvc3Bhbj48c3Bhbj57eyBjY3R2Um93Py5yZXdvcmtDb3VudCB9fTwvc3Bhbj48L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPGRpdiBjbGFzcz1cImNhcmRcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNhcmQtYm9keVwiPlxuICAgICAgICAgIDxoNSBjbGFzcz1cIm1iLTRcIj5BY3Rpdml0eTwvaDU+XG4gICAgICAgICAgPGRpdiAqbmdJZj1cIiFhY3Rpdml0eS5sZW5ndGhcIiBjbGFzcz1cInRleHQtbXV0ZWQgZnMtN1wiPk5vIGFjdGl2aXR5IHlldC48L2Rpdj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWN0aXZpdHktbGlzdFwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImFjdGl2aXR5LXJvd1wiICpuZ0Zvcj1cImxldCBlbnRyeSBvZiBhY3Rpdml0eVwiPlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWN0aXZpdHktZG90XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9kaXY+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4LWdyb3ctMVwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gZ2FwLTNcIj5cbiAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZnctc2VtaWJvbGQgZnMtN1wiPnt7IGVudHJ5LmRlc2NyaXB0aW9uIHx8IGVudHJ5LmFjdGlvblR5cGUgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtbXV0ZWQgZnMtOCB0ZXh0LW5vd3JhcFwiPnt7IGVudHJ5LnRpbWVTdGFtcCB8IGRhdGU6ICdkZCBNTU0sIEhIOm1tJyB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGV4dC1tdXRlZCBmcy04XCIgKm5nSWY9XCJlbnRyeS5jb21tZW50XCI+e3sgZW50cnkuY29tbWVudCB9fTwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LW11dGVkIGZzLThcIiAqbmdJZj1cImVudHJ5LklkZW50aWZpZWRCeSAmJiBlbnRyeS5JZGVudGlmaWVkQnkgIT09ICdUYW5nbydcIj5ieSB7eyBlbnRyeS5JZGVudGlmaWVkQnkgfX08L2Rpdj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==
|
|
191
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJlaW5zdGFsbGF0aW9uLWluZm8uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFuZ28tdGlja2V0LXVzZXIvc3JjL2xpYi9jb21wb25lbnRzL3ByZWluc3RhbGxhdGlvbi1pbmZvL3ByZWluc3RhbGxhdGlvbi1pbmZvLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RhbmdvLXRpY2tldC11c2VyL3NyYy9saWIvY29tcG9uZW50cy9wcmVpbnN0YWxsYXRpb24taW5mby9wcmVpbnN0YWxsYXRpb24taW5mby5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFxQixNQUFNLGVBQWUsQ0FBQztBQUU3RCxPQUFPLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQzs7Ozs7OztBQUkxQzs7Ozs7Ozs7Ozs7O0dBWUc7QUFNSCxNQUFNLE9BQU8sNEJBQTRCO0lBbUI3QjtJQUNBO0lBQ0E7SUFDQTtJQXJCVixRQUFRLENBQWdCO0lBQ3hCLE9BQU8sQ0FBZ0I7SUFDdkIsVUFBVSxDQUFNO0lBQ2hCLE9BQU8sQ0FBTTtJQUNiLFNBQVMsQ0FBTTtJQUNmLHlEQUF5RDtJQUN6RCxTQUFTLEdBQVEsSUFBSSxDQUFDO0lBQ3RCLFFBQVEsR0FBUSxFQUFFLENBQUM7SUFDbkIsT0FBTyxHQUFZLElBQUksQ0FBQztJQUN4QixXQUFXLEdBQVksS0FBSyxDQUFDO0lBQzdCLDRFQUE0RTtJQUM1RSxTQUFTLEdBQVksS0FBSyxDQUFDO0lBQzNCLFNBQVMsR0FBVyxFQUFFLENBQUM7SUFDdkIsUUFBUSxHQUFZLEtBQUssQ0FBQztJQUVULFFBQVEsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO0lBRTFDLFlBQ1UsS0FBcUIsRUFDckIsTUFBYyxFQUNkLE9BQXVCLEVBQ3ZCLFlBQTBCO1FBSDFCLFVBQUss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VyxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRTtTQUN2RCxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsSUFBSTtRQUNGLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxFQUFFLFdBQVcsRUFBRSxFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDdEYsQ0FBQzt3R0F6S1UsNEJBQTRCOzRGQUE1Qiw0QkFBNEIsZ0VDeEJ6QyxxeVZBNExBOzs0RkRwS2EsNEJBQTRCO2tCQUx4QyxTQUFTOytCQUNFLDBCQUEwQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgT25EZXN0cm95LCBPbkluaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlLCBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgU3ViamVjdCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBUb2FzdFNlcnZpY2UgfSBmcm9tICd0YW5nby1hcHAtdWktc2hhcmVkJztcbmltcG9ydCB7IFRpY2tldHNTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvdGlja2V0LWluZnJhLnNlcnZpY2UnO1xuXG4vKipcbiAqIFByZS1JbnN0YWxsYXRpb24gdGlja2V0IGRldGFpbCBwYWdlICh3b3Jrc3BhY2UgZW50cnkgZm9yIFRFX1BSRSB0aWNrZXRzKS5cbiAqIFNhbWUgcm9sZSBhcyBJbnN0YWxsYXRpb25Db21wb25lbnQgZm9yIFRFX0lOUyB0aWNrZXRzOiB0aGUgdGlja2V0IGhlYWRlciArXG4gKiBhY3Rpdml0eSB0cmFpbCBjb21lIGZyb20gdGhlIHRpY2tldHMgQVBJLCB0aGUgTElWRSBjYW1lcmEtcGxhY2VtZW50IHN0YXRlXG4gKiBjb21lcyBmcm9tIHRoZSBzdG9yZS1idWlsZGVyIENDVFYgcm93LCBhbmQgdGhlIHBhZ2UgZ2F0ZXMgdGhlIG5leHQgc3RlcDpcbiAqICAgYXV0b1BsYWNlbWVudCAgLT4gXCJBdXRvIHBsYWNlbWVudCBpbiBwcm9ncmVzc1wiLCBlZGl0b3IgbG9ja2VkLCBzb3VyY2UgcHJldmlld1xuICogICBmYWlsZWQgICAgICAgICAtPiBmYWlsdXJlIHJlYXNvbiArIFJldHJ5XG4gKiAgIG9wZW4gICAgICAgICAgIC0+IFwiT3BlbiBEWEYgZWRpdG9yXCIgKGFzc2lnbmVlIGdhdGVkIHNlcnZlci1zaWRlKVxuICogICBhcHByb3ZhbFBlbmRpbmctPiB3YWl0aW5nIGZvciBhcHByb3ZhbCwgZHJhd2luZyB2aWV3YWJsZVxuICogICBhcHByb3ZlZCAgICAgICAtPiBkb25lICh0aWNrZXQgY2xvc2VzIHZpYSB0aGUgYXBwcm92ZSBob29rKVxuICogTG9hZGluZyB0aGUgQ0NUViBkZXRhaWwgYWxzbyB0cmlnZ2VycyB0aGUgc2VydmVyLXNpZGUgT1MgcmVjb25jaWxlLCBzbyB0aGlzXG4gKiBwYWdlIGtlZXBzIHRoZSByb3cgZnJlc2gsIHRoZSBqb2IgdGhlIENDVFYgdGFibGUgdXNlZCB0byBkby5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbGliLXByZWluc3RhbGxhdGlvbi1pbmZvJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3ByZWluc3RhbGxhdGlvbi1pbmZvLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmw6ICcuL3ByZWluc3RhbGxhdGlvbi1pbmZvLmNvbXBvbmVudC5zY3NzJyxcbn0pXG5leHBvcnQgY2xhc3MgUHJlaW5zdGFsbGF0aW9uSW5mb0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgdGlja2V0SWQ6IHN0cmluZyB8IG51bGw7XG4gIHN0b3JlSWQ6IHN0cmluZyB8IG51bGw7XG4gIHRpY2tldEluZm86IGFueTtcbiAgY2N0dlJvdzogYW55O1xuICBjY3R2Rmxvb3I6IGFueTtcbiAgLyoqIGxpdmUgcGxhY2VtZW50IHN0YXRlIHN0cmFpZ2h0IG9mZiB0aGUgc3RhdHVzIGluZGV4ICovXG4gIHBsYWNlbWVudDogYW55ID0gbnVsbDtcbiAgZmlsZVVybHM6IGFueSA9IHt9O1xuICBsb2FkaW5nOiBib29sZWFuID0gdHJ1ZTtcbiAgY2N0dkxvYWRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcbiAgLyoqIFJlZnJlc2ggY2xpY2tlZCBhbmQgdGhlIHRpY2tldCByZWxvYWQgaXMgc3RpbGwgaW4gZmxpZ2h0IChpY29uIHR1cm5zKSAqL1xuICByZWxvYWRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcbiAgY2N0dkVycm9yOiBzdHJpbmcgPSAnJztcbiAgcmV0cnlpbmc6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3kkID0gbmV3IFN1YmplY3QoKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICBwcml2YXRlIHJvdXRlcjogUm91dGVyLFxuICAgIHByaXZhdGUgc2VydmljZTogVGlja2V0c1NlcnZpY2UsXG4gICAgcHJpdmF0ZSB0b2FzdFNlcnZpY2U6IFRvYXN0U2VydmljZSxcbiAgKSB7XG4gICAgdGhpcy50aWNrZXRJZCA9IHRoaXMucm91dGUuc25hcHNob3QucGFyYW1NYXAuZ2V0KCd0aWNrZXRJZCcpO1xuICAgIHRoaXMuc3RvcmVJZCA9IHRoaXMucm91dGUuc25hcHNob3QucGFyYW1NYXAuZ2V0KCdzdG9yZUlkJyk7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLnZpZXdUaWNrZXQoKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuZGVzdHJveSQubmV4dCh0cnVlKTtcbiAgICB0aGlzLmRlc3Ryb3kkLmNvbXBsZXRlKCk7XG4gIH1cblxuICBnZXQgZmxvb3JJZCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnRpY2tldEluZm8/LnByZUluc3RhbGxhdGlvbj8uZmxvb3JJZCB8fCAnJztcbiAgfVxuXG4gIGdldCBmbG9vck51bWJlcigpOiBhbnkge1xuICAgIHJldHVybiB0aGlzLnRpY2tldEluZm8/LnByZUluc3RhbGxhdGlvbj8uZmxvb3JOdW1iZXIgfHwgJy0nO1xuICB9XG5cbiAgLyoqIFByZXNpZ25lZCBsaW5rIHRvIHRoZSBpbXBvcnRlZCBkcmF3aW5nICh2MSksIGZyb20gdGhlIGRldGFpbCBjYWxsJ3MgdXJsIG1hcC4gKi9cbiAgZ2V0IHNvdXJjZUR4ZlVybCgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICBjb25zdCBrZXkgPSB0aGlzLmNjdHZSb3c/LnNvdXJjZUtleTtcbiAgICByZXR1cm4ga2V5ID8gdGhpcy5maWxlVXJscz8uW2tleV0gfHwgbnVsbCA6IG51bGw7XG4gIH1cblxuICBnZXQgc291cmNlRHhmTmFtZSgpOiBzdHJpbmcge1xuICAgIGNvbnN0IGtleTogc3RyaW5nID0gdGhpcy5jY3R2Um93Py5zb3VyY2VLZXkgfHwgJyc7XG4gICAgcmV0dXJuIGtleS5zcGxpdCgnLycpLnBvcCgpIHx8ICdzb3VyY2UuZHhmJztcbiAgfVxuXG4gIC8vIFRoZSBwYWdlJ3Mgc2luZ2xlIHN0YXRlIHN3aXRjaCwgZGVyaXZlZCBmcm9tIHRpY2tldCArIGxpdmUgQ0NUViByb3cuXG4gIGdldCBwbGFjZW1lbnRTdGF0ZSgpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLnRpY2tldEluZm8/LnN0YXR1cyA9PT0gJ2Nsb3NlZCcpIHJldHVybiAnYXBwcm92ZWQnO1xuICAgIGlmICghdGhpcy5mbG9vcklkKSByZXR1cm4gJ3dhaXRpbmdMYXlvdXQnO1xuICAgIGlmICghdGhpcy5jY3R2Um93KSByZXR1cm4gdGhpcy5jY3R2RXJyb3IgPyAndW5hdmFpbGFibGUnIDogJ2xvYWRpbmcnO1xuXG4gICAgLy8gVGhlIHN0YXR1cyBpbmRleCBvd25zIHRoZSBwbGFjZW1lbnQgaGFsZjogcXVldWVkIGFuZCBydW5uaW5nIGJvdGggcmVhZFxuICAgIC8vIGFzIFwiaW4gcHJvZ3Jlc3NcIiwgYW5kIGEgZmFpbHVyZSBjYXJyaWVzIGl0cyByZWFzb24uIE9uY2UgdGhlIHBsYWNlbWVudFxuICAgIC8vIGlzIGRvbmUgdGhlIHdvcmtmbG93IHJvdyB0YWtlcyBvdmVyIChvcGVuIHwgYXBwcm92YWxQZW5kaW5nIHwgYXBwcm92ZWQpLlxuICAgIGNvbnN0IGpvYlN0YXR1cyA9IHRoaXMucGxhY2VtZW50Py5zdGF0dXM7XG4gICAgaWYgKGpvYlN0YXR1cyA9PT0gJ3BlbmRpbmcnIHx8IGpvYlN0YXR1cyA9PT0gJ3Byb2Nlc3NpbmcnKSByZXR1cm4gJ3Byb2Nlc3NpbmcnO1xuICAgIGlmIChqb2JTdGF0dXMgPT09ICdmYWlsZWQnKSByZXR1cm4gJ2ZhaWxlZCc7XG4gICAgaWYgKHRoaXMuY2N0dlJvdy5zdGF0dXMgPT09ICdhdXRvUGxhY2VtZW50JykgcmV0dXJuICdwcm9jZXNzaW5nJztcbiAgICByZXR1cm4gdGhpcy5jY3R2Um93LnN0YXR1cztcbiAgfVxuXG4gIGdldCB2ZXJzaW9ucygpOiBhbnlbXSB7XG4gICAgY29uc3QgZmlsZXMgPSBBcnJheS5pc0FycmF5KHRoaXMuY2N0dlJvdz8uZmlsZXMpID8gWy4uLnRoaXMuY2N0dlJvdy5maWxlc10gOiBbXTtcbiAgICByZXR1cm4gZmlsZXMuc29ydCgoYSwgYikgPT4gKGI/LnZlcnNpb24gPz8gMCkgLSAoYT8udmVyc2lvbiA/PyAwKSk7XG4gIH1cblxuICBnZXQgYWN0aXZpdHkoKTogYW55W10ge1xuICAgIGNvbnN0IGxpc3QgPSBBcnJheS5pc0FycmF5KHRoaXMudGlja2V0SW5mbz8udGlja2V0QWN0aXZpdHkpID8gWy4uLnRoaXMudGlja2V0SW5mby50aWNrZXRBY3Rpdml0eV0gOiBbXTtcbiAgICByZXR1cm4gbGlzdC5yZXZlcnNlKCk7XG4gIH1cblxuICB2aWV3VGlja2V0KCk6IHZvaWQge1xuICAgIHRoaXMuc2VydmljZS52aWV3VGlja2V0KHsgdGlja2V0SWQ6IHRoaXMudGlja2V0SWQgfSlcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcbiAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICBuZXh0OiAocmVzOiBhbnkpID0+IHtcbiAgICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICB0aGlzLnJlbG9hZGluZyA9IGZhbHNlO1xuICAgICAgICAgIGlmIChyZXMgJiYgcmVzLmNvZGUgPT0gMjAwKSB7XG4gICAgICAgICAgICB0aGlzLnRpY2tldEluZm8gPSByZXMuZGF0YTtcbiAgICAgICAgICAgIGlmICh0aGlzLmZsb29ySWQpIHtcbiAgICAgICAgICAgICAgdGhpcy5sb2FkQ2N0dkRldGFpbCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3I6ICgpID0+IHtcbiAgICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICB0aGlzLnJlbG9hZGluZyA9IGZhbHNlO1xuICAgICAgICAgIHRoaXMudG9hc3RTZXJ2aWNlLmdldEVycm9yVG9hc3QoJ1VuYWJsZSB0byBsb2FkIHRoZSB0aWNrZXQuJyk7XG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgfVxuXG4gIGxvYWRDY3R2RGV0YWlsKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5mbG9vcklkKSByZXR1cm47XG4gICAgdGhpcy5jY3R2TG9hZGluZyA9IHRydWU7XG4gICAgdGhpcy5jY3R2RXJyb3IgPSAnJztcbiAgICB0aGlzLnNlcnZpY2UuZ2V0Q2N0dkRldGFpbCh0aGlzLmZsb29ySWQpXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXG4gICAgICAuc3Vic2NyaWJlKHtcbiAgICAgICAgbmV4dDogKHJlczogYW55KSA9PiB7XG4gICAgICAgICAgdGhpcy5jY3R2TG9hZGluZyA9IGZhbHNlO1xuICAgICAgICAgIHRoaXMuY2N0dlJvdyA9IHJlcz8uZGF0YT8ucm93IHx8IG51bGw7XG4gICAgICAgICAgdGhpcy5jY3R2Rmxvb3IgPSByZXM/LmRhdGE/LmZsb29yIHx8IG51bGw7XG4gICAgICAgICAgdGhpcy5maWxlVXJscyA9IHJlcz8uZGF0YT8udXJscyB8fCB7fTtcbiAgICAgICAgICB0aGlzLnBsYWNlbWVudCA9IHJlcz8uZGF0YT8ucGxhY2VtZW50IHx8IG51bGw7XG4gICAgICAgIH0sXG4gICAgICAgIGVycm9yOiAoKSA9PiB7XG4gICAgICAgICAgdGhpcy5jY3R2TG9hZGluZyA9IGZhbHNlO1xuICAgICAgICAgIHRoaXMuY2N0dkVycm9yID0gJ1VuYWJsZSB0byBsb2FkIHRoZSBjYW1lcmEgcGxhY2VtZW50IHN0YXR1cy4nO1xuICAgICAgICB9LFxuICAgICAgfSk7XG4gIH1cblxuICByZWZyZXNoKCk6IHZvaWQge1xuICAgIHRoaXMucmVsb2FkaW5nID0gdHJ1ZTtcbiAgICB0aGlzLnZpZXdUaWNrZXQoKTtcbiAgfVxuXG4gIHJldHJ5UGxhY2VtZW50KCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5mbG9vcklkIHx8IHRoaXMucmV0cnlpbmcpIHJldHVybjtcbiAgICB0aGlzLnJldHJ5aW5nID0gdHJ1ZTtcbiAgICB0aGlzLnNlcnZpY2UuY2N0dlJldHJ5KHsgZmxvb3JJZDogdGhpcy5mbG9vcklkIH0pXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXG4gICAgICAuc3Vic2NyaWJlKHtcbiAgICAgICAgbmV4dDogKHJlczogYW55KSA9PiB7XG4gICAgICAgICAgdGhpcy5yZXRyeWluZyA9IGZhbHNlO1xuICAgICAgICAgIHRoaXMudG9hc3RTZXJ2aWNlLmdldFN1Y2Nlc3NUb2FzdChcbiAgICAgICAgICAgIHJlcz8uZGF0YT8uc3RhcnRlZE5vdyA/XG4gICAgICAgICAgICAgICdBdXRvIHBsYWNlbWVudCBpcyBydW5uaW5nIGFnYWluLicgOlxuICAgICAgICAgICAgICAnUXVldWVkIGZvciBhdXRvIHBsYWNlbWVudC4gSXQgd2lsbCBzdGFydCBvbiB0aGUgbmV4dCBydW4uJyxcbiAgICAgICAgICApO1xuICAgICAgICAgIHRoaXMubG9hZENjdHZEZXRhaWwoKTtcbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3I6ICgpID0+IHtcbiAgICAgICAgICB0aGlzLnJldHJ5aW5nID0gZmFsc2U7XG4gICAgICAgICAgdGhpcy50b2FzdFNlcnZpY2UuZ2V0RXJyb3JUb2FzdCgnVW5hYmxlIHRvIHJldHJ5LiBQbGVhc2UgdHJ5IGFnYWluLicpO1xuICAgICAgICB9LFxuICAgICAgfSk7XG4gIH1cblxuICBvcGVuRWRpdG9yKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5mbG9vcklkKSByZXR1cm47XG4gICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoWycvbWFuYWdlL3BsYW5vZ3JhbS9jY3R2LWVkaXRvciddLCB7XG4gICAgICBxdWVyeVBhcmFtczogeyBmbG9vcklkOiB0aGlzLmZsb29ySWQsIG1vZGU6ICdlZGl0JyB9LFxuICAgIH0pO1xuICB9XG5cbiAgLyoqIFRoZSBzb3VyY2UgZHJhd2luZywgcmVhZC1vbmx5LCB3aGlsZSBhdXRvIHBsYWNlbWVudCBpcyBzdGlsbCBydW5uaW5nLiAqL1xuICBvcGVuUHJldmlldygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuZmxvb3JJZCkgcmV0dXJuO1xuICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnL21hbmFnZS9wbGFub2dyYW0vY2N0di1wcmV2aWV3J10sIHtcbiAgICAgIHF1ZXJ5UGFyYW1zOiB7IGZsb29ySWQ6IHRoaXMuZmxvb3JJZCwgZnJvbTogJ3RpY2tldCcgfSxcbiAgICB9KTtcbiAgfVxuXG4gIGJhY2soKTogdm9pZCB7XG4gICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoWycvdGlja2V0cy91c2VycyddLCB7IHF1ZXJ5UGFyYW1zOiB7IHR5cGU6ICdpbnN0YWxsYXRpb24nIH0gfSk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJjb250YWluZXItZmx1aWQgcC01IHByZWluc3RhbGwtcGFnZVwiPlxuXG4gIDwhLS0gSGVhZGVyIC0tPlxuICA8ZGl2IGNsYXNzPVwiY2FyZCBtYi01XCI+XG4gICAgPGRpdiBjbGFzcz1cImNhcmQtYm9keSBkLWZsZXggZmxleC13cmFwIGFsaWduLWl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBnYXAtNCBweS00XCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBnYXAtNFwiPlxuICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tc20gYnRuLWxpZ2h0IGJhY2stYnRuXCIgKGNsaWNrKT1cImJhY2soKVwiIGFyaWEtbGFiZWw9XCJCYWNrIHRvIHdvcmtzcGFjZVwiPlxuICAgICAgICAgIDxpIGNsYXNzPVwiYmkgYmktYXJyb3ctbGVmdFwiPjwvaT5cbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxkaXY+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIgZ2FwLTNcIj5cbiAgICAgICAgICAgIDxoNCBjbGFzcz1cIm1iLTBcIj57eyB0aWNrZXRJbmZvPy50aWNrZXRJZCB8fCB0aWNrZXRJZCB9fTwvaDQ+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImJhZGdlIHN0YXRlLWJhZGdlXCIgW25nQ2xhc3NdPVwiJ3N0YXRlLScgKyBwbGFjZW1lbnRTdGF0ZVwiPlxuICAgICAgICAgICAgICB7e1xuICAgICAgICAgICAgICAgIHBsYWNlbWVudFN0YXRlID09PSAnd2FpdGluZ0xheW91dCcgPyAnV2FpdGluZyBmb3IgbGF5b3V0JyA6XG4gICAgICAgICAgICAgICAgcGxhY2VtZW50U3RhdGUgPT09ICdwcm9jZXNzaW5nJyA/ICdBdXRvIHBsYWNlbWVudCBpbiBwcm9ncmVzcycgOlxuICAgICAgICAgICAgICAgIHBsYWNlbWVudFN0YXRlID09PSAnZmFpbGVkJyA/ICdQbGFjZW1lbnQgZmFpbGVkJyA6XG4gICAgICAgICAgICAgICAgcGxhY2VtZW50U3RhdGUgPT09ICdvcGVuJyA/ICdSZWFkeSBmb3IgcGxhY2VtZW50IHJldmlldycgOlxuICAgICAgICAgICAgICAgIHBsYWNlbWVudFN0YXRlID09PSAnYXBwcm92YWxQZW5kaW5nJyA/ICdXYWl0aW5nIGZvciBhcHByb3ZhbCcgOlxuICAgICAgICAgICAgICAgIHBsYWNlbWVudFN0YXRlID09PSAnYXBwcm92ZWQnID8gJ0FwcHJvdmVkJyA6XG4gICAgICAgICAgICAgICAgcGxhY2VtZW50U3RhdGUgPT09ICd1bmF2YWlsYWJsZScgPyAnU3RhdHVzIHVuYXZhaWxhYmxlJyA6ICdMb2FkaW5nJ1xuICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LW11dGVkIGZzLTcgbXQtMVwiPlxuICAgICAgICAgICAgUHJlLUluc3RhbGxhdGlvbiwgY2FtZXJhIHBsYWNlbWVudFxuICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJ0aWNrZXRJbmZvPy5iYXNpY0RldGFpbHM/LnN0b3JlTmFtZVwiPiwge3sgdGlja2V0SW5mbz8uYmFzaWNEZXRhaWxzPy5zdG9yZU5hbWUgfX08L3NwYW4+XG4gICAgICAgICAgICA8c3Bhbj4sIEZsb29yIHt7IGZsb29yTnVtYmVyIH19PC9zcGFuPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIgZ2FwLTNcIj5cbiAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1saWdodCByb3ctYnRuXCIgKGNsaWNrKT1cInJlZnJlc2goKVwiPlxuICAgICAgICAgIDxpIGNsYXNzPVwiYmkgYmktYXJyb3ctY2xvY2t3aXNlIG1lLTFcIiBbY2xhc3Muc3Bpbm5pbmddPVwicmVsb2FkaW5nIHx8IGNjdHZMb2FkaW5nXCI+PC9pPlJlZnJlc2hcbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG5cbiAgPGRpdiAqbmdJZj1cImxvYWRpbmdcIiBjbGFzcz1cInRleHQtY2VudGVyIHB5LTEwIHRleHQtbXV0ZWRcIj5Mb2FkaW5nIHRpY2tldC4uLjwvZGl2PlxuXG4gIDxkaXYgKm5nSWY9XCIhbG9hZGluZyAmJiB0aWNrZXRJbmZvXCIgY2xhc3M9XCJyb3cgZy01XCI+XG5cbiAgICA8IS0tIFBsYWNlbWVudCBzdGF0ZSAvIGFjdGlvbiBwYW5lbCAtLT5cbiAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIGNvbC1sZy03XCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiY2FyZCBoLTEwMFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2FyZC1ib2R5XCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNhcmQtaGVhZCBtYi00XCI+XG4gICAgICAgICAgICA8aDUgY2xhc3M9XCJtYi0wXCI+Q2FtZXJhIHBsYWNlbWVudDwvaDU+XG4gICAgICAgICAgICA8IS0tIFRoZSBpbXBvcnRlZCBkcmF3aW5nIGl0c2VsZiwgZm9yIHRoZSBpbnRlcm5hbCB0ZWFtIHRvIGluc3BlY3QgaW5cbiAgICAgICAgICAgICAgICAgQ0FEIHdoZW4gdGhlIGVuZ2luZSBjYW5ub3QgaGFuZGxlIGl0IG9yIGJlZm9yZSBlZGl0aW5nLiAtLT5cbiAgICAgICAgICAgIDxhICpuZ0lmPVwic291cmNlRHhmVXJsXCIgW2hyZWZdPVwic291cmNlRHhmVXJsXCIgdGFyZ2V0PVwiX2JsYW5rXCIgcmVsPVwibm9vcGVuZXJcIlxuICAgICAgICAgICAgICBjbGFzcz1cImJ0biBidG4tc20gYnRuLWxpZ2h0IHJvdy1idG5cIiBbbmdiVG9vbHRpcF09XCJzb3VyY2VEeGZOYW1lXCI+XG4gICAgICAgICAgICAgIDxzdmcgd2lkdGg9XCIxNlwiIGhlaWdodD1cIjE2XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiIGZpbGw9XCJub25lXCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPlxuICAgICAgICAgICAgICAgIDxwYXRoIGQ9XCJNMTIgM3YxMm0wIDAgNC00bS00IDQtNC00TTQgMTd2MmEyIDIgMCAwIDAgMiAyaDEyYTIgMiAwIDAgMCAyLTJ2LTJcIlxuICAgICAgICAgICAgICAgICAgc3Ryb2tlPVwiY3VycmVudENvbG9yXCIgc3Ryb2tlLXdpZHRoPVwiMS44XCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIgLz5cbiAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibXMtMVwiPkRvd25sb2FkIHNvdXJjZSBEWEY8L3NwYW4+XG4gICAgICAgICAgICA8L2E+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8ZGl2IFtuZ1N3aXRjaF09XCJwbGFjZW1lbnRTdGF0ZVwiIGNsYXNzPVwic3RhdGUtcGFuZWxcIj5cblxuICAgICAgICAgICAgPGRpdiAqbmdTd2l0Y2hDYXNlPVwiJ3dhaXRpbmdMYXlvdXQnXCIgY2xhc3M9XCJzdGF0ZS1ib3hcIj5cbiAgICAgICAgICAgICAgPHAgY2xhc3M9XCJtYi0xIGZ3LXNlbWlib2xkXCI+V2FpdGluZyBmb3IgdGhlIENBRCBsYXlvdXQuPC9wPlxuICAgICAgICAgICAgICA8cCBjbGFzcz1cInRleHQtbXV0ZWQgbWItMFwiPlRoZSBzdG9yZSdzIGZsb29yIGRyYXdpbmcgaGFzIG5vdCBiZWVuIGltcG9ydGVkIHlldC4gQXV0byBwbGFjZW1lbnQgc3RhcnRzIHJpZ2h0IGFmdGVyIHRoZSBDQUQgaW1wb3J0LjwvcD5cbiAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICA8ZGl2ICpuZ1N3aXRjaENhc2U9XCIncHJvY2Vzc2luZydcIiBjbGFzcz1cInN0YXRlLWJveFwiPlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBnYXAtMyBtYi0xXCI+XG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzcGlubmVyLWJvcmRlciBzcGlubmVyLWJvcmRlci1zbSB0ZXh0LXByaW1hcnlcIiByb2xlPVwic3RhdHVzXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9zcGFuPlxuICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwibWItMCBmdy1zZW1pYm9sZFwiPkF1dG8gY2FtZXJhIHBsYWNlbWVudCBpcyBydW5uaW5nLjwvcD5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwidGV4dC1tdXRlZCBtYi0zXCI+VGhlIERYRiBlZGl0b3IgdW5sb2NrcyB3aGVuIHBsYWNlbWVudCBjb21wbGV0ZXMuIFVzZSBSZWZyZXNoIHRvIGNoZWNrIGFnYWluLiBNZWFud2hpbGUgeW91IGNhbiBsb29rIGF0IHRoZSBzb3VyY2UgZHJhd2luZy48L3A+XG4gICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1zbSBidG4tbGlnaHQgcm93LWJ0blwiIChjbGljayk9XCJvcGVuUHJldmlldygpXCI+XG4gICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJiaSBiaS1leWUgbWUtMVwiPjwvaT5WaWV3IHNvdXJjZSBkcmF3aW5nXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIidmYWlsZWQnXCIgY2xhc3M9XCJzdGF0ZS1ib3ggc3RhdGUtYm94LWRhbmdlclwiPlxuICAgICAgICAgICAgICA8cCBjbGFzcz1cIm1iLTEgZnctc2VtaWJvbGRcIj5BdXRvIHBsYWNlbWVudCBmYWlsZWQuPC9wPlxuICAgICAgICAgICAgICA8cCBjbGFzcz1cInRleHQtbXV0ZWQgbWItM1wiPnt7IHBsYWNlbWVudD8uZXJyb3JNc2cgfHwgY2N0dlJvdz8uZXJyb3JNc2cgfHwgJ1RoZSBwbGFjZW1lbnQgZW5naW5lIHJlcG9ydGVkIGEgZmFpbHVyZS4nIH19PC9wPlxuICAgICAgICAgICAgICA8IS0tIFJldHJ5IGhpZGRlbiB1bnRpbCB0aGUgYXV0b1BsYWNlIExhbWJkYSBleGlzdHMgKExBTUJEQVVSTC5hdXRvUGxhY2UgaXMgZW1wdHkpLlxuICAgICAgICAgICAgICAgICAgIFJlLWVuYWJsZSBieSByZW1vdmluZyB0aGlzIGNvbW1lbnQ7IHJldHJ5UGxhY2VtZW50KCkgaXMgc3RpbGwgd2lyZWQgaW4gdGhlIGNvbXBvbmVudC5cbiAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1wcmltYXJ5IHJvdy1idG5cIiBbZGlzYWJsZWRdPVwicmV0cnlpbmdcIiAoY2xpY2spPVwicmV0cnlQbGFjZW1lbnQoKVwiPlxuICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwicmV0cnlpbmdcIiBjbGFzcz1cInNwaW5uZXItYm9yZGVyIHNwaW5uZXItYm9yZGVyLXNtIG1lLTJcIiByb2xlPVwic3RhdHVzXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9zcGFuPlxuICAgICAgICAgICAgICAgIHt7IHJldHJ5aW5nID8gJ1JldHJ5aW5nLi4uJyA6ICdSZXRyeSBhdXRvIHBsYWNlbWVudCcgfX1cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgIC0tPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIidvcGVuJ1wiIGNsYXNzPVwic3RhdGUtYm94XCI+XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwibWItMSBmdy1zZW1pYm9sZFwiPlRoZSBkcmF3aW5nIGlzIHJlYWR5IGZvciBjYW1lcmEgcmV2aWV3LjwvcD5cbiAgICAgICAgICAgICAgPHAgY2xhc3M9XCJ0ZXh0LW11dGVkIG1iLTNcIj5cbiAgICAgICAgICAgICAgICBBZGp1c3QgdGhlIGF1dG8tcGxhY2VkIGNhbWVyYXMgaW4gdGhlIERYRiBlZGl0b3IsIHRoZW4gc3VibWl0IGZvciBhcHByb3ZhbC5cbiAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cImNjdHZSb3c/LmlzUmV3b3JrXCIgY2xhc3M9XCJ0ZXh0LXdhcm5pbmcgZnctc2VtaWJvbGRcIj5UaGlzIGZsb29yIHdhcyBzZW50IGJhY2sgZm9yIHJld29yay48L3NwYW4+XG4gICAgICAgICAgICAgIDwvcD5cbiAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1wcmltYXJ5IHJvdy1idG5cIiAoY2xpY2spPVwib3BlbkVkaXRvcigpXCI+XG4gICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJiaSBiaS1wZW5jaWwtc3F1YXJlIG1lLTFcIj48L2k+T3BlbiBEWEYgZWRpdG9yXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIDxkaXYgKm5nU3dpdGNoQ2FzZT1cIidhcHByb3ZhbFBlbmRpbmcnXCIgY2xhc3M9XCJzdGF0ZS1ib3hcIj5cbiAgICAgICAgICAgICAgPHAgY2xhc3M9XCJtYi0xIGZ3LXNlbWlib2xkXCI+U3VibWl0dGVkLCB3YWl0aW5nIGZvciBhcHByb3ZhbC48L3A+XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwidGV4dC1tdXRlZCBtYi0zXCI+VGhlIGFwcHJvdmFsIHRlYW0gcmV2aWV3cyBpdCBmcm9tIHRoZSBvbmJvYXJkIHRhYmxlLiBZb3UgY2FuIHN0aWxsIHZpZXcgdGhlIGRyYXdpbmcuPC9wPlxuICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tc20gYnRuLWxpZ2h0IHJvdy1idG5cIiAoY2xpY2spPVwib3BlbkVkaXRvcigpXCI+XG4gICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJiaSBiaS1leWUgbWUtMVwiPjwvaT5WaWV3IGRyYXdpbmdcbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPGRpdiAqbmdTd2l0Y2hDYXNlPVwiJ2FwcHJvdmVkJ1wiIGNsYXNzPVwic3RhdGUtYm94IHN0YXRlLWJveC1zdWNjZXNzXCI+XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwibWItMSBmdy1zZW1pYm9sZFwiPkNhbWVyYSBwbGFjZW1lbnQgYXBwcm92ZWQuPC9wPlxuICAgICAgICAgICAgICA8cCBjbGFzcz1cInRleHQtbXV0ZWQgbWItMFwiPlRoaXMgdGlja2V0IGlzIGNsb3NlZC4gVGhlIGluc3RhbGxhdGlvbiB0aWNrZXQgdGFrZXMgb3ZlciBvbmNlIGV2ZXJ5IGZsb29yIG9mIHRoZSBzdG9yZSBpcyBhcHByb3ZlZC48L3A+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPGRpdiAqbmdTd2l0Y2hDYXNlPVwiJ3VuYXZhaWxhYmxlJ1wiIGNsYXNzPVwic3RhdGUtYm94IHN0YXRlLWJveC1kYW5nZXJcIj5cbiAgICAgICAgICAgICAgPHAgY2xhc3M9XCJtYi0xIGZ3LXNlbWlib2xkXCI+UGxhY2VtZW50IHN0YXR1cyB1bmF2YWlsYWJsZS48L3A+XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwidGV4dC1tdXRlZCBtYi0zXCI+e3sgY2N0dkVycm9yIH19PC9wPlxuICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tc20gYnRuLWxpZ2h0IHJvdy1idG5cIiAoY2xpY2spPVwibG9hZENjdHZEZXRhaWwoKVwiPlRyeSBhZ2FpbjwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIDxkaXYgKm5nU3dpdGNoRGVmYXVsdCBjbGFzcz1cInN0YXRlLWJveFwiPlxuICAgICAgICAgICAgICA8cCBjbGFzcz1cInRleHQtbXV0ZWQgbWItMFwiPkxvYWRpbmcgcGxhY2VtZW50IHN0YXR1cy4uLjwvcD5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPCEtLSBWZXJzaW9uIHRpbWVsaW5lIC0tPlxuICAgICAgICAgIDxkaXYgKm5nSWY9XCJ2ZXJzaW9ucy5sZW5ndGhcIiBjbGFzcz1cIm10LTZcIj5cbiAgICAgICAgICAgIDxoNiBjbGFzcz1cInRleHQtbXV0ZWQgbWItM1wiPkRyYXdpbmcgdmVyc2lvbnM8L2g2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInZlcnNpb24tbGlzdFwiPlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidmVyc2lvbi1yb3cgZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlblwiICpuZ0Zvcj1cImxldCBmaWxlIG9mIHZlcnNpb25zXCI+XG4gICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZnctc2VtaWJvbGRcIj52e3sgZmlsZS52ZXJzaW9uIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkIG1zLTIgZnMtN1wiPnt7IGZpbGUua2luZCA9PT0gJ2F1dG8nID8gJ0F1dG8gcGxhY2VtZW50JyA6IGZpbGUua2luZCA9PT0gJ2FwcHJvdmVyJyA/ICdBcHByb3ZlciBlZGl0JyA6ICdJbnRlcm5hbCBlZGl0JyB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1tdXRlZCBtcy0yIGZzLTdcIiAqbmdJZj1cImZpbGUuY2FtZXJhQ291bnQgIT0gbnVsbFwiPnt7IGZpbGUuY2FtZXJhQ291bnQgfX0gY2FtZXJhczwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBnYXAtM1wiPlxuICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkIGZzLTdcIj57eyBmaWxlLnVwbG9hZGVkQXQgfCBkYXRlOiAnZGQgTU1NLCB5IGg6bW0gYScgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICA8YSAqbmdJZj1cImZpbGVVcmxzW2ZpbGUua2V5XVwiIFtocmVmXT1cImZpbGVVcmxzW2ZpbGUua2V5XVwiIHRhcmdldD1cIl9ibGFua1wiIHJlbD1cIm5vb3BlbmVyXCIgY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1saWdodCByb3ctYnRuXCI+XG4gICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiYmkgYmktZG93bmxvYWRcIj48L2k+XG4gICAgICAgICAgICAgICAgICA8L2E+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG5cbiAgICA8IS0tIFRpY2tldCBpbmZvICsgYWN0aXZpdHkgLS0+XG4gICAgPGRpdiBjbGFzcz1cImNvbC0xMiBjb2wtbGctNVwiPlxuICAgICAgPGRpdiBjbGFzcz1cImNhcmQgbWItNVwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2FyZC1ib2R5XCI+XG4gICAgICAgICAgPGg1IGNsYXNzPVwibWItNFwiPlRpY2tldCBkZXRhaWxzPC9oNT5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGV0YWlsLWdyaWRcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkZXRhaWwtcm93XCI+PHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkXCI+U3RvcmU8L3NwYW4+PHNwYW4+e3sgdGlja2V0SW5mbz8uYmFzaWNEZXRhaWxzPy5zdG9yZU5hbWUgfHwgJy0nIH19ICh7eyB0aWNrZXRJbmZvPy5iYXNpY0RldGFpbHM/LnN0b3JlSWQgfHwgc3RvcmVJZCB9fSk8L3NwYW4+PC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGV0YWlsLXJvd1wiPjxzcGFuIGNsYXNzPVwidGV4dC1tdXRlZFwiPkJyYW5kPC9zcGFuPjxzcGFuPnt7IHRpY2tldEluZm8/LmJhc2ljRGV0YWlscz8uY2xpZW50TmFtZSB8fCAnLScgfX08L3NwYW4+PC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGV0YWlsLXJvd1wiPjxzcGFuIGNsYXNzPVwidGV4dC1tdXRlZFwiPkZsb29yPC9zcGFuPjxzcGFuPkZsb29yIHt7IGZsb29yTnVtYmVyIH19PC9zcGFuPjwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRldGFpbC1yb3dcIj48c3BhbiBjbGFzcz1cInRleHQtbXV0ZWRcIj5UaWNrZXQgc3RhdHVzPC9zcGFuPjxzcGFuIGNsYXNzPVwidGV4dC1jYXBpdGFsaXplXCI+e3sgdGlja2V0SW5mbz8uc3RhdHVzIHx8ICctJyB9fTwvc3Bhbj48L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkZXRhaWwtcm93XCI+PHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkXCI+Q3JlYXRlZDwvc3Bhbj48c3Bhbj57eyB0aWNrZXRJbmZvPy5jcmVhdGVkQXQgfCBkYXRlOiAnZGQgTU1NLCB5IGg6bW0gYScgfX08L3NwYW4+PC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGV0YWlsLXJvd1wiICpuZ0lmPVwiY2N0dlJvdz8uYXNzaWduZWVOYW1lXCI+PHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkXCI+QXNzaWduZWU8L3NwYW4+PHNwYW4+e3sgY2N0dlJvdz8uYXNzaWduZWVOYW1lIH19PC9zcGFuPjwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRldGFpbC1yb3dcIiAqbmdJZj1cImNjdHZSb3c/LnJld29ya0NvdW50XCI+PHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkXCI+UmV3b3JrIGNvdW50PC9zcGFuPjxzcGFuPnt7IGNjdHZSb3c/LnJld29ya0NvdW50IH19PC9zcGFuPjwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8ZGl2IGNsYXNzPVwiY2FyZFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2FyZC1ib2R5XCI+XG4gICAgICAgICAgPGg1IGNsYXNzPVwibWItNFwiPkFjdGl2aXR5PC9oNT5cbiAgICAgICAgICA8ZGl2ICpuZ0lmPVwiIWFjdGl2aXR5Lmxlbmd0aFwiIGNsYXNzPVwidGV4dC1tdXRlZCBmcy03XCI+Tm8gYWN0aXZpdHkgeWV0LjwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJhY3Rpdml0eS1saXN0XCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWN0aXZpdHktcm93XCIgKm5nRm9yPVwibGV0IGVudHJ5IG9mIGFjdGl2aXR5XCI+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhY3Rpdml0eS1kb3RcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2Rpdj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXgtZ3Jvdy0xXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBnYXAtM1wiPlxuICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJmdy1zZW1pYm9sZCBmcy03XCI+e3sgZW50cnkuZGVzY3JpcHRpb24gfHwgZW50cnkuYWN0aW9uVHlwZSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1tdXRlZCBmcy04IHRleHQtbm93cmFwXCI+e3sgZW50cnkudGltZVN0YW1wIHwgZGF0ZTogJ2RkIE1NTSwgaDptbSBhJyB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGV4dC1tdXRlZCBmcy04XCIgKm5nSWY9XCJlbnRyeS5jb21tZW50XCI+e3sgZW50cnkuY29tbWVudCB9fTwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LW11dGVkIGZzLThcIiAqbmdJZj1cImVudHJ5LklkZW50aWZpZWRCeSAmJiBlbnRyeS5JZGVudGlmaWVkQnkgIT09ICdUYW5nbydcIj5ieSB7eyBlbnRyeS5JZGVudGlmaWVkQnkgfX08L2Rpdj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==
|
|
@@ -4316,11 +4316,11 @@ class PreinstallationInfoComponent {
|
|
|
4316
4316
|
this.router.navigate(['/tickets/users'], { queryParams: { type: 'installation' } });
|
|
4317
4317
|
}
|
|
4318
4318
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PreinstallationInfoComponent, deps: [{ token: i1$1.ActivatedRoute }, { token: i1$1.Router }, { token: TicketsService }, { token: i3.ToastService }], target: i0.ɵɵFactoryTarget.Component });
|
|
4319
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PreinstallationInfoComponent, selector: "lib-preinstallation-info", ngImport: i0, template: "<div class=\"container-fluid p-5 preinstall-page\">\n\n <!-- Header -->\n <div class=\"card mb-5\">\n <div class=\"card-body d-flex flex-wrap align-items-center justify-content-between gap-4 py-4\">\n <div class=\"d-flex align-items-center gap-4\">\n <button type=\"button\" class=\"btn btn-sm btn-light back-btn\" (click)=\"back()\" aria-label=\"Back to workspace\">\n <i class=\"bi bi-arrow-left\"></i>\n </button>\n <div>\n <div class=\"d-flex align-items-center gap-3\">\n <h4 class=\"mb-0\">{{ ticketInfo?.ticketId || ticketId }}</h4>\n <span class=\"badge state-badge\" [ngClass]=\"'state-' + placementState\">\n {{\n placementState === 'waitingLayout' ? 'Waiting for layout' :\n placementState === 'processing' ? 'Auto placement in progress' :\n placementState === 'failed' ? 'Placement failed' :\n placementState === 'open' ? 'Ready for placement review' :\n placementState === 'approvalPending' ? 'Waiting for approval' :\n placementState === 'approved' ? 'Approved' :\n placementState === 'unavailable' ? 'Status unavailable' : 'Loading'\n }}\n </span>\n </div>\n <div class=\"text-muted fs-7 mt-1\">\n Pre-Installation, camera placement\n <span *ngIf=\"ticketInfo?.basicDetails?.storeName\">, {{ ticketInfo?.basicDetails?.storeName }}</span>\n <span>, Floor {{ floorNumber }}</span>\n </div>\n </div>\n </div>\n <div class=\"d-flex align-items-center gap-3\">\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"refresh()\">\n <i class=\"bi bi-arrow-clockwise me-1\" [class.spinning]=\"reloading || cctvLoading\"></i>Refresh\n </button>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"loading\" class=\"text-center py-10 text-muted\">Loading ticket...</div>\n\n <div *ngIf=\"!loading && ticketInfo\" class=\"row g-5\">\n\n <!-- Placement state / action panel -->\n <div class=\"col-12 col-lg-7\">\n <div class=\"card h-100\">\n <div class=\"card-body\">\n <div class=\"card-head mb-4\">\n <h5 class=\"mb-0\">Camera placement</h5>\n <!-- The imported drawing itself, for the internal team to inspect in\n CAD when the engine cannot handle it or before editing. -->\n <a *ngIf=\"sourceDxfUrl\" [href]=\"sourceDxfUrl\" target=\"_blank\" rel=\"noopener\"\n class=\"btn btn-sm btn-light row-btn\" [ngbTooltip]=\"sourceDxfName\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M12 3v12m0 0 4-4m-4 4-4-4M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <span class=\"ms-1\">Download source DXF</span>\n </a>\n </div>\n\n <div [ngSwitch]=\"placementState\" class=\"state-panel\">\n\n <div *ngSwitchCase=\"'waitingLayout'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">Waiting for the CAD layout.</p>\n <p class=\"text-muted mb-0\">The store's floor drawing has not been imported yet. Auto placement starts right after the CAD import.</p>\n </div>\n\n <div *ngSwitchCase=\"'processing'\" class=\"state-box\">\n <div class=\"d-flex align-items-center gap-3 mb-1\">\n <span class=\"spinner-border spinner-border-sm text-primary\" role=\"status\" aria-hidden=\"true\"></span>\n <p class=\"mb-0 fw-semibold\">Auto camera placement is running.</p>\n </div>\n <p class=\"text-muted mb-3\">The DXF editor unlocks when placement completes. Use Refresh to check again. Meanwhile you can look at the source drawing.</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"openPreview()\">\n <i class=\"bi bi-eye me-1\"></i>View source drawing\n </button>\n </div>\n\n <div *ngSwitchCase=\"'failed'\" class=\"state-box state-box-danger\">\n <p class=\"mb-1 fw-semibold\">Auto placement failed.</p>\n <p class=\"text-muted mb-3\">{{ placement?.errorMsg || cctvRow?.errorMsg || 'The placement engine reported a failure.' }}</p>\n <!-- Retry hidden until the autoPlace Lambda exists (LAMBDAURL.autoPlace is empty).\n Re-enable by removing this comment; retryPlacement() is still wired in the component.\n <button type=\"button\" class=\"btn btn-sm btn-primary row-btn\" [disabled]=\"retrying\" (click)=\"retryPlacement()\">\n <span *ngIf=\"retrying\" class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>\n {{ retrying ? 'Retrying...' : 'Retry auto placement' }}\n </button>\n -->\n </div>\n\n <div *ngSwitchCase=\"'open'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">The drawing is ready for camera review.</p>\n <p class=\"text-muted mb-3\">\n Adjust the auto-placed cameras in the DXF editor, then submit for approval.\n <span *ngIf=\"cctvRow?.isRework\" class=\"text-warning fw-semibold\">This floor was sent back for rework.</span>\n </p>\n <button type=\"button\" class=\"btn btn-sm btn-primary row-btn\" (click)=\"openEditor()\">\n <i class=\"bi bi-pencil-square me-1\"></i>Open DXF editor\n </button>\n </div>\n\n <div *ngSwitchCase=\"'approvalPending'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">Submitted, waiting for approval.</p>\n <p class=\"text-muted mb-3\">The approval team reviews it from the onboard table. You can still view the drawing.</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"openEditor()\">\n <i class=\"bi bi-eye me-1\"></i>View drawing\n </button>\n </div>\n\n <div *ngSwitchCase=\"'approved'\" class=\"state-box state-box-success\">\n <p class=\"mb-1 fw-semibold\">Camera placement approved.</p>\n <p class=\"text-muted mb-0\">This ticket is closed. The installation ticket takes over once every floor of the store is approved.</p>\n </div>\n\n <div *ngSwitchCase=\"'unavailable'\" class=\"state-box state-box-danger\">\n <p class=\"mb-1 fw-semibold\">Placement status unavailable.</p>\n <p class=\"text-muted mb-3\">{{ cctvError }}</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"loadCctvDetail()\">Try again</button>\n </div>\n\n <div *ngSwitchDefault class=\"state-box\">\n <p class=\"text-muted mb-0\">Loading placement status...</p>\n </div>\n </div>\n\n <!-- Version timeline -->\n <div *ngIf=\"versions.length\" class=\"mt-6\">\n <h6 class=\"text-muted mb-3\">Drawing versions</h6>\n <div class=\"version-list\">\n <div class=\"version-row d-flex align-items-center justify-content-between\" *ngFor=\"let file of versions\">\n <div>\n <span class=\"fw-semibold\">v{{ file.version }}</span>\n <span class=\"text-muted ms-2 fs-7\">{{ file.kind === 'auto' ? 'Auto placement' : file.kind === 'approver' ? 'Approver edit' : 'Internal edit' }}</span>\n <span class=\"text-muted ms-2 fs-7\" *ngIf=\"file.cameraCount != null\">{{ file.cameraCount }} cameras</span>\n </div>\n <div class=\"d-flex align-items-center gap-3\">\n <span class=\"text-muted fs-7\">{{ file.uploadedAt | date: 'dd MMM, y HH:mm' }}</span>\n <a *ngIf=\"fileUrls[file.key]\" [href]=\"fileUrls[file.key]\" target=\"_blank\" rel=\"noopener\" class=\"btn btn-sm btn-light row-btn\">\n <i class=\"bi bi-download\"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Ticket info + activity -->\n <div class=\"col-12 col-lg-5\">\n <div class=\"card mb-5\">\n <div class=\"card-body\">\n <h5 class=\"mb-4\">Ticket details</h5>\n <div class=\"detail-grid\">\n <div class=\"detail-row\"><span class=\"text-muted\">Store</span><span>{{ ticketInfo?.basicDetails?.storeName || '-' }} ({{ ticketInfo?.basicDetails?.storeId || storeId }})</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Brand</span><span>{{ ticketInfo?.basicDetails?.clientName || '-' }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Floor</span><span>Floor {{ floorNumber }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Ticket status</span><span class=\"text-capitalize\">{{ ticketInfo?.status || '-' }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Created</span><span>{{ ticketInfo?.createdAt | date: 'dd MMM, y HH:mm' }}</span></div>\n <div class=\"detail-row\" *ngIf=\"cctvRow?.assigneeName\"><span class=\"text-muted\">Assignee</span><span>{{ cctvRow?.assigneeName }}</span></div>\n <div class=\"detail-row\" *ngIf=\"cctvRow?.reworkCount\"><span class=\"text-muted\">Rework count</span><span>{{ cctvRow?.reworkCount }}</span></div>\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-body\">\n <h5 class=\"mb-4\">Activity</h5>\n <div *ngIf=\"!activity.length\" class=\"text-muted fs-7\">No activity yet.</div>\n <div class=\"activity-list\">\n <div class=\"activity-row\" *ngFor=\"let entry of activity\">\n <div class=\"activity-dot\" aria-hidden=\"true\"></div>\n <div class=\"flex-grow-1\">\n <div class=\"d-flex justify-content-between gap-3\">\n <span class=\"fw-semibold fs-7\">{{ entry.description || entry.actionType }}</span>\n <span class=\"text-muted fs-8 text-nowrap\">{{ entry.timeStamp | date: 'dd MMM, HH:mm' }}</span>\n </div>\n <div class=\"text-muted fs-8\" *ngIf=\"entry.comment\">{{ entry.comment }}</div>\n <div class=\"text-muted fs-8\" *ngIf=\"entry.IdentifiedBy && entry.IdentifiedBy !== 'Tango'\">by {{ entry.IdentifiedBy }}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".preinstall-page .back-btn,.preinstall-page .card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.preinstall-page .back-btn .row-btn,.preinstall-page .card-head .row-btn{display:inline-flex;align-items:center;white-space:nowrap}.preinstall-page .row-btn{height:40px;display:inline-flex;align-items:center}.preinstall-page .state-badge{padding:6px 12px;font-weight:600;border-radius:999px}.preinstall-page .state-badge.state-waitingLayout,.preinstall-page .state-badge.state-loading,.preinstall-page .state-badge.state-unavailable{background:#f1f3f5;color:#5e6278}.preinstall-page .state-badge.state-processing{background:#eef6ff;color:#1b84ff}.preinstall-page .state-badge.state-failed{background:#fff5f8;color:#f1416c}.preinstall-page .state-badge.state-open{background:#e8fff3;color:#17c653}.preinstall-page .state-badge.state-approvalPending{background:#fff8dd;color:#f6c000}.preinstall-page .state-badge.state-approved{background:#e8fff3;color:#17c653}.preinstall-page .state-panel .state-box{border:1px solid #e9ecef;border-radius:8px;padding:16px 20px;opacity:0;transform:translateY(4px);animation:preinstallFade .25s ease forwards}.preinstall-page .state-panel .state-box.state-box-danger{border-color:#ffd6e1;background:#fff9fb}.preinstall-page .state-panel .state-box.state-box-success{border-color:#c8f2d8;background:#f6fffa}.preinstall-page .version-list .version-row{padding:10px 0;border-bottom:1px dashed #e9ecef}.preinstall-page .version-list .version-row:last-child{border-bottom:none}.preinstall-page .detail-grid .detail-row{display:flex;justify-content:space-between;gap:12px;padding:7px 0;border-bottom:1px dashed #f1f3f5;font-size:13px}.preinstall-page .detail-grid .detail-row:last-child{border-bottom:none}.preinstall-page .activity-list{max-height:420px;overflow-y:auto}.preinstall-page .activity-list .activity-row{display:flex;gap:10px;padding:8px 0}.preinstall-page .activity-list .activity-row .activity-dot{width:8px;height:8px;border-radius:50%;background:#1b84ff;margin-top:6px;flex-shrink:0}@keyframes preinstallFade{to{opacity:1;transform:translateY(0)}}@media (prefers-reduced-motion: reduce){.preinstall-page .state-panel .state-box{animation:none;opacity:1;transform:none}}.preinstall-page .bi-arrow-clockwise{display:inline-block;line-height:1}.preinstall-page .bi-arrow-clockwise:before{display:inline-block;transform-origin:50% 50%}.preinstall-page .bi-arrow-clockwise.spinning:before{animation:preinstallSpin .8s linear infinite}@keyframes preinstallSpin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion: reduce){.preinstall-page .bi-arrow-clockwise.spinning:before{animation:none}}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i4.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i1$2.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "pipe", type: i4.DatePipe, name: "date" }] });
|
|
4319
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PreinstallationInfoComponent, selector: "lib-preinstallation-info", ngImport: i0, template: "<div class=\"container-fluid p-5 preinstall-page\">\n\n <!-- Header -->\n <div class=\"card mb-5\">\n <div class=\"card-body d-flex flex-wrap align-items-center justify-content-between gap-4 py-4\">\n <div class=\"d-flex align-items-center gap-4\">\n <button type=\"button\" class=\"btn btn-sm btn-light back-btn\" (click)=\"back()\" aria-label=\"Back to workspace\">\n <i class=\"bi bi-arrow-left\"></i>\n </button>\n <div>\n <div class=\"d-flex align-items-center gap-3\">\n <h4 class=\"mb-0\">{{ ticketInfo?.ticketId || ticketId }}</h4>\n <span class=\"badge state-badge\" [ngClass]=\"'state-' + placementState\">\n {{\n placementState === 'waitingLayout' ? 'Waiting for layout' :\n placementState === 'processing' ? 'Auto placement in progress' :\n placementState === 'failed' ? 'Placement failed' :\n placementState === 'open' ? 'Ready for placement review' :\n placementState === 'approvalPending' ? 'Waiting for approval' :\n placementState === 'approved' ? 'Approved' :\n placementState === 'unavailable' ? 'Status unavailable' : 'Loading'\n }}\n </span>\n </div>\n <div class=\"text-muted fs-7 mt-1\">\n Pre-Installation, camera placement\n <span *ngIf=\"ticketInfo?.basicDetails?.storeName\">, {{ ticketInfo?.basicDetails?.storeName }}</span>\n <span>, Floor {{ floorNumber }}</span>\n </div>\n </div>\n </div>\n <div class=\"d-flex align-items-center gap-3\">\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"refresh()\">\n <i class=\"bi bi-arrow-clockwise me-1\" [class.spinning]=\"reloading || cctvLoading\"></i>Refresh\n </button>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"loading\" class=\"text-center py-10 text-muted\">Loading ticket...</div>\n\n <div *ngIf=\"!loading && ticketInfo\" class=\"row g-5\">\n\n <!-- Placement state / action panel -->\n <div class=\"col-12 col-lg-7\">\n <div class=\"card h-100\">\n <div class=\"card-body\">\n <div class=\"card-head mb-4\">\n <h5 class=\"mb-0\">Camera placement</h5>\n <!-- The imported drawing itself, for the internal team to inspect in\n CAD when the engine cannot handle it or before editing. -->\n <a *ngIf=\"sourceDxfUrl\" [href]=\"sourceDxfUrl\" target=\"_blank\" rel=\"noopener\"\n class=\"btn btn-sm btn-light row-btn\" [ngbTooltip]=\"sourceDxfName\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M12 3v12m0 0 4-4m-4 4-4-4M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <span class=\"ms-1\">Download source DXF</span>\n </a>\n </div>\n\n <div [ngSwitch]=\"placementState\" class=\"state-panel\">\n\n <div *ngSwitchCase=\"'waitingLayout'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">Waiting for the CAD layout.</p>\n <p class=\"text-muted mb-0\">The store's floor drawing has not been imported yet. Auto placement starts right after the CAD import.</p>\n </div>\n\n <div *ngSwitchCase=\"'processing'\" class=\"state-box\">\n <div class=\"d-flex align-items-center gap-3 mb-1\">\n <span class=\"spinner-border spinner-border-sm text-primary\" role=\"status\" aria-hidden=\"true\"></span>\n <p class=\"mb-0 fw-semibold\">Auto camera placement is running.</p>\n </div>\n <p class=\"text-muted mb-3\">The DXF editor unlocks when placement completes. Use Refresh to check again. Meanwhile you can look at the source drawing.</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"openPreview()\">\n <i class=\"bi bi-eye me-1\"></i>View source drawing\n </button>\n </div>\n\n <div *ngSwitchCase=\"'failed'\" class=\"state-box state-box-danger\">\n <p class=\"mb-1 fw-semibold\">Auto placement failed.</p>\n <p class=\"text-muted mb-3\">{{ placement?.errorMsg || cctvRow?.errorMsg || 'The placement engine reported a failure.' }}</p>\n <!-- Retry hidden until the autoPlace Lambda exists (LAMBDAURL.autoPlace is empty).\n Re-enable by removing this comment; retryPlacement() is still wired in the component.\n <button type=\"button\" class=\"btn btn-sm btn-primary row-btn\" [disabled]=\"retrying\" (click)=\"retryPlacement()\">\n <span *ngIf=\"retrying\" class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>\n {{ retrying ? 'Retrying...' : 'Retry auto placement' }}\n </button>\n -->\n </div>\n\n <div *ngSwitchCase=\"'open'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">The drawing is ready for camera review.</p>\n <p class=\"text-muted mb-3\">\n Adjust the auto-placed cameras in the DXF editor, then submit for approval.\n <span *ngIf=\"cctvRow?.isRework\" class=\"text-warning fw-semibold\">This floor was sent back for rework.</span>\n </p>\n <button type=\"button\" class=\"btn btn-sm btn-primary row-btn\" (click)=\"openEditor()\">\n <i class=\"bi bi-pencil-square me-1\"></i>Open DXF editor\n </button>\n </div>\n\n <div *ngSwitchCase=\"'approvalPending'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">Submitted, waiting for approval.</p>\n <p class=\"text-muted mb-3\">The approval team reviews it from the onboard table. You can still view the drawing.</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"openEditor()\">\n <i class=\"bi bi-eye me-1\"></i>View drawing\n </button>\n </div>\n\n <div *ngSwitchCase=\"'approved'\" class=\"state-box state-box-success\">\n <p class=\"mb-1 fw-semibold\">Camera placement approved.</p>\n <p class=\"text-muted mb-0\">This ticket is closed. The installation ticket takes over once every floor of the store is approved.</p>\n </div>\n\n <div *ngSwitchCase=\"'unavailable'\" class=\"state-box state-box-danger\">\n <p class=\"mb-1 fw-semibold\">Placement status unavailable.</p>\n <p class=\"text-muted mb-3\">{{ cctvError }}</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"loadCctvDetail()\">Try again</button>\n </div>\n\n <div *ngSwitchDefault class=\"state-box\">\n <p class=\"text-muted mb-0\">Loading placement status...</p>\n </div>\n </div>\n\n <!-- Version timeline -->\n <div *ngIf=\"versions.length\" class=\"mt-6\">\n <h6 class=\"text-muted mb-3\">Drawing versions</h6>\n <div class=\"version-list\">\n <div class=\"version-row d-flex align-items-center justify-content-between\" *ngFor=\"let file of versions\">\n <div>\n <span class=\"fw-semibold\">v{{ file.version }}</span>\n <span class=\"text-muted ms-2 fs-7\">{{ file.kind === 'auto' ? 'Auto placement' : file.kind === 'approver' ? 'Approver edit' : 'Internal edit' }}</span>\n <span class=\"text-muted ms-2 fs-7\" *ngIf=\"file.cameraCount != null\">{{ file.cameraCount }} cameras</span>\n </div>\n <div class=\"d-flex align-items-center gap-3\">\n <span class=\"text-muted fs-7\">{{ file.uploadedAt | date: 'dd MMM, y h:mm a' }}</span>\n <a *ngIf=\"fileUrls[file.key]\" [href]=\"fileUrls[file.key]\" target=\"_blank\" rel=\"noopener\" class=\"btn btn-sm btn-light row-btn\">\n <i class=\"bi bi-download\"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Ticket info + activity -->\n <div class=\"col-12 col-lg-5\">\n <div class=\"card mb-5\">\n <div class=\"card-body\">\n <h5 class=\"mb-4\">Ticket details</h5>\n <div class=\"detail-grid\">\n <div class=\"detail-row\"><span class=\"text-muted\">Store</span><span>{{ ticketInfo?.basicDetails?.storeName || '-' }} ({{ ticketInfo?.basicDetails?.storeId || storeId }})</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Brand</span><span>{{ ticketInfo?.basicDetails?.clientName || '-' }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Floor</span><span>Floor {{ floorNumber }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Ticket status</span><span class=\"text-capitalize\">{{ ticketInfo?.status || '-' }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Created</span><span>{{ ticketInfo?.createdAt | date: 'dd MMM, y h:mm a' }}</span></div>\n <div class=\"detail-row\" *ngIf=\"cctvRow?.assigneeName\"><span class=\"text-muted\">Assignee</span><span>{{ cctvRow?.assigneeName }}</span></div>\n <div class=\"detail-row\" *ngIf=\"cctvRow?.reworkCount\"><span class=\"text-muted\">Rework count</span><span>{{ cctvRow?.reworkCount }}</span></div>\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-body\">\n <h5 class=\"mb-4\">Activity</h5>\n <div *ngIf=\"!activity.length\" class=\"text-muted fs-7\">No activity yet.</div>\n <div class=\"activity-list\">\n <div class=\"activity-row\" *ngFor=\"let entry of activity\">\n <div class=\"activity-dot\" aria-hidden=\"true\"></div>\n <div class=\"flex-grow-1\">\n <div class=\"d-flex justify-content-between gap-3\">\n <span class=\"fw-semibold fs-7\">{{ entry.description || entry.actionType }}</span>\n <span class=\"text-muted fs-8 text-nowrap\">{{ entry.timeStamp | date: 'dd MMM, h:mm a' }}</span>\n </div>\n <div class=\"text-muted fs-8\" *ngIf=\"entry.comment\">{{ entry.comment }}</div>\n <div class=\"text-muted fs-8\" *ngIf=\"entry.IdentifiedBy && entry.IdentifiedBy !== 'Tango'\">by {{ entry.IdentifiedBy }}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".preinstall-page .back-btn,.preinstall-page .card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.preinstall-page .back-btn .row-btn,.preinstall-page .card-head .row-btn{display:inline-flex;align-items:center;white-space:nowrap}.preinstall-page .row-btn{height:40px;display:inline-flex;align-items:center}.preinstall-page .state-badge{padding:6px 12px;font-weight:600;border-radius:999px}.preinstall-page .state-badge.state-waitingLayout,.preinstall-page .state-badge.state-loading,.preinstall-page .state-badge.state-unavailable{background:#f1f3f5;color:#5e6278}.preinstall-page .state-badge.state-processing{background:#eef6ff;color:#1b84ff}.preinstall-page .state-badge.state-failed{background:#fff5f8;color:#f1416c}.preinstall-page .state-badge.state-open{background:#e8fff3;color:#17c653}.preinstall-page .state-badge.state-approvalPending{background:#fff8dd;color:#f6c000}.preinstall-page .state-badge.state-approved{background:#e8fff3;color:#17c653}.preinstall-page .state-panel .state-box{border:1px solid #e9ecef;border-radius:8px;padding:16px 20px;opacity:0;transform:translateY(4px);animation:preinstallFade .25s ease forwards}.preinstall-page .state-panel .state-box.state-box-danger{border-color:#ffd6e1;background:#fff9fb}.preinstall-page .state-panel .state-box.state-box-success{border-color:#c8f2d8;background:#f6fffa}.preinstall-page .version-list .version-row{padding:10px 0;border-bottom:1px dashed #e9ecef}.preinstall-page .version-list .version-row:last-child{border-bottom:none}.preinstall-page .detail-grid .detail-row{display:flex;justify-content:space-between;gap:12px;padding:7px 0;border-bottom:1px dashed #f1f3f5;font-size:13px}.preinstall-page .detail-grid .detail-row:last-child{border-bottom:none}.preinstall-page .activity-list{max-height:420px;overflow-y:auto}.preinstall-page .activity-list .activity-row{display:flex;gap:10px;padding:8px 0}.preinstall-page .activity-list .activity-row .activity-dot{width:8px;height:8px;border-radius:50%;background:#1b84ff;margin-top:6px;flex-shrink:0}@keyframes preinstallFade{to{opacity:1;transform:translateY(0)}}@media (prefers-reduced-motion: reduce){.preinstall-page .state-panel .state-box{animation:none;opacity:1;transform:none}}.preinstall-page .bi-arrow-clockwise{display:inline-block;line-height:1}.preinstall-page .bi-arrow-clockwise:before{display:inline-block;transform-origin:50% 50%}.preinstall-page .bi-arrow-clockwise.spinning:before{animation:preinstallSpin .8s linear infinite}@keyframes preinstallSpin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion: reduce){.preinstall-page .bi-arrow-clockwise.spinning:before{animation:none}}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i4.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i4.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "directive", type: i1$2.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "tooltipContext", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "pipe", type: i4.DatePipe, name: "date" }] });
|
|
4320
4320
|
}
|
|
4321
4321
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PreinstallationInfoComponent, decorators: [{
|
|
4322
4322
|
type: Component,
|
|
4323
|
-
args: [{ selector: 'lib-preinstallation-info', template: "<div class=\"container-fluid p-5 preinstall-page\">\n\n <!-- Header -->\n <div class=\"card mb-5\">\n <div class=\"card-body d-flex flex-wrap align-items-center justify-content-between gap-4 py-4\">\n <div class=\"d-flex align-items-center gap-4\">\n <button type=\"button\" class=\"btn btn-sm btn-light back-btn\" (click)=\"back()\" aria-label=\"Back to workspace\">\n <i class=\"bi bi-arrow-left\"></i>\n </button>\n <div>\n <div class=\"d-flex align-items-center gap-3\">\n <h4 class=\"mb-0\">{{ ticketInfo?.ticketId || ticketId }}</h4>\n <span class=\"badge state-badge\" [ngClass]=\"'state-' + placementState\">\n {{\n placementState === 'waitingLayout' ? 'Waiting for layout' :\n placementState === 'processing' ? 'Auto placement in progress' :\n placementState === 'failed' ? 'Placement failed' :\n placementState === 'open' ? 'Ready for placement review' :\n placementState === 'approvalPending' ? 'Waiting for approval' :\n placementState === 'approved' ? 'Approved' :\n placementState === 'unavailable' ? 'Status unavailable' : 'Loading'\n }}\n </span>\n </div>\n <div class=\"text-muted fs-7 mt-1\">\n Pre-Installation, camera placement\n <span *ngIf=\"ticketInfo?.basicDetails?.storeName\">, {{ ticketInfo?.basicDetails?.storeName }}</span>\n <span>, Floor {{ floorNumber }}</span>\n </div>\n </div>\n </div>\n <div class=\"d-flex align-items-center gap-3\">\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"refresh()\">\n <i class=\"bi bi-arrow-clockwise me-1\" [class.spinning]=\"reloading || cctvLoading\"></i>Refresh\n </button>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"loading\" class=\"text-center py-10 text-muted\">Loading ticket...</div>\n\n <div *ngIf=\"!loading && ticketInfo\" class=\"row g-5\">\n\n <!-- Placement state / action panel -->\n <div class=\"col-12 col-lg-7\">\n <div class=\"card h-100\">\n <div class=\"card-body\">\n <div class=\"card-head mb-4\">\n <h5 class=\"mb-0\">Camera placement</h5>\n <!-- The imported drawing itself, for the internal team to inspect in\n CAD when the engine cannot handle it or before editing. -->\n <a *ngIf=\"sourceDxfUrl\" [href]=\"sourceDxfUrl\" target=\"_blank\" rel=\"noopener\"\n class=\"btn btn-sm btn-light row-btn\" [ngbTooltip]=\"sourceDxfName\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M12 3v12m0 0 4-4m-4 4-4-4M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <span class=\"ms-1\">Download source DXF</span>\n </a>\n </div>\n\n <div [ngSwitch]=\"placementState\" class=\"state-panel\">\n\n <div *ngSwitchCase=\"'waitingLayout'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">Waiting for the CAD layout.</p>\n <p class=\"text-muted mb-0\">The store's floor drawing has not been imported yet. Auto placement starts right after the CAD import.</p>\n </div>\n\n <div *ngSwitchCase=\"'processing'\" class=\"state-box\">\n <div class=\"d-flex align-items-center gap-3 mb-1\">\n <span class=\"spinner-border spinner-border-sm text-primary\" role=\"status\" aria-hidden=\"true\"></span>\n <p class=\"mb-0 fw-semibold\">Auto camera placement is running.</p>\n </div>\n <p class=\"text-muted mb-3\">The DXF editor unlocks when placement completes. Use Refresh to check again. Meanwhile you can look at the source drawing.</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"openPreview()\">\n <i class=\"bi bi-eye me-1\"></i>View source drawing\n </button>\n </div>\n\n <div *ngSwitchCase=\"'failed'\" class=\"state-box state-box-danger\">\n <p class=\"mb-1 fw-semibold\">Auto placement failed.</p>\n <p class=\"text-muted mb-3\">{{ placement?.errorMsg || cctvRow?.errorMsg || 'The placement engine reported a failure.' }}</p>\n <!-- Retry hidden until the autoPlace Lambda exists (LAMBDAURL.autoPlace is empty).\n Re-enable by removing this comment; retryPlacement() is still wired in the component.\n <button type=\"button\" class=\"btn btn-sm btn-primary row-btn\" [disabled]=\"retrying\" (click)=\"retryPlacement()\">\n <span *ngIf=\"retrying\" class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>\n {{ retrying ? 'Retrying...' : 'Retry auto placement' }}\n </button>\n -->\n </div>\n\n <div *ngSwitchCase=\"'open'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">The drawing is ready for camera review.</p>\n <p class=\"text-muted mb-3\">\n Adjust the auto-placed cameras in the DXF editor, then submit for approval.\n <span *ngIf=\"cctvRow?.isRework\" class=\"text-warning fw-semibold\">This floor was sent back for rework.</span>\n </p>\n <button type=\"button\" class=\"btn btn-sm btn-primary row-btn\" (click)=\"openEditor()\">\n <i class=\"bi bi-pencil-square me-1\"></i>Open DXF editor\n </button>\n </div>\n\n <div *ngSwitchCase=\"'approvalPending'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">Submitted, waiting for approval.</p>\n <p class=\"text-muted mb-3\">The approval team reviews it from the onboard table. You can still view the drawing.</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"openEditor()\">\n <i class=\"bi bi-eye me-1\"></i>View drawing\n </button>\n </div>\n\n <div *ngSwitchCase=\"'approved'\" class=\"state-box state-box-success\">\n <p class=\"mb-1 fw-semibold\">Camera placement approved.</p>\n <p class=\"text-muted mb-0\">This ticket is closed. The installation ticket takes over once every floor of the store is approved.</p>\n </div>\n\n <div *ngSwitchCase=\"'unavailable'\" class=\"state-box state-box-danger\">\n <p class=\"mb-1 fw-semibold\">Placement status unavailable.</p>\n <p class=\"text-muted mb-3\">{{ cctvError }}</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"loadCctvDetail()\">Try again</button>\n </div>\n\n <div *ngSwitchDefault class=\"state-box\">\n <p class=\"text-muted mb-0\">Loading placement status...</p>\n </div>\n </div>\n\n <!-- Version timeline -->\n <div *ngIf=\"versions.length\" class=\"mt-6\">\n <h6 class=\"text-muted mb-3\">Drawing versions</h6>\n <div class=\"version-list\">\n <div class=\"version-row d-flex align-items-center justify-content-between\" *ngFor=\"let file of versions\">\n <div>\n <span class=\"fw-semibold\">v{{ file.version }}</span>\n <span class=\"text-muted ms-2 fs-7\">{{ file.kind === 'auto' ? 'Auto placement' : file.kind === 'approver' ? 'Approver edit' : 'Internal edit' }}</span>\n <span class=\"text-muted ms-2 fs-7\" *ngIf=\"file.cameraCount != null\">{{ file.cameraCount }} cameras</span>\n </div>\n <div class=\"d-flex align-items-center gap-3\">\n <span class=\"text-muted fs-7\">{{ file.uploadedAt | date: 'dd MMM, y HH:mm' }}</span>\n <a *ngIf=\"fileUrls[file.key]\" [href]=\"fileUrls[file.key]\" target=\"_blank\" rel=\"noopener\" class=\"btn btn-sm btn-light row-btn\">\n <i class=\"bi bi-download\"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Ticket info + activity -->\n <div class=\"col-12 col-lg-5\">\n <div class=\"card mb-5\">\n <div class=\"card-body\">\n <h5 class=\"mb-4\">Ticket details</h5>\n <div class=\"detail-grid\">\n <div class=\"detail-row\"><span class=\"text-muted\">Store</span><span>{{ ticketInfo?.basicDetails?.storeName || '-' }} ({{ ticketInfo?.basicDetails?.storeId || storeId }})</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Brand</span><span>{{ ticketInfo?.basicDetails?.clientName || '-' }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Floor</span><span>Floor {{ floorNumber }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Ticket status</span><span class=\"text-capitalize\">{{ ticketInfo?.status || '-' }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Created</span><span>{{ ticketInfo?.createdAt | date: 'dd MMM, y HH:mm' }}</span></div>\n <div class=\"detail-row\" *ngIf=\"cctvRow?.assigneeName\"><span class=\"text-muted\">Assignee</span><span>{{ cctvRow?.assigneeName }}</span></div>\n <div class=\"detail-row\" *ngIf=\"cctvRow?.reworkCount\"><span class=\"text-muted\">Rework count</span><span>{{ cctvRow?.reworkCount }}</span></div>\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-body\">\n <h5 class=\"mb-4\">Activity</h5>\n <div *ngIf=\"!activity.length\" class=\"text-muted fs-7\">No activity yet.</div>\n <div class=\"activity-list\">\n <div class=\"activity-row\" *ngFor=\"let entry of activity\">\n <div class=\"activity-dot\" aria-hidden=\"true\"></div>\n <div class=\"flex-grow-1\">\n <div class=\"d-flex justify-content-between gap-3\">\n <span class=\"fw-semibold fs-7\">{{ entry.description || entry.actionType }}</span>\n <span class=\"text-muted fs-8 text-nowrap\">{{ entry.timeStamp | date: 'dd MMM, HH:mm' }}</span>\n </div>\n <div class=\"text-muted fs-8\" *ngIf=\"entry.comment\">{{ entry.comment }}</div>\n <div class=\"text-muted fs-8\" *ngIf=\"entry.IdentifiedBy && entry.IdentifiedBy !== 'Tango'\">by {{ entry.IdentifiedBy }}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".preinstall-page .back-btn,.preinstall-page .card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.preinstall-page .back-btn .row-btn,.preinstall-page .card-head .row-btn{display:inline-flex;align-items:center;white-space:nowrap}.preinstall-page .row-btn{height:40px;display:inline-flex;align-items:center}.preinstall-page .state-badge{padding:6px 12px;font-weight:600;border-radius:999px}.preinstall-page .state-badge.state-waitingLayout,.preinstall-page .state-badge.state-loading,.preinstall-page .state-badge.state-unavailable{background:#f1f3f5;color:#5e6278}.preinstall-page .state-badge.state-processing{background:#eef6ff;color:#1b84ff}.preinstall-page .state-badge.state-failed{background:#fff5f8;color:#f1416c}.preinstall-page .state-badge.state-open{background:#e8fff3;color:#17c653}.preinstall-page .state-badge.state-approvalPending{background:#fff8dd;color:#f6c000}.preinstall-page .state-badge.state-approved{background:#e8fff3;color:#17c653}.preinstall-page .state-panel .state-box{border:1px solid #e9ecef;border-radius:8px;padding:16px 20px;opacity:0;transform:translateY(4px);animation:preinstallFade .25s ease forwards}.preinstall-page .state-panel .state-box.state-box-danger{border-color:#ffd6e1;background:#fff9fb}.preinstall-page .state-panel .state-box.state-box-success{border-color:#c8f2d8;background:#f6fffa}.preinstall-page .version-list .version-row{padding:10px 0;border-bottom:1px dashed #e9ecef}.preinstall-page .version-list .version-row:last-child{border-bottom:none}.preinstall-page .detail-grid .detail-row{display:flex;justify-content:space-between;gap:12px;padding:7px 0;border-bottom:1px dashed #f1f3f5;font-size:13px}.preinstall-page .detail-grid .detail-row:last-child{border-bottom:none}.preinstall-page .activity-list{max-height:420px;overflow-y:auto}.preinstall-page .activity-list .activity-row{display:flex;gap:10px;padding:8px 0}.preinstall-page .activity-list .activity-row .activity-dot{width:8px;height:8px;border-radius:50%;background:#1b84ff;margin-top:6px;flex-shrink:0}@keyframes preinstallFade{to{opacity:1;transform:translateY(0)}}@media (prefers-reduced-motion: reduce){.preinstall-page .state-panel .state-box{animation:none;opacity:1;transform:none}}.preinstall-page .bi-arrow-clockwise{display:inline-block;line-height:1}.preinstall-page .bi-arrow-clockwise:before{display:inline-block;transform-origin:50% 50%}.preinstall-page .bi-arrow-clockwise.spinning:before{animation:preinstallSpin .8s linear infinite}@keyframes preinstallSpin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion: reduce){.preinstall-page .bi-arrow-clockwise.spinning:before{animation:none}}\n"] }]
|
|
4323
|
+
args: [{ selector: 'lib-preinstallation-info', template: "<div class=\"container-fluid p-5 preinstall-page\">\n\n <!-- Header -->\n <div class=\"card mb-5\">\n <div class=\"card-body d-flex flex-wrap align-items-center justify-content-between gap-4 py-4\">\n <div class=\"d-flex align-items-center gap-4\">\n <button type=\"button\" class=\"btn btn-sm btn-light back-btn\" (click)=\"back()\" aria-label=\"Back to workspace\">\n <i class=\"bi bi-arrow-left\"></i>\n </button>\n <div>\n <div class=\"d-flex align-items-center gap-3\">\n <h4 class=\"mb-0\">{{ ticketInfo?.ticketId || ticketId }}</h4>\n <span class=\"badge state-badge\" [ngClass]=\"'state-' + placementState\">\n {{\n placementState === 'waitingLayout' ? 'Waiting for layout' :\n placementState === 'processing' ? 'Auto placement in progress' :\n placementState === 'failed' ? 'Placement failed' :\n placementState === 'open' ? 'Ready for placement review' :\n placementState === 'approvalPending' ? 'Waiting for approval' :\n placementState === 'approved' ? 'Approved' :\n placementState === 'unavailable' ? 'Status unavailable' : 'Loading'\n }}\n </span>\n </div>\n <div class=\"text-muted fs-7 mt-1\">\n Pre-Installation, camera placement\n <span *ngIf=\"ticketInfo?.basicDetails?.storeName\">, {{ ticketInfo?.basicDetails?.storeName }}</span>\n <span>, Floor {{ floorNumber }}</span>\n </div>\n </div>\n </div>\n <div class=\"d-flex align-items-center gap-3\">\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"refresh()\">\n <i class=\"bi bi-arrow-clockwise me-1\" [class.spinning]=\"reloading || cctvLoading\"></i>Refresh\n </button>\n </div>\n </div>\n </div>\n\n <div *ngIf=\"loading\" class=\"text-center py-10 text-muted\">Loading ticket...</div>\n\n <div *ngIf=\"!loading && ticketInfo\" class=\"row g-5\">\n\n <!-- Placement state / action panel -->\n <div class=\"col-12 col-lg-7\">\n <div class=\"card h-100\">\n <div class=\"card-body\">\n <div class=\"card-head mb-4\">\n <h5 class=\"mb-0\">Camera placement</h5>\n <!-- The imported drawing itself, for the internal team to inspect in\n CAD when the engine cannot handle it or before editing. -->\n <a *ngIf=\"sourceDxfUrl\" [href]=\"sourceDxfUrl\" target=\"_blank\" rel=\"noopener\"\n class=\"btn btn-sm btn-light row-btn\" [ngbTooltip]=\"sourceDxfName\">\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M12 3v12m0 0 4-4m-4 4-4-4M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\n stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n <span class=\"ms-1\">Download source DXF</span>\n </a>\n </div>\n\n <div [ngSwitch]=\"placementState\" class=\"state-panel\">\n\n <div *ngSwitchCase=\"'waitingLayout'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">Waiting for the CAD layout.</p>\n <p class=\"text-muted mb-0\">The store's floor drawing has not been imported yet. Auto placement starts right after the CAD import.</p>\n </div>\n\n <div *ngSwitchCase=\"'processing'\" class=\"state-box\">\n <div class=\"d-flex align-items-center gap-3 mb-1\">\n <span class=\"spinner-border spinner-border-sm text-primary\" role=\"status\" aria-hidden=\"true\"></span>\n <p class=\"mb-0 fw-semibold\">Auto camera placement is running.</p>\n </div>\n <p class=\"text-muted mb-3\">The DXF editor unlocks when placement completes. Use Refresh to check again. Meanwhile you can look at the source drawing.</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"openPreview()\">\n <i class=\"bi bi-eye me-1\"></i>View source drawing\n </button>\n </div>\n\n <div *ngSwitchCase=\"'failed'\" class=\"state-box state-box-danger\">\n <p class=\"mb-1 fw-semibold\">Auto placement failed.</p>\n <p class=\"text-muted mb-3\">{{ placement?.errorMsg || cctvRow?.errorMsg || 'The placement engine reported a failure.' }}</p>\n <!-- Retry hidden until the autoPlace Lambda exists (LAMBDAURL.autoPlace is empty).\n Re-enable by removing this comment; retryPlacement() is still wired in the component.\n <button type=\"button\" class=\"btn btn-sm btn-primary row-btn\" [disabled]=\"retrying\" (click)=\"retryPlacement()\">\n <span *ngIf=\"retrying\" class=\"spinner-border spinner-border-sm me-2\" role=\"status\" aria-hidden=\"true\"></span>\n {{ retrying ? 'Retrying...' : 'Retry auto placement' }}\n </button>\n -->\n </div>\n\n <div *ngSwitchCase=\"'open'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">The drawing is ready for camera review.</p>\n <p class=\"text-muted mb-3\">\n Adjust the auto-placed cameras in the DXF editor, then submit for approval.\n <span *ngIf=\"cctvRow?.isRework\" class=\"text-warning fw-semibold\">This floor was sent back for rework.</span>\n </p>\n <button type=\"button\" class=\"btn btn-sm btn-primary row-btn\" (click)=\"openEditor()\">\n <i class=\"bi bi-pencil-square me-1\"></i>Open DXF editor\n </button>\n </div>\n\n <div *ngSwitchCase=\"'approvalPending'\" class=\"state-box\">\n <p class=\"mb-1 fw-semibold\">Submitted, waiting for approval.</p>\n <p class=\"text-muted mb-3\">The approval team reviews it from the onboard table. You can still view the drawing.</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"openEditor()\">\n <i class=\"bi bi-eye me-1\"></i>View drawing\n </button>\n </div>\n\n <div *ngSwitchCase=\"'approved'\" class=\"state-box state-box-success\">\n <p class=\"mb-1 fw-semibold\">Camera placement approved.</p>\n <p class=\"text-muted mb-0\">This ticket is closed. The installation ticket takes over once every floor of the store is approved.</p>\n </div>\n\n <div *ngSwitchCase=\"'unavailable'\" class=\"state-box state-box-danger\">\n <p class=\"mb-1 fw-semibold\">Placement status unavailable.</p>\n <p class=\"text-muted mb-3\">{{ cctvError }}</p>\n <button type=\"button\" class=\"btn btn-sm btn-light row-btn\" (click)=\"loadCctvDetail()\">Try again</button>\n </div>\n\n <div *ngSwitchDefault class=\"state-box\">\n <p class=\"text-muted mb-0\">Loading placement status...</p>\n </div>\n </div>\n\n <!-- Version timeline -->\n <div *ngIf=\"versions.length\" class=\"mt-6\">\n <h6 class=\"text-muted mb-3\">Drawing versions</h6>\n <div class=\"version-list\">\n <div class=\"version-row d-flex align-items-center justify-content-between\" *ngFor=\"let file of versions\">\n <div>\n <span class=\"fw-semibold\">v{{ file.version }}</span>\n <span class=\"text-muted ms-2 fs-7\">{{ file.kind === 'auto' ? 'Auto placement' : file.kind === 'approver' ? 'Approver edit' : 'Internal edit' }}</span>\n <span class=\"text-muted ms-2 fs-7\" *ngIf=\"file.cameraCount != null\">{{ file.cameraCount }} cameras</span>\n </div>\n <div class=\"d-flex align-items-center gap-3\">\n <span class=\"text-muted fs-7\">{{ file.uploadedAt | date: 'dd MMM, y h:mm a' }}</span>\n <a *ngIf=\"fileUrls[file.key]\" [href]=\"fileUrls[file.key]\" target=\"_blank\" rel=\"noopener\" class=\"btn btn-sm btn-light row-btn\">\n <i class=\"bi bi-download\"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Ticket info + activity -->\n <div class=\"col-12 col-lg-5\">\n <div class=\"card mb-5\">\n <div class=\"card-body\">\n <h5 class=\"mb-4\">Ticket details</h5>\n <div class=\"detail-grid\">\n <div class=\"detail-row\"><span class=\"text-muted\">Store</span><span>{{ ticketInfo?.basicDetails?.storeName || '-' }} ({{ ticketInfo?.basicDetails?.storeId || storeId }})</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Brand</span><span>{{ ticketInfo?.basicDetails?.clientName || '-' }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Floor</span><span>Floor {{ floorNumber }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Ticket status</span><span class=\"text-capitalize\">{{ ticketInfo?.status || '-' }}</span></div>\n <div class=\"detail-row\"><span class=\"text-muted\">Created</span><span>{{ ticketInfo?.createdAt | date: 'dd MMM, y h:mm a' }}</span></div>\n <div class=\"detail-row\" *ngIf=\"cctvRow?.assigneeName\"><span class=\"text-muted\">Assignee</span><span>{{ cctvRow?.assigneeName }}</span></div>\n <div class=\"detail-row\" *ngIf=\"cctvRow?.reworkCount\"><span class=\"text-muted\">Rework count</span><span>{{ cctvRow?.reworkCount }}</span></div>\n </div>\n </div>\n </div>\n\n <div class=\"card\">\n <div class=\"card-body\">\n <h5 class=\"mb-4\">Activity</h5>\n <div *ngIf=\"!activity.length\" class=\"text-muted fs-7\">No activity yet.</div>\n <div class=\"activity-list\">\n <div class=\"activity-row\" *ngFor=\"let entry of activity\">\n <div class=\"activity-dot\" aria-hidden=\"true\"></div>\n <div class=\"flex-grow-1\">\n <div class=\"d-flex justify-content-between gap-3\">\n <span class=\"fw-semibold fs-7\">{{ entry.description || entry.actionType }}</span>\n <span class=\"text-muted fs-8 text-nowrap\">{{ entry.timeStamp | date: 'dd MMM, h:mm a' }}</span>\n </div>\n <div class=\"text-muted fs-8\" *ngIf=\"entry.comment\">{{ entry.comment }}</div>\n <div class=\"text-muted fs-8\" *ngIf=\"entry.IdentifiedBy && entry.IdentifiedBy !== 'Tango'\">by {{ entry.IdentifiedBy }}</div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n</div>\n", styles: [".preinstall-page .back-btn,.preinstall-page .card-head{display:flex;align-items:center;justify-content:space-between;gap:12px}.preinstall-page .back-btn .row-btn,.preinstall-page .card-head .row-btn{display:inline-flex;align-items:center;white-space:nowrap}.preinstall-page .row-btn{height:40px;display:inline-flex;align-items:center}.preinstall-page .state-badge{padding:6px 12px;font-weight:600;border-radius:999px}.preinstall-page .state-badge.state-waitingLayout,.preinstall-page .state-badge.state-loading,.preinstall-page .state-badge.state-unavailable{background:#f1f3f5;color:#5e6278}.preinstall-page .state-badge.state-processing{background:#eef6ff;color:#1b84ff}.preinstall-page .state-badge.state-failed{background:#fff5f8;color:#f1416c}.preinstall-page .state-badge.state-open{background:#e8fff3;color:#17c653}.preinstall-page .state-badge.state-approvalPending{background:#fff8dd;color:#f6c000}.preinstall-page .state-badge.state-approved{background:#e8fff3;color:#17c653}.preinstall-page .state-panel .state-box{border:1px solid #e9ecef;border-radius:8px;padding:16px 20px;opacity:0;transform:translateY(4px);animation:preinstallFade .25s ease forwards}.preinstall-page .state-panel .state-box.state-box-danger{border-color:#ffd6e1;background:#fff9fb}.preinstall-page .state-panel .state-box.state-box-success{border-color:#c8f2d8;background:#f6fffa}.preinstall-page .version-list .version-row{padding:10px 0;border-bottom:1px dashed #e9ecef}.preinstall-page .version-list .version-row:last-child{border-bottom:none}.preinstall-page .detail-grid .detail-row{display:flex;justify-content:space-between;gap:12px;padding:7px 0;border-bottom:1px dashed #f1f3f5;font-size:13px}.preinstall-page .detail-grid .detail-row:last-child{border-bottom:none}.preinstall-page .activity-list{max-height:420px;overflow-y:auto}.preinstall-page .activity-list .activity-row{display:flex;gap:10px;padding:8px 0}.preinstall-page .activity-list .activity-row .activity-dot{width:8px;height:8px;border-radius:50%;background:#1b84ff;margin-top:6px;flex-shrink:0}@keyframes preinstallFade{to{opacity:1;transform:translateY(0)}}@media (prefers-reduced-motion: reduce){.preinstall-page .state-panel .state-box{animation:none;opacity:1;transform:none}}.preinstall-page .bi-arrow-clockwise{display:inline-block;line-height:1}.preinstall-page .bi-arrow-clockwise:before{display:inline-block;transform-origin:50% 50%}.preinstall-page .bi-arrow-clockwise.spinning:before{animation:preinstallSpin .8s linear infinite}@keyframes preinstallSpin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion: reduce){.preinstall-page .bi-arrow-clockwise.spinning:before{animation:none}}\n"] }]
|
|
4324
4324
|
}], ctorParameters: () => [{ type: i1$1.ActivatedRoute }, { type: i1$1.Router }, { type: TicketsService }, { type: i3.ToastService }] });
|
|
4325
4325
|
|
|
4326
4326
|
const routes = [
|