techlify-inventory-common 18.1.0 → 18.2.0

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 (53) hide show
  1. package/esm2022/lib/inventory-common/inventory-common-routing.module.mjs +11 -1
  2. package/esm2022/lib/inventory-common/inventory-common.module.mjs +8 -4
  3. package/esm2022/lib/inventory-common/inventory-dashboard-page/inventory-dashboard-page.component.mjs +10 -8
  4. package/esm2022/lib/inventory-common/inventory-value-report.service.mjs +21 -0
  5. package/esm2022/lib/inventory-common/low-stock-report.service.mjs +23 -0
  6. package/esm2022/lib/inventory-common/product/low-stock-products-widget/low-stock-products-widget.component.mjs +9 -7
  7. package/esm2022/lib/inventory-common/product/product-list/product-list.component.mjs +3 -3
  8. package/esm2022/lib/inventory-common/product/product-quick-search/product-quick-search.component.mjs +92 -0
  9. package/esm2022/lib/inventory-common/product/widgets/product-category-badges/product-category-badges.component.mjs +18 -0
  10. package/esm2022/lib/inventory-common/reports/inventory-value-report/inventory-value-report.component.mjs +170 -0
  11. package/esm2022/lib/inventory-common/reports/low-stock-report/low-stock-report.component.mjs +165 -0
  12. package/esm2022/lib/inventory-common/supplier/supplier-delete-button/supplier-delete-button.component.mjs +64 -0
  13. package/esm2022/lib/inventory-common/supplier/supplier-form/supplier-form-button/supplier-form-button.component.mjs +43 -0
  14. package/esm2022/lib/inventory-common/supplier/supplier.module.mjs +11 -3
  15. package/esm2022/lib/inventory-common/supplier/suppliers-list/suppliers-list.component.mjs +6 -65
  16. package/fesm2022/{techlify-inventory-common-category.module-CNm2bEsx.mjs → techlify-inventory-common-category.module-BKEBFEeZ.mjs} +9 -9
  17. package/fesm2022/{techlify-inventory-common-category.module-CNm2bEsx.mjs.map → techlify-inventory-common-category.module-BKEBFEeZ.mjs.map} +1 -1
  18. package/fesm2022/{techlify-inventory-common-measure.module-BEaRHh5Z.mjs → techlify-inventory-common-measure.module-CZHhYoQd.mjs} +9 -9
  19. package/fesm2022/{techlify-inventory-common-measure.module-BEaRHh5Z.mjs.map → techlify-inventory-common-measure.module-CZHhYoQd.mjs.map} +1 -1
  20. package/fesm2022/{techlify-inventory-common-stock-issuances.module-BQRRP-hW.mjs → techlify-inventory-common-stock-issuances.module-BjPbzqUW.mjs} +2 -4
  21. package/fesm2022/{techlify-inventory-common-stock-issuances.module-BQRRP-hW.mjs.map → techlify-inventory-common-stock-issuances.module-BjPbzqUW.mjs.map} +1 -1
  22. package/fesm2022/{techlify-inventory-common-supplier.module-Bwa7gx14.mjs → techlify-inventory-common-supplier.module-CFDwJ-TS.mjs} +251 -218
  23. package/fesm2022/techlify-inventory-common-supplier.module-CFDwJ-TS.mjs.map +1 -0
  24. package/fesm2022/techlify-inventory-common-techlify-inventory-common-CYiCJfk9.mjs +3143 -0
  25. package/fesm2022/techlify-inventory-common-techlify-inventory-common-CYiCJfk9.mjs.map +1 -0
  26. package/fesm2022/techlify-inventory-common.mjs +1 -1
  27. package/lib/inventory-common/inventory-common.module.d.ts +2 -1
  28. package/lib/inventory-common/inventory-value-report.service.d.ts +9 -0
  29. package/lib/inventory-common/low-stock-report.service.d.ts +10 -0
  30. package/lib/inventory-common/product/product-quick-search/product-quick-search.component.d.ts +15 -0
  31. package/lib/inventory-common/product/widgets/product-category-badges/product-category-badges.component.d.ts +6 -0
  32. package/lib/inventory-common/reports/inventory-value-report/inventory-value-report.component.d.ts +26 -0
  33. package/lib/inventory-common/reports/low-stock-report/low-stock-report.component.d.ts +26 -0
  34. package/lib/inventory-common/supplier/supplier-delete-button/supplier-delete-button.component.d.ts +18 -0
  35. package/lib/inventory-common/supplier/supplier-form/supplier-form-button/supplier-form-button.component.d.ts +13 -0
  36. package/lib/inventory-common/supplier/supplier.module.d.ts +3 -1
  37. package/lib/inventory-common/supplier/suppliers-list/suppliers-list.component.d.ts +0 -8
  38. package/package.json +1 -1
  39. package/fesm2022/techlify-inventory-common-product.module-BV9Cy88x.mjs +0 -1168
  40. package/fesm2022/techlify-inventory-common-product.module-BV9Cy88x.mjs.map +0 -1
  41. package/fesm2022/techlify-inventory-common-stock-issuances-list.module-Dt6gx-ji.mjs +0 -436
  42. package/fesm2022/techlify-inventory-common-stock-issuances-list.module-Dt6gx-ji.mjs.map +0 -1
  43. package/fesm2022/techlify-inventory-common-stock-receipt-form.module-DND0GNlf.mjs +0 -302
  44. package/fesm2022/techlify-inventory-common-stock-receipt-form.module-DND0GNlf.mjs.map +0 -1
  45. package/fesm2022/techlify-inventory-common-stock-receipts.module-BvYaKITT.mjs +0 -253
  46. package/fesm2022/techlify-inventory-common-stock-receipts.module-BvYaKITT.mjs.map +0 -1
  47. package/fesm2022/techlify-inventory-common-supplier-form.component-DVBnhiyH.mjs +0 -177
  48. package/fesm2022/techlify-inventory-common-supplier-form.component-DVBnhiyH.mjs.map +0 -1
  49. package/fesm2022/techlify-inventory-common-supplier.module-Bwa7gx14.mjs.map +0 -1
  50. package/fesm2022/techlify-inventory-common-techlify-form-service-CiVfwYTS.mjs +0 -14
  51. package/fesm2022/techlify-inventory-common-techlify-form-service-CiVfwYTS.mjs.map +0 -1
  52. package/fesm2022/techlify-inventory-common-techlify-inventory-common-GFYF7JCA.mjs +0 -495
  53. package/fesm2022/techlify-inventory-common-techlify-inventory-common-GFYF7JCA.mjs.map +0 -1
