From f8097625cffdb7e53977475179d08a9ad1ab8827 Mon Sep 17 00:00:00 2001 From: tammy Date: Tue, 25 Nov 2025 22:26:18 +0530 Subject: [PATCH] feature: Selectall in listview --- .../list-view/list-view.component.html | 337 +++++++++--------- .../list-view/list-view.component.scss | 6 +- .../template/list-view/list-view.component.ts | 82 +++-- .../DigV2/ComplexFields/DataReference.spec.js | 106 ++++++ 4 files changed, 332 insertions(+), 199 deletions(-) diff --git a/packages/angular-sdk-components/src/lib/_components/template/list-view/list-view.component.html b/packages/angular-sdk-components/src/lib/_components/template/list-view/list-view.component.html index cd6d4c27..827ba165 100644 --- a/packages/angular-sdk-components/src/lib/_components/template/list-view/list-view.component.html +++ b/packages/angular-sdk-components/src/lib/_components/template/list-view/list-view.component.html @@ -1,193 +1,196 @@
-

- {{ label }} {{ getResultsText() }} -

- - Search - - +
+

+ {{ label }} {{ getResultsText() }} +

+ + searchSearch + + +
-
- - - - +
- {{ dCol.config.label }} -
- -
-
- -
-
- - - - - - -
-
-
-
- - - - +
- {{ dCol.config.label }} -
- -
-
- -
-
- - - - - - -
-
-
-
-
- - - - - - - - - - -
- - - - - {{ dCol.config.label }} +
+ + + + + + + + + + + + + + + + +
+ + + + + + + + {{ dCol.config.label }} + {{ element[dCol.config.name] || '---' }}
+
+ + + + - + -
+ {{ getValue(col) }} {{ element[dCol.config.name] || '---' }}
-
- - - - - - - - -
- {{ getValue(col) }} -
-
-
- {{ utils.getGenericFieldsLocalizedValue('COSMOSFIELDS.lists', 'No records found.') }} -
+
+
+ {{ utils.getGenericFieldsLocalizedValue('COSMOSFIELDS.lists', 'No records found.') }}
diff --git a/packages/angular-sdk-components/src/lib/_components/template/list-view/list-view.component.scss b/packages/angular-sdk-components/src/lib/_components/template/list-view/list-view.component.scss index 2370af2c..3e217938 100644 --- a/packages/angular-sdk-components/src/lib/_components/template/list-view/list-view.component.scss +++ b/packages/angular-sdk-components/src/lib/_components/template/list-view/list-view.component.scss @@ -1,7 +1,6 @@ .psdk-list-header { border: 1px solid var(--mat-sys-outline-variant); background-color: var(--mat-sys-surface-container); - padding: 0.5rem 0rem; } table { @@ -9,6 +8,11 @@ table { border-bottom: 1px solid var(--app-neutral-light-color); } +.search-label { + display: flex; + align-items: center; +} + ::ng-deep .mat-sort-header-content { white-space: nowrap; } diff --git a/packages/angular-sdk-components/src/lib/_components/template/list-view/list-view.component.ts b/packages/angular-sdk-components/src/lib/_components/template/list-view/list-view.component.ts index c4d41af3..3074e7a9 100644 --- a/packages/angular-sdk-components/src/lib/_components/template/list-view/list-view.component.ts +++ b/packages/angular-sdk-components/src/lib/_components/template/list-view/list-view.component.ts @@ -1,4 +1,5 @@ import { Component, OnInit, Input, ViewChild, forwardRef, OnDestroy } from '@angular/core'; +import { SelectionModel } from '@angular/cdk/collections'; import { CommonModule } from '@angular/common'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatOptionModule } from '@angular/material/core'; @@ -91,6 +92,7 @@ export class ListViewComponent implements OnInit, OnDestroy { @Input() payload; repeatList$: MatTableDataSource; + selection = new SelectionModel(true, []); fields$: any[]; displayedColumns$ = Array(); @@ -402,6 +404,14 @@ export class ListViewComponent implements OnInit, OnDestroy { } this.repeatList$ = new MatTableDataSource(this.updatedRefList); + + if (this.configProps$?.readonlyContextList?.length > 0) { + const readonlyIds = new Set(this.configProps$.readonlyContextList.map(element => element[this.rowID])); + const rowsToSelect = this.repeatList$.data.filter(row => readonlyIds.has(row[this.rowID])); + if (rowsToSelect.length > 0) { + this.selection.select(...rowsToSelect); + } + } this.repeatList$.filterPredicate = this.customFilterPredicate.bind(this); // keeping an original copy to get back after possible sorts, filters and groupBy @@ -531,13 +541,6 @@ export class ListViewComponent implements OnInit, OnDestroy { } } - isChecked(rowIn): any { - const initialVal = false; - return this.configProps$?.readonlyContextList?.reduce((acc, currRow) => { - return acc || rowIn[this.rowID] === currRow[this.rowID]; - }, initialVal); - } - fieldOnChange(row) { const value = row[this.rowID]; const reqObj = {}; @@ -554,32 +557,31 @@ export class ListViewComponent implements OnInit, OnDestroy { this.pConn$?.getListActions?.()?.setSelectedRows([reqObj]); } - onCheckboxClick(row, event) { - const value = row[this.rowID]; - const checked = event?.checked; - const reqObj: any = {}; - if (this.compositeKeys?.length > 1) { - const index = this.response.findIndex(element => element[this.rowID] === value); - const selectedRow = this.response[index]; - this.compositeKeys.forEach(element => { - reqObj[element] = selectedRow[element]; - }); - reqObj.$selected = checked; - } else { - reqObj[this.rowID] = value; - reqObj.$selected = checked; - } - this.pConn$?.getListActions()?.setSelectedRows([reqObj]); + onCheckboxClick(row) { + this.selection.toggle(row); + const requiredValue = this.getSelectedValue(row); + this.pConn$?.getListActions()?.setSelectedRows([requiredValue]); } - // rowClick(row) { - // switch (this.configProps$.rowClickAction) { - // case 'openAssignment': - // this.psService.sendMessage(true); - // this.openAssignment(row); - // break; - // } - // } + isAllSelected() { + const numSelected = this.selection.selected.length; + const numRows = this.repeatList$.data.length; + return numSelected === numRows; + } + + toggleAllRows() { + if (this.isAllSelected()) { + this.selection.clear(); + this.pConn$?.getListActions()?.clearSelectedRows(); + return; + } + if (this.selection.hasValue() && !this.isAllSelected()) { + this.pConn$?.getListActions()?.clearSelectedRows(); + } + this.selection.select(...this.repeatList$.data); + const requiredValues = this.repeatList$.data.map(row => this.getSelectedValue(row)); + this.pConn$?.getListActions()?.setSelectedRows(requiredValues); + } _getIconStyle(level): string { let sReturn = ''; @@ -1442,6 +1444,24 @@ export class ListViewComponent implements OnInit, OnDestroy { return select; } + private getSelectedValue(row) { + const value = row[this.rowID]; + const checked = this.selection.isSelected(row); + const reqObj: any = {}; + if (this.compositeKeys?.length > 1) { + const index = this.response.findIndex(element => element[this.rowID] === value); + const selectedRow = this.response[index]; + this.compositeKeys.forEach(element => { + reqObj[element] = selectedRow[element]; + }); + reqObj.$selected = checked; + } else { + reqObj[this.rowID] = value; + reqObj.$selected = checked; + } + return reqObj; + } + private updateFiltersFromData(data) { if (this.displayAs === 'advancedSearch') { this.filters = {}; diff --git a/projects/angular-test-app/tests/e2e/DigV2/ComplexFields/DataReference.spec.js b/projects/angular-test-app/tests/e2e/DigV2/ComplexFields/DataReference.spec.js index c257403e..04405e7d 100644 --- a/projects/angular-test-app/tests/e2e/DigV2/ComplexFields/DataReference.spec.js +++ b/projects/angular-test-app/tests/e2e/DigV2/ComplexFields/DataReference.spec.js @@ -297,6 +297,112 @@ test.describe('E2E test', () => { /** Submitting the case */ await page.locator('button:has-text("submit")').click(); }, 10000); + + test('should login, create case and run select all scenario in Simple Table for Data Reference', async ({ page }) => { + await common.login(config.config.apps.digv2.user.username, config.config.apps.digv2.user.password, page); + + await common.verifyHomePage(page); + + /** Click on the Create Case button */ + await common.createCase('Complex Fields', page); + + /** Selecting Data Reference from the Category dropdown */ + await common.selectCategory('DataReference', page, true); + + await page.locator('button:has-text("submit")').click(); + + /** MultiSelect mode type test */ + await common.selectSubCategory('Mode', page); + + await page.locator('mat-select[data-test-id="6f64b45d01d11d8efd1693dfcb63b735"]').click(); + await page.getByRole('option', { name: 'MultiSelect' }).click(); + + /** Combo-Box mode type test */ + let displayAs = page.locator('mat-select[data-test-id="4aa668349e0970901aa6b11528f95223"]'); + await displayAs.click(); + await page.getByRole('option', { name: 'Simple table' }).click(); + + const table = page.locator('table[id="list-view"]'); + await expect(table).toBeVisible(); + + /** find and click the select all checkbox */ + const selectAllCheckbox = table.locator('thead >> mat-checkbox'); + await selectAllCheckbox.click(); + + await page.locator('button:has-text("Next")').click(); + + const assignment = page.locator('app-default-form'); + + await expect(assignment.locator('td:has-text("Mobile")')).toBeVisible(); + await expect(assignment.locator('td:has-text("Television")')).toBeVisible(); + await expect(assignment.locator('td:has-text("Washing Machine")')).toBeVisible(); + + await page.locator('button:has-text("Previous")').click(); + + /** 'Unselect all' logic here */ + await expect(table).toBeVisible(); + + /** click the select all checkbox to unselect all */ + await selectAllCheckbox.click(); + + await page.locator('button:has-text("Next")').click(); + + await expect(assignment.locator('td:has-text("Mobile")')).not.toBeVisible(); + await expect(assignment.locator('td:has-text("Television")')).not.toBeVisible(); + await expect(assignment.locator('td:has-text("Washing Machine")')).not.toBeVisible(); + + await page.locator('button:has-text("Previous")').click(); + + await expect(table).toBeVisible(); + + /** select mobile, washing machine checkbox rows */ + await table.locator('tr:has-text("Mobile")').locator('mat-checkbox').click(); + await table.locator('tr:has-text("Washing Machine")').locator('mat-checkbox').click(); + + /** now select all checkbox should be in indeterminate state */ + await expect(selectAllCheckbox.locator('input[type="checkbox"]')).toHaveAttribute('aria-checked', 'mixed'); + + await page.locator('button:has-text("Next")').click(); + + /** confirm screen should display mobile, washing machine */ + await expect(assignment.locator('td:has-text("Mobile")')).toBeVisible(); + await expect(assignment.locator('td:has-text("Washing Machine")')).toBeVisible(); + + await page.locator('button:has-text("Previous")').click(); + + /** now unselect mobile checkbox row */ + await table.locator('tr:has-text("Mobile")').locator('mat-checkbox').click(); + /** now select all checkbox should be in indeterminate state */ + await expect(selectAllCheckbox.locator('input[type="checkbox"]')).toHaveAttribute('aria-checked', 'mixed'); + + await page.locator('button:has-text("Next")').click(); + + /** confirm screen should display only washing machine */ + await expect(assignment.locator('td:has-text("Washing Machine")')).toBeVisible(); + await expect(assignment.locator('td:has-text("Mobile")')).not.toBeVisible(); + + await page.locator('button:has-text("Previous")').click(); + + /** now unselect washing machine checkbox row */ + await table.locator('tr:has-text("Washing Machine")').locator('mat-checkbox').click(); + /** now select all checkbox should be unchecked */ + await expect(selectAllCheckbox.locator('input[type="checkbox"]')).not.toHaveAttribute('aria-checked', 'mixed'); + /** now click on next button */ + await page.locator('button:has-text("Next")').click(); + + /** confirm screen should not display any selected rows */ + await expect(assignment.locator('td:has-text("Washing Machine")')).not.toBeVisible(); + await expect(assignment.locator('td:has-text("Mobile")')).not.toBeVisible(); + + await page.locator('button:has-text("Previous")').click(); + + /** Now select each of the rows one by one and verify that the select all checkbox gets checked */ + await table.locator('tr:has-text("Mobile")').locator('mat-checkbox').click(); + await table.locator('tr:has-text("Television")').locator('mat-checkbox').click(); + await table.locator('tr:has-text("Washing Machine")').locator('mat-checkbox').click(); + /** now select all checkbox should be checked */ + await expect(selectAllCheckbox.locator('input[type="checkbox"]')).toBeChecked(); + }, 10000); }); test.afterEach(async ({ page }) => {