tango-app-ui-store-builder 1.2.4 → 1.2.5

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 (27) hide show
  1. package/esm2022/lib/components/custom-select/custom-select.component.mjs +14 -5
  2. package/esm2022/lib/components/manage-store-plano/manage-store-plano.component.mjs +15 -8
  3. package/esm2022/lib/components/manage-store-plano/zone-verification-feedback/zone-verification-feedback.component.mjs +7 -2
  4. package/esm2022/lib/components/onboard-store-plano/onboard-store-plano.component.mjs +173 -22
  5. package/esm2022/lib/components/plano-tools/cad-files/cad-files.component.mjs +88 -0
  6. package/esm2022/lib/components/plano-tools/move-bucket/move-bucket.component.mjs +239 -0
  7. package/esm2022/lib/components/plano-tools/plano-migrate/plano-migrate.component.mjs +3 -3
  8. package/esm2022/lib/components/plano-tools/swap-template/swap-template.component.mjs +325 -0
  9. package/esm2022/lib/components/plano-tools/tools-parent/tools-parent.component.mjs +3 -3
  10. package/esm2022/lib/components/popups/delete-confirmation/delete-confirmation.component.mjs +10 -3
  11. package/esm2022/lib/services/store-builder.service.mjs +15 -1
  12. package/esm2022/lib/tango-store-builder-routing.module.mjs +16 -1
  13. package/esm2022/lib/tango-store-builder.module.mjs +10 -1
  14. package/fesm2022/tango-app-ui-store-builder.mjs +873 -40
  15. package/fesm2022/tango-app-ui-store-builder.mjs.map +1 -1
  16. package/lib/components/custom-select/custom-select.component.d.ts +5 -2
  17. package/lib/components/manage-plano/rollout-table/rollout-table.component.d.ts +4 -4
  18. package/lib/components/manage-plano/verification-table/verification-table.component.d.ts +5 -5
  19. package/lib/components/manage-store-plano/manage-store-plano.component.d.ts +1 -0
  20. package/lib/components/onboard-store-plano/onboard-store-plano.component.d.ts +11 -1
  21. package/lib/components/plano-tools/cad-files/cad-files.component.d.ts +30 -0
  22. package/lib/components/plano-tools/move-bucket/move-bucket.component.d.ts +64 -0
  23. package/lib/components/plano-tools/swap-template/swap-template.component.d.ts +83 -0
  24. package/lib/components/popups/delete-confirmation/delete-confirmation.component.d.ts +3 -1
  25. package/lib/services/store-builder.service.d.ts +16 -0
  26. package/lib/tango-store-builder.module.d.ts +56 -53
  27. package/package.json +1 -1
