@mediusinc/mng-commons 5.3.0-rc.1 → 5.3.0-rc.3

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.
Files changed (106) hide show
  1. package/core/data-list/filter-metadata.model.d.ts +20 -0
  2. package/core/helpers/number.d.ts +5 -0
  3. package/core/helpers/type-helpers.d.ts +1 -0
  4. package/core/index.d.ts +2 -0
  5. package/core/provide.d.ts +3 -2
  6. package/core/services/tokens/module-config.token.d.ts +7 -6
  7. package/esm2022/core/data-list/data-list-params-helpers.mjs +3 -1
  8. package/esm2022/core/data-list/filter-metadata.model.mjs +2 -0
  9. package/esm2022/core/helpers/date.mjs +2 -2
  10. package/esm2022/core/helpers/number.mjs +19 -0
  11. package/esm2022/core/helpers/type-helpers.mjs +1 -1
  12. package/esm2022/core/index.mjs +3 -1
  13. package/esm2022/core/pipes/boolean.pipe.mjs +7 -1
  14. package/esm2022/core/provide.mjs +4 -3
  15. package/esm2022/core/services/tokens/module-config.token.mjs +1 -1
  16. package/esm2022/filter/descriptors/filter-lookup.descriptor.mjs +2 -3
  17. package/esm2022/filter/descriptors/filter.descriptor.mjs +76 -31
  18. package/esm2022/filter/models/filter.model.mjs +6 -1
  19. package/esm2022/form/components/date-range/date-range.component.mjs +45 -14
  20. package/esm2022/form/components/dropdown/dropdown.component.mjs +77 -93
  21. package/esm2022/form/components/number-range/number-range.component.mjs +29 -12
  22. package/esm2022/table/api/descriptors/column.descriptor.mjs +2 -1
  23. package/esm2022/table/api/descriptors/table.descriptor.mjs +22 -21
  24. package/esm2022/table/api/index.mjs +2 -1
  25. package/esm2022/table/api/models/row-expandable-component.model.mjs +2 -0
  26. package/esm2022/table/api/models/table-columns.model.mjs +1 -1
  27. package/esm2022/table/api/models/table.model.mjs +1 -1
  28. package/esm2022/table/components/column-filter/column-filter.component.mjs +396 -0
  29. package/esm2022/table/components/column-value/column-value.component.mjs +3 -3
  30. package/esm2022/table/components/filter/filter-active-tag/filter-active-tag.component.mjs +52 -0
  31. package/esm2022/table/components/filter/filter-form/filter-form.component.mjs +197 -0
  32. package/esm2022/table/components/filter/filter-overlay-with-tag/filter-overlay-with-tag.component.mjs +135 -0
  33. package/esm2022/table/components/table/table.component.mjs +34 -25
  34. package/esm2022/table/helpers/filters.mjs +297 -0
  35. package/esm2022/table/index.mjs +13 -2
  36. package/esm2022/table/models/filter.model.mjs +2 -0
  37. package/esm2022/table/pipes/filter-value.pipe.mjs +77 -0
  38. package/esm2022/table/provide.mjs +19 -0
  39. package/esm2022/table/services/data-list.service.mjs +1 -1
  40. package/esm2022/table/services/table-feature-config.token.mjs +3 -0
  41. package/esm2022/tableview/action/components/action/action.component.mjs +3 -3
  42. package/esm2022/tableview/action/components/editor/injector-context/action-editor-injector-context.component.mjs +2 -2
  43. package/esm2022/tableview/action/components/localization/data-language-dropdown.component.mjs +2 -2
  44. package/esm2022/tableview/action/components/table/action-table.component.mjs +3 -3
  45. package/esm2022/tableview/api/editor/descriptors/field-base.descriptor.mjs +1 -3
  46. package/esm2022/tableview/api/editor/descriptors/field.descriptor.mjs +14 -1
  47. package/esm2022/tableview/api/editor/models/editor-fields.model.mjs +1 -1
  48. package/esm2022/tableview/api/editor/models/field-image-preview.model.mjs +2 -0
  49. package/esm2022/tableview/api/index.mjs +2 -1
  50. package/esm2022/tableview/api/tableview/descriptors/tableview.descriptor.mjs +11 -13
  51. package/esm2022/tableview/editor/components/formly/fields/formly-field-autocomplete/formly-field-autocomplete.component.mjs +3 -3
  52. package/esm2022/tableview/editor/components/formly/fields/formly-field-datepicker/formly-field-datepicker.component.mjs +3 -3
  53. package/esm2022/tableview/editor/components/formly/fields/formly-field-dropdown/formly-field-dropdown.component.mjs +3 -3
  54. package/esm2022/tableview/editor/components/formly/fields/formly-field-input/formly-field-input.component.mjs +9 -3
  55. package/esm2022/tableview/editor/components/formly/fields/formly-field-lookup-dialog/formly-field-lookup-dialog.component.mjs +3 -3
  56. package/esm2022/tableview/editor/components/formly/fields/formly-field-table-dialog-form/formly-field-table-dialog-form.component.mjs +3 -3
  57. package/esm2022/tableview/editor/components/formly/fields/formly-field-table-dialog-multiselect/formly-field-table-dialog-multiselect.component.mjs +3 -3
  58. package/esm2022/tableview/tableview/components/tableview/tableview.component.mjs +3 -4
  59. package/fesm2022/mediusinc-mng-commons-core.mjs +32 -4
  60. package/fesm2022/mediusinc-mng-commons-core.mjs.map +1 -1
  61. package/fesm2022/mediusinc-mng-commons-filter.mjs +81 -32
  62. package/fesm2022/mediusinc-mng-commons-filter.mjs.map +1 -1
  63. package/fesm2022/mediusinc-mng-commons-form.mjs +149 -117
  64. package/fesm2022/mediusinc-mng-commons-form.mjs.map +1 -1
  65. package/fesm2022/mediusinc-mng-commons-table-api.mjs +22 -20
  66. package/fesm2022/mediusinc-mng-commons-table-api.mjs.map +1 -1
  67. package/fesm2022/mediusinc-mng-commons-table.mjs +833 -360
  68. package/fesm2022/mediusinc-mng-commons-table.mjs.map +1 -1
  69. package/fesm2022/mediusinc-mng-commons-tableview-api.mjs +23 -14
  70. package/fesm2022/mediusinc-mng-commons-tableview-api.mjs.map +1 -1
  71. package/fesm2022/mediusinc-mng-commons-tableview.mjs +27 -22
  72. package/fesm2022/mediusinc-mng-commons-tableview.mjs.map +1 -1
  73. package/filter/descriptors/filter.descriptor.d.ts +60 -16
  74. package/filter/models/filter.model.d.ts +4 -0
  75. package/form/components/date-range/date-range.component.d.ts +9 -3
  76. package/form/components/dropdown/dropdown.component.d.ts +6 -7
  77. package/form/components/number-range/number-range.component.d.ts +8 -4
  78. package/i18n/en.json +32 -0
  79. package/i18n/sl.json +32 -0
  80. package/package.json +1 -1
  81. package/table/api/descriptors/table.descriptor.d.ts +15 -8
  82. package/table/api/index.d.ts +1 -0
  83. package/table/api/models/row-expandable-component.model.d.ts +4 -0
  84. package/table/api/models/table-columns.model.d.ts +3 -3
  85. package/table/api/models/table.model.d.ts +0 -12
  86. package/table/components/{column-filter-full/column-filter-full.component.d.ts → column-filter/column-filter.component.d.ts} +23 -38
  87. package/table/components/filter/filter-active-tag/filter-active-tag.component.d.ts +20 -0
  88. package/table/components/filter/filter-form/filter-form.component.d.ts +53 -0
  89. package/table/components/filter/filter-overlay-with-tag/filter-overlay-with-tag.component.d.ts +35 -0
  90. package/table/components/table/table.component.d.ts +10 -7
  91. package/table/helpers/filters.d.ts +31 -0
  92. package/table/index.d.ts +10 -1
  93. package/table/models/filter.model.d.ts +24 -0
  94. package/table/pipes/filter-value.pipe.d.ts +19 -0
  95. package/table/provide.d.ts +8 -0
  96. package/table/services/data-list.service.d.ts +3 -2
  97. package/table/services/table-feature-config.token.d.ts +6 -0
  98. package/tableview/api/editor/descriptors/field-base.descriptor.d.ts +4 -4
  99. package/tableview/api/editor/descriptors/field.descriptor.d.ts +13 -3
  100. package/tableview/api/editor/models/editor-fields.model.d.ts +4 -4
  101. package/tableview/api/editor/models/field-image-preview.model.d.ts +4 -0
  102. package/tableview/api/index.d.ts +1 -0
  103. package/tableview/api/tableview/descriptors/tableview.descriptor.d.ts +8 -6
  104. package/tableview/editor/components/formly/fields/formly-field-input/formly-field-input.component.d.ts +1 -0
  105. package/version-info.json +5 -5
  106. package/esm2022/table/components/column-filter-full/column-filter-full.component.mjs +0 -655
