Data explorer/context menu initial (#6264)

* fixed context for data explorer

* added more files

* initial servers and database context menu actions finished

* added all actions for servers and databases with correct conditions

* added nodetype and nodelabel for subtype actions

* added nodeinfo logic to oe shim

* fixed context for cms

* added all scripting actions to data explorer

* review comments

* fix import

* fix correct context key

* removed unused import

* separate PR for commands and menus added

* rename mssql context menu nodes

* remove command id constants
This commit is contained in:
Aditya Bist
2019-07-03 16:03:09 -07:00
committed by GitHub
parent 10b066d300
commit ecfcb92a89
19 changed files with 276 additions and 36 deletions

View File

@@ -5,7 +5,7 @@
'use strict'; 'use strict';
import { AzureResource } from 'azdata'; import { AzureResource, ExtensionNodeType } from 'azdata';
import { TreeItem, TreeItemCollapsibleState, ExtensionContext } from 'vscode'; import { TreeItem, TreeItemCollapsibleState, ExtensionContext } from 'vscode';
import { TokenCredentials } from 'ms-rest'; import { TokenCredentials } from 'ms-rest';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
@@ -72,7 +72,8 @@ export class AzureResourceDatabaseTreeDataProvider implements azureResource.IAzu
saveProfile: false, saveProfile: false,
options: {} options: {}
}, },
childProvider: 'MSSQL' childProvider: 'MSSQL',
type: ExtensionNodeType.Database
} }
}); });
} }

View File

@@ -5,7 +5,7 @@
'use strict'; 'use strict';
import { AzureResource } from 'azdata'; import { AzureResource, ExtensionNodeType } from 'azdata';
import { TreeItem, TreeItemCollapsibleState, ExtensionContext } from 'vscode'; import { TreeItem, TreeItemCollapsibleState, ExtensionContext } from 'vscode';
import { TokenCredentials } from 'ms-rest'; import { TokenCredentials } from 'ms-rest';
import * as nls from 'vscode-nls'; import * as nls from 'vscode-nls';
@@ -72,7 +72,8 @@ export class AzureResourceDatabaseServerTreeDataProvider implements azureResourc
saveProfile: false, saveProfile: false,
options: {} options: {}
}, },
childProvider: 'MSSQL' childProvider: 'MSSQL',
type: ExtensionNodeType.Server
} }
}); });
} }

View File

