mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
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:
@@ -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
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
6
src/sql/azdata.proposed.d.ts
vendored
6
src/sql/azdata.proposed.d.ts
vendored
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ export class DataExplorerViewlet extends ViewContainerViewlet {
|
|||||||
actions.push(...group[1]);
|
actions.push(...group[1]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
menu.dispose();
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
159
src/sql/workbench/parts/dataExplorer/common/mssqlNodeContext.ts
Normal file
159
src/sql/workbench/parts/dataExplorer/common/mssqlNodeContext.ts
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
||||||
});
|
});
|
||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user