Skip to content

Commit 4bf4eed

Browse files
committed
Add UI scaffolding for sort dropdown
1 parent 44a1d19 commit 4bf4eed

File tree

5 files changed

+145
-14
lines changed

5 files changed

+145
-14
lines changed

src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/summaryRowActionBar/summaryRowActionBar.tsx

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { PositronActionBar } from '../../../../../../../platform/positronActionB
1313
import { PositronActionBarContextProvider } from '../../../../../../../platform/positronActionBar/browser/positronActionBarContext.js';
1414
import { ActionBarRegion } from '../../../../../../../platform/positronActionBar/browser/components/actionBarRegion.js';
1515
import { ActionBarFilter, ActionBarFilterHandle } from '../../../../../../../platform/positronActionBar/browser/components/actionBarFilter.js';
16+
import { SummaryRowSortOption } from '../../../../../../services/positronDataExplorer/common/tableSummaryCache.js';
1617

1718
// This is the debounce time for the search input in milliseconds.
1819
// It allows the user to type without triggering a search on every keystroke.
@@ -28,6 +29,8 @@ export const SummaryRowActionBar = ({ instance }: SummaryRowActionBarProps) => {
2829
const [searchText, setSearchText] = useState('');
2930
// State to hold the debounced search text that we use to filter data.
3031
const [debouncedSearchText, setDebouncedSearchText] = useState('');
32+
// State to hold the current sort option
33+
const [sortOption, setSortOption] = useState<SummaryRowSortOption>(SummaryRowSortOption.Original);
3134

3235
/**
3336
* Update the debounced search text after a delay.
@@ -52,21 +55,33 @@ export const SummaryRowActionBar = ({ instance }: SummaryRowActionBarProps) => {
5255
search();
5356
}, [debouncedSearchText, instance]);
5457

58+
/**
59+
* Update the sort option when the user selects a new sort option from the dropdown.
60+
* @param newSortOption The new sort option selected by the user.
61+
*/
62+
const handleSortChanged = (newSortOption: SummaryRowSortOption) => {
63+
setSortOption(newSortOption);
64+
// TODO: Implement sorting logic in the TableSummaryDataGridInstance
65+
// instance.setSortOption(newSortOption);
66+
};
67+
5568

5669
return (
5770
<PositronActionBarContextProvider>
58-
<PositronActionBar>
71+
<PositronActionBar paddingLeft={8} paddingRight={14}>
5972
<ActionBarRegion location='left'>
60-
<SummaryRowSortDropdown />
73+
<SummaryRowSortDropdown
74+
currentSort={sortOption}
75+
onSortChanged={handleSortChanged}
76+
/>
6177
</ActionBarRegion>
6278
<ActionBarRegion location='right'>
6379
<ActionBarFilter
6480
ref={filterRef}
65-
width={150}
81+
width={140}
6682
onFilterTextChanged={filterText => setSearchText(filterText)} />
6783
</ActionBarRegion>
6884
</PositronActionBar>
6985
</PositronActionBarContextProvider>
70-
7186
);
7287
}

src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/summaryRowActionBar/summaryRowSortDropdown.css

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,3 @@
22
* Copyright (C) 2025 Posit Software, PBC. All rights reserved.
33
* Licensed under the Elastic License 2.0. See LICENSE.txt for license information.
44
*--------------------------------------------------------------------------------------------*/
5-
6-
.summary-row-sort-dropdown-container {
7-
margin-left: 8px
8-
}

src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/summaryRowActionBar/summaryRowSortDropdown.tsx

Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,88 @@
33
* Licensed under the Elastic License 2.0. See LICENSE.txt for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6+
import './summaryRowSortDropdown.css';
7+
68
import React from 'react';
79

