diff --git a/packages/devextreme/js/__internal/grids/grid_core/ai_assistant/__tests__/ai_assistant_integration_controller.integration.test.ts b/packages/devextreme/js/__internal/grids/grid_core/ai_assistant/__tests__/ai_assistant_integration_controller.integration.test.ts index 6e75f77f5b45..6a0348944681 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/ai_assistant/__tests__/ai_assistant_integration_controller.integration.test.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/ai_assistant/__tests__/ai_assistant_integration_controller.integration.test.ts @@ -737,6 +737,7 @@ describe('AIAssistantIntegrationController', () => { expect(paging.pageIndex).toBe(0); expect(paging.pageSize).toBe(2); expect(paging.totalCount).toBe(3); + expect(paging.visibleRowCount).toBe(2); }); it('should return empty string for search text when not set', async () => { diff --git a/packages/devextreme/js/__internal/grids/grid_core/ai_assistant/ai_assistant_integration_controller.ts b/packages/devextreme/js/__internal/grids/grid_core/ai_assistant/ai_assistant_integration_controller.ts index d76f646af331..9326628359f2 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/ai_assistant/ai_assistant_integration_controller.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/ai_assistant/ai_assistant_integration_controller.ts @@ -55,6 +55,10 @@ export class AIAssistantIntegrationController extends Controller { pageIndex: this.dataController.pageIndex(), pageSize: this.dataController.pageSize(), totalCount: this.dataController.totalCount(), + visibleRowCount: this.dataController + .getVisibleRows() + .filter((row) => row.rowType === 'data') + .length, }, search: { searchText: this.option('searchPanel.text') ?? '', diff --git a/packages/devextreme/js/__internal/grids/grid_core/ai_assistant/commands/selection.ts b/packages/devextreme/js/__internal/grids/grid_core/ai_assistant/commands/selection.ts index 4fbdf4bed23e..b6b9cbc5ab61 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/ai_assistant/commands/selection.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/ai_assistant/commands/selection.ts @@ -185,6 +185,8 @@ export const selectionByIndexesCommand = defineGridCommand({ + 'Always set scope to choose how indexes are interpreted: ' + '"allPages" — indexes are positions within the currently filtered and sorted dataset, NOT limited to the current page; index 1 is the first row of the dataset, regardless of pageIndex/pageSize. Use this when the user does NOT explicitly refer to the visible page (e.g. "select rows 1 to 100"). ' + '"page" — indexes are positions within the currently rendered page; index 1 is the first data row on the visible page and group/header rows are not counted. Use this ONLY when the user explicitly mentions the current/visible page (e.g. "select the first 3 rows on the current page", "deselect row 2 on this page"). ' + + 'This ALSO covers "select/deselect ALL rows on the current/visible page" when selection.selectAllMode is "allPages" (in that case selectAll/deselectAll cannot target a single page, so use this command instead): list every 1-based index from 1 to paging.visibleRowCount. ' + + 'visibleRowCount is the exact number of data rows currently rendered on the visible page (group/header rows excluded) and is correct for every scrolling mode — do NOT derive the count from pageSize/pageIndex/totalCount, because with virtual or infinite scrolling the rendered rows may span more or fewer than pageSize and totalCount may be unknown (-1). ' + 'Set mode to "select" to add the listed rows to the current selection (multiple calls accumulate, so previously selected ranges are kept); set mode to "deselect" to remove the listed rows from the current selection (e.g. "unselect row 1"). ' + 'To clear selection only within the current selectAll scope, use deselectAll; to clear selection across all pages regardless of selectAllMode, use clearSelection. ' + 'To target rows by key value rather than by index, use selectByKeys.', @@ -223,7 +225,9 @@ export const selectionByIndexesCommand = defineGridCommand({ export const selectAllCommand = defineGridCommand({ name: 'selectAll', - description: 'Select rows. Scope depends on selection.selectAllMode: "allPages" (default) selects across every page; "page" selects only the currently rendered page. If a filter is applied, only rows matching the filter are selected.', + description: 'Select rows. Scope depends on selection.selectAllMode: "allPages" (default) selects across every page; "page" selects only the currently rendered page. If a filter is applied, only rows matching the filter are selected. ' + + 'Use this command ONLY when the scope the user asks for matches selection.selectAllMode: for an unqualified "select all rows" request when selectAllMode is "allPages", or for "select all rows on the current/visible page" when selectAllMode is "page". ' + + 'If the user asks to select all rows on the CURRENT/VISIBLE page but selectAllMode is "allPages", do NOT use this command (it would select every page) — instead use selectionByIndexes with scope "page", mode "select", and indexes listing every row on the current page.', schema: z.object({}).strict(), execute: (component, { success, failure }) => async (): Promise => { const defaultMessage = 'Select all rows.'; @@ -244,7 +248,10 @@ export const selectAllCommand = defineGridCommand({ export const deselectAllCommand = defineGridCommand({ name: 'deselectAll', - description: 'Deselect rows. Scope depends on selection.selectAllMode: "allPages" (default) deselects across every page; "page" deselects only the currently rendered page. If a filter is applied, only rows matching the filter are deselected.', + description: 'Deselect rows. Scope depends on selection.selectAllMode: "allPages" (default) deselects across every page; "page" deselects only the currently rendered page. If a filter is applied, only rows matching the filter are deselected. ' + + 'Use this command ONLY when the scope the user asks for matches selection.selectAllMode: for an unqualified "deselect all rows" request when selectAllMode is "allPages", or for "deselect all rows on the current/visible page" when selectAllMode is "page". ' + + 'If the user asks to deselect all rows on the CURRENT/VISIBLE page but selectAllMode is "allPages", do NOT use this command (it would deselect every page) — instead use selectionByIndexes with scope "page", mode "deselect", and indexes listing every row on the current page. ' + + 'To clear selection across all pages regardless of selectAllMode, use clearSelection.', schema: z.object({}).strict(), execute: (component, { success, failure }) => async (): Promise => { const defaultMessage = 'Deselect all rows.';