@jcbautistam/custom-table
Version:
Librería de tabla reutilizable con acciones, filtros, exportación y más.
262 lines • 33.6 kB
JavaScript
import { Injectable } from '@angular/core';
import { BehaviorSubject, interval } from 'rxjs';
import { take, map } from 'rxjs/operators';
import * as i0 from "@angular/core";
export class ExportNotificationService {
constructor() {
this.defaultStatus = {
isExporting: false,
activeJobs: [],
showNotification: false
};
this.exportStatusSubject = new BehaviorSubject(this.defaultStatus);
this.exportStatus$ = this.exportStatusSubject.asObservable();
}
/**
* Inicia una nueva exportación y retorna su ID
*/
startExport(fileName) {
const jobId = this.generateJobId();
const currentStatus = this.exportStatusSubject.value;
const newJob = {
id: jobId,
fileName,
progress: 0,
isCompleted: false,
error: null,
timestamp: Date.now(),
progressAnimation: null
};
// Añadir el nuevo trabajo a la lista de trabajos activos
const updatedJobs = [...currentStatus.activeJobs, newJob];
this.exportStatusSubject.next({
isExporting: true,
activeJobs: updatedJobs,
showNotification: true
});
// Iniciar la animación de progreso hasta el 10%
this.animateProgressTo(jobId, 0, 10, 800);
return jobId;
}
/**
* Actualiza el progreso de una exportación específica
*/
updateProgress(jobId, targetProgress) {
const currentStatus = this.exportStatusSubject.value;
const job = currentStatus.activeJobs.find(j => j.id === jobId);
if (job) {
// Detener cualquier animación previa
this.stopAnimation(job);
// Animar desde el progreso actual hasta el objetivo
const currentProgress = job.progress;
this.animateProgressTo(jobId, currentProgress, targetProgress, 1000);
}
}
/**
* Detiene de forma segura una animación
*/
stopAnimation(job) {
if (job && job.progressAnimation) {
try {
job.progressAnimation.unsubscribe();
job.progressAnimation = null;
}
catch (error) {
console.error('Error al detener animación:', error);
}
}
}
/**
* Anima el progreso de una forma más realista
*/
animateProgressTo(jobId, fromProgress, toProgress, duration) {
// Obtener estado actual
const currentStatus = this.exportStatusSubject.value;
const jobIndex = currentStatus.activeJobs.findIndex(j => j.id === jobId);
if (jobIndex === -1)
return;
const job = currentStatus.activeJobs[jobIndex];
// Detener animación previa si existe
this.stopAnimation(job);
// Calcular cuántos pasos necesitamos
const steps = Math.max(Math.ceil(duration / 50), 5); // Al menos 5 pasos
const stepValue = (toProgress - fromProgress) / steps;
// Crear una animación con interval
const animation = interval(duration / steps).pipe(take(steps), map(step => fromProgress + stepValue * (step + 1))).subscribe({
next: (progress) => {
// Obtener el estado actual
const updatedStatus = this.exportStatusSubject.value;
const currentJobIndex = updatedStatus.activeJobs.findIndex(j => j.id === jobId);
if (currentJobIndex !== -1) {
// Crear una copia de los trabajos
const updatedJobs = [...updatedStatus.activeJobs];
// Actualizar el progreso del trabajo específico
updatedJobs[currentJobIndex] = {
...updatedJobs[currentJobIndex],
progress: progress
};
// Actualizar el estado
this.exportStatusSubject.next({
...updatedStatus,
activeJobs: updatedJobs
});
// Limpiar la suscripción cuando llegamos al último paso
if (progress >= toProgress - stepValue / 2) {
this.stopAnimation(updatedJobs[currentJobIndex]);
}
}
},
error: (err) => {
console.error('Error en animación:', err);
},
complete: () => {
// Completar la animación
}
});
// Guardar la animación en el job
const updatedJobs = [...currentStatus.activeJobs];
updatedJobs[jobIndex] = {
...updatedJobs[jobIndex],
progressAnimation: animation
};
this.exportStatusSubject.next({
...currentStatus,
activeJobs: updatedJobs
});
}
/**
* Marca una exportación como completada
*/
completeExport(jobId) {
const currentStatus = this.exportStatusSubject.value;
const jobIndex = currentStatus.activeJobs.findIndex(j => j.id === jobId);
if (jobIndex !== -1) {
const job = currentStatus.activeJobs[jobIndex];
// Detener cualquier animación en curso
this.stopAnimation(job);
// Animar al 100% para completar
this.animateProgressTo(jobId, job.progress, 100, 500);
// Actualizar el estado a completado
const updatedJobs = currentStatus.activeJobs.map(job => {
if (job.id === jobId) {
return {
...job,
isCompleted: true
};
}
return job;
});
this.exportStatusSubject.next({
...currentStatus,
activeJobs: updatedJobs,
isExporting: updatedJobs.some(job => !job.isCompleted && !job.error)
});
// Programar la eliminación del trabajo completado después de cierto tiempo
setTimeout(() => {
this.removeJob(jobId);
}, 5000);
}
}
/**
* Marca una exportación como fallida
*/
errorExport(jobId, error) {
console.error('Error en la exportación:', error);
const currentStatus = this.exportStatusSubject.value;
const jobIndex = currentStatus.activeJobs.findIndex(j => j.id === jobId);
if (jobIndex !== -1) {
const job = currentStatus.activeJobs[jobIndex];
// Detener cualquier animación en curso
this.stopAnimation(job);
const updatedJobs = currentStatus.activeJobs.map(job => {
if (job.id === jobId) {
return {
...job,
error: error.message || 'Error al exportar',
isCompleted: true
};
}
return job;
});
this.exportStatusSubject.next({
...currentStatus,
activeJobs: updatedJobs,
isExporting: updatedJobs.some(job => !job.isCompleted && !job.error)
});
// Programar la eliminación del trabajo fallido después de cierto tiempo
setTimeout(() => {
this.removeJob(jobId);
}, 5000);
}
}
/**
* Elimina un trabajo de la lista de trabajos activos
*/
removeJob(jobId) {
const currentStatus = this.exportStatusSubject.value;
const jobIndex = currentStatus.activeJobs.findIndex(j => j.id === jobId);
if (jobIndex !== -1) {
const job = currentStatus.activeJobs[jobIndex];
// Detener cualquier animación en curso
this.stopAnimation(job);
const updatedJobs = currentStatus.activeJobs.filter(job => job.id !== jobId);
if (updatedJobs.length === 0) {
// Si no hay más trabajos, ocultar la notificación
this.exportStatusSubject.next({
isExporting: false,
activeJobs: [],
showNotification: false
});
}
else {
// Si aún hay trabajos, actualizar la lista
this.exportStatusSubject.next({
...currentStatus,
activeJobs: updatedJobs,
isExporting: updatedJobs.some(job => !job.isCompleted && !job.error)
});
}
}
}
/**
* Oculta la notificación manualmente
*/
hideNotification() {
const currentStatus = this.exportStatusSubject.value;
// Detener todas las animaciones en curso
currentStatus.activeJobs.forEach(job => {
this.stopAnimation(job);
});
this.exportStatusSubject.next({
...currentStatus,
showNotification: false
});
}
/**
* Muestra la notificación si estaba oculta
*/
showNotification() {
const currentStatus = this.exportStatusSubject.value;
if (currentStatus.activeJobs.length > 0) {
this.exportStatusSubject.next({
...currentStatus,
showNotification: true
});
}
}
/**
* Genera un ID único para cada trabajo
*/
generateJobId() {
return 'export-' + Date.now() + '-' + Math.floor(Math.random() * 1000);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: ExportNotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: ExportNotificationService, providedIn: 'root' }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.2", ngImport: i0, type: ExportNotificationService, decorators: [{
type: Injectable,
args: [{
providedIn: 'root'
}]
}], ctorParameters: function () { return []; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhwb3J0Tm90aWZpY2F0aW9uLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jdXN0b20tdGFibGUvc3JjL2xpYi9TZXJ2aWNlcy9leHBvcnROb3RpZmljYXRpb24uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxlQUFlLEVBQWMsUUFBUSxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUMzRSxPQUFPLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDOztBQXFCM0MsTUFBTSxPQUFPLHlCQUF5QjtJQVVwQztRQVRRLGtCQUFhLEdBQWlCO1lBQ3BDLFdBQVcsRUFBRSxLQUFLO1lBQ2xCLFVBQVUsRUFBRSxFQUFFO1lBQ2QsZ0JBQWdCLEVBQUUsS0FBSztTQUN4QixDQUFDO1FBRU0sd0JBQW1CLEdBQUcsSUFBSSxlQUFlLENBQWUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQzdFLGtCQUFhLEdBQTZCLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUV6RSxDQUFDO0lBRWpCOztPQUVHO0lBQ0gsV0FBVyxDQUFDLFFBQWdCO1FBQzFCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUNuQyxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsS0FBSyxDQUFDO1FBRXJELE1BQU0sTUFBTSxHQUFjO1lBQ3hCLEVBQUUsRUFBRSxLQUFLO1lBQ1QsUUFBUTtZQUNSLFFBQVEsRUFBRSxDQUFDO1lBQ1gsV0FBVyxFQUFFLEtBQUs7WUFDbEIsS0FBSyxFQUFFLElBQUk7WUFDWCxTQUFTLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTtZQUNyQixpQkFBaUIsRUFBRSxJQUFJO1NBQ3hCLENBQUM7UUFFRix5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QUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ3pFLENBQUM7OEdBdFNVLHlCQUF5QjtrSEFBekIseUJBQXlCLGNBRnhCLE1BQU07OzJGQUVQLHlCQUF5QjtrQkFIckMsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSwgaW50ZXJ2YWwsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyB0YWtlLCBtYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIEV4cG9ydEpvYiB7XHJcbiAgaWQ6IHN0cmluZztcclxuICBmaWxlTmFtZTogc3RyaW5nO1xyXG4gIHByb2dyZXNzOiBudW1iZXI7XHJcbiAgaXNDb21wbGV0ZWQ6IGJvb2xlYW47XHJcbiAgZXJyb3I6IHN0cmluZyB8IG51bGw7XHJcbiAgdGltZXN0YW1wOiBudW1iZXI7XHJcbiAgcHJvZ3Jlc3NBbmltYXRpb24/OiBTdWJzY3JpcHRpb24gfCBudWxsO1xyXG59XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIEV4cG9ydFN0YXR1cyB7XHJcbiAgaXNFeHBvcnRpbmc6IGJvb2xlYW47XHJcbiAgYWN0aXZlSm9iczogRXhwb3J0Sm9iW107XHJcbiAgc2hvd05vdGlmaWNhdGlvbjogYm9vbGVhbjtcclxufVxyXG5cclxuQEluamVjdGFibGUoe1xyXG4gIHByb3ZpZGVkSW46ICdyb290J1xyXG59KVxyXG5leHBvcnQgY2xhc3MgRXhwb3J0Tm90aWZpY2F0aW9uU2VydmljZSB7XHJcbiAgcHJpdmF0ZSBkZWZhdWx0U3RhdHVzOiBFeHBvcnRTdGF0dXMgPSB7XHJcbiAgICBpc0V4cG9ydGluZzogZmFsc2UsXHJcbiAgICBhY3RpdmVKb2JzOiBbXSxcclxuICAgIHNob3dOb3RpZmljYXRpb246IGZhbHNlXHJcbiAgfTtcclxuXHJcbiAgcHJpdmF0ZSBleHBvcnRTdGF0dXNTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxFeHBvcnRTdGF0dXM+KHRoaXMuZGVmYXVsdFN0YXR1cyk7XHJcbiAgcHVibGljIGV4cG9ydFN0YXR1cyQ6IE9ic2VydmFibGU8RXhwb3J0U3RhdHVzPiA9IHRoaXMuZXhwb3J0U3RhdHVzU3ViamVjdC5hc09ic2VydmFibGUoKTtcclxuXHJcbiAgY29uc3RydWN0b3IoKSB7IH1cclxuXHJcbiAgLyoqXHJcbiAgICogSW5pY2lhIHVuYSBudWV2YSBleHBvcnRhY2nDs24geSByZXRvcm5hIHN1IElEXHJcbiAgICovXHJcbiAgc3RhcnRFeHBvcnQoZmlsZU5hbWU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBqb2JJZCA9IHRoaXMuZ2VuZXJhdGVKb2JJZCgpO1xyXG4gICAgY29uc3QgY3VycmVudFN0YXR1cyA9IHRoaXMuZXhwb3J0U3RhdHVzU3ViamVjdC52YWx1ZTtcclxuICAgIFxyXG4gICAgY29uc3QgbmV3Sm9iOiBFeHBvcnRKb2IgPSB7XHJcbiAgICAgIGlkOiBqb2JJZCxcclxuICAgICAgZmlsZU5hbWUsXHJcbiAgICAgIHByb2dyZXNzOiAwLFxyXG4gICAgICBpc0NvbXBsZXRlZDogZmFsc2UsXHJcbiAgICAgIGVycm9yOiBudWxsLFxyXG4gICAgICB0aW1lc3RhbXA6IERhdGUubm93KCksXHJcbiAgICAgIHByb2dyZXNzQW5pbWF0aW9uOiBudWxsXHJcbiAgICB9O1xyXG4gICAgXHJcbiAgICAvLyBBw7FhZGlyIGVsIG51ZXZvIHRyYWJham8gYSBsYSBsaXN0YSBkZSB0cmFiYWpvcyBhY3Rpdm9zXHJcbiAgICBjb25zdCB1cGRhdGVkSm9icyA9IFsuLi5jdXJyZW50U3RhdHVzLmFjdGl2ZUpvYnMsIG5ld0pvYl07XHJcbiAgICBcclxuICAgIHRoaXMuZXhwb3J0U3RhdHVzU3ViamVjdC5uZXh0KHtcclxuICAgICAgaXNFeHBvcnRpbmc6IHRydWUsXHJcbiAgICAgIGFjdGl2ZUpvYnM6IHVwZGF0ZWRKb2JzLFxyXG4gICAgICBzaG93Tm90aWZpY2F0aW9uOiB0cnVlXHJcbiAgICB9KTtcclxuICAgIFxyXG4gICAgLy8gSW5pY2lhciBsYSBhbmltYWNpw7NuIGRlIHByb2dyZXNvIGhhc3RhIGVsIDEwJVxyXG4gICAgdGhpcy5hbmltYXRlUHJvZ3Jlc3NUbyhqb2JJZCwgMCwgMTAsIDgwMCk7XHJcbiAgICBcclxuICAgIHJldHVybiBqb2JJZDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFjdHVhbGl6YSBlbCBwcm9ncmVzbyBkZSB1bmEgZXhwb3J0YWNpw7NuIGVzcGVjw61maWNhXHJcbiAgICovXHJcbiAgdXBkYXRlUHJvZ3Jlc3Moam9iSWQ6IHN0cmluZywgdGFyZ2V0UHJvZ3Jlc3M6IG51bWJlcik6IHZvaWQge1xyXG4gICAgY29uc3QgY3VycmVudFN0YXR1cyA9IHRoaXMuZXhwb3J0U3RhdHVzU3ViamVjdC52YWx1ZTtcclxuICAgIGNvbnN0IGpvYiA9IGN1cnJlbnRTdGF0dXMuYWN0aXZlSm9icy5maW5kKGogPT4gai5pZCA9PT0gam9iSWQpO1xyXG4gICAgXHJcbiAgICBpZiAoam9iKSB7XHJcbiAgICAgIC8vIERldGVuZXIgY3VhbHF1aWVyIGFuaW1hY2nDs24gcHJldmlhXHJcbiAgICAgIHRoaXMuc3RvcEFuaW1hdGlvbihqb2IpO1xyXG4gICAgICBcclxuICAgICAgLy8gQW5pbWFyIGRlc2RlIGVsIHByb2dyZXNvIGFjdHVhbCBoYXN0YSBlbCBvYmpldGl2b1xyXG4gICAgICBjb25zdCBjdXJyZW50UHJvZ3Jlc3MgPSBqb2IucHJvZ3Jlc3M7XHJcbiAgICAgIHRoaXMuYW5pbWF0ZVByb2dyZXNzVG8oam9iSWQsIGN1cnJlbnRQcm9ncmVzcywgdGFyZ2V0UHJvZ3Jlc3MsIDEwMDApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRGV0aWVuZSBkZSBmb3JtYSBzZWd1cmEgdW5hIGFuaW1hY2nDs25cclxuICAgKi9cclxuICBwcml2YXRlIHN0b3BBbmltYXRpb24oam9iOiBFeHBvcnRKb2IpOiB2b2lkIHtcclxuICAgIGlmIChqb2IgJiYgam9iLnByb2dyZXNzQW5pbWF0aW9uKSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgam9iLnByb2dyZXNzQW5pbWF0aW9uLnVuc3Vic2NyaWJlKCk7XHJcbiAgICAgICAgam9iLnByb2dyZXNzQW5pbWF0aW9uID0gbnVsbDtcclxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBhbCBkZXRlbmVyIGFuaW1hY2nDs246JywgZXJyb3IpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBbmltYSBlbCBwcm9ncmVzbyBkZSB1bmEgZm9ybWEgbcOhcyByZWFsaXN0YVxyXG4gICAqL1xyXG4gIHByaXZhdGUgYW5pbWF0ZVByb2dyZXNzVG8oam9iSWQ6IHN0cmluZywgZnJvbVByb2dyZXNzOiBudW1iZXIsIHRvUHJvZ3Jlc3M6IG51bWJlciwgZHVyYXRpb246IG51bWJlcik6IHZvaWQge1xyXG4gICAgLy8gT2J0ZW5lciBlc3RhZG8gYWN0dWFsXHJcbiAgICBjb25zdCBjdXJyZW50U3RhdHVzID0gdGhpcy5leHBvcnRTdGF0dXNTdWJqZWN0LnZhbHVlO1xyXG4gICAgY29uc3Qgam9iSW5kZXggPSBjdXJyZW50U3RhdHVzLmFjdGl2ZUpvYnMuZmluZEluZGV4KGogPT4gai5pZCA9PT0gam9iSWQpO1xyXG4gICAgXHJcbiAgICBpZiAoam9iSW5kZXggPT09IC0xKSByZXR1cm47XHJcbiAgICBcclxuICAgIGNvbnN0IGpvYiA9IGN1cnJlbnRTdGF0dXMuYWN0aXZlSm9ic1tqb2JJbmRleF07XHJcbiAgICBcclxuICAgIC8vIERldGVuZXIgYW5pbWFjacOzbiBwcmV2aWEgc2kgZXhpc3RlXHJcbiAgICB0aGlzLnN0b3BBbmltYXRpb24oam9iKTtcclxuICAgIFxyXG4gICAgLy8gQ2FsY3VsYXIgY3XDoW50b3MgcGFzb3MgbmVjZXNpdGFtb3NcclxuICAgIGNvbnN0IHN0ZXBzID0gTWF0aC5tYXgoTWF0aC5jZWlsKGR1cmF0aW9uIC8gNTApLCA1KTsgLy8gQWwgbWVub3MgNSBwYXNvc1xyXG4gICAgY29uc3Qgc3RlcFZhbHVlID0gKHRvUHJvZ3Jlc3MgLSBmcm9tUHJvZ3Jlc3MpIC8gc3RlcHM7XHJcbiAgICBcclxuICAgIC8vIENyZWFyIHVuYSBhbmltYWNpw7NuIGNvbiBpbnRlcnZhbFxyXG4gICAgY29uc3QgYW5pbWF0aW9uID0gaW50ZXJ2YWwoZHVyYXRpb24gLyBzdGVwcykucGlwZShcclxuICAgICAgdGFrZShzdGVwcyksXHJcbiAgICAgIG1hcChzdGVwID0+IGZyb21Qcm9ncmVzcyArIHN0ZXBWYWx1ZSAqIChzdGVwICsgMSkpXHJcbiAgICApLnN1YnNjcmliZSh7XHJcbiAgICAgIG5leHQ6IChwcm9ncmVzcykgPT4ge1xyXG4gICAgICAgIC8vIE9idGVuZXIgZWwgZXN0YWRvIGFjdHVhbFxyXG4gICAgICAgIGNvbnN0IHVwZGF0ZWRTdGF0dXMgPSB0aGlzLmV4cG9ydFN0YXR1c1N1YmplY3QudmFsdWU7XHJcbiAgICAgICAgY29uc3QgY3VycmVudEpvYkluZGV4ID0gdXBkYXRlZFN0YXR1cy5hY3RpdmVKb2JzLmZpbmRJbmRleChqID0+IGouaWQgPT09IGpvYklkKTtcclxuICAgICAgICBcclxuICAgICAgICBpZiAoY3VycmVudEpvYkluZGV4ICE9PSAtMSkge1xyXG4gICAgICAgICAgLy8gQ3JlYXIgdW5hIGNvcGlhIGRlIGxvcyB0cmFiYWpvc1xyXG4gICAgICAgICAgY29uc3QgdXBkYXRlZEpvYnMgPSBbLi4udXBkYXRlZFN0YXR1cy5hY3RpdmVKb2JzXTtcclxuICAgICAgICAgIFxyXG4gICAgICAgICAgLy8gQWN0dWFsaXphciBlbCBwcm9ncmVzbyBkZWwgdHJhYmFqbyBlc3BlY8OtZmljb1xyXG4gICAgICAgICAgdXBkYXRlZEpvYnNbY3VycmVudEpvYkluZGV4XSA9IHtcclxuICAgICAgICAgICAgLi4udXBkYXRlZEpvYnNbY3VycmVudEpvYkluZGV4XSxcclxuICAgICAgICAgICAgcHJvZ3Jlc3M6IHByb2dyZXNzXHJcbiAgICAgICAgICB9O1xyXG4gICAgICAgICAgXHJcbiAgICAgICAgICAvLyBBY3R1YWxpemFyIGVsIGVzdGFkb1xyXG4gICAgICAgICAgdGhpcy5leHBvcnRTdGF0dXNTdWJqZWN0Lm5leHQoe1xyXG4gICAgICAgICAgICAuLi51cGRhdGVkU3RhdHVzLFxyXG4gICAgICAgICAgICBhY3RpdmVKb2JzOiB1cGRhdGVkSm9ic1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgICBcclxuICAgICAgICAgIC8vIExpbXBpYXIgbGEgc3VzY3JpcGNpw7NuIGN1YW5kbyBsbGVnYW1vcyBhbCDDumx0aW1vIHBhc29cclxuICAgICAgICAgIGlmIChwcm9ncmVzcyA+PSB0b1Byb2dyZXNzIC0gc3RlcFZhbHVlLzIpIHtcclxuICAgICAgICAgICAgdGhpcy5zdG9wQW5pbWF0aW9uKHVwZGF0ZWRKb2JzW2N1cnJlbnRKb2JJbmRleF0pO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfSxcclxuICAgICAgZXJyb3I6IChlcnIpID0+IHtcclxuICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBlbiBhbmltYWNpw7NuOicsIGVycik7XHJcbiAgICAgIH0sXHJcbiAgICAgIGNvbXBsZXRlOiAoKSA9PiB7XHJcbiAgICAgICAgLy8gQ29tcGxldGFyIGxhIGFuaW1hY2nDs25cclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgICBcclxuICAgIC8vIEd1YXJkYXIgbGEgYW5pbWFjacOzbiBlbiBlbCBqb2JcclxuICAgIGNvbnN0IHVwZGF0ZWRKb2JzID0gWy4uLmN1cnJlbnRTdGF0dXMuYWN0aXZlSm9ic107XHJcbiAgICB1cGRhdGVkSm9ic1tqb2JJbmRleF0gPSB7XHJcbiAgICAgIC4uLnVwZGF0ZWRKb2JzW2pvYkluZGV4XSxcclxuICAgICAgcHJvZ3Jlc3NBbmltYXRpb246IGFuaW1hdGlvblxyXG4gICAgfTtcclxuICAgIFxyXG4gICAgdGhpcy5leHBvcnRTdGF0dXNTdWJqZWN0Lm5leHQoe1xyXG4gICAgICAuLi5jdXJyZW50U3RhdHVzLFxyXG4gICAgICBhY3RpdmVKb2JzOiB1cGRhdGVkSm9ic1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBNYXJjYSB1bmEgZXhwb3J0YWNpw7NuIGNvbW8gY29tcGxldGFkYVxyXG4gICAqL1xyXG4gIGNvbXBsZXRlRXhwb3J0KGpvYklkOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGNvbnN0IGN1cnJlbnRTdGF0dXMgPSB0aGlzLmV4cG9ydFN0YXR1c1N1YmplY3QudmFsdWU7XHJcbiAgICBjb25zdCBqb2JJbmRleCA9IGN1cnJlbnRTdGF0dXMuYWN0aXZlSm9icy5maW5kSW5kZXgoaiA9PiBqLmlkID09PSBqb2JJZCk7XHJcbiAgICBcclxuICAgIGlmIChqb2JJbmRleCAhPT0gLTEpIHtcclxuICAgICAgY29uc3Qgam9iID0gY3VycmVudFN0YXR1cy5hY3RpdmVKb2JzW2pvYkluZGV4XTtcclxuICAgICAgXHJcbiAgICAgIC8vIERldGVuZXIgY3VhbHF1aWVyIGFuaW1hY2nDs24gZW4gY3Vyc29cclxuICAgICAgdGhpcy5zdG9wQW5pbWF0aW9uKGpvYik7XHJcbiAgICAgIFxyXG4gICAgICAvLyBBbmltYXIgYWwgMTAwJSBwYXJhIGNvbXBsZXRhclxyXG4gICAgICB0aGlzLmFuaW1hdGVQcm9ncmVzc1RvKGpvYklkLCBqb2IucHJvZ3Jlc3MsIDEwMCwgNTAwKTtcclxuICAgICAgXHJcbiAgICAgIC8vIEFjdHVhbGl6YXIgZWwgZXN0YWRvIGEgY29tcGxldGFkb1xyXG4gICAgICBjb25zdCB1cGRhdGVkSm9icyA9IGN1cnJlbnRTdGF0dXMuYWN0aXZlSm9icy5tYXAoam9iID0+IHtcclxuICAgICAgICBpZiAoam9iLmlkID09PSBqb2JJZCkge1xyXG4gICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgLi4uam9iLFxyXG4gICAgICAgICAgICBpc0NvbXBsZXRlZDogdHJ1ZVxyXG4gICAgICAgICAgfTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGpvYjtcclxuICAgICAgfSk7XHJcbiAgICAgIFxyXG4gICAgICB0aGlzLmV4cG9ydFN0YXR1c1N1YmplY3QubmV4dCh7XHJcbiAgICAgICAgLi4uY3VycmVudFN0YXR1cyxcclxuICAgICAgICBhY3RpdmVKb2JzOiB1cGRhdGVkSm9icyxcclxuICAgICAgICBpc0V4cG9ydGluZzogdXBkYXRlZEpvYnMuc29tZShqb2IgPT4gIWpvYi5pc0NvbXBsZXRlZCAmJiAham9iLmVycm9yKVxyXG4gICAgICB9KTtcclxuICAgICAgXHJcbiAgICAgIC8vIFByb2dyYW1hciBsYSBlbGltaW5hY2nDs24gZGVsIHRyYWJham8gY29tcGxldGFkbyBkZXNwdcOpcyBkZSBjaWVydG8gdGllbXBvXHJcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgIHRoaXMucmVtb3ZlSm9iKGpvYklkKTtcclxuICAgICAgfSwgNTAwMCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBNYXJjYSB1bmEgZXhwb3J0YWNpw7NuIGNvbW8gZmFsbGlkYVxyXG4gICAqL1xyXG4gIGVycm9yRXhwb3J0KGpvYklkOiBzdHJpbmcsIGVycm9yOiBhbnkpOiB2b2lkIHtcclxuICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGVuIGxhIGV4cG9ydGFjacOzbjonLCBlcnJvcik7XHJcbiAgICBcclxuICAgIGNvbnN0IGN1cnJlbnRTdGF0dXMgPSB0aGlzLmV4cG9ydFN0YXR1c1N1YmplY3QudmFsdWU7XHJcbiAgICBjb25zdCBqb2JJbmRleCA9IGN1cnJlbnRTdGF0dXMuYWN0aXZlSm9icy5maW5kSW5kZXgoaiA9PiBqLmlkID09PSBqb2JJZCk7XHJcbiAgICBcclxuICAgIGlmIChqb2JJbmRleCAhPT0gLTEpIHtcclxuICAgICAgY29uc3Qgam9iID0gY3VycmVudFN0YXR1cy5hY3RpdmVKb2JzW2pvYkluZGV4XTtcclxuICAgICAgXHJcbiAgICAgIC8vIERldGVuZXIgY3VhbHF1aWVyIGFuaW1hY2nDs24gZW4gY3Vyc29cclxuICAgICAgdGhpcy5zdG9wQW5pbWF0aW9uKGpvYik7XHJcbiAgICAgIFxyXG4gICAgICBjb25zdCB1cGRhdGVkSm9icyA9IGN1cnJlbnRTdGF0dXMuYWN0aXZlSm9icy5tYXAoam9iID0+IHtcclxuICAgICAgICBpZiAoam9iLmlkID09PSBqb2JJZCkge1xyXG4gICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgLi4uam9iLFxyXG4gICAgICAgICAgICBlcnJvcjogZXJyb3IubWVzc2FnZSB8fCAnRXJyb3IgYWwgZXhwb3J0YXInLFxyXG4gICAgICAgICAgICBpc0NvbXBsZXRlZDogdHJ1ZVxyXG4gICAgICAgICAgfTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIGpvYjtcclxuICAgICAgfSk7XHJcbiAgICAgIFxyXG4gICAgICB0aGlzLmV4cG9ydFN0YXR1c1N1YmplY3QubmV4dCh7XHJcbiAgICAgICAgLi4uY3VycmVudFN0YXR1cyxcclxuICAgICAgICBhY3RpdmVKb2JzOiB1cGRhdGVkSm9icyxcclxuICAgICAgICBpc0V4cG9ydGluZzogdXBkYXRlZEpvYnMuc29tZShqb2IgPT4gIWpvYi5pc0NvbXBsZXRlZCAmJiAham9iLmVycm9yKVxyXG4gICAgICB9KTtcclxuICAgICAgXHJcbiAgICAgIC8vIFByb2dyYW1hciBsYSBlbGltaW5hY2nDs24gZGVsIHRyYWJham8gZmFsbGlkbyBkZXNwdcOpcyBkZSBjaWVydG8gdGllbXBvXHJcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgIHRoaXMucmVtb3ZlSm9iKGpvYklkKTtcclxuICAgICAgfSwgNTAwMCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBFbGltaW5hIHVuIHRyYWJham8gZGUgbGEgbGlzdGEgZGUgdHJhYmFqb3MgYWN0aXZvc1xyXG4gICAqL1xyXG4gIHByaXZhdGUgcmVtb3ZlSm9iKGpvYklkOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGNvbnN0IGN1cnJlbnRTdGF0dXMgPSB0aGlzLmV4cG9ydFN0YXR1c1N1YmplY3QudmFsdWU7XHJcbiAgICBjb25zdCBqb2JJbmRleCA9IGN1cnJlbnRTdGF0dXMuYWN0aXZlSm9icy5maW5kSW5kZXgoaiA9PiBqLmlkID09PSBqb2JJZCk7XHJcbiAgICBcclxuICAgIGlmIChqb2JJbmRleCAhPT0gLTEpIHtcclxuICAgICAgY29uc3Qgam9iID0gY3VycmVudFN0YXR1cy5hY3RpdmVKb2JzW2pvYkluZGV4XTtcclxuICAgICAgXHJcbiAgICAgIC8vIERldGVuZXIgY3VhbHF1aWVyIGFuaW1hY2nDs24gZW4gY3Vyc29cclxuICAgICAgdGhpcy5zdG9wQW5pbWF0aW9uKGpvYik7XHJcbiAgICAgIFxyXG4gICAgICBjb25zdCB1cGRhdGVkSm9icyA9IGN1cnJlbnRTdGF0dXMuYWN0aXZlSm9icy5maWx0ZXIoam9iID0+IGpvYi5pZCAhPT0gam9iSWQpO1xyXG4gICAgICBcclxuICAgICAgaWYgKHVwZGF0ZWRKb2JzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgIC8vIFNpIG5vIGhheSBtw6FzIHRyYWJham9zLCBvY3VsdGFyIGxhIG5vdGlmaWNhY2nDs25cclxuICAgICAgICB0aGlzLmV4cG9ydFN0YXR1c1N1YmplY3QubmV4dCh7XHJcbiAgICAgICAgICBpc0V4cG9ydGluZzogZmFsc2UsXHJcbiAgICAgICAgICBhY3RpdmVKb2JzOiBbXSxcclxuICAgICAgICAgIHNob3dOb3RpZmljYXRpb246IGZhbHNlXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8gU2kgYcO6biBoYXkgdHJhYmFqb3MsIGFjdHVhbGl6YXIgbGEgbGlzdGFcclxuICAgICAgICB0aGlzLmV4cG9ydFN0YXR1c1N1YmplY3QubmV4dCh7XHJcbiAgICAgICAgICAuLi5jdXJyZW50U3RhdHVzLFxyXG4gICAgICAgICAgYWN0aXZlSm9iczogdXBkYXRlZEpvYnMsXHJcbiAgICAgICAgICBpc0V4cG9ydGluZzogdXBkYXRlZEpvYnMuc29tZShqb2IgPT4gIWpvYi5pc0NvbXBsZXRlZCAmJiAham9iLmVycm9yKVxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBPY3VsdGEgbGEgbm90aWZpY2FjacOzbiBtYW51YWxtZW50ZVxyXG4gICAqL1xyXG4gIGhpZGVOb3RpZmljYXRpb24oKTogdm9pZCB7XHJcbiAgICBjb25zdCBjdXJyZW50U3RhdHVzID0gdGhpcy5leHBvcnRTdGF0dXNTdWJqZWN0LnZhbHVlO1xyXG4gICAgXHJcbiAgICAvLyBEZXRlbmVyIHRvZGFzIGxhcyBhbmltYWNpb25lcyBlbiBjdXJzb1xyXG4gICAgY3VycmVudFN0YXR1cy5hY3RpdmVKb2JzLmZvckVhY2goam9iID0+IHtcclxuICAgICAgdGhpcy5zdG9wQW5pbWF0aW9uKGpvYik7XHJcbiAgICB9KTtcclxuICAgIFxyXG4gICAgdGhpcy5leHBvcnRTdGF0dXNTdWJqZWN0Lm5leHQoe1xyXG4gICAgICAuLi5jdXJyZW50U3RhdHVzLFxyXG4gICAgICBzaG93Tm90aWZpY2F0aW9uOiBmYWxzZVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBNdWVzdHJhIGxhIG5vdGlmaWNhY2nDs24gc2kgZXN0YWJhIG9jdWx0YVxyXG4gICAqL1xyXG4gIHNob3dOb3RpZmljYXRpb24oKTogdm9pZCB7XHJcbiAgICBjb25zdCBjdXJyZW50U3RhdHVzID0gdGhpcy5leHBvcnRTdGF0dXNTdWJqZWN0LnZhbHVlO1xyXG4gICAgaWYgKGN1cnJlbnRTdGF0dXMuYWN0aXZlSm9icy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIHRoaXMuZXhwb3J0U3RhdHVzU3ViamVjdC5uZXh0KHtcclxuICAgICAgICAuLi5jdXJyZW50U3RhdHVzLFxyXG4gICAgICAgIHNob3dOb3RpZmljYXRpb246IHRydWVcclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZW5lcmEgdW4gSUQgw7puaWNvIHBhcmEgY2FkYSB0cmFiYWpvXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBnZW5lcmF0ZUpvYklkKCk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gJ2V4cG9ydC0nICsgRGF0ZS5ub3coKSArICctJyArIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIDEwMDApO1xyXG4gIH1cclxufSAiXX0=