diff --git a/frog-runner.jar b/frog-runner.jar index c8bc9dd..cb8d03a 100644 Binary files a/frog-runner.jar and b/frog-runner.jar differ diff --git a/package.json b/package.json index f2d3619..1315a37 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,11 @@ { "command": "extension.executeSnippet", "title": "Execute SQL Snippet" - } + }, + { + "command": "selectConnection", + "title": "Selects the connection to use" + } ], "keybindings": [{ "command": "extension.executeSnippet", @@ -36,6 +40,17 @@ "name": "Connections" } ] + }, + "configuration": { + "type": "object", + "title": "Frog configuration", + "properties": { + "frog.connections": { + "type": "string", + "default": "", + "description": "Set connections to use" + } + } } }, "scripts": { diff --git a/src/connections.ts b/src/connections.ts index 21ab6d1..46f1942 100644 --- a/src/connections.ts +++ b/src/connections.ts @@ -1,4 +1,5 @@ import { ExtensionContext, TreeDataProvider, EventEmitter, TreeItem, Event, window, TreeItemCollapsibleState, Uri, commands, workspace, TextDocumentContentProvider, CancellationToken, ProviderResult } from 'vscode'; +import * as os from 'os'; import * as path from 'path'; interface IEntry { @@ -6,65 +7,90 @@ interface IEntry { type: string; } -export class ConnectionNode { +type TreeNode = ConnectionNode | FolderNode - constructor(private _name:string, private _uri:string) { +export class FolderNode { + constructor(public name:string, public children : TreeNode[]) { } +} - public get name(): string { - return this._name; - } +export class ConnectionNode { - public get uri(): string { - return this._name; - } + constructor(public name:string, public host:string, public port:Number, public schema:String, public username:String, public password:String) { + } } export class ConnectionModel { - public get roots(): Thenable { - let list : ConnectionNode[] = [ - new ConnectionNode("swdev", "foobar"), - new ConnectionNode("swint", "foobar") - ]; + constructor(public data:any) { + } + + private traverse(data) : TreeNode[] { + return data['items'].map( (x) => { + if (x['type'] == 'connection') { + return new ConnectionNode(x['name'], x['host'], x['port'], x['sid'], x['username'], x['password']) + } else { + return new FolderNode(x['name'], this.traverse(x)) + } + }); + } + public get roots(): Thenable { + let list : TreeNode[] = this.traverse(this.data); return new Promise((c, e) => c(list)); } - public getChildren(node: ConnectionNode): Thenable { - return new Promise((c, e) => []); + public getChildren(node: TreeNode): Thenable { + if (node instanceof FolderNode) { + return new Promise((c, e) => c(node.children)); + } else { + return new Promise((c, e) => c([])); + } } } -export class ConnectionProvider implements TreeDataProvider, TextDocumentContentProvider { +export class ConnectionProvider implements TreeDataProvider, TextDocumentContentProvider { private _onDidChangeTreeData: EventEmitter = new EventEmitter(); readonly onDidChangeTreeData: Event = this._onDidChangeTreeData.event; private model: ConnectionModel; - public getTreeItem(element: ConnectionNode): TreeItem { - return { - label: element.name, - collapsibleState: void 0, - command: { - command: 'openConnection', - arguments: [element.uri], - title: 'Open Connection' + public getTreeItem(element: TreeNode): TreeItem { + if (element instanceof FolderNode) { + return { + label: element.name, + collapsibleState: TreeItemCollapsibleState.Collapsed, + command: void 0 } - }; + } else { + return { + label: element.name, + collapsibleState: void 0, + command: { + command: 'selectConnection', + arguments: [element], + title: 'Open Connection' + } + } + } } - public getChildren(element?: ConnectionNode): ConnectionNode[] | Thenable { + public getChildren(element?: TreeNode): TreeNode[] | Thenable { if (!element) { if (!this.model) { - this.model = new ConnectionModel(); + let data = require(os.homedir() + '/.frog.json'); + this.model = new ConnectionModel(data); } return this.model.roots; } - return []; + if (element instanceof FolderNode) { + return element.children; + } else { + return []; + } } public provideTextDocumentContent(uri: Uri, token: CancellationToken): ProviderResult { diff --git a/src/extension.ts b/src/extension.ts index dacfe92..d15b7d6 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -8,7 +8,8 @@ import { TextDocumentContentProvider } from './resultsetview' const { spawn } = require('child_process'); const extensionName = "frog"; -var dbSession = null; +let currentConnection : ConnectionNode = null; +let dbSession = null; // this method is called when your extension is activated @@ -16,6 +17,11 @@ var dbSession = null; export function activate(context: vscode.ExtensionContext) { let previewUri = vscode.Uri.parse('frog-view://authority/resultset'); + let statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); + statusBarItem.text = 'Frog: No connection' + statusBarItem.show() + context.subscriptions.push(statusBarItem); + const connectionProvider = new ConnectionProvider(); let myOutputChannel = vscode.window.createOutputChannel('SQL Query Results'); context.subscriptions.push(myOutputChannel); @@ -47,8 +53,13 @@ export function activate(context: vscode.ExtensionContext) { let text = editor.document.getText(selection); if (!dbSession) { + if (!currentConnection) { + vscode.window.showWarningMessage('No connection selected'); + return; + } + let extPath = vscode.extensions.getExtension("todie.frog").extensionPath; - dbSession = spawn("java", ['-jar', extPath + '/frog-runner.jar', '172.19.23.18', '1521', 'aax2sm', 'aax2sm', 'aax2sm']); + dbSession = spawn("java", ['-jar', extPath + '/frog-runner.jar', currentConnection.host, currentConnection.port, currentConnection.schema, currentConnection.username, currentConnection.password]); let outputBuffer = ""; @@ -81,6 +92,8 @@ export function activate(context: vscode.ExtensionContext) { diagnosticCollection.set(document.uri, diagnostics); } else if (json['exception']) { myOutputChannel.append("Exception caught: " + json['exceptionMessage'] + "\n"); + } else if ("affectedRows" in json) { + myOutputChannel.append(json['affectedRows'] + " rows affected.\n"); } else { myOutputChannel.append("SQL executed successfully.\n"); } @@ -101,6 +114,7 @@ export function activate(context: vscode.ExtensionContext) { } catch (e) { console.log(e); } + statusBarItem.text = currentConnection.name + " (Connected)"; }); dbSession.stderr.on('data', (data) => { @@ -125,6 +139,20 @@ export function activate(context: vscode.ExtensionContext) { }); context.subscriptions.push(disposable, registration); + + vscode.commands.registerCommand('selectConnection', (node: ConnectionNode) => { + vscode.window.showInformationMessage(`You want to change the connection to '${node.name}'. Sure?`, 'Yes') + .then( (selection) => { + if (selection == 'Yes') { + currentConnection = node; + statusBarItem.text = node.name; + if (dbSession) { + dbSession.stdin.end(); + dbSession = null; + } + } + }, (reason) => {}) + }) } // this method is called when your extension is deactivated