@@ -0,0 +1,135 @@
1
+ import { NgTemplateOutlet } from '@angular/common';
2
+ import { ChangeDetectionStrategy, Component, computed, contentChildren, inject, input, signal, viewChild } from '@angular/core';
3
+ import { TranslateModule } from '@ngx-translate/core';
4
+ import { Button } from 'primeng/button';
5
+ import { OverlayPanel, OverlayPanelModule } from 'primeng/overlaypanel';
6
+ import { Table } from 'primeng/table';
7
+ import { TagModule } from 'primeng/tag';
8
+ import { COMMONS_MODULE_CONFIG_IT, FilterMatchMode, TemplateDirective, findTemplateByName } from '@mediusinc/mng-commons/core';
9
+ import { filterApplySerializationConfigToCmp, filterGetDateConfig, filterSetMetadataOnChange, filterSetMetadataOnDisplayChange } from '../../../helpers/filters';
10
+ import { DataListService } from '../../../services/data-list.service';
11
+ import { FilterActiveTagComponent } from '../filter-active-tag/filter-active-tag.component';
12
+ import { FilterFormComponent } from '../filter-form/filter-form.component';
13
+ import * as i0 from "@angular/core";
14
+ import * as i1 from "primeng/overlaypanel";
15
+ export class FilterOverlayWithTagComponent {
16
+ constructor() {
17
+ this.primeTable = inject(Table);
18
+ this.dataListService = inject((DataListService));
19
+ this.moduleConfig = inject(COMMONS_MODULE_CONFIG_IT, { optional: true });
20
+ this.descriptors = input.required();
21
+ this.model = input.required();
22
+ this.filterOverlay = viewChild.required(OverlayPanel);
23
+ this.templates = contentChildren(TemplateDirective);
24
+ this.titleTemplate = computed(() => findTemplateByName([...this.templates()], 'title'));
25
+ this.filters = computed(() => {
26
+ return this.setInitialFilters(this.dataListService.filterMeta());
27
+ });
28
+ this.activeFilters = computed(() => {
29
+ const filterEntry = this.filters();
30
+ return this.descriptors()
31
+ .filter(d => {
32
+ const filter = filterEntry[d.property];
33
+ return (filter &&
34
+ filter.matchMode !== undefined &&
35
+ filter.displayMatchMode !== undefined &&
36
+ (filter.matchMode === FilterMatchMode.Exists ||
37
+ filter.matchMode === FilterMatchMode.DoesNotExist ||
38
+ (filter.value !== undefined && filter.displayValue !== undefined)));
39
+ })
40
+ .map(d => filterEntry[d.property]);
41
+ });
42
+ this.activeFilterProperties = computed(() => this.activeFilters().map(f => f.descriptor.property));
43
+ this.filterEdit = signal(undefined);
44
+ this.serializationCfg = {};
45
+ // UI utilities
46
+ this.clickedOnFilterEvent = undefined;
47
+ filterApplySerializationConfigToCmp(this.moduleConfig, this.serializationCfg);
48
+ }
49
+ onFilterFormApply(event) {
50
+ const descriptor = this.descriptors().find(d => d.property === event.property);
51
+ if (!descriptor) {
52
+ return;
53
+ }
54
+ this.updatePrimeTableFilter({
55
+ ...filterSetMetadataOnDisplayChange({ caseSensitive: event.caseSensitive }, event.matchMode, event.value, descriptor.filterType, filterGetDateConfig(descriptor, this.serializationCfg)),
56
+ descriptor: descriptor
57
+ });
58
+ // Resetting the form is done in the onOverlayHide callback because resetting the
59
+ // values here renders empty inputs for a split second before closing the overlay
60
+ this.filterOverlay().hide();
61
+ }
62
+ onFilterRemove(event) {
63
+ this.updatePrimeTableFilter({
64
+ ...this.filters()[event.filter.descriptor.property],
65
+ matchMode: undefined,
66
+ displayMatchMode: undefined,
67
+ value: undefined,
68
+ displayValue: undefined
69
+ });
70
+ }
71
+ onFilterEdit(event) {
72
+ this.onFilterAddOrEdit(event.filter, event.event);
73
+ }
74
+ onFilterAdd(event) {
75
+ this.onFilterAddOrEdit(undefined, event);
76
+ }
77
+ onOverlayHide() {
78
+ if (this.clickedOnFilterEvent) {
79
+ // show the overlay again if the user clicked another filter
80
+ setTimeout(() => {
81
+ this.filterOverlay().show(this.clickedOnFilterEvent);
82
+ this.clickedOnFilterEvent = undefined;
83
+ }, 0);
84
+ return;
85
+ }
86
+ else {
87
+ // clean state
88
+ this.filterEdit.set(undefined);
89
+ }
90
+ }
91
+ onFilterAddOrEdit(filter, event) {
92
+ // If user clicks on the same filter or add that is already open, close the overlay
93
+ if (this.filterOverlay().overlayVisible && this.filterEdit()?.descriptor.property === filter?.descriptor.property) {
94
+ this.filterOverlay().hide();
95
+ this.filterEdit.set(undefined);
96
+ return;
97
+ }
98
+ this.filterEdit.set(filter);
99
+ if (this.filterOverlay().overlayVisible) {
100
+ // In case the user clicks another filter, 're-showing' the overlay in
101
+ // the new position is done in the onOverlayHide callback
102
+ this.clickedOnFilterEvent = event;
103
+ this.filterOverlay().hide();
104
+ }
105
+ else {
106
+ this.filterOverlay().show(event);
107
+ }
108
+ }
109
+ setInitialFilters(filtersInit) {
110
+ const filtersResult = {};
111
+ for (const property in filtersInit) {
112
+ const filterInit = filtersInit[property];
113
+ const descriptor = this.descriptors().find(filterDescriptor => filterDescriptor.property === property);
114
+ if (!descriptor) {
115
+ continue;
116
+ }
117
+ filtersResult[property] = {
118
+ ...filterSetMetadataOnChange(filterInit, filterInit.matchMode, filterInit.value, descriptor.filterType, filterGetDateConfig(descriptor, this.serializationCfg)),
119
+ descriptor: descriptor
120
+ };
121
+ }
122
+ return filtersResult;
123
+ }
124
+ updatePrimeTableFilter(filter) {
125
+ this.primeTable.filters[filter.descriptor.property] = { ...filter };
126
+ this.primeTable._filter();
127
+ }
128
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: FilterOverlayWithTagComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
129
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.5", type: FilterOverlayWithTagComponent, isStandalone: true, selector: "mng-filter-overlay-with-tag", inputs: { descriptors: { classPropertyName: "descriptors", publicName: "descriptors", isSignal: true, isRequired: true, transformFunction: null }, model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: true, transformFunction: null } }, queries: [{ propertyName: "templates", predicate: TemplateDirective, isSignal: true }], viewQueries: [{ propertyName: "filterOverlay", first: true, predicate: OverlayPanel, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"flex align-items-center flex-grow-1\">\n @if (titleTemplate()) {\n <ng-container *ngTemplateOutlet=\"titleTemplate()\"></ng-container>\n }\n <p-button\n icon=\"pi pi-filter\"\n rounded=\"true\"\n [severity]=\"activeFilters().length > 0 ? 'primary' : 'secondary'\"\n size=\"small\"\n (click)=\"onFilterAdd($event)\"\n [styleClass]=\"'my-1 mr-2' + (titleTemplate() ? ' ml-3' : '')\">\n </p-button>\n</div>\n@if (activeFilters().length > 0) {\n <div class=\"flex align-items-center flex-wrap mt-2\">\n @for (filter of activeFilters(); track filter.descriptor.property) {\n <mng-filter-active-tag [model]=\"model()\" [filter]=\"filter\" (edit)=\"onFilterEdit($event)\" (remove)=\"onFilterRemove($event)\" />\n }\n </div>\n}\n<p-overlayPanel #op [showCloseIcon]=\"true\" (onHide)=\"onOverlayHide()\" appendTo=\"body\">\n <mng-filter-form\n [model]=\"model()\"\n [descriptors]=\"descriptors()\"\n [filter]=\"filterEdit()\"\n [disabledProperties]=\"activeFilterProperties()\"\n [overlay]=\"op\"\n (apply)=\"onFilterFormApply($event)\" />\n</p-overlayPanel>\n", dependencies: [{ kind: "ngmodule", type: OverlayPanelModule }, { kind: "component", type: i1.OverlayPanel, selector: "p-overlayPanel", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "showCloseIcon", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: TagModule }, { kind: "component", type: FilterFormComponent, selector: "mng-filter-form", inputs: ["title", "descriptors", "model", "filter", "overlay", "disabledProperties"], outputs: ["apply"] }, { kind: "component", type: Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "raised", "rounded", "text", "plain", "severity", "outlined", "link", "tabindex", "size", "style", "styleClass", "badgeClass", "ariaLabel", "autofocus"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: FilterActiveTagComponent, selector: "mng-filter-active-tag", inputs: ["model", "filter"], outputs: ["edit", "remove"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
130
+ }
131
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.5", ngImport: i0, type: FilterOverlayWithTagComponent, decorators: [{
132
+ type: Component,
133
+ args: [{ standalone: true, selector: 'mng-filter-overlay-with-tag', imports: [OverlayPanelModule, TranslateModule, TagModule, FilterFormComponent, Button, FilterActiveTagComponent, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"flex align-items-center flex-grow-1\">\n @if (titleTemplate()) {\n <ng-container *ngTemplateOutlet=\"titleTemplate()\"></ng-container>\n }\n <p-button\n icon=\"pi pi-filter\"\n rounded=\"true\"\n [severity]=\"activeFilters().length > 0 ? 'primary' : 'secondary'\"\n size=\"small\"\n (click)=\"onFilterAdd($event)\"\n [styleClass]=\"'my-1 mr-2' + (titleTemplate() ? ' ml-3' : '')\">\n </p-button>\n</div>\n@if (activeFilters().length > 0) {\n <div class=\"flex align-items-center flex-wrap mt-2\">\n @for (filter of activeFilters(); track filter.descriptor.property) {\n <mng-filter-active-tag [model]=\"model()\" [filter]=\"filter\" (edit)=\"onFilterEdit($event)\" (remove)=\"onFilterRemove($event)\" />\n }\n </div>\n}\n<p-overlayPanel #op [showCloseIcon]=\"true\" (onHide)=\"onOverlayHide()\" appendTo=\"body\">\n <mng-filter-form\n [model]=\"model()\"\n [descriptors]=\"descriptors()\"\n [filter]=\"filterEdit()\"\n [disabledProperties]=\"activeFilterProperties()\"\n [overlay]=\"op\"\n (apply)=\"onFilterFormApply($event)\" />\n</p-overlayPanel>\n" }]
134
+ }], ctorParameters: () => [] });
135
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsdGVyLW92ZXJsYXktd2l0aC10YWcuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vdGFibGUvc3JjL2NvbXBvbmVudHMvZmlsdGVyL2ZpbHRlci1vdmVybGF5LXdpdGgtdGFnL2ZpbHRlci1vdmVybGF5LXdpdGgtdGFnLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3RhYmxlL3NyYy9jb21wb25lbnRzL2ZpbHRlci9maWx0ZXItb3ZlcmxheS13aXRoLXRhZy9maWx0ZXItb3ZlcmxheS13aXRoLXRhZy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUNqRCxPQUFPLEVBQUMsdUJBQXVCLEVBQUUsU0FBUyxFQUF1QixRQUFRLEVBQUUsZUFBZSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUVuSixPQUFPLEVBQUMsZUFBZSxFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFDcEQsT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQ3RDLE9BQU8sRUFBQyxZQUFZLEVBQUUsa0JBQWtCLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUN0RSxPQUFPLEVBQUMsS0FBSyxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3BDLE9BQU8sRUFBQyxTQUFTLEVBQUMsTUFBTSxhQUFhLENBQUM7QUFFdEMsT0FBTyxFQUFDLHdCQUF3QixFQUFxRCxlQUFlLEVBQUUsaUJBQWlCLEVBQUUsa0JBQWtCLEVBQUMsTUFBTSw2QkFBNkIsQ0FBQztBQUloTCxPQUFPLEVBQUMsbUNBQW1DLEVBQUUsbUJBQW1CLEVBQUUseUJBQXlCLEVBQUUsZ0NBQWdDLEVBQUMsTUFBTSwwQkFBMEIsQ0FBQztBQUUvSixPQUFPLEVBQUMsZUFBZSxFQUFDLE1B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LHdCQUF3QixFQUFFLGdCQUFnQixDQUFDLG1CQUNqSCx1QkFBdUIsQ0FBQyxNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtOZ1RlbXBsYXRlT3V0bGV0fSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBTaWduYWwsIFRlbXBsYXRlUmVmLCBjb21wdXRlZCwgY29udGVudENoaWxkcmVuLCBpbmplY3QsIGlucHV0LCBzaWduYWwsIHZpZXdDaGlsZH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7VHJhbnNsYXRlTW9kdWxlfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJztcbmltcG9ydCB7QnV0dG9ufSBmcm9tICdwcmltZW5nL2J1dHRvbic7XG5pbXBvcnQge092ZXJsYXlQYW5lbCwgT3ZlcmxheVBhbmVsTW9kdWxlfSBmcm9tICdwcmltZW5nL292ZXJsYXlwYW5lbCc7XG5pbXBvcnQge1RhYmxlfSBmcm9tICdwcmltZW5nL3RhYmxlJztcbmltcG9ydCB7VGFnTW9kdWxlfSBmcm9tICdwcmltZW5nL3RhZyc7XG5cbmltcG9ydCB7Q09NTU9OU19NT0RVTEVfQ09ORklHX0lULCBDb21tb25zRmlsdGVyTWV0YWRhdGEsIENvbW1vbnNTZXJpYWxpemF0aW9uQ29uZmlnLCBGaWx0ZXJNYXRjaE1vZGUsIFRlbXBsYXRlRGlyZWN0aXZlLCBmaW5kVGVtcGxhdGVCeU5hbWV9IGZyb20gJ0BtZWRpdXNpbmMvbW5nLWNvbW1vbnMvY29yZSc7XG5pbXBvcnQge0ZpbHRlckRlc2NyaXB0b3J9IGZyb20gJ0BtZWRpdXNpbmMvbW5nLWNvbW1vbnMvZmlsdGVyJztcbmltcG9ydCB7TW9kZWxEZXNjcmlwdG9yfSBmcm9tICdAbWVkaXVzaW5jL21uZy1jb21tb25zL21vZGVsJztcblxuaW1wb3J0IHtmaWx0ZXJBcHBseVNlcmlhbGl6YXRpb25Db25maWdUb0NtcCwgZmlsdGVyR2V0RGF0ZUNvbmZpZywgZmlsdGVyU2V0TWV0YWRhdGFPbkNoYW5nZSwgZmlsdGVyU2V0TWV0YWRhdGFPbkRpc3BsYXlDaGFuZ2V9IGZyb20gJy4uLy4uLy4uL2hlbHBlcnMvZmlsdGVycyc7XG5pbXBvcnQge0NvbW1vbnNGaWx0ZXJNZXRhZGF0YVdpdGhEZXNjcmlwdG9yLCBGaWx0ZXJBY3RpdmVUYWdFdmVudCwgRmlsdGVyRm9ybUVtaXRFdmVudH0gZnJvbSAnLi4vLi4vLi4vbW9kZWxzL2ZpbHRlci5tb2RlbCc7XG5pbXBvcnQge0RhdGFMaXN0U2VydmljZX0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvZGF0YS1saXN0LnNlcnZpY2UnO1xuaW1wb3J0IHtGaWx0ZXJBY3RpdmVUYWdDb21wb25lbnR9IGZyb20gJy4uL2ZpbHRlci1hY3RpdmUtdGFnL2ZpbHRlci1hY3RpdmUtdGFnLmNvbXBvbmVudCc7XG5pbXBvcnQge0ZpbHRlckZvcm1Db21wb25lbnR9IGZyb20gJy4uL2ZpbHRlci1mb3JtL2ZpbHRlci1mb3JtLmNvbXBvbmVudCc7XG5cbkBDb21wb25lbnQoe1xuICAgIHN0YW5kYWxvbmU6IHRydWUsXG4gICAgc2VsZWN0b3I6ICdtbmctZmlsdGVyLW92ZXJsYXktd2l0aC10YWcnLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9maWx0ZXItb3ZlcmxheS13aXRoLXRhZy5jb21wb25lbnQuaHRtbCcsXG4gICAgaW1wb3J0czogW092ZXJsYXlQYW5lbE1vZHVsZSwgVHJhbnNsYXRlTW9kdWxlLCBUYWdNb2R1bGUsIEZpbHRlckZvcm1Db21wb25lbnQsIEJ1dHRvbiwgRmlsdGVyQWN0aXZlVGFnQ29tcG9uZW50LCBOZ1RlbXBsYXRlT3V0bGV0XSxcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaFxufSlcbmV4cG9ydCBjbGFzcyBGaWx0ZXJPdmVybGF5V2l0aFRhZ0NvbXBvbmVudCB7XG4gICAgcHJpdmF0ZSByZWFkb25seSBwcmltZVRhYmxlID0gaW5qZWN0KFRhYmxlKTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IGRhdGFMaXN0U2VydmljZSA9IGluamVjdChEYXRhTGlzdFNlcnZpY2U8YW55Pik7XG4gICAgcHJpdmF0ZSByZWFkb25seSBtb2R1bGVDb25maWcgPSBpbmplY3QoQ09NTU9OU19NT0RVTEVfQ09ORklHX0lULCB7b3B0aW9uYWw6IHRydWV9KTtcblxuICAgIHB1YmxpYyBkZXNjcmlwdG9ycyA9IGlucHV0LnJlcXVpcmVkPEZpbHRlckRlc2NyaXB0b3I8YW55LCBhbnk+W10+KCk7XG4gICAgcHVibGljIG1vZGVsID0gaW5wdXQucmVxdWlyZWQ8TW9kZWxEZXNjcmlwdG9yPGFueT4+KCk7XG5cbiAgICBwcml2YXRlIGZpbHRlck92ZXJsYXkgPSB2aWV3Q2hpbGQucmVxdWlyZWQoT3ZlcmxheVBhbmVsKTtcblxuICAgIHB1YmxpYyB0ZW1wbGF0ZXMgPSBjb250ZW50Q2hpbGRyZW4oVGVtcGxhdGVEaXJlY3RpdmUpO1xuICAgIHB1YmxpYyB0aXRsZVRlbXBsYXRlOiBTaWduYWw8VGVtcGxhdGVSZWY8YW55PiB8IG51bGw+ID0gY29tcHV0ZWQoKCkgPT4gZmluZFRlbXBsYXRlQnlOYW1lKFsuLi50aGlzLnRlbXBsYXRlcygpXSwgJ3RpdGxlJykpO1xuXG4gICAgcHVibGljIGZpbHRlcnMgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLnNldEluaXRpYWxGaWx0ZXJzKHRoaXMuZGF0YUxpc3RTZXJ2aWNlLmZpbHRlck1ldGEoKSk7XG4gICAgfSk7XG5cbiAgICBwdWJsaWMgYWN0aXZlRmlsdGVycyA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICAgICAgY29uc3QgZmlsdGVyRW50cnkgPSB0aGlzLmZpbHRlcnMoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGVzY3JpcHRvcnMoKVxuICAgICAgICAgICAgLmZpbHRlcihkID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBmaWx0ZXIgPSBmaWx0ZXJFbnRyeVtkLnByb3BlcnR5XTtcbiAgICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgICAgICBmaWx0ZXIgJiZcbiAgICAgICAgICAgICAgICAgICAgZmlsdGVyLm1hdGNoTW9kZSAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICAgICAgICAgIGZpbHRlci5kaXNwbGF5TWF0Y2hNb2RlICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgKGZpbHRlci5tYXRjaE1vZGUgPT09IEZpbHRlck1hdGNoTW9kZS5FeGlzdHMgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlci5tYXRjaE1vZGUgPT09IEZpbHRlck1hdGNoTW9kZS5Eb2VzTm90RXhpc3QgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIChmaWx0ZXIudmFsdWUgIT09IHVuZGVmaW5lZCAmJiBmaWx0ZXIuZGlzcGxheVZhbHVlICE9PSB1bmRlZmluZWQpKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLm1hcChkID0+IGZpbHRlckVudHJ5W2QucHJvcGVydHldISk7XG4gICAgfSk7XG4gICAgcHVibGljIGFjdGl2ZUZpbHRlclByb3BlcnRpZXMgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmFjdGl2ZUZpbHRlcnMoKS5tYXAoZiA9PiBmLmRlc2NyaXB0b3IucHJvcGVydHkpKTtcbiAgICBwdWJsaWMgZmlsdGVyRWRpdCA9IHNpZ25hbDxDb21tb25zRmlsdGVyTWV0YWRhdGFXaXRoRGVzY3JpcHRvciB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKTtcblxuICAgIHByaXZhdGUgc2VyaWFsaXphdGlvbkNmZzogQ29tbW9uc1NlcmlhbGl6YXRpb25Db25maWcgPSB7fTtcblxuICAgIC8vIFVJIHV0aWxpdGllc1xuICAgIHByaXZhdGUgY2xpY2tlZE9uRmlsdGVyRXZlbnQ6IEV2ZW50IHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIGZpbHRlckFwcGx5U2VyaWFsaXphdGlvbkNvbmZpZ1RvQ21wKHRoaXMubW9kdWxlQ29uZmlnLCB0aGlzLnNlcmlhbGl6YXRpb25DZmcpO1xuICAgIH1cblxuICAgIG9uRmlsdGVyRm9ybUFwcGx5KGV2ZW50OiBGaWx0ZXJGb3JtRW1pdEV2ZW50KSB7XG4gICAgICAgIGNvbnN0IGRlc2NyaXB0b3IgPSB0aGlzLmRlc2NyaXB0b3JzKCkuZmluZChkID0+IGQucHJvcGVydHkgPT09IGV2ZW50LnByb3BlcnR5KTtcbiAgICAgICAgaWYgKCFkZXNjcmlwdG9yKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnVwZGF0ZVByaW1lVGFibGVGaWx0ZXIoe1xuICAgICAgICAgICAgLi4uZmlsdGVyU2V0TWV0YWRhdGFPbkRpc3BsYXlDaGFuZ2UoXG4gICAgICAgICAgICAgICAge2Nhc2VTZW5zaXRpdmU6IGV2ZW50LmNhc2VTZW5zaXRpdmV9LFxuICAgICAgICAgICAgICAgIGV2ZW50Lm1hdGNoTW9kZSxcbiAgICAgICAgICAgICAgICBldmVudC52YWx1ZSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdG9yLmZpbHRlclR5cGUsXG4gICAgICAgICAgICAgICAgZmlsdGVyR2V0RGF0ZUNvbmZpZyhkZXNjcmlwdG9yLCB0aGlzLnNlcmlhbGl6YXRpb25DZmcpXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgZGVzY3JpcHRvcjogZGVzY3JpcHRvclxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBSZXNldHRpbmcgdGhlIGZvcm0gaXMgZG9uZSBpbiB0aGUgb25PdmVybGF5SGlkZSBjYWxsYmFjayBiZWNhdXNlIHJlc2V0dGluZyB0aGVcbiAgICAgICAgLy8gdmFsdWVzIGhlcmUgcmVuZGVycyBlbXB0eSBpbnB1dHMgZm9yIGEgc3BsaXQgc2Vjb25kIGJlZm9yZSBjbG9zaW5nIHRoZSBvdmVybGF5XG4gICAgICAgIHRoaXMuZmlsdGVyT3ZlcmxheSgpLmhpZGUoKTtcbiAgICB9XG5cbiAgICBvbkZpbHRlclJlbW92ZShldmVudDogRmlsdGVyQWN0aXZlVGFnRXZlbnQpIHtcbiAgICAgICAgdGhpcy51cGRhdGVQcmltZVRhYmxlRmlsdGVyKHtcbiAgICAgICAgICAgIC4uLnRoaXMuZmlsdGVycygpW2V2ZW50LmZpbHRlci5kZXNjcmlwdG9yLnByb3BlcnR5XSxcbiAgICAgICAgICAgIG1hdGNoTW9kZTogdW5kZWZpbmVkLFxuICAgICAgICAgICAgZGlzcGxheU1hdGNoTW9kZTogdW5kZWZpbmVkLFxuICAgICAgICAgICAgdmFsdWU6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGRpc3BsYXlWYWx1ZTogdW5kZWZpbmVkXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIG9uRmlsdGVyRWRpdChldmVudDogRmlsdGVyQWN0aXZlVGFnRXZlbnQpIHtcbiAgICAgICAgdGhpcy5vbkZpbHRlckFkZE9yRWRpdChldmVudC5maWx0ZXIsIGV2ZW50LmV2ZW50KTtcbiAgICB9XG5cbiAgICBvbkZpbHRlckFkZChldmVudDogRXZlbnQpIHtcbiAgICAgICAgdGhpcy5vbkZpbHRlckFkZE9yRWRpdCh1bmRlZmluZWQsIGV2ZW50KTtcbiAgICB9XG5cbiAgICBvbk92ZXJsYXlIaWRlKCkge1xuICAgICAgICBpZiAodGhpcy5jbGlja2VkT25GaWx0ZXJFdmVudCkge1xuICAgICAgICAgICAgLy8gc2hvdyB0aGUgb3ZlcmxheSBhZ2FpbiBpZiB0aGUgdXNlciBjbGlja2VkIGFub3RoZXIgZmlsdGVyXG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmZpbHRlck92ZXJsYXkoKS5zaG93KHRoaXMuY2xpY2tlZE9uRmlsdGVyRXZlbnQpO1xuICAgICAgICAgICAgICAgIHRoaXMuY2xpY2tlZE9uRmlsdGVyRXZlbnQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9LCAwKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGNsZWFuIHN0YXRlXG4gICAgICAgICAgICB0aGlzLmZpbHRlckVkaXQuc2V0KHVuZGVmaW5lZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIG9uRmlsdGVyQWRkT3JFZGl0KGZpbHRlcj86IENvbW1vbnNGaWx0ZXJNZXRhZGF0YVdpdGhEZXNjcmlwdG9yLCBldmVudD86IEV2ZW50KSB7XG4gICAgICAgIC8vIElmIHVzZXIgY2xpY2tzIG9uIHRoZSBzYW1lIGZpbHRlciBvciBhZGQgdGhhdCBpcyBhbHJlYWR5IG9wZW4sIGNsb3NlIHRoZSBvdmVybGF5XG4gICAgICAgIGlmICh0aGlzLmZpbHRlck92ZXJsYXkoKS5vdmVybGF5VmlzaWJsZSAmJiB0aGlzLmZpbHRlckVkaXQoKT8uZGVzY3JpcHRvci5wcm9wZXJ0eSA9PT0gZmlsdGVyPy5kZXNjcmlwdG9yLnByb3BlcnR5KSB7XG4gICAgICAgICAgICB0aGlzLmZpbHRlck92ZXJsYXkoKS5oaWRlKCk7XG4gICAgICAgICAgICB0aGlzLmZpbHRlckVkaXQuc2V0KHVuZGVmaW5lZCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmZpbHRlckVkaXQuc2V0KGZpbHRlcik7XG4gICAgICAgIGlmICh0aGlzLmZpbHRlck92ZXJsYXkoKS5vdmVybGF5VmlzaWJsZSkge1xuICAgICAgICAgICAgLy8gSW4gY2FzZSB0aGUgdXNlciBjbGlja3MgYW5vdGhlciBmaWx0ZXIsICdyZS1zaG93aW5nJyB0aGUgb3ZlcmxheSBpblxuICAgICAgICAgICAgLy8gdGhlIG5ldyBwb3NpdGlvbiBpcyBkb25lIGluIHRoZSBvbk92ZXJsYXlIaWRlIGNhbGxiYWNrXG4gICAgICAgICAgICB0aGlzLmNsaWNrZWRPbkZpbHRlckV2ZW50ID0gZXZlbnQ7XG4gICAgICAgICAgICB0aGlzLmZpbHRlck92ZXJsYXkoKS5oaWRlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmZpbHRlck92ZXJsYXkoKS5zaG93KGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgc2V0SW5pdGlhbEZpbHRlcnMoZmlsdGVyc0luaXQ6IFJlY29yZDxzdHJpbmcsIENvbW1vbnNGaWx0ZXJNZXRhZGF0YT4pIHtcbiAgICAgICAgY29uc3QgZmlsdGVyc1Jlc3VsdDoge1twOiBzdHJpbmddOiBDb21tb25zRmlsdGVyTWV0YWRhdGFXaXRoRGVzY3JpcHRvcn0gPSB7fTtcblxuICAgICAgICBmb3IgKGNvbnN0IHByb3BlcnR5IGluIGZpbHRlcnNJbml0KSB7XG4gICAgICAgICAgICBjb25zdCBmaWx0ZXJJbml0ID0gZmlsdGVyc0luaXRbcHJvcGVydHldO1xuXG4gICAgICAgICAgICBjb25zdCBkZXNjcmlwdG9yID0gdGhpcy5kZXNjcmlwdG9ycygpLmZpbmQoZmlsdGVyRGVzY3JpcHRvciA9PiBmaWx0ZXJEZXNjcmlwdG9yLnByb3BlcnR5ID09PSBwcm9wZXJ0eSk7XG4gICAgICAgICAgICBpZiAoIWRlc2NyaXB0b3IpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZmlsdGVyc1Jlc3VsdFtwcm9wZXJ0eV0gPSB7XG4gICAgICAgICAgICAgICAgLi4uZmlsdGVyU2V0TWV0YWRhdGFPbkNoYW5nZShmaWx0ZXJJbml0LCBmaWx0ZXJJbml0Lm1hdGNoTW9kZSwgZmlsdGVySW5pdC52YWx1ZSwgZGVzY3JpcHRvci5maWx0ZXJUeXBlLCBmaWx0ZXJHZXREYXRlQ29uZmlnKGRlc2NyaXB0b3IsIHRoaXMuc2VyaWFsaXphdGlvbkNmZykpLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0b3I6IGRlc2NyaXB0b3JcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmlsdGVyc1Jlc3VsdDtcbiAgICB9XG5cbiAgICBwcml2YXRlIHVwZGF0ZVByaW1lVGFibGVGaWx0ZXIoZmlsdGVyOiBDb21tb25zRmlsdGVyTWV0YWRhdGFXaXRoRGVzY3JpcHRvcikge1xuICAgICAgICB0aGlzLnByaW1lVGFibGUuZmlsdGVyc1tmaWx0ZXIuZGVzY3JpcHRvci5wcm9wZXJ0eV0gPSB7Li4uZmlsdGVyfTtcbiAgICAgICAgdGhpcy5wcmltZVRhYmxlLl9maWx0ZXIoKTtcbiAgICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwiZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIgZmxleC1ncm93LTFcIj5cbiAgICBAaWYgKHRpdGxlVGVtcGxhdGUoKSkge1xuICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidGl0bGVUZW1wbGF0ZSgpXCI+PC9uZy1jb250YWluZXI+XG4gICAgfVxuICAgIDxwLWJ1dHRvblxuICAgICAgICBpY29uPVwicGkgcGktZmlsdGVyXCJcbiAgICAgICAgcm91bmRlZD1cInRydWVcIlxuICAgICAgICBbc2V2ZXJpdHldPVwiYWN0aXZlRmlsdGVycygpLmxlbmd0aCA+IDAgPyAncHJpbWFyeScgOiAnc2Vjb25kYXJ5J1wiXG4gICAgICAgIHNpemU9XCJzbWFsbFwiXG4gICAgICAgIChjbGljayk9XCJvbkZpbHRlckFkZCgkZXZlbnQpXCJcbiAgICAgICAgW3N0eWxlQ2xhc3NdPVwiJ215LTEgbXItMicgKyAodGl0bGVUZW1wbGF0ZSgpID8gJyBtbC0zJyA6ICcnKVwiPlxuICAgIDwvcC1idXR0b24+XG48L2Rpdj5cbkBpZiAoYWN0aXZlRmlsdGVycygpLmxlbmd0aCA+IDApIHtcbiAgICA8ZGl2IGNsYXNzPVwiZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIgZmxleC13cmFwIG10LTJcIj5cbiAgICAgICAgQGZvciAoZmlsdGVyIG9mIGFjdGl2ZUZpbHRlcnMoKTsgdHJhY2sgZmlsdGVyLmRlc2NyaXB0b3IucHJvcGVydHkpIHtcbiAgICAgICAgICAgIDxtbmctZmlsdGVyLWFjdGl2ZS10YWcgW21vZGVsXT1cIm1vZGVsKClcIiBbZmlsdGVyXT1cImZpbHRlclwiIChlZGl0KT1cIm9uRmlsdGVyRWRpdCgkZXZlbnQpXCIgKHJlbW92ZSk9XCJvbkZpbHRlclJlbW92ZSgkZXZlbnQpXCIgLz5cbiAgICAgICAgfVxuICAgIDwvZGl2PlxufVxuPHAtb3ZlcmxheVBhbmVsICNvcCBbc2hvd0Nsb3NlSWNvbl09XCJ0cnVlXCIgKG9uSGlkZSk9XCJvbk92ZXJsYXlIaWRlKClcIiBhcHBlbmRUbz1cImJvZHlcIj5cbiAgICA8bW5nLWZpbHRlci1mb3JtXG4gICAgICAgIFttb2RlbF09XCJtb2RlbCgpXCJcbiAgICAgICAgW2Rlc2NyaXB0b3JzXT1cImRlc2NyaXB0b3JzKClcIlxuICAgICAgICBbZmlsdGVyXT1cImZpbHRlckVkaXQoKVwiXG4gICAgICAgIFtkaXNhYmxlZFByb3BlcnRpZXNdPVwiYWN0aXZlRmlsdGVyUHJvcGVydGllcygpXCJcbiAgICAgICAgW292ZXJsYXldPVwib3BcIlxuICAgICAgICAoYXBwbHkpPVwib25GaWx0ZXJGb3JtQXBwbHkoJGV2ZW50KVwiIC8+XG48L3Atb3ZlcmxheVBhbmVsPlxuIl19