@cqa-lib/cqa-ui 1.1.512 → 1.1.514
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/esm2020/lib/compare-runs/compare-runs.component.mjs +147 -37
- package/esm2020/lib/compare-runs/view-compare-button.component.mjs +18 -9
- package/esm2020/lib/table/dynamic-table/dynamic-table.component.mjs +33 -5
- package/fesm2015/cqa-lib-cqa-ui.mjs +193 -47
- package/fesm2015/cqa-lib-cqa-ui.mjs.map +1 -1
- package/fesm2020/cqa-lib-cqa-ui.mjs +193 -47
- package/fesm2020/cqa-lib-cqa-ui.mjs.map +1 -1
- package/lib/compare-runs/compare-runs.component.d.ts +23 -0
- package/lib/compare-runs/view-compare-button.component.d.ts +3 -1
- package/lib/table/dynamic-table/dynamic-table.component.d.ts +11 -0
- package/package.json +1 -1
- package/styles.css +1 -1
|
@@ -1192,6 +1192,15 @@ class DynamicTableComponent {
|
|
|
1192
1192
|
this.computedData = [];
|
|
1193
1193
|
this.computedGridTemplate = '';
|
|
1194
1194
|
this.computedColumnWidths = [];
|
|
1195
|
+
/**
|
|
1196
|
+
* Hard floor on the `<table>` width = sum of every visible column's minimum (fixed
|
|
1197
|
+
* widths + dynamic columns' `minWidth`). With `table-layout: fixed; width: 100%;` set
|
|
1198
|
+
* by consumers, `<col>` widths become advisory once the container is narrower than
|
|
1199
|
+
* the column-width sum — the browser silently shrinks them. Pinning `min-width` on
|
|
1200
|
+
* the table itself prevents that compaction; the consumer's `overflow-x: auto`
|
|
1201
|
+
* wrapper then scrolls horizontally instead of squishing columns to zero width.
|
|
1202
|
+
*/
|
|
1203
|
+
this.computedTableMinWidth = 0;
|
|
1195
1204
|
// Cache for sanitized HTML to avoid redundant innerHTML renders
|
|
1196
1205
|
this.htmlCache = new Map();
|
|
1197
1206
|
this._sortDirection = null;
|
|
@@ -1444,13 +1453,32 @@ class DynamicTableComponent {
|
|
|
1444
1453
|
const fixedPx = cols.reduce((sum, c) => sum + (c.fixedPx || 0), 0);
|
|
1445
1454
|
const dynamicCols = cols.filter(c => !c.fixedPx);
|
|
1446
1455
|
const totalWeight = dynamicCols.reduce((sum, c) => sum + (c.weight || 1), 0) || 1;
|
|
1456
|
+
// Floor on the table itself = every column's minimum width contribution. Fixed
|
|
1457
|
+
// columns contribute `fixedPx`; dynamic columns contribute `minWidth` (or 0 when
|
|
1458
|
+
// unset). The template binds this via `[style.min-width.px]` on the <table> so
|
|
1459
|
+
// narrow containers force horizontal scroll instead of squishing columns to 0.
|
|
1460
|
+
this.computedTableMinWidth = cols.reduce((sum, c) => sum + (c.fixedPx && c.fixedPx > 0 ? c.fixedPx : (c.minWidth || 0)), 0);
|
|
1447
1461
|
this.computedColumnWidths = cols.map(c => {
|
|
1448
1462
|
if (c.fixedPx && c.fixedPx > 0) {
|
|
1449
|
-
|
|
1463
|
+
// Fixed-width columns still respect minWidth in the (rare) case the consumer
|
|
1464
|
+
// configured both — `max(fixed, min)` picks whichever is larger.
|
|
1465
|
+
return c.minWidth && c.minWidth > c.fixedPx
|
|
1466
|
+
? `max(${c.fixedPx}px, ${c.minWidth}px)`
|
|
1467
|
+
: `${c.fixedPx}px`;
|
|
1450
1468
|
}
|
|
1451
1469
|
const share = (c.weight || 1) / totalWeight;
|
|
1452
|
-
|
|
1470
|
+
const dynamicWidth = `calc((100% - ${fixedPx}px) * ${share.toFixed(4)})`;
|
|
1471
|
+
// Dynamic-share columns can collapse to ~0 when the table is narrower than
|
|
1472
|
+
// (sum of fixed widths) + the share they'd compute to. Using CSS `max()` floors
|
|
1473
|
+
// the column at `minWidth` so it grows naturally as the table widens but never
|
|
1474
|
+
// shrinks below the configured pixel minimum. With `table-layout: fixed`, the
|
|
1475
|
+
// <col> width is authoritative — without max() here the cell-level `min-width`
|
|
1476
|
+
// we set on <th>/<td> is ignored and columns visually disappear at narrow widths.
|
|
1477
|
+
return c.minWidth && c.minWidth > 0
|
|
1478
|
+
? `max(${c.minWidth}px, ${dynamicWidth})`
|
|
1479
|
+
: dynamicWidth;
|
|
1453
1480
|
});
|
|
1481
|
+
console.log('computedColumnWidths', this.computedColumnWidths);
|
|
1454
1482
|
if (this.gridTemplateColumns) {
|
|
1455
1483
|
this.computedGridTemplate = this.gridTemplateColumns;
|
|
1456
1484
|
}
|
|
@@ -1598,10 +1626,10 @@ class DynamicTableComponent {
|
|
|
1598
1626
|
}
|
|
1599
1627
|
}
|
|
1600
1628
|
DynamicTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicTableComponent, deps: [{ token: i1$2.DomSanitizer }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
1601
|
-
DynamicTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DynamicTableComponent, selector: "app-dynamic-table", inputs: { data: "data", columns: "columns", emptyState: "emptyState", gridTemplateColumns: "gridTemplateColumns", screenWidth: "screenWidth", enableSelectAll: "enableSelectAll", rowSelectable: "rowSelectable", enableLocalSort: "enableLocalSort", isTableLoading: "isTableLoading", isTableDataLoading: "isTableDataLoading", cellJsonPathGetter: "cellJsonPathGetter", onJsonPathCopiedHandler: "onJsonPathCopiedHandler" }, outputs: { sortChange: "sortChange" }, host: { classAttribute: "cqa-ui-root" }, queries: [{ propertyName: "emptyTableTpl", first: true, predicate: ["emptyTableTpl"], descendants: true, read: TemplateRef }, { propertyName: "cellTemplates", predicate: DynamicCellTemplateDirective }, { propertyName: "headerTemplates", predicate: DynamicHeaderTemplateDirective }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-ui-root\">\n <div class=\"cqa-relative\" [class.cqa-max-h-[100px]]=\"showTableLoading\">\n <cqa-full-table-loader *ngIf=\"showTableLoading\"></cqa-full-table-loader>\n <cqa-table-data-loader *ngIf=\"showTableDataLoading\"></cqa-table-data-loader>\n <table class=\"table-inner cqa-w-full cqa-border cqa-border-solid cqa-border-gray-200\"
|
|
1629
|
+
DynamicTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: DynamicTableComponent, selector: "app-dynamic-table", inputs: { data: "data", columns: "columns", emptyState: "emptyState", gridTemplateColumns: "gridTemplateColumns", screenWidth: "screenWidth", enableSelectAll: "enableSelectAll", rowSelectable: "rowSelectable", enableLocalSort: "enableLocalSort", isTableLoading: "isTableLoading", isTableDataLoading: "isTableDataLoading", cellJsonPathGetter: "cellJsonPathGetter", onJsonPathCopiedHandler: "onJsonPathCopiedHandler" }, outputs: { sortChange: "sortChange" }, host: { classAttribute: "cqa-ui-root" }, queries: [{ propertyName: "emptyTableTpl", first: true, predicate: ["emptyTableTpl"], descendants: true, read: TemplateRef }, { propertyName: "cellTemplates", predicate: DynamicCellTemplateDirective }, { propertyName: "headerTemplates", predicate: DynamicHeaderTemplateDirective }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-ui-root\">\n <div class=\"cqa-relative\" [class.cqa-max-h-[100px]]=\"showTableLoading\">\n <cqa-full-table-loader *ngIf=\"showTableLoading\"></cqa-full-table-loader>\n <cqa-table-data-loader *ngIf=\"showTableDataLoading\"></cqa-table-data-loader>\n <table class=\"table-inner cqa-w-full cqa-border cqa-border-solid cqa-border-gray-200\"\n [class.is-loading]=\"true\"\n [style.min-width.px]=\"computedTableMinWidth || null\"\n *ngIf=\"!showTableLoading\">\n <colgroup>\n <ng-container *ngFor=\"let width of computedColumnWidths; trackBy: trackByIndex\">\n <col [style.width]=\"width\" />\n </ng-container>\n </colgroup>\n\n <thead *ngIf=\"data?.length\">\n <tr class=\"table-header cqa-items-center\">\n <ng-container *ngFor=\"let col of visibleColumns; trackBy: trackByIndex\">\n <th\n class=\"header-cell cqa-py-[13.25px] cqa-px-[10.5px] cqa-text-xs cqa-font-semibold cqa-text-[#374151] cqa-bg-[#eff0f7]\"\n [style.min-width.px]=\"col.minWidth\"\n [ngClass]=\"[\n col.fieldId + '-cell',\n col.align === 'center' ? 'cqa-text-center' : col.align === 'right' ? 'cqa-text-right' : 'cqa-text-left'\n ]\">\n <!-- Built-in select-all for checkbox column when enabled and no custom header template -->\n <ng-container\n *ngIf=\"col.fieldId === 'checkbox' && enableSelectAll && !getHeaderTemplate(col.fieldId); else headerTplOrDefault\">\n <div class=\"custom-checkbox\">\n <input type=\"checkbox\" id=\"checkbox\" aria-label=\"Select all rows\" [checked]=\"allSelected\"\n [indeterminate]=\"someSelected\" (change)=\"onSelectAllChange($event)\" class=\"hidden-checkbox\" />\n <label for=\"checkbox\" class=\"custom-checkbox-label\"></label>\n </div>\n </ng-container>\n <ng-template #headerTplOrDefault>\n <ng-container *ngIf=\"getHeaderTemplate(col.fieldId) as headerTpl; else defaultHeader\">\n <ng-container *ngTemplateOutlet=\"headerTpl\"></ng-container>\n </ng-container>\n <ng-template #defaultHeader>\n <ng-container *ngIf=\"col.sortable; else plainHeader\">\n <button type=\"button\" class=\"header-text cqa-inline-flex cqa-items-center cqa-gap-1 cqa-px-0\"\n (click)=\"toggleSort(col)\" [attr.aria-label]=\"'Sort by ' + (col.fieldName || col.fieldId)\">\n <span class=\"cqa-text-[12.3px] cqa-leading-[17.5px] cqa-text-[#0A0A0A] cqa-font-medium\">{{\n col.fieldName }}</span>\n <span *ngIf=\"isSortedAsc(col.fieldId)\">\u25B2</span>\n <span *ngIf=\"isSortedDesc(col.fieldId)\">\u25BC</span>\n </button>\n </ng-container>\n <ng-template #plainHeader>\n <span class=\"header-text\">{{ col.fieldName }}</span>\n </ng-template>\n </ng-template>\n </ng-template>\n </th>\n </ng-container>\n </tr>\n </thead>\n\n <tbody class=\"table-body cqa-w-full\">\n <tr class=\"table-row cqa-bg-surface-default hover:cqa-bg-surface-hover\" *ngFor=\"let row of computedData; let rowIndex = index; trackBy: trackByIndex\"\n [class.selected]=\"row?.isSelected\">\n <ng-container *ngFor=\"let col of visibleColumns; trackBy: trackByIndex\">\n <td class=\"cell cqa-px-[10.5px] cqa-py-[11px]\"\n [style.min-width.px]=\"col.minWidth\"\n [ngClass]=\"[\n col.fieldId + '-cell',\n col.align === 'center' ? 'cqa-text-center' : col.align === 'right' ? 'cqa-text-right' : 'cqa-text-left',\n cellJsonPathGetter && col.fieldId !== 'checkbox' && col.fieldId !== 'actions' ? 'cqa-cursor-pointer' : ''\n ]\"\n (dblclick)=\"cellJsonPathGetter && col?.fieldId !== 'checkbox' && col?.fieldId !== 'actions' && copyCellJsonPath(cellJsonPathGetter(rowIndex, col?.fieldId, row), $event, 'dbQueryResponse')\">\n <!-- Built-in checkbox cell when no custom template is provided -->\n <ng-container *ngIf=\"col.fieldId === 'checkbox' && !getCellTemplate(col.fieldId); else regularCell\">\n <div class=\"custom-checkbox\" [ngClass]=\"[\n col.align === 'center' ? 'cqa-flex cqa-justify-center' : col.align === 'right' ? 'cqa-flex cqa-justify-end' : ''\n ]\">\n <input\n type=\"checkbox\"\n class=\"hidden-checkbox\"\n [attr.id]=\"'row-checkbox-' + rowIndex\"\n aria-label=\"Select row\"\n [checked]=\"row?.isSelected\"\n [disabled]=\"!isRowSelectable(row)\"\n (change)=\"onRowSelectChange($event, row)\" />\n <label\n class=\"custom-checkbox-label\"\n [style.opacity]=\"!isRowSelectable(row) ? '0.45' : null\"\n [style.cursor]=\"!isRowSelectable(row) ? 'not-allowed' : null\"\n [style.pointer-events]=\"!isRowSelectable(row) ? 'none' : null\"\n [attr.for]=\"'row-checkbox-' + rowIndex\">\n </label>\n </div>\n </ng-container>\n <ng-template #regularCell>\n <ng-container *ngIf=\"getCellTemplate(col.fieldId) as cellTpl; else defaultCell\">\n <ng-container\n *ngTemplateOutlet=\"cellTpl; context: {$implicit: row, row: row, value: getCellValue(row, col.fieldValue)}\"></ng-container>\n </ng-container>\n <ng-template #defaultCell>\n <ng-container *ngIf=\"getRenderedValue(row, col) as renderedValue\">\n <ng-container *ngIf=\"isComponent(renderedValue); else nonComponentCell\">\n <ng-container \n cqaCellContainer \n #cellContainer=\"cqaCellContainer\"\n [componentConfig]=\"renderedValue\"\n [row]=\"row\"\n [column]=\"col\"\n [rowIndex]=\"rowIndex\"\n [colId]=\"col.fieldId\">\n </ng-container>\n </ng-container>\n <ng-template #nonComponentCell>\n <ng-container *ngIf=\"isHtmlString(renderedValue); else textCell\">\n <div class=\"cqa-text-xs cqa-leading-[17px]\" [innerHTML]=\"getSanitizedHtml(renderedValue)\" [ngClass]=\"[\n col.align === 'center' ? 'cqa-flex cqa-justify-center' : col.align === 'right' ? 'cqa-flex cqa-justify-end' : ''\n ]\"></div>\n </ng-container>\n <ng-template #textCell>\n <span class=\"cqa-text-xs cqa-text-[#374151]\" [ngClass]=\"[\n col.align === 'center' ? 'cqa-flex cqa-justify-center' : col.align === 'right' ? 'cqa-flex cqa-justify-end' : ''\n ]\">{{ renderedValue }}</span>\n </ng-template>\n </ng-template>\n </ng-container>\n </ng-template>\n </ng-template>\n </td>\n </ng-container>\n </tr>\n </tbody>\n </table>\n </div>\n</div>", components: [{ type: FullTableLoaderComponent, selector: "cqa-full-table-loader", inputs: ["label"] }, { type: TableDataLoaderComponent, selector: "cqa-table-data-loader", inputs: ["label", "size"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: DynamicCellContainerDirective, selector: "[cqaCellContainer]", inputs: ["componentConfig", "row", "column", "rowIndex", "colId"], exportAs: ["cqaCellContainer"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1602
1630
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: DynamicTableComponent, decorators: [{
|
|
1603
1631
|
type: Component,
|
|
1604
|
-
args: [{ selector: "app-dynamic-table", host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"cqa-ui-root\">\n <div class=\"cqa-relative\" [class.cqa-max-h-[100px]]=\"showTableLoading\">\n <cqa-full-table-loader *ngIf=\"showTableLoading\"></cqa-full-table-loader>\n <cqa-table-data-loader *ngIf=\"showTableDataLoading\"></cqa-table-data-loader>\n <table class=\"table-inner cqa-w-full cqa-border cqa-border-solid cqa-border-gray-200\"
|
|
1632
|
+
args: [{ selector: "app-dynamic-table", host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"cqa-ui-root\">\n <div class=\"cqa-relative\" [class.cqa-max-h-[100px]]=\"showTableLoading\">\n <cqa-full-table-loader *ngIf=\"showTableLoading\"></cqa-full-table-loader>\n <cqa-table-data-loader *ngIf=\"showTableDataLoading\"></cqa-table-data-loader>\n <table class=\"table-inner cqa-w-full cqa-border cqa-border-solid cqa-border-gray-200\"\n [class.is-loading]=\"true\"\n [style.min-width.px]=\"computedTableMinWidth || null\"\n *ngIf=\"!showTableLoading\">\n <colgroup>\n <ng-container *ngFor=\"let width of computedColumnWidths; trackBy: trackByIndex\">\n <col [style.width]=\"width\" />\n </ng-container>\n </colgroup>\n\n <thead *ngIf=\"data?.length\">\n <tr class=\"table-header cqa-items-center\">\n <ng-container *ngFor=\"let col of visibleColumns; trackBy: trackByIndex\">\n <th\n class=\"header-cell cqa-py-[13.25px] cqa-px-[10.5px] cqa-text-xs cqa-font-semibold cqa-text-[#374151] cqa-bg-[#eff0f7]\"\n [style.min-width.px]=\"col.minWidth\"\n [ngClass]=\"[\n col.fieldId + '-cell',\n col.align === 'center' ? 'cqa-text-center' : col.align === 'right' ? 'cqa-text-right' : 'cqa-text-left'\n ]\">\n <!-- Built-in select-all for checkbox column when enabled and no custom header template -->\n <ng-container\n *ngIf=\"col.fieldId === 'checkbox' && enableSelectAll && !getHeaderTemplate(col.fieldId); else headerTplOrDefault\">\n <div class=\"custom-checkbox\">\n <input type=\"checkbox\" id=\"checkbox\" aria-label=\"Select all rows\" [checked]=\"allSelected\"\n [indeterminate]=\"someSelected\" (change)=\"onSelectAllChange($event)\" class=\"hidden-checkbox\" />\n <label for=\"checkbox\" class=\"custom-checkbox-label\"></label>\n </div>\n </ng-container>\n <ng-template #headerTplOrDefault>\n <ng-container *ngIf=\"getHeaderTemplate(col.fieldId) as headerTpl; else defaultHeader\">\n <ng-container *ngTemplateOutlet=\"headerTpl\"></ng-container>\n </ng-container>\n <ng-template #defaultHeader>\n <ng-container *ngIf=\"col.sortable; else plainHeader\">\n <button type=\"button\" class=\"header-text cqa-inline-flex cqa-items-center cqa-gap-1 cqa-px-0\"\n (click)=\"toggleSort(col)\" [attr.aria-label]=\"'Sort by ' + (col.fieldName || col.fieldId)\">\n <span class=\"cqa-text-[12.3px] cqa-leading-[17.5px] cqa-text-[#0A0A0A] cqa-font-medium\">{{\n col.fieldName }}</span>\n <span *ngIf=\"isSortedAsc(col.fieldId)\">\u25B2</span>\n <span *ngIf=\"isSortedDesc(col.fieldId)\">\u25BC</span>\n </button>\n </ng-container>\n <ng-template #plainHeader>\n <span class=\"header-text\">{{ col.fieldName }}</span>\n </ng-template>\n </ng-template>\n </ng-template>\n </th>\n </ng-container>\n </tr>\n </thead>\n\n <tbody class=\"table-body cqa-w-full\">\n <tr class=\"table-row cqa-bg-surface-default hover:cqa-bg-surface-hover\" *ngFor=\"let row of computedData; let rowIndex = index; trackBy: trackByIndex\"\n [class.selected]=\"row?.isSelected\">\n <ng-container *ngFor=\"let col of visibleColumns; trackBy: trackByIndex\">\n <td class=\"cell cqa-px-[10.5px] cqa-py-[11px]\"\n [style.min-width.px]=\"col.minWidth\"\n [ngClass]=\"[\n col.fieldId + '-cell',\n col.align === 'center' ? 'cqa-text-center' : col.align === 'right' ? 'cqa-text-right' : 'cqa-text-left',\n cellJsonPathGetter && col.fieldId !== 'checkbox' && col.fieldId !== 'actions' ? 'cqa-cursor-pointer' : ''\n ]\"\n (dblclick)=\"cellJsonPathGetter && col?.fieldId !== 'checkbox' && col?.fieldId !== 'actions' && copyCellJsonPath(cellJsonPathGetter(rowIndex, col?.fieldId, row), $event, 'dbQueryResponse')\">\n <!-- Built-in checkbox cell when no custom template is provided -->\n <ng-container *ngIf=\"col.fieldId === 'checkbox' && !getCellTemplate(col.fieldId); else regularCell\">\n <div class=\"custom-checkbox\" [ngClass]=\"[\n col.align === 'center' ? 'cqa-flex cqa-justify-center' : col.align === 'right' ? 'cqa-flex cqa-justify-end' : ''\n ]\">\n <input\n type=\"checkbox\"\n class=\"hidden-checkbox\"\n [attr.id]=\"'row-checkbox-' + rowIndex\"\n aria-label=\"Select row\"\n [checked]=\"row?.isSelected\"\n [disabled]=\"!isRowSelectable(row)\"\n (change)=\"onRowSelectChange($event, row)\" />\n <label\n class=\"custom-checkbox-label\"\n [style.opacity]=\"!isRowSelectable(row) ? '0.45' : null\"\n [style.cursor]=\"!isRowSelectable(row) ? 'not-allowed' : null\"\n [style.pointer-events]=\"!isRowSelectable(row) ? 'none' : null\"\n [attr.for]=\"'row-checkbox-' + rowIndex\">\n </label>\n </div>\n </ng-container>\n <ng-template #regularCell>\n <ng-container *ngIf=\"getCellTemplate(col.fieldId) as cellTpl; else defaultCell\">\n <ng-container\n *ngTemplateOutlet=\"cellTpl; context: {$implicit: row, row: row, value: getCellValue(row, col.fieldValue)}\"></ng-container>\n </ng-container>\n <ng-template #defaultCell>\n <ng-container *ngIf=\"getRenderedValue(row, col) as renderedValue\">\n <ng-container *ngIf=\"isComponent(renderedValue); else nonComponentCell\">\n <ng-container \n cqaCellContainer \n #cellContainer=\"cqaCellContainer\"\n [componentConfig]=\"renderedValue\"\n [row]=\"row\"\n [column]=\"col\"\n [rowIndex]=\"rowIndex\"\n [colId]=\"col.fieldId\">\n </ng-container>\n </ng-container>\n <ng-template #nonComponentCell>\n <ng-container *ngIf=\"isHtmlString(renderedValue); else textCell\">\n <div class=\"cqa-text-xs cqa-leading-[17px]\" [innerHTML]=\"getSanitizedHtml(renderedValue)\" [ngClass]=\"[\n col.align === 'center' ? 'cqa-flex cqa-justify-center' : col.align === 'right' ? 'cqa-flex cqa-justify-end' : ''\n ]\"></div>\n </ng-container>\n <ng-template #textCell>\n <span class=\"cqa-text-xs cqa-text-[#374151]\" [ngClass]=\"[\n col.align === 'center' ? 'cqa-flex cqa-justify-center' : col.align === 'right' ? 'cqa-flex cqa-justify-end' : ''\n ]\">{{ renderedValue }}</span>\n </ng-template>\n </ng-template>\n </ng-container>\n </ng-template>\n </ng-template>\n </td>\n </ng-container>\n </tr>\n </tbody>\n </table>\n </div>\n</div>", styles: [] }]
|
|
1605
1633
|
}], ctorParameters: function () { return [{ type: i1$2.DomSanitizer }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { data: [{
|
|
1606
1634
|
type: Input
|
|
1607
1635
|
}], columns: [{
|
|
@@ -19286,19 +19314,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
19286
19314
|
|
|
19287
19315
|
class ViewCompareButtonComponent {
|
|
19288
19316
|
constructor() {
|
|
19317
|
+
this.label = 'View Compare';
|
|
19318
|
+
this.isFailureAction = false;
|
|
19289
19319
|
this.clicked = new EventEmitter();
|
|
19290
19320
|
}
|
|
19291
19321
|
}
|
|
19292
19322
|
ViewCompareButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ViewCompareButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
19293
|
-
ViewCompareButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ViewCompareButtonComponent, selector: "cqa-view-compare-button", outputs: { clicked: "clicked" }, ngImport: i0, template: `
|
|
19323
|
+
ViewCompareButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: ViewCompareButtonComponent, selector: "cqa-view-compare-button", inputs: { label: "label", isFailureAction: "isFailureAction" }, outputs: { clicked: "clicked" }, ngImport: i0, template: `
|
|
19294
19324
|
<button
|
|
19295
19325
|
type="button"
|
|
19296
|
-
class="cqa-inline-flex cqa-items-center cqa-justify-center cqa-px-3 cqa-py-1.5 cqa-text-xs cqa-font-medium cqa-rounded-[6px] cqa-border
|
|
19326
|
+
class="cqa-inline-flex cqa-items-center cqa-justify-center cqa-min-w-[92px] cqa-px-3 cqa-py-1.5 cqa-text-xs cqa-font-medium cqa-rounded-[6px] cqa-border"
|
|
19327
|
+
[ngClass]="isFailureAction ? 'cqa-border-[#F7C9CD] cqa-text-[#FB2C36] cqa-bg-[#FDE8EA]' : 'cqa-border-[#D1D5DB] cqa-text-[#636363] cqa-bg-[#F9FAFB]'"
|
|
19297
19328
|
(click)="clicked.emit()"
|
|
19298
19329
|
>
|
|
19299
|
-
|
|
19330
|
+
{{ label }}
|
|
19300
19331
|
</button>
|
|
19301
|
-
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
19332
|
+
`, isInline: true, directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
19302
19333
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: ViewCompareButtonComponent, decorators: [{
|
|
19303
19334
|
type: Component,
|
|
19304
19335
|
args: [{
|
|
@@ -19306,15 +19337,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
19306
19337
|
template: `
|
|
19307
19338
|
<button
|
|
19308
19339
|
type="button"
|
|
19309
|
-
class="cqa-inline-flex cqa-items-center cqa-justify-center cqa-px-3 cqa-py-1.5 cqa-text-xs cqa-font-medium cqa-rounded-[6px] cqa-border
|
|
19340
|
+
class="cqa-inline-flex cqa-items-center cqa-justify-center cqa-min-w-[92px] cqa-px-3 cqa-py-1.5 cqa-text-xs cqa-font-medium cqa-rounded-[6px] cqa-border"
|
|
19341
|
+
[ngClass]="isFailureAction ? 'cqa-border-[#F7C9CD] cqa-text-[#FB2C36] cqa-bg-[#FDE8EA]' : 'cqa-border-[#D1D5DB] cqa-text-[#636363] cqa-bg-[#F9FAFB]'"
|
|
19310
19342
|
(click)="clicked.emit()"
|
|
19311
19343
|
>
|
|
19312
|
-
|
|
19344
|
+
{{ label }}
|
|
19313
19345
|
</button>
|
|
19314
19346
|
`,
|
|
19315
19347
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
19316
19348
|
}]
|
|
19317
|
-
}], propDecorators: {
|
|
19349
|
+
}], propDecorators: { label: [{
|
|
19350
|
+
type: Input
|
|
19351
|
+
}], isFailureAction: [{
|
|
19352
|
+
type: Input
|
|
19353
|
+
}], clicked: [{
|
|
19318
19354
|
type: Output
|
|
19319
19355
|
}] } });
|
|
19320
19356
|
|
|
@@ -19589,6 +19625,14 @@ class CompareRunsComponent {
|
|
|
19589
19625
|
setupTableColumns() {
|
|
19590
19626
|
if (this.compareMode === 'testPlan') {
|
|
19591
19627
|
this.tableColumns = [
|
|
19628
|
+
{
|
|
19629
|
+
fieldId: 'rowIndex',
|
|
19630
|
+
fieldName: '',
|
|
19631
|
+
fieldValue: '_compareRowOrdinal',
|
|
19632
|
+
isShow: true,
|
|
19633
|
+
fixedPx: 44,
|
|
19634
|
+
align: 'center'
|
|
19635
|
+
},
|
|
19592
19636
|
{
|
|
19593
19637
|
fieldId: 'testCase',
|
|
19594
19638
|
fieldName: 'Test Cases',
|
|
@@ -19636,9 +19680,7 @@ class CompareRunsComponent {
|
|
|
19636
19680
|
isShow: true,
|
|
19637
19681
|
weight: 1.1,
|
|
19638
19682
|
align: 'center',
|
|
19639
|
-
render: (row) =>
|
|
19640
|
-
<span class="cqa-text-xs cqa-text-[#636363]">${row.priorityName || 'Unassigned'}</span>
|
|
19641
|
-
`
|
|
19683
|
+
render: (row) => this.renderPriorityChip(row.priorityName)
|
|
19642
19684
|
},
|
|
19643
19685
|
{
|
|
19644
19686
|
fieldId: 'actions',
|
|
@@ -19648,6 +19690,10 @@ class CompareRunsComponent {
|
|
|
19648
19690
|
align: 'center',
|
|
19649
19691
|
render: (row) => ({
|
|
19650
19692
|
component: ViewCompareButtonComponent,
|
|
19693
|
+
inputs: {
|
|
19694
|
+
label: this.getActionLabel(row),
|
|
19695
|
+
isFailureAction: this.isFailureAction(row)
|
|
19696
|
+
},
|
|
19651
19697
|
outputs: {
|
|
19652
19698
|
clicked: () => this.onViewCompare(row)
|
|
19653
19699
|
}
|
|
@@ -19657,6 +19703,14 @@ class CompareRunsComponent {
|
|
|
19657
19703
|
return;
|
|
19658
19704
|
}
|
|
19659
19705
|
this.tableColumns = [
|
|
19706
|
+
{
|
|
19707
|
+
fieldId: 'rowIndex',
|
|
19708
|
+
fieldName: '',
|
|
19709
|
+
fieldValue: '_compareRowOrdinal',
|
|
19710
|
+
isShow: true,
|
|
19711
|
+
fixedPx: 44,
|
|
19712
|
+
align: 'center'
|
|
19713
|
+
},
|
|
19660
19714
|
{
|
|
19661
19715
|
fieldId: 'step',
|
|
19662
19716
|
fieldName: 'Step',
|
|
@@ -19664,9 +19718,12 @@ class CompareRunsComponent {
|
|
|
19664
19718
|
isShow: true,
|
|
19665
19719
|
weight: 3,
|
|
19666
19720
|
render: (row) => {
|
|
19721
|
+
const inner = row.stepTitle != null && String(row.stepTitle).trim() !== ''
|
|
19722
|
+
? row.stepTitle
|
|
19723
|
+
: '<span class="cqa-text-xs cqa-text-[#9CA3AF]">—</span>';
|
|
19667
19724
|
return `
|
|
19668
|
-
<div class="cqa-flex cqa-items-center cqa-gap-2">
|
|
19669
|
-
<span class="cqa-text-xs cqa-text-[#0B0B0B]">${
|
|
19725
|
+
<div class="cqa-flex cqa-items-center cqa-gap-2" style="min-width:0;">
|
|
19726
|
+
<span class="cqa-text-xs cqa-text-[#0B0B0B]">${inner}</span>
|
|
19670
19727
|
</div>
|
|
19671
19728
|
`;
|
|
19672
19729
|
}
|
|
@@ -19807,45 +19864,67 @@ class CompareRunsComponent {
|
|
|
19807
19864
|
'TIMING_CHANGED': 'Timing Changed',
|
|
19808
19865
|
'FIXED': 'Fixed',
|
|
19809
19866
|
'REGRESSION': 'Regression',
|
|
19810
|
-
'ADDED': '
|
|
19811
|
-
'NEW STEP': 'New
|
|
19867
|
+
'ADDED': 'New',
|
|
19868
|
+
'NEW STEP': 'New',
|
|
19812
19869
|
'REMOVED': 'Removed',
|
|
19813
19870
|
'DELETED STEP': 'Deleted Step'
|
|
19814
19871
|
};
|
|
19815
19872
|
const changeColors = {
|
|
19816
|
-
'UNCHANGED': '#6B7280',
|
|
19817
|
-
'NO CHANGE': '#6B7280',
|
|
19818
|
-
'
|
|
19819
|
-
'
|
|
19820
|
-
'
|
|
19821
|
-
'
|
|
19822
|
-
'ADDED': '#
|
|
19823
|
-
'NEW STEP': '#
|
|
19824
|
-
'REMOVED': '#
|
|
19825
|
-
'DELETED STEP': '#
|
|
19826
|
-
};
|
|
19827
|
-
const changeBgColors = {
|
|
19828
|
-
'UNCHANGED': '#F3F4F6',
|
|
19829
|
-
'NO CHANGE': '#F3F4F6',
|
|
19830
|
-
'STATUS_CHANGED': '#DBEAFE',
|
|
19831
|
-
'TIMING_CHANGED': '#DBEAFE',
|
|
19832
|
-
'FIXED': '#DBEAFE',
|
|
19833
|
-
'REGRESSION': '#DBEAFE',
|
|
19834
|
-
'ADDED': '#D1FAE5',
|
|
19835
|
-
'NEW STEP': '#D1FAE5',
|
|
19836
|
-
'REMOVED': '#FEE2E2',
|
|
19837
|
-
'DELETED STEP': '#FEE2E2'
|
|
19873
|
+
'UNCHANGED': { text: '#6B7280', bg: '#F3F4F6', dot: '#9CA3AF' },
|
|
19874
|
+
'NO CHANGE': { text: '#6B7280', bg: '#F3F4F6', dot: '#9CA3AF' },
|
|
19875
|
+
'TIMING_CHANGED': { text: '#6B7280', bg: '#F3F4F6', dot: '#9CA3AF' },
|
|
19876
|
+
'FIXED': { text: '#00A63E', bg: '#DDF5E8', dot: '#00C950' },
|
|
19877
|
+
'REGRESSION': { text: '#FB2C36', bg: '#FDE8EA', dot: '#FB2C36' },
|
|
19878
|
+
'STATUS_CHANGED': { text: '#FB2C36', bg: '#FDE8EA', dot: '#FB2C36' },
|
|
19879
|
+
'ADDED': { text: '#155DFC', bg: '#DBEAFE', dot: '#0A84FF' },
|
|
19880
|
+
'NEW STEP': { text: '#155DFC', bg: '#DBEAFE', dot: '#0A84FF' },
|
|
19881
|
+
'REMOVED': { text: '#6B7280', bg: '#F3F4F6', dot: '#9CA3AF' },
|
|
19882
|
+
'DELETED STEP': { text: '#6B7280', bg: '#F3F4F6', dot: '#9CA3AF' }
|
|
19838
19883
|
};
|
|
19839
19884
|
const label = changeLabels[normalizedChange] || change;
|
|
19840
|
-
const
|
|
19841
|
-
const bgColor = changeBgColors[normalizedChange] || '#F3F4F6';
|
|
19885
|
+
const token = changeColors[normalizedChange] || { text: '#6B7280', bg: '#F3F4F6', dot: '#9CA3AF' };
|
|
19842
19886
|
return `
|
|
19843
|
-
<span class="cqa-inline-flex cqa-items-center cqa-
|
|
19844
|
-
style="background-color: ${
|
|
19887
|
+
<span class="cqa-inline-flex cqa-items-center cqa-gap-1 cqa-px-3 cqa-py-1 cqa-rounded-full cqa-text-xs cqa-font-medium cqa-leading-none cqa-w-max"
|
|
19888
|
+
style="background-color: ${token.bg}; color: ${token.text};">
|
|
19889
|
+
<span style="width: 10px; height: 10px; border-radius: 50%; background-color: ${token.dot}; display: inline-block;"></span>
|
|
19845
19890
|
${label}
|
|
19846
19891
|
</span>
|
|
19847
19892
|
`;
|
|
19848
19893
|
}
|
|
19894
|
+
renderPriorityChip(priority) {
|
|
19895
|
+
const raw = (priority || '').toString().trim();
|
|
19896
|
+
const normalized = raw.toUpperCase();
|
|
19897
|
+
const priorityTokens = {
|
|
19898
|
+
CRITICAL: { label: 'Critical', text: '#FB2C36', bg: '#FDE8EA' },
|
|
19899
|
+
HIGH: { label: 'High', text: '#FB2C36', bg: '#FDE8EA' },
|
|
19900
|
+
MEDIUM: { label: 'Medium', text: '#D97706', bg: '#FEF3C7' },
|
|
19901
|
+
NORMAL: { label: 'Normal', text: '#EA580C', bg: '#FDEFE3' },
|
|
19902
|
+
LOW: { label: 'Low', text: '#A16207', bg: '#F5EEDC' }
|
|
19903
|
+
};
|
|
19904
|
+
const token = priorityTokens[normalized];
|
|
19905
|
+
if (!token) {
|
|
19906
|
+
const fallback = raw || 'Unassigned';
|
|
19907
|
+
return `
|
|
19908
|
+
<span class="cqa-inline-flex cqa-items-center cqa-justify-center cqa-px-3 cqa-py-1 cqa-rounded-full cqa-text-xs cqa-font-medium cqa-leading-none cqa-w-max"
|
|
19909
|
+
style="background-color: #F3F4F6; color: #6B7280;">
|
|
19910
|
+
${fallback}
|
|
19911
|
+
</span>
|
|
19912
|
+
`;
|
|
19913
|
+
}
|
|
19914
|
+
return `
|
|
19915
|
+
<span class="cqa-inline-flex cqa-items-center cqa-justify-center cqa-px-3 cqa-py-1 cqa-rounded-full cqa-text-xs cqa-font-medium cqa-leading-none cqa-w-max"
|
|
19916
|
+
style="background-color: ${token.bg}; color: ${token.text};">
|
|
19917
|
+
${token.label}
|
|
19918
|
+
</span>
|
|
19919
|
+
`;
|
|
19920
|
+
}
|
|
19921
|
+
isFailureAction(row) {
|
|
19922
|
+
const runBStatus = (row?.runBStatus || '').toString().toUpperCase().trim();
|
|
19923
|
+
return runBStatus === 'FAILURE';
|
|
19924
|
+
}
|
|
19925
|
+
getActionLabel(row) {
|
|
19926
|
+
return this.isFailureAction(row) ? 'View Failure' : 'View Compare';
|
|
19927
|
+
}
|
|
19849
19928
|
getRunColumnHeader(run) {
|
|
19850
19929
|
const selectedRun = run === 'A' ? this.selectedRunA : this.selectedRunB;
|
|
19851
19930
|
if (selectedRun && selectedRun.id != null) {
|
|
@@ -19946,10 +20025,77 @@ class CompareRunsComponent {
|
|
|
19946
20025
|
if (!this.comparisonData)
|
|
19947
20026
|
return;
|
|
19948
20027
|
this.comparisonSummary = this.comparisonData.summary;
|
|
19949
|
-
|
|
20028
|
+
const steps = this.comparisonData.stepsComparison || [];
|
|
20029
|
+
this.stepComparisons = steps.map((row, i) => ({ ...row, _compareRowOrdinal: i + 1 }));
|
|
20030
|
+
this.testPlanCardSummary = this.computeTestPlanCardSummary(this.stepComparisons);
|
|
19950
20031
|
this.pageIndex = 0;
|
|
19951
20032
|
this.cdr.markForCheck();
|
|
19952
20033
|
}
|
|
20034
|
+
/**
|
|
20035
|
+
* Builds summary card counts for test-plan compare: pass/fail from Run B vs total;
|
|
20036
|
+
* change buckets from `change` (REGRESSION, FIXED, NEW STEP, etc.).
|
|
20037
|
+
*/
|
|
20038
|
+
computeTestPlanCardSummary(steps) {
|
|
20039
|
+
const totalCases = steps.length;
|
|
20040
|
+
let passed = 0;
|
|
20041
|
+
let regressions = 0;
|
|
20042
|
+
let fixed = 0;
|
|
20043
|
+
let newSteps = 0;
|
|
20044
|
+
let removed = 0;
|
|
20045
|
+
let noChange = 0;
|
|
20046
|
+
for (const row of steps) {
|
|
20047
|
+
const b = (row.runBStatus || '').toUpperCase().trim();
|
|
20048
|
+
if (b === 'SUCCESS') {
|
|
20049
|
+
passed++;
|
|
20050
|
+
}
|
|
20051
|
+
const changeUpper = (row.change || '').toString().toUpperCase().trim();
|
|
20052
|
+
if (changeUpper === 'REGRESSION') {
|
|
20053
|
+
regressions++;
|
|
20054
|
+
}
|
|
20055
|
+
else if (changeUpper === 'FIXED') {
|
|
20056
|
+
fixed++;
|
|
20057
|
+
}
|
|
20058
|
+
else if (changeUpper === 'NEW STEP' || changeUpper === 'ADDED') {
|
|
20059
|
+
newSteps++;
|
|
20060
|
+
}
|
|
20061
|
+
else if (changeUpper === 'DELETED STEP' || changeUpper === 'REMOVED') {
|
|
20062
|
+
removed++;
|
|
20063
|
+
}
|
|
20064
|
+
else if (changeUpper === 'NO CHANGE' ||
|
|
20065
|
+
changeUpper === 'UNCHANGED' ||
|
|
20066
|
+
changeUpper === 'TIMING_CHANGED' ||
|
|
20067
|
+
changeUpper === 'TIMING CHANGED') {
|
|
20068
|
+
noChange++;
|
|
20069
|
+
}
|
|
20070
|
+
else if (changeUpper === 'STATUS_CHANGED') {
|
|
20071
|
+
const ra = (row.runAStatus || '').toUpperCase().trim();
|
|
20072
|
+
const rb = (row.runBStatus || '').toUpperCase().trim();
|
|
20073
|
+
if (ra === 'SUCCESS' && rb === 'FAILURE') {
|
|
20074
|
+
regressions++;
|
|
20075
|
+
}
|
|
20076
|
+
else if (ra === 'FAILURE' && rb === 'SUCCESS') {
|
|
20077
|
+
fixed++;
|
|
20078
|
+
}
|
|
20079
|
+
else {
|
|
20080
|
+
regressions++;
|
|
20081
|
+
}
|
|
20082
|
+
}
|
|
20083
|
+
else {
|
|
20084
|
+
noChange++;
|
|
20085
|
+
}
|
|
20086
|
+
}
|
|
20087
|
+
const failed = Math.max(0, totalCases - passed);
|
|
20088
|
+
return {
|
|
20089
|
+
totalCases,
|
|
20090
|
+
passed,
|
|
20091
|
+
failed,
|
|
20092
|
+
regressions,
|
|
20093
|
+
fixed,
|
|
20094
|
+
newSteps,
|
|
20095
|
+
removed,
|
|
20096
|
+
noChange
|
|
20097
|
+
};
|
|
20098
|
+
}
|
|
19953
20099
|
onPageChange(event) {
|
|
19954
20100
|
this.pageIndex = event.pageIndex;
|
|
19955
20101
|
this.pageSize = event.pageSize;
|
|
@@ -20094,10 +20240,10 @@ class CompareRunsComponent {
|
|
|
20094
20240
|
}
|
|
20095
20241
|
}
|
|
20096
20242
|
CompareRunsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: CompareRunsComponent, deps: [{ token: i1$1.FormBuilder }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
20097
|
-
CompareRunsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: CompareRunsComponent, selector: "cqa-compare-runs", inputs: { runs: "runs", comparisonData: "comparisonData", compareMode: "compareMode", initialRunAId: "initialRunAId", initialRunBId: "initialRunBId", autoCompareOnInit: "autoCompareOnInit", isLoadingRuns: "isLoadingRuns", hasMoreRuns: "hasMoreRuns", isComparingRuns: "isComparingRuns", hasComparedRuns: "hasComparedRuns", pageSizeMenuDirection: "pageSizeMenuDirection", hideRunSelectorsAndCompareButton: "hideRunSelectorsAndCompareButton", isExportingTestPlanCompare: "isExportingTestPlanCompare" }, outputs: { searchRuns: "searchRuns", loadMoreRuns: "loadMoreRuns", compareRuns: "compareRuns", viewCompare: "viewCompare", testCaseClick: "testCaseClick", exportTestPlanCompare: "exportTestPlanCompare" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-ui-root\" style=\"display: flex; flex-direction: column; width: 100%; height: 100%;\">\n <div class=\"cqa-flex cqa-flex-col\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3 sm:cqa-gap-4 cqa-py-3 sm:cqa-py-4 cqa-px-4 sm:cqa-px-6\" style=\"border-bottom: 1px solid #E4E4E4\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-mb-1\">\n <span class=\"cqa-text-[11px] cqa-text-[#6B7280]\">Status legend:</span>\n <div class=\"cqa-flex cqa-items-center cqa-gap-3\">\n <!-- Passed -->\n <span class=\"cqa-inline-flex cqa-items-center cqa-gap-1\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M7.99998 14.6663C11.6819 14.6663 14.6666 11.6816 14.6666 7.99967C14.6666 4.31778 11.6819 1.33301 7.99998 1.33301C4.31808 1.33301 1.33331 4.31778 1.33331 7.99967C1.33331 11.6816 4.31808 14.6663 7.99998 14.6663Z\" stroke=\"#0B9D68\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6 8.00033L7.33333 9.33366L10 6.66699\" stroke=\"#0B9D68\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span class=\"cqa-text-[11px] cqa-text-[#0B9D68] cqa-font-medium\">Passed</span>\n </span>\n <!-- Failed -->\n <span class=\"cqa-inline-flex cqa-items-center cqa-gap-1\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M8.00004 14.6673C11.6819 14.6673 14.6667 11.6825 14.6667 8.00065C14.6667 4.31875 11.6819 1.33398 8.00004 1.33398C4.31814 1.33398 1.33337 4.31875 1.33337 8.00065C1.33337 11.6825 4.31814 14.6673 8.00004 14.6673Z\" stroke=\"#FB2C36\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M10 6L6 10\" stroke=\"#FB2C36\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6 6L10 10\" stroke=\"#FB2C36\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span class=\"cqa-text-[11px] cqa-text-[#FB2C36] cqa-font-medium\">Failed</span>\n </span>\n <!-- Aborted -->\n <span class=\"cqa-inline-flex cqa-items-center cqa-gap-1\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M8.00004 14.6673C11.6819 14.6673 14.6667 11.6825 14.6667 8.00065C14.6667 4.31875 11.6819 1.33398 8.00004 1.33398C4.31814 1.33398 1.33337 4.31875 1.33337 8.00065C1.33337 11.6825 4.31814 14.6673 8.00004 14.6673Z\" stroke=\"#F59E0B\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6 8H10\" stroke=\"#F59E0B\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span class=\"cqa-text-[11px] cqa-text-[#F59E0B] cqa-font-medium\">Aborted</span>\n </span>\n </div>\n </div>\n\n <div *ngIf=\"!hideRunSelectorsAndCompareButton\" class=\"cqa-grid cqa-grid-cols-1 md:cqa-grid-cols-2 cqa-gap-4 md:cqa-gap-16 cqa-relative\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5\">\n <span class=\"cqa-text-[12px] cqa-font-semibold cqa-text-[#636363]\">Run A (Base)</span>\n <cqa-dynamic-select \n [form]=\"form\" \n [config]=\"runASelectConfig\"\n (searchChange)=\"onSearchChange($event)\"\n (loadMore)=\"onLoadMore($event)\">\n </cqa-dynamic-select>\n </div>\n \n <div class=\"cqa-hidden md:cqa-flex cqa-items-center cqa-justify-center\" style=\"position: absolute; left: 50%; transform: translateX(-50%); top: 30px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M4.16669 10H15.8334\" stroke=\"#636363\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M10 4.16699L15.8333 10.0003L10 15.8337\" stroke=\"#636363\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n \n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5\">\n <span class=\"cqa-text-[12px] cqa-font-semibold cqa-text-[#636363]\">Run B (Compare)</span>\n <cqa-dynamic-select \n [form]=\"form\" \n [config]=\"runBSelectConfig\"\n (searchChange)=\"onSearchChange($event)\"\n (loadMore)=\"onLoadMore($event)\">\n </cqa-dynamic-select>\n </div>\n </div>\n \n <ng-container *ngIf=\"selectedRunA || selectedRunB\">\n <div class=\"cqa-grid cqa-grid-cols-1 md:cqa-grid-cols-2 cqa-gap-4\">\n <div class=\"cqa-bg-white cqa-rounded-lg cqa-p-3\"\n [style.background-color]=\"selectedRunA ? runAStatusBgColor : null\"\n [style.border-color]=\"selectedRunA ? runAStatusBorderColor : null\"\n [ngClass]=\"{'cqa-border cqa-border-solid': selectedRunA}\">\n <ng-container *ngIf=\"selectedRunA\">\n <div class=\"cqa-flex cqa-items-start cqa-justify-between cqa-mb-2\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1\">\n <span class=\"cqa-text-[12px] cqa-font-semibold cqa-text-[#0B0B0B]\">Run #{{ selectedRunA.id }}</span>\n </div>\n <span class=\"cqa-inline-flex cqa-items-center cqa-justify-center cqa-px-2 cqa-py-0.5 cqa-rounded-full cqa-text-[10px] cqa-font-medium\"\n [style.background-color]=\"runAStatusColor\"\n [style.color]=\"'#FFFFFF'\">\n {{ runAStatusLabel }}\n </span>\n </div>\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Time: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ formatTime(selectedRunA.startTime) }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Duration: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ formatDurationString(selectedRunA.duration) }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Env: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ selectedRunA.environment || 'NA' }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\" *ngIf=\"selectedRunA.device\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">{{ selectedRunA?.platform === 'desktop' ? 'Browser' : 'Device' }}: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ selectedRunA.device }}</span>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-bg-white cqa-rounded-lg cqa-p-3\"\n [style.background-color]=\"selectedRunB ? runBStatusBgColor : null\"\n [style.border-color]=\"selectedRunB ? runBStatusBorderColor : null\"\n [ngClass]=\"{'cqa-border cqa-border-solid': selectedRunB}\">\n <ng-container *ngIf=\"selectedRunB\">\n <div class=\"cqa-flex cqa-items-start cqa-justify-between cqa-mb-2\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1\">\n <span class=\"cqa-text-[12px] cqa-font-semibold cqa-text-[#0B0B0B]\">Run #{{ selectedRunB.id }}</span>\n </div>\n <span class=\"cqa-inline-flex cqa-items-center cqa-justify-center cqa-px-2 cqa-py-0.5 cqa-rounded-full cqa-text-[10px] cqa-font-medium\"\n [style.background-color]=\"runBStatusColor\"\n [style.color]=\"'#FFFFFF'\">\n {{ runBStatusLabel }}\n </span>\n </div>\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Time: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ formatTime(selectedRunB.startTime) }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Duration: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ formatDurationString(selectedRunB.duration) }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Env: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ selectedRunB.environment || 'NA' }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\" *ngIf=\"selectedRunB.device\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">{{ selectedRunB?.platform === 'desktop' ? 'Browser' : 'Device' }}: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ selectedRunB.device }}</span>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n </ng-container>\n\n <div *ngIf=\"!hideRunSelectorsAndCompareButton\" class=\"cqa-w-full cqa-flex cqa-items-center cqa-justify-center cqa-gap-3\">\n <cqa-button \n variant=\"filled\" \n [disabled]=\"!canCompare\"\n (click)=\"onCompareClick()\">\n {{ isComparingRuns ? 'Comparing...' : 'Compare Runs' }}\n </cqa-button>\n <cqa-button\n *ngIf=\"compareMode === 'testPlan'\"\n variant=\"outlined\"\n [text]=\"isExportingTestPlanCompare ? 'Exporting\u2026' : 'Export'\"\n [loading]=\"isExportingTestPlanCompare\"\n [disabled]=\"!canCompare\"\n (clicked)=\"onExportTestPlanCompare()\"\n ></cqa-button>\n </div>\n </div>\n\n <div *ngIf=\"showComparison && comparisonSummary && stepComparisons && stepComparisons.length > 0\" \n class=\"cqa-bg-white cqa-py-3 sm:cqa-py-4 cqa-px-3 sm:cqa-px-6 cqa-flex cqa-items-center cqa-gap-3 sm:cqa-gap-4\"\n style=\"flex-shrink: 0;\">\n <p class=\"cqa-text-[12px] cqa-text-[#636363]\">Summary:</p>\n <div class=\"cqa-flex cqa-flex-wrap cqa-items-center cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"cqa-w-[14px] cqa-h-[14px] cqa-text-sm\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path d=\"M2.91669 5.25H11.0834\" stroke=\"#636363\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M2.91669 8.75H11.0834\" stroke=\"#636363\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <span class=\"cqa-text-sm cqa-font-semibold leading-normal cqa-text-[#0B0B0B]\">{{ comparisonSummary.unchanged }}</span>\n <span class=\"cqa-text-[10px] cqa-font-semibold cqa-text-[#6B7280]\">Unchanged</span>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"cqa-flex-shrink-0 cqa-w-[14px] cqa-h-[14px] cqa-text-sm\">\n <svg fill=\"#000000\" viewBox=\"0 0 24 24\" id=\"update-alt-2\" data-name=\"Flat Color\" xmlns=\"http://www.w3.org/2000/svg\" class=\"icon flat-color\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path id=\"primary\" d=\"M21.71,10.29a1,1,0,0,0-1.42,0L19,11.59V7a3,3,0,0,0-3-3H6A1,1,0,0,0,6,6H16a1,1,0,0,1,1,1v4.59l-1.29-1.3a1,1,0,0,0-1.42,1.42l3,3a1,1,0,0,0,1.42,0l3-3A1,1,0,0,0,21.71,10.29Z\" fill=\"#155DFC\"></path>\n <path id=\"secondary\" d=\"M18,18H8a1,1,0,0,1-1-1V12.41l1.29,1.3a1,1,0,0,0,1.42,0,1,1,0,0,0,0-1.42l-3-3a1,1,0,0,0-1.42,0l-3,3a1,1,0,0,0,1.42,1.42L5,12.41V17a3,3,0,0,0,3,3H18a1,1,0,0,0,0-2Z\" fill=\"#155DFC\"></path>\n </g>\n </svg>\n </mat-icon>\n <span class=\"cqa-text-sm cqa-font-semibold leading-normal cqa-text-[#155DFC]\">{{ comparisonSummary.statusChanged }}</span>\n <span class=\"cqa-text-[10px] cqa-font-semibold cqa-text-[#6B7280]\">Status Changed</span>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"cqa-flex-shrink-0 cqa-w-[14px] cqa-h-[14px] cqa-text-sm\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path d=\"M2.91669 7H11.0834\" stroke=\"#00C950\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M7 2.91699V11.0837\" stroke=\"#00C950\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <span class=\"cqa-text-sm cqa-font-semibold leading-normal cqa-text-[#00A63E]\">{{ comparisonSummary.added }}</span>\n <span class=\"cqa-text-[10px] cqa-font-semibold cqa-text-[#6B7280]\">Added</span>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"cqa-flex-shrink-0 cqa-w-[14px] cqa-h-[14px] cqa-text-sm\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path d=\"M2.91669 7H11.0834\" stroke=\"#FB2C36\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <span class=\"cqa-text-sm cqa-font-semibold leading-normal cqa-text-[#FB2C36]\">{{ comparisonSummary.removed }}</span>\n <span class=\"cqa-text-[10px] cqa-font-semibold cqa-text-[#6B7280]\">Removed</span>\n </div>\n\n <!-- Timing Changed summary removed -->\n </div>\n </div>\n\n <div class=\"cqa-bg-white cqa-rounded-lg\" style=\"overflow-y: auto; max-height: calc(90dvh - 468px); scrollbar-width: thin;\">\n <cqa-table-template style=\"height: 100%; display: block;\"\n [columns]=\"tableColumns\"\n [data]=\"stepComparisons\"\n [pageIndex]=\"pageIndex\"\n [pageSize]=\"pageSize\"\n [pageSizeMenuDirection]=\"pageSizeMenuDirection\"\n [isEmptyState]=\"isEmptyState\"\n [emptyStateConfig]=\"emptyStateConfig\"\n [isTableDataLoading]=\"isComparingRuns\"\n [showSearchBar]=\"false\"\n [showFilterButton]=\"false\"\n [showSettingsButton]=\"false\"\n [showAutoRefreshButton]=\"false\"\n [showOtherButton]=\"false\"\n [showFilterPanel]=\"false\"\n [serverSidePagination]=\"false\"\n (pageChange)=\"onPageChange($event)\">\n </cqa-table-template>\n </div>\n\n </div>\n</div>\n\n", components: [{ type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore", "addCustomValue"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "loading", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: TableTemplateComponent, selector: "cqa-table-template", inputs: ["searchPlaceholder", "searchValue", "showClear", "showSearchBar", "showExportButton", "isExporting", "filterConfig", "filterModel", "showFilterPanel", "showFilterButton", "otherButtons", "otherDropDownButtons", "otherSelectDropDownButtons", "otherButtonLabel", "otherButtonVariant", "showOtherButton", "showActionButton", "showSettingsButton", "showAutoRefreshButton", "data", "isEmptyState", "emptyStateConfig", "actions", "chips", "filterApplied", "columns", "rowSelectable", "selectedAutoRefreshInterval", "pageIndex", "pageSize", "pageSizeOptions", "pageSizeMenuDirection", "serverSidePagination", "totalElements", "enableLocalSort", "isTableLoading", "isTableDataLoading", "cellJsonPathGetter", "onJsonPathCopiedHandler", "selectedItems"], outputs: ["onSearchChange", "onExportClick", "onApplyFilterClick", "onResetFilterClick", "onClearAll", "removeChip", "pageChange", "sortChange", "onReload", "onAutoRefreshClick"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
20243
|
+
CompareRunsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: CompareRunsComponent, selector: "cqa-compare-runs", inputs: { runs: "runs", comparisonData: "comparisonData", compareMode: "compareMode", initialRunAId: "initialRunAId", initialRunBId: "initialRunBId", autoCompareOnInit: "autoCompareOnInit", isLoadingRuns: "isLoadingRuns", hasMoreRuns: "hasMoreRuns", isComparingRuns: "isComparingRuns", hasComparedRuns: "hasComparedRuns", pageSizeMenuDirection: "pageSizeMenuDirection", hideRunSelectorsAndCompareButton: "hideRunSelectorsAndCompareButton", isExportingTestPlanCompare: "isExportingTestPlanCompare" }, outputs: { searchRuns: "searchRuns", loadMoreRuns: "loadMoreRuns", compareRuns: "compareRuns", viewCompare: "viewCompare", testCaseClick: "testCaseClick", exportTestPlanCompare: "exportTestPlanCompare" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-ui-root\" style=\"display: flex; flex-direction: column; width: 100%; height: 100%;\">\n <div class=\"cqa-flex cqa-flex-col\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3 sm:cqa-gap-4 cqa-py-3 sm:cqa-py-4 cqa-px-4 sm:cqa-px-6\" style=\"border-bottom: 1px solid #E4E4E4\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-mb-1\">\n <span class=\"cqa-text-[11px] cqa-text-[#6B7280]\">Status legend:</span>\n <div class=\"cqa-flex cqa-items-center cqa-gap-3\">\n <!-- Passed -->\n <span class=\"cqa-inline-flex cqa-items-center cqa-gap-1\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M7.99998 14.6663C11.6819 14.6663 14.6666 11.6816 14.6666 7.99967C14.6666 4.31778 11.6819 1.33301 7.99998 1.33301C4.31808 1.33301 1.33331 4.31778 1.33331 7.99967C1.33331 11.6816 4.31808 14.6663 7.99998 14.6663Z\" stroke=\"#0B9D68\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6 8.00033L7.33333 9.33366L10 6.66699\" stroke=\"#0B9D68\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span class=\"cqa-text-[11px] cqa-text-[#0B9D68] cqa-font-medium\">Passed</span>\n </span>\n <!-- Failed -->\n <span class=\"cqa-inline-flex cqa-items-center cqa-gap-1\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M8.00004 14.6673C11.6819 14.6673 14.6667 11.6825 14.6667 8.00065C14.6667 4.31875 11.6819 1.33398 8.00004 1.33398C4.31814 1.33398 1.33337 4.31875 1.33337 8.00065C1.33337 11.6825 4.31814 14.6673 8.00004 14.6673Z\" stroke=\"#FB2C36\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M10 6L6 10\" stroke=\"#FB2C36\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6 6L10 10\" stroke=\"#FB2C36\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span class=\"cqa-text-[11px] cqa-text-[#FB2C36] cqa-font-medium\">Failed</span>\n </span>\n <!-- Aborted -->\n <span class=\"cqa-inline-flex cqa-items-center cqa-gap-1\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M8.00004 14.6673C11.6819 14.6673 14.6667 11.6825 14.6667 8.00065C14.6667 4.31875 11.6819 1.33398 8.00004 1.33398C4.31814 1.33398 1.33337 4.31875 1.33337 8.00065C1.33337 11.6825 4.31814 14.6673 8.00004 14.6673Z\" stroke=\"#F59E0B\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6 8H10\" stroke=\"#F59E0B\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span class=\"cqa-text-[11px] cqa-text-[#F59E0B] cqa-font-medium\">Aborted</span>\n </span>\n </div>\n </div>\n\n <div *ngIf=\"!hideRunSelectorsAndCompareButton\" class=\"cqa-grid cqa-grid-cols-1 md:cqa-grid-cols-2 cqa-gap-4 md:cqa-gap-16 cqa-relative\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5\">\n <span class=\"cqa-text-[12px] cqa-font-semibold cqa-text-[#636363]\">Run A (Base)</span>\n <cqa-dynamic-select \n [form]=\"form\" \n [config]=\"runASelectConfig\"\n (searchChange)=\"onSearchChange($event)\"\n (loadMore)=\"onLoadMore($event)\">\n </cqa-dynamic-select>\n </div>\n \n <div class=\"cqa-hidden md:cqa-flex cqa-items-center cqa-justify-center\" style=\"position: absolute; left: 50%; transform: translateX(-50%); top: 30px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M4.16669 10H15.8334\" stroke=\"#636363\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M10 4.16699L15.8333 10.0003L10 15.8337\" stroke=\"#636363\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n \n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5\">\n <span class=\"cqa-text-[12px] cqa-font-semibold cqa-text-[#636363]\">Run B (Compare)</span>\n <cqa-dynamic-select \n [form]=\"form\" \n [config]=\"runBSelectConfig\"\n (searchChange)=\"onSearchChange($event)\"\n (loadMore)=\"onLoadMore($event)\">\n </cqa-dynamic-select>\n </div>\n </div>\n \n <ng-container *ngIf=\"selectedRunA || selectedRunB\">\n <div class=\"cqa-grid cqa-grid-cols-1 md:cqa-grid-cols-2 cqa-gap-4\">\n <div class=\"cqa-bg-white cqa-rounded-lg cqa-p-3\"\n [style.background-color]=\"selectedRunA ? runAStatusBgColor : null\"\n [style.border-color]=\"selectedRunA ? runAStatusBorderColor : null\"\n [ngClass]=\"{'cqa-border cqa-border-solid': selectedRunA}\">\n <ng-container *ngIf=\"selectedRunA\">\n <div class=\"cqa-flex cqa-items-start cqa-justify-between cqa-mb-2\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1\">\n <span class=\"cqa-text-[12px] cqa-font-semibold cqa-text-[#0B0B0B]\">Run #{{ selectedRunA.id }}</span>\n </div>\n <span class=\"cqa-inline-flex cqa-items-center cqa-justify-center cqa-px-2 cqa-py-0.5 cqa-rounded-full cqa-text-[10px] cqa-font-medium\"\n [style.background-color]=\"runAStatusColor\"\n [style.color]=\"'#FFFFFF'\">\n {{ runAStatusLabel }}\n </span>\n </div>\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Time: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ formatTime(selectedRunA.startTime) }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Duration: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ formatDurationString(selectedRunA.duration) }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Env: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ selectedRunA.environment || 'NA' }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\" *ngIf=\"selectedRunA.device\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">{{ selectedRunA?.platform === 'desktop' ? 'Browser' : 'Device' }}: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ selectedRunA.device }}</span>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-bg-white cqa-rounded-lg cqa-p-3\"\n [style.background-color]=\"selectedRunB ? runBStatusBgColor : null\"\n [style.border-color]=\"selectedRunB ? runBStatusBorderColor : null\"\n [ngClass]=\"{'cqa-border cqa-border-solid': selectedRunB}\">\n <ng-container *ngIf=\"selectedRunB\">\n <div class=\"cqa-flex cqa-items-start cqa-justify-between cqa-mb-2\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1\">\n <span class=\"cqa-text-[12px] cqa-font-semibold cqa-text-[#0B0B0B]\">Run #{{ selectedRunB.id }}</span>\n </div>\n <span class=\"cqa-inline-flex cqa-items-center cqa-justify-center cqa-px-2 cqa-py-0.5 cqa-rounded-full cqa-text-[10px] cqa-font-medium\"\n [style.background-color]=\"runBStatusColor\"\n [style.color]=\"'#FFFFFF'\">\n {{ runBStatusLabel }}\n </span>\n </div>\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Time: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ formatTime(selectedRunB.startTime) }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Duration: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ formatDurationString(selectedRunB.duration) }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Env: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ selectedRunB.environment || 'NA' }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\" *ngIf=\"selectedRunB.device\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">{{ selectedRunB?.platform === 'desktop' ? 'Browser' : 'Device' }}: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ selectedRunB.device }}</span>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n </ng-container>\n\n <div *ngIf=\"!hideRunSelectorsAndCompareButton\" class=\"cqa-w-full cqa-flex cqa-items-center cqa-justify-center cqa-gap-3\">\n <cqa-button \n variant=\"filled\" \n [disabled]=\"!canCompare\"\n (click)=\"onCompareClick()\">\n {{ isComparingRuns ? 'Comparing...' : 'Compare Runs' }}\n </cqa-button>\n <cqa-button\n *ngIf=\"compareMode === 'testPlan'\"\n variant=\"outlined\"\n [text]=\"isExportingTestPlanCompare ? 'Exporting\u2026' : 'Export'\"\n [loading]=\"isExportingTestPlanCompare\"\n [disabled]=\"!canCompare\"\n (clicked)=\"onExportTestPlanCompare()\"\n ></cqa-button>\n </div>\n </div>\n\n <div\n *ngIf=\"showComparison && compareMode === 'testPlan' && testPlanCardSummary && stepComparisons && stepComparisons.length > 0\"\n class=\"cqa-bg-white cqa-py-3 sm:cqa-py-4 cqa-px-3 sm:cqa-px-6\"\n style=\"flex-shrink: 0;\"\n >\n <div\n class=\"cqa-flex cqa-flex-row cqa-flex-wrap cqa-items-stretch cqa-justify-between sm:cqa-justify-start cqa-gap-2 sm:cqa-gap-3\"\n >\n <div\n class=\"cqa-flex cqa-min-w-0 cqa-flex-[1_1_72px] sm:cqa-flex-none sm:cqa-w-[92px] cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-1 cqa-rounded-xl cqa-border cqa-border-solid cqa-border-[#A5B4FC] cqa-bg-[#EEF2FF] cqa-py-3 cqa-px-2\"\n >\n <span class=\"cqa-text-xl cqa-font-bold cqa-leading-none cqa-text-[#1E293B]\">{{ testPlanCardSummary.totalCases }}</span>\n <span class=\"cqa-text-center cqa-text-[10px] cqa-font-semibold cqa-leading-tight cqa-text-[#64748B]\">Total Cases</span>\n </div>\n <div\n class=\"cqa-flex cqa-min-w-0 cqa-flex-[1_1_72px] sm:cqa-flex-none sm:cqa-w-[88px] cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-1 cqa-rounded-xl cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-bg-white cqa-py-3 cqa-px-2\"\n >\n <span class=\"cqa-text-xl cqa-font-bold cqa-leading-none cqa-text-[#00A63E]\">{{ testPlanCardSummary.passed }}</span>\n <span class=\"cqa-text-center cqa-text-[10px] cqa-font-semibold cqa-leading-tight cqa-text-[#6B7280]\">Passed</span>\n </div>\n <div\n class=\"cqa-flex cqa-min-w-0 cqa-flex-[1_1_72px] sm:cqa-flex-none sm:cqa-w-[88px] cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-1 cqa-rounded-xl cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-bg-white cqa-py-3 cqa-px-2\"\n >\n <span class=\"cqa-text-xl cqa-font-bold cqa-leading-none cqa-text-[#FB2C36]\">{{ testPlanCardSummary.failed }}</span>\n <span class=\"cqa-text-center cqa-text-[10px] cqa-font-semibold cqa-leading-tight cqa-text-[#6B7280]\">Failed</span>\n </div>\n <div\n class=\"cqa-flex cqa-min-w-0 cqa-flex-[1_1_72px] sm:cqa-flex-none sm:cqa-w-[88px] cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-1 cqa-rounded-xl cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-bg-white cqa-py-3 cqa-px-2\"\n >\n <span class=\"cqa-text-xl cqa-font-bold cqa-leading-none cqa-text-[#FB2C36]\">{{ testPlanCardSummary.regressions }}</span>\n <span class=\"cqa-text-center cqa-text-[10px] cqa-font-semibold cqa-leading-tight cqa-text-[#6B7280]\">Regressions</span>\n </div>\n <div\n class=\"cqa-flex cqa-min-w-0 cqa-flex-[1_1_72px] sm:cqa-flex-none sm:cqa-w-[88px] cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-1 cqa-rounded-xl cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-bg-white cqa-py-3 cqa-px-2\"\n >\n <span class=\"cqa-text-xl cqa-font-bold cqa-leading-none cqa-text-[#00A63E]\">{{ testPlanCardSummary.fixed }}</span>\n <span class=\"cqa-text-center cqa-text-[10px] cqa-font-semibold cqa-leading-tight cqa-text-[#6B7280]\">Fixed</span>\n </div>\n <div\n class=\"cqa-flex cqa-min-w-0 cqa-flex-[1_1_72px] sm:cqa-flex-none sm:cqa-w-[88px] cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-1 cqa-rounded-xl cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-bg-white cqa-py-3 cqa-px-2\"\n >\n <span class=\"cqa-text-xl cqa-font-bold cqa-leading-none cqa-text-[#155DFC]\">{{ testPlanCardSummary.newSteps }}</span>\n <span class=\"cqa-text-center cqa-text-[10px] cqa-font-semibold cqa-leading-tight cqa-text-[#6B7280]\">New</span>\n </div>\n <div\n class=\"cqa-flex cqa-min-w-0 cqa-flex-[1_1_72px] sm:cqa-flex-none sm:cqa-w-[88px] cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-1 cqa-rounded-xl cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-bg-white cqa-py-3 cqa-px-2\"\n >\n <span class=\"cqa-text-xl cqa-font-bold cqa-leading-none cqa-text-[#6B7280]\">{{ testPlanCardSummary.removed }}</span>\n <span class=\"cqa-text-center cqa-text-[10px] cqa-font-semibold cqa-leading-tight cqa-text-[#6B7280]\">Removed</span>\n </div>\n <div\n class=\"cqa-flex cqa-min-w-0 cqa-flex-[1_1_72px] sm:cqa-flex-none sm:cqa-w-[88px] cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-1 cqa-rounded-xl cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-bg-white cqa-py-3 cqa-px-2\"\n >\n <span class=\"cqa-text-xl cqa-font-bold cqa-leading-none cqa-text-[#6B7280]\">{{ testPlanCardSummary.noChange }}</span>\n <span class=\"cqa-text-center cqa-text-[10px] cqa-font-semibold cqa-leading-tight cqa-text-[#6B7280]\">No Change</span>\n </div>\n </div>\n </div>\n\n <div\n *ngIf=\"showComparison && compareMode !== 'testPlan' && comparisonSummary && stepComparisons && stepComparisons.length > 0\"\n class=\"cqa-bg-white cqa-py-3 sm:cqa-py-4 cqa-px-3 sm:cqa-px-6 cqa-flex cqa-items-center cqa-gap-3 sm:cqa-gap-4\"\n style=\"flex-shrink: 0;\"\n >\n <p class=\"cqa-text-[12px] cqa-text-[#636363]\">Summary:</p>\n <div class=\"cqa-flex cqa-flex-wrap cqa-items-center cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"cqa-w-[14px] cqa-h-[14px] cqa-text-sm\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path d=\"M2.91669 5.25H11.0834\" stroke=\"#636363\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M2.91669 8.75H11.0834\" stroke=\"#636363\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <span class=\"cqa-text-sm cqa-font-semibold leading-normal cqa-text-[#0B0B0B]\">{{ comparisonSummary.unchanged }}</span>\n <span class=\"cqa-text-[10px] cqa-font-semibold cqa-text-[#6B7280]\">Unchanged</span>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"cqa-flex-shrink-0 cqa-w-[14px] cqa-h-[14px] cqa-text-sm\">\n <svg fill=\"#000000\" viewBox=\"0 0 24 24\" id=\"update-alt-2\" data-name=\"Flat Color\" xmlns=\"http://www.w3.org/2000/svg\" class=\"icon flat-color\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path id=\"primary\" d=\"M21.71,10.29a1,1,0,0,0-1.42,0L19,11.59V7a3,3,0,0,0-3-3H6A1,1,0,0,0,6,6H16a1,1,0,0,1,1,1v4.59l-1.29-1.3a1,1,0,0,0-1.42,1.42l3,3a1,1,0,0,0,1.42,0l3-3A1,1,0,0,0,21.71,10.29Z\" fill=\"#155DFC\"></path>\n <path id=\"secondary\" d=\"M18,18H8a1,1,0,0,1-1-1V12.41l1.29,1.3a1,1,0,0,0,1.42,0,1,1,0,0,0,0-1.42l-3-3a1,1,0,0,0-1.42,0l-3,3a1,1,0,0,0,1.42,1.42L5,12.41V17a3,3,0,0,0,3,3H18a1,1,0,0,0,0-2Z\" fill=\"#155DFC\"></path>\n </g>\n </svg>\n </mat-icon>\n <span class=\"cqa-text-sm cqa-font-semibold leading-normal cqa-text-[#155DFC]\">{{ comparisonSummary.statusChanged }}</span>\n <span class=\"cqa-text-[10px] cqa-font-semibold cqa-text-[#6B7280]\">Status Changed</span>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"cqa-flex-shrink-0 cqa-w-[14px] cqa-h-[14px] cqa-text-sm\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path d=\"M2.91669 7H11.0834\" stroke=\"#00C950\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M7 2.91699V11.0837\" stroke=\"#00C950\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <span class=\"cqa-text-sm cqa-font-semibold leading-normal cqa-text-[#00A63E]\">{{ comparisonSummary.added }}</span>\n <span class=\"cqa-text-[10px] cqa-font-semibold cqa-text-[#6B7280]\">Added</span>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"cqa-flex-shrink-0 cqa-w-[14px] cqa-h-[14px] cqa-text-sm\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path d=\"M2.91669 7H11.0834\" stroke=\"#FB2C36\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <span class=\"cqa-text-sm cqa-font-semibold leading-normal cqa-text-[#FB2C36]\">{{ comparisonSummary.removed }}</span>\n <span class=\"cqa-text-[10px] cqa-font-semibold cqa-text-[#6B7280]\">Removed</span>\n </div>\n </div>\n </div>\n\n <div class=\"cqa-bg-white cqa-rounded-lg\" style=\"overflow-y: auto; max-height: calc(90dvh - 468px); scrollbar-width: thin;\">\n <cqa-table-template style=\"height: 100%; display: block;\"\n [columns]=\"tableColumns\"\n [data]=\"stepComparisons\"\n [pageIndex]=\"pageIndex\"\n [pageSize]=\"pageSize\"\n [pageSizeMenuDirection]=\"pageSizeMenuDirection\"\n [isEmptyState]=\"isEmptyState\"\n [emptyStateConfig]=\"emptyStateConfig\"\n [isTableDataLoading]=\"isComparingRuns\"\n [showSearchBar]=\"false\"\n [showFilterButton]=\"false\"\n [showSettingsButton]=\"false\"\n [showAutoRefreshButton]=\"false\"\n [showOtherButton]=\"false\"\n [showFilterPanel]=\"false\"\n [serverSidePagination]=\"false\"\n (pageChange)=\"onPageChange($event)\">\n </cqa-table-template>\n </div>\n\n </div>\n</div>\n\n", components: [{ type: DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore", "addCustomValue"] }, { type: ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "loading", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { type: i1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: TableTemplateComponent, selector: "cqa-table-template", inputs: ["searchPlaceholder", "searchValue", "showClear", "showSearchBar", "showExportButton", "isExporting", "filterConfig", "filterModel", "showFilterPanel", "showFilterButton", "otherButtons", "otherDropDownButtons", "otherSelectDropDownButtons", "otherButtonLabel", "otherButtonVariant", "showOtherButton", "showActionButton", "showSettingsButton", "showAutoRefreshButton", "data", "isEmptyState", "emptyStateConfig", "actions", "chips", "filterApplied", "columns", "rowSelectable", "selectedAutoRefreshInterval", "pageIndex", "pageSize", "pageSizeOptions", "pageSizeMenuDirection", "serverSidePagination", "totalElements", "enableLocalSort", "isTableLoading", "isTableDataLoading", "cellJsonPathGetter", "onJsonPathCopiedHandler", "selectedItems"], outputs: ["onSearchChange", "onExportClick", "onApplyFilterClick", "onResetFilterClick", "onClearAll", "removeChip", "pageChange", "sortChange", "onReload", "onAutoRefreshClick"] }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
20098
20244
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: CompareRunsComponent, decorators: [{
|
|
20099
20245
|
type: Component,
|
|
20100
|
-
args: [{ selector: 'cqa-compare-runs', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"cqa-ui-root\" style=\"display: flex; flex-direction: column; width: 100%; height: 100%;\">\n <div class=\"cqa-flex cqa-flex-col\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3 sm:cqa-gap-4 cqa-py-3 sm:cqa-py-4 cqa-px-4 sm:cqa-px-6\" style=\"border-bottom: 1px solid #E4E4E4\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-mb-1\">\n <span class=\"cqa-text-[11px] cqa-text-[#6B7280]\">Status legend:</span>\n <div class=\"cqa-flex cqa-items-center cqa-gap-3\">\n <!-- Passed -->\n <span class=\"cqa-inline-flex cqa-items-center cqa-gap-1\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M7.99998 14.6663C11.6819 14.6663 14.6666 11.6816 14.6666 7.99967C14.6666 4.31778 11.6819 1.33301 7.99998 1.33301C4.31808 1.33301 1.33331 4.31778 1.33331 7.99967C1.33331 11.6816 4.31808 14.6663 7.99998 14.6663Z\" stroke=\"#0B9D68\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6 8.00033L7.33333 9.33366L10 6.66699\" stroke=\"#0B9D68\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span class=\"cqa-text-[11px] cqa-text-[#0B9D68] cqa-font-medium\">Passed</span>\n </span>\n <!-- Failed -->\n <span class=\"cqa-inline-flex cqa-items-center cqa-gap-1\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M8.00004 14.6673C11.6819 14.6673 14.6667 11.6825 14.6667 8.00065C14.6667 4.31875 11.6819 1.33398 8.00004 1.33398C4.31814 1.33398 1.33337 4.31875 1.33337 8.00065C1.33337 11.6825 4.31814 14.6673 8.00004 14.6673Z\" stroke=\"#FB2C36\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M10 6L6 10\" stroke=\"#FB2C36\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6 6L10 10\" stroke=\"#FB2C36\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span class=\"cqa-text-[11px] cqa-text-[#FB2C36] cqa-font-medium\">Failed</span>\n </span>\n <!-- Aborted -->\n <span class=\"cqa-inline-flex cqa-items-center cqa-gap-1\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M8.00004 14.6673C11.6819 14.6673 14.6667 11.6825 14.6667 8.00065C14.6667 4.31875 11.6819 1.33398 8.00004 1.33398C4.31814 1.33398 1.33337 4.31875 1.33337 8.00065C1.33337 11.6825 4.31814 14.6673 8.00004 14.6673Z\" stroke=\"#F59E0B\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6 8H10\" stroke=\"#F59E0B\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span class=\"cqa-text-[11px] cqa-text-[#F59E0B] cqa-font-medium\">Aborted</span>\n </span>\n </div>\n </div>\n\n <div *ngIf=\"!hideRunSelectorsAndCompareButton\" class=\"cqa-grid cqa-grid-cols-1 md:cqa-grid-cols-2 cqa-gap-4 md:cqa-gap-16 cqa-relative\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5\">\n <span class=\"cqa-text-[12px] cqa-font-semibold cqa-text-[#636363]\">Run A (Base)</span>\n <cqa-dynamic-select \n [form]=\"form\" \n [config]=\"runASelectConfig\"\n (searchChange)=\"onSearchChange($event)\"\n (loadMore)=\"onLoadMore($event)\">\n </cqa-dynamic-select>\n </div>\n \n <div class=\"cqa-hidden md:cqa-flex cqa-items-center cqa-justify-center\" style=\"position: absolute; left: 50%; transform: translateX(-50%); top: 30px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M4.16669 10H15.8334\" stroke=\"#636363\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M10 4.16699L15.8333 10.0003L10 15.8337\" stroke=\"#636363\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n \n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5\">\n <span class=\"cqa-text-[12px] cqa-font-semibold cqa-text-[#636363]\">Run B (Compare)</span>\n <cqa-dynamic-select \n [form]=\"form\" \n [config]=\"runBSelectConfig\"\n (searchChange)=\"onSearchChange($event)\"\n (loadMore)=\"onLoadMore($event)\">\n </cqa-dynamic-select>\n </div>\n </div>\n \n <ng-container *ngIf=\"selectedRunA || selectedRunB\">\n <div class=\"cqa-grid cqa-grid-cols-1 md:cqa-grid-cols-2 cqa-gap-4\">\n <div class=\"cqa-bg-white cqa-rounded-lg cqa-p-3\"\n [style.background-color]=\"selectedRunA ? runAStatusBgColor : null\"\n [style.border-color]=\"selectedRunA ? runAStatusBorderColor : null\"\n [ngClass]=\"{'cqa-border cqa-border-solid': selectedRunA}\">\n <ng-container *ngIf=\"selectedRunA\">\n <div class=\"cqa-flex cqa-items-start cqa-justify-between cqa-mb-2\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1\">\n <span class=\"cqa-text-[12px] cqa-font-semibold cqa-text-[#0B0B0B]\">Run #{{ selectedRunA.id }}</span>\n </div>\n <span class=\"cqa-inline-flex cqa-items-center cqa-justify-center cqa-px-2 cqa-py-0.5 cqa-rounded-full cqa-text-[10px] cqa-font-medium\"\n [style.background-color]=\"runAStatusColor\"\n [style.color]=\"'#FFFFFF'\">\n {{ runAStatusLabel }}\n </span>\n </div>\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Time: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ formatTime(selectedRunA.startTime) }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Duration: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ formatDurationString(selectedRunA.duration) }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Env: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ selectedRunA.environment || 'NA' }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\" *ngIf=\"selectedRunA.device\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">{{ selectedRunA?.platform === 'desktop' ? 'Browser' : 'Device' }}: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ selectedRunA.device }}</span>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-bg-white cqa-rounded-lg cqa-p-3\"\n [style.background-color]=\"selectedRunB ? runBStatusBgColor : null\"\n [style.border-color]=\"selectedRunB ? runBStatusBorderColor : null\"\n [ngClass]=\"{'cqa-border cqa-border-solid': selectedRunB}\">\n <ng-container *ngIf=\"selectedRunB\">\n <div class=\"cqa-flex cqa-items-start cqa-justify-between cqa-mb-2\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1\">\n <span class=\"cqa-text-[12px] cqa-font-semibold cqa-text-[#0B0B0B]\">Run #{{ selectedRunB.id }}</span>\n </div>\n <span class=\"cqa-inline-flex cqa-items-center cqa-justify-center cqa-px-2 cqa-py-0.5 cqa-rounded-full cqa-text-[10px] cqa-font-medium\"\n [style.background-color]=\"runBStatusColor\"\n [style.color]=\"'#FFFFFF'\">\n {{ runBStatusLabel }}\n </span>\n </div>\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Time: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ formatTime(selectedRunB.startTime) }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Duration: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ formatDurationString(selectedRunB.duration) }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Env: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ selectedRunB.environment || 'NA' }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\" *ngIf=\"selectedRunB.device\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">{{ selectedRunB?.platform === 'desktop' ? 'Browser' : 'Device' }}: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ selectedRunB.device }}</span>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n </ng-container>\n\n <div *ngIf=\"!hideRunSelectorsAndCompareButton\" class=\"cqa-w-full cqa-flex cqa-items-center cqa-justify-center cqa-gap-3\">\n <cqa-button \n variant=\"filled\" \n [disabled]=\"!canCompare\"\n (click)=\"onCompareClick()\">\n {{ isComparingRuns ? 'Comparing...' : 'Compare Runs' }}\n </cqa-button>\n <cqa-button\n *ngIf=\"compareMode === 'testPlan'\"\n variant=\"outlined\"\n [text]=\"isExportingTestPlanCompare ? 'Exporting\u2026' : 'Export'\"\n [loading]=\"isExportingTestPlanCompare\"\n [disabled]=\"!canCompare\"\n (clicked)=\"onExportTestPlanCompare()\"\n ></cqa-button>\n </div>\n </div>\n\n <div *ngIf=\"showComparison && comparisonSummary && stepComparisons && stepComparisons.length > 0\" \n class=\"cqa-bg-white cqa-py-3 sm:cqa-py-4 cqa-px-3 sm:cqa-px-6 cqa-flex cqa-items-center cqa-gap-3 sm:cqa-gap-4\"\n style=\"flex-shrink: 0;\">\n <p class=\"cqa-text-[12px] cqa-text-[#636363]\">Summary:</p>\n <div class=\"cqa-flex cqa-flex-wrap cqa-items-center cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"cqa-w-[14px] cqa-h-[14px] cqa-text-sm\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path d=\"M2.91669 5.25H11.0834\" stroke=\"#636363\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M2.91669 8.75H11.0834\" stroke=\"#636363\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <span class=\"cqa-text-sm cqa-font-semibold leading-normal cqa-text-[#0B0B0B]\">{{ comparisonSummary.unchanged }}</span>\n <span class=\"cqa-text-[10px] cqa-font-semibold cqa-text-[#6B7280]\">Unchanged</span>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"cqa-flex-shrink-0 cqa-w-[14px] cqa-h-[14px] cqa-text-sm\">\n <svg fill=\"#000000\" viewBox=\"0 0 24 24\" id=\"update-alt-2\" data-name=\"Flat Color\" xmlns=\"http://www.w3.org/2000/svg\" class=\"icon flat-color\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path id=\"primary\" d=\"M21.71,10.29a1,1,0,0,0-1.42,0L19,11.59V7a3,3,0,0,0-3-3H6A1,1,0,0,0,6,6H16a1,1,0,0,1,1,1v4.59l-1.29-1.3a1,1,0,0,0-1.42,1.42l3,3a1,1,0,0,0,1.42,0l3-3A1,1,0,0,0,21.71,10.29Z\" fill=\"#155DFC\"></path>\n <path id=\"secondary\" d=\"M18,18H8a1,1,0,0,1-1-1V12.41l1.29,1.3a1,1,0,0,0,1.42,0,1,1,0,0,0,0-1.42l-3-3a1,1,0,0,0-1.42,0l-3,3a1,1,0,0,0,1.42,1.42L5,12.41V17a3,3,0,0,0,3,3H18a1,1,0,0,0,0-2Z\" fill=\"#155DFC\"></path>\n </g>\n </svg>\n </mat-icon>\n <span class=\"cqa-text-sm cqa-font-semibold leading-normal cqa-text-[#155DFC]\">{{ comparisonSummary.statusChanged }}</span>\n <span class=\"cqa-text-[10px] cqa-font-semibold cqa-text-[#6B7280]\">Status Changed</span>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"cqa-flex-shrink-0 cqa-w-[14px] cqa-h-[14px] cqa-text-sm\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path d=\"M2.91669 7H11.0834\" stroke=\"#00C950\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M7 2.91699V11.0837\" stroke=\"#00C950\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <span class=\"cqa-text-sm cqa-font-semibold leading-normal cqa-text-[#00A63E]\">{{ comparisonSummary.added }}</span>\n <span class=\"cqa-text-[10px] cqa-font-semibold cqa-text-[#6B7280]\">Added</span>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"cqa-flex-shrink-0 cqa-w-[14px] cqa-h-[14px] cqa-text-sm\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path d=\"M2.91669 7H11.0834\" stroke=\"#FB2C36\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <span class=\"cqa-text-sm cqa-font-semibold leading-normal cqa-text-[#FB2C36]\">{{ comparisonSummary.removed }}</span>\n <span class=\"cqa-text-[10px] cqa-font-semibold cqa-text-[#6B7280]\">Removed</span>\n </div>\n\n <!-- Timing Changed summary removed -->\n </div>\n </div>\n\n <div class=\"cqa-bg-white cqa-rounded-lg\" style=\"overflow-y: auto; max-height: calc(90dvh - 468px); scrollbar-width: thin;\">\n <cqa-table-template style=\"height: 100%; display: block;\"\n [columns]=\"tableColumns\"\n [data]=\"stepComparisons\"\n [pageIndex]=\"pageIndex\"\n [pageSize]=\"pageSize\"\n [pageSizeMenuDirection]=\"pageSizeMenuDirection\"\n [isEmptyState]=\"isEmptyState\"\n [emptyStateConfig]=\"emptyStateConfig\"\n [isTableDataLoading]=\"isComparingRuns\"\n [showSearchBar]=\"false\"\n [showFilterButton]=\"false\"\n [showSettingsButton]=\"false\"\n [showAutoRefreshButton]=\"false\"\n [showOtherButton]=\"false\"\n [showFilterPanel]=\"false\"\n [serverSidePagination]=\"false\"\n (pageChange)=\"onPageChange($event)\">\n </cqa-table-template>\n </div>\n\n </div>\n</div>\n\n", styles: [] }]
|
|
20246
|
+
args: [{ selector: 'cqa-compare-runs', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"cqa-ui-root\" style=\"display: flex; flex-direction: column; width: 100%; height: 100%;\">\n <div class=\"cqa-flex cqa-flex-col\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-3 sm:cqa-gap-4 cqa-py-3 sm:cqa-py-4 cqa-px-4 sm:cqa-px-6\" style=\"border-bottom: 1px solid #E4E4E4\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-3 cqa-mb-1\">\n <span class=\"cqa-text-[11px] cqa-text-[#6B7280]\">Status legend:</span>\n <div class=\"cqa-flex cqa-items-center cqa-gap-3\">\n <!-- Passed -->\n <span class=\"cqa-inline-flex cqa-items-center cqa-gap-1\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M7.99998 14.6663C11.6819 14.6663 14.6666 11.6816 14.6666 7.99967C14.6666 4.31778 11.6819 1.33301 7.99998 1.33301C4.31808 1.33301 1.33331 4.31778 1.33331 7.99967C1.33331 11.6816 4.31808 14.6663 7.99998 14.6663Z\" stroke=\"#0B9D68\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6 8.00033L7.33333 9.33366L10 6.66699\" stroke=\"#0B9D68\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span class=\"cqa-text-[11px] cqa-text-[#0B9D68] cqa-font-medium\">Passed</span>\n </span>\n <!-- Failed -->\n <span class=\"cqa-inline-flex cqa-items-center cqa-gap-1\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M8.00004 14.6673C11.6819 14.6673 14.6667 11.6825 14.6667 8.00065C14.6667 4.31875 11.6819 1.33398 8.00004 1.33398C4.31814 1.33398 1.33337 4.31875 1.33337 8.00065C1.33337 11.6825 4.31814 14.6673 8.00004 14.6673Z\" stroke=\"#FB2C36\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M10 6L6 10\" stroke=\"#FB2C36\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6 6L10 10\" stroke=\"#FB2C36\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span class=\"cqa-text-[11px] cqa-text-[#FB2C36] cqa-font-medium\">Failed</span>\n </span>\n <!-- Aborted -->\n <span class=\"cqa-inline-flex cqa-items-center cqa-gap-1\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M8.00004 14.6673C11.6819 14.6673 14.6667 11.6825 14.6667 8.00065C14.6667 4.31875 11.6819 1.33398 8.00004 1.33398C4.31814 1.33398 1.33337 4.31875 1.33337 8.00065C1.33337 11.6825 4.31814 14.6673 8.00004 14.6673Z\" stroke=\"#F59E0B\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6 8H10\" stroke=\"#F59E0B\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <span class=\"cqa-text-[11px] cqa-text-[#F59E0B] cqa-font-medium\">Aborted</span>\n </span>\n </div>\n </div>\n\n <div *ngIf=\"!hideRunSelectorsAndCompareButton\" class=\"cqa-grid cqa-grid-cols-1 md:cqa-grid-cols-2 cqa-gap-4 md:cqa-gap-16 cqa-relative\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5\">\n <span class=\"cqa-text-[12px] cqa-font-semibold cqa-text-[#636363]\">Run A (Base)</span>\n <cqa-dynamic-select \n [form]=\"form\" \n [config]=\"runASelectConfig\"\n (searchChange)=\"onSearchChange($event)\"\n (loadMore)=\"onLoadMore($event)\">\n </cqa-dynamic-select>\n </div>\n \n <div class=\"cqa-hidden md:cqa-flex cqa-items-center cqa-justify-center\" style=\"position: absolute; left: 50%; transform: translateX(-50%); top: 30px;\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M4.16669 10H15.8334\" stroke=\"#636363\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M10 4.16699L15.8333 10.0003L10 15.8337\" stroke=\"#636363\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\n \n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5\">\n <span class=\"cqa-text-[12px] cqa-font-semibold cqa-text-[#636363]\">Run B (Compare)</span>\n <cqa-dynamic-select \n [form]=\"form\" \n [config]=\"runBSelectConfig\"\n (searchChange)=\"onSearchChange($event)\"\n (loadMore)=\"onLoadMore($event)\">\n </cqa-dynamic-select>\n </div>\n </div>\n \n <ng-container *ngIf=\"selectedRunA || selectedRunB\">\n <div class=\"cqa-grid cqa-grid-cols-1 md:cqa-grid-cols-2 cqa-gap-4\">\n <div class=\"cqa-bg-white cqa-rounded-lg cqa-p-3\"\n [style.background-color]=\"selectedRunA ? runAStatusBgColor : null\"\n [style.border-color]=\"selectedRunA ? runAStatusBorderColor : null\"\n [ngClass]=\"{'cqa-border cqa-border-solid': selectedRunA}\">\n <ng-container *ngIf=\"selectedRunA\">\n <div class=\"cqa-flex cqa-items-start cqa-justify-between cqa-mb-2\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1\">\n <span class=\"cqa-text-[12px] cqa-font-semibold cqa-text-[#0B0B0B]\">Run #{{ selectedRunA.id }}</span>\n </div>\n <span class=\"cqa-inline-flex cqa-items-center cqa-justify-center cqa-px-2 cqa-py-0.5 cqa-rounded-full cqa-text-[10px] cqa-font-medium\"\n [style.background-color]=\"runAStatusColor\"\n [style.color]=\"'#FFFFFF'\">\n {{ runAStatusLabel }}\n </span>\n </div>\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Time: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ formatTime(selectedRunA.startTime) }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Duration: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ formatDurationString(selectedRunA.duration) }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Env: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ selectedRunA.environment || 'NA' }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\" *ngIf=\"selectedRunA.device\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">{{ selectedRunA?.platform === 'desktop' ? 'Browser' : 'Device' }}: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ selectedRunA.device }}</span>\n </div>\n </div>\n </ng-container>\n </div>\n \n <div class=\"cqa-bg-white cqa-rounded-lg cqa-p-3\"\n [style.background-color]=\"selectedRunB ? runBStatusBgColor : null\"\n [style.border-color]=\"selectedRunB ? runBStatusBorderColor : null\"\n [ngClass]=\"{'cqa-border cqa-border-solid': selectedRunB}\">\n <ng-container *ngIf=\"selectedRunB\">\n <div class=\"cqa-flex cqa-items-start cqa-justify-between cqa-mb-2\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1\">\n <span class=\"cqa-text-[12px] cqa-font-semibold cqa-text-[#0B0B0B]\">Run #{{ selectedRunB.id }}</span>\n </div>\n <span class=\"cqa-inline-flex cqa-items-center cqa-justify-center cqa-px-2 cqa-py-0.5 cqa-rounded-full cqa-text-[10px] cqa-font-medium\"\n [style.background-color]=\"runBStatusColor\"\n [style.color]=\"'#FFFFFF'\">\n {{ runBStatusLabel }}\n </span>\n </div>\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Time: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ formatTime(selectedRunB.startTime) }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Duration: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ formatDurationString(selectedRunB.duration) }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">Env: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ selectedRunB.environment || 'NA' }}</span>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-1\" *ngIf=\"selectedRunB.device\">\n <span class=\"cqa-text-xs cqa-text-[#636363]\">{{ selectedRunB?.platform === 'desktop' ? 'Browser' : 'Device' }}: </span>\n <span class=\"cqa-text-xs cqa-text-[#0B0B0B] cqa-font-medium\">{{ selectedRunB.device }}</span>\n </div>\n </div>\n </ng-container>\n </div>\n </div>\n </ng-container>\n\n <div *ngIf=\"!hideRunSelectorsAndCompareButton\" class=\"cqa-w-full cqa-flex cqa-items-center cqa-justify-center cqa-gap-3\">\n <cqa-button \n variant=\"filled\" \n [disabled]=\"!canCompare\"\n (click)=\"onCompareClick()\">\n {{ isComparingRuns ? 'Comparing...' : 'Compare Runs' }}\n </cqa-button>\n <cqa-button\n *ngIf=\"compareMode === 'testPlan'\"\n variant=\"outlined\"\n [text]=\"isExportingTestPlanCompare ? 'Exporting\u2026' : 'Export'\"\n [loading]=\"isExportingTestPlanCompare\"\n [disabled]=\"!canCompare\"\n (clicked)=\"onExportTestPlanCompare()\"\n ></cqa-button>\n </div>\n </div>\n\n <div\n *ngIf=\"showComparison && compareMode === 'testPlan' && testPlanCardSummary && stepComparisons && stepComparisons.length > 0\"\n class=\"cqa-bg-white cqa-py-3 sm:cqa-py-4 cqa-px-3 sm:cqa-px-6\"\n style=\"flex-shrink: 0;\"\n >\n <div\n class=\"cqa-flex cqa-flex-row cqa-flex-wrap cqa-items-stretch cqa-justify-between sm:cqa-justify-start cqa-gap-2 sm:cqa-gap-3\"\n >\n <div\n class=\"cqa-flex cqa-min-w-0 cqa-flex-[1_1_72px] sm:cqa-flex-none sm:cqa-w-[92px] cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-1 cqa-rounded-xl cqa-border cqa-border-solid cqa-border-[#A5B4FC] cqa-bg-[#EEF2FF] cqa-py-3 cqa-px-2\"\n >\n <span class=\"cqa-text-xl cqa-font-bold cqa-leading-none cqa-text-[#1E293B]\">{{ testPlanCardSummary.totalCases }}</span>\n <span class=\"cqa-text-center cqa-text-[10px] cqa-font-semibold cqa-leading-tight cqa-text-[#64748B]\">Total Cases</span>\n </div>\n <div\n class=\"cqa-flex cqa-min-w-0 cqa-flex-[1_1_72px] sm:cqa-flex-none sm:cqa-w-[88px] cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-1 cqa-rounded-xl cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-bg-white cqa-py-3 cqa-px-2\"\n >\n <span class=\"cqa-text-xl cqa-font-bold cqa-leading-none cqa-text-[#00A63E]\">{{ testPlanCardSummary.passed }}</span>\n <span class=\"cqa-text-center cqa-text-[10px] cqa-font-semibold cqa-leading-tight cqa-text-[#6B7280]\">Passed</span>\n </div>\n <div\n class=\"cqa-flex cqa-min-w-0 cqa-flex-[1_1_72px] sm:cqa-flex-none sm:cqa-w-[88px] cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-1 cqa-rounded-xl cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-bg-white cqa-py-3 cqa-px-2\"\n >\n <span class=\"cqa-text-xl cqa-font-bold cqa-leading-none cqa-text-[#FB2C36]\">{{ testPlanCardSummary.failed }}</span>\n <span class=\"cqa-text-center cqa-text-[10px] cqa-font-semibold cqa-leading-tight cqa-text-[#6B7280]\">Failed</span>\n </div>\n <div\n class=\"cqa-flex cqa-min-w-0 cqa-flex-[1_1_72px] sm:cqa-flex-none sm:cqa-w-[88px] cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-1 cqa-rounded-xl cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-bg-white cqa-py-3 cqa-px-2\"\n >\n <span class=\"cqa-text-xl cqa-font-bold cqa-leading-none cqa-text-[#FB2C36]\">{{ testPlanCardSummary.regressions }}</span>\n <span class=\"cqa-text-center cqa-text-[10px] cqa-font-semibold cqa-leading-tight cqa-text-[#6B7280]\">Regressions</span>\n </div>\n <div\n class=\"cqa-flex cqa-min-w-0 cqa-flex-[1_1_72px] sm:cqa-flex-none sm:cqa-w-[88px] cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-1 cqa-rounded-xl cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-bg-white cqa-py-3 cqa-px-2\"\n >\n <span class=\"cqa-text-xl cqa-font-bold cqa-leading-none cqa-text-[#00A63E]\">{{ testPlanCardSummary.fixed }}</span>\n <span class=\"cqa-text-center cqa-text-[10px] cqa-font-semibold cqa-leading-tight cqa-text-[#6B7280]\">Fixed</span>\n </div>\n <div\n class=\"cqa-flex cqa-min-w-0 cqa-flex-[1_1_72px] sm:cqa-flex-none sm:cqa-w-[88px] cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-1 cqa-rounded-xl cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-bg-white cqa-py-3 cqa-px-2\"\n >\n <span class=\"cqa-text-xl cqa-font-bold cqa-leading-none cqa-text-[#155DFC]\">{{ testPlanCardSummary.newSteps }}</span>\n <span class=\"cqa-text-center cqa-text-[10px] cqa-font-semibold cqa-leading-tight cqa-text-[#6B7280]\">New</span>\n </div>\n <div\n class=\"cqa-flex cqa-min-w-0 cqa-flex-[1_1_72px] sm:cqa-flex-none sm:cqa-w-[88px] cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-1 cqa-rounded-xl cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-bg-white cqa-py-3 cqa-px-2\"\n >\n <span class=\"cqa-text-xl cqa-font-bold cqa-leading-none cqa-text-[#6B7280]\">{{ testPlanCardSummary.removed }}</span>\n <span class=\"cqa-text-center cqa-text-[10px] cqa-font-semibold cqa-leading-tight cqa-text-[#6B7280]\">Removed</span>\n </div>\n <div\n class=\"cqa-flex cqa-min-w-0 cqa-flex-[1_1_72px] sm:cqa-flex-none sm:cqa-w-[88px] cqa-flex-col cqa-items-center cqa-justify-center cqa-gap-1 cqa-rounded-xl cqa-border cqa-border-solid cqa-border-[#E5E7EB] cqa-bg-white cqa-py-3 cqa-px-2\"\n >\n <span class=\"cqa-text-xl cqa-font-bold cqa-leading-none cqa-text-[#6B7280]\">{{ testPlanCardSummary.noChange }}</span>\n <span class=\"cqa-text-center cqa-text-[10px] cqa-font-semibold cqa-leading-tight cqa-text-[#6B7280]\">No Change</span>\n </div>\n </div>\n </div>\n\n <div\n *ngIf=\"showComparison && compareMode !== 'testPlan' && comparisonSummary && stepComparisons && stepComparisons.length > 0\"\n class=\"cqa-bg-white cqa-py-3 sm:cqa-py-4 cqa-px-3 sm:cqa-px-6 cqa-flex cqa-items-center cqa-gap-3 sm:cqa-gap-4\"\n style=\"flex-shrink: 0;\"\n >\n <p class=\"cqa-text-[12px] cqa-text-[#636363]\">Summary:</p>\n <div class=\"cqa-flex cqa-flex-wrap cqa-items-center cqa-gap-3\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"cqa-w-[14px] cqa-h-[14px] cqa-text-sm\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path d=\"M2.91669 5.25H11.0834\" stroke=\"#636363\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M2.91669 8.75H11.0834\" stroke=\"#636363\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <span class=\"cqa-text-sm cqa-font-semibold leading-normal cqa-text-[#0B0B0B]\">{{ comparisonSummary.unchanged }}</span>\n <span class=\"cqa-text-[10px] cqa-font-semibold cqa-text-[#6B7280]\">Unchanged</span>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"cqa-flex-shrink-0 cqa-w-[14px] cqa-h-[14px] cqa-text-sm\">\n <svg fill=\"#000000\" viewBox=\"0 0 24 24\" id=\"update-alt-2\" data-name=\"Flat Color\" xmlns=\"http://www.w3.org/2000/svg\" class=\"icon flat-color\">\n <g id=\"SVGRepo_bgCarrier\" stroke-width=\"0\"></g>\n <g id=\"SVGRepo_tracerCarrier\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g id=\"SVGRepo_iconCarrier\">\n <path id=\"primary\" d=\"M21.71,10.29a1,1,0,0,0-1.42,0L19,11.59V7a3,3,0,0,0-3-3H6A1,1,0,0,0,6,6H16a1,1,0,0,1,1,1v4.59l-1.29-1.3a1,1,0,0,0-1.42,1.42l3,3a1,1,0,0,0,1.42,0l3-3A1,1,0,0,0,21.71,10.29Z\" fill=\"#155DFC\"></path>\n <path id=\"secondary\" d=\"M18,18H8a1,1,0,0,1-1-1V12.41l1.29,1.3a1,1,0,0,0,1.42,0,1,1,0,0,0,0-1.42l-3-3a1,1,0,0,0-1.42,0l-3,3a1,1,0,0,0,1.42,1.42L5,12.41V17a3,3,0,0,0,3,3H18a1,1,0,0,0,0-2Z\" fill=\"#155DFC\"></path>\n </g>\n </svg>\n </mat-icon>\n <span class=\"cqa-text-sm cqa-font-semibold leading-normal cqa-text-[#155DFC]\">{{ comparisonSummary.statusChanged }}</span>\n <span class=\"cqa-text-[10px] cqa-font-semibold cqa-text-[#6B7280]\">Status Changed</span>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"cqa-flex-shrink-0 cqa-w-[14px] cqa-h-[14px] cqa-text-sm\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path d=\"M2.91669 7H11.0834\" stroke=\"#00C950\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M7 2.91699V11.0837\" stroke=\"#00C950\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <span class=\"cqa-text-sm cqa-font-semibold leading-normal cqa-text-[#00A63E]\">{{ comparisonSummary.added }}</span>\n <span class=\"cqa-text-[10px] cqa-font-semibold cqa-text-[#6B7280]\">Added</span>\n </div>\n\n <div class=\"cqa-flex cqa-items-center cqa-gap-1.5\">\n <mat-icon class=\"cqa-flex-shrink-0 cqa-w-[14px] cqa-h-[14px] cqa-text-sm\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\">\n <path d=\"M2.91669 7H11.0834\" stroke=\"#FB2C36\" stroke-width=\"1.16667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </mat-icon>\n <span class=\"cqa-text-sm cqa-font-semibold leading-normal cqa-text-[#FB2C36]\">{{ comparisonSummary.removed }}</span>\n <span class=\"cqa-text-[10px] cqa-font-semibold cqa-text-[#6B7280]\">Removed</span>\n </div>\n </div>\n </div>\n\n <div class=\"cqa-bg-white cqa-rounded-lg\" style=\"overflow-y: auto; max-height: calc(90dvh - 468px); scrollbar-width: thin;\">\n <cqa-table-template style=\"height: 100%; display: block;\"\n [columns]=\"tableColumns\"\n [data]=\"stepComparisons\"\n [pageIndex]=\"pageIndex\"\n [pageSize]=\"pageSize\"\n [pageSizeMenuDirection]=\"pageSizeMenuDirection\"\n [isEmptyState]=\"isEmptyState\"\n [emptyStateConfig]=\"emptyStateConfig\"\n [isTableDataLoading]=\"isComparingRuns\"\n [showSearchBar]=\"false\"\n [showFilterButton]=\"false\"\n [showSettingsButton]=\"false\"\n [showAutoRefreshButton]=\"false\"\n [showOtherButton]=\"false\"\n [showFilterPanel]=\"false\"\n [serverSidePagination]=\"false\"\n (pageChange)=\"onPageChange($event)\">\n </cqa-table-template>\n </div>\n\n </div>\n</div>\n\n", styles: [] }]
|
|
20101
20247
|
}], ctorParameters: function () { return [{ type: i1$1.FormBuilder }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { runs: [{
|
|
20102
20248
|
type: Input
|
|
20103
20249
|
}], comparisonData: [{
|