diff --git a/src/vs/workbench/contrib/positronConnections/browser/components/resumeConnectionModalDialog.tsx b/src/vs/workbench/contrib/positronConnections/browser/components/resumeConnectionModalDialog.tsx index d190abf8ded..81dc2c59d39 100644 --- a/src/vs/workbench/contrib/positronConnections/browser/components/resumeConnectionModalDialog.tsx +++ b/src/vs/workbench/contrib/positronConnections/browser/components/resumeConnectionModalDialog.tsx @@ -3,7 +3,7 @@ * Licensed under the Elastic License 2.0. See LICENSE.txt for license information. *--------------------------------------------------------------------------------------------*/ -import React, { PropsWithChildren } from 'react'; +import React, { PropsWithChildren, useEffect, useRef } from 'react'; import { localize } from 'vs/nls'; import { ContentArea } from 'vs/workbench/browser/positronComponents/positronModalDialog/components/contentArea'; import { PositronModalDialog } from 'vs/workbench/browser/positronComponents/positronModalDialog/positronModalDialog'; @@ -12,6 +12,10 @@ import { PositronConnectionsServices } from 'vs/workbench/contrib/positronConnec import { PositronButton } from 'vs/base/browser/ui/positronComponents/button/positronButton'; import 'vs/css!./resumeConnectionModalDialog'; import Severity from 'vs/base/common/severity'; +import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditor/codeEditorWidget'; +import { DisposableStore } from 'vs/base/common/lifecycle'; +import { getSimpleCodeEditorWidgetOptions, getSimpleEditorOptions } from 'vs/workbench/contrib/codeEditor/browser/simpleEditorOptions'; +import { Emitter } from 'vs/base/common/event'; const RESUME_CONNECTION_MODAL_DIALOG_WIDTH = 700; const RESUME_CONNECTION_MODAL_DIALOG_HEIGHT = 430; @@ -25,7 +29,7 @@ export const showResumeConnectionModalDialog = ( const renderer = new PositronModalReactRenderer({ keybindingService: services.keybindingService, layoutService: services.layoutService, - container: services.layoutService.activeContainer + container: services.layoutService.activeContainer, }); renderer.render( @@ -48,20 +52,58 @@ interface ResumeConnectionModalDialogProps { const ResumeConnectionModalDialog = (props: PropsWithChildren) => { const { services, activeInstaceId } = props; - const activeInstace = services.connectionsService.getConnections().find(item => item.id === activeInstaceId); - - if (!activeInstace) { + const activeInstance = services.connectionsService.getConnections().find(item => item.id === activeInstaceId); + + const editorContainerRef = useRef(undefined!); + const editorRef = useRef(undefined!); + + const code = activeInstance?.metadata.code; + const language_id = activeInstance?.metadata.language_id; + + useEffect(() => { + const disposableStore = new DisposableStore(); + const editor = disposableStore.add(services.instantiationService.createInstance( + CodeEditorWidget, + editorContainerRef.current, + { + ...getSimpleEditorOptions(services.configurationService), + readOnly: true, + domReadOnly: true, + cursorBlinking: 'solid', + }, + getSimpleCodeEditorWidgetOptions() + )); + + const emitter = disposableStore.add(new Emitter); + const inputModel = disposableStore.add(services.modelService.createModel( + code || '', + { languageId: language_id || '', onDidChange: emitter.event }, + undefined, + true + )); + + editor.setModel(inputModel); + editorRef.current = editor; + + return () => { + disposableStore.dispose(); + }; + }, + [ + code, language_id, + services.instantiationService, + services.configurationService, + editorContainerRef, + services.modelService, + ]); + + if (!activeInstance) { // This should never happen. return null; } - const code = activeInstace.metadata.code; - const copyHandler = async () => { - if (!code) { - // The button is disabled when no code is available. - return; - } + const code = editorRef.current?.getValue() || ''; await services.clipboardService.writeText(code); props.renderer.dispose(); @@ -74,36 +116,40 @@ const ResumeConnectionModalDialog = (props: PropsWithChildren { - if (!code) { + const editor = editorRef.current; + + if (!editor) { return; } - props.renderer.dispose(); - await services.editorService.openEditor({ - resource: undefined, - contents: code, - languageId: activeInstace.metadata.language_id - }); + editor.focus(); + editor.updateOptions({ readOnly: false, domReadOnly: false, cursorBlinking: 'blink' }); + editor.setScrollTop(0); }; const resumeHandler = async () => { - if (!activeInstace.connect) { + if (!activeInstance.connect) { return; } + // Acquire code before disposing of the renderer + const code = editorRef.current?.getValue(); + props.renderer.dispose(); const handle = services.notificationService.notify({ message: localize( 'positron.resumeConnectionModalDialog.connecting', "Connecting to data source ({0})...", - activeInstace.metadata.name + activeInstance.metadata.name ), severity: Severity.Info }); try { - await activeInstace.connect(); - props.setActiveInstanceId(activeInstace.id); + // Set instance code to the latest value. + activeInstance.metadata.update({ code: code }); + await activeInstance.connect(); + props.setActiveInstanceId(activeInstance.id); } catch (err) { services.notificationService.error(err); } @@ -128,7 +174,7 @@ const ResumeConnectionModalDialog = (props: PropsWithChildren
{localize('positron.resumeConnectionModalDialog.code', "Connection Code")}
- {code} +
@@ -160,7 +206,7 @@ const ResumeConnectionModalDialog = (props: PropsWithChildren {(() => localize('positron.resumeConnectionModalDialog.resume', "Resume Connection"))()} diff --git a/src/vs/workbench/contrib/positronConnections/browser/positronConnectionsContext.tsx b/src/vs/workbench/contrib/positronConnections/browser/positronConnectionsContext.tsx index dfb6057308d..f972c84e0e1 100644 --- a/src/vs/workbench/contrib/positronConnections/browser/positronConnectionsContext.tsx +++ b/src/vs/workbench/contrib/positronConnections/browser/positronConnectionsContext.tsx @@ -5,6 +5,7 @@ import React, { PropsWithChildren, createContext, useContext } from 'react'; import { IReactComponentContainer } from 'vs/base/browser/positronReactRenderer'; +import { IModelService } from 'vs/editor/common/services/model'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { ICommandService } from 'vs/platform/commands/common/commands'; @@ -12,6 +13,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IHoverService } from 'vs/platform/hover/browser/hover'; +import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; import { INotificationService } from 'vs/platform/notification/common/notification'; @@ -32,6 +34,8 @@ export interface PositronConnectionsServices { readonly clipboardService: IClipboardService; readonly notificationService: INotificationService; readonly editorService: IEditorService; + readonly instantiationService: IInstantiationService; + readonly modelService: IModelService; } const PositronConnectionsContext = createContext(undefined!); diff --git a/src/vs/workbench/contrib/positronConnections/browser/positronConnectionsView.tsx b/src/vs/workbench/contrib/positronConnections/browser/positronConnectionsView.tsx index b94286466e9..cb05b2f875a 100644 --- a/src/vs/workbench/contrib/positronConnections/browser/positronConnectionsView.tsx +++ b/src/vs/workbench/contrib/positronConnections/browser/positronConnectionsView.tsx @@ -31,6 +31,7 @@ import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService import { INotificationService } from 'vs/platform/notification/common/notification'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; +import { IModelService } from 'vs/editor/common/services/model'; export class PositronConnectionsView extends PositronViewPane @@ -89,7 +90,8 @@ export class PositronConnectionsView @ILayoutService private readonly layoutService: ILayoutService, @IClipboardService private readonly clipboardService: IClipboardService, @INotificationService private readonly notificationService: INotificationService, - @IEditorService private readonly editorService: IEditorService + @IEditorService private readonly editorService: IEditorService, + @IModelService private readonly modelService: IModelService ) { super( options, @@ -148,6 +150,8 @@ export class PositronConnectionsView clipboardService={this.clipboardService} notificationService={this.notificationService} editorService={this.editorService} + instantiationService={this.instantiationService} + modelService={this.modelService} /> ); } diff --git a/src/vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsInstance.ts b/src/vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsInstance.ts index a8338157ecc..97390630f35 100644 --- a/src/vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsInstance.ts +++ b/src/vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsInstance.ts @@ -6,7 +6,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { IPositronConnectionEntry } from 'vs/workbench/services/positronConnections/browser/positronConnectionsUtils'; -export interface ConnectionMetadata { +export interface IConnectionMetadata { name: string; language_id: string; host?: string; @@ -15,6 +15,28 @@ export interface ConnectionMetadata { icon?: string; } +export class ConnectionMetadata implements IConnectionMetadata { + name: string; + language_id: string; + host?: string; + type?: string; + code?: string; + icon?: string; + + constructor(metadata: IConnectionMetadata) { + this.name = metadata.name; + this.language_id = metadata.language_id; + this.code = metadata.code; + this.update(metadata); + } + + update(values: Partial): void { + console.log(values); + Object.assign(this, values); + console.log(this); + } +} + /*** * A Connection Instance represents the root of a connection to a data * source. Children of a connection instance are tables, views, and other diff --git a/src/vs/workbench/services/positronConnections/browser/positronConnectionsService.ts b/src/vs/workbench/services/positronConnections/browser/positronConnectionsService.ts index e31935fd85a..32707056619 100644 --- a/src/vs/workbench/services/positronConnections/browser/positronConnectionsService.ts +++ b/src/vs/workbench/services/positronConnections/browser/positronConnectionsService.ts @@ -6,7 +6,7 @@ import { Disposable } from 'vs/base/common/lifecycle'; import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { ConnectionsClientInstance } from 'vs/workbench/services/languageRuntime/common/languageRuntimeConnectionsClient'; -import { ConnectionMetadata, IPositronConnectionInstance } from 'vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsInstance'; +import { ConnectionMetadata, IConnectionMetadata, IPositronConnectionInstance } from 'vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsInstance'; import { IPositronConnectionsService, POSITRON_CONNECTIONS_VIEW_ID } from 'vs/workbench/services/positronConnections/browser/interfaces/positronConnectionsService'; import { DisconnectedPositronConnectionsInstance, PositronConnectionsInstance } from 'vs/workbench/services/positronConnections/browser/positronConnectionsInstance'; import { ILanguageRuntimeSession, IRuntimeSessionService, RuntimeClientType } from 'vs/workbench/services/runtimeSession/common/runtimeSessionService'; @@ -52,7 +52,7 @@ class PositronConnectionsService extends Disposable implements IPositronConnecti this.attachRuntime(runtime); })); - const storedConnections: ConnectionMetadata[] = JSON.parse( + const storedConnections: IConnectionMetadata[] = JSON.parse( this.storageService.get('positron-connections', StorageScope.WORKSPACE, '[]') ); storedConnections.forEach((metadata) => { @@ -61,7 +61,7 @@ class PositronConnectionsService extends Disposable implements IPositronConnecti } const instance = new DisconnectedPositronConnectionsInstance( - metadata, + new ConnectionMetadata(metadata), this.runtimeSessionService, this ); @@ -103,7 +103,7 @@ class PositronConnectionsService extends Disposable implements IPositronConnecti } const instance = await PositronConnectionsInstance.init( - message.data as ConnectionMetadata, + new ConnectionMetadata(message.data as IConnectionMetadata), new ConnectionsClientInstance(client), this ); @@ -121,7 +121,7 @@ class PositronConnectionsService extends Disposable implements IPositronConnecti const metadata = await connectionsClient.getMetadata(); const instance = await PositronConnectionsInstance.init( - metadata, + new ConnectionMetadata(metadata), connectionsClient, this );