@@ -0,0 +1,170 @@
1
+ import { Component } from '@angular/core';
2
+ import { MatCard, MatCardContent } from '@angular/material/card';
3
+ import { MatCell, MatCellDef, MatColumnDef, MatFooterCell, MatFooterCellDef, MatFooterRow, MatFooterRowDef, MatHeaderCell, MatHeaderCellDef, MatHeaderRow, MatHeaderRowDef, MatRow, MatRowDef, MatTable } from '@angular/material/table';
4
+ import { SearchableSelectorModule, TechlifyListingControllerInterface } from 'ngx-techlify-core';
5
+ import { RouterLink } from '@angular/router';
6
+ import { ProductCategoryBadgesComponent } from '../../product/widgets/product-category-badges/product-category-badges.component';
7
+ import { CurrencyPipe, NgIf } from '@angular/common';
8
+ import { MatProgressBar } from '@angular/material/progress-bar';
9
+ import { debounceTime, distinctUntilChanged } from 'rxjs';
10
+ import { ReactiveFormsModule } from '@angular/forms';
11
+ import { MatFormField, MatLabel } from '@angular/material/form-field';
12
+ import { MatInput } from '@angular/material/input';
13
+ import { InfiniteScrollDirective } from 'ngx-infinite-scroll';
14
+ import { MatSort, MatSortHeader } from '@angular/material/sort';
15
+ import * as i0 from "@angular/core";
16
+ import * as i1 from "../../inventory-value-report.service";
17
+ import * as i2 from "@angular/router";
18
+ import * as i3 from "ngx-techlify-core";
19
+ import * as i4 from "@angular/forms";
20
+ export class InventoryValueReportComponent extends TechlifyListingControllerInterface {
21
+ service;
22
+ activatedRoute;
23
+ requestHelperService;
24
+ formBuilder;
25
+ displayedColumns = [
26
+ '#',
27
+ 'Product',
28
+ 'Description',
29
+ 'Categories',
30
+ 'Available Stock',
31
+ 'Average Price',
32
+ 'Inventory Value',
33
+ 'Last Purchase Price',
34
+ 'Inventory Value Based On Last Purchase Price',
35
+ ];
36
+ totalInventoryValue = 0;
37
+ isExporting = false;
38
+ constructor(service, activatedRoute, requestHelperService, formBuilder) {
39
+ super();
40
+ this.service = service;
41
+ this.activatedRoute = activatedRoute;
42
+ this.requestHelperService = requestHelperService;
43
+ this.formBuilder = formBuilder;
44
+ this.filterForm = this.formBuilder.group({
45
+ category_ids: [''],
46
+ search: [''],
47
+ sort_by: ['id|desc']
48
+ });
49
+ }
50
+ ngOnInit() {
51
+ this.updateFormWithQueryParams();
52
+ this.subscribeToFormChanges();
53
+ this.subscribeToRouteChanges();
54
+ }
55
+ loadData() {
56
+ const params = {
57
+ ...this.requestHelperService.convertToFormData(this.filterForm.value),
58
+ page: this.page,
59
+ perPage: this.perPage,
60
+ with: 'categories,lastStockReceipt',
61
+ };
62
+ this.isWorking = true;
63
+ this.service.index(params).subscribe({
64
+ next: (response) => {
65
+ this.models = this.models?.concat(response?.data);
66
+ this.isWorking = false;
67
+ this.models.forEach((model) => {
68
+ this.totalInventoryValue += model?.inventory_value;
69
+ });
70
+ },
71
+ error: () => (this.isWorking = false),
72
+ });
73
+ }
74
+ updateFormWithQueryParams() {
75
+ this.requestHelperService.updateFormWithQueryParams(this.filterForm, {
76
+ category_ids: { multiple: true }
77
+ });
78
+ }
79
+ subscribeToFormChanges() {
80
+ this.filterForm.valueChanges.pipe(debounceTime(800)).subscribe({
81
+ next: () => {
82
+ this.requestHelperService.updateQueryParams(this.requestHelperService.convertToFormData(this.filterForm.value));
83
+ }
84
+ });
85
+ }
86
+ subscribeToRouteChanges() {
87
+ this.activatedRoute.queryParams
88
+ .pipe(debounceTime(500), distinctUntilChanged())
89
+ .subscribe(() => {
90
+ this.reload();
91
+ });
92
+ }
93
+ onSortChange(sort) {
94
+ let { active, direction } = sort;
95
+ if (!active)
96
+ active = 'id';
97
+ if (!direction)
98
+ direction = 'desc';
99
+ this.filterForm.get('sort_by')?.setValue(active + '|' + direction);
100
+ }
101
+ export(type = 'excel') {
102
+ const params = {
103
+ ...this.requestHelperService.convertToFormData(this.filterForm.value),
104
+ page: this.page,
105
+ perPage: 50000,
106
+ with: 'categories,lastStockReceipt',
107
+ export_type: type,
108
+ };
109
+ this.isExporting = true;
110
+ this.service.export(params).subscribe({
111
+ next: (response) => {
112
+ this.isExporting = false;
113
+ window.open(response?.item?.file_link, '_blank');
114
+ },
115
+ error: () => (this.isExporting = false)
116
+ });
117
+ }
118
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryValueReportComponent, deps: [{ token: i1.InventoryValueReportService }, { token: i2.ActivatedRoute }, { token: i3.RequestHelperService }, { token: i4.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
119
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: InventoryValueReportComponent, isStandalone: true, selector: "app-inventory-value-report", usesInheritance: true, ngImport: i0, template: "<div class=\"container\">\n <mat-card>\n <mat-card-content class=\"d-flex justify-content-between align-items-center gap-2\">\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <h3 class=\"mb-0\">Inventory Value Report</h3>\n <i class=\"fa-solid fa-file-excel cursor-pointer d-print-none\" (click)=\"export('excel')\"></i>\n <i class=\"fa-solid fa-file-pdf cursor-pointer d-print-none\" (click)=\"export('pdf')\"></i>\n </div>\n <form [formGroup]=\"filterForm\" class=\"d-flex justify-content-end align-items-center gap-2\">\n <mat-form-field>\n <mat-label>Search</mat-label>\n <input matInput placeholder=\"Search products\" formControlName=\"search\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Category</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-categories\"\n formControlName=\"category_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n </form>\n </mat-card-content>\n </mat-card>\n\n <mat-card class=\"mt-3\">\n <mat-card-content class=\"p-0\">\n <table\n mat-table [dataSource]=\"models\" class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\" [infiniteScrollThrottle]=\"50\" (scrolled)=\"onScroll()\"\n matSort (matSortChange)=\"onSortChange($event)\"\n >\n\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef> # </th>\n <td mat-cell *matCellDef=\"let element; let i = index\"> {{ i + 1}} </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Product Column -->\n <ng-container matColumnDef=\"Product\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"name\"> Product </th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n [routerLink]=\"['/inventory/products', element?.id, 'view']\"\n class=\"text-dark\"\n >\n {{ element?.name }}\n </a>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Description Column -->\n <ng-container matColumnDef=\"Description\">\n <th mat-header-cell *matHeaderCellDef> Description </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.description }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Categories Column -->\n <ng-container matColumnDef=\"Categories\">\n <th mat-header-cell *matHeaderCellDef> Categories </th>\n <td mat-cell *matCellDef=\"let element\">\n <app-product-category-badges [product]=\"element\"></app-product-category-badges>\n </td>\n <td mat-footer-cell *matFooterCellDef>\n <strong>Total</strong>\n </td>\n </ng-container>\n\n <!-- Available Stock Column -->\n <ng-container matColumnDef=\"Available Stock\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"current_stock\"> Available Stock </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.current_stock }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Average Price Column -->\n <ng-container matColumnDef=\"Average Price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"average_purchase_price\"> Average Price </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.average_purchase_price | currency }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Inventory Value Column -->\n <ng-container matColumnDef=\"Inventory Value\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"inventory_value\"> Inventory Value </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.inventory_value | currency }}\n </td>\n <td mat-footer-cell *matFooterCellDef>\n <strong>{{ totalInventoryValue | currency }}</strong>\n </td>\n </ng-container>\n\n <!-- Last Purchase Price Column -->\n <ng-container matColumnDef=\"Last Purchase Price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"last_stock_receipt.purchase_price\">\n Last Purchase Price\n </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.last_stock_receipt?.purchase_price ?? 0 | currency }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Inventory Value Based On Last Purchase Price Column -->\n <ng-container matColumnDef=\"Inventory Value Based On Last Purchase Price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"last_stock_receipt.amount\">\n <div>\n <p class=\"mb-0\">Inventory Value</p>\n <small class=\"text-secondary\">Based on last purchase price</small>\n </div>\n </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.last_stock_receipt?.amount ?? 0 | currency }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n <tr mat-footer-row *matFooterRowDef=\"displayedColumns\"></tr>\n </table>\n\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isWorking\"></mat-progress-bar>\n </mat-card-content>\n </mat-card>\n</div>\n", styles: [""], dependencies: [{ kind: "component", type: MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: MatCardContent, selector: "mat-card-content" }, { kind: "component", type: MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: MatCellDef, selector: "[matCellDef]" }, { kind: "component", type: MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "component", type: MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "directive", type: MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: ProductCategoryBadgesComponent, selector: "app-product-category-badges", inputs: ["product"] }, { kind: "pipe", type: CurrencyPipe, name: "currency" }, { kind: "component", type: MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "component", type: MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "directive", type: MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i4.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i4.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i4.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: SearchableSelectorModule }, { kind: "component", type: i3.SearchableSelectorComponent, selector: "app-searchable-selector", inputs: ["valueField", "titleField", "subtitleField", "apiUrl", "multiple", "selectedValue", "enableSearch", "add", "addConfig", "edit", "editConfig", "sort", "sortBy", "searchField", "itemComponent", "items", "apiDataProperty", "cache", "perPage", "inDataSearch", "panelWidth", "focusSearchOnOpen", "required", "disabled", "value"], outputs: ["selectedValueChange", "selectionChange", "itemsChange"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "directive", type: MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }], preserveWhitespaces: true });
120
+ }
121
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InventoryValueReportComponent, decorators: [{
122
+ type: Component,
123
+ args: [{ selector: 'app-inventory-value-report', standalone: true, imports: [
124
+ MatCard,
125
+ MatCardContent,
126
+ MatTable,
127
+ MatColumnDef,
128
+ MatColumnDef,
129
+ MatCellDef,
130
+ MatRow,
131
+ MatCellDef,
132
+ MatHeaderCell,
133
+ MatCell,
134
+ MatRowDef,
135
+ MatCellDef,
136
+ MatHeaderCell,
137
+ MatColumnDef,
138
+ MatCell,
139
+ MatColumnDef,
140
+ MatHeaderCell,
141
+ MatHeaderRowDef,
142
+ MatHeaderCell,
143
+ MatCell,
144
+ MatHeaderRow,
145
+ MatCell,
146
+ MatCellDef,
147
+ MatHeaderCellDef,
148
+ MatHeaderCellDef,
149
+ MatHeaderCellDef,
150
+ MatHeaderCellDef,
151
+ RouterLink,
152
+ ProductCategoryBadgesComponent,
153
+ CurrencyPipe,
154
+ MatProgressBar,
155
+ NgIf,
156
+ MatFooterRowDef,
157
+ MatFooterRow,
158
+ MatFooterCellDef,
159
+ MatFooterCell,
160
+ MatFormField,
161
+ MatLabel,
162
+ ReactiveFormsModule,
163
+ SearchableSelectorModule,
164
+ MatInput,
165
+ InfiniteScrollDirective,
166
+ MatSort,
167
+ MatSortHeader
168
+ ], template: "<div class=\"container\">\n <mat-card>\n <mat-card-content class=\"d-flex justify-content-between align-items-center gap-2\">\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <h3 class=\"mb-0\">Inventory Value Report</h3>\n <i class=\"fa-solid fa-file-excel cursor-pointer d-print-none\" (click)=\"export('excel')\"></i>\n <i class=\"fa-solid fa-file-pdf cursor-pointer d-print-none\" (click)=\"export('pdf')\"></i>\n </div>\n <form [formGroup]=\"filterForm\" class=\"d-flex justify-content-end align-items-center gap-2\">\n <mat-form-field>\n <mat-label>Search</mat-label>\n <input matInput placeholder=\"Search products\" formControlName=\"search\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Category</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-categories\"\n formControlName=\"category_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n </form>\n </mat-card-content>\n </mat-card>\n\n <mat-card class=\"mt-3\">\n <mat-card-content class=\"p-0\">\n <table\n mat-table [dataSource]=\"models\" class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\" [infiniteScrollThrottle]=\"50\" (scrolled)=\"onScroll()\"\n matSort (matSortChange)=\"onSortChange($event)\"\n >\n\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef> # </th>\n <td mat-cell *matCellDef=\"let element; let i = index\"> {{ i + 1}} </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Product Column -->\n <ng-container matColumnDef=\"Product\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"name\"> Product </th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n [routerLink]=\"['/inventory/products', element?.id, 'view']\"\n class=\"text-dark\"\n >\n {{ element?.name }}\n </a>\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Description Column -->\n <ng-container matColumnDef=\"Description\">\n <th mat-header-cell *matHeaderCellDef> Description </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.description }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Categories Column -->\n <ng-container matColumnDef=\"Categories\">\n <th mat-header-cell *matHeaderCellDef> Categories </th>\n <td mat-cell *matCellDef=\"let element\">\n <app-product-category-badges [product]=\"element\"></app-product-category-badges>\n </td>\n <td mat-footer-cell *matFooterCellDef>\n <strong>Total</strong>\n </td>\n </ng-container>\n\n <!-- Available Stock Column -->\n <ng-container matColumnDef=\"Available Stock\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"current_stock\"> Available Stock </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.current_stock }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Average Price Column -->\n <ng-container matColumnDef=\"Average Price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"average_purchase_price\"> Average Price </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.average_purchase_price | currency }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Inventory Value Column -->\n <ng-container matColumnDef=\"Inventory Value\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"inventory_value\"> Inventory Value </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.inventory_value | currency }}\n </td>\n <td mat-footer-cell *matFooterCellDef>\n <strong>{{ totalInventoryValue | currency }}</strong>\n </td>\n </ng-container>\n\n <!-- Last Purchase Price Column -->\n <ng-container matColumnDef=\"Last Purchase Price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"last_stock_receipt.purchase_price\">\n Last Purchase Price\n </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.last_stock_receipt?.purchase_price ?? 0 | currency }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <!-- Inventory Value Based On Last Purchase Price Column -->\n <ng-container matColumnDef=\"Inventory Value Based On Last Purchase Price\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"last_stock_receipt.amount\">\n <div>\n <p class=\"mb-0\">Inventory Value</p>\n <small class=\"text-secondary\">Based on last purchase price</small>\n </div>\n </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.last_stock_receipt?.amount ?? 0 | currency }}\n </td>\n <td mat-footer-cell *matFooterCellDef></td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n <tr mat-footer-row *matFooterRowDef=\"displayedColumns\"></tr>\n </table>\n\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isWorking\"></mat-progress-bar>\n </mat-card-content>\n </mat-card>\n</div>\n" }]
169
+ }], ctorParameters: () => [{ type: i1.InventoryValueReportService }, { type: i2.ActivatedRoute }, { type: i3.RequestHelperService }, { type: i4.FormBuilder }] });
170
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW52ZW50b3J5LXZhbHVlLXJlcG9ydC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9pbnZlbnRvcnktY29tbW9uL3NyYy9saWIvaW52ZW50b3J5LWNvbW1vbi9yZXBvcnRzL2ludmVudG9yeS12YWx1ZS1yZXBvcnQvaW52ZW50b3J5LXZhbHVlLXJlcG9ydC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9pbnZlbnRvcnktY29tbW9uL3NyYy9saWIvaW52ZW50b3J5LWNvbW1vbi9yZXBvcnRzL2ludmVudG9yeS12YWx1ZS1yZXBvcnQvaW52ZW50b3J5LXZhbHVlLXJlcG9ydC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsU0FBUyxFQUFTLE1BQU0sZUFBZSxDQUFDO0FBQ2hELE9BQU8sRUFBQyxPQUFPLEVBQUUsY0FBYyxFQUFDLE1BQU0sd0JBQXdCLENBQUM7QUFDL0QsT0FBTyxFQUNMLE9BQU8sRUFDUCxVQUFVLEVBQ1YsWUFBWSxFQUFFLGFBQWEsRUFBRSxnQkFBZ0IsRUFBRSxZQUFZLEVBQUUsZUFBZSxFQUM1RSxhQUFhLEVBQUUsZ0JBQWdCLEVBQUUsWUFBWSxFQUM3QyxlQUFlLEVBQ2YsTUFBTSxFQUNOLFNBQVMsRUFDVCxRQUFRLEVBQ1QsTUFBTSx5QkFBeUIsQ0FBQztBQUNqQyxPQUFPLEVBQXVCLHdCQUF3QixFQUFFLGtDQUFrQyxFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFFckgsT0FBTyxFQUFpQixVQUFVLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUMzRCxPQUFPLEVBQ0wsOEJBQThCLEVBQy9CLE1BQU0saUZBQWlGLENBQUM7QUFDekYsT0FBTyxFQUFDLFlBQVksRUFBRSxJQUFJLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUNuRCxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sZ0NB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T0FBTzt3QkFDUCxjQUFjO3dCQUNkLFFBQVE7d0JBQ1IsWUFBWTt3QkFDWixZQUFZO3dCQUNaLFVBQVU7d0JBQ1YsTUFBTTt3QkFDTixVQUFVO3dCQUNWLGFBQWE7d0JBQ2IsT0FBTzt3QkFDUCxTQUFTO3dCQUNULFVBQVU7d0JBQ1YsYUFBYTt3QkFDYixZQUFZO3dCQUNaLE9BQU87d0JBQ1AsWUFBWTt3QkFDWixhQUFhO3dCQUNiLGVBQWU7d0JBQ2YsYUFBYTt3QkFDYixPQUFPO3dCQUNQLFlBQVk7d0JBQ1osT0FBTzt3QkFDUCxVQUFVO3dCQUNWLGdCQUFnQjt3QkFDaEIsZ0JBQWdCO3dCQUNoQixnQkFBZ0I7d0JBQ2hCLGdCQUFnQjt3QkFDaEIsVUFBVTt3QkFDViw4QkFBOEI7d0JBQzlCLFlBQVk7d0JBQ1osY0FBYzt3QkFDZCxJQUFJO3dCQUNKLGVBQWU7d0JBQ2YsWUFBWTt3QkFDWixnQkFBZ0I7d0JBQ2hCLGFBQWE7d0JBQ2IsWUFBWTt3QkFDWixRQUFRO3dCQUNSLG1CQUFtQjt3QkFDbkIsd0JBQXdCO3dCQUN4QixRQUFRO3dCQUNSLHVCQUF1Qjt3QkFDdkIsT0FBTzt3QkFDUCxhQUFhO3FCQUNkIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtDb21wb25lbnQsIE9uSW5pdH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge01hdENhcmQsIE1hdENhcmRDb250ZW50fSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9jYXJkJztcbmltcG9ydCB7XG4gIE1hdENlbGwsXG4gIE1hdENlbGxEZWYsXG4gIE1hdENvbHVtbkRlZiwgTWF0Rm9vdGVyQ2VsbCwgTWF0Rm9vdGVyQ2VsbERlZiwgTWF0Rm9vdGVyUm93LCBNYXRGb290ZXJSb3dEZWYsXG4gIE1hdEhlYWRlckNlbGwsIE1hdEhlYWRlckNlbGxEZWYsIE1hdEhlYWRlclJvdyxcbiAgTWF0SGVhZGVyUm93RGVmLFxuICBNYXRSb3csXG4gIE1hdFJvd0RlZixcbiAgTWF0VGFibGVcbn0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdGFibGUnO1xuaW1wb3J0IHtSZXF1ZXN0SGVscGVyU2VydmljZSwgU2VhcmNoYWJsZVNlbGVjdG9yTW9kdWxlLCBUZWNobGlmeUxpc3RpbmdDb250cm9sbGVySW50ZXJmYWNlfSBmcm9tICduZ3gtdGVjaGxpZnktY29yZSc7XG5pbXBvcnQge0ludmVudG9yeVZhbHVlUmVwb3J0U2VydmljZX0gZnJvbSAnLi4vLi4vaW52ZW50b3J5LXZhbHVlLXJlcG9ydC5zZXJ2aWNlJztcbmltcG9ydCB7QWN0aXZhdGVkUm91dGUsIFJvdXRlckxpbmt9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQge1xuICBQcm9kdWN0Q2F0ZWdvcnlCYWRnZXNDb21wb25lbnRcbn0gZnJvbSAnLi4vLi4vcHJvZHVjdC93aWRnZXRzL3Byb2R1Y3QtY2F0ZWdvcnktYmFkZ2VzL3Byb2R1Y3QtY2F0ZWdvcnktYmFkZ2VzLmNvbXBvbmVudCc7XG5pbXBvcnQge0N1cnJlbmN5UGlwZSwgTmdJZn0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7TWF0UHJvZ3Jlc3NCYXJ9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3Byb2dyZXNzLWJhcic7XG5pbXBvcnQge2RlYm91bmNlVGltZSwgZGlzdGluY3RVbnRpbENoYW5nZWR9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtGb3JtQnVpbGRlciwgRm9ybUdyb3VwLCBSZWFjdGl2ZUZvcm1zTW9kdWxlfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQge01hdEZvcm1GaWVsZCwgTWF0TGFiZWx9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2Zvcm0tZmllbGQnO1xuaW1wb3J0IHtNYXRJbnB1dH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaW5wdXQnO1xuaW1wb3J0IHtJbmZpbml0ZVNjcm9sbERpcmVjdGl2ZX0gZnJvbSAnbmd4LWluZmluaXRlLXNjcm9sbCc7XG5pbXBvcnQge01hdFNvcnQsIE1hdFNvcnRIZWFkZXIsIFNvcnR9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NvcnQnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhcHAtaW52ZW50b3J5LXZhbHVlLXJlcG9ydCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBNYXRDYXJkLFxuICAgIE1hdENhcmRDb250ZW50LFxuICAgIE1hdFRhYmxlLFxuICAgIE1hdENvbHVtbkRlZixcbiAgICBNYXRDb2x1bW5EZWYsXG4gICAgTWF0Q2VsbERlZixcbiAgICBNYXRSb3csXG4gICAgTWF0Q2VsbERlZixcbiAgICBNYXRIZWFkZXJDZWxsLFxuICAgIE1hdENlbGwsXG4gICAgTWF0Um93RGVmLFxuICAgIE1hdENlbGxEZWYsXG4gICAgTWF0SGVhZGVyQ2VsbCxcbiAgICBNYXRDb2x1bW5EZWYsXG4gICAgTWF0Q2VsbCxcbiAgICBNYXRDb2x1bW5EZWYsXG4gICAgTWF0SGVhZGVyQ2VsbCxcbiAgICBNYXRIZWFkZXJSb3dEZWYsXG4gICAgTWF0SGVhZGVyQ2VsbCxcbiAgICBNYXRDZWxsLFxuICAgIE1hdEhlYWRlclJvdyxcbiAgICBNYXRDZWxsLFxuICAgIE1hdENlbGxEZWYsXG4gICAgTWF0SGVhZGVyQ2VsbERlZixcbiAgICBNYXRIZWFkZXJDZWxsRGVmLFxuICAgIE1hdEhlYWRlckNlbGxEZWYsXG4gICAgTWF0SGVhZGVyQ2VsbERlZixcbiAgICBSb3V0ZXJMaW5rLFxuICAgIFByb2R1Y3RDYXRlZ29yeUJhZGdlc0NvbXBvbmVudCxcbiAgICBDdXJyZW5jeVBpcGUsXG4gICAgTWF0UHJvZ3Jlc3NCYXIsXG4gICAgTmdJZixcbiAgICBNYXRGb290ZXJSb3dEZWYsXG4gICAgTWF0Rm9vdGVyUm93LFxuICAgIE1hdEZvb3RlckNlbGxEZWYsXG4gICAgTWF0Rm9vdGVyQ2VsbCxcbiAgICBNYXRGb3JtRmllbGQsXG4gICAgTWF0TGFiZWwsXG4gICAgUmVhY3RpdmVGb3Jtc01vZHVsZSxcbiAgICBTZWFyY2hhYmxlU2VsZWN0b3JNb2R1bGUsXG4gICAgTWF0SW5wdXQsXG4gICAgSW5maW5pdGVTY3JvbGxEaXJlY3RpdmUsXG4gICAgTWF0U29ydCxcbiAgICBNYXRTb3J0SGVhZGVyXG4gIF0sXG4gIHRlbXBsYXRlVXJsOiAnLi9pbnZlbnRvcnktdmFsdWUtcmVwb3J0LmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmw6ICcuL2ludmVudG9yeS12YWx1ZS1yZXBvcnQuY29tcG9uZW50LnNjc3MnXG59KVxuZXhwb3J0IGNsYXNzIEludmVudG9yeVZhbHVlUmVwb3J0Q29tcG9uZW50IGV4dGVuZHMgVGVjaGxpZnlMaXN0aW5nQ29udHJvbGxlckludGVyZmFjZSBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIGRpc3BsYXllZENvbHVtbnM6IHN0cmluZ1tdID0gW1xuICAgICcjJyxcbiAgICAnUHJvZHVjdCcsXG4gICAgJ0Rlc2NyaXB0aW9uJyxcbiAgICAnQ2F0ZWdvcmllcycsXG4gICAgJ0F2YWlsYWJsZSBTdG9jaycsXG4gICAgJ0F2ZXJhZ2UgUHJpY2UnLFxuICAgICdJbnZlbnRvcnkgVmFsdWUnLFxuICAgICdMYXN0IFB1cmNoYXNlIFByaWNlJyxcbiAgICAnSW52ZW50b3J5IFZhbHVlIEJhc2VkIE9uIExhc3QgUHVyY2hhc2UgUHJpY2UnLFxuICBdO1xuICB0b3RhbEludmVudG9yeVZhbHVlID0gMDtcbiAgaXNFeHBvcnRpbmcgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHNlcnZpY2U6IEludmVudG9yeVZhbHVlUmVwb3J0U2VydmljZSxcbiAgICBwcml2YXRlIGFjdGl2YXRlZFJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICBwcml2YXRlIHJlcXVlc3RIZWxwZXJTZXJ2aWNlOiBSZXF1ZXN0SGVscGVyU2VydmljZSxcbiAgICBwcml2YXRlIGZvcm1CdWlsZGVyOiBGb3JtQnVpbGRlclxuICApIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5maWx0ZXJGb3JtID0gdGhpcy5mb3JtQnVpbGRlci5ncm91cCh7XG4gICAgICBjYXRlZ29yeV9pZHM6IFsnJ10sXG4gICAgICBzZWFyY2g6IFsnJ10sXG4gICAgICBzb3J0X2J5OiBbJ2lkfGRlc2MnXVxuICAgIH0pO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy51cGRhdGVGb3JtV2l0aFF1ZXJ5UGFyYW1zKCk7XG4gICAgdGhpcy5zdWJzY3JpYmVUb0Zvcm1DaGFuZ2VzKCk7XG4gICAgdGhpcy5zdWJzY3JpYmVUb1JvdXRlQ2hhbmdlcygpO1xuICB9XG5cbiAgbG9hZERhdGEoKTogdm9pZCB7XG4gICAgY29uc3QgcGFyYW1zOiBhbnkgPSB7XG4gICAgICAuLi50aGlzLnJlcXVlc3RIZWxwZXJTZXJ2aWNlLmNvbnZlcnRUb0Zvcm1EYXRhKHRoaXMuZmlsdGVyRm9ybS52YWx1ZSksXG4gICAgICBwYWdlOiB0aGlzLnBhZ2UsXG4gICAgICBwZXJQYWdlOiB0aGlzLnBlclBhZ2UsXG4gICAgICB3aXRoOiAnY2F0ZWdvcmllcyxsYXN0U3RvY2tSZWNlaXB0JyxcbiAgICB9XG4gICAgdGhpcy5pc1dvcmtpbmcgPSB0cnVlO1xuICAgIHRoaXMuc2VydmljZS5pbmRleChwYXJhbXMpLnN1YnNjcmliZSh7XG4gICAgICBuZXh0OiAocmVzcG9uc2U6IGFueSkgPT4ge1xuICAgICAgICB0aGlzLm1vZGVscyA9IHRoaXMubW9kZWxzPy5jb25jYXQocmVzcG9uc2U/LmRhdGEpO1xuICAgICAgICB0aGlzLmlzV29ya2luZyA9IGZhbHNlO1xuXG4gICAgICAgIHRoaXMubW9kZWxzLmZvckVhY2goKG1vZGVsOiBhbnkpID0+IHtcbiAgICAgICAgICB0aGlzLnRvdGFsSW52ZW50b3J5VmFsdWUgKz0gbW9kZWw/LmludmVudG9yeV92YWx1ZTtcbiAgICAgICAgfSlcbiAgICAgIH0sXG4gICAgICBlcnJvcjogKCkgPT4gKHRoaXMuaXNXb3JraW5nID0gZmFsc2UpLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVGb3JtV2l0aFF1ZXJ5UGFyYW1zKCk6IHZvaWQge1xuICAgIHRoaXMucmVxdWVzdEhlbHBlclNlcnZpY2UudXBkYXRlRm9ybVdpdGhRdWVyeVBhcmFtcyhcbiAgICAgIHRoaXMuZmlsdGVyRm9ybSxcbiAgICAgIHtcbiAgICAgICAgY2F0ZWdvcnlfaWRzOiB7IG11bHRpcGxlOiB0cnVlIH1cbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBzdWJzY3JpYmVUb0Zvcm1DaGFuZ2VzKCk6IHZvaWQge1xuICAgICh0aGlzLmZpbHRlckZvcm0gYXMgRm9ybUdyb3VwKS52YWx1ZUNoYW5nZXMucGlwZShcbiAgICAgIGRlYm91bmNlVGltZSg4MDApXG4gICAgKS5zdWJzY3JpYmUoe1xuICAgICAgbmV4dDogKCkgPT4ge1xuICAgICAgICB0aGlzLnJlcXVlc3RIZWxwZXJTZXJ2aWNlLnVwZGF0ZVF1ZXJ5UGFyYW1zKFxuICAgICAgICAgIHRoaXMucmVxdWVzdEhlbHBlclNlcnZpY2UuY29udmVydFRvRm9ybURhdGEodGhpcy5maWx0ZXJGb3JtLnZhbHVlKVxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBzdWJzY3JpYmVUb1JvdXRlQ2hhbmdlcygpOiB2b2lkIHtcbiAgICB0aGlzLmFjdGl2YXRlZFJvdXRlLnF1ZXJ5UGFyYW1zXG4gICAgICAucGlwZShkZWJvdW5jZVRpbWUoNTAwKSxcbiAgICAgICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKSlcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLnJlbG9hZCgpO1xuICAgICAgfSk7XG4gIH1cblxuICBvblNvcnRDaGFuZ2Uoc29ydDogU29ydCkge1xuICAgIGxldCB7YWN0aXZlLCBkaXJlY3Rpb259ID0gc29ydDtcbiAgICBpZiAoIWFjdGl2ZSkgYWN0aXZlID0gJ2lkJztcbiAgICBpZiAoIWRpcmVjdGlvbikgZGlyZWN0aW9uID0gJ2Rlc2MnO1xuICAgIHRoaXMuZmlsdGVyRm9ybS5nZXQoJ3NvcnRfYnknKT8uc2V0VmFsdWUoYWN0aXZlICsgJ3wnICsgZGlyZWN0aW9uKTtcbiAgfVxuXG4gIGV4cG9ydCh0eXBlOiBzdHJpbmcgPSAnZXhjZWwnKSB7XG4gICAgY29uc3QgcGFyYW1zOiBhbnkgPSB7XG4gICAgICAuLi50aGlzLnJlcXVlc3RIZWxwZXJTZXJ2aWNlLmNvbnZlcnRUb0Zvcm1EYXRhKHRoaXMuZmlsdGVyRm9ybS52YWx1ZSksXG4gICAgICBwYWdlOiB0aGlzLnBhZ2UsXG4gICAgICBwZXJQYWdlOiA1MDAwMCxcbiAgICAgIHdpdGg6ICdjYXRlZ29yaWVzLGxhc3RTdG9ja1JlY2VpcHQnLFxuICAgICAgZXhwb3J0X3R5cGU6IHR5cGUsXG4gICAgfVxuICAgIHRoaXMuaXNFeHBvcnRpbmcgPSB0cnVlO1xuICAgIHRoaXMuc2VydmljZS5leHBvcnQocGFyYW1zKS5zdWJzY3JpYmUoe1xuICAgICAgbmV4dDogKHJlc3BvbnNlOiBhbnkpID0+IHtcbiAgICAgICAgdGhpcy5pc0V4cG9ydGluZyA9IGZhbHNlO1xuICAgICAgICB3aW5kb3cub3BlbihyZXNwb25zZT8uaXRlbT8uZmlsZV9saW5rLCAnX2JsYW5rJyk7XG4gICAgICB9LFxuICAgICAgZXJyb3I6ICgpID0+ICh0aGlzLmlzRXhwb3J0aW5nID0gZmFsc2UpXG4gICAgfSk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJjb250YWluZXJcIj5cbiAgPG1hdC1jYXJkPlxuICAgIDxtYXQtY2FyZC1jb250ZW50IGNsYXNzPVwiZC1mbGV4IGp1c3RpZnktY29udGVudC1iZXR3ZWVuIGFsaWduLWl0ZW1zLWNlbnRlciBnYXAtMlwiPlxuICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtc3RhcnQgYWxpZ24taXRlbXMtY2VudGVyIGdhcC0yXCI+XG4gICAgICAgIDxoMyBjbGFzcz1cIm1iLTBcIj5JbnZlbnRvcnkgVmFsdWUgUmVwb3J0PC9oMz5cbiAgICAgICAgPGkgY2xhc3M9XCJmYS1zb2xpZCBmYS1maWxlLWV4Y2VsIGN1cnNvci1wb2ludGVyIGQtcHJpbnQtbm9uZVwiIChjbGljayk9XCJleHBvcnQoJ2V4Y2VsJylcIj48L2k+XG4gICAgICAgIDxpIGNsYXNzPVwiZmEtc29saWQgZmEtZmlsZS1wZGYgY3Vyc29yLXBvaW50ZXIgZC1wcmludC1ub25lXCIgKGNsaWNrKT1cImV4cG9ydCgncGRmJylcIj48L2k+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxmb3JtIFtmb3JtR3JvdXBdPVwiZmlsdGVyRm9ybVwiIGNsYXNzPVwiZC1mbGV4IGp1c3RpZnktY29udGVudC1lbmQgYWxpZ24taXRlbXMtY2VudGVyIGdhcC0yXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICA8bWF0LWxhYmVsPlNlYXJjaDwvbWF0LWxhYmVsPlxuICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCBwbGFjZWhvbGRlcj1cIlNlYXJjaCBwcm9kdWN0c1wiIGZvcm1Db250cm9sTmFtZT1cInNlYXJjaFwiIC8+XG4gICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG5cbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgIDxtYXQtbGFiZWw+Q2F0ZWdvcnk8L21hdC1sYWJlbD5cbiAgICAgICAgICA8YXBwLXNlYXJjaGFibGUtc2VsZWN0b3JcbiAgICAgICAgICAgIGFwaVVybD1cImFwaS9wcm9kdWN0LWNhdGVnb3JpZXNcIlxuICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiY2F0ZWdvcnlfaWRzXCJcbiAgICAgICAgICAgIFttdWx0aXBsZV09XCJ0cnVlXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgPC9hcHAtc2VhcmNoYWJsZS1zZWxlY3Rvcj5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgIDwvZm9ybT5cbiAgICA8L21hdC1jYXJkLWNvbnRlbnQ+XG4gIDwvbWF0LWNhcmQ+XG5cbiAgPG1hdC1jYXJkIGNsYXNzPVwibXQtM1wiPlxuICAgIDxtYXQtY2FyZC1jb250ZW50IGNsYXNzPVwicC0wXCI+XG4gICAgICA8dGFibGVcbiAgICAgICAgbWF0LXRhYmxlIFtkYXRhU291cmNlXT1cIm1vZGVsc1wiIGNsYXNzPVwidy0xMDBcIlxuICAgICAgICBpbmZpbml0ZVNjcm9sbFxuICAgICAgICBbaW5maW5pdGVTY3JvbGxEaXN0YW5jZV09XCIyXCIgW2luZmluaXRlU2Nyb2xsVGhyb3R0bGVdPVwiNTBcIiAoc2Nyb2xsZWQpPVwib25TY3JvbGwoKVwiXG4gICAgICAgIG1hdFNvcnQgKG1hdFNvcnRDaGFuZ2UpPVwib25Tb3J0Q2hhbmdlKCRldmVudClcIlxuICAgICAgPlxuXG4gICAgICAgIDwhLS0gIyBDb2x1bW4gLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiI1wiPlxuICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+ICMgPC90aD5cbiAgICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgZWxlbWVudDsgbGV0IGkgPSBpbmRleFwiPiB7eyBpICsgMX19IDwvdGQ+XG4gICAgICAgICAgPHRkIG1hdC1mb290ZXItY2VsbCAqbWF0Rm9vdGVyQ2VsbERlZj48L3RkPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8IS0tIFByb2R1Y3QgQ29sdW1uIC0tPlxuICAgICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cIlByb2R1Y3RcIj5cbiAgICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj1cIm5hbWVcIj4gUHJvZHVjdCA8L3RoPlxuICAgICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCBlbGVtZW50XCI+XG4gICAgICAgICAgICA8YVxuICAgICAgICAgICAgICBbcm91dGVyTGlua109XCJbJy9pbnZlbnRvcnkvcHJvZHVjdHMnLCBlbGVtZW50Py5pZCwgJ3ZpZXcnXVwiXG4gICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1kYXJrXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAge3sgZWxlbWVudD8ubmFtZSB9fVxuICAgICAgICAgICAgPC9hPlxuICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgPHRkIG1hdC1mb290ZXItY2VsbCAqbWF0Rm9vdGVyQ2VsbERlZj48L3RkPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8IS0tIERlc2NyaXB0aW9uIENvbHVtbiAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJEZXNjcmlwdGlvblwiPlxuICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+IERlc2NyaXB0aW9uIDwvdGg+XG4gICAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IGVsZW1lbnRcIj5cbiAgICAgICAgICAgIHt7IGVsZW1lbnQ/LmRlc2NyaXB0aW9uIH19XG4gICAgICAgICAgPC90ZD5cbiAgICAgICAgICA8dGQgbWF0LWZvb3Rlci1jZWxsICptYXRGb290ZXJDZWxsRGVmPjwvdGQ+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgIDwhLS0gQ2F0ZWdvcmllcyBDb2x1bW4gLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiQ2F0ZWdvcmllc1wiPlxuICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+IENhdGVnb3JpZXMgPC90aD5cbiAgICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgZWxlbWVudFwiPlxuICAgICAgICAgICAgPGFwcC1wcm9kdWN0LWNhdGVnb3J5LWJhZGdlcyBbcHJvZHVjdF09XCJlbGVtZW50XCI+PC9hcHAtcHJvZHVjdC1jYXRlZ29yeS1iYWRnZXM+XG4gICAgICAgICAgPC90ZD5cbiAgICAgICAgICA8dGQgbWF0LWZvb3Rlci1jZWxsICptYXRGb290ZXJDZWxsRGVmPlxuICAgICAgICAgICAgPHN0cm9uZz5Ub3RhbDwvc3Ryb25nPlxuICAgICAgICAgIDwvdGQ+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgIDwhLS0gQXZhaWxhYmxlIFN0b2NrIENvbHVtbiAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJBdmFpbGFibGUgU3RvY2tcIj5cbiAgICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj1cImN1cnJlbnRfc3RvY2tcIj4gQXZhaWxhYmxlIFN0b2NrIDwvdGg+XG4gICAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IGVsZW1lbnRcIj5cbiAgICAgICAgICAgIHt7IGVsZW1lbnQ/LmN1cnJlbnRfc3RvY2sgfX1cbiAgICAgICAgICA8L3RkPlxuICAgICAgICAgIDx0ZCBtYXQtZm9vdGVyLWNlbGwgKm1hdEZvb3RlckNlbGxEZWY+PC90ZD5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPCEtLSBBdmVyYWdlIFByaWNlIENvbHVtbiAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJBdmVyYWdlIFByaWNlXCI+XG4gICAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZiBtYXQtc29ydC1oZWFkZXI9XCJhdmVyYWdlX3B1cmNoYXNlX3ByaWNlXCI+IEF2ZXJhZ2UgUHJpY2UgPC90aD5cbiAgICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgZWxlbWVudFwiPlxuICAgICAgICAgICAge3sgZWxlbWVudD8uYXZlcmFnZV9wdXJjaGFzZV9wcmljZSB8IGN1cnJlbmN5IH19XG4gICAgICAgICAgPC90ZD5cbiAgICAgICAgICA8dGQgbWF0LWZvb3Rlci1jZWxsICptYXRGb290ZXJDZWxsRGVmPjwvdGQ+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgIDwhLS0gSW52ZW50b3J5IFZhbHVlIENvbHVtbiAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJJbnZlbnRvcnkgVmFsdWVcIj5cbiAgICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj1cImludmVudG9yeV92YWx1ZVwiPiBJbnZlbnRvcnkgVmFsdWUgPC90aD5cbiAgICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgZWxlbWVudFwiPlxuICAgICAgICAgICAge3sgZWxlbWVudD8uaW52ZW50b3J5X3ZhbHVlIHwgY3VycmVuY3kgfX1cbiAgICAgICAgICA8L3RkPlxuICAgICAgICAgIDx0ZCBtYXQtZm9vdGVyLWNlbGwgKm1hdEZvb3RlckNlbGxEZWY+XG4gICAgICAgICAgICA8c3Ryb25nPnt7IHRvdGFsSW52ZW50b3J5VmFsdWUgfCBjdXJyZW5jeSB9fTwvc3Ryb25nPlxuICAgICAgICAgIDwvdGQ+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgIDwhLS0gTGFzdCBQdXJjaGFzZSBQcmljZSBDb2x1bW4gLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiTGFzdCBQdXJjaGFzZSBQcmljZVwiPlxuICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWYgbWF0LXNvcnQtaGVhZGVyPVwibGFzdF9zdG9ja19yZWNlaXB0LnB1cmNoYXNlX3ByaWNlXCI+XG4gICAgICAgICAgICBMYXN0IFB1cmNoYXNlIFByaWNlXG4gICAgICAgICAgPC90aD5cbiAgICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgZWxlbWVudFwiPlxuICAgICAgICAgICAge3sgZWxlbWVudD8ubGFzdF9zdG9ja19yZWNlaXB0Py5wdXJjaGFzZV9wcmljZSA/PyAwIHwgY3VycmVuY3kgfX1cbiAgICAgICAgICA8L3RkPlxuICAgICAgICAgIDx0ZCBtYXQtZm9vdGVyLWNlbGwgKm1hdEZvb3RlckNlbGxEZWY+PC90ZD5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPCEtLSBJbnZlbnRvcnkgVmFsdWUgQmFzZWQgT24gTGFzdCBQdXJjaGFzZSBQcmljZSBDb2x1bW4gLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiSW52ZW50b3J5IFZhbHVlIEJhc2VkIE9uIExhc3QgUHVyY2hhc2UgUHJpY2VcIj5cbiAgICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj1cImxhc3Rfc3RvY2tfcmVjZWlwdC5hbW91bnRcIj5cbiAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwibWItMFwiPkludmVudG9yeSBWYWx1ZTwvcD5cbiAgICAgICAgICAgICAgPHNtYWxsIGNsYXNzPVwidGV4dC1zZWNvbmRhcnlcIj5CYXNlZCBvbiBsYXN0IHB1cmNoYXNlIHByaWNlPC9zbWFsbD5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IGVsZW1lbnRcIj5cbiAgICAgICAgICAgIHt7IGVsZW1lbnQ/Lmxhc3Rfc3RvY2tfcmVjZWlwdD8uYW1vdW50ID8/IDAgfCBjdXJyZW5jeSB9fVxuICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgPHRkIG1hdC1mb290ZXItY2VsbCAqbWF0Rm9vdGVyQ2VsbERlZj48L3RkPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8dHIgbWF0LWhlYWRlci1yb3cgKm1hdEhlYWRlclJvd0RlZj1cImRpc3BsYXllZENvbHVtbnNcIj48L3RyPlxuICAgICAgICA8dHIgbWF0LXJvdyAqbWF0Um93RGVmPVwibGV0IHJvdzsgY29sdW1uczogZGlzcGxheWVkQ29sdW1ucztcIj48L3RyPlxuICAgICAgICA8dHIgbWF0LWZvb3Rlci1yb3cgKm1hdEZvb3RlclJvd0RlZj1cImRpc3BsYXllZENvbHVtbnNcIj48L3RyPlxuICAgICAgPC90YWJsZT5cblxuICAgICAgPG1hdC1wcm9ncmVzcy1iYXIgbW9kZT1cImluZGV0ZXJtaW5hdGVcIiAqbmdJZj1cImlzV29ya2luZ1wiPjwvbWF0LXByb2dyZXNzLWJhcj5cbiAgICA8L21hdC1jYXJkLWNvbnRlbnQ+XG4gIDwvbWF0LWNhcmQ+XG48L2Rpdj5cbiJdfQ==
@@ -0,0 +1,165 @@
1
+ import { Component } from '@angular/core';
2
+ import { CurrencyPipe, DatePipe, NgIf } from "@angular/common";
3
+ import { FormsModule, ReactiveFormsModule } from "@angular/forms";
4
+ import { InfiniteScrollDirective } from "ngx-infinite-scroll";
5
+ import { MatCard, MatCardContent } from "@angular/material/card";
6
+ import { MatCell, MatCellDef, MatColumnDef, MatFooterCell, MatFooterCellDef, MatFooterRow, MatFooterRowDef, MatHeaderCell, MatHeaderCellDef, MatHeaderRow, MatHeaderRowDef, MatRow, MatRowDef, MatTable } from "@angular/material/table";
7
+ import { MatFormField, MatLabel } from "@angular/material/form-field";
8
+ import { MatInput } from "@angular/material/input";
9
+ import { MatProgressBar } from "@angular/material/progress-bar";
10
+ import { MatSort, MatSortHeader } from "@angular/material/sort";
11
+ import { ProductCategoryBadgesComponent } from "../../product/widgets/product-category-badges/product-category-badges.component";
12
+ import { SearchableSelectorModule, TechlifyListingControllerInterface } from "ngx-techlify-core";
13
+ import { RouterLink } from '@angular/router';
14
+ import { debounceTime, distinctUntilChanged } from 'rxjs';
15
+ import * as i0 from "@angular/core";
16
+ import * as i1 from "../../low-stock-report.service";
17
+ import * as i2 from "@angular/router";
18
+ import * as i3 from "ngx-techlify-core";
19
+ import * as i4 from "@angular/forms";
20
+ export class LowStockReportComponent extends TechlifyListingControllerInterface {
21
+ service;
22
+ activatedRoute;
23
+ requestHelperService;
24
+ formBuilder;
25
+ displayedColumns = [
26
+ '#',
27
+ 'Product',
28
+ 'Type',
29
+ 'Categories',
30
+ 'Reorder Point',
31
+ 'Stock',
32
+ 'Last Purchase',
33
+ '30d Issues',
34
+ '30d Receipts',
35
+ '60d Issues',
36
+ '60d Receipts',
37
+ '90d Issues',
38
+ '90d Receipts',
39
+ '1y Issues',
40
+ '1y Receipts',
41
+ ];
42
+ totalInventoryValue = 0;
43
+ isExporting = false;
44
+ constructor(service, activatedRoute, requestHelperService, formBuilder) {
45
+ super();
46
+ this.service = service;
47
+ this.activatedRoute = activatedRoute;
48
+ this.requestHelperService = requestHelperService;
49
+ this.formBuilder = formBuilder;
50
+ this.filterForm = this.formBuilder.group({
51
+ category_ids: [''],
52
+ search: [''],
53
+ sort_by: ['id|desc']
54
+ });
55
+ }
56
+ ngOnInit() {
57
+ this.updateFormWithQueryParams();
58
+ this.subscribeToFormChanges();
59
+ this.subscribeToRouteChanges();
60
+ }
61
+ loadData() {
62
+ const params = {
63
+ ...this.requestHelperService.convertToFormData(this.filterForm.value),
64
+ page: this.page,
65
+ perPage: this.perPage,
66
+ with: 'categories,lastStockReceipt,type,measure',
67
+ };
68
+ this.isWorking = true;
69
+ this.service.index(params).subscribe({
70
+ next: (response) => {
71
+ this.models = this.models?.concat(response?.data);
72
+ this.isWorking = false;
73
+ this.models.forEach((model) => {
74
+ this.totalInventoryValue += model?.inventory_value;
75
+ });
76
+ },
77
+ error: () => (this.isWorking = false),
78
+ });
79
+ }
80
+ onSortChange(sort) {
81
+ let { active, direction } = sort;
82
+ if (!active)
83
+ active = 'id';
84
+ if (!direction)
85
+ direction = 'desc';
86
+ this.filterForm.get('sort_by')?.setValue(active + '|' + direction);
87
+ }
88
+ export() {
89
+ const params = {
90
+ ...this.requestHelperService.convertToFormData(this.filterForm.value),
91
+ page: this.page,
92
+ perPage: 50000,
93
+ with: 'categories,lastStockReceipt',
94
+ };
95
+ this.isExporting = true;
96
+ this.service.export(params).subscribe({
97
+ next: (response) => {
98
+ this.isExporting = false;
99
+ window.open(response?.item?.file_link, '_blank');
100
+ },
101
+ error: () => (this.isExporting = false)
102
+ });
103
+ }
104
+ updateFormWithQueryParams() {
105
+ this.requestHelperService.updateFormWithQueryParams(this.filterForm, {
106
+ category_ids: { multiple: true }
107
+ });
108
+ }
109
+ subscribeToFormChanges() {
110
+ this.filterForm.valueChanges.pipe(debounceTime(800)).subscribe({
111
+ next: () => {
112
+ this.requestHelperService.updateQueryParams(this.requestHelperService.convertToFormData(this.filterForm.value));
113
+ }
114
+ });
115
+ }
116
+ subscribeToRouteChanges() {
117
+ this.activatedRoute.queryParams
118
+ .pipe(debounceTime(500), distinctUntilChanged())
119
+ .subscribe(() => {
120
+ this.reload();
121
+ });
122
+ }
123
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockReportComponent, deps: [{ token: i1.LowStockReportService }, { token: i2.ActivatedRoute }, { token: i3.RequestHelperService }, { token: i4.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
124
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: LowStockReportComponent, isStandalone: true, selector: "app-low-stock-report", usesInheritance: true, ngImport: i0, template: "<div>\n <mat-card>\n <mat-card-content class=\"d-flex justify-content-between align-items-center gap-2\">\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <h3 class=\"mb-0\">Low Stock Report</h3>\n <i class=\"fa-solid fa-file-excel cursor-pointer d-print-none\" (click)=\"export()\"></i>\n </div>\n <form [formGroup]=\"filterForm\" class=\"d-flex justify-content-end align-items-center gap-2\">\n <mat-form-field>\n <mat-label>Search</mat-label>\n <input matInput placeholder=\"Search products\" formControlName=\"search\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Category</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-categories\"\n formControlName=\"category_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n </form>\n </mat-card-content>\n </mat-card>\n\n <mat-card class=\"mt-3\">\n <mat-card-content class=\"p-0\">\n <table\n mat-table [dataSource]=\"models\" class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\" [infiniteScrollThrottle]=\"50\" (scrolled)=\"onScroll()\"\n matSort (matSortChange)=\"onSortChange($event)\"\n >\n\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef> # </th>\n <td mat-cell *matCellDef=\"let element; let i = index\"> {{ i + 1}} </td>\n </ng-container>\n\n <!-- Product Column -->\n <ng-container matColumnDef=\"Product\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"name\"> Product </th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n [routerLink]=\"['/inventory/products', element?.id, 'view']\"\n class=\"text-dark\"\n >\n {{ element?.name }}\n </a>\n </td>\n </ng-container>\n\n <!-- Type Column -->\n <ng-container matColumnDef=\"Type\">\n <th mat-header-cell *matHeaderCellDef> Type </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.type?.title }}\n </td>\n </ng-container>\n\n <!-- Reorder Point Column -->\n <ng-container matColumnDef=\"Reorder Point\">\n <th mat-header-cell *matHeaderCellDef> Reorder Point </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.reorder_point }}\n </td>\n </ng-container>\n\n <!-- Categories Column -->\n <ng-container matColumnDef=\"Categories\">\n <th mat-header-cell *matHeaderCellDef> Categories </th>\n <td mat-cell *matCellDef=\"let element\">\n <app-product-category-badges [product]=\"element\"></app-product-category-badges>\n </td>\n </ng-container>\n\n <!-- Stock Column -->\n <ng-container matColumnDef=\"Stock\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"stock\"> Stock </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.stock }}\n </td>\n </ng-container>\n\n <!-- Last Purchase Column -->\n <ng-container matColumnDef=\"Last Purchase\">\n <th mat-header-cell *matHeaderCellDef>\n Last Purchase\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\" *ngIf=\"element?.last_stock_receipt\">\n {{ element?.last_stock_receipt?.date | date }} -\n {{ element?.last_stock_receipt?.quantity }} {{ element?.measure?.title }}\n </p>\n <small class=\"text-secondary\" *ngIf=\"element?.last_stock_receipt\">\n {{ element?.last_stock_receipt?.purchase_price ?? 0 | currency }} per {{ element?.measure?.title }}\n </small>\n </td>\n </ng-container>\n\n <!-- 30d Issues -->\n <ng-container matColumnDef=\"30d Issues\">\n <th mat-header-cell *matHeaderCellDef> 30d Issues </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.issues_30d }}</td>\n </ng-container>\n\n <!-- 30d Receipts -->\n <ng-container matColumnDef=\"30d Receipts\">\n <th mat-header-cell *matHeaderCellDef> 30d Receipts </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.receipts_30d }}</td>\n </ng-container>\n\n <!-- 60d Issues -->\n <ng-container matColumnDef=\"60d Issues\">\n <th mat-header-cell *matHeaderCellDef> 60d Issues </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.issues_60d }}</td>\n </ng-container>\n\n <!-- 60d Receipts -->\n <ng-container matColumnDef=\"60d Receipts\">\n <th mat-header-cell *matHeaderCellDef> 60d Receipts </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.receipts_60d }}</td>\n </ng-container>\n\n <!-- 90d Issues -->\n <ng-container matColumnDef=\"90d Issues\">\n <th mat-header-cell *matHeaderCellDef> 90d Issues </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.issues_90d }}</td>\n </ng-container>\n\n <!-- 90d Receipts -->\n <ng-container matColumnDef=\"90d Receipts\">\n <th mat-header-cell *matHeaderCellDef> 90d Receipts </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.receipts_90d }}</td>\n </ng-container>\n\n <!-- 1y Issues -->\n <ng-container matColumnDef=\"1y Issues\">\n <th mat-header-cell *matHeaderCellDef> 1y Issues </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.issues_1y }}</td>\n </ng-container>\n\n <!-- 60d Receipts -->\n <ng-container matColumnDef=\"1y Receipts\">\n <th mat-header-cell *matHeaderCellDef> 1y Receipts </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.receipts_1y }}</td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isWorking\"></mat-progress-bar>\n </mat-card-content>\n </mat-card>\n</div>\n", styles: [""], dependencies: [{ kind: "pipe", type: CurrencyPipe, name: "currency" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i4.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: InfiniteScrollDirective, selector: "[infiniteScroll], [infinite-scroll], [data-infinite-scroll]", inputs: ["infiniteScrollDistance", "infiniteScrollUpDistance", "infiniteScrollThrottle", "infiniteScrollDisabled", "infiniteScrollContainer", "scrollWindow", "immediateCheck", "horizontal", "alwaysCallback", "fromRoot"], outputs: ["scrolled", "scrolledUp"] }, { kind: "component", type: MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: MatCardContent, selector: "mat-card-content" }, { kind: "directive", type: MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "component", type: MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "directive", type: MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: ProductCategoryBadgesComponent, selector: "app-product-category-badges", inputs: ["product"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i4.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i4.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: SearchableSelectorModule }, { kind: "component", type: i3.SearchableSelectorComponent, selector: "app-searchable-selector", inputs: ["valueField", "titleField", "subtitleField", "apiUrl", "multiple", "selectedValue", "enableSearch", "add", "addConfig", "edit", "editConfig", "sort", "sortBy", "searchField", "itemComponent", "items", "apiDataProperty", "cache", "perPage", "inDataSearch", "panelWidth", "focusSearchOnOpen", "required", "disabled", "value"], outputs: ["selectedValueChange", "selectionChange", "itemsChange"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "pipe", type: DatePipe, name: "date" }], preserveWhitespaces: true });
125
+ }
126
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LowStockReportComponent, decorators: [{
127
+ type: Component,
128
+ args: [{ selector: 'app-low-stock-report', standalone: true, imports: [
129
+ CurrencyPipe,
130
+ FormsModule,
131
+ InfiniteScrollDirective,
132
+ MatCard,
133
+ MatCardContent,
134
+ MatCell,
135
+ MatCellDef,
136
+ MatColumnDef,
137
+ MatFooterCell,
138
+ MatFooterRow,
139
+ MatFooterRowDef,
140
+ MatFormField,
141
+ MatHeaderCell,
142
+ MatHeaderRow,
143
+ MatHeaderRowDef,
144
+ MatInput,
145
+ MatLabel,
146
+ MatProgressBar,
147
+ MatRow,
148
+ MatRowDef,
149
+ MatSort,
150
+ MatSortHeader,
151
+ MatTable,
152
+ NgIf,
153
+ ProductCategoryBadgesComponent,
154
+ ReactiveFormsModule,
155
+ SearchableSelectorModule,
156
+ RouterLink,
157
+ MatFooterCellDef,
158
+ MatHeaderCellDef,
159
+ MatFooterCellDef,
160
+ MatHeaderCellDef,
161
+ MatHeaderCellDef,
162
+ DatePipe
163
+ ], template: "<div>\n <mat-card>\n <mat-card-content class=\"d-flex justify-content-between align-items-center gap-2\">\n <div class=\"d-flex justify-content-start align-items-center gap-2\">\n <h3 class=\"mb-0\">Low Stock Report</h3>\n <i class=\"fa-solid fa-file-excel cursor-pointer d-print-none\" (click)=\"export()\"></i>\n </div>\n <form [formGroup]=\"filterForm\" class=\"d-flex justify-content-end align-items-center gap-2\">\n <mat-form-field>\n <mat-label>Search</mat-label>\n <input matInput placeholder=\"Search products\" formControlName=\"search\" />\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Category</mat-label>\n <app-searchable-selector\n apiUrl=\"api/product-categories\"\n formControlName=\"category_ids\"\n [multiple]=\"true\"\n >\n </app-searchable-selector>\n </mat-form-field>\n </form>\n </mat-card-content>\n </mat-card>\n\n <mat-card class=\"mt-3\">\n <mat-card-content class=\"p-0\">\n <table\n mat-table [dataSource]=\"models\" class=\"w-100\"\n infiniteScroll\n [infiniteScrollDistance]=\"2\" [infiniteScrollThrottle]=\"50\" (scrolled)=\"onScroll()\"\n matSort (matSortChange)=\"onSortChange($event)\"\n >\n\n <!-- # Column -->\n <ng-container matColumnDef=\"#\">\n <th mat-header-cell *matHeaderCellDef> # </th>\n <td mat-cell *matCellDef=\"let element; let i = index\"> {{ i + 1}} </td>\n </ng-container>\n\n <!-- Product Column -->\n <ng-container matColumnDef=\"Product\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"name\"> Product </th>\n <td mat-cell *matCellDef=\"let element\">\n <a\n [routerLink]=\"['/inventory/products', element?.id, 'view']\"\n class=\"text-dark\"\n >\n {{ element?.name }}\n </a>\n </td>\n </ng-container>\n\n <!-- Type Column -->\n <ng-container matColumnDef=\"Type\">\n <th mat-header-cell *matHeaderCellDef> Type </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.type?.title }}\n </td>\n </ng-container>\n\n <!-- Reorder Point Column -->\n <ng-container matColumnDef=\"Reorder Point\">\n <th mat-header-cell *matHeaderCellDef> Reorder Point </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.reorder_point }}\n </td>\n </ng-container>\n\n <!-- Categories Column -->\n <ng-container matColumnDef=\"Categories\">\n <th mat-header-cell *matHeaderCellDef> Categories </th>\n <td mat-cell *matCellDef=\"let element\">\n <app-product-category-badges [product]=\"element\"></app-product-category-badges>\n </td>\n </ng-container>\n\n <!-- Stock Column -->\n <ng-container matColumnDef=\"Stock\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header=\"stock\"> Stock </th>\n <td mat-cell *matCellDef=\"let element\">\n {{ element?.stock }}\n </td>\n </ng-container>\n\n <!-- Last Purchase Column -->\n <ng-container matColumnDef=\"Last Purchase\">\n <th mat-header-cell *matHeaderCellDef>\n Last Purchase\n </th>\n <td mat-cell *matCellDef=\"let element\">\n <p class=\"mb-0\" *ngIf=\"element?.last_stock_receipt\">\n {{ element?.last_stock_receipt?.date | date }} -\n {{ element?.last_stock_receipt?.quantity }} {{ element?.measure?.title }}\n </p>\n <small class=\"text-secondary\" *ngIf=\"element?.last_stock_receipt\">\n {{ element?.last_stock_receipt?.purchase_price ?? 0 | currency }} per {{ element?.measure?.title }}\n </small>\n </td>\n </ng-container>\n\n <!-- 30d Issues -->\n <ng-container matColumnDef=\"30d Issues\">\n <th mat-header-cell *matHeaderCellDef> 30d Issues </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.issues_30d }}</td>\n </ng-container>\n\n <!-- 30d Receipts -->\n <ng-container matColumnDef=\"30d Receipts\">\n <th mat-header-cell *matHeaderCellDef> 30d Receipts </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.receipts_30d }}</td>\n </ng-container>\n\n <!-- 60d Issues -->\n <ng-container matColumnDef=\"60d Issues\">\n <th mat-header-cell *matHeaderCellDef> 60d Issues </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.issues_60d }}</td>\n </ng-container>\n\n <!-- 60d Receipts -->\n <ng-container matColumnDef=\"60d Receipts\">\n <th mat-header-cell *matHeaderCellDef> 60d Receipts </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.receipts_60d }}</td>\n </ng-container>\n\n <!-- 90d Issues -->\n <ng-container matColumnDef=\"90d Issues\">\n <th mat-header-cell *matHeaderCellDef> 90d Issues </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.issues_90d }}</td>\n </ng-container>\n\n <!-- 90d Receipts -->\n <ng-container matColumnDef=\"90d Receipts\">\n <th mat-header-cell *matHeaderCellDef> 90d Receipts </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.receipts_90d }}</td>\n </ng-container>\n\n <!-- 1y Issues -->\n <ng-container matColumnDef=\"1y Issues\">\n <th mat-header-cell *matHeaderCellDef> 1y Issues </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.issues_1y }}</td>\n </ng-container>\n\n <!-- 60d Receipts -->\n <ng-container matColumnDef=\"1y Receipts\">\n <th mat-header-cell *matHeaderCellDef> 1y Receipts </th>\n <td mat-cell *matCellDef=\"let element\">{{ element?.receipts_1y }}</td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n\n <mat-progress-bar mode=\"indeterminate\" *ngIf=\"isWorking\"></mat-progress-bar>\n </mat-card-content>\n </mat-card>\n</div>\n" }]
164
+ }], ctorParameters: () => [{ type: i1.LowStockReportService }, { type: i2.ActivatedRoute }, { type: i3.RequestHelperService }, { type: i4.FormBuilder }] });
165
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG93LXN0b2NrLXJlcG9ydC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9pbnZlbnRvcnktY29tbW9uL3NyYy9saWIvaW52ZW50b3J5LWNvbW1vbi9yZXBvcnRzL2xvdy1zdG9jay1yZXBvcnQvbG93LXN0b2NrLXJlcG9ydC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9pbnZlbnRvcnktY29tbW9uL3NyYy9saWIvaW52ZW50b3J5LWNvbW1vbi9yZXBvcnRzL2xvdy1zdG9jay1yZXBvcnQvbG93LXN0b2NrLXJlcG9ydC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsU0FBUyxFQUFTLE1BQU0sZUFBZSxDQUFDO0FBQ2hELE9BQU8sRUFBQyxZQUFZLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQzdELE9BQU8sRUFBeUIsV0FBVyxFQUFFLG1CQUFtQixFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEYsT0FBTyxFQUFDLHVCQUF1QixFQUFDLE1BQU0scUJBQXFCLENBQUM7QUFDNUQsT0FBTyxFQUFDLE9BQU8sRUFBRSxjQUFjLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQztBQUMvRCxPQUFPLEVBQ0wsT0FBTyxFQUNQLFVBQVUsRUFDVixZQUFZLEVBQ1osYUFBYSxFQUFFLGdCQUFnQixFQUMvQixZQUFZLEVBQ1osZUFBZSxFQUNmLGFBQWEsRUFBRSxnQkFBZ0IsRUFDL0IsWUFBWSxFQUNaLGVBQWUsRUFDZixNQUFNLEVBQ04sU0FBUyxFQUNULFFBQVEsRUFDVCxNQUFNLHlCQUF5QixDQUFDO0FBQ2pDLE9BQU8sRUFBQyxZQUFZLEVBQUUsUUFBUSxFQUFDLE1BQU0sOEJBQThCLENBQUM7QUFDcEUsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLHlCQUF5QixDQUFDO0FBQ2pE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QUF1Qjt3QkFDdkIsT0FBTzt3QkFDUCxjQUFjO3dCQUNkLE9BQU87d0JBQ1AsVUFBVTt3QkFDVixZQUFZO3dCQUNaLGFBQWE7d0JBQ2IsWUFBWTt3QkFDWixlQUFlO3dCQUNmLFlBQVk7d0JBQ1osYUFBYTt3QkFDYixZQUFZO3dCQUNaLGVBQWU7d0JBQ2YsUUFBUTt3QkFDUixRQUFRO3dCQUNSLGNBQWM7d0JBQ2QsTUFBTTt3QkFDTixTQUFTO3dCQUNULE9BQU87d0JBQ1AsYUFBYTt3QkFDYixRQUFRO3dCQUNSLElBQUk7d0JBQ0osOEJBQThCO3dCQUM5QixtQkFBbUI7d0JBQ25CLHdCQUF3Qjt3QkFDeEIsVUFBVTt3QkFDVixnQkFBZ0I7d0JBQ2hCLGdCQUFnQjt3QkFDaEIsZ0JBQWdCO3dCQUNoQixnQkFBZ0I7d0JBQ2hCLGdCQUFnQjt3QkFDaEIsUUFBUTtxQkFDVCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7Q29tcG9uZW50LCBPbkluaXR9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtDdXJyZW5jeVBpcGUsIERhdGVQaXBlLCBOZ0lmfSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uXCI7XG5pbXBvcnQge0Zvcm1CdWlsZGVyLCBGb3JtR3JvdXAsIEZvcm1zTW9kdWxlLCBSZWFjdGl2ZUZvcm1zTW9kdWxlfSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcbmltcG9ydCB7SW5maW5pdGVTY3JvbGxEaXJlY3RpdmV9IGZyb20gXCJuZ3gtaW5maW5pdGUtc2Nyb2xsXCI7XG5pbXBvcnQge01hdENhcmQsIE1hdENhcmRDb250ZW50fSBmcm9tIFwiQGFuZ3VsYXIvbWF0ZXJpYWwvY2FyZFwiO1xuaW1wb3J0IHtcbiAgTWF0Q2VsbCxcbiAgTWF0Q2VsbERlZixcbiAgTWF0Q29sdW1uRGVmLFxuICBNYXRGb290ZXJDZWxsLCBNYXRGb290ZXJDZWxsRGVmLFxuICBNYXRGb290ZXJSb3csXG4gIE1hdEZvb3RlclJvd0RlZixcbiAgTWF0SGVhZGVyQ2VsbCwgTWF0SGVhZGVyQ2VsbERlZixcbiAgTWF0SGVhZGVyUm93LFxuICBNYXRIZWFkZXJSb3dEZWYsXG4gIE1hdFJvdyxcbiAgTWF0Um93RGVmLFxuICBNYXRUYWJsZVxufSBmcm9tIFwiQGFuZ3VsYXIvbWF0ZXJpYWwvdGFibGVcIjtcbmltcG9ydCB7TWF0Rm9ybUZpZWxkLCBNYXRMYWJlbH0gZnJvbSBcIkBhbmd1bGFyL21hdGVyaWFsL2Zvcm0tZmllbGRcIjtcbmltcG9ydCB7TWF0SW5wdXR9IGZyb20gXCJAYW5ndWxhci9tYXRlcmlhbC9pbnB1dFwiO1xuaW1wb3J0IHtNYXRQcm9ncmVzc0Jhcn0gZnJvbSBcIkBhbmd1bGFyL21hdGVyaWFsL3Byb2dyZXNzLWJhclwiO1xuaW1wb3J0IHtNYXRTb3J0LCBNYXRTb3J0SGVhZGVyLCBTb3J0fSBmcm9tIFwiQGFuZ3VsYXIvbWF0ZXJpYWwvc29ydFwiO1xuaW1wb3J0IHtcbiAgUHJvZHVjdENhdGVnb3J5QmFkZ2VzQ29tcG9uZW50XG59IGZyb20gXCIuLi8uLi9wcm9kdWN0L3dpZGdldHMvcHJvZHVjdC1jYXRlZ29yeS1iYWRnZXMvcHJvZHVjdC1jYXRlZ29yeS1iYWRnZXMuY29tcG9uZW50XCI7XG5pbXBvcnQge1JlcXVlc3RIZWxwZXJTZXJ2aWNlLCBTZWFyY2hhYmxlU2VsZWN0b3JNb2R1bGUsIFRlY2hsaWZ5TGlzdGluZ0NvbnRyb2xsZXJJbnRlcmZhY2V9IGZyb20gXCJuZ3gtdGVjaGxpZnktY29yZVwiO1xuaW1wb3J0IHtJbnZlbnRvcnlWYWx1ZVJlcG9ydFNlcnZpY2V9IGZyb20gJy4uLy4uL2ludmVudG9yeS12YWx1ZS1yZXBvcnQuc2VydmljZSc7XG5pbXBvcnQge0FjdGl2YXRlZFJvdXRlLCBSb3V0ZXJMaW5rfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHtkZWJvdW5jZVRpbWUsIGRpc3RpbmN0VW50aWxDaGFuZ2VkfSBmcm9tICdyeGpzJztcbmltcG9ydCB7TG93U3RvY2tSZXBvcnRTZXJ2aWNlfSBmcm9tICcuLi8uLi9sb3ctc3RvY2stcmVwb3J0LnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhcHAtbG93LXN0b2NrLXJlcG9ydCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBDdXJyZW5jeVBpcGUsXG4gICAgRm9ybXNNb2R1bGUsXG4gICAgSW5maW5pdGVTY3JvbGxEaXJlY3RpdmUsXG4gICAgTWF0Q2FyZCxcbiAgICBNYXRDYXJkQ29udGVudCxcbiAgICBNYXRDZWxsLFxuICAgIE1hdENlbGxEZWYsXG4gICAgTWF0Q29sdW1uRGVmLFxuICAgIE1hdEZvb3RlckNlbGwsXG4gICAgTWF0Rm9vdGVyUm93LFxuICAgIE1hdEZvb3RlclJvd0RlZixcbiAgICBNYXRGb3JtRmllbGQsXG4gICAgTWF0SGVhZGVyQ2VsbCxcbiAgICBNYXRIZWFkZXJSb3csXG4gICAgTWF0SGVhZGVyUm93RGVmLFxuICAgIE1hdElucHV0LFxuICAgIE1hdExhYmVsLFxuICAgIE1hdFByb2dyZXNzQmFyLFxuICAgIE1hdFJvdyxcbiAgICBNYXRSb3dEZWYsXG4gICAgTWF0U29ydCxcbiAgICBNYXRTb3J0SGVhZGVyLFxuICAgIE1hdFRhYmxlLFxuICAgIE5nSWYsXG4gICAgUHJvZHVjdENhdGVnb3J5QmFkZ2VzQ29tcG9uZW50LFxuICAgIFJlYWN0aXZlRm9ybXNNb2R1bGUsXG4gICAgU2VhcmNoYWJsZVNlbGVjdG9yTW9kdWxlLFxuICAgIFJvdXRlckxpbmssXG4gICAgTWF0Rm9vdGVyQ2VsbERlZixcbiAgICBNYXRIZWFkZXJDZWxsRGVmLFxuICAgIE1hdEZvb3RlckNlbGxEZWYsXG4gICAgTWF0SGVhZGVyQ2VsbERlZixcbiAgICBNYXRIZWFkZXJDZWxsRGVmLFxuICAgIERhdGVQaXBlXG4gIF0sXG4gIHRlbXBsYXRlVXJsOiAnLi9sb3ctc3RvY2stcmVwb3J0LmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmw6ICcuL2xvdy1zdG9jay1yZXBvcnQuY29tcG9uZW50LnNjc3MnXG59KVxuZXhwb3J0IGNsYXNzIExvd1N0b2NrUmVwb3J0Q29tcG9uZW50IGV4dGVuZHMgVGVjaGxpZnlMaXN0aW5nQ29udHJvbGxlckludGVyZmFjZSBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIGRpc3BsYXllZENvbHVtbnM6IHN0cmluZ1tdID0gW1xuICAgICcjJyxcbiAgICAnUHJvZHVjdCcsXG4gICAgJ1R5cGUnLFxuICAgICdDYXRlZ29yaWVzJyxcbiAgICAnUmVvcmRlciBQb2ludCcsXG4gICAgJ1N0b2NrJyxcbiAgICAnTGFzdCBQdXJjaGFzZScsXG4gICAgJzMwZCBJc3N1ZXMnLFxuICAgICczMGQgUmVjZWlwdHMnLFxuICAgICc2MGQgSXNzdWVzJyxcbiAgICAnNjBkIFJlY2VpcHRzJyxcbiAgICAnOTBkIElzc3VlcycsXG4gICAgJzkwZCBSZWNlaXB0cycsXG4gICAgJzF5IElzc3VlcycsXG4gICAgJzF5IFJlY2VpcHRzJyxcbiAgXTtcbiAgdG90YWxJbnZlbnRvcnlWYWx1ZSA9IDA7XG4gIGlzRXhwb3J0aW5nID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBzZXJ2aWNlOiBMb3dTdG9ja1JlcG9ydFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBhY3RpdmF0ZWRSb3V0ZTogQWN0aXZhdGVkUm91dGUsXG4gICAgcHJpdmF0ZSByZXF1ZXN0SGVscGVyU2VydmljZTogUmVxdWVzdEhlbHBlclNlcnZpY2UsXG4gICAgcHJpdmF0ZSBmb3JtQnVpbGRlcjogRm9ybUJ1aWxkZXJcbiAgKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuZmlsdGVyRm9ybSA9IHRoaXMuZm9ybUJ1aWxkZXIuZ3JvdXAoe1xuICAgICAgY2F0ZWdvcnlfaWRzOiBbJyddLFxuICAgICAgc2VhcmNoOiBbJyddLFxuICAgICAgc29ydF9ieTogWydpZHxkZXNjJ11cbiAgICB9KTtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMudXBkYXRlRm9ybVdpdGhRdWVyeVBhcmFtcygpO1xuICAgIHRoaXMuc3Vic2NyaWJlVG9Gb3JtQ2hhbmdlcygpO1xuICAgIHRoaXMuc3Vic2NyaWJlVG9Sb3V0ZUNoYW5nZXMoKTtcbiAgfVxuXG4gIGxvYWREYXRhKCk6IHZvaWQge1xuICAgIGNvbnN0IHBhcmFtczogYW55ID0ge1xuICAgICAgLi4udGhpcy5yZXF1ZXN0SGVscGVyU2VydmljZS5jb252ZXJ0VG9Gb3JtRGF0YSh0aGlzLmZpbHRlckZvcm0udmFsdWUpLFxuICAgICAgcGFnZTogdGhpcy5wYWdlLFxuICAgICAgcGVyUGFnZTogdGhpcy5wZXJQYWdlLFxuICAgICAgd2l0aDogJ2NhdGVnb3JpZXMsbGFzdFN0b2NrUmVjZWlwdCx0eXBlLG1lYXN1cmUnLFxuICAgIH1cbiAgICB0aGlzLmlzV29ya2luZyA9IHRydWU7XG4gICAgdGhpcy5zZXJ2aWNlLmluZGV4KHBhcmFtcykuc3Vic2NyaWJlKHtcbiAgICAgIG5leHQ6IChyZXNwb25zZTogYW55KSA9PiB7XG4gICAgICAgIHRoaXMubW9kZWxzID0gdGhpcy5tb2RlbHM/LmNvbmNhdChyZXNwb25zZT8uZGF0YSk7XG4gICAgICAgIHRoaXMuaXNXb3JraW5nID0gZmFsc2U7XG5cbiAgICAgICAgdGhpcy5tb2RlbHMuZm9yRWFjaCgobW9kZWw6IGFueSkgPT4ge1xuICAgICAgICAgIHRoaXMudG90YWxJbnZlbnRvcnlWYWx1ZSArPSBtb2RlbD8uaW52ZW50b3J5X3ZhbHVlO1xuICAgICAgICB9KVxuICAgICAgfSxcbiAgICAgIGVycm9yOiAoKSA9PiAodGhpcy5pc1dvcmtpbmcgPSBmYWxzZSksXG4gICAgfSk7XG4gIH1cblxuICBvblNvcnRDaGFuZ2Uoc29ydDogU29ydCkge1xuICAgIGxldCB7YWN0aXZlLCBkaXJlY3Rpb259ID0gc29ydDtcbiAgICBpZiAoIWFjdGl2ZSkgYWN0aXZlID0gJ2lkJztcbiAgICBpZiAoIWRpcmVjdGlvbikgZGlyZWN0aW9uID0gJ2Rlc2MnO1xuICAgIHRoaXMuZmlsdGVyRm9ybS5nZXQoJ3NvcnRfYnknKT8uc2V0VmFsdWUoYWN0aXZlICsgJ3wnICsgZGlyZWN0aW9uKTtcbiAgfVxuXG4gIGV4cG9ydCgpIHtcbiAgICBjb25zdCBwYXJhbXM6IGFueSA9IHtcbiAgICAgIC4uLnRoaXMucmVxdWVzdEhlbHBlclNlcnZpY2UuY29udmVydFRvRm9ybURhdGEodGhpcy5maWx0ZXJGb3JtLnZhbHVlKSxcbiAgICAgIHBhZ2U6IHRoaXMucGFnZSxcbiAgICAgIHBlclBhZ2U6IDUwMDAwLFxuICAgICAgd2l0aDogJ2NhdGVnb3JpZXMsbGFzdFN0b2NrUmVjZWlwdCcsXG4gICAgfVxuICAgIHRoaXMuaXNFeHBvcnRpbmcgPSB0cnVlO1xuICAgIHRoaXMuc2VydmljZS5leHBvcnQocGFyYW1zKS5zdWJzY3JpYmUoe1xuICAgICAgbmV4dDogKHJlc3BvbnNlOiBhbnkpID0+IHtcbiAgICAgICAgdGhpcy5pc0V4cG9ydGluZyA9IGZhbHNlO1xuICAgICAgICB3aW5kb3cub3BlbihyZXNwb25zZT8uaXRlbT8uZmlsZV9saW5rLCAnX2JsYW5rJyk7XG4gICAgICB9LFxuICAgICAgZXJyb3I6ICgpID0+ICh0aGlzLmlzRXhwb3J0aW5nID0gZmFsc2UpXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZUZvcm1XaXRoUXVlcnlQYXJhbXMoKTogdm9pZCB7XG4gICAgdGhpcy5yZXF1ZXN0SGVscGVyU2VydmljZS51cGRhdGVGb3JtV2l0aFF1ZXJ5UGFyYW1zKFxuICAgICAgdGhpcy5maWx0ZXJGb3JtLFxuICAgICAge1xuICAgICAgICBjYXRlZ29yeV9pZHM6IHttdWx0aXBsZTogdHJ1ZX1cbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBzdWJzY3JpYmVUb0Zvcm1DaGFuZ2VzKCk6IHZvaWQge1xuICAgICh0aGlzLmZpbHRlckZvcm0gYXMgRm9ybUdyb3VwKS52YWx1ZUNoYW5nZXMucGlwZShcbiAgICAgIGRlYm91bmNlVGltZSg4MDApXG4gICAgKS5zdWJzY3JpYmUoe1xuICAgICAgbmV4dDogKCkgPT4ge1xuICAgICAgICB0aGlzLnJlcXVlc3RIZWxwZXJTZXJ2aWNlLnVwZGF0ZVF1ZXJ5UGFyYW1zKFxuICAgICAgICAgIHRoaXMucmVxdWVzdEhlbHBlclNlcnZpY2UuY29udmVydFRvRm9ybURhdGEodGhpcy5maWx0ZXJGb3JtLnZhbHVlKVxuICAgICAgICApO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBzdWJzY3JpYmVUb1JvdXRlQ2hhbmdlcygpOiB2b2lkIHtcbiAgICB0aGlzLmFjdGl2YXRlZFJvdXRlLnF1ZXJ5UGFyYW1zXG4gICAgICAucGlwZShkZWJvdW5jZVRpbWUoNTAwKSxcbiAgICAgICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKSlcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLnJlbG9hZCgpO1xuICAgICAgfSk7XG4gIH1cbn1cbiIsIjxkaXY+XG4gIDxtYXQtY2FyZD5cbiAgICA8bWF0LWNhcmQtY29udGVudCBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1jZW50ZXIgZ2FwLTJcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LXN0YXJ0IGFsaWduLWl0ZW1zLWNlbnRlciBnYXAtMlwiPlxuICAgICAgICA8aDMgY2xhc3M9XCJtYi0wXCI+TG93IFN0b2NrIFJlcG9ydDwvaDM+XG4gICAgICAgIDxpIGNsYXNzPVwiZmEtc29saWQgZmEtZmlsZS1leGNlbCBjdXJzb3ItcG9pbnRlciBkLXByaW50LW5vbmVcIiAoY2xpY2spPVwiZXhwb3J0KClcIj48L2k+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxmb3JtIFtmb3JtR3JvdXBdPVwiZmlsdGVyRm9ybVwiIGNsYXNzPVwiZC1mbGV4IGp1c3RpZnktY29udGVudC1lbmQgYWxpZ24taXRlbXMtY2VudGVyIGdhcC0yXCI+XG4gICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICA8bWF0LWxhYmVsPlNlYXJjaDwvbWF0LWxhYmVsPlxuICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCBwbGFjZWhvbGRlcj1cIlNlYXJjaCBwcm9kdWN0c1wiIGZvcm1Db250cm9sTmFtZT1cInNlYXJjaFwiIC8+XG4gICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG5cbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgIDxtYXQtbGFiZWw+Q2F0ZWdvcnk8L21hdC1sYWJlbD5cbiAgICAgICAgICA8YXBwLXNlYXJjaGFibGUtc2VsZWN0b3JcbiAgICAgICAgICAgIGFwaVVybD1cImFwaS9wcm9kdWN0LWNhdGVnb3JpZXNcIlxuICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiY2F0ZWdvcnlfaWRzXCJcbiAgICAgICAgICAgIFttdWx0aXBsZV09XCJ0cnVlXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgPC9hcHAtc2VhcmNoYWJsZS1zZWxlY3Rvcj5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgIDwvZm9ybT5cbiAgICA8L21hdC1jYXJkLWNvbnRlbnQ+XG4gIDwvbWF0LWNhcmQ+XG5cbiAgPG1hdC1jYXJkIGNsYXNzPVwibXQtM1wiPlxuICAgIDxtYXQtY2FyZC1jb250ZW50IGNsYXNzPVwicC0wXCI+XG4gICAgICA8dGFibGVcbiAgICAgICAgbWF0LXRhYmxlIFtkYXRhU291cmNlXT1cIm1vZGVsc1wiIGNsYXNzPVwidy0xMDBcIlxuICAgICAgICBpbmZpbml0ZVNjcm9sbFxuICAgICAgICBbaW5maW5pdGVTY3JvbGxEaXN0YW5jZV09XCIyXCIgW2luZmluaXRlU2Nyb2xsVGhyb3R0bGVdPVwiNTBcIiAoc2Nyb2xsZWQpPVwib25TY3JvbGwoKVwiXG4gICAgICAgIG1hdFNvcnQgKG1hdFNvcnRDaGFuZ2UpPVwib25Tb3J0Q2hhbmdlKCRldmVudClcIlxuICAgICAgPlxuXG4gICAgICAgIDwhLS0gIyBDb2x1bW4gLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiI1wiPlxuICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+ICMgPC90aD5cbiAgICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgZWxlbWVudDsgbGV0IGkgPSBpbmRleFwiPiB7eyBpICsgMX19IDwvdGQ+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgIDwhLS0gUHJvZHVjdCBDb2x1bW4gLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiUHJvZHVjdFwiPlxuICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWYgbWF0LXNvcnQtaGVhZGVyPVwibmFtZVwiPiBQcm9kdWN0IDwvdGg+XG4gICAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IGVsZW1lbnRcIj5cbiAgICAgICAgICAgIDxhXG4gICAgICAgICAgICAgIFtyb3V0ZXJMaW5rXT1cIlsnL2ludmVudG9yeS9wcm9kdWN0cycsIGVsZW1lbnQ/LmlkLCAndmlldyddXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LWRhcmtcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICB7eyBlbGVtZW50Py5uYW1lIH19XG4gICAgICAgICAgICA8L2E+XG4gICAgICAgICAgPC90ZD5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPCEtLSBUeXBlIENvbHVtbiAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJUeXBlXCI+XG4gICAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZj4gVHlwZSA8L3RoPlxuICAgICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCBlbGVtZW50XCI+XG4gICAgICAgICAgICB7eyBlbGVtZW50Py50eXBlPy50aXRsZSB9fVxuICAgICAgICAgIDwvdGQ+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgIDwhLS0gUmVvcmRlciBQb2ludCBDb2x1bW4gLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiUmVvcmRlciBQb2ludFwiPlxuICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+IFJlb3JkZXIgUG9pbnQgPC90aD5cbiAgICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgZWxlbWVudFwiPlxuICAgICAgICAgICAge3sgZWxlbWVudD8ucmVvcmRlcl9wb2ludCB9fVxuICAgICAgICAgIDwvdGQ+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgIDwhLS0gQ2F0ZWdvcmllcyBDb2x1bW4gLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiQ2F0ZWdvcmllc1wiPlxuICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+IENhdGVnb3JpZXMgPC90aD5cbiAgICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgZWxlbWVudFwiPlxuICAgICAgICAgICAgPGFwcC1wcm9kdWN0LWNhdGVnb3J5LWJhZGdlcyBbcHJvZHVjdF09XCJlbGVtZW50XCI+PC9hcHAtcHJvZHVjdC1jYXRlZ29yeS1iYWRnZXM+XG4gICAgICAgICAgPC90ZD5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPCEtLSBTdG9jayBDb2x1bW4gLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiU3RvY2tcIj5cbiAgICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmIG1hdC1zb3J0LWhlYWRlcj1cInN0b2NrXCI+IFN0b2NrIDwvdGg+XG4gICAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IGVsZW1lbnRcIj5cbiAgICAgICAgICAgIHt7IGVsZW1lbnQ/LnN0b2NrIH19XG4gICAgICAgICAgPC90ZD5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPCEtLSBMYXN0IFB1cmNoYXNlIENvbHVtbiAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJMYXN0IFB1cmNoYXNlXCI+XG4gICAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZj5cbiAgICAgICAgICAgIExhc3QgUHVyY2hhc2VcbiAgICAgICAgICA8L3RoPlxuICAgICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCBlbGVtZW50XCI+XG4gICAgICAgICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdJZj1cImVsZW1lbnQ/Lmxhc3Rfc3RvY2tfcmVjZWlwdFwiPlxuICAgICAgICAgICAgICB7eyBlbGVtZW50Py5sYXN0X3N0b2NrX3JlY2VpcHQ/LmRhdGUgfCBkYXRlIH19IC1cbiAgICAgICAgICAgICAge3sgZWxlbWVudD8ubGFzdF9zdG9ja19yZWNlaXB0Py5xdWFudGl0eSB9fSB7eyBlbGVtZW50Py5tZWFzdXJlPy50aXRsZSB9fVxuICAgICAgICAgICAgPC9wPlxuICAgICAgICAgICAgPHNtYWxsIGNsYXNzPVwidGV4dC1zZWNvbmRhcnlcIiAqbmdJZj1cImVsZW1lbnQ/Lmxhc3Rfc3RvY2tfcmVjZWlwdFwiPlxuICAgICAgICAgICAgICB7eyBlbGVtZW50Py5sYXN0X3N0b2NrX3JlY2VpcHQ/LnB1cmNoYXNlX3ByaWNlID8/IDAgfCBjdXJyZW5jeSB9fSBwZXIge3sgZWxlbWVudD8ubWVhc3VyZT8udGl0bGUgfX1cbiAgICAgICAgICAgIDwvc21hbGw+XG4gICAgICAgICAgPC90ZD5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPCEtLSAzMGQgSXNzdWVzIC0tPlxuICAgICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cIjMwZCBJc3N1ZXNcIj5cbiAgICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmPiAzMGQgSXNzdWVzIDwvdGg+XG4gICAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IGVsZW1lbnRcIj57eyBlbGVtZW50Py5pc3N1ZXNfMzBkIH19PC90ZD5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPCEtLSAzMGQgUmVjZWlwdHMgLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiMzBkIFJlY2VpcHRzXCI+XG4gICAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZj4gMzBkIFJlY2VpcHRzIDwvdGg+XG4gICAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IGVsZW1lbnRcIj57eyBlbGVtZW50Py5yZWNlaXB0c18zMGQgfX08L3RkPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8IS0tIDYwZCBJc3N1ZXMgLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiNjBkIElzc3Vlc1wiPlxuICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+IDYwZCBJc3N1ZXMgPC90aD5cbiAgICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgZWxlbWVudFwiPnt7IGVsZW1lbnQ/Lmlzc3Vlc182MGQgfX08L3RkPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8IS0tIDYwZCBSZWNlaXB0cyAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCI2MGQgUmVjZWlwdHNcIj5cbiAgICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmPiA2MGQgUmVjZWlwdHMgPC90aD5cbiAgICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgZWxlbWVudFwiPnt7IGVsZW1lbnQ/LnJlY2VpcHRzXzYwZCB9fTwvdGQ+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgIDwhLS0gOTBkIElzc3VlcyAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCI5MGQgSXNzdWVzXCI+XG4gICAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZj4gOTBkIElzc3VlcyA8L3RoPlxuICAgICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCBlbGVtZW50XCI+e3sgZWxlbWVudD8uaXNzdWVzXzkwZCB9fTwvdGQ+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgIDwhLS0gOTBkIFJlY2VpcHRzIC0tPlxuICAgICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cIjkwZCBSZWNlaXB0c1wiPlxuICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+IDkwZCBSZWNlaXB0cyA8L3RoPlxuICAgICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCBlbGVtZW50XCI+e3sgZWxlbWVudD8ucmVjZWlwdHNfOTBkIH19PC90ZD5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPCEtLSAxeSBJc3N1ZXMgLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiMXkgSXNzdWVzXCI+XG4gICAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZj4gMXkgSXNzdWVzIDwvdGg+XG4gICAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IGVsZW1lbnRcIj57eyBlbGVtZW50Py5pc3N1ZXNfMXkgfX08L3RkPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8IS0tIDYwZCBSZWNlaXB0cyAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCIxeSBSZWNlaXB0c1wiPlxuICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+IDF5IFJlY2VpcHRzIDwvdGg+XG4gICAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IGVsZW1lbnRcIj57eyBlbGVtZW50Py5yZWNlaXB0c18xeSB9fTwvdGQ+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgIDx0ciBtYXQtaGVhZGVyLXJvdyAqbWF0SGVhZGVyUm93RGVmPVwiZGlzcGxheWVkQ29sdW1uc1wiPjwvdHI+XG4gICAgICAgIDx0ciBtYXQtcm93ICptYXRSb3dEZWY9XCJsZXQgcm93OyBjb2x1bW5zOiBkaXNwbGF5ZWRDb2x1bW5zO1wiPjwvdHI+XG4gICAgICA8L3RhYmxlPlxuXG4gICAgICA8bWF0LXByb2dyZXNzLWJhciBtb2RlPVwiaW5kZXRlcm1pbmF0ZVwiICpuZ0lmPVwiaXNXb3JraW5nXCI+PC9tYXQtcHJvZ3Jlc3MtYmFyPlxuICAgIDwvbWF0LWNhcmQtY29udGVudD5cbiAgPC9tYXQtY2FyZD5cbjwvZGl2PlxuIl19
@@ -0,0 +1,64 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component, EventEmitter, Input, Output } from '@angular/core';
3
+ import { MaterialModule } from '../../material.module';
4
+ import { ActionPopupComponent } from 'ngx-techlify-core';
5
+ import { lastValueFrom } from 'rxjs';
6
+ import { NgxPermissionsModule } from 'ngx-permissions';
7
+ import * as i0 from "@angular/core";
8
+ import * as i1 from "@angular/material/dialog";
9
+ import * as i2 from "ngx-techlify-core";
10
+ import * as i3 from "../supplier.service";
11
+ import * as i4 from "@angular/material/icon";
12
+ import * as i5 from "ngx-permissions";
13
+ export class SupplierDeleteButtonComponent {
14
+ dialog;
15
+ alertService;
16
+ errorHandler;
17
+ supplierService;
18
+ supplier;
19
+ onDelete = new EventEmitter();
20
+ constructor(dialog, alertService, errorHandler, supplierService) {
21
+ this.dialog = dialog;
22
+ this.alertService = alertService;
23
+ this.errorHandler = errorHandler;
24
+ this.supplierService = supplierService;
25
+ }
26
+ ngOnInit() {
27
+ }
28
+ openDialog() {
29
+ this.dialog.open(ActionPopupComponent, {
30
+ width: '400px',
31
+ data: {
32
+ title: 'Delete Supplier',
33
+ message: 'Are you sure you want to delete the Supplier?',
34
+ },
35
+ autoFocus: false,
36
+ }).afterClosed().subscribe(async (result) => {
37
+ if (result) {
38
+ try {
39
+ await lastValueFrom(this.supplierService.destroy(this.supplier.id));
40
+ this.alertService.addAlert('Successfully deleted the Supplier', 'success');
41
+ this.onDelete.emit(this.supplier);
42
+ }
43
+ catch (error) {
44
+ this.errorHandler.handleError(error);
45
+ }
46
+ }
47
+ });
48
+ }
49
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SupplierDeleteButtonComponent, deps: [{ token: i1.MatDialog }, { token: i2.AlertService }, { token: i2.ErrorHandlerService }, { token: i3.SupplierService }], target: i0.ɵɵFactoryTarget.Component });
50
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SupplierDeleteButtonComponent, isStandalone: true, selector: "app-supplier-delete-button", inputs: { supplier: "supplier" }, outputs: { onDelete: "onDelete" }, ngImport: i0, template: "<mat-icon class=\"cursor-pointer\" *ngxPermissionsOnly=\"['supplier.delete']\" (click)=\"openDialog()\">\n delete\n</mat-icon>", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MaterialModule }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: NgxPermissionsModule }, { kind: "directive", type: i5.NgxPermissionsDirective, selector: "[ngxPermissionsOnly],[ngxPermissionsExcept]", inputs: ["ngxPermissionsOnly", "ngxPermissionsOnlyThen", "ngxPermissionsOnlyElse", "ngxPermissionsExcept", "ngxPermissionsExceptElse", "ngxPermissionsExceptThen", "ngxPermissionsThen", "ngxPermissionsElse", "ngxPermissionsOnlyAuthorisedStrategy", "ngxPermissionsOnlyUnauthorisedStrategy", "ngxPermissionsExceptUnauthorisedStrategy", "ngxPermissionsExceptAuthorisedStrategy", "ngxPermissionsUnauthorisedStrategy", "ngxPermissionsAuthorisedStrategy"], outputs: ["permissionsAuthorized", "permissionsUnauthorized"] }], preserveWhitespaces: true });
51
+ }
52
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SupplierDeleteButtonComponent, decorators: [{
53
+ type: Component,
54
+ args: [{ selector: 'app-supplier-delete-button', standalone: true, imports: [
55
+ CommonModule,
56
+ MaterialModule,
57
+ NgxPermissionsModule
58
+ ], template: "<mat-icon class=\"cursor-pointer\" *ngxPermissionsOnly=\"['supplier.delete']\" (click)=\"openDialog()\">\n delete\n</mat-icon>" }]
59
+ }], ctorParameters: () => [{ type: i1.MatDialog }, { type: i2.AlertService }, { type: i2.ErrorHandlerService }, { type: i3.SupplierService }], propDecorators: { supplier: [{
60
+ type: Input
61
+ }], onDelete: [{
62
+ type: Output
63
+ }] } });
64
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VwcGxpZXItZGVsZXRlLWJ1dHRvbi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9pbnZlbnRvcnktY29tbW9uL3NyYy9saWIvaW52ZW50b3J5LWNvbW1vbi9zdXBwbGllci9zdXBwbGllci1kZWxldGUtYnV0dG9uL3N1cHBsaWVyLWRlbGV0ZS1idXR0b24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvaW52ZW50b3J5LWNvbW1vbi9zcmMvbGliL2ludmVudG9yeS1jb21tb24vc3VwcGxpZXIvc3VwcGxpZXItZGVsZXRlLWJ1dHRvbi9zdXBwbGllci1kZWxldGUtYnV0dG9uLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQVUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQy9FLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN2RCxPQUFPLEVBQWUsb0JBQW9CLEVBQXFDLE1BQU0sbUJBQW1CLENBQUM7QUFFekcsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUVyQyxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQzs7Ozs7OztBQWF2RCxNQUFNLE9BQU8sNkJBQTZCO0lBS3BCO0lBQ1Y7SUFDQTtJQUNBO0lBTkQsUUFBUSxDQUFLO0lBQ1osUUFBUSxHQUFzQixJQUFJLFlBQVksRUFBTyxDQUFBO0lBRS9ELFlBQW9CLE1BQWlCLEVBQzNCLFlBQTBCLEVBQzFCLFlBQWlDLEVBQ2pDLGVBQWdDO1FBSHRCLFdBQU0sR0FBTixNQUFNLENBQVc7UUFDM0IsaUJBQVksR0FBWixZQUFZLENBQWM7UUFDMUIsaUJBQVksR0FBWixZQUFZLENBQXFCO1FBQ2pDLG9CQUFlLEdBQWYsZUFBZSxDQUFpQjtJQUN0QyxDQUFDO0lBRUwsUUFBUTtJQUNSLENBQUM7SUFFRCxVQUFVO1FBQ1IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEVBQUU7WUFDckMsS0FBSyxFQUFFLE9BQU87WUFDZCxJQUFJLEVBQWU7Z0JBQ2pCLEtBQUssRUFBRSxpQkFBaUI7Z0JBQ3hCLE9BQU8sRUFBRSwrQ0FBK0M7YUFDekQ7WUFDRCxTQUFTLEVBQUUsS0FBSztTQUNqQixDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUMxQyxJQUFJLE1BQU0sRUFBRSxDQUFDO2dCQUNYLElBQUksQ0FBQztvQkFDSCxNQUFNLGFBQWEsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUE7b0JBQ25FLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLG1DQUFtQyxFQUFFLFNBQVMsQ0FBQyxDQUFDO29CQUMzRSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7Z0JBQ25DLENBQUM7Z0JBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztvQkFDZixJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDdkMsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7d0dBakNVLDZCQUE2Qjs0RkFBN0IsNkJBQTZCLDJKQ3BCMUMsaUlBRVcseUREYVAsWUFBWSw4QkFDWixjQUFjLG1MQUNkLG9CQUFvQjs7NEZBR1gsNkJBQTZCO2tCQVh6QyxTQUFTOytCQUNFLDRCQUE0QixjQUcxQixJQUFJLFdBQ1A7d0JBQ1AsWUFBWTt3QkFDWixjQUFjO3dCQUNkLG9CQUFvQjtxQkFDckI7eUtBSVEsUUFBUTtzQkFBaEIsS0FBSztnQkFDSSxRQUFRO3NCQUFqQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25Jbml0LCBPdXRwdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE1hdGVyaWFsTW9kdWxlIH0gZnJvbSAnLi4vLi4vbWF0ZXJpYWwubW9kdWxlJztcbmltcG9ydCB7IEFjdGlvblBvcHVwLCBBY3Rpb25Qb3B1cENvbXBvbmVudCwgQWxlcnRTZXJ2aWNlLCBFcnJvckhhbmRsZXJTZXJ2aWNlIH0gZnJvbSAnbmd4LXRlY2hsaWZ5LWNvcmUnO1xuaW1wb3J0IHsgTWF0RGlhbG9nIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcbmltcG9ydCB7IGxhc3RWYWx1ZUZyb20gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFN1cHBsaWVyU2VydmljZSB9IGZyb20gJy4uL3N1cHBsaWVyLnNlcnZpY2UnO1xuaW1wb3J0IHsgTmd4UGVybWlzc2lvbnNNb2R1bGUgfSBmcm9tICduZ3gtcGVybWlzc2lvbnMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhcHAtc3VwcGxpZXItZGVsZXRlLWJ1dHRvbicsXG4gIHRlbXBsYXRlVXJsOiAnLi9zdXBwbGllci1kZWxldGUtYnV0dG9uLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vc3VwcGxpZXItZGVsZXRlLWJ1dHRvbi5jb21wb25lbnQuY3NzJ10sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBDb21tb25Nb2R1bGUsXG4gICAgTWF0ZXJpYWxNb2R1bGUsXG4gICAgTmd4UGVybWlzc2lvbnNNb2R1bGVcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgU3VwcGxpZXJEZWxldGVCdXR0b25Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuXG4gIEBJbnB1dCgpIHN1cHBsaWVyOiBhbnlcbiAgQE91dHB1dCgpIG9uRGVsZXRlOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpXG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBkaWFsb2c6IE1hdERpYWxvZyxcbiAgICBwcml2YXRlIGFsZXJ0U2VydmljZTogQWxlcnRTZXJ2aWNlLFxuICAgIHByaXZhdGUgZXJyb3JIYW5kbGVyOiBFcnJvckhhbmRsZXJTZXJ2aWNlLFxuICAgIHByaXZhdGUgc3VwcGxpZXJTZXJ2aWNlOiBTdXBwbGllclNlcnZpY2VcbiAgKSB7IH1cblxuICBuZ09uSW5pdCgpIHtcbiAgfVxuXG4gIG9wZW5EaWFsb2coKSB7XG4gICAgdGhpcy5kaWFsb2cub3BlbihBY3Rpb25Qb3B1cENvbXBvbmVudCwge1xuICAgICAgd2lkdGg6ICc0MDBweCcsXG4gICAgICBkYXRhOiA8QWN0aW9uUG9wdXA+e1xuICAgICAgICB0aXRsZTogJ0RlbGV0ZSBTdXBwbGllcicsXG4gICAgICAgIG1lc3NhZ2U6ICdBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gZGVsZXRlIHRoZSBTdXBwbGllcj8nLFxuICAgICAgfSxcbiAgICAgIGF1dG9Gb2N1czogZmFsc2UsXG4gICAgfSkuYWZ0ZXJDbG9zZWQoKS5zdWJzY3JpYmUoYXN5bmMgKHJlc3VsdCkgPT4ge1xuICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGF3YWl0IGxhc3RWYWx1ZUZyb20odGhpcy5zdXBwbGllclNlcnZpY2UuZGVzdHJveSh0aGlzLnN1cHBsaWVyLmlkKSlcbiAgICAgICAgICB0aGlzLmFsZXJ0U2VydmljZS5hZGRBbGVydCgnU3VjY2Vzc2Z1bGx5IGRlbGV0ZWQgdGhlIFN1cHBsaWVyJywgJ3N1Y2Nlc3MnKTtcbiAgICAgICAgICB0aGlzLm9uRGVsZXRlLmVtaXQodGhpcy5zdXBwbGllcilcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICB0aGlzLmVycm9ySGFuZGxlci5oYW5kbGVFcnJvcihlcnJvcik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG59XG4iLCI8bWF0LWljb24gY2xhc3M9XCJjdXJzb3ItcG9pbnRlclwiICpuZ3hQZXJtaXNzaW9uc09ubHk9XCJbJ3N1cHBsaWVyLmRlbGV0ZSddXCIgKGNsaWNrKT1cIm9wZW5EaWFsb2coKVwiPlxuICBkZWxldGVcbjwvbWF0LWljb24+Il19