@junte/ui
Version:
Quality Angular UI components kit
162 lines • 28.1 kB
JavaScript
var TableComponent_1;
import { __decorate, __metadata } from "tslib";
import { Component, ContentChild, ContentChildren, EventEmitter, forwardRef, HostBinding, HostListener, Input, Output, QueryList, TemplateRef } from '@angular/core';
import { ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR } from '@angular/forms';
import { NGXLogger } from 'ngx-logger';
import { Subscription } from 'rxjs';
import { debounceTime, filter as filtering, finalize } from 'rxjs/operators';
import { ContentApi, MethodApi, PropertyApi } from '../../core/decorators/api';
import { Feature } from '../../core/enums/feature';
import { UI } from '../../core/enums/ui';
import { I18N_PROVIDERS } from '../../core/i18n/providers';
import { TableColumnComponent } from './table-column';
const FIRST = 10;
const FILTER_DELAY = 500;
let TableComponent = TableComponent_1 = class TableComponent {
constructor(logger, fb) {
this.logger = logger;
this.fb = fb;
this.ui = UI;
this.subscriptions = { fetcher: new Subscription() };
this.progress = { loading: false };
this.source = [];
this.orderByControl = this.fb.control(null);
this.firstControl = this.fb.control(FIRST);
this.form = this.fb.group({
q: [null],
orderBy: this.orderByControl,
first: this.firstControl,
offset: [0]
});
this.host = 'jnt-table-host';
this.features = [];
this.reloaded = new EventEmitter();
this.onChange = () => this.logger.error('value accessor is not registered');
this.onTouched = () => this.logger.error('value accessor is not registered');
this.registerOnChange = fn => this.onChange = fn;
this.registerOnTouched = fn => this.onTouched = fn;
this.onBlur = () => this.onTouched();
}
ngOnInit() {
this.form.valueChanges.pipe(filtering(() => !!this.fetcher), debounceTime(FILTER_DELAY)).subscribe(({ q, orderBy, first, offset }) => {
this.onChange({ q, orderBy, first, offset });
});
}
ngOnDestroy() {
this.subscriptions.fetcher.unsubscribe();
}
load(filter = this.form.getRawValue()) {
if (!!this.fetcher) {
this.progress.loading = true;
this.subscriptions.fetcher.unsubscribe();
this.subscriptions.fetcher = this.fetcher(filter)
.pipe(finalize(() => this.progress.loading = false))
.subscribe(resp => {
this.source = resp.results;
this.count = resp.count;
});
}
}
sorting(field) {
this.orderByControl.setValue(this.orderByControl.value === field ? `-${field}` : field);
}
writeValue({ q, orderBy, first, offset }) {
this.form.patchValue({ q, orderBy, first, offset }, { emitEvent: false });
}
hideActions() {
this.popover.hide();
}
};
TableComponent.ctorParameters = () => [
{ type: NGXLogger },
{ type: FormBuilder }
];
__decorate([
HostBinding('attr.host'),
__metadata("design:type", Object)
], TableComponent.prototype, "host", void 0);
__decorate([
PropertyApi({
description: 'Table features',
path: 'ui.feature',
options: [Feature.search, Feature.reload]
}),
Input(),
__metadata("design:type", Array)
], TableComponent.prototype, "features", void 0);
__decorate([
PropertyApi({
description: 'Table fetch function',
type: 'Function'
}),
Input(),
__metadata("design:type", Function)
], TableComponent.prototype, "fetcher", void 0);
__decorate([
PropertyApi({
description: 'Output event of reload table'
}),
Output(),
__metadata("design:type", Object)
], TableComponent.prototype, "reloaded", void 0);
__decorate([
ContentChildren(TableColumnComponent),
__metadata("design:type", QueryList)
], TableComponent.prototype, "columns", void 0);
__decorate([
ContentApi({
selector: '#tableRowActionsTemplate',
description: 'table row actions template'
}),
ContentChild('tableRowActionsTemplate'),
__metadata("design:type", TemplateRef)
], TableComponent.prototype, "rowActionsTemplate", void 0);
__decorate([
ContentApi({
selector: '#tableActionsTemplate',
description: 'table actions template'
}),
ContentChild('tableActionsTemplate'),
__metadata("design:type", TemplateRef)
], TableComponent.prototype, "actionsTemplate", void 0);
__decorate([
ContentApi({
selector: '#tableFiltersTemplate',
description: 'table filters template'
}),
ContentChild('tableFiltersTemplate'),
__metadata("design:type", TemplateRef)
], TableComponent.prototype, "filtersTemplate", void 0);
__decorate([
HostListener('blur'),
__metadata("design:type", Object)
], TableComponent.prototype, "onBlur", void 0);
__decorate([
MethodApi({ description: 'reload table' }),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", void 0)
], TableComponent.prototype, "load", null);
__decorate([
MethodApi({ description: 'sorting data table by field' }),
__metadata("design:type", Function),
__metadata("design:paramtypes", [String]),
__metadata("design:returntype", void 0)
], TableComponent.prototype, "sorting", null);
TableComponent = TableComponent_1 = __decorate([
Component({
selector: 'jnt-table',
template: "<form child-of=\"jnt-table-host\" [formGroup]=\"form\">\n <jnt-stack child-of=\"jnt-table-host\" [align]=\"ui.align.stretch\" [gutter]=\"ui.gutter.none\">\n <ng-container *jntMinFor=\"ui.breakpoint.desktop\">\n <jnt-stack child-of=\"jnt-table-host\" data-feature *ngIf=\"(features | includes : [ui.feature.reload, ui.feature.search]) || !!actionsTemplate\"\n [orientation]=\"ui.orientation.horizontal\"\n [align]=\"ui.align.center\"\n [justify]=\"ui.justify.between\">\n <jnt-stack child-of=\"jnt-table-host\" *ngIf=\"(features | includes : ui.feature.reload) || !!actionsTemplate\"\n [orientation]=\"ui.orientation.horizontal\"\n [align]=\"ui.align.center\">\n <jnt-button child-of=\"jnt-table-host\" data-button *ngIf=\"features | includes : ui.feature.reload\"\n [text]=\"'action.reload' | translate\"\n [icon]=\"progress.loading ? ui.icons.animated.reload : ui.icons.reload\"\n [outline]=\"ui.outline.transparent\"\n [disabled]=\"progress.loading\"\n (click)=\"load(); reloaded.emit()\">\n </jnt-button>\n <ng-container *ngTemplateOutlet=\"actionsTemplate\"></ng-container>\n </jnt-stack>\n <jnt-input child-of=\"jnt-table-host\" data-search *ngIf=\"features | includes : ui.feature.search\"\n formControlName=\"q\"\n [icon]=\"ui.icons.search\"\n [features]=\"[ui.feature.allowEmpty]\"\n [placeholder]=\"'label.search' | translate\">\n </jnt-input>\n </jnt-stack>\n\n <div child-of=\"jnt-table-host\" data-filters *ngIf=\"!!filtersTemplate\">\n <ng-container *ngTemplateOutlet=\"filtersTemplate\"></ng-container>\n </div>\n </ng-container>\n\n <jnt-stack child-of=\"jnt-table-host\" [align]=\"ui.align.stretch\">\n <div child-of=\"jnt-table-host\" *jntMinFor=\"ui.breakpoint.desktop\" data-table>\n <table child-of=\"jnt-table-host\" >\n <div child-of=\"jnt-table-host\" data-spinner *ngIf=\"source.length && progress.loading\">\n <jnt-spinner child-of=\"jnt-table-host\" [size]=\"ui.size.large\"></jnt-spinner>\n </div>\n\n <thead child-of=\"jnt-table-host\" >\n <tr child-of=\"jnt-table-host\" >\n <th child-of=\"jnt-table-host\" data-actions *ngIf=\"!!rowActionsTemplate\"></th>\n <th child-of=\"jnt-table-host\" *ngFor=\"let column of columns\"\n [attr.data-sortable]=\"!!column.orderBy\"\n [style.text-align]=\"column.align\"\n [style.width]=\"column.width\"\n (click)=\"column.orderBy ? sorting(column.orderBy) : null\">\n <span child-of=\"jnt-table-host\" >\n {{column.title}}\n <i child-of=\"jnt-table-host\" *ngIf=\"!!orderByControl.value && (orderByControl.value === '-' + column.orderBy\n || orderByControl.value === column.orderBy)\"\n [innerHTML]=\"(orderByControl.value === column.orderBy) ? '↑' : '↓'\"></i>\n </span>\n </th>\n </tr>\n </thead>\n\n <tbody child-of=\"jnt-table-host\" >\n <ng-container *ngIf=\"source.length; else noDataTemplate\">\n <tr child-of=\"jnt-table-host\" *ngFor=\"let row of source; let i = index\" [class.even]=\"!(i % 2)\">\n <td child-of=\"jnt-table-host\" *ngIf=\"!!rowActionsTemplate\" data-actions>\n <jnt-button child-of=\"jnt-table-host\" data-trigger\n [outline]=\"ui.outline.transparent\"\n [icon]=\"ui.icons.actions\"\n (attached)=\"popover = $event\"\n [jntPopover]=\"{\n context: 'table-row-action',\n contentTemplate: dropdownTemplate,\n behaviour: ui.behaviour.dropdown,\n trigger: ui.trigger.click,\n padding: ui.gutter.small,\n minWidth: '150px'\n }\">\n </jnt-button>\n <ng-template #dropdownTemplate>\n <ng-container *ngTemplateOutlet=\"rowActionsTemplate;\n context: {row: row, hide: hideActions.bind(this)}\">\n </ng-container>\n </ng-template>\n </td>\n <td child-of=\"jnt-table-host\" *ngFor=\"let column of columns\">\n <ng-container *ngTemplateOutlet=\"column.tableCellTemplate; context: row\"></ng-container>\n </td>\n </tr>\n </ng-container>\n <ng-template #noDataTemplate>\n <ng-container *ngIf=\"!progress.loading; else skeletonTemplate\">\n <tr child-of=\"jnt-table-host\" data-nodata>\n <td child-of=\"jnt-table-host\" [attr.colspan]=\"!!rowActionsTemplate ? columns.length + 1 : columns.length\">\n <jnt-icon child-of=\"jnt-table-host\" [icon]=\"ui.icons.neutral\"></jnt-icon>\n </td>\n </tr>\n </ng-container>\n <ng-template #skeletonTemplate>\n <tr child-of=\"jnt-table-host\" data-loading>\n <td child-of=\"jnt-table-host\" [attr.colspan]=\"!!rowActionsTemplate ? columns.length + 1 : columns.length\">\n <jnt-skeleton child-of=\"jnt-table-host\" [lines]=\"4\"></jnt-skeleton>\n </td>\n </tr>\n </ng-template>\n </ng-template>\n </tbody>\n </table>\n </div>\n\n <jnt-stack child-of=\"jnt-table-host\" *jntMaxFor=\"ui.breakpoint.tablet\" [align]=\"ui.align.stretch\">\n <jnt-stack child-of=\"jnt-table-host\" data-feature [align]=\"ui.align.stretch\">\n <jnt-stack child-of=\"jnt-table-host\" *ngIf=\"(features | includes : ui.feature.reload) || !!actionsTemplate\"\n [orientation]=\"ui.orientation.horizontal\" [wrap]=\"ui.wrap.wrap\">\n <jnt-button child-of=\"jnt-table-host\" data-button *ngIf=\"features | includes : ui.feature.reload\"\n [text]=\"'action.reload' | translate\"\n [icon]=\"progress.loading ? ui.icons.animated.reload : ui.icons.reload\"\n [outline]=\"ui.outline.transparent\"\n [disabled]=\"progress.loading\"\n (click)=\"load(); reloaded.emit()\">\n </jnt-button>\n <jnt-stack child-of=\"jnt-table-host\" *ngIf=\"!!actionsTemplate\" [orientation]=\"ui.orientation.horizontal\" [wrap]=\"ui.wrap.wrap\">\n <ng-container *ngTemplateOutlet=\"actionsTemplate\"></ng-container>\n </jnt-stack>\n </jnt-stack>\n <jnt-input child-of=\"jnt-table-host\" data-search *ngIf=\"features | includes : ui.feature.search\"\n formControlName=\"q\"\n [icon]=\"ui.icons.search\"\n [features]=\"[ui.feature.allowEmpty]\"\n [placeholder]=\"'label.search' | translate\">\n </jnt-input>\n <ng-container *ngIf=\"!!filtersTemplate\">\n <ng-container *ngTemplateOutlet=\"filtersTemplate\"></ng-container>\n </ng-container>\n </jnt-stack>\n <ng-template #noDataCardTemplate>\n <jnt-stack child-of=\"jnt-table-host\" *ngIf=\"!progress.loading; else skeletonCardTemplate\" [align]=\"ui.align.center\">\n <jnt-icon child-of=\"jnt-table-host\" data-nodata [icon]=\"ui.icons.neutral\"></jnt-icon>\n </jnt-stack>\n <ng-template #skeletonCardTemplate>\n <ng-container *ngFor=\"let card of 5 | mockArray\">\n <jnt-skeleton child-of=\"jnt-table-host\" [type]=\"ui.skeleton.type.card\"></jnt-skeleton>\n </ng-container>\n </ng-template>\n </ng-template>\n <div child-of=\"jnt-table-host\" data-spinner *ngIf=\"source.length && progress.loading\">\n <jnt-spinner child-of=\"jnt-table-host\" [size]=\"ui.size.large\"></jnt-spinner>\n </div>\n <ng-container *ngIf=\"source.length; else noDataCardTemplate\">\n <jnt-card child-of=\"jnt-table-host\" *ngFor=\"let row of source; let i = index\">\n <table child-of=\"jnt-table-host\" data-line cellpadding=\"0\" cellspacing=\"0\">\n <tr child-of=\"jnt-table-host\" *ngFor=\"let column of columns\">\n <td child-of=\"jnt-table-host\" >\n <b child-of=\"jnt-table-host\" *ngIf=\"!!column.title\">{{column.title}}</b>\n </td>\n <td child-of=\"jnt-table-host\" >\n <ng-container *ngTemplateOutlet=\"column.tableCellTemplate; context: row\"></ng-container>\n </td>\n </tr>\n </table>\n <ng-template *ngIf=\"!!rowActionsTemplate\" #cardActionsTemplate let-hide=\"hide\">\n <ng-container *ngTemplateOutlet=\"rowActionsTemplate;\n context: {row: row, hide: hideActions.bind(this)}\">\n </ng-container>\n </ng-template>\n </jnt-card>\n </ng-container>\n </jnt-stack>\n\n <ng-container *ngIf=\"!!count\">\n <div child-of=\"jnt-table-host\" data-pagination>\n <jnt-pager child-of=\"jnt-table-host\" data-pages formControlName=\"offset\"\n [count]=\"count\" [pageSize]=\"firstControl.value\">\n </jnt-pager>\n <jnt-select child-of=\"jnt-table-host\" *jntMinFor=\"ui.breakpoint.desktop\" formControlName=\"first\" [size]=\"ui.size.small\">\n <jnt-select-option child-of=\"jnt-table-host\" label=\"10\" key=\"10\"></jnt-select-option>\n <jnt-select-option child-of=\"jnt-table-host\" label=\"20\" key=\"20\"></jnt-select-option>\n <jnt-select-option child-of=\"jnt-table-host\" label=\"30\" key=\"30\"></jnt-select-option>\n </jnt-select>\n </div>\n </ng-container>\n </jnt-stack>\n </jnt-stack>\n</form>",
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => TableComponent_1),
multi: true
}, ...I18N_PROVIDERS
]
}),
__metadata("design:paramtypes", [NGXLogger,
FormBuilder])
], TableComponent);
export { TableComponent };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vQGp1bnRlL3VpLyIsInNvdXJjZXMiOlsibGliL2NvbGxlY3Rpb25zL3RhYmxlL3RhYmxlLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLGVBQWUsRUFDZixZQUFZLEVBQ1osVUFBVSxFQUNWLFdBQVcsRUFDWCxZQUFZLEVBQ1osS0FBSyxFQUdMLE1BQU0sRUFDTixTQUFTLEVBQ1QsV0FBVyxFQUNaLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxXQUFXLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN0RixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDcEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLElBQUksU0FBUyxFQUFFLFFBQVEsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQy9FLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDekMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBRTNELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBR3RELE1BQU0sS0FBSyxHQUFHLEVBQUUsQ0FBQztBQUNqQixNQUFNLFlBQVksR0FBRyxHQUFHLENBQUM7QUFhekIsSUFBYSxjQUFjLHNCQUEzQixNQUFhLGNBQWM7SUEwRXpCLFlBQW9CLE1BQWlCLEVBQ2pCLEVBQWU7UUFEZixXQUFNLEdBQU4sTUFBTSxDQUFX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bnRDaGlsZHJlbixcbiAgRXZlbnRFbWl0dGVyLFxuICBmb3J3YXJkUmVmLFxuICBIb3N0QmluZGluZyxcbiAgSG9zdExpc3RlbmVyLFxuICBJbnB1dCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgUXVlcnlMaXN0LFxuICBUZW1wbGF0ZVJlZlxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBGb3JtQnVpbGRlciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBOR1hMb2dnZXIgfSBmcm9tICduZ3gtbG9nZ2VyJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBmaWx0ZXIgYXMgZmlsdGVyaW5nLCBmaW5hbGl6ZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IENvbnRlbnRBcGksIE1ldGhvZEFwaSwgUHJvcGVydHlBcGkgfSBmcm9tICcuLi8uLi9jb3JlL2RlY29yYXRvcnMvYXBpJztcbmltcG9ydCB7IEZlYXR1cmUgfSBmcm9tICcuLi8uLi9jb3JlL2VudW1zL2ZlYXR1cmUnO1xuaW1wb3J0IHsgVUkgfSBmcm9tICcuLi8uLi9jb3JlL2VudW1zL3VpJztcbmltcG9ydCB7IEkxOE5fUFJPVklERVJTIH0gZnJvbSAnLi4vLi4vY29yZS9pMThuL3Byb3ZpZGVycyc7XG5pbXBvcnQgeyBQb3BvdmVyQ29tcG9uZW50IH0gZnJvbSAnLi4vLi4vb3ZlcmxheXMvcG9wb3Zlci9wb3BvdmVyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBUYWJsZUNvbHVtbkNvbXBvbmVudCB9IGZyb20gJy4vdGFibGUtY29sdW1uJztcbmltcG9ydCB7IERlZmF1bHRTZWFyY2hGaWx0ZXIgfSBmcm9tICcuL3R5cGVzJztcblxuY29uc3QgRklSU1QgPSAxMDtcbmNvbnN0IEZJTFRFUl9ERUxBWSA9IDUwMDtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnam50LXRhYmxlJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3RhYmxlLmVuY2Fwc3VsYXRlZC5odG1sJyxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBUYWJsZUNvbXBvbmVudCksXG4gICAgICBtdWx0aTogdHJ1ZVxuICAgIH0sIC4uLkkxOE5fUFJPVklERVJTXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgVGFibGVDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSwgQ29udHJvbFZhbHVlQWNjZXNzb3Ige1xuXG4gIHVpID0gVUk7XG5cbiAgcHJpdmF0ZSBzdWJzY3JpcHRpb25zID0ge2ZldGNoZXI6IG5ldyBTdWJzY3JpcHRpb24oKX07XG4gIHBvcG92ZXI6IFBvcG92ZXJDb21wb25lbnQ7XG5cbiAgcHJvZ3Jlc3MgPSB7bG9hZGluZzogZmFsc2V9O1xuICBzb3VyY2U6IE9iamVjdFtdID0gW107XG4gIGNvdW50OiBudW1iZXI7XG5cbiAgb3JkZXJCeUNvbnRyb2wgPSB0aGlzLmZiLmNvbnRyb2wobnVsbCk7XG4gIGZpcnN0Q29udHJvbCA9IHRoaXMuZmIuY29udHJvbChGSVJTVCk7XG5cbiAgZm9ybSA9IHRoaXMuZmIuZ3JvdXAoe1xuICAgIHE6IFtudWxsXSxcbiAgICBvcmRlckJ5OiB0aGlzLm9yZGVyQnlDb250cm9sLFxuICAgIGZpcnN0OiB0aGlzLmZpcnN0Q29udHJvbCxcbiAgICBvZmZzZXQ6IFswXVxuICB9KTtcblxuICBASG9zdEJpbmRpbmcoJ2F0dHIuaG9zdCcpIHJlYWRvbmx5IGhvc3QgPSAnam50LXRhYmxlLWhvc3QnO1xuXG4gIEBQcm9wZXJ0eUFwaSh7XG4gICAgZGVzY3JpcHRpb246ICdUYWJsZSBmZWF0dXJlcycsXG4gICAgcGF0aDogJ3VpLmZlYXR1cmUnLFxuICAgIG9wdGlvbnM6IFtGZWF0dXJlLnNlYXJjaCwgRmVhdHVyZS5yZWxvYWRdXG4gIH0pXG4gIEBJbnB1dCgpXG4gIGZlYXR1cmVzOiBGZWF0dXJlW10gPSBbXTtcblxuICBAUHJvcGVydHlBcGkoe1xuICAgIGRlc2NyaXB0aW9uOiAnVGFibGUgZmV0Y2ggZnVuY3Rpb24nLFxuICAgIHR5cGU6ICdGdW5jdGlvbidcbiAgfSlcbiAgQElucHV0KClcbiAgZmV0Y2hlcjogRnVuY3Rpb247XG5cbiAgQFByb3BlcnR5QXBpKHtcbiAgICBkZXNjcmlwdGlvbjogJ091dHB1dCBldmVudCBvZiByZWxvYWQgdGFibGUnXG4gIH0pXG4gIEBPdXRwdXQoKVxuICByZWxvYWRlZCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gIEBDb250ZW50Q2hpbGRyZW4oVGFibGVDb2x1bW5Db21wb25lbnQpXG4gIGNvbHVtbnM6IFF1ZXJ5TGlzdDxUYWJsZUNvbHVtbkNvbXBvbmVudD47XG5cbiAgQENvbnRlbnRBcGkoe1xuICAgIHNlbGVjdG9yOiAnI3RhYmxlUm93QWN0aW9uc1RlbXBsYXRlJyxcbiAgICBkZXNjcmlwdGlvbjogJ3RhYmxlIHJvdyBhY3Rpb25zIHRlbXBsYXRlJ1xuICB9KVxuICBAQ29udGVudENoaWxkKCd0YWJsZVJvd0FjdGlvbnNUZW1wbGF0ZScpXG4gIHJvd0FjdGlvbnNUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcblxuICBAQ29udGVudEFwaSh7XG4gICAgc2VsZWN0b3I6ICcjdGFibGVBY3Rpb25zVGVtcGxhdGUnLFxuICAgIGRlc2NyaXB0aW9uOiAndGFibGUgYWN0aW9ucyB0ZW1wbGF0ZSdcbiAgfSlcbiAgQENvbnRlbnRDaGlsZCgndGFibGVBY3Rpb25zVGVtcGxhdGUnKVxuICBhY3Rpb25zVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XG5cbiAgQENvbnRlbnRBcGkoe1xuICAgIHNlbGVjdG9yOiAnI3RhYmxlRmlsdGVyc1RlbXBsYXRlJyxcbiAgICBkZXNjcmlwdGlvbjogJ3RhYmxlIGZpbHRlcnMgdGVtcGxhdGUnXG4gIH0pXG4gIEBDb250ZW50Q2hpbGQoJ3RhYmxlRmlsdGVyc1RlbXBsYXRlJylcbiAgZmlsdGVyc1RlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gIG9uQ2hhbmdlOiAoZmlsdGVyOiBEZWZhdWx0U2VhcmNoRmlsdGVyKSA9PiB2b2lkID0gKCkgPT4gdGhpcy5sb2dnZXIuZXJyb3IoJ3ZhbHVlIGFjY2Vzc29yIGlzIG5vdCByZWdpc3RlcmVkJyk7XG4gIG9uVG91Y2hlZDogKCkgPT4gdm9pZCA9ICgpID0+IHRoaXMubG9nZ2VyLmVycm9yKCd2YWx1ZSBhY2Nlc3NvciBpcyBub3QgcmVnaXN0ZXJlZCcpO1xuICByZWdpc3Rlck9uQ2hhbmdlID0gZm4gPT4gdGhpcy5vbkNoYW5nZSA9IGZuO1xuICByZWdpc3Rlck9uVG91Y2hlZCA9IGZuID0+IHRoaXMub25Ub3VjaGVkID0gZm47XG4gIEBIb3N0TGlzdGVuZXIoJ2JsdXInKSBvbkJsdXIgPSAoKSA9PiB0aGlzLm9uVG91Y2hlZCgpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgbG9nZ2VyOiBOR1hMb2dnZXIsXG4gICAgICAgICAgICAgIHByaXZhdGUgZmI6IEZvcm1CdWlsZGVyKSB7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmZvcm0udmFsdWVDaGFuZ2VzLnBpcGUoZmlsdGVyaW5nKCgpID0+ICEhdGhpcy5mZXRjaGVyKSxcbiAgICAgIGRlYm91bmNlVGltZShGSUxURVJfREVMQVkpKS5zdWJzY3JpYmUoKHtxLCBvcmRlckJ5LCBmaXJzdCwgb2Zmc2V0fSkgPT4ge1xuICAgICAgdGhpcy5vbkNoYW5nZSh7cSwgb3JkZXJCeSwgZmlyc3QsIG9mZnNldH0pO1xuICAgIH0pO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLmZldGNoZXIudW5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIEBNZXRob2RBcGkoe2Rlc2NyaXB0aW9uOiAncmVsb2FkIHRhYmxlJ30pXG4gIGxvYWQoZmlsdGVyID0gdGhpcy5mb3JtLmdldFJhd1ZhbHVlKCkpIHtcbiAgICBpZiAoISF0aGlzLmZldGNoZXIpIHtcbiAgICAgIHRoaXMucHJvZ3Jlc3MubG9hZGluZyA9IHRydWU7XG4gICAgICB0aGlzLnN1YnNjcmlwdGlvbnMuZmV0Y2hlci51bnN1YnNjcmliZSgpO1xuICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLmZldGNoZXIgPSB0aGlzLmZldGNoZXIoZmlsdGVyKVxuICAgICAgICAucGlwZShmaW5hbGl6ZSgoKSA9PiB0aGlzLnByb2dyZXNzLmxvYWRpbmcgPSBmYWxzZSkpXG4gICAgICAgIC5zdWJzY3JpYmUocmVzcCA9PiB7XG4gICAgICAgICAgdGhpcy5zb3VyY2UgPSByZXNwLnJlc3VsdHM7XG4gICAgICAgICAgdGhpcy5jb3VudCA9IHJlc3AuY291bnQ7XG4gICAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIEBNZXRob2RBcGkoe2Rlc2NyaXB0aW9uOiAnc29ydGluZyBkYXRhIHRhYmxlIGJ5IGZpZWxkJ30pXG4gIHNvcnRpbmcoZmllbGQ6IHN0cmluZykge1xuICAgIHRoaXMub3JkZXJCeUNvbnRyb2wuc2V0VmFsdWUodGhpcy5vcmRlckJ5Q29udHJvbC52YWx1ZSA9PT0gZmllbGQgPyBgLSR7ZmllbGR9YCA6IGZpZWxkKTtcbiAgfVxuXG4gIHdyaXRlVmFsdWUoe3EsIG9yZGVyQnksIGZpcnN0LCBvZmZzZXR9OiBEZWZhdWx0U2VhcmNoRmlsdGVyKSB7XG4gICAgdGhpcy5mb3JtLnBhdGNoVmFsdWUoe3EsIG9yZGVyQnksIGZpcnN0LCBvZmZzZXR9LFxuICAgICAge2VtaXRFdmVudDogZmFsc2V9KTtcbiAgfVxuXG4gIGhpZGVBY3Rpb25zKCkge1xuICAgIHRoaXMucG9wb3Zlci5oaWRlKCk7XG4gIH1cbn1cbiJdfQ==