UNPKG

@junte/ui

Version:

Quality Angular UI components kit

162 lines 28.1 kB
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) ? '&#8593;' : '&#8595;'\"></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==