diff --git a/src/sql/workbench/contrib/objectExplorer/test/browser/serverTreeView.test.ts b/src/sql/workbench/contrib/objectExplorer/test/browser/serverTreeView.test.ts index afe4a9c699..7c16182f78 100644 --- a/src/sql/workbench/contrib/objectExplorer/test/browser/serverTreeView.test.ts +++ b/src/sql/workbench/contrib/objectExplorer/test/browser/serverTreeView.test.ts @@ -12,7 +12,7 @@ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/ import * as TypeMoq from 'typemoq'; import { TestCapabilitiesService } from 'sql/platform/capabilities/test/common/testCapabilitiesService'; import { ITree } from 'vs/base/parts/tree/browser/tree'; -import { TestTree } from 'sql/workbench/contrib/objectExplorer/test/browser/treeMock'; +import { TestTree } from 'sql/workbench/test/treeMock'; import { IStorageService } from 'vs/platform/storage/common/storage'; import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices'; diff --git a/src/sql/workbench/contrib/scripting/test/browser/scriptingActions.test.ts b/src/sql/workbench/contrib/scripting/test/browser/scriptingActions.test.ts index 4af371f8fd..0f3a7e9370 100644 --- a/src/sql/workbench/contrib/scripting/test/browser/scriptingActions.test.ts +++ b/src/sql/workbench/contrib/scripting/test/browser/scriptingActions.test.ts @@ -21,7 +21,7 @@ import { ServerTreeView } from 'sql/workbench/contrib/objectExplorer/browser/ser import { createObjectExplorerServiceMock } from 'sql/workbench/services/objectExplorer/test/browser/testObjectExplorerService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ITree } from 'vs/base/parts/tree/browser/tree'; -import { TestTree } from 'sql/workbench/contrib/objectExplorer/test/browser/treeMock'; +import { TestTree } from 'sql/workbench/test/treeMock'; import { TestConnectionManagementService } from 'sql/platform/connection/test/common/testConnectionManagementService'; const connection: azdata.IConnectionProfile = { diff --git a/src/sql/workbench/services/objectExplorer/browser/dragAndDropController.ts b/src/sql/workbench/services/objectExplorer/browser/dragAndDropController.ts index a640982df8..9a31c8ae5a 100644 --- a/src/sql/workbench/services/objectExplorer/browser/dragAndDropController.ts +++ b/src/sql/workbench/services/objectExplorer/browser/dragAndDropController.ts @@ -10,7 +10,8 @@ import { ITree, IDragAndDrop, IDragOverReaction, DRAG_OVER_ACCEPT_BUBBLE_DOWN, D import { DragMouseEvent } from 'vs/base/browser/mouseEvent'; import { TreeUpdateUtils } from 'sql/workbench/services/objectExplorer/browser/treeUpdateUtils'; import { UNSAVED_GROUP_ID } from 'sql/platform/connection/common/constants'; -import { IDragAndDropData } from 'vs/base/browser/dnd'; +import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd'; +import { TreeNode } from 'sql/workbench/services/objectExplorer/common/treeNode'; /** * Implements drag and drop for the server tree @@ -27,24 +28,40 @@ export class ServerTreeDragAndDrop implements IDragAndDrop { * Returns null, otherwise. */ public getDragURI(tree: ITree, element: any): string { - if (element instanceof ConnectionProfile) { - return (element).id; + if (element) { + if (element instanceof ConnectionProfile) { + return (element).id; + } else if (element instanceof ConnectionProfileGroup) { + return (element).id; + } else if (element.nodeTypeId === 'Table' || element.nodeTypeId === 'Column') { + return (element).id; + } + else { + return undefined; + } } - else if (element instanceof ConnectionProfileGroup) { - return (element).id; + else { + return undefined; } - return null; } /** * Returns a label(name) to display when dragging the element. */ public getDragLabel(tree: ITree, elements: any[]): string { - if (elements[0] instanceof ConnectionProfile) { - return (elements[0]).serverName; - } else if (elements[0] instanceof ConnectionProfileGroup) { - return (elements[0]).name; - } else { + if (elements) { + if (elements[0] instanceof ConnectionProfile) { + return (elements[0]).serverName; + } else if (elements[0] instanceof ConnectionProfileGroup) { + return (elements[0]).name; + } else if (elements[0].label) { + return elements[0].label; + } + else { + return undefined; + } + } + else { return undefined; } } @@ -52,8 +69,15 @@ export class ServerTreeDragAndDrop implements IDragAndDrop { /** * Called when the drag operation starts. */ - public onDragStart(tree: ITree, data: IDragAndDropData, originalEvent: DragMouseEvent): void { + public onDragStart(tree: ITree, dragAndDropData: IDragAndDropData, originalEvent: DragMouseEvent): void { TreeUpdateUtils.isInDragAndDrop = true; + const data = dragAndDropData.getData(); + const element = data[0]; + if (element.nodeTypeId === 'Column' || element.nodeTypeId === 'Table') { + const schema = element.metadata.schema; + const name = element.metadata.name; + originalEvent.dataTransfer.setData(DataTransfers.RESOURCES, JSON.stringify([`${element.nodeTypeId}:${element.id}?${schema ? schema + '.' + name : name}`])); + } return; } @@ -78,9 +102,8 @@ export class ServerTreeDragAndDrop implements IDragAndDrop { // to avoid creating a circular structure. canDragOver = source.id !== targetElement.id && !source.isAncestorOf(targetElement); } - } else { - canDragOver = false; + canDragOver = true; } if (canDragOver) { diff --git a/src/sql/workbench/services/objectExplorer/test/browser/dragAndDropController.test.ts b/src/sql/workbench/services/objectExplorer/test/browser/dragAndDropController.test.ts new file mode 100644 index 0000000000..5998b0f44d --- /dev/null +++ b/src/sql/workbench/services/objectExplorer/test/browser/dragAndDropController.test.ts @@ -0,0 +1,111 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile'; +import { ConnectionProfileGroup } from 'sql/platform/connection/common/connectionProfileGroup'; +import { ConnectionManagementService } from 'sql/workbench/services/connection/browser/connectionManagementService'; +import { TestCapabilitiesService } from 'sql/platform/capabilities/test/common/testCapabilitiesService'; +import { IStorageService } from 'vs/platform/storage/common/storage'; +import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices'; +import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; +import { ServerTreeDragAndDrop } from 'sql/workbench/services/objectExplorer/browser/dragAndDropController'; +import { TestTree } from 'sql/workbench/test/treeMock'; +import { ConnectionProviderProperties } from 'sql/platform/capabilities/common/capabilitiesService'; +import { IConnectionProfile } from 'sql/platform/connection/common/interfaces'; +import { mssqlProviderName } from 'sql/platform/connection/common/constants'; +import { TreeNode } from 'sql/workbench/services/objectExplorer/common/treeNode'; + + + +import * as TypeMoq from 'typemoq'; +import * as assert from 'assert'; + + + +suite('SQL Drag And Drop Controller tests', () => { + const testTree = new TestTree(); + let serverTreeDragAndDrop: ServerTreeDragAndDrop; + let msSQLCapabilities: ConnectionProviderProperties; + let capabilitiesService: TestCapabilitiesService; + + let iConnectionProfileId: IConnectionProfile = { + connectionName: 'new name', + serverName: 'new server', + databaseName: 'database', + userName: 'user', + password: 'password', + authenticationType: '', + savePassword: true, + groupFullName: 'g2/g2-2', + groupId: 'group id', + getOptionsKey: undefined!, + matches: undefined!, + providerName: mssqlProviderName, + options: {}, + saveProfile: true, + id: 'd936bb32-422b-49c3-963f-ae9532d63dc5' + }; + + let connectionProfileId = new ConnectionProfile(capabilitiesService, iConnectionProfileId); + let connectionProfileArray = [connectionProfileId]; + let connectionProfileGroupId = new ConnectionProfileGroup('name', undefined, 'd936bb32-422b-49c3-963f-ae9532d63dc5', 'color', 'description'); + let connectionProfileGroupArray = [connectionProfileGroupId]; + let treeNode = new TreeNode('Column', 'label', undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined); + let treeNodeArray = [treeNode]; + + setup(() => { + let instantiationService = new TestInstantiationService(); + instantiationService.stub(IStorageService, new TestStorageService()); + let mockConnectionManagementService = TypeMoq.Mock.ofType(ConnectionManagementService, TypeMoq.MockBehavior.Strict, + undefined, //connection store + undefined, // connectionstatusmanager + undefined, // connectiondialog service + instantiationService, // instantiation service + undefined, // editor service + undefined, // telemetryservice + undefined, // configuration service + new TestCapabilitiesService(), // capabilities service + ); + serverTreeDragAndDrop = new ServerTreeDragAndDrop(mockConnectionManagementService.object); + + capabilitiesService = new TestCapabilitiesService(); + capabilitiesService.capabilities[mssqlProviderName] = { connection: msSQLCapabilities }; + }); + + + test('create new serverTreeDragAndDrop object should create serverTreeDragAndDrop object successfully', async () => { + + assert.equal(serverTreeDragAndDrop !== null || serverTreeDragAndDrop !== undefined, true); + }); + + test('able to get DragURI', async () => { + let uri = serverTreeDragAndDrop.getDragURI(testTree, connectionProfileId); + assert.equal(connectionProfileId.id, uri); + + let uriGroup = serverTreeDragAndDrop.getDragURI(testTree, connectionProfileGroupId); + assert.equal(connectionProfileGroupId.id, uriGroup); + + let uriUndefined = serverTreeDragAndDrop.getDragURI(testTree, null); + assert.equal(null, uriUndefined); + + }); + + test('able to get DragLabel', async () => { + let label = serverTreeDragAndDrop.getDragLabel(testTree, connectionProfileArray); + assert.equal(connectionProfileArray[0].serverName, label); + + let labelGroup = serverTreeDragAndDrop.getDragLabel(testTree, connectionProfileGroupArray); + assert.equal(connectionProfileGroupArray[0].name, labelGroup); + + let labelTreeNode = serverTreeDragAndDrop.getDragLabel(testTree, treeNodeArray); + assert.equal(treeNodeArray[0].label, labelTreeNode); + + let labelUndefined = serverTreeDragAndDrop.getDragLabel(testTree, null); + assert.equal(undefined, labelUndefined); + + }); + + +}); diff --git a/src/sql/workbench/contrib/objectExplorer/test/browser/treeMock.ts b/src/sql/workbench/test/treeMock.ts similarity index 100% rename from src/sql/workbench/contrib/objectExplorer/test/browser/treeMock.ts rename to src/sql/workbench/test/treeMock.ts diff --git a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts index 933ee44d9f..067efc57ee 100644 --- a/src/vs/workbench/browser/parts/editor/editorDropTarget.ts +++ b/src/vs/workbench/browser/parts/editor/editorDropTarget.ts @@ -4,7 +4,8 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/editordroptarget'; -import { LocalSelectionTransfer, DraggedEditorIdentifier, ResourcesDropHandler, DraggedEditorGroupIdentifier, DragAndDropObserver, containsDragType } from 'vs/workbench/browser/dnd'; +// {{SQL CARBON EDIT}} +import { LocalSelectionTransfer, DraggedEditorIdentifier, ResourcesDropHandler, DraggedEditorGroupIdentifier, DragAndDropObserver, containsDragType, extractResources } from 'vs/workbench/browser/dnd'; import { addDisposableListener, EventType, EventHelper, isAncestor, toggleClass, addClass, removeClass } from 'vs/base/browser/dom'; import { IEditorGroupsAccessor, EDITOR_TITLE_HEIGHT, IEditorGroupView, getActiveTextEditorOptions } from 'vs/workbench/browser/parts/editor/editor'; import { EDITOR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme'; @@ -25,6 +26,9 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { assertIsDefined, assertAllDefined } from 'vs/base/common/types'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { localize } from 'vs/nls'; +// {{SQL CARBON EDIT}} +import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; +import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2'; interface IDropOperation { splitDirection?: GroupDirection; @@ -346,6 +350,20 @@ class DropOverlay extends Themable { // Check for URI transfer else { const dropHandler = this.instantiationService.createInstance(ResourcesDropHandler, { allowWorkspaceOpen: true /* open workspace instead of file if dropped */ }); + + // {{SQL CARBON EDIT}} + const untitledOrFileResources = extractResources(event); + if (!untitledOrFileResources.length) { + return; + } + + // {{SQL CARBON EDIT}} + const editor = this.editorService.activeTextEditorControl as ICodeEditor; + if (untitledOrFileResources[0].resource.scheme === 'Column' || untitledOrFileResources[0].resource.scheme === 'Table') { + SnippetController2.get(editor).insert(`[${untitledOrFileResources[0].resource.query}]`); + return; + } + dropHandler.handleDrop(event, () => ensureTargetGroup(), targetGroup => { if (targetGroup) { targetGroup.focus();