diff --git a/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesView.ts b/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesView.ts index 80e9e0bb97..e6984028f8 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesView.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesView.ts @@ -112,7 +112,7 @@ export class ExecutionPlanPropertiesView extends ExecutionPlanPropertiesViewBase this.populateTable(columns, this.convertPropertiesToTableRows(this._model.graphElement?.properties)); } - private convertPropertiesToTableRows(properties: azdata.executionPlan.ExecutionPlanGraphElementProperty[]): Slick.SlickData[] { + private convertPropertiesToTableRows(properties: azdata.executionPlan.ExecutionPlanGraphElementProperty[] | undefined): Slick.SlickData[] { if (!properties) { return []; } diff --git a/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesViewBase.ts b/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesViewBase.ts index 02165fbc59..92950cfd2a 100644 --- a/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesViewBase.ts +++ b/src/sql/workbench/contrib/executionPlan/browser/executionPlanPropertiesViewBase.ts @@ -118,7 +118,13 @@ export abstract class ExecutionPlanPropertiesViewBase extends Disposable impleme this._headerActions = this._register(new ActionBar(this._headerActionsContainer, { orientation: ActionsOrientation.HORIZONTAL, context: this })); - this._headerActions.pushAction([new SortPropertiesByDisplayOrderAction(), new SortPropertiesAlphabeticallyAction(), new SortPropertiesReverseAlphabeticallyAction()], { icon: true, label: false }); + this._headerActions.pushAction([ + new SortPropertiesByDisplayOrderAction(), + new SortPropertiesAlphabeticallyAction(), + new SortPropertiesReverseAlphabeticallyAction(), + new ExpandAllPropertiesAction(), + new CollapseAllPropertiesAction() + ], { icon: true, label: false }); this._propertiesSearchInputContainer = DOM.$('.table-search'); this._propertiesSearchInputContainer.classList.add('codicon', searchIconClassNames); @@ -258,10 +264,36 @@ export abstract class ExecutionPlanPropertiesViewBase extends Disposable impleme this.resizeTable(); } + private repopulateTable() { + this._tableComponent.setData(this.flattenTableData(this._tableData, -1)); + this.resizeTable(); + } + public updateTableColumns(columns: Slick.Column[]) { this._tableComponent.columns = columns; } + public setPropertyRowsExpanded(expand: boolean): void { + this.setPropertyRowsExpandedHelper(this._tableComponent.getData().getItems(), expand); + this.repopulateTable(); + } + + /** + * Expands or collapses the rows of the properties table recursively. + * + * @param rows The rows to be expanded or collapsed. + * @param expand Flag indicating if the rows should be expanded or collapsed. + */ + private setPropertyRowsExpandedHelper(rows: Slick.SlickData[], expand: boolean): void { + rows.forEach(row => { + if (row.treeGridChildren && row.treeGridChildren.length > 0) { + row.expanded = expand; + + this.setPropertyRowsExpandedHelper(row.treeGridChildren, expand); + } + }); + } + private resizeTable(): void { const spaceOccupied = (this._titleBarContainer.getBoundingClientRect().height + this._headerContainer.getBoundingClientRect().height @@ -400,6 +432,32 @@ export enum PropertiesSortType { ReverseAlphabetical } +export class ExpandAllPropertiesAction extends Action { + public static ID = 'ep.propertiesView.expandAllProperties'; + public static LABEL = localize('executionPlanExpandAllProperties', 'Expand All'); + + constructor() { + super(ExpandAllPropertiesAction.ID, ExpandAllPropertiesAction.LABEL, Codicon.expandAll.classNames); + } + + public override async run(context: ExecutionPlanPropertiesViewBase): Promise { + context.setPropertyRowsExpanded(true); + } +} + +export class CollapseAllPropertiesAction extends Action { + public static ID = 'ep.propertiesView.collapseAllProperties'; + public static LABEL = localize('executionPlanCollapseAllProperties', 'Collapse All'); + + constructor() { + super(CollapseAllPropertiesAction.ID, CollapseAllPropertiesAction.LABEL, Codicon.collapseAll.classNames); + } + + public override async run(context: ExecutionPlanPropertiesViewBase): Promise { + context.setPropertyRowsExpanded(false); + } +} + registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) => { const menuBackgroundColor = theme.getColor(listHoverBackground);