tango-app-ui-store-builder 1.2.21 → 1.2.23
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.
- package/esm2022/lib/components/onboard-store-plano/onboard-store-plano.component.mjs +90 -33
- package/esm2022/lib/components/plano-tools/fixture-conformance/fixture-conformance.component.mjs +6 -4
- package/fesm2022/{tango-app-ui-store-builder-dxf-source-viewer.component-B0ut7XVu.mjs → tango-app-ui-store-builder-dxf-source-viewer.component-BplzhK87.mjs} +2 -2
- package/fesm2022/{tango-app-ui-store-builder-dxf-source-viewer.component-B0ut7XVu.mjs.map → tango-app-ui-store-builder-dxf-source-viewer.component-BplzhK87.mjs.map} +1 -1
- package/fesm2022/{tango-app-ui-store-builder-tango-app-ui-store-builder-UJrKxjTl.mjs → tango-app-ui-store-builder-tango-app-ui-store-builder-CXw6OsFW.mjs} +96 -37
- package/fesm2022/{tango-app-ui-store-builder-tango-app-ui-store-builder-UJrKxjTl.mjs.map → tango-app-ui-store-builder-tango-app-ui-store-builder-CXw6OsFW.mjs.map} +1 -1
- package/fesm2022/tango-app-ui-store-builder.mjs +1 -1
- package/lib/components/manage-plano/onboard-table/onboard-table.component.d.ts +1 -1
- package/lib/components/manage-plano/rollout-table/rollout-table.component.d.ts +4 -4
- package/lib/components/manage-plano/verification-table/verification-table.component.d.ts +5 -5
- package/lib/components/onboard-store-plano/onboard-store-plano.component.d.ts +4 -2
- package/lib/components/plano-tools/fixture-conformance/fixture-conformance.component.d.ts +3 -1
- package/package.json +1 -1
|
@@ -7624,7 +7624,7 @@ class CadSourceService {
|
|
|
7624
7624
|
async open(storeName, cadFiles) {
|
|
7625
7625
|
if (!this.hasSource(cadFiles))
|
|
7626
7626
|
return;
|
|
7627
|
-
const { DxfSourceViewerComponent } = await import('./tango-app-ui-store-builder-dxf-source-viewer.component-
|
|
7627
|
+
const { DxfSourceViewerComponent } = await import('./tango-app-ui-store-builder-dxf-source-viewer.component-BplzhK87.mjs');
|
|
7628
7628
|
const ref = this.ngbModal.open(DxfSourceViewerComponent, {
|
|
7629
7629
|
size: "xl",
|
|
7630
7630
|
centered: true,
|
|
@@ -62369,31 +62369,88 @@ class OnboardStorePlanoComponent {
|
|
|
62369
62369
|
height: maxY - minY,
|
|
62370
62370
|
};
|
|
62371
62371
|
}
|
|
62372
|
-
//
|
|
62373
|
-
|
|
62374
|
-
|
|
62375
|
-
|
|
62376
|
-
|
|
62377
|
-
|
|
62378
|
-
|
|
62372
|
+
// Shared median helper for the robust (outlier-tolerant) bounds below.
|
|
62373
|
+
median(values) {
|
|
62374
|
+
if (!values.length)
|
|
62375
|
+
return 0;
|
|
62376
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
62377
|
+
const mid = Math.floor(sorted.length / 2);
|
|
62378
|
+
return sorted.length % 2
|
|
62379
|
+
? sorted[mid]
|
|
62380
|
+
: (sorted[mid - 1] + sorted[mid]) / 2;
|
|
62381
|
+
}
|
|
62382
|
+
// Union bounds of the canvas objects with gross positional outliers removed.
|
|
62383
|
+
// A single element carrying a bad far coordinate — a CAD orphan wall stranded
|
|
62384
|
+
// at the origin, an unplaced fixture — would otherwise inflate the frame and
|
|
62385
|
+
// collapse the fit zoom to an invisible speck. We drop objects whose center
|
|
62386
|
+
// lies far outside the cluster (median center + a generous multiple of the
|
|
62387
|
+
// spread) and fit to what remains, so no single stray of ANY type (wall,
|
|
62388
|
+
// entrance, fixture, other) can hide the whole layout. Falls back to the full
|
|
62389
|
+
// union when there are too few objects to reason about statistically.
|
|
62390
|
+
getRobustLayoutBounds() {
|
|
62391
|
+
const entries = this.canvas
|
|
62379
62392
|
.getObjects()
|
|
62380
|
-
.
|
|
62381
|
-
|
|
62393
|
+
.map((o) => ({ o, r: o.getBoundingRect() }))
|
|
62394
|
+
.filter(({ r }) => Number.isFinite(r.left) &&
|
|
62395
|
+
Number.isFinite(r.top) &&
|
|
62396
|
+
Number.isFinite(r.width) &&
|
|
62397
|
+
Number.isFinite(r.height));
|
|
62398
|
+
if (!entries.length)
|
|
62382
62399
|
return { left: 0, top: 0, width: 0, height: 0 };
|
|
62383
|
-
|
|
62384
|
-
|
|
62385
|
-
const
|
|
62386
|
-
|
|
62387
|
-
|
|
62388
|
-
|
|
62389
|
-
|
|
62390
|
-
|
|
62391
|
-
|
|
62392
|
-
left: minX,
|
|
62393
|
-
top: minY,
|
|
62394
|
-
width: maxX - minX,
|
|
62395
|
-
height: maxY - minY,
|
|
62400
|
+
const union = (list) => {
|
|
62401
|
+
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
|
|
62402
|
+
for (const { r } of list) {
|
|
62403
|
+
minX = Math.min(minX, r.left);
|
|
62404
|
+
minY = Math.min(minY, r.top);
|
|
62405
|
+
maxX = Math.max(maxX, r.left + r.width);
|
|
62406
|
+
maxY = Math.max(maxY, r.top + r.height);
|
|
62407
|
+
}
|
|
62408
|
+
return { left: minX, top: minY, width: maxX - minX, height: maxY - minY };
|
|
62396
62409
|
};
|
|
62410
|
+
if (entries.length < 4)
|
|
62411
|
+
return union(entries);
|
|
62412
|
+
const cxs = entries.map(({ r }) => r.left + r.width / 2);
|
|
62413
|
+
const cys = entries.map(({ r }) => r.top + r.height / 2);
|
|
62414
|
+
const medX = this.median(cxs);
|
|
62415
|
+
const medY = this.median(cys);
|
|
62416
|
+
const dists = entries.map((_, i) => Math.hypot(cxs[i] - medX, cys[i] - medY));
|
|
62417
|
+
const medDist = this.median(dists);
|
|
62418
|
+
const mad = this.median(dists.map((d) => Math.abs(d - medDist)));
|
|
62419
|
+
const spread = mad > 1 ? mad : medDist > 1 ? medDist : 1;
|
|
62420
|
+
const threshold = medDist + 6 * spread;
|
|
62421
|
+
const kept = entries.filter((_, i) => dists[i] <= threshold);
|
|
62422
|
+
const dropped = entries.filter((_, i) => dists[i] > threshold);
|
|
62423
|
+
if (dropped.length) {
|
|
62424
|
+
console.warn(`[fit] ignoring ${dropped.length} out-of-cluster object(s) while fitting`, dropped.map(({ o, r }) => ({
|
|
62425
|
+
type: o?.objType,
|
|
62426
|
+
id: o?.fixtureId ?? o?.data?._id ?? o?.data?.elementNumber,
|
|
62427
|
+
bounds: r,
|
|
62428
|
+
})));
|
|
62429
|
+
}
|
|
62430
|
+
return kept.length ? union(kept) : union(entries);
|
|
62431
|
+
}
|
|
62432
|
+
// Wall start-points (px) with gross outliers removed. A CAD orphan wall far
|
|
62433
|
+
// from the store must not define the perimeter that reclaim places elements
|
|
62434
|
+
// into, so strip it the same way the fit does before building the polygon.
|
|
62435
|
+
getRobustWallPolygon() {
|
|
62436
|
+
const pts = (this.floorData?.layoutPolygon ?? [])
|
|
62437
|
+
.filter((w) => w?.elementType === "wall")
|
|
62438
|
+
.map((w) => ({
|
|
62439
|
+
x: this.toPixels(w.relativePosition?.x ?? 0, w.relativePosition?.unit || "ft"),
|
|
62440
|
+
y: this.toPixels(w.relativePosition?.y ?? 0, w.relativePosition?.unit || "ft"),
|
|
62441
|
+
}))
|
|
62442
|
+
.filter((p) => Number.isFinite(p.x) && Number.isFinite(p.y));
|
|
62443
|
+
if (pts.length < 4)
|
|
62444
|
+
return pts;
|
|
62445
|
+
const medX = this.median(pts.map((p) => p.x));
|
|
62446
|
+
const medY = this.median(pts.map((p) => p.y));
|
|
62447
|
+
const dists = pts.map((p) => Math.hypot(p.x - medX, p.y - medY));
|
|
62448
|
+
const medDist = this.median(dists);
|
|
62449
|
+
const mad = this.median(dists.map((d) => Math.abs(d - medDist)));
|
|
62450
|
+
const spread = mad > 1 ? mad : medDist > 1 ? medDist : 1;
|
|
62451
|
+
const threshold = medDist + 6 * spread;
|
|
62452
|
+
const kept = pts.filter((_, i) => dists[i] <= threshold);
|
|
62453
|
+
return kept.length >= 3 ? kept : pts;
|
|
62397
62454
|
}
|
|
62398
62455
|
// Reclaims elements whose stored position renders them outside the wall
|
|
62399
62456
|
// perimeter — the bad-coordinate artifacts a CAD import can leave behind.
|
|
@@ -62406,7 +62463,10 @@ class OnboardStorePlanoComponent {
|
|
|
62406
62463
|
const floor = this.floorData;
|
|
62407
62464
|
if (!floor?.layoutPolygon?.length)
|
|
62408
62465
|
return 0;
|
|
62409
|
-
|
|
62466
|
+
// Robust wall polygon so an orphan wall (bad coordinate) can't define the
|
|
62467
|
+
// perimeter — otherwise fixtures/other elements would all look "inside" the
|
|
62468
|
+
// inflated frame and never get reclaimed.
|
|
62469
|
+
const wallPolygon = this.getRobustWallPolygon();
|
|
62410
62470
|
if (wallPolygon.length < 3)
|
|
62411
62471
|
return 0;
|
|
62412
62472
|
const bounds = this.polygonBounds(wallPolygon);
|
|
@@ -62627,15 +62687,12 @@ class OnboardStorePlanoComponent {
|
|
|
62627
62687
|
return;
|
|
62628
62688
|
if (this.layoutForm.enabled)
|
|
62629
62689
|
return;
|
|
62630
|
-
// Fit to the
|
|
62631
|
-
// union of
|
|
62632
|
-
//
|
|
62633
|
-
//
|
|
62634
|
-
//
|
|
62635
|
-
const
|
|
62636
|
-
const bounds = perimeter.width && perimeter.height
|
|
62637
|
-
? perimeter
|
|
62638
|
-
: this.getFullLayoutBounds();
|
|
62690
|
+
// Fit to the cluster of objects with gross outliers removed, rather than the
|
|
62691
|
+
// union of everything. A single element with a bad far coordinate — e.g. a
|
|
62692
|
+
// CAD orphan wall stranded at the origin while the real store sits thousands
|
|
62693
|
+
// of feet away — would otherwise blow up the frame and collapse the zoom to
|
|
62694
|
+
// an invisible speck. getRobustLayoutBounds() drops such strays of any type.
|
|
62695
|
+
const bounds = this.getRobustLayoutBounds();
|
|
62639
62696
|
if (!bounds.width || !bounds.height)
|
|
62640
62697
|
return;
|
|
62641
62698
|
const canvasW = this.canvas.getWidth();
|
|
@@ -69087,6 +69144,7 @@ class FixtureConformanceComponent {
|
|
|
69087
69144
|
case 'ok': return 'Conforms';
|
|
69088
69145
|
case 'shelf-count-mismatch': return 'Shelf count mismatch';
|
|
69089
69146
|
case 'zone-mismatch': return 'Zone mismatch';
|
|
69147
|
+
case 'type-mismatch': return 'Shelf type mismatch';
|
|
69090
69148
|
case 'no-library': return 'No library match';
|
|
69091
69149
|
case 'ambiguous': return 'Ambiguous library';
|
|
69092
69150
|
case 'no-shelves': return 'No shelves';
|
|
@@ -69097,7 +69155,8 @@ class FixtureConformanceComponent {
|
|
|
69097
69155
|
switch (reason) {
|
|
69098
69156
|
case 'ok': return 'badge-ok';
|
|
69099
69157
|
case 'shelf-count-mismatch':
|
|
69100
|
-
case 'zone-mismatch':
|
|
69158
|
+
case 'zone-mismatch':
|
|
69159
|
+
case 'type-mismatch': return 'badge-warn';
|
|
69101
69160
|
case 'no-library':
|
|
69102
69161
|
case 'ambiguous':
|
|
69103
69162
|
case 'no-shelves': return 'badge-muted';
|
|
@@ -69114,11 +69173,11 @@ class FixtureConformanceComponent {
|
|
|
69114
69173
|
this.destroy$.complete();
|
|
69115
69174
|
}
|
|
69116
69175
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FixtureConformanceComponent, deps: [{ token: StoreBuilderService }, { token: i2$1.GlobalStateService }], target: i0.ɵɵFactoryTarget.Component });
|
|
69117
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: FixtureConformanceComponent, selector: "lib-fixture-conformance", ngImport: i0, template: "<section class=\"fixture-conformance p-3\">\n <lib-tool-page-header\n title=\"Sync Fixtures to Library\"\n description=\"Check a store's fixtures against the library, then sync shelf count and zones for the ones that don't match.\"\n ></lib-tool-page-header>\n\n <div class=\"card p-4\">\n <!-- Store Select -->\n <div class=\"mb-3\" style=\"max-width: 600px;\">\n <label class=\"form-label\">Store</label>\n <lib-store-select\n [options]=\"storeOptions\"\n [singleSelect]=\"true\"\n (selectedChange)=\"onStoresSelected($event)\">\n </lib-store-select>\n </div>\n\n <!-- Fixture List -->\n @if (selectedStoreName) {\n @if (isLoadingFixtures) {\n <div class=\"text-muted\">Loading fixtures...</div>\n } @else if (fixtures.length === 0) {\n <div class=\"text-muted\">No fixtures found for this store.</div>\n } @else {\n <div class=\"d-flex align-items-center justify-content-between mb-2\">\n <h6 class=\"section-heading mb-0\">\n Fixtures\n <span class=\"text-muted small\">({{ selectedFixtureIds.length }} of {{ fixtures.length }} selected)</span>\n </h6>\n <button\n class=\"btn btn-primary btn-sm\"\n (click)=\"onAudit()\"\n [disabled]=\"selectedFixtureIds.length === 0 || isAuditing\">\n {{ isAuditing ? 'Auditing...' : 'Audit Selected' }}\n </button>\n </div>\n\n <div class=\"table-responsive mb-2\">\n <table class=\"table table-sm align-middle fc-table\">\n <thead>\n <tr>\n <th style=\"width: 42px;\">\n <input type=\"checkbox\"\n [checked]=\"allFixturesSelected\"\n (change)=\"toggleAllFixtures($any($event.target).checked)\">\n </th>\n <th style=\"width: 90px;\">Fixture #</th>\n <th>Header</th>\n <th>Fixture ID</th>\n <th>Category</th>\n <th style=\"width: 90px;\">Width</th>\n </tr>\n </thead>\n <tbody>\n @for (f of fixtures; track f._id) {\n <tr (click)=\"f.selected = !f.selected\" class=\"selectable-row\">\n <td (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" [(ngModel)]=\"f.selected\">\n </td>\n <td>{{ f.fixtureNumber ?? '\u2014' }}</td>\n <td>{{ f.headerLabel || '\u2014' }}</td>\n <td class=\"fixture-id\">{{ f._id }}</td>\n <td>{{ f.fixtureCategory || '\u2014' }}</td>\n <td>{{ f.width || '\u2014' }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n\n <!-- Audit Results -->\n @if (hasAudited) {\n <hr class=\"my-4\" />\n <div class=\"d-flex align-items-center justify-content-between mb-2\">\n <h6 class=\"section-heading mb-0\">\n Audit Result\n <span class=\"text-muted small\">({{ fixableRows.length }} fixable, {{ selectedAuditIds.length }} selected)</span>\n </h6>\n <button\n class=\"btn btn-success btn-sm\"\n (click)=\"onApplyFix()\"\n [disabled]=\"selectedAuditIds.length === 0 || isApplying\">\n {{ isApplying ? 'Applying...' : 'Apply Fix' }}\n </button>\n </div>\n\n @if (auditRows.length === 0) {\n <div class=\"text-muted\">No results.</div>\n } @else {\n <div class=\"table-responsive\">\n <table class=\"table table-sm align-middle fc-table\">\n <thead>\n <tr>\n <th style=\"width: 42px;\">\n <input type=\"checkbox\"\n [checked]=\"allFixableSelected\"\n [disabled]=\"fixableRows.length === 0\"\n (change)=\"toggleAllFixable($any($event.target).checked)\">\n </th>\n <th style=\"width: 90px;\">Fixture #</th>\n <th>Header</th>\n <th>Category</th>\n <th style=\"width: 70px;\">Width</th>\n <th style=\"width: 110px;\">Shelves</th>\n <th>Current Zones</th>\n <th>Library Zones</th>\n <th style=\"width: 160px;\">Status</th>\n </tr>\n </thead>\n <tbody>\n @for (r of auditRows; track r.fixtureId) {\n <tr [class.row-fixable]=\"r.fixable\">\n <td>\n <input type=\"checkbox\" [(ngModel)]=\"r.selected\" [disabled]=\"!r.fixable\">\n </td>\n <td>{{ r.fixtureNumber ?? '\u2014' }}</td>\n <td>{{ r.header || '\u2014' }}</td>\n <td>{{ r.category || '\u2014' }}</td>\n <td>{{ r.width || '\u2014' }}</td>\n <td>\n @if (r.libShelfCount != null) {\n <span [class.text-danger]=\"r.curShelfCount !== r.libShelfCount\">\n {{ r.curShelfCount }} \u2192 {{ r.libShelfCount }}\n </span>\n } @else {\n {{ r.curShelfCount }}\n }\n </td>\n <td class=\"zones\">{{ r.currentZones || '\u2014' }}</td>\n <td class=\"zones\">{{ r.libZones || '\u2014' }}</td>\n <td>\n <span class=\"status-badge\" [ngClass]=\"reasonClass(r.reason)\">\n {{ reasonLabel(r.reason) }}\n </span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n\n <!-- Apply summary per fixture -->\n @if (applyResults.length > 0) {\n <hr class=\"my-4\" />\n <h6 class=\"section-heading mb-2\">Apply Summary</h6>\n <div class=\"table-responsive\">\n <table class=\"table table-sm align-middle fc-table\">\n <thead>\n <tr>\n <th style=\"width: 90px;\">Fixture #</th>\n <th style=\"width: 140px;\">Status</th>\n <th>Shelves</th>\n <th>Compliance Synced</th>\n <th>Note</th>\n </tr>\n </thead>\n <tbody>\n @for (ar of applyResults; track ar.fixtureId) {\n <tr>\n <td>{{ ar.fixtureNumber ?? '\u2014' }}</td>\n <td>\n <span class=\"status-badge\"\n [class.badge-ok]=\"ar.status === 'fixed' || ar.status === 'already-conform'\"\n [class.badge-warn]=\"ar.status === 'skipped'\"\n [class.badge-danger]=\"ar.status === 'failed'\">\n {{ ar.status }}\n </span>\n </td>\n <td>\n @if (ar.shelvesFrom != null) {\n {{ ar.shelvesFrom }} \u2192 {{ ar.shelvesTo }}\n } @else { \u2014 }\n </td>\n <td>{{ ar.complianceSynced ?? 0 }}</td>\n <td class=\"text-muted small\">{{ ar.error || ar.reason || '' }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n <!-- Message -->\n @if (message) {\n <div class=\"mt-3 alert\" [class.alert-success]=\"messageType === 'success'\"\n [class.alert-danger]=\"messageType === 'error'\">\n {{ message }}\n </div>\n }\n </div>\n</section>\n", styles: [".fixture-conformance .section-heading{color:#344054;font-weight:600}.fixture-conformance .fc-table th{background-color:#f9fafb;font-weight:600;font-size:13px;color:#475467;white-space:nowrap}.fixture-conformance .fc-table td{font-size:13px;vertical-align:middle}.fixture-conformance .fc-table .zones{font-family:Courier New,monospace;font-size:12px;color:#475467;word-break:break-word}.fixture-conformance .fc-table .fixture-id{font-family:Courier New,monospace;font-size:12px;color:#667085}.fixture-conformance .fc-table .selectable-row{cursor:pointer}.fixture-conformance .fc-table .selectable-row:hover{background-color:#f9fafb}.fixture-conformance .fc-table .row-fixable{background-color:#fffaf0}.fixture-conformance .status-badge{display:inline-block;padding:2px 10px;border-radius:12px;font-size:12px;font-weight:600;white-space:nowrap}.fixture-conformance .status-badge.badge-ok{background-color:#ecfdf3;color:#027a48}.fixture-conformance .status-badge.badge-warn{background-color:#fffaeb;color:#b54708}.fixture-conformance .status-badge.badge-muted{background-color:#f2f4f7;color:#475467}.fixture-conformance .status-badge.badge-danger{background-color:#fef3f2;color:#b42318}\n"], dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: StoreSelectComponent, selector: "lib-store-select", inputs: ["options", "initialSelected", "singleSelect"], outputs: ["selectedChange"] }, { kind: "component", type: ToolPageHeaderComponent, selector: "lib-tool-page-header", inputs: ["title", "description", "backLink"] }] });
|
|
69176
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: FixtureConformanceComponent, selector: "lib-fixture-conformance", ngImport: i0, template: "<section class=\"fixture-conformance p-3\">\n <lib-tool-page-header\n title=\"Sync Fixtures to Library\"\n description=\"Check a store's fixtures against the library, then sync shelf count and zones for the ones that don't match.\"\n ></lib-tool-page-header>\n\n <div class=\"card p-4\">\n <!-- Store Select -->\n <div class=\"mb-3\" style=\"max-width: 600px;\">\n <label class=\"form-label\">Store</label>\n <lib-store-select\n [options]=\"storeOptions\"\n [singleSelect]=\"true\"\n (selectedChange)=\"onStoresSelected($event)\">\n </lib-store-select>\n </div>\n\n <!-- Fixture List -->\n @if (selectedStoreName) {\n @if (isLoadingFixtures) {\n <div class=\"text-muted\">Loading fixtures...</div>\n } @else if (fixtures.length === 0) {\n <div class=\"text-muted\">No fixtures found for this store.</div>\n } @else {\n <div class=\"d-flex align-items-center justify-content-between mb-2\">\n <h6 class=\"section-heading mb-0\">\n Fixtures\n <span class=\"text-muted small\">({{ selectedFixtureIds.length }} of {{ fixtures.length }} selected)</span>\n </h6>\n <button\n class=\"btn btn-primary btn-sm\"\n (click)=\"onAudit()\"\n [disabled]=\"selectedFixtureIds.length === 0 || isAuditing\">\n {{ isAuditing ? 'Auditing...' : 'Audit Selected' }}\n </button>\n </div>\n\n <div class=\"table-responsive mb-2\">\n <table class=\"table table-sm align-middle fc-table\">\n <thead>\n <tr>\n <th style=\"width: 42px;\">\n <input type=\"checkbox\"\n [checked]=\"allFixturesSelected\"\n (change)=\"toggleAllFixtures($any($event.target).checked)\">\n </th>\n <th style=\"width: 90px;\">Fixture #</th>\n <th>Header</th>\n <th>Fixture ID</th>\n <th>Category</th>\n <th style=\"width: 90px;\">Width</th>\n </tr>\n </thead>\n <tbody>\n @for (f of fixtures; track f._id) {\n <tr (click)=\"f.selected = !f.selected\" class=\"selectable-row\">\n <td (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" [(ngModel)]=\"f.selected\">\n </td>\n <td>{{ f.fixtureNumber ?? '\u2014' }}</td>\n <td>{{ f.headerLabel || '\u2014' }}</td>\n <td class=\"fixture-id\">{{ f._id }}</td>\n <td>{{ f.fixtureCategory || '\u2014' }}</td>\n <td>{{ f.width || '\u2014' }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n\n <!-- Audit Results -->\n @if (hasAudited) {\n <hr class=\"my-4\" />\n <div class=\"d-flex align-items-center justify-content-between mb-2\">\n <h6 class=\"section-heading mb-0\">\n Audit Result\n <span class=\"text-muted small\">({{ fixableRows.length }} fixable, {{ selectedAuditIds.length }} selected)</span>\n </h6>\n <button\n class=\"btn btn-success btn-sm\"\n (click)=\"onApplyFix()\"\n [disabled]=\"selectedAuditIds.length === 0 || isApplying\">\n {{ isApplying ? 'Applying...' : 'Apply Fix' }}\n </button>\n </div>\n\n @if (auditRows.length === 0) {\n <div class=\"text-muted\">No results.</div>\n } @else {\n <div class=\"table-responsive\">\n <table class=\"table table-sm align-middle fc-table\">\n <thead>\n <tr>\n <th style=\"width: 42px;\">\n <input type=\"checkbox\"\n [checked]=\"allFixableSelected\"\n [disabled]=\"fixableRows.length === 0\"\n (change)=\"toggleAllFixable($any($event.target).checked)\">\n </th>\n <th style=\"width: 90px;\">Fixture #</th>\n <th>Header</th>\n <th>Category</th>\n <th style=\"width: 70px;\">Width</th>\n <th style=\"width: 110px;\">Shelves</th>\n <th>Current Zones</th>\n <th>Library Zones</th>\n <th>Current Types</th>\n <th>Library Types</th>\n <th style=\"width: 160px;\">Status</th>\n </tr>\n </thead>\n <tbody>\n @for (r of auditRows; track r.fixtureId) {\n <tr [class.row-fixable]=\"r.fixable\">\n <td>\n <input type=\"checkbox\" [(ngModel)]=\"r.selected\" [disabled]=\"!r.fixable\">\n </td>\n <td>{{ r.fixtureNumber ?? '\u2014' }}</td>\n <td>{{ r.header || '\u2014' }}</td>\n <td>{{ r.category || '\u2014' }}</td>\n <td>{{ r.width || '\u2014' }}</td>\n <td>\n @if (r.libShelfCount != null) {\n <span [class.text-danger]=\"r.curShelfCount !== r.libShelfCount\">\n {{ r.curShelfCount }} \u2192 {{ r.libShelfCount }}\n </span>\n } @else {\n {{ r.curShelfCount }}\n }\n </td>\n <td class=\"zones\">{{ r.currentZones || '\u2014' }}</td>\n <td class=\"zones\">{{ r.libZones || '\u2014' }}</td>\n <td class=\"zones\" [class.text-danger]=\"r.reason === 'type-mismatch'\">{{ r.currentTypes || '\u2014' }}</td>\n <td class=\"zones\">{{ r.libTypes || '\u2014' }}</td>\n <td>\n <span class=\"status-badge\" [ngClass]=\"reasonClass(r.reason)\">\n {{ reasonLabel(r.reason) }}\n </span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n\n <!-- Apply summary per fixture -->\n @if (applyResults.length > 0) {\n <hr class=\"my-4\" />\n <h6 class=\"section-heading mb-2\">Apply Summary</h6>\n <div class=\"table-responsive\">\n <table class=\"table table-sm align-middle fc-table\">\n <thead>\n <tr>\n <th style=\"width: 90px;\">Fixture #</th>\n <th style=\"width: 140px;\">Status</th>\n <th>Shelves</th>\n <th>Compliance Synced</th>\n <th>Note</th>\n </tr>\n </thead>\n <tbody>\n @for (ar of applyResults; track ar.fixtureId) {\n <tr>\n <td>{{ ar.fixtureNumber ?? '\u2014' }}</td>\n <td>\n <span class=\"status-badge\"\n [class.badge-ok]=\"ar.status === 'fixed' || ar.status === 'already-conform'\"\n [class.badge-warn]=\"ar.status === 'skipped'\"\n [class.badge-danger]=\"ar.status === 'failed'\">\n {{ ar.status }}\n </span>\n </td>\n <td>\n @if (ar.shelvesFrom != null) {\n {{ ar.shelvesFrom }} \u2192 {{ ar.shelvesTo }}\n } @else { \u2014 }\n </td>\n <td>{{ ar.complianceSynced ?? 0 }}</td>\n <td class=\"text-muted small\">{{ ar.error || ar.reason || '' }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n <!-- Message -->\n @if (message) {\n <div class=\"mt-3 alert\" [class.alert-success]=\"messageType === 'success'\"\n [class.alert-danger]=\"messageType === 'error'\">\n {{ message }}\n </div>\n }\n </div>\n</section>\n", styles: [".fixture-conformance .section-heading{color:#344054;font-weight:600}.fixture-conformance .fc-table th{background-color:#f9fafb;font-weight:600;font-size:13px;color:#475467;white-space:nowrap}.fixture-conformance .fc-table td{font-size:13px;vertical-align:middle}.fixture-conformance .fc-table .zones{font-family:Courier New,monospace;font-size:12px;color:#475467;word-break:break-word}.fixture-conformance .fc-table .fixture-id{font-family:Courier New,monospace;font-size:12px;color:#667085}.fixture-conformance .fc-table .selectable-row{cursor:pointer}.fixture-conformance .fc-table .selectable-row:hover{background-color:#f9fafb}.fixture-conformance .fc-table .row-fixable{background-color:#fffaf0}.fixture-conformance .status-badge{display:inline-block;padding:2px 10px;border-radius:12px;font-size:12px;font-weight:600;white-space:nowrap}.fixture-conformance .status-badge.badge-ok{background-color:#ecfdf3;color:#027a48}.fixture-conformance .status-badge.badge-warn{background-color:#fffaeb;color:#b54708}.fixture-conformance .status-badge.badge-muted{background-color:#f2f4f7;color:#475467}.fixture-conformance .status-badge.badge-danger{background-color:#fef3f2;color:#b42318}\n"], dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: StoreSelectComponent, selector: "lib-store-select", inputs: ["options", "initialSelected", "singleSelect"], outputs: ["selectedChange"] }, { kind: "component", type: ToolPageHeaderComponent, selector: "lib-tool-page-header", inputs: ["title", "description", "backLink"] }] });
|
|
69118
69177
|
}
|
|
69119
69178
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: FixtureConformanceComponent, decorators: [{
|
|
69120
69179
|
type: Component,
|
|
69121
|
-
args: [{ selector: 'lib-fixture-conformance', template: "<section class=\"fixture-conformance p-3\">\n <lib-tool-page-header\n title=\"Sync Fixtures to Library\"\n description=\"Check a store's fixtures against the library, then sync shelf count and zones for the ones that don't match.\"\n ></lib-tool-page-header>\n\n <div class=\"card p-4\">\n <!-- Store Select -->\n <div class=\"mb-3\" style=\"max-width: 600px;\">\n <label class=\"form-label\">Store</label>\n <lib-store-select\n [options]=\"storeOptions\"\n [singleSelect]=\"true\"\n (selectedChange)=\"onStoresSelected($event)\">\n </lib-store-select>\n </div>\n\n <!-- Fixture List -->\n @if (selectedStoreName) {\n @if (isLoadingFixtures) {\n <div class=\"text-muted\">Loading fixtures...</div>\n } @else if (fixtures.length === 0) {\n <div class=\"text-muted\">No fixtures found for this store.</div>\n } @else {\n <div class=\"d-flex align-items-center justify-content-between mb-2\">\n <h6 class=\"section-heading mb-0\">\n Fixtures\n <span class=\"text-muted small\">({{ selectedFixtureIds.length }} of {{ fixtures.length }} selected)</span>\n </h6>\n <button\n class=\"btn btn-primary btn-sm\"\n (click)=\"onAudit()\"\n [disabled]=\"selectedFixtureIds.length === 0 || isAuditing\">\n {{ isAuditing ? 'Auditing...' : 'Audit Selected' }}\n </button>\n </div>\n\n <div class=\"table-responsive mb-2\">\n <table class=\"table table-sm align-middle fc-table\">\n <thead>\n <tr>\n <th style=\"width: 42px;\">\n <input type=\"checkbox\"\n [checked]=\"allFixturesSelected\"\n (change)=\"toggleAllFixtures($any($event.target).checked)\">\n </th>\n <th style=\"width: 90px;\">Fixture #</th>\n <th>Header</th>\n <th>Fixture ID</th>\n <th>Category</th>\n <th style=\"width: 90px;\">Width</th>\n </tr>\n </thead>\n <tbody>\n @for (f of fixtures; track f._id) {\n <tr (click)=\"f.selected = !f.selected\" class=\"selectable-row\">\n <td (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" [(ngModel)]=\"f.selected\">\n </td>\n <td>{{ f.fixtureNumber ?? '\u2014' }}</td>\n <td>{{ f.headerLabel || '\u2014' }}</td>\n <td class=\"fixture-id\">{{ f._id }}</td>\n <td>{{ f.fixtureCategory || '\u2014' }}</td>\n <td>{{ f.width || '\u2014' }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n\n <!-- Audit Results -->\n @if (hasAudited) {\n <hr class=\"my-4\" />\n <div class=\"d-flex align-items-center justify-content-between mb-2\">\n <h6 class=\"section-heading mb-0\">\n Audit Result\n <span class=\"text-muted small\">({{ fixableRows.length }} fixable, {{ selectedAuditIds.length }} selected)</span>\n </h6>\n <button\n class=\"btn btn-success btn-sm\"\n (click)=\"onApplyFix()\"\n [disabled]=\"selectedAuditIds.length === 0 || isApplying\">\n {{ isApplying ? 'Applying...' : 'Apply Fix' }}\n </button>\n </div>\n\n @if (auditRows.length === 0) {\n <div class=\"text-muted\">No results.</div>\n } @else {\n <div class=\"table-responsive\">\n <table class=\"table table-sm align-middle fc-table\">\n <thead>\n <tr>\n <th style=\"width: 42px;\">\n <input type=\"checkbox\"\n [checked]=\"allFixableSelected\"\n [disabled]=\"fixableRows.length === 0\"\n (change)=\"toggleAllFixable($any($event.target).checked)\">\n </th>\n <th style=\"width: 90px;\">Fixture #</th>\n <th>Header</th>\n <th>Category</th>\n <th style=\"width: 70px;\">Width</th>\n <th style=\"width: 110px;\">Shelves</th>\n <th>Current Zones</th>\n <th>Library Zones</th>\n <th style=\"width: 160px;\">Status</th>\n </tr>\n </thead>\n <tbody>\n @for (r of auditRows; track r.fixtureId) {\n <tr [class.row-fixable]=\"r.fixable\">\n <td>\n <input type=\"checkbox\" [(ngModel)]=\"r.selected\" [disabled]=\"!r.fixable\">\n </td>\n <td>{{ r.fixtureNumber ?? '\u2014' }}</td>\n <td>{{ r.header || '\u2014' }}</td>\n <td>{{ r.category || '\u2014' }}</td>\n <td>{{ r.width || '\u2014' }}</td>\n <td>\n @if (r.libShelfCount != null) {\n <span [class.text-danger]=\"r.curShelfCount !== r.libShelfCount\">\n {{ r.curShelfCount }} \u2192 {{ r.libShelfCount }}\n </span>\n } @else {\n {{ r.curShelfCount }}\n }\n </td>\n <td class=\"zones\">{{ r.currentZones || '\u2014' }}</td>\n <td class=\"zones\">{{ r.libZones || '\u2014' }}</td>\n <td>\n <span class=\"status-badge\" [ngClass]=\"reasonClass(r.reason)\">\n {{ reasonLabel(r.reason) }}\n </span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n\n <!-- Apply summary per fixture -->\n @if (applyResults.length > 0) {\n <hr class=\"my-4\" />\n <h6 class=\"section-heading mb-2\">Apply Summary</h6>\n <div class=\"table-responsive\">\n <table class=\"table table-sm align-middle fc-table\">\n <thead>\n <tr>\n <th style=\"width: 90px;\">Fixture #</th>\n <th style=\"width: 140px;\">Status</th>\n <th>Shelves</th>\n <th>Compliance Synced</th>\n <th>Note</th>\n </tr>\n </thead>\n <tbody>\n @for (ar of applyResults; track ar.fixtureId) {\n <tr>\n <td>{{ ar.fixtureNumber ?? '\u2014' }}</td>\n <td>\n <span class=\"status-badge\"\n [class.badge-ok]=\"ar.status === 'fixed' || ar.status === 'already-conform'\"\n [class.badge-warn]=\"ar.status === 'skipped'\"\n [class.badge-danger]=\"ar.status === 'failed'\">\n {{ ar.status }}\n </span>\n </td>\n <td>\n @if (ar.shelvesFrom != null) {\n {{ ar.shelvesFrom }} \u2192 {{ ar.shelvesTo }}\n } @else { \u2014 }\n </td>\n <td>{{ ar.complianceSynced ?? 0 }}</td>\n <td class=\"text-muted small\">{{ ar.error || ar.reason || '' }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n <!-- Message -->\n @if (message) {\n <div class=\"mt-3 alert\" [class.alert-success]=\"messageType === 'success'\"\n [class.alert-danger]=\"messageType === 'error'\">\n {{ message }}\n </div>\n }\n </div>\n</section>\n", styles: [".fixture-conformance .section-heading{color:#344054;font-weight:600}.fixture-conformance .fc-table th{background-color:#f9fafb;font-weight:600;font-size:13px;color:#475467;white-space:nowrap}.fixture-conformance .fc-table td{font-size:13px;vertical-align:middle}.fixture-conformance .fc-table .zones{font-family:Courier New,monospace;font-size:12px;color:#475467;word-break:break-word}.fixture-conformance .fc-table .fixture-id{font-family:Courier New,monospace;font-size:12px;color:#667085}.fixture-conformance .fc-table .selectable-row{cursor:pointer}.fixture-conformance .fc-table .selectable-row:hover{background-color:#f9fafb}.fixture-conformance .fc-table .row-fixable{background-color:#fffaf0}.fixture-conformance .status-badge{display:inline-block;padding:2px 10px;border-radius:12px;font-size:12px;font-weight:600;white-space:nowrap}.fixture-conformance .status-badge.badge-ok{background-color:#ecfdf3;color:#027a48}.fixture-conformance .status-badge.badge-warn{background-color:#fffaeb;color:#b54708}.fixture-conformance .status-badge.badge-muted{background-color:#f2f4f7;color:#475467}.fixture-conformance .status-badge.badge-danger{background-color:#fef3f2;color:#b42318}\n"] }]
|
|
69180
|
+
args: [{ selector: 'lib-fixture-conformance', template: "<section class=\"fixture-conformance p-3\">\n <lib-tool-page-header\n title=\"Sync Fixtures to Library\"\n description=\"Check a store's fixtures against the library, then sync shelf count and zones for the ones that don't match.\"\n ></lib-tool-page-header>\n\n <div class=\"card p-4\">\n <!-- Store Select -->\n <div class=\"mb-3\" style=\"max-width: 600px;\">\n <label class=\"form-label\">Store</label>\n <lib-store-select\n [options]=\"storeOptions\"\n [singleSelect]=\"true\"\n (selectedChange)=\"onStoresSelected($event)\">\n </lib-store-select>\n </div>\n\n <!-- Fixture List -->\n @if (selectedStoreName) {\n @if (isLoadingFixtures) {\n <div class=\"text-muted\">Loading fixtures...</div>\n } @else if (fixtures.length === 0) {\n <div class=\"text-muted\">No fixtures found for this store.</div>\n } @else {\n <div class=\"d-flex align-items-center justify-content-between mb-2\">\n <h6 class=\"section-heading mb-0\">\n Fixtures\n <span class=\"text-muted small\">({{ selectedFixtureIds.length }} of {{ fixtures.length }} selected)</span>\n </h6>\n <button\n class=\"btn btn-primary btn-sm\"\n (click)=\"onAudit()\"\n [disabled]=\"selectedFixtureIds.length === 0 || isAuditing\">\n {{ isAuditing ? 'Auditing...' : 'Audit Selected' }}\n </button>\n </div>\n\n <div class=\"table-responsive mb-2\">\n <table class=\"table table-sm align-middle fc-table\">\n <thead>\n <tr>\n <th style=\"width: 42px;\">\n <input type=\"checkbox\"\n [checked]=\"allFixturesSelected\"\n (change)=\"toggleAllFixtures($any($event.target).checked)\">\n </th>\n <th style=\"width: 90px;\">Fixture #</th>\n <th>Header</th>\n <th>Fixture ID</th>\n <th>Category</th>\n <th style=\"width: 90px;\">Width</th>\n </tr>\n </thead>\n <tbody>\n @for (f of fixtures; track f._id) {\n <tr (click)=\"f.selected = !f.selected\" class=\"selectable-row\">\n <td (click)=\"$event.stopPropagation()\">\n <input type=\"checkbox\" [(ngModel)]=\"f.selected\">\n </td>\n <td>{{ f.fixtureNumber ?? '\u2014' }}</td>\n <td>{{ f.headerLabel || '\u2014' }}</td>\n <td class=\"fixture-id\">{{ f._id }}</td>\n <td>{{ f.fixtureCategory || '\u2014' }}</td>\n <td>{{ f.width || '\u2014' }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n\n <!-- Audit Results -->\n @if (hasAudited) {\n <hr class=\"my-4\" />\n <div class=\"d-flex align-items-center justify-content-between mb-2\">\n <h6 class=\"section-heading mb-0\">\n Audit Result\n <span class=\"text-muted small\">({{ fixableRows.length }} fixable, {{ selectedAuditIds.length }} selected)</span>\n </h6>\n <button\n class=\"btn btn-success btn-sm\"\n (click)=\"onApplyFix()\"\n [disabled]=\"selectedAuditIds.length === 0 || isApplying\">\n {{ isApplying ? 'Applying...' : 'Apply Fix' }}\n </button>\n </div>\n\n @if (auditRows.length === 0) {\n <div class=\"text-muted\">No results.</div>\n } @else {\n <div class=\"table-responsive\">\n <table class=\"table table-sm align-middle fc-table\">\n <thead>\n <tr>\n <th style=\"width: 42px;\">\n <input type=\"checkbox\"\n [checked]=\"allFixableSelected\"\n [disabled]=\"fixableRows.length === 0\"\n (change)=\"toggleAllFixable($any($event.target).checked)\">\n </th>\n <th style=\"width: 90px;\">Fixture #</th>\n <th>Header</th>\n <th>Category</th>\n <th style=\"width: 70px;\">Width</th>\n <th style=\"width: 110px;\">Shelves</th>\n <th>Current Zones</th>\n <th>Library Zones</th>\n <th>Current Types</th>\n <th>Library Types</th>\n <th style=\"width: 160px;\">Status</th>\n </tr>\n </thead>\n <tbody>\n @for (r of auditRows; track r.fixtureId) {\n <tr [class.row-fixable]=\"r.fixable\">\n <td>\n <input type=\"checkbox\" [(ngModel)]=\"r.selected\" [disabled]=\"!r.fixable\">\n </td>\n <td>{{ r.fixtureNumber ?? '\u2014' }}</td>\n <td>{{ r.header || '\u2014' }}</td>\n <td>{{ r.category || '\u2014' }}</td>\n <td>{{ r.width || '\u2014' }}</td>\n <td>\n @if (r.libShelfCount != null) {\n <span [class.text-danger]=\"r.curShelfCount !== r.libShelfCount\">\n {{ r.curShelfCount }} \u2192 {{ r.libShelfCount }}\n </span>\n } @else {\n {{ r.curShelfCount }}\n }\n </td>\n <td class=\"zones\">{{ r.currentZones || '\u2014' }}</td>\n <td class=\"zones\">{{ r.libZones || '\u2014' }}</td>\n <td class=\"zones\" [class.text-danger]=\"r.reason === 'type-mismatch'\">{{ r.currentTypes || '\u2014' }}</td>\n <td class=\"zones\">{{ r.libTypes || '\u2014' }}</td>\n <td>\n <span class=\"status-badge\" [ngClass]=\"reasonClass(r.reason)\">\n {{ reasonLabel(r.reason) }}\n </span>\n </td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n }\n\n <!-- Apply summary per fixture -->\n @if (applyResults.length > 0) {\n <hr class=\"my-4\" />\n <h6 class=\"section-heading mb-2\">Apply Summary</h6>\n <div class=\"table-responsive\">\n <table class=\"table table-sm align-middle fc-table\">\n <thead>\n <tr>\n <th style=\"width: 90px;\">Fixture #</th>\n <th style=\"width: 140px;\">Status</th>\n <th>Shelves</th>\n <th>Compliance Synced</th>\n <th>Note</th>\n </tr>\n </thead>\n <tbody>\n @for (ar of applyResults; track ar.fixtureId) {\n <tr>\n <td>{{ ar.fixtureNumber ?? '\u2014' }}</td>\n <td>\n <span class=\"status-badge\"\n [class.badge-ok]=\"ar.status === 'fixed' || ar.status === 'already-conform'\"\n [class.badge-warn]=\"ar.status === 'skipped'\"\n [class.badge-danger]=\"ar.status === 'failed'\">\n {{ ar.status }}\n </span>\n </td>\n <td>\n @if (ar.shelvesFrom != null) {\n {{ ar.shelvesFrom }} \u2192 {{ ar.shelvesTo }}\n } @else { \u2014 }\n </td>\n <td>{{ ar.complianceSynced ?? 0 }}</td>\n <td class=\"text-muted small\">{{ ar.error || ar.reason || '' }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n }\n\n <!-- Message -->\n @if (message) {\n <div class=\"mt-3 alert\" [class.alert-success]=\"messageType === 'success'\"\n [class.alert-danger]=\"messageType === 'error'\">\n {{ message }}\n </div>\n }\n </div>\n</section>\n", styles: [".fixture-conformance .section-heading{color:#344054;font-weight:600}.fixture-conformance .fc-table th{background-color:#f9fafb;font-weight:600;font-size:13px;color:#475467;white-space:nowrap}.fixture-conformance .fc-table td{font-size:13px;vertical-align:middle}.fixture-conformance .fc-table .zones{font-family:Courier New,monospace;font-size:12px;color:#475467;word-break:break-word}.fixture-conformance .fc-table .fixture-id{font-family:Courier New,monospace;font-size:12px;color:#667085}.fixture-conformance .fc-table .selectable-row{cursor:pointer}.fixture-conformance .fc-table .selectable-row:hover{background-color:#f9fafb}.fixture-conformance .fc-table .row-fixable{background-color:#fffaf0}.fixture-conformance .status-badge{display:inline-block;padding:2px 10px;border-radius:12px;font-size:12px;font-weight:600;white-space:nowrap}.fixture-conformance .status-badge.badge-ok{background-color:#ecfdf3;color:#027a48}.fixture-conformance .status-badge.badge-warn{background-color:#fffaeb;color:#b54708}.fixture-conformance .status-badge.badge-muted{background-color:#f2f4f7;color:#475467}.fixture-conformance .status-badge.badge-danger{background-color:#fef3f2;color:#b42318}\n"] }]
|
|
69122
69181
|
}], ctorParameters: () => [{ type: StoreBuilderService }, { type: i2$1.GlobalStateService }] });
|
|
69123
69182
|
|
|
69124
69183
|
class SwapTemplateComponent {
|
|
@@ -80271,4 +80330,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
80271
80330
|
*/
|
|
80272
80331
|
|
|
80273
80332
|
export { StoreBuilderService as S, TangoStoreBuilderModule as T, TangoStorePlanoModule as a };
|
|
80274
|
-
//# sourceMappingURL=tango-app-ui-store-builder-tango-app-ui-store-builder-
|
|
80333
|
+
//# sourceMappingURL=tango-app-ui-store-builder-tango-app-ui-store-builder-CXw6OsFW.mjs.map
|