Add OE node refresh API method (#2578)

* Initial working commit for refreshing OE node via API

* Add test and fix up code

* Run tsfmt

* Fix test
This commit is contained in:
Matt Irvine
2018-09-13 18:43:47 -07:00
committed by Karl Burtram
parent 36f7c283b8
commit 05040425df
7 changed files with 64 additions and 6 deletions

View File

@@ -72,6 +72,8 @@ export interface IObjectExplorerService {
getActiveConnectionNodes(): TreeNode[]; getActiveConnectionNodes(): TreeNode[];
getTreeNode(connectionId: string, nodePath: string): Thenable<TreeNode>; getTreeNode(connectionId: string, nodePath: string): Thenable<TreeNode>;
refreshNodeInView(connectionId: string, nodePath: string): Thenable<TreeNode>;
} }
interface SessionStatus { interface SessionStatus {
@@ -476,6 +478,20 @@ export class ObjectExplorerService implements IObjectExplorerService {
return Object.values(this._activeObjectExplorerNodes); return Object.values(this._activeObjectExplorerNodes);
} }
public async refreshNodeInView(connectionId: string, nodePath: string): Promise<TreeNode> {
// Get the tree node and call refresh from the provider
let treeNode = await this.getTreeNode(connectionId, nodePath);
await this.refreshTreeNode(treeNode.getSession(), treeNode);
// Get the new tree node, refresh it in the view, and expand it if needed
treeNode = await this.getTreeNode(connectionId, nodePath);
await this._serverTreeView.refreshElement(treeNode);
if (treeNode.children.length > 0) {
await treeNode.setExpandedState(TreeItemCollapsibleState.Expanded);
}
return treeNode;
}
private async setNodeExpandedState(treeNode: TreeNode, expandedState: TreeItemCollapsibleState): Promise<void> { private async setNodeExpandedState(treeNode: TreeNode, expandedState: TreeItemCollapsibleState): Promise<void> {
treeNode = await this.getUpdatedTreeNode(treeNode); treeNode = await this.getUpdatedTreeNode(treeNode);
let expandNode = this.getTreeItem(treeNode); let expandNode = this.getTreeItem(treeNode);

View File

@@ -138,7 +138,7 @@ export class ServerTreeView {
let expandGroups: boolean = self._configurationService.getValue(SERVER_GROUP_CONFIG)[SERVER_GROUP_AUTOEXPAND_CONFIG]; let expandGroups: boolean = self._configurationService.getValue(SERVER_GROUP_CONFIG)[SERVER_GROUP_AUTOEXPAND_CONFIG];
if (expandGroups) { if (expandGroups) {
self._tree.expandAll(ConnectionProfileGroup.getSubgroups(root)); self._tree.expandAll(ConnectionProfileGroup.getSubgroups(root));
} }
if (root && !root.hasValidConnections) { if (root && !root.hasValidConnections) {
@@ -244,6 +244,10 @@ export class ServerTreeView {
TreeUpdateUtils.registeredServerUpdate(this._tree, this._connectionManagementService); TreeUpdateUtils.registeredServerUpdate(this._tree, this._connectionManagementService);
} }
public refreshElement(element: any): Thenable<void> {
return this._tree.refresh(element);
}
/** /**
* Filter connections based on view (recent/active) * Filter connections based on view (recent/active)
*/ */

5
src/sql/sqlops.d.ts vendored
View File

@@ -185,6 +185,11 @@ declare module 'sqlops' {
* Get the parent node. Returns undefined if there is none. * Get the parent node. Returns undefined if there is none.
*/ */
getParent(): Thenable<ObjectExplorerNode>; getParent(): Thenable<ObjectExplorerNode>;
/**
* Refresh the node, expanding it if it has children
*/
refresh(): Thenable<void>;
} }
} }

View File

@@ -9,7 +9,7 @@ import { ExtHostObjectExplorerShape, SqlMainContext, MainThreadObjectExplorerSha
import * as sqlops from 'sqlops'; import * as sqlops from 'sqlops';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
export class ExtHostObjectExplorer implements ExtHostObjectExplorerShape { export class ExtHostObjectExplorer implements ExtHostObjectExplorerShape {
private _proxy: MainThreadObjectExplorerShape; private _proxy: MainThreadObjectExplorerShape;
@@ -44,7 +44,7 @@ class ExtHostObjectExplorerNode implements sqlops.objectexplorer.ObjectExplorerN
public errorMessage: string; public errorMessage: string;
constructor(nodeInfo: sqlops.NodeInfo, connectionId: string, private _proxy: MainThreadObjectExplorerShape) { constructor(nodeInfo: sqlops.NodeInfo, connectionId: string, private _proxy: MainThreadObjectExplorerShape) {
Object.entries(nodeInfo).forEach(([key, value]) => this[key] = value); this.getDetailsFromInfo(nodeInfo);
this.connectionId = connectionId; this.connectionId = connectionId;
} }
@@ -71,4 +71,12 @@ class ExtHostObjectExplorerNode implements sqlops.objectexplorer.ObjectExplorerN
} }
return this._proxy.$getNode(this.connectionId, this.nodePath.slice(0, parentPathEndIndex)).then(nodeInfo => nodeInfo ? new ExtHostObjectExplorerNode(nodeInfo, this.connectionId, this._proxy) : undefined); return this._proxy.$getNode(this.connectionId, this.nodePath.slice(0, parentPathEndIndex)).then(nodeInfo => nodeInfo ? new ExtHostObjectExplorerNode(nodeInfo, this.connectionId, this._proxy) : undefined);
} }
refresh(): Thenable<void> {
return this._proxy.$refresh(this.connectionId, this.nodePath).then(nodeInfo => this.getDetailsFromInfo(nodeInfo));
}
private getDetailsFromInfo(nodeInfo: sqlops.NodeInfo): void {
Object.entries(nodeInfo).forEach(([key, value]) => this[key] = value);
}
} }