@@ -95,6 +95,7 @@ export class CmsResourceTreeNode extends CmsResourceTreeNodeBase {
item.contextValue = CmsResourceItemType.cmsNodeContainer; item.contextValue = CmsResourceItemType.cmsNodeContainer;
item.id = this._id; item.id = this._id;
item.tooltip = this.description; item.tooltip = this.description;
item.type = azdata.ExtensionNodeType.Server;
item.iconPath = { item.iconPath = {
dark: this.appContext.extensionContext.asAbsolutePath('resources/light/centralmanagement_server.svg'), dark: this.appContext.extensionContext.asAbsolutePath('resources/light/centralmanagement_server.svg'),
light: this.appContext.extensionContext.asAbsolutePath('resources/light/centralmanagement_server.svg') light: this.appContext.extensionContext.asAbsolutePath('resources/light/centralmanagement_server.svg')

View File

@@ -55,6 +55,7 @@ export class RegisteredServerTreeNode extends CmsResourceTreeNodeBase {
collapsibleState: TreeItemCollapsibleState.Collapsed, collapsibleState: TreeItemCollapsibleState.Collapsed,
label: this.name ? this.name : this.serverName, label: this.name ? this.name : this.serverName,
childProvider: 'MSSQL', childProvider: 'MSSQL',
type: azdata.ExtensionNodeType.Server,
iconPath: { iconPath: {
dark: this.appContext.extensionContext.asAbsolutePath('resources/light/regserverserver.svg'), dark: this.appContext.extensionContext.asAbsolutePath('resources/light/regserverserver.svg'),
light: this.appContext.extensionContext.asAbsolutePath('resources/light/regserverserver.svg') light: this.appContext.extensionContext.asAbsolutePath('resources/light/regserverserver.svg')

View File

@@ -2632,9 +2632,15 @@ declare module 'azdata' {
serverInfo: ServerInfo; serverInfo: ServerInfo;
} }
export enum ExtensionNodeType {
Server = 'Server',
Database = 'Database'
}
export class TreeItem extends vscode.TreeItem { export class TreeItem extends vscode.TreeItem {
payload?: IConnectionProfile; payload?: IConnectionProfile;
childProvider?: string; childProvider?: string;
type?: ExtensionNodeType;
} }
export namespace tasks { export namespace tasks {

View File

@@ -191,6 +191,11 @@ export enum StepCompletionAction {
GoToStep = 4 GoToStep = 4
} }
export enum ExtensionNodeType {
Server = 'Server',
Database = 'Database'
}
export interface IComponentShape { export interface IComponentShape {
type: ModelComponentTypes; type: ModelComponentTypes;
id: string; id: string;

View File

@@ -21,7 +21,9 @@ export class ExtHostConnectionManagement extends ExtHostConnectionManagementShap
public $getCurrentConnection(): Thenable<azdata.connection.ConnectionProfile> { public $getCurrentConnection(): Thenable<azdata.connection.ConnectionProfile> {
let connection: any = this._proxy.$getCurrentConnection(); let connection: any = this._proxy.$getCurrentConnection();
connection.then((conn) => { connection.then((conn) => {
conn.providerId = conn.providerName; if (conn && conn.providerId) {
conn.providerId = conn.providerName;
}
}); });
return connection; return connection;
} }

View File

@@ -552,7 +552,8 @@ export function createApiFactory(
ColumnType: sqlExtHostTypes.ColumnType, ColumnType: sqlExtHostTypes.ColumnType,
ActionOnCellCheckboxCheck: sqlExtHostTypes.ActionOnCellCheckboxCheck, ActionOnCellCheckboxCheck: sqlExtHostTypes.ActionOnCellCheckboxCheck,
StepCompletionAction: sqlExtHostTypes.StepCompletionAction, StepCompletionAction: sqlExtHostTypes.StepCompletionAction,
AgentSubSystem: sqlExtHostTypes.AgentSubSystem AgentSubSystem: sqlExtHostTypes.AgentSubSystem,
ExtensionNodeType: sqlExtHostTypes.ExtensionNodeType
}; };
}, },

View File

@@ -43,7 +43,6 @@ import { dirname } from 'vs/base/common/resources';
import { ITreeItem, ITreeView } from 'sql/workbench/common/views'; import { ITreeItem, ITreeView } from 'sql/workbench/common/views';
import { IOEShimService } from 'sql/workbench/parts/objectExplorer/common/objectExplorerViewTreeShim'; import { IOEShimService } from 'sql/workbench/parts/objectExplorer/common/objectExplorerViewTreeShim';
import { equalsIgnoreCase } from 'vs/base/common/strings';
import { NodeContextKey } from 'sql/workbench/parts/dataExplorer/common/nodeContext'; import { NodeContextKey } from 'sql/workbench/parts/dataExplorer/common/nodeContext';
import { fillInActionBarActions, fillInContextMenuActions, ContextAwareMenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; import { fillInActionBarActions, fillInContextMenuActions, ContextAwareMenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { mssqlProviderName } from 'sql/platform/connection/common/constants'; import { mssqlProviderName } from 'sql/platform/connection/common/constants';

View File

@@ -5,6 +5,7 @@
import { ITreeViewDataProvider, ITreeItem as vsITreeItem, IViewDescriptor, ITreeView as vsITreeView } from 'vs/workbench/common/views'; import { ITreeViewDataProvider, ITreeItem as vsITreeItem, IViewDescriptor, ITreeView as vsITreeView } from 'vs/workbench/common/views';
import { IConnectionProfile } from 'azdata'; import { IConnectionProfile } from 'azdata';
import { ExtensionNodeType } from 'sql/workbench/api/common/sqlExtHostTypes';
export interface ITreeComponentItem extends vsITreeItem { export interface ITreeComponentItem extends vsITreeItem {
checked?: boolean; checked?: boolean;
@@ -22,6 +23,7 @@ export interface ITreeItem extends vsITreeItem {
childProvider?: string; childProvider?: string;
payload?: IConnectionProfile; // its possible we will want this to be more generic payload?: IConnectionProfile; // its possible we will want this to be more generic
sqlIcon?: string; sqlIcon?: string;
type?: ExtensionNodeType;
} }
export interface ITreeView extends vsITreeView { export interface ITreeView extends vsITreeView {

View File

@@ -112,6 +112,7 @@ export class DataExplorerViewlet extends ViewContainerViewlet {
actions.push(...group[1]); actions.push(...group[1]);
} }
}); });
menu.dispose();
return actions; return actions;
} }

View File

@@ -0,0 +1,159 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as os from 'os';
import { INodeContextValue } from 'sql/workbench/parts/dataExplorer/common/nodeContext';
import { RawContextKey, IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { Disposable } from 'vs/base/common/lifecycle';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
import { mssqlProviderName } from 'sql/platform/connection/common/constants';
import { NodeType } from 'sql/workbench/parts/objectExplorer/common/nodeType';
import { ExtensionNodeType } from 'sql/workbench/api/common/sqlExtHostTypes';
export class MssqlNodeContext extends Disposable {
static readonly canSelect = new Set([NodeType.Table, NodeType.View]);
static readonly canEditData = new Set([NodeType.Table]);
static readonly canCreateOrDelete = new Set([NodeType.AggregateFunction, NodeType.PartitionFunction, NodeType.ScalarValuedFunction,
NodeType.Schema, NodeType.StoredProcedure, NodeType.Table, NodeType.TableValuedFunction,
NodeType.User, NodeType.UserDefinedTableType, NodeType.View]);
static readonly canExecute = new Set([NodeType.StoredProcedure]);
static readonly canAlter = new Set([NodeType.AggregateFunction, NodeType.PartitionFunction, NodeType.ScalarValuedFunction,
NodeType.StoredProcedure, NodeType.TableValuedFunction, NodeType.View]);
// General node context keys
static NodeProvider = new RawContextKey<string>('nodeProvider', undefined);
static IsDatabaseOrServer = new RawContextKey<boolean>('isDatabaseOrServer', false);
static IsWindows = new RawContextKey<boolean>('isWindows', os.platform() === 'win32');
static IsCloud = new RawContextKey<boolean>('isCloud', false);
static NodeType = new RawContextKey<string>('nodeType', undefined);
static NodeLabel = new RawContextKey<string>('nodeLabel', undefined);
// Scripting context keys
static CanScriptAsSelect = new RawContextKey<boolean>('canScriptAsSelect', false);
static CanEditData = new RawContextKey<boolean>('canEditData', false);
static CanScriptAsCreateOrDelete = new RawContextKey<boolean>('canScriptAsCreateOeDelete', false);
static CanScriptAsExecute = new RawContextKey<boolean>('canScriptAsExecute', false);
static CanScriptAsAlter = new RawContextKey<boolean>('canScriptAsAlter', false);
private nodeProviderKey: IContextKey<string>;
private isCloudKey: IContextKey<boolean>;
private nodeTypeKey: IContextKey<string>;
private nodeLabelKey: IContextKey<string>;
private isDatabaseOrServerKey: IContextKey<boolean>;
private canScriptAsSelectKey: IContextKey<boolean>;
private canEditDataKey: IContextKey<boolean>;
private canScriptAsCreateOrDeleteKey: IContextKey<boolean>;
private canScriptAsExecuteKey: IContextKey<boolean>;
private canScriptAsAlterKey: IContextKey<boolean>;
constructor(
private nodeContextValue: INodeContextValue,
@IContextKeyService private contextKeyService: IContextKeyService,
@IConnectionManagementService private connectionManagementService: IConnectionManagementService,
@ICapabilitiesService private capabilitiesService: ICapabilitiesService
) {
super();
this.bindContextKeys();
// Set additional node context keys
if (this.nodeContextValue.node) {
const node = this.nodeContextValue.node;
if (node.payload) {
this.setNodeProvider();
this.setIsCloud();
if (node.type) {
this.setIsDatabaseOrServer();
this.nodeTypeKey.set(node.type);
} else if (node.contextValue && node.providerHandle === mssqlProviderName) {
this.setIsDatabaseOrServer();
this.setScriptingContextKeys();
this.nodeTypeKey.set(node.contextValue);
}
}
if (node.label) {
this.nodeLabelKey.set(node.label.label);
}
}
}
private bindContextKeys(): void {
this.isCloudKey = MssqlNodeContext.IsCloud.bindTo(this.contextKeyService);
this.nodeTypeKey = MssqlNodeContext.NodeType.bindTo(this.contextKeyService);
this.nodeLabelKey = MssqlNodeContext.NodeLabel.bindTo(this.contextKeyService);
this.isDatabaseOrServerKey = MssqlNodeContext.IsDatabaseOrServer.bindTo(this.contextKeyService);
this.canScriptAsSelectKey = MssqlNodeContext.CanScriptAsSelect.bindTo(this.contextKeyService);
this.canEditDataKey = MssqlNodeContext.CanEditData.bindTo(this.contextKeyService);
this.canScriptAsCreateOrDeleteKey = MssqlNodeContext.CanScriptAsCreateOrDelete.bindTo(this.contextKeyService);
this.canScriptAsExecuteKey = MssqlNodeContext.CanScriptAsExecute.bindTo(this.contextKeyService);
this.canScriptAsAlterKey = MssqlNodeContext.CanScriptAsAlter.bindTo(this.contextKeyService);
this.nodeProviderKey = MssqlNodeContext.NodeProvider.bindTo(this.contextKeyService);
}
/**
* Helper function to get the node provider
*/
private setNodeProvider(): void {
if (this.nodeContextValue.node.payload.providerName) {
this.nodeProviderKey.set(this.nodeContextValue.node.payload.providerName);
} else if (this.nodeContextValue.node.childProvider) {
this.nodeProviderKey.set(this.nodeContextValue.node.childProvider);
}
}
/**
* Helper function to tell whether a connected node is cloud or not
*/
private setIsCloud(): void {
const profile = new ConnectionProfile(this.capabilitiesService,
this.nodeContextValue.node.payload);
const connection = this.connectionManagementService.findExistingConnection(profile);
if (connection) {
const serverInfo = this.connectionManagementService.getServerInfo(connection.id);
if (serverInfo.isCloud) {
this.isCloudKey.set(true);
}
}
}
/**
* Helper function to tell whether a connected node is a database or a
* server or not. Added this key because this is easier to write than
* writing an OR statement in ContextKeyExpr
*/
private setIsDatabaseOrServer(): void {
const isDatabaseOrServer = (this.nodeContextValue.node.contextValue === NodeType.Server ||
this.nodeContextValue.node.contextValue === NodeType.Database ||
this.nodeContextValue.node.type === ExtensionNodeType.Server ||
this.nodeContextValue.node.type === ExtensionNodeType.Database);
this.isDatabaseOrServerKey.set(isDatabaseOrServer);
}
/**
* Helper function to get the correct context from node for showing
* scripting context menu actions
*/
private setScriptingContextKeys(): void {
const nodeType = this.nodeContextValue.node.contextValue;
if (MssqlNodeContext.canCreateOrDelete.has(nodeType)) {
this.canScriptAsCreateOrDeleteKey.set(true);
}
if (MssqlNodeContext.canEditData.has(nodeType)) {
this.canEditDataKey.set(true);
}
if (MssqlNodeContext.canAlter.has(nodeType)) {
this.canScriptAsAlterKey.set(true);
}
if (MssqlNodeContext.canExecute.has(nodeType)) {
this.canScriptAsExecuteKey.set(true);
}
if (MssqlNodeContext.canSelect.has(nodeType)) {
this.canScriptAsSelectKey.set(true);
}
}
}

View File

@@ -9,6 +9,9 @@ import { ITreeItem } from 'sql/workbench/common/views';
import { Disposable } from 'vs/base/common/lifecycle'; import { Disposable } from 'vs/base/common/lifecycle';
import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IQueryManagementService } from 'sql/platform/query/common/queryManagement'; import { IQueryManagementService } from 'sql/platform/query/common/queryManagement';
import { MssqlNodeContext } from 'sql/workbench/parts/dataExplorer/common/mssqlNodeContext';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
export interface INodeContextValue { export interface INodeContextValue {
node: ITreeItem; node: ITreeItem;
@@ -30,10 +33,14 @@ export class NodeContextKey extends Disposable implements IContextKey<INodeConte
private readonly _viewItemKey: IContextKey<string>; private readonly _viewItemKey: IContextKey<string>;
private readonly _nodeContextKey: IContextKey<INodeContextValue>; private readonly _nodeContextKey: IContextKey<INodeContextValue>;
private _nodeContextUtils: MssqlNodeContext;
constructor( constructor(
@IContextKeyService contextKeyService: IContextKeyService, @IContextKeyService private contextKeyService: IContextKeyService,
@IOEShimService private oeService: IOEShimService, @IOEShimService private oeService: IOEShimService,
@IQueryManagementService queryManagementService: IQueryManagementService @IQueryManagementService queryManagementService: IQueryManagementService,
@IConnectionManagementService private connectionManagementService: IConnectionManagementService,
@ICapabilitiesService private capabilitiesService: ICapabilitiesService
) { ) {
super(); super();
@@ -62,6 +69,8 @@ export class NodeContextKey extends Disposable implements IContextKey<INodeConte
} }
this._nodeContextKey.set(value); this._nodeContextKey.set(value);
this._viewIdKey.set(value.viewId); this._viewIdKey.set(value.viewId);
this._nodeContextUtils = new MssqlNodeContext(this._nodeContextKey.get(), this.contextKeyService,
this.connectionManagementService, this.capabilitiesService);
} }
reset(): void { reset(): void {
@@ -71,6 +80,7 @@ export class NodeContextKey extends Disposable implements IContextKey<INodeConte
this._connectedKey.reset(); this._connectedKey.reset();
this._connectionContextKey.reset(); this._connectionContextKey.reset();
this._nodeContextKey.reset(); this._nodeContextKey.reset();
this._nodeContextUtils.dispose();
} }
get(): INodeContextValue | undefined { get(): INodeContextValue | undefined {

View File

@@ -4,10 +4,26 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import { mssqlProviderName } from 'sql/platform/connection/common/constants';
import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
import { DISCONNECT_COMMAND_ID, MANAGE_COMMAND_ID, NEW_QUERY_COMMAND_ID, REFRESH_COMMAND_ID } from './nodeCommands'; import {
import { ContextKeyExpr, ContextKeyRegexExpr } from 'vs/platform/contextkey/common/contextkey'; DISCONNECT_COMMAND_ID, MANAGE_COMMAND_ID, NEW_QUERY_COMMAND_ID, REFRESH_COMMAND_ID
} from './nodeCommands';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { NodeContextKey } from 'sql/workbench/parts/dataExplorer/common/nodeContext'; import { NodeContextKey } from 'sql/workbench/parts/dataExplorer/common/nodeContext';
import { MssqlNodeContext } from 'sql/workbench/parts/dataExplorer/common/mssqlNodeContext';
// Disconnect
MenuRegistry.appendMenuItem(MenuId.DataExplorerContext, {
group: 'connection',
order: 4,
command: {
id: DISCONNECT_COMMAND_ID,
title: localize('disconnect', 'Disconnect')
},
when: NodeContextKey.IsConnected //add for folders
});
MenuRegistry.appendMenuItem(MenuId.DataExplorerContext, { MenuRegistry.appendMenuItem(MenuId.DataExplorerContext, {
group: 'connection', group: 'connection',
@@ -16,13 +32,12 @@ MenuRegistry.appendMenuItem(MenuId.DataExplorerContext, {
id: DISCONNECT_COMMAND_ID, id: DISCONNECT_COMMAND_ID,
title: localize('disconnect', 'Disconnect') title: localize('disconnect', 'Disconnect')
}, },
when: NodeContextKey.IsConnected when: ContextKeyExpr.and(NodeContextKey.IsConnected,
MssqlNodeContext.NodeProvider.isEqualTo(mssqlProviderName),
MssqlNodeContext.IsDatabaseOrServer)
}); });
// The weird regex is because we want this to generically apply to Database and Server nodes but right now // New Query
// there isn't a consistent standard for the values there. We can't just search for database or server being
// in the string at all because there's lots of node types which have those values (such as ServerLevelLogin)
// that we don't want these menu items showing up on.
MenuRegistry.appendMenuItem(MenuId.DataExplorerContext, { MenuRegistry.appendMenuItem(MenuId.DataExplorerContext, {
group: 'connection', group: 'connection',
order: 2, order: 2,
@@ -30,13 +45,10 @@ MenuRegistry.appendMenuItem(MenuId.DataExplorerContext, {
id: NEW_QUERY_COMMAND_ID, id: NEW_QUERY_COMMAND_ID,
title: localize('newQuery', 'New Query') title: localize('newQuery', 'New Query')
}, },
when: ContextKeyExpr.and( when: MssqlNodeContext.IsDatabaseOrServer
NodeContextKey.IsConnectable,
new ContextKeyRegexExpr('viewItem', /.+itemType\.database.*|^database$/i))
}); });
// Note that we don't show this for Databases under Server nodes (viewItem == Database) because // Manage
// of an issue there where the connection always being master instead of the actual DB
MenuRegistry.appendMenuItem(MenuId.DataExplorerContext, { MenuRegistry.appendMenuItem(MenuId.DataExplorerContext, {
group: 'connection', group: 'connection',
order: 1, order: 1,
@@ -44,17 +56,17 @@ MenuRegistry.appendMenuItem(MenuId.DataExplorerContext, {
id: MANAGE_COMMAND_ID, id: MANAGE_COMMAND_ID,
title: localize('manage', 'Manage') title: localize('manage', 'Manage')
}, },
when: ContextKeyExpr.and( when: MssqlNodeContext.IsDatabaseOrServer
NodeContextKey.IsConnectable,
new ContextKeyRegexExpr('viewItem', /.+itemType\.database.*/i))
}); });
// Refresh
MenuRegistry.appendMenuItem(MenuId.DataExplorerContext, { MenuRegistry.appendMenuItem(MenuId.DataExplorerContext, {
group: 'connection', group: 'connection',
order: 4, order: 6,
command: { command: {
id: REFRESH_COMMAND_ID, id: REFRESH_COMMAND_ID,
title: localize('refresh', 'Refresh') title: localize('refresh', 'Refresh')
}, },
when: NodeContextKey.IsConnected when: NodeContextKey.IsConnectable
}); });

View File

@@ -10,7 +10,7 @@ import { ConnectionProfile } from 'sql/platform/connection/common/connectionProf
import { generateUri } from 'sql/platform/connection/common/utils'; import { generateUri } from 'sql/platform/connection/common/utils';
import { ICustomViewDescriptor, TreeViewItemHandleArg } from 'sql/workbench/common/views'; import { ICustomViewDescriptor, TreeViewItemHandleArg } from 'sql/workbench/common/views';
import { IQueryEditorService } from 'sql/workbench/services/queryEditor/common/queryEditorService'; import { IQueryEditorService } from 'sql/workbench/services/queryEditor/common/queryEditorService';
import { CommandsRegistry } from 'vs/platform/commands/common/commands'; import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
import { IViewsRegistry, Extensions } from 'vs/workbench/common/views'; import { IViewsRegistry, Extensions } from 'vs/workbench/common/views';
import { IProgressService2 } from 'vs/platform/progress/common/progress'; import { IProgressService2 } from 'vs/platform/progress/common/progress';
import { Registry } from 'vs/platform/registry/common/platform'; import { Registry } from 'vs/platform/registry/common/platform';
@@ -20,6 +20,7 @@ export const MANAGE_COMMAND_ID = 'dataExplorer.manage';
export const NEW_QUERY_COMMAND_ID = 'dataExplorer.newQuery'; export const NEW_QUERY_COMMAND_ID = 'dataExplorer.newQuery';
export const REFRESH_COMMAND_ID = 'dataExplorer.refresh'; export const REFRESH_COMMAND_ID = 'dataExplorer.refresh';
// Disconnect
CommandsRegistry.registerCommand({ CommandsRegistry.registerCommand({
id: DISCONNECT_COMMAND_ID, id: DISCONNECT_COMMAND_ID,
handler: (accessor, args: TreeViewItemHandleArg) => { handler: (accessor, args: TreeViewItemHandleArg) => {
@@ -35,6 +36,7 @@ CommandsRegistry.registerCommand({
} }
}); });
// New Query
CommandsRegistry.registerCommand({ CommandsRegistry.registerCommand({
id: NEW_QUERY_COMMAND_ID, id: NEW_QUERY_COMMAND_ID,
handler: (accessor, args: TreeViewItemHandleArg) => { handler: (accessor, args: TreeViewItemHandleArg) => {
@@ -58,6 +60,7 @@ CommandsRegistry.registerCommand({
} }
}); });
// Manage
CommandsRegistry.registerCommand({ CommandsRegistry.registerCommand({
id: MANAGE_COMMAND_ID, id: MANAGE_COMMAND_ID,
handler: (accessor, args: TreeViewItemHandleArg) => { handler: (accessor, args: TreeViewItemHandleArg) => {
@@ -79,6 +82,7 @@ CommandsRegistry.registerCommand({
} }
}); });
// Refresh
CommandsRegistry.registerCommand({ CommandsRegistry.registerCommand({
id: REFRESH_COMMAND_ID, id: REFRESH_COMMAND_ID,
handler: (accessor, args: TreeViewItemHandleArg) => { handler: (accessor, args: TreeViewItemHandleArg) => {
@@ -94,4 +98,4 @@ CommandsRegistry.registerCommand({
} }
return Promise.resolve(true); return Promise.resolve(true);
} }
}); });

View File

@@ -558,7 +558,6 @@ export class NewNotebookAction extends Action {
run(context?: azdata.ConnectedContext): Promise<void> { run(context?: azdata.ConnectedContext): Promise<void> {
return this.commandService.executeCommand(NewNotebookAction.INTERNAL_NEW_NOTEBOOK_CMD_ID, context); return this.commandService.executeCommand(NewNotebookAction.INTERNAL_NEW_NOTEBOOK_CMD_ID, context);
} }
} }

View File

@@ -60,7 +60,6 @@ export class OEAction extends ExecuteCommandAction {
public async run(actionContext: any): Promise<boolean> { public async run(actionContext: any): Promise<boolean> {
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler); this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
let profile: IConnectionProfile; let profile: IConnectionProfile;
if (actionContext instanceof ObjectExplorerActionsContext) { if (actionContext instanceof ObjectExplorerActionsContext) {
if (actionContext.isConnectionNode) { if (actionContext.isConnectionNode) {
@@ -240,7 +239,7 @@ export class OEScriptCreateAction extends ScriptCreateAction {
@IScriptingService protected _scriptingService: IScriptingService, @IScriptingService protected _scriptingService: IScriptingService,
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService, @IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
@IInstantiationService private _instantiationService: IInstantiationService, @IInstantiationService private _instantiationService: IInstantiationService,
@IErrorMessageService protected _errorMessageService: IErrorMessageService @IErrorMessageService protected _errorMessageService: IErrorMessageService,
) { ) {
super(id, label, _queryEditorService, _connectionManagementService, _scriptingService, _errorMessageService); super(id, label, _queryEditorService, _connectionManagementService, _scriptingService, _errorMessageService);
} }

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information. * Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { Deferred } from 'sql/base/common/promise'; import * as azdata from 'azdata';
import { TreeNode } from 'sql/workbench/parts/objectExplorer/common/treeNode'; import { TreeNode } from 'sql/workbench/parts/objectExplorer/common/treeNode';
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService'; import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
import { ConnectionType, IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement'; import { ConnectionType, IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
@@ -17,6 +17,7 @@ import { generateUuid } from 'vs/base/common/uuid';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { TreeItemCollapsibleState } from 'vs/workbench/common/views'; import { TreeItemCollapsibleState } from 'vs/workbench/common/views';
import { localize } from 'vs/nls'; import { localize } from 'vs/nls';
import { NodeType } from 'sql/workbench/parts/objectExplorer/common/nodeType';
export const SERVICE_ID = 'oeShimService'; export const SERVICE_ID = 'oeShimService';
export const IOEShimService = createDecorator<IOEShimService>(SERVICE_ID); export const IOEShimService = createDecorator<IOEShimService>(SERVICE_ID);
@@ -27,6 +28,7 @@ export interface IOEShimService {
disconnectNode(viewId: string, node: ITreeItem): Promise<boolean>; disconnectNode(viewId: string, node: ITreeItem): Promise<boolean>;
providerExists(providerId: string): boolean; providerExists(providerId: string): boolean;
isNodeConnected(viewId: string, node: ITreeItem): boolean; isNodeConnected(viewId: string, node: ITreeItem): boolean;
getNodeInfoForTreeItem(treeItem: ITreeItem): azdata.NodeInfo;
} }
export class OEShimService extends Disposable implements IOEShimService { export class OEShimService extends Disposable implements IOEShimService {
@@ -34,6 +36,7 @@ export class OEShimService extends Disposable implements IOEShimService {
private sessionMap = new Map<number, string>(); private sessionMap = new Map<number, string>();
private nodeHandleMap = new Map<number, string>(); private nodeHandleMap = new Map<number, string>();
private nodeInfoMap = new Map<ITreeItem, azdata.NodeInfo>();
constructor( constructor(
@IObjectExplorerService private oe: IObjectExplorerService, @IObjectExplorerService private oe: IObjectExplorerService,
@@ -140,8 +143,8 @@ export class OEShimService extends Disposable implements IOEShimService {
private treeNodeToITreeItem(viewId: string, node: TreeNode, parentNode: ITreeItem): ITreeItem { private treeNodeToITreeItem(viewId: string, node: TreeNode, parentNode: ITreeItem): ITreeItem {
let handle = generateUuid(); let handle = generateUuid();
let nodePath = node.nodePath;
let icon: string = ''; let icon: string = '';
let nodePath = node.nodePath;
if (node.iconType) { if (node.iconType) {
icon = (typeof node.iconType === 'string') ? node.iconType : node.iconType.id; icon = (typeof node.iconType === 'string') ? node.iconType : node.iconType.id;
} else { } else {
@@ -154,6 +157,31 @@ export class OEShimService extends Disposable implements IOEShimService {
} }
} }
icon = icon.toLowerCase(); icon = icon.toLowerCase();
// Change the database if the node has a different database
// than its parent
let databaseChanged = false;
let updatedPayload: azdata.IConnectionProfile | any = {};
if (node.nodeTypeId === NodeType.Database) {
const database = node.getDatabaseName();
if (database) {
databaseChanged = true;
updatedPayload = Object.assign(updatedPayload, parentNode.payload);
updatedPayload.databaseName = node.getDatabaseName();
}
}
const nodeInfo: azdata.NodeInfo = {
nodePath: nodePath,
nodeType: node.nodeTypeId,
nodeSubType: node.nodeSubType,
nodeStatus: node.nodeStatus,
label: node.label,
isLeaf: node.isAlwaysLeaf,
metadata: node.metadata,
errorMessage: node.errorStateMessage,
iconType: icon,
childProvider: node.childProvider || parentNode.childProvider,
payload: node.payload || (databaseChanged ? updatedPayload : parentNode.payload)
};
let newTreeItem: ITreeItem = { let newTreeItem: ITreeItem = {
parentHandle: node.parent.id, parentHandle: node.parent.id,
handle, handle,
@@ -163,11 +191,12 @@ export class OEShimService extends Disposable implements IOEShimService {
}, },
childProvider: node.childProvider || parentNode.childProvider, childProvider: node.childProvider || parentNode.childProvider,
providerHandle: parentNode.childProvider, providerHandle: parentNode.childProvider,
payload: node.payload || parentNode.payload, payload: node.payload || (databaseChanged ? updatedPayload : parentNode.payload),
contextValue: node.nodeTypeId, contextValue: node.nodeTypeId,
sqlIcon: icon sqlIcon: icon
}; };
this.nodeHandleMap.set(generateNodeMapKey(viewId, newTreeItem), nodePath); this.nodeHandleMap.set(generateNodeMapKey(viewId, newTreeItem), nodePath);
this.nodeInfoMap.set(newTreeItem, nodeInfo);
return newTreeItem; return newTreeItem;
} }
@@ -178,6 +207,13 @@ export class OEShimService extends Disposable implements IOEShimService {
public isNodeConnected(viewId: string, node: ITreeItem): boolean { public isNodeConnected(viewId: string, node: ITreeItem): boolean {
return this.sessionMap.has(generateSessionMapKey(viewId, node)); return this.sessionMap.has(generateSessionMapKey(viewId, node));
} }
public getNodeInfoForTreeItem(treeItem: ITreeItem): azdata.NodeInfo {
if (this.nodeInfoMap.has(treeItem)) {
return this.nodeInfoMap.get(treeItem);
}
return undefined;
}
} }
function generateSessionMapKey(viewId: string, node: ITreeItem): number { function generateSessionMapKey(viewId: string, node: ITreeItem): number {

View File

@@ -483,7 +483,8 @@ export class ExtHostTreeView<T> extends Disposable {
collapsibleState: isUndefinedOrNull(extensionTreeItem.collapsibleState) ? TreeItemCollapsibleState.None : extensionTreeItem.collapsibleState, collapsibleState: isUndefinedOrNull(extensionTreeItem.collapsibleState) ? TreeItemCollapsibleState.None : extensionTreeItem.collapsibleState,
// {{SQL CARBON EDIT}} // {{SQL CARBON EDIT}}
payload: extensionTreeItem.payload, payload: extensionTreeItem.payload,
childProvider: extensionTreeItem.childProvider childProvider: extensionTreeItem.childProvider,
type: extensionTreeItem.type
}; };
return item; return item;