@@ -0,0 +1,88 @@
1
+ import { Component } from '@angular/core';
2
+ import { Subject, finalize } from 'rxjs';
3
+ import * as FileSaver from 'file-saver';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "../../../services/store-builder.service";
6
+ import * as i2 from "@angular/forms";
7
+ import * as i3 from "@angular/common";
8
+ export class CadFilesComponent {
9
+ sbs;
10
+ storeName = '';
11
+ files = [];
12
+ hasSearched = false;
13
+ isLoading = false;
14
+ downloadingKey = null;
15
+ message = '';
16
+ messageType = 'success';
17
+ destroy$ = new Subject();
18
+ constructor(sbs) {
19
+ this.sbs = sbs;
20
+ }
21
+ onFetch() {
22
+ let storeName = (this.storeName || '').trim();
23
+ if (!storeName) {
24
+ this.showMessage('Please enter a store name.', 'error');
25
+ return;
26
+ }
27
+ this.isLoading = true;
28
+ this.hasSearched = true;
29
+ this.files = [];
30
+ this.message = '';
31
+ this.sbs
32
+ .getCadFiles(storeName)
33
+ .pipe(finalize(() => (this.isLoading = false)))
34
+ .subscribe({
35
+ next: (res) => {
36
+ this.files = res?.data?.files || [];
37
+ },
38
+ error: (err) => {
39
+ this.showMessage(err?.error?.error?.errMsg ||
40
+ err?.error?.error ||
41
+ err?.error?.message ||
42
+ 'Failed to fetch files.', 'error');
43
+ },
44
+ });
45
+ }
46
+ async onDownload(file) {
47
+ if (!file.url) {
48
+ this.showMessage('Download URL is not available for this file.', 'error');
49
+ return;
50
+ }
51
+ this.downloadingKey = file.key;
52
+ try {
53
+ const response = await fetch(file.url);
54
+ if (!response.ok) {
55
+ throw new Error(`HTTP ${response.status}`);
56
+ }
57
+ const blob = await response.blob();
58
+ FileSaver.saveAs(blob, file.name);
59
+ }
60
+ catch {
61
+ this.showMessage(`Failed to download ${file.name}.`, 'error');
62
+ }
63
+ finally {
64
+ this.downloadingKey = null;
65
+ }
66
+ }
67
+ formatSize(bytes) {
68
+ if (bytes == null || isNaN(bytes))
69
+ return '-';
70
+ return (bytes / (1024 * 1024)).toFixed(2) + ' MB';
71
+ }
72
+ showMessage(msg, type) {
73
+ this.message = msg;
74
+ this.messageType = type;
75
+ setTimeout(() => (this.message = ''), 5000);
76
+ }
77
+ ngOnDestroy() {
78
+ this.destroy$.next();
79
+ this.destroy$.complete();
80
+ }
81
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CadFilesComponent, deps: [{ token: i1.StoreBuilderService }], target: i0.ɵɵFactoryTarget.Component });
82
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: CadFilesComponent, selector: "lib-cad-files", ngImport: i0, template: "<section class=\"cad-files p-3\">\n <div class=\"card p-4\">\n <h5 class=\"mb-1\">CAD &amp; Kissflow Files</h5>\n <p class=\"text-muted small mb-3\">\n Enter a store name to list the uploaded CAD and Kissflow files (sorted).\n </p>\n\n <div class=\"d-flex gap-2 align-items-end mb-3 flex-wrap\">\n <div class=\"flex-grow-1\" style=\"min-width: 260px; max-width: 420px;\">\n <label class=\"form-label\">Store Name</label>\n <input\n type=\"text\"\n class=\"form-control\"\n placeholder=\"Enter store name\"\n [(ngModel)]=\"storeName\"\n (keyup.enter)=\"onFetch()\"\n [disabled]=\"isLoading\" />\n </div>\n\n <button\n class=\"btn btn-primary\"\n (click)=\"onFetch()\"\n [disabled]=\"isLoading || !storeName.trim()\">\n {{ isLoading ? 'Fetching...' : 'Fetch Files' }}\n </button>\n </div>\n\n @if (message) {\n <div\n class=\"alert\"\n [class.alert-success]=\"messageType === 'success'\"\n [class.alert-danger]=\"messageType === 'error'\">\n {{ message }}\n </div>\n }\n\n @if (isLoading) {\n <div class=\"text-muted\">Loading files...</div>\n } @else if (hasSearched && files.length === 0) {\n <div class=\"text-muted\">No files found for this store.</div>\n } @else if (files.length > 0) {\n <div class=\"table-responsive\">\n <table class=\"table table-sm align-middle\">\n <thead>\n <tr>\n <th>Name</th>\n <th>Key</th>\n <th>Uploaded At</th>\n <th>Size</th>\n <th class=\"text-end\">Action</th>\n </tr>\n </thead>\n <tbody>\n @for (file of files; track file.key) {\n <tr>\n <td>{{ file.name }}</td>\n <td class=\"text-muted small text-break\">{{ file.key }}</td>\n <td>{{ file.uploadedAt | date: 'medium' }}</td>\n <td>{{ formatSize(file.size) }}</td>\n <td class=\"text-end\">\n <button\n class=\"btn btn-sm btn-outline-primary\"\n (click)=\"onDownload(file)\"\n [disabled]=\"downloadingKey === file.key\">\n {{ downloadingKey === file.key ? 'Downloading...' : 'Download' }}\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n</section>\n", styles: [".cad-files .card{border:1px solid #e0e0e0}.cad-files .table th{font-size:.85rem;color:#475467;font-weight:600}.cad-files .table td{vertical-align:middle}.cad-files .table .text-break{word-break:break-all}\n"], dependencies: [{ kind: "directive", type: i2.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: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: i3.DatePipe, name: "date" }] });
83
+ }
84
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CadFilesComponent, decorators: [{
85
+ type: Component,
86
+ args: [{ selector: 'lib-cad-files', template: "<section class=\"cad-files p-3\">\n <div class=\"card p-4\">\n <h5 class=\"mb-1\">CAD &amp; Kissflow Files</h5>\n <p class=\"text-muted small mb-3\">\n Enter a store name to list the uploaded CAD and Kissflow files (sorted).\n </p>\n\n <div class=\"d-flex gap-2 align-items-end mb-3 flex-wrap\">\n <div class=\"flex-grow-1\" style=\"min-width: 260px; max-width: 420px;\">\n <label class=\"form-label\">Store Name</label>\n <input\n type=\"text\"\n class=\"form-control\"\n placeholder=\"Enter store name\"\n [(ngModel)]=\"storeName\"\n (keyup.enter)=\"onFetch()\"\n [disabled]=\"isLoading\" />\n </div>\n\n <button\n class=\"btn btn-primary\"\n (click)=\"onFetch()\"\n [disabled]=\"isLoading || !storeName.trim()\">\n {{ isLoading ? 'Fetching...' : 'Fetch Files' }}\n </button>\n </div>\n\n @if (message) {\n <div\n class=\"alert\"\n [class.alert-success]=\"messageType === 'success'\"\n [class.alert-danger]=\"messageType === 'error'\">\n {{ message }}\n </div>\n }\n\n @if (isLoading) {\n <div class=\"text-muted\">Loading files...</div>\n } @else if (hasSearched && files.length === 0) {\n <div class=\"text-muted\">No files found for this store.</div>\n } @else if (files.length > 0) {\n <div class=\"table-responsive\">\n <table class=\"table table-sm align-middle\">\n <thead>\n <tr>\n <th>Name</th>\n <th>Key</th>\n <th>Uploaded At</th>\n <th>Size</th>\n <th class=\"text-end\">Action</th>\n </tr>\n </thead>\n <tbody>\n @for (file of files; track file.key) {\n <tr>\n <td>{{ file.name }}</td>\n <td class=\"text-muted small text-break\">{{ file.key }}</td>\n <td>{{ file.uploadedAt | date: 'medium' }}</td>\n <td>{{ formatSize(file.size) }}</td>\n <td class=\"text-end\">\n <button\n class=\"btn btn-sm btn-outline-primary\"\n (click)=\"onDownload(file)\"\n [disabled]=\"downloadingKey === file.key\">\n {{ downloadingKey === file.key ? 'Downloading...' : 'Download' }}\n </button>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n</section>\n", styles: [".cad-files .card{border:1px solid #e0e0e0}.cad-files .table th{font-size:.85rem;color:#475467;font-weight:600}.cad-files .table td{vertical-align:middle}.cad-files .table .text-break{word-break:break-all}\n"] }]
87
+ }], ctorParameters: () => [{ type: i1.StoreBuilderService }] });
88
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FkLWZpbGVzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RhbmdvLXN0b3JlLWJ1aWxkZXIvc3JjL2xpYi9jb21wb25lbnRzL3BsYW5vLXRvb2xzL2NhZC1maWxlcy9jYWQtZmlsZXMuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFuZ28tc3RvcmUtYnVpbGRlci9zcmMvbGliL2NvbXBvbmVudHMvcGxhbm8tdG9vbHMvY2FkLWZpbGVzL2NhZC1maWxlcy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFhLE1BQU0sZUFBZSxDQUFDO0FBQ3JELE9BQU8sRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxTQUFTLE1BQU0sWUFBWSxDQUFDOzs7OztBQWdCeEMsTUFBTSxPQUFPLGlCQUFpQjtJQWNSO0lBYnBCLFNBQVMsR0FBVyxFQUFFLENBQUM7SUFFdkIsS0FBSyxHQUFjLEVBQUUsQ0FBQztJQUN0QixXQUFXLEdBQVksS0FBSyxDQUFDO0lBRTdCLFNBQVMsR0FBWSxLQUFLLENBQUM7SUFDM0IsY0FBYyxHQUFrQixJQUFJLENBQUM7SUFFckMsT0FBTyxHQUFXLEVBQUUsQ0FBQztJQUNyQixXQUFXLEdBQXdCLFNBQVMsQ0FBQztJQUU1QixRQUFRLEdBQUcsSUFBSSxPQUFPLEVBQVEsQ0FBQztJQUVoRCxZQUFvQixHQUF3QjtRQUF4QixRQUFHLEdBQUgsR0FBRyxDQUFxQjtJQUFHLENBQUM7SUFFaEQsT0FBTztRQUNMLElBQUksU0FBUyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUM5QyxJQUFJLENBQUMsU0FBUyxFQUFFO1lBQ2QsSUFBSSxDQUFDLFdBQVcsQ0FB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RlUsaUJBQWlCOzRGQUFqQixpQkFBaUIscURDbEI5Qix3Z0ZBMkVBOzs0RkR6RGEsaUJBQWlCO2tCQUw3QixTQUFTOytCQUNFLGVBQWUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uRGVzdHJveSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCwgZmluYWxpemUgfSBmcm9tICdyeGpzJztcbmltcG9ydCAqIGFzIEZpbGVTYXZlciBmcm9tICdmaWxlLXNhdmVyJztcbmltcG9ydCB7IFN0b3JlQnVpbGRlclNlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi9zZXJ2aWNlcy9zdG9yZS1idWlsZGVyLnNlcnZpY2UnO1xuXG5pbnRlcmZhY2UgQ2FkRmlsZSB7XG4gIG5hbWU6IHN0cmluZztcbiAga2V5OiBzdHJpbmc7XG4gIHVwbG9hZGVkQXQ6IHN0cmluZztcbiAgc2l6ZTogbnVtYmVyO1xuICB1cmw6IHN0cmluZztcbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbGliLWNhZC1maWxlcycsXG4gIHRlbXBsYXRlVXJsOiAnLi9jYWQtZmlsZXMuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vY2FkLWZpbGVzLmNvbXBvbmVudC5zY3NzJyxcbn0pXG5leHBvcnQgY2xhc3MgQ2FkRmlsZXNDb21wb25lbnQgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICBzdG9yZU5hbWU6IHN0cmluZyA9ICcnO1xuXG4gIGZpbGVzOiBDYWRGaWxlW10gPSBbXTtcbiAgaGFzU2VhcmNoZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBpc0xvYWRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcbiAgZG93bmxvYWRpbmdLZXk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIG1lc3NhZ2U6IHN0cmluZyA9ICcnO1xuICBtZXNzYWdlVHlwZTogJ3N1Y2Nlc3MnIHwgJ2Vycm9yJyA9ICdzdWNjZXNzJztcblxuICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3kkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHNiczogU3RvcmVCdWlsZGVyU2VydmljZSkge31cblxuICBvbkZldGNoKCkge1xuICAgIGxldCBzdG9yZU5hbWUgPSAodGhpcy5zdG9yZU5hbWUgfHwgJycpLnRyaW0oKTtcbiAgICBpZiAoIXN0b3JlTmFtZSkge1xuICAgICAgdGhpcy5zaG93TWVzc2FnZSgnUGxlYXNlIGVudGVyIGEgc3RvcmUgbmFtZS4nLCAnZXJyb3InKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmlzTG9hZGluZyA9IHRydWU7XG4gICAgdGhpcy5oYXNTZWFyY2hlZCA9IHRydWU7XG4gICAgdGhpcy5maWxlcyA9IFtdO1xuICAgIHRoaXMubWVzc2FnZSA9ICcnO1xuXG4gICAgdGhpcy5zYnNcbiAgICAgIC5nZXRDYWRGaWxlcyhzdG9yZU5hbWUpXG4gICAgICAucGlwZShmaW5hbGl6ZSgoKSA9PiAodGhpcy5pc0xvYWRpbmcgPSBmYWxzZSkpKVxuICAgICAgLnN1YnNjcmliZSh7XG4gICAgICAgIG5leHQ6IChyZXM6IGFueSkgPT4ge1xuICAgICAgICAgIHRoaXMuZmlsZXMgPSByZXM/LmRhdGE/LmZpbGVzIHx8IFtdO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogKGVycjogYW55KSA9PiB7XG4gICAgICAgICAgdGhpcy5zaG93TWVzc2FnZShcbiAgICAgICAgICAgIGVycj8uZXJyb3I/LmVycm9yPy5lcnJNc2cgfHxcbiAgICAgICAgICAgICAgZXJyPy5lcnJvcj8uZXJyb3IgfHxcbiAgICAgICAgICAgICAgZXJyPy5lcnJvcj8ubWVzc2FnZSB8fFxuICAgICAgICAgICAgICAnRmFpbGVkIHRvIGZldGNoIGZpbGVzLicsXG4gICAgICAgICAgICAnZXJyb3InLFxuICAgICAgICAgICk7XG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIG9uRG93bmxvYWQoZmlsZTogQ2FkRmlsZSkge1xuICAgIGlmICghZmlsZS51cmwpIHtcbiAgICAgIHRoaXMuc2hvd01lc3NhZ2UoJ0Rvd25sb2FkIFVSTCBpcyBub3QgYXZhaWxhYmxlIGZvciB0aGlzIGZpbGUuJywgJ2Vycm9yJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5kb3dubG9hZGluZ0tleSA9IGZpbGUua2V5O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGZpbGUudXJsKTtcbiAgICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBIVFRQICR7cmVzcG9uc2Uuc3RhdHVzfWApO1xuICAgICAgfVxuICAgICAgY29uc3QgYmxvYiA9IGF3YWl0IHJlc3BvbnNlLmJsb2IoKTtcbiAgICAgIEZpbGVTYXZlci5zYXZlQXMoYmxvYiwgZmlsZS5uYW1lKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHRoaXMuc2hvd01lc3NhZ2UoYEZhaWxlZCB0byBkb3dubG9hZCAke2ZpbGUubmFtZX0uYCwgJ2Vycm9yJyk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuZG93bmxvYWRpbmdLZXkgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIGZvcm1hdFNpemUoYnl0ZXM6IG51bWJlcik6IHN0cmluZyB7XG4gICAgaWYgKGJ5dGVzID09IG51bGwgfHwgaXNOYU4oYnl0ZXMpKSByZXR1cm4gJy0nO1xuICAgIHJldHVybiAoYnl0ZXMgLyAoMTAyNCAqIDEwMjQpKS50b0ZpeGVkKDIpICsgJyBNQic7XG4gIH1cblxuICBzaG93TWVzc2FnZShtc2c6IHN0cmluZywgdHlwZTogJ3N1Y2Nlc3MnIHwgJ2Vycm9yJykge1xuICAgIHRoaXMubWVzc2FnZSA9IG1zZztcbiAgICB0aGlzLm1lc3NhZ2VUeXBlID0gdHlwZTtcbiAgICBzZXRUaW1lb3V0KCgpID0+ICh0aGlzLm1lc3NhZ2UgPSAnJyksIDUwMDApO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5kZXN0cm95JC5uZXh0KCk7XG4gICAgdGhpcy5kZXN0cm95JC5jb21wbGV0ZSgpO1xuICB9XG59XG4iLCI8c2VjdGlvbiBjbGFzcz1cImNhZC1maWxlcyBwLTNcIj5cbiAgPGRpdiBjbGFzcz1cImNhcmQgcC00XCI+XG4gICAgPGg1IGNsYXNzPVwibWItMVwiPkNBRCAmYW1wOyBLaXNzZmxvdyBGaWxlczwvaDU+XG4gICAgPHAgY2xhc3M9XCJ0ZXh0LW11dGVkIHNtYWxsIG1iLTNcIj5cbiAgICAgIEVudGVyIGEgc3RvcmUgbmFtZSB0byBsaXN0IHRoZSB1cGxvYWRlZCBDQUQgYW5kIEtpc3NmbG93IGZpbGVzIChzb3J0ZWQpLlxuICAgIDwvcD5cblxuICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggZ2FwLTIgYWxpZ24taXRlbXMtZW5kIG1iLTMgZmxleC13cmFwXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZmxleC1ncm93LTFcIiBzdHlsZT1cIm1pbi13aWR0aDogMjYwcHg7IG1heC13aWR0aDogNDIwcHg7XCI+XG4gICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tbGFiZWxcIj5TdG9yZSBOYW1lPC9sYWJlbD5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgICAgICBwbGFjZWhvbGRlcj1cIkVudGVyIHN0b3JlIG5hbWVcIlxuICAgICAgICAgIFsobmdNb2RlbCldPVwic3RvcmVOYW1lXCJcbiAgICAgICAgICAoa2V5dXAuZW50ZXIpPVwib25GZXRjaCgpXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwiaXNMb2FkaW5nXCIgLz5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8YnV0dG9uXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5XCJcbiAgICAgICAgKGNsaWNrKT1cIm9uRmV0Y2goKVwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJpc0xvYWRpbmcgfHwgIXN0b3JlTmFtZS50cmltKClcIj5cbiAgICAgICAge3sgaXNMb2FkaW5nID8gJ0ZldGNoaW5nLi4uJyA6ICdGZXRjaCBGaWxlcycgfX1cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuXG4gICAgQGlmIChtZXNzYWdlKSB7XG4gICAgICA8ZGl2XG4gICAgICAgIGNsYXNzPVwiYWxlcnRcIlxuICAgICAgICBbY2xhc3MuYWxlcnQtc3VjY2Vzc109XCJtZXNzYWdlVHlwZSA9PT0gJ3N1Y2Nlc3MnXCJcbiAgICAgICAgW2NsYXNzLmFsZXJ0LWRhbmdlcl09XCJtZXNzYWdlVHlwZSA9PT0gJ2Vycm9yJ1wiPlxuICAgICAgICB7eyBtZXNzYWdlIH19XG4gICAgICA8L2Rpdj5cbiAgICB9XG5cbiAgICBAaWYgKGlzTG9hZGluZykge1xuICAgICAgPGRpdiBjbGFzcz1cInRleHQtbXV0ZWRcIj5Mb2FkaW5nIGZpbGVzLi4uPC9kaXY+XG4gICAgfSBAZWxzZSBpZiAoaGFzU2VhcmNoZWQgJiYgZmlsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICA8ZGl2IGNsYXNzPVwidGV4dC1tdXRlZFwiPk5vIGZpbGVzIGZvdW5kIGZvciB0aGlzIHN0b3JlLjwvZGl2PlxuICAgIH0gQGVsc2UgaWYgKGZpbGVzLmxlbmd0aCA+IDApIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJ0YWJsZS1yZXNwb25zaXZlXCI+XG4gICAgICAgIDx0YWJsZSBjbGFzcz1cInRhYmxlIHRhYmxlLXNtIGFsaWduLW1pZGRsZVwiPlxuICAgICAgICAgIDx0aGVhZD5cbiAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgPHRoPk5hbWU8L3RoPlxuICAgICAgICAgICAgICA8dGg+S2V5PC90aD5cbiAgICAgICAgICAgICAgPHRoPlVwbG9hZGVkIEF0PC90aD5cbiAgICAgICAgICAgICAgPHRoPlNpemU8L3RoPlxuICAgICAgICAgICAgICA8dGggY2xhc3M9XCJ0ZXh0LWVuZFwiPkFjdGlvbjwvdGg+XG4gICAgICAgICAgICA8L3RyPlxuICAgICAgICAgIDwvdGhlYWQ+XG4gICAgICAgICAgPHRib2R5PlxuICAgICAgICAgICAgQGZvciAoZmlsZSBvZiBmaWxlczsgdHJhY2sgZmlsZS5rZXkpIHtcbiAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgIDx0ZD57eyBmaWxlLm5hbWUgfX08L3RkPlxuICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInRleHQtbXV0ZWQgc21hbGwgdGV4dC1icmVha1wiPnt7IGZpbGUua2V5IH19PC90ZD5cbiAgICAgICAgICAgICAgICA8dGQ+e3sgZmlsZS51cGxvYWRlZEF0IHwgZGF0ZTogJ21lZGl1bScgfX08L3RkPlxuICAgICAgICAgICAgICAgIDx0ZD57eyBmb3JtYXRTaXplKGZpbGUuc2l6ZSkgfX08L3RkPlxuICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInRleHQtZW5kXCI+XG4gICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1zbSBidG4tb3V0bGluZS1wcmltYXJ5XCJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uRG93bmxvYWQoZmlsZSlcIlxuICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiZG93bmxvYWRpbmdLZXkgPT09IGZpbGUua2V5XCI+XG4gICAgICAgICAgICAgICAgICAgIHt7IGRvd25sb2FkaW5nS2V5ID09PSBmaWxlLmtleSA/ICdEb3dubG9hZGluZy4uLicgOiAnRG93bmxvYWQnIH19XG4gICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgfVxuICAgICAgICAgIDwvdGJvZHk+XG4gICAgICAgIDwvdGFibGU+XG4gICAgICA8L2Rpdj5cbiAgICB9XG4gIDwvZGl2PlxuPC9zZWN0aW9uPlxuIl19
@@ -0,0 +1,239 @@
1
+ import { Component } from "@angular/core";
2
+ import { debounceTime, distinctUntilChanged, filter, Subject, takeUntil, } from "rxjs";
3
+ import { DeleteConfirmationComponent } from "../../popups/delete-confirmation/delete-confirmation.component";
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "../../../services/store-builder.service";
6
+ import * as i2 from "tango-app-ui-global";
7
+ import * as i3 from "@ng-bootstrap/ng-bootstrap";
8
+ import * as i4 from "../../reactive-select/reactive-select.component";
9
+ import * as i5 from "@angular/common";
10
+ import * as i6 from "@angular/forms";
11
+ const STATUS_OPTIONS = [
12
+ { value: "draft", label: "Draft", bucket: "Onboarding" },
13
+ {
14
+ value: "allocationPending",
15
+ label: "Allocation Pending",
16
+ bucket: "Onboarding",
17
+ },
18
+ { value: "completed", label: "Completed", bucket: "ManagePlano" },
19
+ ];
20
+ export class MoveBucketComponent {
21
+ sbs;
22
+ gs;
23
+ modalService;
24
+ clientId;
25
+ storeOptions = [];
26
+ selectedStoreId = null;
27
+ selectedStoreLabel = null;
28
+ floors = [];
29
+ selectedFloorId = null;
30
+ isLoadingFloors = false;
31
+ statusOptions = STATUS_OPTIONS;
32
+ targetStatus = null;
33
+ currentStatus = null;
34
+ clearLayoutTasks = false;
35
+ clearFixtureTasks = false;
36
+ clearZoneTasks = false;
37
+ isSubmitting = false;
38
+ message = "";
39
+ messageType = "success";
40
+ destroy$ = new Subject();
41
+ constructor(sbs, gs, modalService) {
42
+ this.sbs = sbs;
43
+ this.gs = gs;
44
+ this.modalService = modalService;
45
+ }
46
+ ngOnInit() {
47
+ this.gs.dataRangeValue
48
+ .pipe(takeUntil(this.destroy$), debounceTime(200), filter((data) => !!data), distinctUntilChanged())
49
+ .subscribe((data) => {
50
+ if (data?.client) {
51
+ this.clientId = data.client;
52
+ }
53
+ else {
54
+ const headerData = JSON.parse(localStorage.getItem("header-filters"));
55
+ this.clientId = headerData?.client;
56
+ }
57
+ this.loadStores();
58
+ });
59
+ }
60
+ loadStores() {
61
+ this.sbs
62
+ .getStoreOrClusterList({ searchMode: "store" })
63
+ .subscribe((res) => {
64
+ this.storeOptions = res?.data || [];
65
+ });
66
+ }
67
+ onStoreSelected(storeId) {
68
+ this.selectedStoreId = storeId;
69
+ const store = this.storeOptions.find((s) => s.id === storeId);
70
+ this.selectedStoreLabel = store?.label ?? null;
71
+ this.resetFloorState();
72
+ if (this.selectedStoreLabel) {
73
+ this.loadFloors();
74
+ }
75
+ }
76
+ resetFloorState() {
77
+ this.floors = [];
78
+ this.selectedFloorId = null;
79
+ this.currentStatus = null;
80
+ this.targetStatus = null;
81
+ this.clearLayoutTasks = false;
82
+ this.clearFixtureTasks = false;
83
+ this.clearZoneTasks = false;
84
+ }
85
+ loadFloors() {
86
+ if (!this.selectedStoreLabel)
87
+ return;
88
+ this.isLoadingFloors = true;
89
+ this.sbs
90
+ .getFloorsWithStatus(this.selectedStoreLabel, this.clientId)
91
+ .subscribe({
92
+ next: (res) => {
93
+ const raw = res?.data?.floors || [];
94
+ this.floors = raw
95
+ .map((f) => ({
96
+ _id: f._id,
97
+ floorNumber: f.floorNumber,
98
+ floorName: f.floorName,
99
+ status: f.status,
100
+ isPlanoApproved: f.isPlanoApproved,
101
+ displayName: `Floor ${f.floorNumber} — ${f.floorName} [${this.getStatusLabel(f.status)}]`,
102
+ }))
103
+ .sort((a, b) => a.floorNumber - b.floorNumber);
104
+ if (this.floors.length === 1) {
105
+ this.onFloorSelected(this.floors[0]._id);
106
+ }
107
+ this.isLoadingFloors = false;
108
+ },
109
+ error: (err) => {
110
+ this.showMessage(err?.error?.message || "Failed to load floors.", "error");
111
+ this.isLoadingFloors = false;
112
+ },
113
+ });
114
+ }
115
+ onFloorSelected(floorId) {
116
+ this.selectedFloorId = floorId;
117
+ const floor = this.floors.find((f) => f._id === floorId);
118
+ if (floor) {
119
+ this.currentStatus = floor.status;
120
+ this.targetStatus = floor.status;
121
+ }
122
+ else {
123
+ this.currentStatus = null;
124
+ this.targetStatus = null;
125
+ }
126
+ }
127
+ onTargetStatusSelected(value) {
128
+ this.targetStatus = value;
129
+ }
130
+ get statusChanged() {
131
+ return !!this.targetStatus && this.targetStatus !== this.currentStatus;
132
+ }
133
+ get canSubmit() {
134
+ if (this.isSubmitting)
135
+ return false;
136
+ if (!this.selectedFloorId || !this.targetStatus)
137
+ return false;
138
+ const anyClear = this.clearLayoutTasks || this.clearFixtureTasks || this.clearZoneTasks;
139
+ return this.statusChanged || anyClear;
140
+ }
141
+ getStatusLabel(status) {
142
+ if (!status)
143
+ return "--";
144
+ return STATUS_OPTIONS.find((s) => s.value === status)?.label || status;
145
+ }
146
+ getBucketLabel(status) {
147
+ if (!status)
148
+ return "--";
149
+ return STATUS_OPTIONS.find((s) => s.value === status)?.bucket || "--";
150
+ }
151
+ async onSubmit() {
152
+ if (!this.canSubmit)
153
+ return;
154
+ const floor = this.floors.find((f) => f._id === this.selectedFloorId);
155
+ const floorLabel = floor
156
+ ? `Floor ${floor.floorNumber} (${floor.floorName})`
157
+ : "selected floor";
158
+ const clearSummary = [];
159
+ if (this.clearLayoutTasks)
160
+ clearSummary.push("Layout");
161
+ if (this.clearFixtureTasks)
162
+ clearSummary.push("Fixture");
163
+ if (this.clearZoneTasks)
164
+ clearSummary.push("Zone");
165
+ const lines = [];
166
+ lines.push(`Store: ${this.selectedStoreLabel ?? "--"}`);
167
+ lines.push(floorLabel);
168
+ if (this.statusChanged) {
169
+ lines.push(`Status: ${this.getStatusLabel(this.currentStatus)} → ${this.getStatusLabel(this.targetStatus)}`);
170
+ }
171
+ if (clearSummary.length) {
172
+ lines.push(`Clear tasks: ${clearSummary.join(", ")}`);
173
+ }
174
+ lines.push("This action cannot be undone. Continue?");
175
+ const confirmed = await this.confirm("Confirm bucket update", lines.join("\n"));
176
+ if (!confirmed)
177
+ return;
178
+ const payload = {
179
+ floorId: this.selectedFloorId,
180
+ targetStatus: this.targetStatus,
181
+ clearLayoutTasks: this.clearLayoutTasks,
182
+ clearFixtureTasks: this.clearFixtureTasks,
183
+ clearZoneTasks: this.clearZoneTasks,
184
+ };
185
+ this.isSubmitting = true;
186
+ this.sbs.moveStoreBucket(payload).subscribe({
187
+ next: (res) => {
188
+ const data = res?.data || {};
189
+ const deleted = data?.deletedCounts || {};
190
+ const parts = [];
191
+ if (data?.prevStatus && data?.nextStatus) {
192
+ parts.push(`Moved ${this.getStatusLabel(data.prevStatus)} → ${this.getStatusLabel(data.nextStatus)}`);
193
+ }
194
+ if (deleted.processedTasks || deleted.planoTaskCompliances) {
195
+ parts.push(`Cleared ${deleted.processedTasks || 0} task(s), ${deleted.planoTaskCompliances || 0} compliance row(s)`);
196
+ }
197
+ this.showMessage(parts.join(". ") || "Updated successfully", "success");
198
+ this.isSubmitting = false;
199
+ this.loadFloors();
200
+ },
201
+ error: (err) => {
202
+ this.showMessage(err?.error?.message || "Failed to update.", "error");
203
+ this.isSubmitting = false;
204
+ },
205
+ });
206
+ }
207
+ async confirm(title, description) {
208
+ try {
209
+ const ref = this.modalService.open(DeleteConfirmationComponent, {
210
+ centered: true,
211
+ });
212
+ ref.componentInstance.title = title;
213
+ ref.componentInstance.description = description;
214
+ ref.componentInstance.confirmLabel = "Update";
215
+ ref.componentInstance.confirmClass = "btn-primary";
216
+ const result = await ref.result;
217
+ return result === "ok";
218
+ }
219
+ catch {
220
+ return false;
221
+ }
222
+ }
223
+ showMessage(msg, type) {
224
+ this.message = msg;
225
+ this.messageType = type;
226
+ setTimeout(() => (this.message = ""), 6000);
227
+ }
228
+ ngOnDestroy() {
229
+ this.destroy$.next();
230
+ this.destroy$.complete();
231
+ }
232
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MoveBucketComponent, deps: [{ token: i1.StoreBuilderService }, { token: i2.GlobalStateService }, { token: i3.NgbModal }], target: i0.ɵɵFactoryTarget.Component });
233
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: MoveBucketComponent, selector: "lib-move-bucket", ngImport: i0, template: "<section class=\"move-bucket p-3\">\n <div class=\"card p-4\" style=\"max-width: 640px;\">\n <h5 class=\"mb-1\">Move Store Bucket</h5>\n <p class=\"text-muted small mb-3\">\n Move a floor between Onboarding (Draft / Allocation Pending) and ManagePlano (Completed) without losing store data.\n </p>\n\n <!-- Store -->\n <div class=\"mb-3\">\n <lib-reactive-select\n label=\"Store\"\n [idField]=\"'id'\"\n [nameField]=\"'label'\"\n [data]=\"storeOptions\"\n [search]=\"true\"\n [ngModel]=\"selectedStoreId\"\n (ngModelChange)=\"onStoreSelected($event)\">\n </lib-reactive-select>\n </div>\n\n <!-- Floor -->\n <div class=\"mb-3\" *ngIf=\"selectedStoreId\">\n <ng-container *ngIf=\"isLoadingFloors; else floorPicker\">\n <div class=\"text-muted small\">Loading floors...</div>\n </ng-container>\n <ng-template #floorPicker>\n <ng-container *ngIf=\"floors.length > 0; else noFloors\">\n <lib-reactive-select\n label=\"Floor\"\n [idField]=\"'_id'\"\n [nameField]=\"'displayName'\"\n [data]=\"floors\"\n [search]=\"true\"\n [ngModel]=\"selectedFloorId\"\n (ngModelChange)=\"onFloorSelected($event)\">\n </lib-reactive-select>\n </ng-container>\n <ng-template #noFloors>\n <div class=\"text-muted small\">No floors found for this store.</div>\n </ng-template>\n </ng-template>\n </div>\n\n <!-- Current bucket info + target status -->\n <ng-container *ngIf=\"selectedFloorId && currentStatus\">\n <div class=\"mb-3 p-3 rounded current-info\">\n <div class=\"d-flex justify-content-between small\">\n <span class=\"text-muted\">Current bucket</span>\n <span class=\"fw-semibold\">{{ getBucketLabel(currentStatus) }}</span>\n </div>\n <div class=\"d-flex justify-content-between small mt-1\">\n <span class=\"text-muted\">Current status</span>\n <span class=\"fw-semibold\">{{ getStatusLabel(currentStatus) }}</span>\n </div>\n </div>\n\n <div class=\"mb-3\">\n <lib-reactive-select\n label=\"Move to status\"\n [idField]=\"'value'\"\n [nameField]=\"'label'\"\n [subTextField]=\"'bucket'\"\n [data]=\"statusOptions\"\n [ngModel]=\"targetStatus\"\n (ngModelChange)=\"onTargetStatusSelected($event)\">\n </lib-reactive-select>\n <div class=\"form-text text-warning\" *ngIf=\"statusChanged\">\n isPlanoApproved will be set to\n <strong>{{ targetStatus === 'draft' ? 'false' : 'true' }}</strong>,\n planoProgress will be set to\n <strong>{{ targetStatus === 'completed' ? 25 : 0 }}</strong>.\n </div>\n </div>\n\n <!-- Task cleanup checkboxes -->\n <div class=\"mb-3\">\n <label class=\"form-label\">Clear tasks &amp; compliance rows (optional)</label>\n <div class=\"d-flex flex-column gap-2\">\n <div class=\"form-check\">\n <input class=\"form-check-input\" type=\"checkbox\" id=\"clrLayout\"\n [(ngModel)]=\"clearLayoutTasks\">\n <label class=\"form-check-label\" for=\"clrLayout\">\n Layout tasks\n <span class=\"text-muted small\">(planoType: layout, layoutFixture)</span>\n </label>\n </div>\n <div class=\"form-check\">\n <input class=\"form-check-input\" type=\"checkbox\" id=\"clrFixture\"\n [(ngModel)]=\"clearFixtureTasks\">\n <label class=\"form-check-label\" for=\"clrFixture\">\n Fixture tasks\n <span class=\"text-muted small\">(planoType: fixture, vm)</span>\n </label>\n </div>\n <div class=\"form-check\">\n <input class=\"form-check-input\" type=\"checkbox\" id=\"clrZone\"\n [(ngModel)]=\"clearZoneTasks\">\n <label class=\"form-check-label\" for=\"clrZone\">\n Zone tasks\n <span class=\"text-muted small\">(planoType: zoneVerification)</span>\n </label>\n </div>\n </div>\n </div>\n </ng-container>\n\n <!-- Submit -->\n <button class=\"btn btn-primary\" (click)=\"onSubmit()\" [disabled]=\"!canSubmit\">\n {{ isSubmitting ? 'Updating...' : 'Update' }}\n </button>\n\n <div class=\"mt-3 alert\" *ngIf=\"message\"\n [class.alert-success]=\"messageType === 'success'\"\n [class.alert-danger]=\"messageType === 'error'\"\n style=\"white-space: pre-line;\">\n {{ message }}\n </div>\n </div>\n</section>\n", styles: [".move-bucket .current-info{background-color:#f9fafb;border:1px solid #e4e7ec}\n"], dependencies: [{ kind: "component", type: i4.ReactiveSelectComponent, selector: "lib-reactive-select", inputs: ["idField", "nameField", "subTextField", "searchField", "label", "data", "action", "search", "prefix", "actionLabel"], outputs: ["actionClick"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] });
234
+ }
235
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: MoveBucketComponent, decorators: [{
236
+ type: Component,
237
+ args: [{ selector: "lib-move-bucket", template: "<section class=\"move-bucket p-3\">\n <div class=\"card p-4\" style=\"max-width: 640px;\">\n <h5 class=\"mb-1\">Move Store Bucket</h5>\n <p class=\"text-muted small mb-3\">\n Move a floor between Onboarding (Draft / Allocation Pending) and ManagePlano (Completed) without losing store data.\n </p>\n\n <!-- Store -->\n <div class=\"mb-3\">\n <lib-reactive-select\n label=\"Store\"\n [idField]=\"'id'\"\n [nameField]=\"'label'\"\n [data]=\"storeOptions\"\n [search]=\"true\"\n [ngModel]=\"selectedStoreId\"\n (ngModelChange)=\"onStoreSelected($event)\">\n </lib-reactive-select>\n </div>\n\n <!-- Floor -->\n <div class=\"mb-3\" *ngIf=\"selectedStoreId\">\n <ng-container *ngIf=\"isLoadingFloors; else floorPicker\">\n <div class=\"text-muted small\">Loading floors...</div>\n </ng-container>\n <ng-template #floorPicker>\n <ng-container *ngIf=\"floors.length > 0; else noFloors\">\n <lib-reactive-select\n label=\"Floor\"\n [idField]=\"'_id'\"\n [nameField]=\"'displayName'\"\n [data]=\"floors\"\n [search]=\"true\"\n [ngModel]=\"selectedFloorId\"\n (ngModelChange)=\"onFloorSelected($event)\">\n </lib-reactive-select>\n </ng-container>\n <ng-template #noFloors>\n <div class=\"text-muted small\">No floors found for this store.</div>\n </ng-template>\n </ng-template>\n </div>\n\n <!-- Current bucket info + target status -->\n <ng-container *ngIf=\"selectedFloorId && currentStatus\">\n <div class=\"mb-3 p-3 rounded current-info\">\n <div class=\"d-flex justify-content-between small\">\n <span class=\"text-muted\">Current bucket</span>\n <span class=\"fw-semibold\">{{ getBucketLabel(currentStatus) }}</span>\n </div>\n <div class=\"d-flex justify-content-between small mt-1\">\n <span class=\"text-muted\">Current status</span>\n <span class=\"fw-semibold\">{{ getStatusLabel(currentStatus) }}</span>\n </div>\n </div>\n\n <div class=\"mb-3\">\n <lib-reactive-select\n label=\"Move to status\"\n [idField]=\"'value'\"\n [nameField]=\"'label'\"\n [subTextField]=\"'bucket'\"\n [data]=\"statusOptions\"\n [ngModel]=\"targetStatus\"\n (ngModelChange)=\"onTargetStatusSelected($event)\">\n </lib-reactive-select>\n <div class=\"form-text text-warning\" *ngIf=\"statusChanged\">\n isPlanoApproved will be set to\n <strong>{{ targetStatus === 'draft' ? 'false' : 'true' }}</strong>,\n planoProgress will be set to\n <strong>{{ targetStatus === 'completed' ? 25 : 0 }}</strong>.\n </div>\n </div>\n\n <!-- Task cleanup checkboxes -->\n <div class=\"mb-3\">\n <label class=\"form-label\">Clear tasks &amp; compliance rows (optional)</label>\n <div class=\"d-flex flex-column gap-2\">\n <div class=\"form-check\">\n <input class=\"form-check-input\" type=\"checkbox\" id=\"clrLayout\"\n [(ngModel)]=\"clearLayoutTasks\">\n <label class=\"form-check-label\" for=\"clrLayout\">\n Layout tasks\n <span class=\"text-muted small\">(planoType: layout, layoutFixture)</span>\n </label>\n </div>\n <div class=\"form-check\">\n <input class=\"form-check-input\" type=\"checkbox\" id=\"clrFixture\"\n [(ngModel)]=\"clearFixtureTasks\">\n <label class=\"form-check-label\" for=\"clrFixture\">\n Fixture tasks\n <span class=\"text-muted small\">(planoType: fixture, vm)</span>\n </label>\n </div>\n <div class=\"form-check\">\n <input class=\"form-check-input\" type=\"checkbox\" id=\"clrZone\"\n [(ngModel)]=\"clearZoneTasks\">\n <label class=\"form-check-label\" for=\"clrZone\">\n Zone tasks\n <span class=\"text-muted small\">(planoType: zoneVerification)</span>\n </label>\n </div>\n </div>\n </div>\n </ng-container>\n\n <!-- Submit -->\n <button class=\"btn btn-primary\" (click)=\"onSubmit()\" [disabled]=\"!canSubmit\">\n {{ isSubmitting ? 'Updating...' : 'Update' }}\n </button>\n\n <div class=\"mt-3 alert\" *ngIf=\"message\"\n [class.alert-success]=\"messageType === 'success'\"\n [class.alert-danger]=\"messageType === 'error'\"\n style=\"white-space: pre-line;\">\n {{ message }}\n </div>\n </div>\n</section>\n", styles: [".move-bucket .current-info{background-color:#f9fafb;border:1px solid #e4e7ec}\n"] }]
238
+ }], ctorParameters: () => [{ type: i1.StoreBuilderService }, { type: i2.GlobalStateService }, { type: i3.NgbModal }] });
239
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW92ZS1idWNrZXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFuZ28tc3RvcmUtYnVpbGRlci9zcmMvbGliL2NvbXBvbmVudHMvcGxhbm8tdG9vbHMvbW92ZS1idWNrZXQvbW92ZS1idWNrZXQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFuZ28tc3RvcmUtYnVpbGRlci9zcmMvbGliL2NvbXBvbmVudHMvcGxhbm8tdG9vbHMvbW92ZS1idWNrZXQvbW92ZS1idWNrZXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBcUIsTUFBTSxlQUFlLENBQUM7QUFFN0QsT0FBTyxFQUNMLFlBQVksRUFDWixvQkFBb0IsRUFDcEIsTUFBTSxFQUNOLE9BQU8sRUFDUCxTQUFTLEdBQ1YsTUFBTSxNQUFNLENBQUM7QUFHZCxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxnRUFBZ0UsQ0FBQzs7Ozs7Ozs7QUF3QjdHLE1BQU0sY0FBYyxHQUFtQjtJQUNyQyxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFO0lBQ3hEO1FBQ0UsS0FBSyxFQUFFLG1CQUFtQjtRQUMxQixLQUFLLEVBQUUsb0JBQW9CO1FBQzNCLE1BQU0sRUFBRSxZQUFZO0tBQ3JCO0lBQ0QsRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLGFBQWEsRUFBRTtDQUNsRSxDQUFDO0FBT0YsTUFBTSxPQUFPLG1CQUFtQjtJQTBCcEI7SUFDQTtJQUNBO0lBM0JWLFFBQVEsQ0FBUztJQUVqQixZQUFZLEdBQWtCLEVBQUUsQ0FBQztJQUNqQyxlQUFlLEdBQWtCLElBQUksQ0FBQztJQUN0QyxrQkFBa0IsR0FBa0IsSUFB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QUUsQ0FBQztJQUMzQixDQUFDO3dHQXRQVSxtQkFBbUI7NEZBQW5CLG1CQUFtQix1RENsRGhDLDJuSkF1SEE7OzRGRHJFYSxtQkFBbUI7a0JBTC9CLFNBQVM7K0JBQ0UsaUJBQWlCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkRlc3Ryb3ksIE9uSW5pdCB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBOZ2JNb2RhbCB9IGZyb20gXCJAbmctYm9vdHN0cmFwL25nLWJvb3RzdHJhcFwiO1xuaW1wb3J0IHtcbiAgZGVib3VuY2VUaW1lLFxuICBkaXN0aW5jdFVudGlsQ2hhbmdlZCxcbiAgZmlsdGVyLFxuICBTdWJqZWN0LFxuICB0YWtlVW50aWwsXG59IGZyb20gXCJyeGpzXCI7XG5pbXBvcnQgeyBHbG9iYWxTdGF0ZVNlcnZpY2UgfSBmcm9tIFwidGFuZ28tYXBwLXVpLWdsb2JhbFwiO1xuaW1wb3J0IHsgU3RvcmVCdWlsZGVyU2VydmljZSB9IGZyb20gXCIuLi8uLi8uLi9zZXJ2aWNlcy9zdG9yZS1idWlsZGVyLnNlcnZpY2VcIjtcbmltcG9ydCB7IERlbGV0ZUNvbmZpcm1hdGlvbkNvbXBvbmVudCB9IGZyb20gXCIuLi8uLi9wb3B1cHMvZGVsZXRlLWNvbmZpcm1hdGlvbi9kZWxldGUtY29uZmlybWF0aW9uLmNvbXBvbmVudFwiO1xuXG5pbnRlcmZhY2UgU3RvcmVPcHRpb24ge1xuICBpZDogc3RyaW5nO1xuICBsYWJlbDogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgRmxvb3JPcHRpb24ge1xuICBfaWQ6IHN0cmluZztcbiAgZmxvb3JOdW1iZXI6IG51bWJlcjtcbiAgZmxvb3JOYW1lOiBzdHJpbmc7XG4gIHN0YXR1czogQnVja2V0U3RhdHVzO1xuICBpc1BsYW5vQXBwcm92ZWQ/OiBib29sZWFuO1xuICBkaXNwbGF5TmFtZTogc3RyaW5nO1xufVxuXG50eXBlIEJ1Y2tldFN0YXR1cyA9IFwiZHJhZnRcIiB8IFwiYWxsb2NhdGlvblBlbmRpbmdcIiB8IFwiY29tcGxldGVkXCI7XG5cbmludGVyZmFjZSBTdGF0dXNPcHRpb24ge1xuICB2YWx1ZTogQnVja2V0U3RhdHVzO1xuICBsYWJlbDogc3RyaW5nO1xuICBidWNrZXQ6IHN0cmluZztcbn1cblxuY29uc3QgU1RBVFVTX09QVElPTlM6IFN0YXR1c09wdGlvbltdID0gW1xuICB7IHZhbHVlOiBcImRyYWZ0XCIsIGxhYmVsOiBcIkRyYWZ0XCIsIGJ1Y2tldDogXCJPbmJvYXJkaW5nXCIgfSxcbiAge1xuICAgIHZhbHVlOiBcImFsbG9jYXRpb25QZW5kaW5nXCIsXG4gICAgbGFiZWw6IFwiQWxsb2NhdGlvbiBQZW5kaW5nXCIsXG4gICAgYnVja2V0OiBcIk9uYm9hcmRpbmdcIixcbiAgfSxcbiAgeyB2YWx1ZTogXCJjb21wbGV0ZWRcIiwgbGFiZWw6IFwiQ29tcGxldGVkXCIsIGJ1Y2tldDogXCJNYW5hZ2VQbGFub1wiIH0sXG5dO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6IFwibGliLW1vdmUtYnVja2V0XCIsXG4gIHRlbXBsYXRlVXJsOiBcIi4vbW92ZS1idWNrZXQuY29tcG9uZW50Lmh0bWxcIixcbiAgc3R5bGVVcmw6IFwiLi9tb3ZlLWJ1Y2tldC5jb21wb25lbnQuc2Nzc1wiLFxufSlcbmV4cG9ydCBjbGFzcyBNb3ZlQnVja2V0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuICBjbGllbnRJZDogc3RyaW5nO1xuXG4gIHN0b3JlT3B0aW9uczogU3RvcmVPcHRpb25bXSA9IFtdO1xuICBzZWxlY3RlZFN0b3JlSWQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBzZWxlY3RlZFN0b3JlTGFiZWw6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIGZsb29yczogRmxvb3JPcHRpb25bXSA9IFtdO1xuICBzZWxlY3RlZEZsb29ySWQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBpc0xvYWRpbmdGbG9vcnM6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBzdGF0dXNPcHRpb25zID0gU1RBVFVTX09QVElPTlM7XG4gIHRhcmdldFN0YXR1czogQnVja2V0U3RhdHVzIHwgbnVsbCA9IG51bGw7XG4gIGN1cnJlbnRTdGF0dXM6IEJ1Y2tldFN0YXR1cyB8IG51bGwgPSBudWxsO1xuXG4gIGNsZWFyTGF5b3V0VGFza3M6IGJvb2xlYW4gPSBmYWxzZTtcbiAgY2xlYXJGaXh0dXJlVGFza3M6IGJvb2xlYW4gPSBmYWxzZTtcbiAgY2xlYXJab25lVGFza3M6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBpc1N1Ym1pdHRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcbiAgbWVzc2FnZTogc3RyaW5nID0gXCJcIjtcbiAgbWVzc2FnZVR5cGU6IFwic3VjY2Vzc1wiIHwgXCJlcnJvclwiID0gXCJzdWNjZXNzXCI7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBkZXN0cm95JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBzYnM6IFN0b3JlQnVpbGRlclNlcnZpY2UsXG4gICAgcHJpdmF0ZSBnczogR2xvYmFsU3RhdGVTZXJ2aWNlLFxuICAgIHByaXZhdGUgbW9kYWxTZXJ2aWNlOiBOZ2JNb2RhbCxcbiAgKSB7fVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuZ3MuZGF0YVJhbmdlVmFsdWVcbiAgICAgIC5waXBlKFxuICAgICAgICB0YWtlVW50aWwodGhpcy5kZXN0cm95JCksXG4gICAgICAgIGRlYm91bmNlVGltZSgyMDApLFxuICAgICAgICBmaWx0ZXIoKGRhdGEpID0+ICEhZGF0YSksXG4gICAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKChkYXRhOiBhbnkpID0+IHtcbiAgICAgICAgaWYgKGRhdGE/LmNsaWVudCkge1xuICAgICAgICAgIHRoaXMuY2xpZW50SWQgPSBkYXRhLmNsaWVudDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zdCBoZWFkZXJEYXRhID0gSlNPTi5wYXJzZShcbiAgICAgICAgICAgIGxvY2FsU3RvcmFnZS5nZXRJdGVtKFwiaGVhZGVyLWZpbHRlcnNcIikgYXMgc3RyaW5nLFxuICAgICAgICAgICk7XG4gICAgICAgICAgdGhpcy5jbGllbnRJZCA9IGhlYWRlckRhdGE/LmNsaWVudDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmxvYWRTdG9yZXMoKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgbG9hZFN0b3JlcygpIHtcbiAgICB0aGlzLnNic1xuICAgICAgLmdldFN0b3JlT3JDbHVzdGVyTGlzdCh7IHNlYXJjaE1vZGU6IFwic3RvcmVcIiB9KVxuICAgICAgLnN1YnNjcmliZSgocmVzOiBhbnkpID0+IHtcbiAgICAgICAgdGhpcy5zdG9yZU9wdGlvbnMgPSByZXM/LmRhdGEgfHwgW107XG4gICAgICB9KTtcbiAgfVxuXG4gIG9uU3RvcmVTZWxlY3RlZChzdG9yZUlkOiBzdHJpbmcgfCBudWxsKSB7XG4gICAgdGhpcy5zZWxlY3RlZFN0b3JlSWQgPSBzdG9yZUlkO1xuICAgIGNvbnN0IHN0b3JlID0gdGhpcy5zdG9yZU9wdGlvbnMuZmluZCgocykgPT4gcy5pZCA9PT0gc3RvcmVJZCk7XG4gICAgdGhpcy5zZWxlY3RlZFN0b3JlTGFiZWwgPSBzdG9yZT8ubGFiZWwgPz8gbnVsbDtcbiAgICB0aGlzLnJlc2V0Rmxvb3JTdGF0ZSgpO1xuICAgIGlmICh0aGlzLnNlbGVjdGVkU3RvcmVMYWJlbCkge1xuICAgICAgdGhpcy5sb2FkRmxvb3JzKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZXNldEZsb29yU3RhdGUoKSB7XG4gICAgdGhpcy5mbG9vcnMgPSBbXTtcbiAgICB0aGlzLnNlbGVjdGVkRmxvb3JJZCA9IG51bGw7XG4gICAgdGhpcy5jdXJyZW50U3RhdHVzID0gbnVsbDtcbiAgICB0aGlzLnRhcmdldFN0YXR1cyA9IG51bGw7XG4gICAgdGhpcy5jbGVhckxheW91dFRhc2tzID0gZmFsc2U7XG4gICAgdGhpcy5jbGVhckZpeHR1cmVUYXNrcyA9IGZhbHNlO1xuICAgIHRoaXMuY2xlYXJab25lVGFza3MgPSBmYWxzZTtcbiAgfVxuXG4gIGxvYWRGbG9vcnMoKSB7XG4gICAgaWYgKCF0aGlzLnNlbGVjdGVkU3RvcmVMYWJlbCkgcmV0dXJuO1xuICAgIHRoaXMuaXNMb2FkaW5nRmxvb3JzID0gdHJ1ZTtcbiAgICB0aGlzLnNic1xuICAgICAgLmdldEZsb29yc1dpdGhTdGF0dXModGhpcy5zZWxlY3RlZFN0b3JlTGFiZWwsIHRoaXMuY2xpZW50SWQpXG4gICAgICAuc3Vic2NyaWJlKHtcbiAgICAgICAgbmV4dDogKHJlczogYW55KSA9PiB7XG4gICAgICAgICAgY29uc3QgcmF3OiBhbnlbXSA9IHJlcz8uZGF0YT8uZmxvb3JzIHx8IFtdO1xuICAgICAgICAgIHRoaXMuZmxvb3JzID0gcmF3XG4gICAgICAgICAgICAubWFwKChmKSA9PiAoe1xuICAgICAgICAgICAgICBfaWQ6IGYuX2lkLFxuICAgICAgICAgICAgICBmbG9vck51bWJlcjogZi5mbG9vck51bWJlcixcbiAgICAgICAgICAgICAgZmxvb3JOYW1lOiBmLmZsb29yTmFtZSxcbiAgICAgICAgICAgICAgc3RhdHVzOiBmLnN0YXR1cyxcbiAgICAgICAgICAgICAgaXNQbGFub0FwcHJvdmVkOiBmLmlzUGxhbm9BcHByb3ZlZCxcbiAgICAgICAgICAgICAgZGlzcGxheU5hbWU6IGBGbG9vciAke2YuZmxvb3JOdW1iZXJ9IOKAlCAke2YuZmxvb3JOYW1lfSBbJHt0aGlzLmdldFN0YXR1c0xhYmVsKGYuc3RhdHVzKX1dYCxcbiAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgLnNvcnQoKGEsIGIpID0+IGEuZmxvb3JOdW1iZXIgLSBiLmZsb29yTnVtYmVyKTtcbiAgICAgICAgICBpZiAodGhpcy5mbG9vcnMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICB0aGlzLm9uRmxvb3JTZWxlY3RlZCh0aGlzLmZsb29yc1swXS5faWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLmlzTG9hZGluZ0Zsb29ycyA9IGZhbHNlO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogKGVycjogYW55KSA9PiB7XG4gICAgICAgICAgdGhpcy5zaG93TWVzc2FnZShcbiAgICAgICAgICAgIGVycj8uZXJyb3I/Lm1lc3NhZ2UgfHwgXCJGYWlsZWQgdG8gbG9hZCBmbG9vcnMuXCIsXG4gICAgICAgICAgICBcImVycm9yXCIsXG4gICAgICAgICAgKTtcbiAgICAgICAgICB0aGlzLmlzTG9hZGluZ0Zsb29ycyA9IGZhbHNlO1xuICAgICAgICB9LFxuICAgICAgfSk7XG4gIH1cblxuICBvbkZsb29yU2VsZWN0ZWQoZmxvb3JJZDogc3RyaW5nIHwgbnVsbCkge1xuICAgIHRoaXMuc2VsZWN0ZWRGbG9vcklkID0gZmxvb3JJZDtcbiAgICBjb25zdCBmbG9vciA9IHRoaXMuZmxvb3JzLmZpbmQoKGYpID0+IGYuX2lkID09PSBmbG9vcklkKTtcbiAgICBpZiAoZmxvb3IpIHtcbiAgICAgIHRoaXMuY3VycmVudFN0YXR1cyA9IGZsb29yLnN0YXR1cztcbiAgICAgIHRoaXMudGFyZ2V0U3RhdHVzID0gZmxvb3Iuc3RhdHVzO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmN1cnJlbnRTdGF0dXMgPSBudWxsO1xuICAgICAgdGhpcy50YXJnZXRTdGF0dXMgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIG9uVGFyZ2V0U3RhdHVzU2VsZWN0ZWQodmFsdWU6IEJ1Y2tldFN0YXR1cyB8IG51bGwpIHtcbiAgICB0aGlzLnRhcmdldFN0YXR1cyA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0IHN0YXR1c0NoYW5nZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhdGhpcy50YXJnZXRTdGF0dXMgJiYgdGhpcy50YXJnZXRTdGF0dXMgIT09IHRoaXMuY3VycmVudFN0YXR1cztcbiAgfVxuXG4gIGdldCBjYW5TdWJtaXQoKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuaXNTdWJtaXR0aW5nKSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKCF0aGlzLnNlbGVjdGVkRmxvb3JJZCB8fCAhdGhpcy50YXJnZXRTdGF0dXMpIHJldHVybiBmYWxzZTtcbiAgICBjb25zdCBhbnlDbGVhciA9XG4gICAgICB0aGlzLmNsZWFyTGF5b3V0VGFza3MgfHwgdGhpcy5jbGVhckZpeHR1cmVUYXNrcyB8fCB0aGlzLmNsZWFyWm9uZVRhc2tzO1xuICAgIHJldHVybiB0aGlzLnN0YXR1c0NoYW5nZWQgfHwgYW55Q2xlYXI7XG4gIH1cblxuICBnZXRTdGF0dXNMYWJlbChzdGF0dXM6IEJ1Y2tldFN0YXR1cyB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcge1xuICAgIGlmICghc3RhdHVzKSByZXR1cm4gXCItLVwiO1xuICAgIHJldHVybiBTVEFUVVNfT1BUSU9OUy5maW5kKChzKSA9PiBzLnZhbHVlID09PSBzdGF0dXMpPy5sYWJlbCB8fCBzdGF0dXM7XG4gIH1cblxuICBnZXRCdWNrZXRMYWJlbChzdGF0dXM6IEJ1Y2tldFN0YXR1cyB8IG51bGwgfCB1bmRlZmluZWQpOiBzdHJpbmcge1xuICAgIGlmICghc3RhdHVzKSByZXR1cm4gXCItLVwiO1xuICAgIHJldHVybiBTVEFUVVNfT1BUSU9OUy5maW5kKChzKSA9PiBzLnZhbHVlID09PSBzdGF0dXMpPy5idWNrZXQgfHwgXCItLVwiO1xuICB9XG5cbiAgYXN5bmMgb25TdWJtaXQoKSB7XG4gICAgaWYgKCF0aGlzLmNhblN1Ym1pdCkgcmV0dXJuO1xuXG4gICAgY29uc3QgZmxvb3IgPSB0aGlzLmZsb29ycy5maW5kKChmKSA9PiBmLl9pZCA9PT0gdGhpcy5zZWxlY3RlZEZsb29ySWQpO1xuICAgIGNvbnN0IGZsb29yTGFiZWwgPSBmbG9vclxuICAgICAgPyBgRmxvb3IgJHtmbG9vci5mbG9vck51bWJlcn0gKCR7Zmxvb3IuZmxvb3JOYW1lfSlgXG4gICAgICA6IFwic2VsZWN0ZWQgZmxvb3JcIjtcblxuICAgIGNvbnN0IGNsZWFyU3VtbWFyeTogc3RyaW5nW10gPSBbXTtcbiAgICBpZiAodGhpcy5jbGVhckxheW91dFRhc2tzKSBjbGVhclN1bW1hcnkucHVzaChcIkxheW91dFwiKTtcbiAgICBpZiAodGhpcy5jbGVhckZpeHR1cmVUYXNrcykgY2xlYXJTdW1tYXJ5LnB1c2goXCJGaXh0dXJlXCIpO1xuICAgIGlmICh0aGlzLmNsZWFyWm9uZVRhc2tzKSBjbGVhclN1bW1hcnkucHVzaChcIlpvbmVcIik7XG5cbiAgICBjb25zdCBsaW5lczogc3RyaW5nW10gPSBbXTtcbiAgICBsaW5lcy5wdXNoKGBTdG9yZTogJHt0aGlzLnNlbGVjdGVkU3RvcmVMYWJlbCA/PyBcIi0tXCJ9YCk7XG4gICAgbGluZXMucHVzaChmbG9vckxhYmVsKTtcbiAgICBpZiAodGhpcy5zdGF0dXNDaGFuZ2VkKSB7XG4gICAgICBsaW5lcy5wdXNoKFxuICAgICAgICBgU3RhdHVzOiAke3RoaXMuZ2V0U3RhdHVzTGFiZWwodGhpcy5jdXJyZW50U3RhdHVzKX0g4oaSICR7dGhpcy5nZXRTdGF0dXNMYWJlbCh0aGlzLnRhcmdldFN0YXR1cyl9YCxcbiAgICAgICk7XG4gICAgfVxuICAgIGlmIChjbGVhclN1bW1hcnkubGVuZ3RoKSB7XG4gICAgICBsaW5lcy5wdXNoKGBDbGVhciB0YXNrczogJHtjbGVhclN1bW1hcnkuam9pbihcIiwgXCIpfWApO1xuICAgIH1cbiAgICBsaW5lcy5wdXNoKFwiVGhpcyBhY3Rpb24gY2Fubm90IGJlIHVuZG9uZS4gQ29udGludWU/XCIpO1xuXG4gICAgY29uc3QgY29uZmlybWVkID0gYXdhaXQgdGhpcy5jb25maXJtKFxuICAgICAgXCJDb25maXJtIGJ1Y2tldCB1cGRhdGVcIixcbiAgICAgIGxpbmVzLmpvaW4oXCJcXG5cIiksXG4gICAgKTtcbiAgICBpZiAoIWNvbmZpcm1lZCkgcmV0dXJuO1xuXG4gICAgY29uc3QgcGF5bG9hZCA9IHtcbiAgICAgIGZsb29ySWQ6IHRoaXMuc2VsZWN0ZWRGbG9vcklkISxcbiAgICAgIHRhcmdldFN0YXR1czogdGhpcy50YXJnZXRTdGF0dXMhLFxuICAgICAgY2xlYXJMYXlvdXRUYXNrczogdGhpcy5jbGVhckxheW91dFRhc2tzLFxuICAgICAgY2xlYXJGaXh0dXJlVGFza3M6IHRoaXMuY2xlYXJGaXh0dXJlVGFza3MsXG4gICAgICBjbGVhclpvbmVUYXNrczogdGhpcy5jbGVhclpvbmVUYXNrcyxcbiAgICB9O1xuXG4gICAgdGhpcy5pc1N1Ym1pdHRpbmcgPSB0cnVlO1xuICAgIHRoaXMuc2JzLm1vdmVTdG9yZUJ1Y2tldChwYXlsb2FkKS5zdWJzY3JpYmUoe1xuICAgICAgbmV4dDogKHJlczogYW55KSA9PiB7XG4gICAgICAgIGNvbnN0IGRhdGEgPSByZXM/LmRhdGEgfHwge307XG4gICAgICAgIGNvbnN0IGRlbGV0ZWQgPSBkYXRhPy5kZWxldGVkQ291bnRzIHx8IHt9O1xuICAgICAgICBjb25zdCBwYXJ0czogc3RyaW5nW10gPSBbXTtcbiAgICAgICAgaWYgKGRhdGE/LnByZXZTdGF0dXMgJiYgZGF0YT8ubmV4dFN0YXR1cykge1xuICAgICAgICAgIHBhcnRzLnB1c2goXG4gICAgICAgICAgICBgTW92ZWQgJHt0aGlzLmdldFN0YXR1c0xhYmVsKGRhdGEucHJldlN0YXR1cyl9IOKGkiAke3RoaXMuZ2V0U3RhdHVzTGFiZWwoZGF0YS5uZXh0U3RhdHVzKX1gLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRlbGV0ZWQucHJvY2Vzc2VkVGFza3MgfHwgZGVsZXRlZC5wbGFub1Rhc2tDb21wbGlhbmNlcykge1xuICAgICAgICAgIHBhcnRzLnB1c2goXG4gICAgICAgICAgICBgQ2xlYXJlZCAke2RlbGV0ZWQucHJvY2Vzc2VkVGFza3MgfHwgMH0gdGFzayhzKSwgJHtkZWxldGVkLnBsYW5vVGFza0NvbXBsaWFuY2VzIHx8IDB9IGNvbXBsaWFuY2Ugcm93KHMpYCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2hvd01lc3NhZ2UoXG4gICAgICAgICAgcGFydHMuam9pbihcIi4gXCIpIHx8IFwiVXBkYXRlZCBzdWNjZXNzZnVsbHlcIixcbiAgICAgICAgICBcInN1Y2Nlc3NcIixcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5pc1N1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5sb2FkRmxvb3JzKCk7XG4gICAgICB9LFxuICAgICAgZXJyb3I6IChlcnI6IGFueSkgPT4ge1xuICAgICAgICB0aGlzLnNob3dNZXNzYWdlKGVycj8uZXJyb3I/Lm1lc3NhZ2UgfHwgXCJGYWlsZWQgdG8gdXBkYXRlLlwiLCBcImVycm9yXCIpO1xuICAgICAgICB0aGlzLmlzU3VibWl0dGluZyA9IGZhbHNlO1xuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY29uZmlybSh0aXRsZTogc3RyaW5nLCBkZXNjcmlwdGlvbjogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlZiA9IHRoaXMubW9kYWxTZXJ2aWNlLm9wZW4oRGVsZXRlQ29uZmlybWF0aW9uQ29tcG9uZW50LCB7XG4gICAgICAgIGNlbnRlcmVkOiB0cnVlLFxuICAgICAgfSk7XG4gICAgICByZWYuY29tcG9uZW50SW5zdGFuY2UudGl0bGUgPSB0aXRsZTtcbiAgICAgIHJlZi5jb21wb25lbnRJbnN0YW5jZS5kZXNjcmlwdGlvbiA9IGRlc2NyaXB0aW9uO1xuICAgICAgcmVmLmNvbXBvbmVudEluc3RhbmNlLmNvbmZpcm1MYWJlbCA9IFwiVXBkYXRlXCI7XG4gICAgICByZWYuY29tcG9uZW50SW5zdGFuY2UuY29uZmlybUNsYXNzID0gXCJidG4tcHJpbWFyeVwiO1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcmVmLnJlc3VsdDtcbiAgICAgIHJldHVybiByZXN1bHQgPT09IFwib2tcIjtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBzaG93TWVzc2FnZShtc2c6IHN0cmluZywgdHlwZTogXCJzdWNjZXNzXCIgfCBcImVycm9yXCIpIHtcbiAgICB0aGlzLm1lc3NhZ2UgPSBtc2c7XG4gICAgdGhpcy5tZXNzYWdlVHlwZSA9IHR5cGU7XG4gICAgc2V0VGltZW91dCgoKSA9PiAodGhpcy5tZXNzYWdlID0gXCJcIiksIDYwMDApO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5kZXN0cm95JC5uZXh0KCk7XG4gICAgdGhpcy5kZXN0cm95JC5jb21wbGV0ZSgpO1xuICB9XG59XG4iLCI8c2VjdGlvbiBjbGFzcz1cIm1vdmUtYnVja2V0IHAtM1wiPlxuICA8ZGl2IGNsYXNzPVwiY2FyZCBwLTRcIiBzdHlsZT1cIm1heC13aWR0aDogNjQwcHg7XCI+XG4gICAgPGg1IGNsYXNzPVwibWItMVwiPk1vdmUgU3RvcmUgQnVja2V0PC9oNT5cbiAgICA8cCBjbGFzcz1cInRleHQtbXV0ZWQgc21hbGwgbWItM1wiPlxuICAgICAgTW92ZSBhIGZsb29yIGJldHdlZW4gT25ib2FyZGluZyAoRHJhZnQgLyBBbGxvY2F0aW9uIFBlbmRpbmcpIGFuZCBNYW5hZ2VQbGFubyAoQ29tcGxldGVkKSB3aXRob3V0IGxvc2luZyBzdG9yZSBkYXRhLlxuICAgIDwvcD5cblxuICAgIDwhLS0gU3RvcmUgLS0+XG4gICAgPGRpdiBjbGFzcz1cIm1iLTNcIj5cbiAgICAgIDxsaWItcmVhY3RpdmUtc2VsZWN0XG4gICAgICAgIGxhYmVsPVwiU3RvcmVcIlxuICAgICAgICBbaWRGaWVsZF09XCInaWQnXCJcbiAgICAgICAgW25hbWVGaWVsZF09XCInbGFiZWwnXCJcbiAgICAgICAgW2RhdGFdPVwic3RvcmVPcHRpb25zXCJcbiAgICAgICAgW3NlYXJjaF09XCJ0cnVlXCJcbiAgICAgICAgW25nTW9kZWxdPVwic2VsZWN0ZWRTdG9yZUlkXCJcbiAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwib25TdG9yZVNlbGVjdGVkKCRldmVudClcIj5cbiAgICAgIDwvbGliLXJlYWN0aXZlLXNlbGVjdD5cbiAgICA8L2Rpdj5cblxuICAgIDwhLS0gRmxvb3IgLS0+XG4gICAgPGRpdiBjbGFzcz1cIm1iLTNcIiAqbmdJZj1cInNlbGVjdGVkU3RvcmVJZFwiPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImlzTG9hZGluZ0Zsb29yczsgZWxzZSBmbG9vclBpY2tlclwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwidGV4dC1tdXRlZCBzbWFsbFwiPkxvYWRpbmcgZmxvb3JzLi4uPC9kaXY+XG4gICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIDxuZy10ZW1wbGF0ZSAjZmxvb3JQaWNrZXI+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJmbG9vcnMubGVuZ3RoID4gMDsgZWxzZSBub0Zsb29yc1wiPlxuICAgICAgICAgIDxsaWItcmVhY3RpdmUtc2VsZWN0XG4gICAgICAgICAgICBsYWJlbD1cIkZsb29yXCJcbiAgICAgICAgICAgIFtpZEZpZWxkXT1cIidfaWQnXCJcbiAgICAgICAgICAgIFtuYW1lRmllbGRdPVwiJ2Rpc3BsYXlOYW1lJ1wiXG4gICAgICAgICAgICBbZGF0YV09XCJmbG9vcnNcIlxuICAgICAgICAgICAgW3NlYXJjaF09XCJ0cnVlXCJcbiAgICAgICAgICAgIFtuZ01vZGVsXT1cInNlbGVjdGVkRmxvb3JJZFwiXG4gICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJvbkZsb29yU2VsZWN0ZWQoJGV2ZW50KVwiPlxuICAgICAgICAgIDwvbGliLXJlYWN0aXZlLXNlbGVjdD5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgIDxuZy10ZW1wbGF0ZSAjbm9GbG9vcnM+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInRleHQtbXV0ZWQgc21hbGxcIj5ObyBmbG9vcnMgZm91bmQgZm9yIHRoaXMgc3RvcmUuPC9kaXY+XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICA8L25nLXRlbXBsYXRlPlxuICAgIDwvZGl2PlxuXG4gICAgPCEtLSBDdXJyZW50IGJ1Y2tldCBpbmZvICsgdGFyZ2V0IHN0YXR1cyAtLT5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwic2VsZWN0ZWRGbG9vcklkICYmIGN1cnJlbnRTdGF0dXNcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJtYi0zIHAtMyByb3VuZGVkIGN1cnJlbnQtaW5mb1wiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGp1c3RpZnktY29udGVudC1iZXR3ZWVuIHNtYWxsXCI+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkXCI+Q3VycmVudCBidWNrZXQ8L3NwYW4+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJmdy1zZW1pYm9sZFwiPnt7IGdldEJ1Y2tldExhYmVsKGN1cnJlbnRTdGF0dXMpIH19PC9zcGFuPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBzbWFsbCBtdC0xXCI+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkXCI+Q3VycmVudCBzdGF0dXM8L3NwYW4+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJmdy1zZW1pYm9sZFwiPnt7IGdldFN0YXR1c0xhYmVsKGN1cnJlbnRTdGF0dXMpIH19PC9zcGFuPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8ZGl2IGNsYXNzPVwibWItM1wiPlxuICAgICAgICA8bGliLXJlYWN0aXZlLXNlbGVjdFxuICAgICAgICAgIGxhYmVsPVwiTW92ZSB0byBzdGF0dXNcIlxuICAgICAgICAgIFtpZEZpZWxkXT1cIid2YWx1ZSdcIlxuICAgICAgICAgIFtuYW1lRmllbGRdPVwiJ2xhYmVsJ1wiXG4gICAgICAgICAgW3N1YlRleHRGaWVsZF09XCInYnVja2V0J1wiXG4gICAgICAgICAgW2RhdGFdPVwic3RhdHVzT3B0aW9uc1wiXG4gICAgICAgICAgW25nTW9kZWxdPVwidGFyZ2V0U3RhdHVzXCJcbiAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJvblRhcmdldFN0YXR1c1NlbGVjdGVkKCRldmVudClcIj5cbiAgICAgICAgPC9saWItcmVhY3RpdmUtc2VsZWN0PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS10ZXh0IHRleHQtd2FybmluZ1wiICpuZ0lmPVwic3RhdHVzQ2hhbmdlZFwiPlxuICAgICAgICAgIGlzUGxhbm9BcHByb3ZlZCB3aWxsIGJlIHNldCB0b1xuICAgICAgICAgIDxzdHJvbmc+e3sgdGFyZ2V0U3RhdHVzID09PSAnZHJhZnQnID8gJ2ZhbHNlJyA6ICd0cnVlJyB9fTwvc3Ryb25nPixcbiAgICAgICAgICBwbGFub1Byb2dyZXNzIHdpbGwgYmUgc2V0IHRvXG4gICAgICAgICAgPHN0cm9uZz57eyB0YXJnZXRTdGF0dXMgPT09ICdjb21wbGV0ZWQnID8gMjUgOiAwIH19PC9zdHJvbmc+LlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8IS0tIFRhc2sgY2xlYW51cCBjaGVja2JveGVzIC0tPlxuICAgICAgPGRpdiBjbGFzcz1cIm1iLTNcIj5cbiAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1sYWJlbFwiPkNsZWFyIHRhc2tzICZhbXA7IGNvbXBsaWFuY2Ugcm93cyAob3B0aW9uYWwpPC9sYWJlbD5cbiAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBmbGV4LWNvbHVtbiBnYXAtMlwiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrXCI+XG4gICAgICAgICAgICA8aW5wdXQgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCIgdHlwZT1cImNoZWNrYm94XCIgaWQ9XCJjbHJMYXlvdXRcIlxuICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImNsZWFyTGF5b3V0VGFza3NcIj5cbiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWxcIiBmb3I9XCJjbHJMYXlvdXRcIj5cbiAgICAgICAgICAgICAgTGF5b3V0IHRhc2tzXG4gICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1tdXRlZCBzbWFsbFwiPihwbGFub1R5cGU6IGxheW91dCwgbGF5b3V0Rml4dHVyZSk8L3NwYW4+XG4gICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrXCI+XG4gICAgICAgICAgICA8aW5wdXQgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCIgdHlwZT1cImNoZWNrYm94XCIgaWQ9XCJjbHJGaXh0dXJlXCJcbiAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJjbGVhckZpeHR1cmVUYXNrc1wiPlxuICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbFwiIGZvcj1cImNsckZpeHR1cmVcIj5cbiAgICAgICAgICAgICAgRml4dHVyZSB0YXNrc1xuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtbXV0ZWQgc21hbGxcIj4ocGxhbm9UeXBlOiBmaXh0dXJlLCB2bSk8L3NwYW4+XG4gICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrXCI+XG4gICAgICAgICAgICA8aW5wdXQgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCIgdHlwZT1cImNoZWNrYm94XCIgaWQ9XCJjbHJab25lXCJcbiAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJjbGVhclpvbmVUYXNrc1wiPlxuICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbFwiIGZvcj1cImNsclpvbmVcIj5cbiAgICAgICAgICAgICAgWm9uZSB0YXNrc1xuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtbXV0ZWQgc21hbGxcIj4ocGxhbm9UeXBlOiB6b25lVmVyaWZpY2F0aW9uKTwvc3Bhbj5cbiAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9uZy1jb250YWluZXI+XG5cbiAgICA8IS0tIFN1Ym1pdCAtLT5cbiAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5XCIgKGNsaWNrKT1cIm9uU3VibWl0KClcIiBbZGlzYWJsZWRdPVwiIWNhblN1Ym1pdFwiPlxuICAgICAge3sgaXNTdWJtaXR0aW5nID8gJ1VwZGF0aW5nLi4uJyA6ICdVcGRhdGUnIH19XG4gICAgPC9idXR0b24+XG5cbiAgICA8ZGl2IGNsYXNzPVwibXQtMyBhbGVydFwiICpuZ0lmPVwibWVzc2FnZVwiXG4gICAgICBbY2xhc3MuYWxlcnQtc3VjY2Vzc109XCJtZXNzYWdlVHlwZSA9PT0gJ3N1Y2Nlc3MnXCJcbiAgICAgIFtjbGFzcy5hbGVydC1kYW5nZXJdPVwibWVzc2FnZVR5cGUgPT09ICdlcnJvcidcIlxuICAgICAgc3R5bGU9XCJ3aGl0ZS1zcGFjZTogcHJlLWxpbmU7XCI+XG4gICAgICB7eyBtZXNzYWdlIH19XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9zZWN0aW9uPlxuIl19