View File

@@ -15,6 +15,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import * as TaskUtilities from 'sql/workbench/common/taskUtilities'; import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces'; import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
import { dispose, IDisposable } from 'vs/base/common/lifecycle'; import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { TreeItemCollapsibleState } from 'sql/parts/objectExplorer/common/treeNode';
@extHostNamedCustomer(SqlMainContext.MainThreadObjectExplorer) @extHostNamedCustomer(SqlMainContext.MainThreadObjectExplorer)
export class MainThreadObjectExplorer implements MainThreadObjectExplorerShape { export class MainThreadObjectExplorer implements MainThreadObjectExplorerShape {
@@ -50,7 +51,7 @@ export class MainThreadObjectExplorer implements MainThreadObjectExplorerShape {
public $getActiveConnectionNodes(): Thenable<NodeInfoWithConnection[]> { public $getActiveConnectionNodes(): Thenable<NodeInfoWithConnection[]> {
let connectionNodes = this._objectExplorerService.getActiveConnectionNodes(); let connectionNodes = this._objectExplorerService.getActiveConnectionNodes();
return Promise.resolve(connectionNodes.map(node => { return Promise.resolve(connectionNodes.map(node => {
return {connectionId: node.connection.id, nodeInfo: node.toNodeInfo()}; return { connectionId: node.connection.id, nodeInfo: node.toNodeInfo() };
})); }));
} }
@@ -73,4 +74,8 @@ export class MainThreadObjectExplorer implements MainThreadObjectExplorerShape {
public $findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames: string[]): Thenable<sqlops.NodeInfo[]> { public $findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames: string[]): Thenable<sqlops.NodeInfo[]> {
return this._objectExplorerService.findNodes(connectionId, type, schema, name, database, parentObjectNames); return this._objectExplorerService.findNodes(connectionId, type, schema, name, database, parentObjectNames);
} }
public $refresh(connectionId: string, nodePath: string): Thenable<sqlops.NodeInfo> {
return this._objectExplorerService.refreshNodeInView(connectionId, nodePath).then(node => node.toNodeInfo());
}
} }

View File

@@ -36,7 +36,7 @@ export abstract class ExtHostAccountManagementShape {
export abstract class ExtHostConnectionManagementShape { export abstract class ExtHostConnectionManagementShape {
$onConnectionOpened(handleId: string, connection: sqlops.connection.Connection): void { throw ni; } $onConnectionOpened(handleId: string, connection: sqlops.connection.Connection): void { throw ni; }
} }
export abstract class ExtHostDataProtocolShape { export abstract class ExtHostDataProtocolShape {
@@ -663,6 +663,7 @@ export interface MainThreadObjectExplorerShape extends IDisposable {
$getChildren(connectionId: string, nodePath: string): Thenable<sqlops.NodeInfo[]>; $getChildren(connectionId: string, nodePath: string): Thenable<sqlops.NodeInfo[]>;
$isExpanded(connectionId: string, nodePath: string): Thenable<boolean>; $isExpanded(connectionId: string, nodePath: string): Thenable<boolean>;
$findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames: string[]): Thenable<sqlops.NodeInfo[]>; $findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames: string[]): Thenable<sqlops.NodeInfo[]>;
$refresh(connectionId: string, nodePath: string): Thenable<sqlops.NodeInfo>;
} }
export interface ExtHostModelViewDialogShape { export interface ExtHostModelViewDialogShape {

View File

@@ -301,7 +301,8 @@ suite('SQL Object Explorer Service tests', () => {
reveal: element => Promise.resolve() as Thenable<void>, reveal: element => Promise.resolve() as Thenable<void>,
setSelected: (element, selected, clearOtherSelections) => undefined, setSelected: (element, selected, clearOtherSelections) => undefined,
isExpanded: element => undefined, isExpanded: element => undefined,
onSelectionOrFocusChange: Event.None onSelectionOrFocusChange: Event.None,
refreshElement: (element) => Promise.resolve() as Thenable<void>
} as ServerTreeView); } as ServerTreeView);
}); });
@@ -738,4 +739,22 @@ suite('SQL Object Explorer Service tests', () => {
}, err => done(err)); }, err => done(err));
}); });
}); });
test('refreshInView refreshes the node, expands it, and returns the refreshed node', async () => {
// Set up the session and tree view
await objectExplorerService.createNewSession('MSSQL', connection);
objectExplorerService.onSessionCreated(1, objectExplorerSession);
serverTreeView.setup(x => x.refreshElement(TypeMoq.It.isAny())).returns(() => Promise.resolve());
objectExplorerService.registerServerTreeView(serverTreeView.object);
// Refresh the node
let nodePath = objectExplorerSession.rootNode.nodePath;
let refreshedNode = await objectExplorerService.refreshNodeInView(connection.id, nodePath);
// Verify that it was refreshed, expanded, and the refreshed detailed were returned
sqlOEProvider.verify(x => x.refreshNode(TypeMoq.It.is(refreshNode => refreshNode.nodePath === nodePath)), TypeMoq.Times.once());
refreshedNode.children.forEach((childNode, index) => {
assert.equal(childNode.nodePath, objectExplorerExpandInfoRefresh.nodes[index].nodePath);
});
});
}); });