8-
import './summaryRowSortDropdown.css';
10+
import { ActionBarMenuButton } from '../../../../../../../platform/positronActionBar/browser/components/actionBarMenuButton.js';
11+
import { localize } from '../../../../../../../nls.js';
12+
import { SummaryRowSortOption } from '../../../../../../services/positronDataExplorer/common/tableSummaryCache.js';
13+
14+
/**
15+
* Localized strings.
16+
*/
17+
const positronDataExplorerSummarySort = localize('positron.dataExplorer.sort', "Sort summary row data");
18+
const positronSortByOriginal = localize('positron.dataExplorer.sortByOriginal', "Sort by Original");
19+
const positronSortByNameAsc = localize('positron.dataExplorer.sortByNameAsc', "Sort by Name, Ascending");
20+
const positronSortByNameDesc = localize('positron.dataExplorer.sortByNameDesc', "Sort by Name, Descending");
21+
const positronSortByTypeAsc = localize('positron.dataExplorer.sortByTypeAsc', "Sort by Type, Ascending");
22+
const positronSortByTypeDesc = localize('positron.dataExplorer.sortByTypeDesc', "Sort by Type, Descending");
23+
24+
const sortOptions = [
25+
{
26+
id: SummaryRowSortOption.Original,
27+
label: positronSortByOriginal,
28+
option: SummaryRowSortOption.Original
29+
},
30+
{
31+
id: SummaryRowSortOption.NameAscending,
32+
label: positronSortByNameAsc,
33+
option: SummaryRowSortOption.NameAscending
34+
},
35+
{
36+
id: SummaryRowSortOption.NameDescending,
37+
label: positronSortByNameDesc,
38+
option: SummaryRowSortOption.NameDescending
39+
},
40+
{
41+
id: SummaryRowSortOption.TypeAscending,
42+
label: positronSortByTypeAsc,
43+
option: SummaryRowSortOption.TypeAscending
44+
},
45+
{
46+
id: SummaryRowSortOption.TypeDescending,
47+
label: positronSortByTypeDesc,
48+
option: SummaryRowSortOption.TypeDescending
49+
}
50+
];
51+
52+
// create a map of sort id to sort label for the dropdown
53+
const sortLabelMap = new Map(
54+
sortOptions.map(option => [option.id, option.label])
55+
);
56+
57+
/**
58+
* SummaryRowSortDropdownProps interface.
59+
*/
60+
export interface SummaryRowSortDropdownProps {
61+
currentSort: SummaryRowSortOption; // TODO: replace with backend supported option or map to backend supported options
62+
onSortChanged: (sortOption: SummaryRowSortOption) => void;
63+
}
64+
65+
export const SummaryRowSortDropdown = ({ currentSort, onSortChanged }: SummaryRowSortDropdownProps) => {
66+
// Get the label for the current sort option
67+
const currentSortLabel = sortLabelMap.get(currentSort) || positronSortByOriginal;
68+
69+
// Builds the actions.
70+
const actions = () => {
71+
return sortOptions.map(sortOption => ({
72+
class: undefined,
73+
id: sortOption.id,
74+
label: sortOption.label,
75+
tooltip: sortOption.label,
76+
enabled: true,
77+
checked: currentSort === sortOption.option,
78+
run: () => { onSortChanged(sortOption.option) }
79+
}));
80+
};
981

10-
export const SummaryRowSortDropdown = () => {
1182
return (
12-
<div className='summary-row-sort-dropdown-container'>
13-
<span>Sort by original</span>
14-
</div>
83+
<ActionBarMenuButton
84+
actions={actions}
85+
ariaLabel={positronDataExplorerSummarySort}
86+
label={currentSortLabel}
87+
tooltip={positronDataExplorerSummarySort}
88+
/>
1589
);
1690
}

src/vs/workbench/services/positronDataExplorer/browser/tableSummaryDataGridInstance.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import React, { JSX } from 'react';
99
// Other dependencies.
1010
import { Emitter } from '../../../../base/common/event.js';
1111
import { DataGridInstance } from '../../../browser/positronDataGrid/classes/dataGridInstance.js';
12-
import { TableSummaryCache } from '../common/tableSummaryCache.js';
12+
import { SummaryRowSortOption, TableSummaryCache } from '../common/tableSummaryCache.js';
1313
import { ColumnSummaryCell } from './components/columnSummaryCell.js';
1414
import { BackendState, ColumnDisplayType } from '../../languageRuntime/common/positronDataExplorerComm.js';
1515
import { DataExplorerClientInstance } from '../../languageRuntime/common/languageRuntimeDataExplorerClient.js';
@@ -44,6 +44,11 @@ export class TableSummaryDataGridInstance extends DataGridInstance {
4444
*/
4545
private _searchText?: string;
4646

47+
/**
48+
* The current sort option for the summary rows
49+
*/
50+
private _sortOption?: SummaryRowSortOption // TODO: replace with backend supported sort options type
51+
4752
/**
4853
* The onDidSelectColumn event emitter.
4954
*/
@@ -207,6 +212,7 @@ export class TableSummaryDataGridInstance extends DataGridInstance {
207212
await this._tableSummaryCache.update({
208213
invalidateCache: !!invalidateCache,
209214
searchText: this._searchText,
215+
sortOption: this._sortOption,
210216
firstColumnIndex: rowDescriptor.rowIndex,
211217
screenColumns: this.screenRows
212218
});
@@ -398,6 +404,15 @@ export class TableSummaryDataGridInstance extends DataGridInstance {
398404
await this.fetchData(!this._searchText);
399405
}
400406

407+
/**
408+
* Sets the sort option for the summary rows.
409+
* @param sortOption The sort option used to order the rows.
410+
*/
411+
async setSortOption(sortOption: SummaryRowSortOption): Promise<void> {
412+
this._sortOption = sortOption;
413+
await this.fetchData();
414+
}
415+
401416
//#endregion Public Methods
402417

403418
//#region Private Methods

src/vs/workbench/services/positronDataExplorer/common/tableSummaryCache.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,35 @@ const LARGE_HISTOGRAM_NUM_BINS = 200;
2121
const SMALL_FREQUENCY_TABLE_LIMIT = 8;
2222
const LARGE_FREQUENCY_TABLE_LIMIT = 16;
2323

24+
/**
25+
* TODO: replace with backend supported sort options type
26+
*
27+
* Enum options for sorting the summary row.
28+
*
29+
* These options are used to determine how the summary row data should be sorted.
30+
*
31+
* Each option corresponds to a specific sorting criterion:
32+
* - Original: No sorting, uses the original order of the data
33+
* - NameAscending: Sort by name in ascending order
34+
* - NameDescending: Sort by name in descending order
35+
* - TypeAscending: Sort by the data type of the column field in ascending order, e.g. boolean, number, string
36+
* - TypeDescending: Sort by the data type of the column field in descending order, e.g. string, number, boolean
37+
*/
38+
export enum SummaryRowSortOption {
39+
Original = 'original',
40+
NameAscending = 'name-asc',
41+
NameDescending = 'name-desc',
42+
TypeAscending = 'type-asc',
43+
TypeDescending = 'type-desc'
44+
}
45+
2446
/**
2547
* UpdateDescriptor interface.
2648
*/
2749
interface UpdateDescriptor {
2850
invalidateCache: boolean;
2951
searchText?: string;
52+
sortOption?: SummaryRowSortOption;
3053
firstColumnIndex: number;
3154
screenColumns: number;
3255
}
@@ -59,6 +82,11 @@ export class TableSummaryCache extends Disposable {
5982
*/
6083
private _searchText?: string;
6184

85+
/**
86+
* The sort option used to order the summary rows.
87+
*/
88+
private _sortOption?: SummaryRowSortOption;
89+
6290
/**
6391
* Gets or sets the columns.
6492
*/
@@ -216,10 +244,12 @@ export class TableSummaryCache extends Disposable {
216244
const {
217245
invalidateCache,
218246
searchText,
247+
sortOption,
219248
firstColumnIndex,
220249
screenColumns
221250
} = updateDescriptor;
222251

252+
this._sortOption = sortOption;
223253
const searchTextChanged = searchText !== this._searchText;
224254
this._searchText = searchText;
225255

@@ -261,6 +291,7 @@ export class TableSummaryCache extends Disposable {
261291
const tableSchema = this._searchText
262292
? await this._dataExplorerClientInstance.searchSchema({
263293
searchText: this._searchText,
294+
//sortOption: this._sortOption ?? SummaryRowSortOption.Original,
264295
startIndex: columnIndices[0],
265296
numColumns: columnIndices[columnIndices.length - 1] - columnIndices[0] + 1
266297
})

0 commit comments

Comments
 (0)