From 02a2c28d0ad7ace3919c038b8e56f0f78d52c5bf Mon Sep 17 00:00:00 2001 From: isabel zimmerman Date: Wed, 2 Jul 2025 15:03:36 -0400 Subject: [PATCH 01/26] make action and button --- .../browser/positronDataExplorerActions.ts | 101 +++++++++++++++++- .../positronDataExplorerInstance.ts | 5 + .../browser/positronDataExplorerInstance.ts | 11 ++ .../browser/tableDataDataGridInstance.tsx | 2 +- 4 files changed, 117 insertions(+), 2 deletions(-) diff --git a/src/vs/workbench/contrib/positronDataExplorerEditor/browser/positronDataExplorerActions.ts b/src/vs/workbench/contrib/positronDataExplorerEditor/browser/positronDataExplorerActions.ts index df49c98b98d9..a9952d0b9bc9 100644 --- a/src/vs/workbench/contrib/positronDataExplorerEditor/browser/positronDataExplorerActions.ts +++ b/src/vs/workbench/contrib/positronDataExplorerEditor/browser/positronDataExplorerActions.ts @@ -53,7 +53,8 @@ export const enum PositronDataExplorerCommandId { SummaryOnLeftAction = 'workbench.action.positronDataExplorer.summaryOnLeft', SummaryOnRightAction = 'workbench.action.positronDataExplorer.summaryOnRight', ClearColumnSortingAction = 'workbench.action.positronDataExplorer.clearColumnSorting', - OpenAsPlaintext = 'workbench.action.positronDataExplorer.openAsPlaintext' + OpenAsPlaintext = 'workbench.action.positronDataExplorer.openAsPlaintext', + ExportToCodeAction = 'workbench.action.positronDataExplorer.exportToCode' } /** @@ -688,6 +689,103 @@ class PositronDataExplorerClearColumnSortingAction extends Action2 { } } +/** + * PositronDataExplorerExportToCodeAction action. + */ +class PositronDataExplorerExportToCodeAction extends Action2 { + /** + * Constructor. + */ + constructor() { + super({ + id: PositronDataExplorerCommandId.ExportToCodeAction, + title: { + value: localize('positronDataExplorer.exportToCode', 'Export to Code'), + original: 'Export to Code' + }, + positronActionBarOptions: { + controlType: 'button', + displayTitle: true, + }, + category, + f1: true, + precondition: ContextKeyExpr.and( + POSITRON_DATA_EXPLORER_IS_ACTIVE_EDITOR, + ), + icon: Codicon.code, + menu: [ + { + id: MenuId.EditorActionsLeft, + when: POSITRON_DATA_EXPLORER_IS_ACTIVE_EDITOR, + }, + { + id: MenuId.EditorTitle, + group: 'navigation', + when: POSITRON_DATA_EXPLORER_IS_ACTIVE_EDITOR, + } + ] + }); + } + + /** + * Runs the action. + * @param accessor The services accessor. + */ + async run(accessor: ServicesAccessor): Promise { + // Access the services we need. + const editorService = accessor.get(IEditorService); + const notificationService = accessor.get(INotificationService); + const positronDataExplorerService = accessor.get(IPositronDataExplorerService); + + // Get the Positron data explorer editor. + const positronDataExplorerEditor = getPositronDataExplorerEditorFromEditorPane( + editorService.activeEditorPane + ); + + /** + * Notifies the user that clear sorting failed. + */ + const notifyUserThatCodeCopied = () => { + // Notify the user. + notificationService.notify({ + severity: Severity.Info, + message: localize( + 'positron.dataExplorer.exportToCode.copiedToClipboard', + "Successfully copied code to clipboard." + ), + sticky: false + }); + }; + + // Make sure that the Positron data explorer editor was returned. + if (!positronDataExplorerEditor) { + return; + } + + // Get the identifier. + const identifier = positronDataExplorerEditor.identifier; + + // Make sure the identifier was returned. + if (!identifier) { + return; + } + + // Get the Positron data explorer instance. + const positronDataExplorerInstance = positronDataExplorerService.getInstance( + identifier + ); + + // Make sure the Positron data explorer instance was returned. + if (!positronDataExplorerInstance) { + return; + } + + // Export filters as code. + await positronDataExplorerInstance.exportToCode(); + notifyUserThatCodeCopied(); + } +} + /** * PositronDataExplorerOpenAsPlaintextAction action. */ @@ -787,4 +885,5 @@ export function registerPositronDataExplorerActions() { registerAction2(PositronDataExplorerSummaryOnRightAction); registerAction2(PositronDataExplorerClearColumnSortingAction); registerAction2(PositronDataExplorerOpenAsPlaintextAction); + registerAction2(PositronDataExplorerExportToCodeAction); } diff --git a/src/vs/workbench/services/positronDataExplorer/browser/interfaces/positronDataExplorerInstance.ts b/src/vs/workbench/services/positronDataExplorer/browser/interfaces/positronDataExplorerInstance.ts index a97d9943c479..13d405b718f0 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/interfaces/positronDataExplorerInstance.ts +++ b/src/vs/workbench/services/positronDataExplorer/browser/interfaces/positronDataExplorerInstance.ts @@ -119,4 +119,9 @@ export interface IPositronDataExplorerInstance extends IDisposable { * Copies the table data to the clipboard. */ copyTableDataToClipboard(): Promise; + + /** + * Exports the table data to code. + */ + exportToCode(): Promise; } diff --git a/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerInstance.ts b/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerInstance.ts index 22e2d1b5d31b..1f07a4b70d06 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerInstance.ts +++ b/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerInstance.ts @@ -430,6 +430,17 @@ export class PositronDataExplorerInstance extends Disposable implements IPositro notificationHandle.progress.done(); } + /** + * Export filters as code. + * @returns A Promise that resolves when generated code is copied to clipboard. + */ + async exportToCode(): Promise { + // Write the code to the clipboard. + this._clipboardService.writeText('1234567890'); + await this._tableDataDataGridInstance._tableDataCache.getColumnSchema(0); + } + + /** * onDidClose event. */ diff --git a/src/vs/workbench/services/positronDataExplorer/browser/tableDataDataGridInstance.tsx b/src/vs/workbench/services/positronDataExplorer/browser/tableDataDataGridInstance.tsx index 1deb16278743..79d50168b86a 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/tableDataDataGridInstance.tsx +++ b/src/vs/workbench/services/positronDataExplorer/browser/tableDataDataGridInstance.tsx @@ -72,7 +72,7 @@ export class TableDataDataGridInstance extends DataGridInstance { private readonly _layoutService: ILayoutService, private readonly _hoverService: IHoverService, private readonly _dataExplorerClientInstance: DataExplorerClientInstance, - private readonly _tableDataCache: TableDataCache, + public readonly _tableDataCache: TableDataCache, ) { // Call the base class's constructor. super({ From 6f502e065efe59fc8feef1a306da78b6fee6d267 Mon Sep 17 00:00:00 2001 From: isabel zimmerman Date: Wed, 9 Jul 2025 12:46:42 -0400 Subject: [PATCH 02/26] plumb through comms --- extensions/positron-duckdb/src/interfaces.ts | 1 + .../posit/positron/data_explorer.py | 5 ++ .../posit/positron/data_explorer_comm.py | 81 +++++++++++++++++++ .../comms/data_explorer-backend-openrpc.json | 81 ++++++++++++++++++- .../browser/positronDataExplorerActions.ts | 17 ++-- .../languageRuntimeDataExplorerClient.ts | 15 +++- .../common/positronDataExplorerComm.ts | 65 +++++++++++++++ .../positronDataExplorerInstance.ts | 2 +- .../browser/positronDataExplorerInstance.ts | 16 +++- .../positronDataExplorerDuckDBBackend.ts | 15 ++++ 10 files changed, 284 insertions(+), 14 deletions(-) diff --git a/extensions/positron-duckdb/src/interfaces.ts b/extensions/positron-duckdb/src/interfaces.ts index 4718607ebabb..9141a29f6acb 100644 --- a/extensions/positron-duckdb/src/interfaces.ts +++ b/extensions/positron-duckdb/src/interfaces.ts @@ -1448,6 +1448,7 @@ export enum DataExplorerBackendRequest { GetDataValues = 'get_data_values', GetRowLabels = 'get_row_labels', ExportDataSelection = 'export_data_selection', + ExportToCode = 'export_to_code', SetColumnFilters = 'set_column_filters', SetRowFilters = 'set_row_filters', SetSortColumns = 'set_sort_columns', diff --git a/extensions/positron-python/python_files/posit/positron/data_explorer.py b/extensions/positron-python/python_files/posit/positron/data_explorer.py index dbbc3d8dcac9..60fca71d6377 100644 --- a/extensions/positron-python/python_files/posit/positron/data_explorer.py +++ b/extensions/positron-python/python_files/posit/positron/data_explorer.py @@ -50,8 +50,10 @@ DataSelectionIndices, DataSelectionRange, DataSelectionSingleCell, + ExportAsCodeRequest, ExportDataSelectionFeatures, ExportDataSelectionRequest, + ExportedCode, ExportedData, ExportFormat, FilterBetween, @@ -403,6 +405,9 @@ def export_data_selection(self, request: ExportDataSelectionRequest): else: raise NotImplementedError(f"Unknown data export: {kind}") + def export_as_code(self, request: ExportAsCodeRequest): + return ExportedCode(data="import pandas as pd\n\n# TODO: Implement export to code").dict() + def _export_cell(self, row_index: int, column_index: int, fmt: ExportFormat): raise NotImplementedError diff --git a/extensions/positron-python/python_files/posit/positron/data_explorer_comm.py b/extensions/positron-python/python_files/posit/positron/data_explorer_comm.py index 0f09dcb95071..4f737e207072 100644 --- a/extensions/positron-python/python_files/posit/positron/data_explorer_comm.py +++ b/extensions/positron-python/python_files/posit/positron/data_explorer_comm.py @@ -168,6 +168,23 @@ class ColumnHistogramParamsMethod(str, enum.Enum): Fixed = "fixed" +@enum.unique +class CodeSyntax(str, enum.Enum): + """ + Possible values for CodeSyntax + """ + + Datatable = "datatable" + + Dplyr = "dplyr" + + Pandas = "pandas" + + Polars = "polars" + + BaseR = "baseR" + + @enum.unique class TableSelectionKind(str, enum.Enum): """ @@ -252,6 +269,17 @@ class ExportedData(BaseModel): ) +class ExportedCode(BaseModel): + """ + Resulting code + """ + + data: Optional[StrictStr] = Field( + default=None, + description="Exported code as a string suitable for copy and paste", + ) + + class FilterResult(BaseModel): """ The result of applying filters to a table @@ -1208,6 +1236,9 @@ class DataExplorerBackendRequest(str, enum.Enum): # Export data selection as a string in different formats ExportDataSelection = "export_data_selection" + # Export filters and sort keys as code + ExportAsCode = "export_as_code" + # Set column filters to select subset of table columns SetColumnFilters = "set_column_filters" @@ -1422,6 +1453,49 @@ class ExportDataSelectionRequest(BaseModel): ) +class ExportAsCodeParams(BaseModel): + """ + Export filters and sort keys as code in different formats like pandas, + polars, data.table, dplyr + """ + + column_filters: List[ColumnFilter] = Field( + description="Zero or more column filters to apply", + ) + + row_filters: List[RowFilter] = Field( + description="Zero or more row filters to apply", + ) + + sort_keys: List[ColumnSortKey] = Field( + description="Zero or more sort keys to apply", + ) + + code_syntax: StrictStr = Field( + description="Exported code format", + ) + + +class ExportAsCodeRequest(BaseModel): + """ + Export filters and sort keys as code in different formats like pandas, + polars, data.table, dplyr + """ + + params: ExportAsCodeParams = Field( + description="Parameters to the ExportAsCode method", + ) + + method: Literal[DataExplorerBackendRequest.ExportAsCode] = Field( + description="The JSON-RPC method name (export_as_code)", + ) + + jsonrpc: str = Field( + default="2.0", + description="The JSON-RPC version specifier", + ) + + class SetColumnFiltersParams(BaseModel): """ Set or clear column filters on table, replacing any previous filters @@ -1575,6 +1649,7 @@ class DataExplorerBackendMessageContent(BaseModel): GetDataValuesRequest, GetRowLabelsRequest, ExportDataSelectionRequest, + ExportAsCodeRequest, SetColumnFiltersRequest, SetRowFiltersRequest, SetSortColumnsRequest, @@ -1623,6 +1698,8 @@ class ReturnColumnProfilesParams(BaseModel): ExportedData.update_forward_refs() +ExportedCode.update_forward_refs() + FilterResult.update_forward_refs() BackendState.update_forward_refs() @@ -1741,6 +1818,10 @@ class ReturnColumnProfilesParams(BaseModel): ExportDataSelectionRequest.update_forward_refs() +ExportAsCodeParams.update_forward_refs() + +ExportAsCodeRequest.update_forward_refs() + SetColumnFiltersParams.update_forward_refs() SetColumnFiltersRequest.update_forward_refs() diff --git a/positron/comms/data_explorer-backend-openrpc.json b/positron/comms/data_explorer-backend-openrpc.json index aec2e4f97d6c..6d7132176a64 100644 --- a/positron/comms/data_explorer-backend-openrpc.json +++ b/positron/comms/data_explorer-backend-openrpc.json @@ -215,6 +215,73 @@ } } }, +{ + "name": "export_as_code", + "summary": "Export filters and sort keys as code", + "description": "Export filters and sort keys as code in different formats like pandas, polars, data.table, dplyr", + "params": [ + { + "name": "column_filters", + "description": "Zero or more column filters to apply", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/column_filter" + } + } + }, + { + "name": "row_filters", + "description": "Zero or more row filters to apply", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/row_filter" + } + } + }, + { + "name": "sort_keys", + "description": "Zero or more sort keys to apply", + "required": true, + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/column_sort_key" + } + } + }, + { + "name": "code_syntax", + "description": "Exported code format", + "required": true, + "schema": { + "type": "string", + "items": { + "$ref": "#/components/schemas/code_syntax" + } + } + } + ], + "result": { + "schema": { + "name": "exported_code", + "type": "object", + "description": "Resulting code", + "required": [ + "code" + ], + "properties": { + "data": { + "type": "string", + "description": "Exported code as a string suitable for copy and paste" + } + } + } + } + }, { "name": "set_column_filters", "summary": "Set column filters to select subset of table columns", @@ -1293,6 +1360,17 @@ } } }, + "code_syntax": { + "type": "string", + "description": "The syntax for code", + "enum": [ + "datatable", + "dplyr", + "pandas", + "polars", + "baseR" + ] + }, "supported_features": { "type": "object", "description": "For each field, returns flags indicating supported features", @@ -1302,7 +1380,8 @@ "set_row_filters", "get_column_profiles", "set_sort_columns", - "export_data_selection" + "export_data_selection", + "export_as_code" ], "properties": { "search_schema": { diff --git a/src/vs/workbench/contrib/positronDataExplorerEditor/browser/positronDataExplorerActions.ts b/src/vs/workbench/contrib/positronDataExplorerEditor/browser/positronDataExplorerActions.ts index a9952d0b9bc9..53c1ccb6eab9 100644 --- a/src/vs/workbench/contrib/positronDataExplorerEditor/browser/positronDataExplorerActions.ts +++ b/src/vs/workbench/contrib/positronDataExplorerEditor/browser/positronDataExplorerActions.ts @@ -54,7 +54,7 @@ export const enum PositronDataExplorerCommandId { SummaryOnRightAction = 'workbench.action.positronDataExplorer.summaryOnRight', ClearColumnSortingAction = 'workbench.action.positronDataExplorer.clearColumnSorting', OpenAsPlaintext = 'workbench.action.positronDataExplorer.openAsPlaintext', - ExportToCodeAction = 'workbench.action.positronDataExplorer.exportToCode' + ExportAsCodeAction = 'workbench.action.positronDataExplorer.exportAsCode' } /** @@ -692,16 +692,16 @@ class PositronDataExplorerClearColumnSortingAction extends Action2 { /** * PositronDataExplorerExportToCodeAction action. */ -class PositronDataExplorerExportToCodeAction extends Action2 { +class PositronDataExplorerExportAsCodeAction extends Action2 { /** * Constructor. */ constructor() { super({ - id: PositronDataExplorerCommandId.ExportToCodeAction, + id: PositronDataExplorerCommandId.ExportAsCodeAction, title: { - value: localize('positronDataExplorer.exportToCode', 'Export to Code'), - original: 'Export to Code' + value: localize('positronDataExplorer.exportAsCode', 'Export as Code'), + original: 'Export as Code' }, positronActionBarOptions: { controlType: 'button', @@ -711,6 +711,7 @@ class PositronDataExplorerExportToCodeAction extends Action2 { f1: true, precondition: ContextKeyExpr.and( POSITRON_DATA_EXPLORER_IS_ACTIVE_EDITOR, + IsDevelopmentContext // hide this from release until implemented ), icon: Codicon.code, menu: [ @@ -750,7 +751,7 @@ class PositronDataExplorerExportToCodeAction extends Action2 { notificationService.notify({ severity: Severity.Info, message: localize( - 'positron.dataExplorer.exportToCode.copiedToClipboard', + 'positron.dataExplorer.exportAsCode.copiedToClipboard', "Successfully copied code to clipboard." ), sticky: false @@ -781,7 +782,7 @@ class PositronDataExplorerExportToCodeAction extends Action2 { } // Export filters as code. - await positronDataExplorerInstance.exportToCode(); + await positronDataExplorerInstance.exportAsCode(); notifyUserThatCodeCopied(); } } @@ -885,5 +886,5 @@ export function registerPositronDataExplorerActions() { registerAction2(PositronDataExplorerSummaryOnRightAction); registerAction2(PositronDataExplorerClearColumnSortingAction); registerAction2(PositronDataExplorerOpenAsPlaintextAction); - registerAction2(PositronDataExplorerExportToCodeAction); + registerAction2(PositronDataExplorerExportAsCodeAction); } diff --git a/src/vs/workbench/services/languageRuntime/common/languageRuntimeDataExplorerClient.ts b/src/vs/workbench/services/languageRuntime/common/languageRuntimeDataExplorerClient.ts index 69895159ec18..bc073b0efdde 100644 --- a/src/vs/workbench/services/languageRuntime/common/languageRuntimeDataExplorerClient.ts +++ b/src/vs/workbench/services/languageRuntime/common/languageRuntimeDataExplorerClient.ts @@ -8,7 +8,7 @@ import { Emitter, Event } from '../../../../base/common/event.js'; import { Disposable } from '../../../../base/common/lifecycle.js'; import { URI } from '../../../../base/common/uri.js'; import { generateUuid } from '../../../../base/common/uuid.js'; -import { ArraySelection, BackendState, ColumnFilter, ColumnProfileRequest, ColumnProfileResult, ColumnSchema, ColumnSelection, ColumnSortKey, DataExplorerFrontendEvent, DataUpdateEvent, ExportedData, ExportFormat, FilterResult, FormatOptions, ReturnColumnProfilesEvent, RowFilter, SchemaUpdateEvent, SupportedFeatures, SupportStatus, TableData, TableRowLabels, TableSchema, TableSelection } from './positronDataExplorerComm.js'; +import { ArraySelection, BackendState, CodeSyntax, ColumnFilter, ColumnProfileRequest, ColumnProfileResult, ColumnSchema, ColumnSelection, ColumnSortKey, DataExplorerFrontendEvent, DataUpdateEvent, ExportedCode, ExportedData, ExportFormat, FilterResult, FormatOptions, ReturnColumnProfilesEvent, RowFilter, SchemaUpdateEvent, SupportedFeatures, SupportStatus, TableData, TableRowLabels, TableSchema, TableSelection } from './positronDataExplorerComm.js'; /** * TableSchemaSearchResult interface. This is here temporarily until searching the tabe schema @@ -66,6 +66,7 @@ export interface IDataExplorerBackendClient extends Disposable { getDataValues(columns: Array, formatOptions: FormatOptions): Promise; getRowLabels(selection: ArraySelection, formatOptions: FormatOptions): Promise; exportDataSelection(selection: TableSelection, format: ExportFormat): Promise; + exportAsCode(columnFilters: Array, rowFilters: Array, sortKeys: Array, exportOptions: CodeSyntax): Promise; setColumnFilters(filters: Array): Promise; setRowFilters(filters: Array): Promise; setSortColumns(sortKeys: Array): Promise; @@ -496,6 +497,18 @@ export class DataExplorerClientInstance extends Disposable { } } + async exportAsCode(): Promise { + const state = await this.getBackendState(); + const columnFilters: Array = state.column_filters; + const rowFilters: Array = state.row_filters; + const sortKeys: Array = state.sort_keys; + + return this.runBackendTask( + () => this._backendClient.exportAsCode(columnFilters, rowFilters, sortKeys, CodeSyntax.Datatable), + () => ({ 'data': 'import as pd' }) + ); + } + //#endregion Public Methods //#region Private Methods diff --git a/src/vs/workbench/services/languageRuntime/common/positronDataExplorerComm.ts b/src/vs/workbench/services/languageRuntime/common/positronDataExplorerComm.ts index f03d5683d39e..37e654fa4915 100644 --- a/src/vs/workbench/services/languageRuntime/common/positronDataExplorerComm.ts +++ b/src/vs/workbench/services/languageRuntime/common/positronDataExplorerComm.ts @@ -54,6 +54,17 @@ export interface ExportedData { } +/** + * Resulting code + */ +export interface ExportedCode { + /** + * Exported code as a string suitable for copy and paste + */ + data?: string; + +} + /** * The result of applying filters to a table */ @@ -1169,6 +1180,17 @@ export enum ColumnHistogramParamsMethod { Fixed = 'fixed' } +/** + * Possible values for CodeSyntax + */ +export enum CodeSyntax { + Datatable = 'datatable', + Dplyr = 'dplyr', + Pandas = 'pandas', + Polars = 'polars', + BaseR = 'baseR' +} + /** * Possible values for Kind in TableSelection */ @@ -1286,6 +1308,31 @@ export interface ExportDataSelectionParams { format: ExportFormat; } +/** + * Parameters for the ExportAsCode method. + */ +export interface ExportAsCodeParams { + /** + * Zero or more column filters to apply + */ + column_filters: Array; + + /** + * Zero or more row filters to apply + */ + row_filters: Array; + + /** + * Zero or more sort keys to apply + */ + sort_keys: Array; + + /** + * Exported code format + */ + code_syntax: string; +} + /** * Parameters for the SetColumnFilters method. */ @@ -1402,6 +1449,7 @@ export enum DataExplorerBackendRequest { GetDataValues = 'get_data_values', GetRowLabels = 'get_row_labels', ExportDataSelection = 'export_data_selection', + ExportAsCode = 'export_as_code', SetColumnFilters = 'set_column_filters', SetRowFilters = 'set_row_filters', SetSortColumns = 'set_sort_columns', @@ -1510,6 +1558,23 @@ export class PositronDataExplorerComm extends PositronBaseComm { return super.performRpc('export_data_selection', ['selection', 'format'], [selection, format]); } + /** + * Export filters and sort keys as code + * + * Export filters and sort keys as code in different formats like pandas, + * polars, data.table, dplyr + * + * @param columnFilters Zero or more column filters to apply + * @param rowFilters Zero or more row filters to apply + * @param sortKeys Zero or more sort keys to apply + * @param codeSyntax Exported code format + * + * @returns Resulting code + */ + exportAsCode(columnFilters: Array, rowFilters: Array, sortKeys: Array, codeSyntax: string): Promise { + return super.performRpc('export_as_code', ['column_filters', 'row_filters', 'sort_keys', 'code_syntax'], [columnFilters, rowFilters, sortKeys, codeSyntax]); + } + /** * Set column filters to select subset of table columns * diff --git a/src/vs/workbench/services/positronDataExplorer/browser/interfaces/positronDataExplorerInstance.ts b/src/vs/workbench/services/positronDataExplorer/browser/interfaces/positronDataExplorerInstance.ts index 13d405b718f0..0af3cc3c3ecc 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/interfaces/positronDataExplorerInstance.ts +++ b/src/vs/workbench/services/positronDataExplorer/browser/interfaces/positronDataExplorerInstance.ts @@ -123,5 +123,5 @@ export interface IPositronDataExplorerInstance extends IDisposable { /** * Exports the table data to code. */ - exportToCode(): Promise; + exportAsCode(): Promise; } diff --git a/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerInstance.ts b/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerInstance.ts index 1f07a4b70d06..6303d08466a7 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerInstance.ts +++ b/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerInstance.ts @@ -434,10 +434,20 @@ export class PositronDataExplorerInstance extends Disposable implements IPositro * Export filters as code. * @returns A Promise that resolves when generated code is copied to clipboard. */ - async exportToCode(): Promise { + async exportAsCode(): Promise { + const generatedCode = await this._dataExplorerClientInstance.exportAsCode(); + if (!generatedCode.data) { + this._notificationService.error( + localize( + 'positron.dataExplorer.exportAsCodeFailed', + 'Failed to export data as code.' + ) + ); + return; + } // Write the code to the clipboard. - this._clipboardService.writeText('1234567890'); - await this._tableDataDataGridInstance._tableDataCache.getColumnSchema(0); + this._clipboardService.writeText(generatedCode.data); + } diff --git a/src/vs/workbench/services/positronDataExplorer/common/positronDataExplorerDuckDBBackend.ts b/src/vs/workbench/services/positronDataExplorer/common/positronDataExplorerDuckDBBackend.ts index c6cb6c1639a8..f4b35ad5ed69 100644 --- a/src/vs/workbench/services/positronDataExplorer/common/positronDataExplorerDuckDBBackend.ts +++ b/src/vs/workbench/services/positronDataExplorer/common/positronDataExplorerDuckDBBackend.ts @@ -9,6 +9,7 @@ import { DataExplorerUiEvent, IDataExplorerBackendClient } from '../../languageR import { ArraySelection, BackendState, + CodeSyntax, ColumnFilter, ColumnProfileRequest, ColumnSelection, @@ -17,6 +18,7 @@ import { DataExplorerFrontendEvent, DataUpdateEvent, ExportDataSelectionParams, + ExportedCode, ExportedData, ExportFormat, FilterResult, @@ -207,6 +209,19 @@ export class PositronDataExplorerDuckDBBackend extends Disposable implements IDa }); } + async exportAsCode(columnFilters: Array, rowFilters: Array, sortKeys: Array, exportOptions: CodeSyntax): Promise { + return this._execRpc({ + method: DataExplorerBackendRequest.ExportAsCode, + uri: this.uri.toString(), + params: { + column_filters: columnFilters, + row_filters: rowFilters, + sort_keys: sortKeys, + export_options: exportOptions + } + }); + } + async setColumnFilters(filters: Array): Promise { return this._execRpc({ method: DataExplorerBackendRequest.SetColumnFilters, From dcf380b03766082de6f6da32cd9bcbe4b7f0848b Mon Sep 17 00:00:00 2001 From: isabel zimmerman Date: Wed, 9 Jul 2025 22:30:31 -0400 Subject: [PATCH 03/26] export -> copy --- .../posit/positron/data_explorer_comm.py | 20 +++++++++---------- .../comms/data_explorer-backend-openrpc.json | 2 +- .../browser/positronDataExplorerActions.ts | 2 +- .../languageRuntimeDataExplorerClient.ts | 6 +++--- .../common/positronDataExplorerComm.ts | 10 +++++----- .../positronDataExplorerInstance.ts | 2 +- .../browser/positronDataExplorerInstance.ts | 4 ++-- .../positronDataExplorerDuckDBBackend.ts | 4 ++-- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/extensions/positron-python/python_files/posit/positron/data_explorer_comm.py b/extensions/positron-python/python_files/posit/positron/data_explorer_comm.py index 4f737e207072..7e3284ccfca2 100644 --- a/extensions/positron-python/python_files/posit/positron/data_explorer_comm.py +++ b/extensions/positron-python/python_files/posit/positron/data_explorer_comm.py @@ -1237,7 +1237,7 @@ class DataExplorerBackendRequest(str, enum.Enum): ExportDataSelection = "export_data_selection" # Export filters and sort keys as code - ExportAsCode = "export_as_code" + CopyAsCode = "copy_as_code" # Set column filters to select subset of table columns SetColumnFilters = "set_column_filters" @@ -1453,7 +1453,7 @@ class ExportDataSelectionRequest(BaseModel): ) -class ExportAsCodeParams(BaseModel): +class CopyAsCodeParams(BaseModel): """ Export filters and sort keys as code in different formats like pandas, polars, data.table, dplyr @@ -1476,18 +1476,18 @@ class ExportAsCodeParams(BaseModel): ) -class ExportAsCodeRequest(BaseModel): +class CopyAsCodeRequest(BaseModel): """ Export filters and sort keys as code in different formats like pandas, polars, data.table, dplyr """ - params: ExportAsCodeParams = Field( - description="Parameters to the ExportAsCode method", + params: CopyAsCodeParams = Field( + description="Parameters to the CopyAsCode method", ) - method: Literal[DataExplorerBackendRequest.ExportAsCode] = Field( - description="The JSON-RPC method name (export_as_code)", + method: Literal[DataExplorerBackendRequest.CopyAsCode] = Field( + description="The JSON-RPC method name (copy_as_code)", ) jsonrpc: str = Field( @@ -1649,7 +1649,7 @@ class DataExplorerBackendMessageContent(BaseModel): GetDataValuesRequest, GetRowLabelsRequest, ExportDataSelectionRequest, - ExportAsCodeRequest, + CopyAsCodeRequest, SetColumnFiltersRequest, SetRowFiltersRequest, SetSortColumnsRequest, @@ -1818,9 +1818,9 @@ class ReturnColumnProfilesParams(BaseModel): ExportDataSelectionRequest.update_forward_refs() -ExportAsCodeParams.update_forward_refs() +CopyAsCodeParams.update_forward_refs() -ExportAsCodeRequest.update_forward_refs() +CopyAsCodeRequest.update_forward_refs() SetColumnFiltersParams.update_forward_refs() diff --git a/positron/comms/data_explorer-backend-openrpc.json b/positron/comms/data_explorer-backend-openrpc.json index 6d7132176a64..9b4738cb571d 100644 --- a/positron/comms/data_explorer-backend-openrpc.json +++ b/positron/comms/data_explorer-backend-openrpc.json @@ -216,7 +216,7 @@ } }, { - "name": "export_as_code", + "name": "copy_as_code", "summary": "Export filters and sort keys as code", "description": "Export filters and sort keys as code in different formats like pandas, polars, data.table, dplyr", "params": [ diff --git a/src/vs/workbench/contrib/positronDataExplorerEditor/browser/positronDataExplorerActions.ts b/src/vs/workbench/contrib/positronDataExplorerEditor/browser/positronDataExplorerActions.ts index 53c1ccb6eab9..d482c1df064c 100644 --- a/src/vs/workbench/contrib/positronDataExplorerEditor/browser/positronDataExplorerActions.ts +++ b/src/vs/workbench/contrib/positronDataExplorerEditor/browser/positronDataExplorerActions.ts @@ -782,7 +782,7 @@ class PositronDataExplorerExportAsCodeAction extends Action2 { } // Export filters as code. - await positronDataExplorerInstance.exportAsCode(); + await positronDataExplorerInstance.copyAsCode(); notifyUserThatCodeCopied(); } } diff --git a/src/vs/workbench/services/languageRuntime/common/languageRuntimeDataExplorerClient.ts b/src/vs/workbench/services/languageRuntime/common/languageRuntimeDataExplorerClient.ts index bc073b0efdde..5899d6383600 100644 --- a/src/vs/workbench/services/languageRuntime/common/languageRuntimeDataExplorerClient.ts +++ b/src/vs/workbench/services/languageRuntime/common/languageRuntimeDataExplorerClient.ts @@ -66,7 +66,7 @@ export interface IDataExplorerBackendClient extends Disposable { getDataValues(columns: Array, formatOptions: FormatOptions): Promise; getRowLabels(selection: ArraySelection, formatOptions: FormatOptions): Promise; exportDataSelection(selection: TableSelection, format: ExportFormat): Promise; - exportAsCode(columnFilters: Array, rowFilters: Array, sortKeys: Array, exportOptions: CodeSyntax): Promise; + copyAsCode(columnFilters: Array, rowFilters: Array, sortKeys: Array, exportOptions: CodeSyntax): Promise; setColumnFilters(filters: Array): Promise; setRowFilters(filters: Array): Promise; setSortColumns(sortKeys: Array): Promise; @@ -497,14 +497,14 @@ export class DataExplorerClientInstance extends Disposable { } } - async exportAsCode(): Promise { + async copyAsCode(): Promise { const state = await this.getBackendState(); const columnFilters: Array = state.column_filters; const rowFilters: Array = state.row_filters; const sortKeys: Array = state.sort_keys; return this.runBackendTask( - () => this._backendClient.exportAsCode(columnFilters, rowFilters, sortKeys, CodeSyntax.Datatable), + () => this._backendClient.copyAsCode(columnFilters, rowFilters, sortKeys, CodeSyntax.Datatable), () => ({ 'data': 'import as pd' }) ); } diff --git a/src/vs/workbench/services/languageRuntime/common/positronDataExplorerComm.ts b/src/vs/workbench/services/languageRuntime/common/positronDataExplorerComm.ts index 37e654fa4915..b88875534464 100644 --- a/src/vs/workbench/services/languageRuntime/common/positronDataExplorerComm.ts +++ b/src/vs/workbench/services/languageRuntime/common/positronDataExplorerComm.ts @@ -1309,9 +1309,9 @@ export interface ExportDataSelectionParams { } /** - * Parameters for the ExportAsCode method. + * Parameters for the CopyAsCode method. */ -export interface ExportAsCodeParams { +export interface CopyAsCodeParams { /** * Zero or more column filters to apply */ @@ -1449,7 +1449,7 @@ export enum DataExplorerBackendRequest { GetDataValues = 'get_data_values', GetRowLabels = 'get_row_labels', ExportDataSelection = 'export_data_selection', - ExportAsCode = 'export_as_code', + CopyAsCode = 'copy_as_code', SetColumnFilters = 'set_column_filters', SetRowFilters = 'set_row_filters', SetSortColumns = 'set_sort_columns', @@ -1571,8 +1571,8 @@ export class PositronDataExplorerComm extends PositronBaseComm { * * @returns Resulting code */ - exportAsCode(columnFilters: Array, rowFilters: Array, sortKeys: Array, codeSyntax: string): Promise { - return super.performRpc('export_as_code', ['column_filters', 'row_filters', 'sort_keys', 'code_syntax'], [columnFilters, rowFilters, sortKeys, codeSyntax]); + copyAsCode(columnFilters: Array, rowFilters: Array, sortKeys: Array, codeSyntax: string): Promise { + return super.performRpc('copy_as_code', ['column_filters', 'row_filters', 'sort_keys', 'code_syntax'], [columnFilters, rowFilters, sortKeys, codeSyntax]); } /** diff --git a/src/vs/workbench/services/positronDataExplorer/browser/interfaces/positronDataExplorerInstance.ts b/src/vs/workbench/services/positronDataExplorer/browser/interfaces/positronDataExplorerInstance.ts index 0af3cc3c3ecc..b050391116f3 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/interfaces/positronDataExplorerInstance.ts +++ b/src/vs/workbench/services/positronDataExplorer/browser/interfaces/positronDataExplorerInstance.ts @@ -123,5 +123,5 @@ export interface IPositronDataExplorerInstance extends IDisposable { /** * Exports the table data to code. */ - exportAsCode(): Promise; + copyAsCode(): Promise; } diff --git a/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerInstance.ts b/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerInstance.ts index 6303d08466a7..bd563e5d49f9 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerInstance.ts +++ b/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerInstance.ts @@ -434,8 +434,8 @@ export class PositronDataExplorerInstance extends Disposable implements IPositro * Export filters as code. * @returns A Promise that resolves when generated code is copied to clipboard. */ - async exportAsCode(): Promise { - const generatedCode = await this._dataExplorerClientInstance.exportAsCode(); + async copyAsCode(): Promise { + const generatedCode = await this._dataExplorerClientInstance.copyAsCode(); if (!generatedCode.data) { this._notificationService.error( localize( diff --git a/src/vs/workbench/services/positronDataExplorer/common/positronDataExplorerDuckDBBackend.ts b/src/vs/workbench/services/positronDataExplorer/common/positronDataExplorerDuckDBBackend.ts index f4b35ad5ed69..0352b5686598 100644 --- a/src/vs/workbench/services/positronDataExplorer/common/positronDataExplorerDuckDBBackend.ts +++ b/src/vs/workbench/services/positronDataExplorer/common/positronDataExplorerDuckDBBackend.ts @@ -209,9 +209,9 @@ export class PositronDataExplorerDuckDBBackend extends Disposable implements IDa }); } - async exportAsCode(columnFilters: Array, rowFilters: Array, sortKeys: Array, exportOptions: CodeSyntax): Promise { + async copyAsCode(columnFilters: Array, rowFilters: Array, sortKeys: Array, exportOptions: CodeSyntax): Promise { return this._execRpc({ - method: DataExplorerBackendRequest.ExportAsCode, + method: DataExplorerBackendRequest.CopyAsCode, uri: this.uri.toString(), params: { column_filters: columnFilters, From 32eb2c0b310d7274e7ba8fe7ca3db73bde8d9748 Mon Sep 17 00:00:00 2001 From: isabel zimmerman Date: Fri, 11 Jul 2025 16:21:09 -0400 Subject: [PATCH 04/26] add modal on filter bar --- .../posit/positron/data_explorer.py | 15 +++- .../posit/positron/data_explorer_comm.py | 52 ++++++++----- .../comms/data_explorer-backend-openrpc.json | 40 +++++++--- .../copyAsCodeModalPopup.css | 4 + .../copyAsCodeModalPopup.tsx | 73 +++++++++++++++++++ .../components/rowFilterBar/rowFilterBar.tsx | 26 +++++++ .../positronDataExplorer.tsx | 1 + .../browser/positronDataExplorerActions.ts | 35 +++------ .../languageRuntimeDataExplorerClient.ts | 23 +++++- .../common/positronDataExplorerComm.ts | 43 +++++++---- .../positronDataExplorerInstance.ts | 2 +- .../browser/positronDataExplorerInstance.ts | 15 +--- .../positronDataExplorerDuckDBBackend.ts | 12 ++- 13 files changed, 251 insertions(+), 90 deletions(-) create mode 100644 src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/copyAsCodeModalPopup/copyAsCodeModalPopup.css create mode 100644 src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/copyAsCodeModalPopup/copyAsCodeModalPopup.tsx diff --git a/extensions/positron-python/python_files/posit/positron/data_explorer.py b/extensions/positron-python/python_files/posit/positron/data_explorer.py index 60fca71d6377..df417c09e8af 100644 --- a/extensions/positron-python/python_files/posit/positron/data_explorer.py +++ b/extensions/positron-python/python_files/posit/positron/data_explorer.py @@ -44,13 +44,14 @@ ColumnSortKey, ColumnSummaryStats, ColumnValue, + CopyAsCodeRequest, DataExplorerBackendMessageContent, DataExplorerFrontendEvent, DataSelectionCellRange, DataSelectionIndices, DataSelectionRange, DataSelectionSingleCell, - ExportAsCodeRequest, + DesiredCodeTypes, ExportDataSelectionFeatures, ExportDataSelectionRequest, ExportedCode, @@ -64,6 +65,7 @@ FilterSetMembership, FilterTextSearch, FormatOptions, + GetCodeTypesRequest, GetColumnProfilesFeatures, GetColumnProfilesRequest, GetDataValuesRequest, @@ -405,7 +407,16 @@ def export_data_selection(self, request: ExportDataSelectionRequest): else: raise NotImplementedError(f"Unknown data export: {kind}") - def export_as_code(self, request: ExportAsCodeRequest): + def get_code_types(self, request: GetCodeTypesRequest): + """ + Returns the supported code types for exporting data. + This is a placeholder implementation that returns an empty list. + """ + # In a real implementation, this would return the supported code types + # based on the backend capabilities or configuration. + return DesiredCodeTypes(code_types=['hello']).dict() + + def copy_as_code(self, request: CopyAsCodeRequest): return ExportedCode(data="import pandas as pd\n\n# TODO: Implement export to code").dict() def _export_cell(self, row_index: int, column_index: int, fmt: ExportFormat): diff --git a/extensions/positron-python/python_files/posit/positron/data_explorer_comm.py b/extensions/positron-python/python_files/posit/positron/data_explorer_comm.py index 7e3284ccfca2..1ed703c7c6b3 100644 --- a/extensions/positron-python/python_files/posit/positron/data_explorer_comm.py +++ b/extensions/positron-python/python_files/posit/positron/data_explorer_comm.py @@ -168,23 +168,6 @@ class ColumnHistogramParamsMethod(str, enum.Enum): Fixed = "fixed" -@enum.unique -class CodeSyntax(str, enum.Enum): - """ - Possible values for CodeSyntax - """ - - Datatable = "datatable" - - Dplyr = "dplyr" - - Pandas = "pandas" - - Polars = "polars" - - BaseR = "baseR" - - @enum.unique class TableSelectionKind(str, enum.Enum): """ @@ -280,6 +263,16 @@ class ExportedCode(BaseModel): ) +class DesiredCodeTypes(BaseModel): + """ + Resulting code types + """ + + code_types: List[StrictStr] = Field( + description="tktk", + ) + + class FilterResult(BaseModel): """ The result of applying filters to a table @@ -1239,6 +1232,9 @@ class DataExplorerBackendRequest(str, enum.Enum): # Export filters and sort keys as code CopyAsCode = "copy_as_code" + # Get code syntaxes supported for export + GetCodeTypes = "get_code_types" + # Set column filters to select subset of table columns SetColumnFilters = "set_column_filters" @@ -1471,7 +1467,7 @@ class CopyAsCodeParams(BaseModel): description="Zero or more sort keys to apply", ) - code_syntax: StrictStr = Field( + export_code_syntax: StrictStr = Field( description="Exported code format", ) @@ -1496,6 +1492,21 @@ class CopyAsCodeRequest(BaseModel): ) +class GetCodeTypesRequest(BaseModel): + """ + tktk + """ + + method: Literal[DataExplorerBackendRequest.GetCodeTypes] = Field( + description="The JSON-RPC method name (get_code_types)", + ) + + jsonrpc: str = Field( + default="2.0", + description="The JSON-RPC version specifier", + ) + + class SetColumnFiltersParams(BaseModel): """ Set or clear column filters on table, replacing any previous filters @@ -1650,6 +1661,7 @@ class DataExplorerBackendMessageContent(BaseModel): GetRowLabelsRequest, ExportDataSelectionRequest, CopyAsCodeRequest, + GetCodeTypesRequest, SetColumnFiltersRequest, SetRowFiltersRequest, SetSortColumnsRequest, @@ -1700,6 +1712,8 @@ class ReturnColumnProfilesParams(BaseModel): ExportedCode.update_forward_refs() +DesiredCodeTypes.update_forward_refs() + FilterResult.update_forward_refs() BackendState.update_forward_refs() @@ -1822,6 +1836,8 @@ class ReturnColumnProfilesParams(BaseModel): CopyAsCodeRequest.update_forward_refs() +GetCodeTypesRequest.update_forward_refs() + SetColumnFiltersParams.update_forward_refs() SetColumnFiltersRequest.update_forward_refs() diff --git a/positron/comms/data_explorer-backend-openrpc.json b/positron/comms/data_explorer-backend-openrpc.json index 9b4738cb571d..47f42281fec0 100644 --- a/positron/comms/data_explorer-backend-openrpc.json +++ b/positron/comms/data_explorer-backend-openrpc.json @@ -254,13 +254,13 @@ } }, { - "name": "code_syntax", + "name": "export_code_syntax", "description": "Exported code format", "required": true, "schema": { "type": "string", "items": { - "$ref": "#/components/schemas/code_syntax" + "$ref": "#/components/schemas/export_code_syntax" } } } @@ -282,6 +282,31 @@ } } }, +{ + "name": "get_code_types", + "summary": "Get code syntaxes supported for export", + "description": "tktk", + "params": [], + "result": { + "schema": { + "name": "desired_code_types", + "type": "object", + "description": "Resulting code types", + "required": [ + "code_types" + ], + "properties": { + "code_types": { + "type": "array", + "description": "tktk", + "items": { + "type": "string" + } + } + } + } + } + }, { "name": "set_column_filters", "summary": "Set column filters to select subset of table columns", @@ -1360,16 +1385,9 @@ } } }, - "code_syntax": { + "export_code_syntax": { "type": "string", - "description": "The syntax for code", - "enum": [ - "datatable", - "dplyr", - "pandas", - "polars", - "baseR" - ] + "description": "The syntax for code" }, "supported_features": { "type": "object", diff --git a/src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/copyAsCodeModalPopup/copyAsCodeModalPopup.css b/src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/copyAsCodeModalPopup/copyAsCodeModalPopup.css new file mode 100644 index 000000000000..d4d2fcf77d0a --- /dev/null +++ b/src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/copyAsCodeModalPopup/copyAsCodeModalPopup.css @@ -0,0 +1,4 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (C) 2025 Posit Software, PBC. All rights reserved. + * Licensed under the Elastic License 2.0. See LICENSE.txt for license information. + *--------------------------------------------------------------------------------------------*/ diff --git a/src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/copyAsCodeModalPopup/copyAsCodeModalPopup.tsx b/src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/copyAsCodeModalPopup/copyAsCodeModalPopup.tsx new file mode 100644 index 000000000000..4193caf24975 --- /dev/null +++ b/src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/copyAsCodeModalPopup/copyAsCodeModalPopup.tsx @@ -0,0 +1,73 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (C) 2025 Posit Software, PBC. All rights reserved. + * Licensed under the Elastic License 2.0. See LICENSE.txt for license information. + *--------------------------------------------------------------------------------------------*/ + +// CSS. +import './copyAsCodeModalPopup.css'; + +// React. +import React, { useEffect, useState } from 'react'; + +import { PositronModalPopup } from '../../../../../../browser/positronComponents/positronModalPopup/positronModalPopup.js' +import { PositronModalReactRenderer } from '../../../../../positronModalReactRenderer/positronModalReactRenderer.js'; +import { ICommandService } from '../../../../../../../platform/commands/common/commands.js'; +import { DisposableStore } from '../../../../../../../base/common/lifecycle.js'; +import { DataExplorerClientInstance } from '../../../../../../services/languageRuntime/common/languageRuntimeDataExplorerClient.js'; +import { PositronDataExplorerCommandId } from '../../../../../../contrib/positronDataExplorerEditor/browser/positronDataExplorerActions.js'; + +interface CopyAsCodeModalPopupProps { + anchorElement: HTMLElement; + commandService: ICommandService; + dataExplorerClientInstance: DataExplorerClientInstance + renderer: PositronModalReactRenderer; +} + +export const CopyAsCodeModalPopup = (props: CopyAsCodeModalPopupProps) => { + const [codeString, setCodeString] = useState('1234'); + + + useEffect(() => { + const getCodeString = async () => { + const codeString = await props.commandService.executeCommand(PositronDataExplorerCommandId.CopyAsCodeAction); + setCodeString(codeString); + } + getCodeString(); + }, [props.commandService]); + + // listen to onFilterChanged/sortChanged event (look at consoleInstanceInfoButton.tsx for example) and update the codeString state + useEffect(() => { + const disposableStore = new DisposableStore(); + + const getCodeString = async () => { + const codeString = await props.commandService.executeCommand(PositronDataExplorerCommandId.CopyAsCodeAction); + setCodeString(codeString); + } + + // Add the onDidUpdateBackendState event handler. + disposableStore.add(props.dataExplorerClientInstance.onDidUpdateBackendState( + state => { + getCodeString(); + }) + ); + + return () => disposableStore.dispose(); + }, [props.commandService, props.dataExplorerClientInstance]); + + // Render. + return ( + +
+				{codeString ?? 'hello'}
+			
+
+ ) +}; diff --git a/src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/rowFilterBar/rowFilterBar.tsx b/src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/rowFilterBar/rowFilterBar.tsx index 07e74514c736..41353dfd1c5c 100644 --- a/src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/rowFilterBar/rowFilterBar.tsx +++ b/src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/rowFilterBar/rowFilterBar.tsx @@ -25,6 +25,7 @@ import { CustomContextMenuItem } from '../../../../../positronComponents/customC import { CustomContextMenuSeparator } from '../../../../../positronComponents/customContextMenu/customContextMenuSeparator.js'; import { CustomContextMenuEntry, showCustomContextMenu } from '../../../../../positronComponents/customContextMenu/customContextMenu.js'; import { dataExplorerExperimentalFeatureEnabled } from '../../../../../../services/positronDataExplorer/common/positronDataExplorerExperimentalConfig.js'; +import { CopyAsCodeModalPopup } from '../copyAsCodeModalPopup/copyAsCodeModalPopup.js'; /** * Constants. @@ -253,9 +254,34 @@ export const RowFilterBar = () => { return () => disposableStore.dispose(); }, [addRowFilterHandler, context.instance, rowFilterDescriptors.length]); + const handleCopyAsCodePressed = async () => { + // Create the renderer. + const renderer = new PositronModalReactRenderer({ + keybindingService: context.keybindingService, + layoutService: context.layoutService, + container: context.layoutService.getContainer(DOM.getWindow(ref.current)), + parent: ref.current + }); + + renderer.render() + } + // Render. return (
+