mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Column/Table Drag & Drop (#10702)
* able to drag objects from left pane * changed scheme from file * base functionality working * extended functionality to tables * added string literals and formatting * cleanup * cleanup * added table/column parsing * removed bad logic * updated to use metadata * cleanup and added sql carbon edit tags * moved changes from vs into sql code base * refactoring drag and drop * cleanup * cleanup * cleanup * added unit tests * pr changes * moved treeMock file * fixed small bug
This commit is contained in:
@@ -12,7 +12,7 @@ import { TestInstantiationService } from 'vs/platform/instantiation/test/common/
|
|||||||
import * as TypeMoq from 'typemoq';
|
import * as TypeMoq from 'typemoq';
|
||||||
import { TestCapabilitiesService } from 'sql/platform/capabilities/test/common/testCapabilitiesService';
|
import { TestCapabilitiesService } from 'sql/platform/capabilities/test/common/testCapabilitiesService';
|
||||||
import { ITree } from 'vs/base/parts/tree/browser/tree';
|
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 { IStorageService } from 'vs/platform/storage/common/storage';
|
||||||
import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
|
import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import { ServerTreeView } from 'sql/workbench/contrib/objectExplorer/browser/ser
|
|||||||
import { createObjectExplorerServiceMock } from 'sql/workbench/services/objectExplorer/test/browser/testObjectExplorerService';
|
import { createObjectExplorerServiceMock } from 'sql/workbench/services/objectExplorer/test/browser/testObjectExplorerService';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { ITree } from 'vs/base/parts/tree/browser/tree';
|
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';
|
import { TestConnectionManagementService } from 'sql/platform/connection/test/common/testConnectionManagementService';
|
||||||
|
|
||||||
const connection: azdata.IConnectionProfile = {
|
const connection: azdata.IConnectionProfile = {
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ import { ITree, IDragAndDrop, IDragOverReaction, DRAG_OVER_ACCEPT_BUBBLE_DOWN, D
|
|||||||
import { DragMouseEvent } from 'vs/base/browser/mouseEvent';
|
import { DragMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||||
import { TreeUpdateUtils } from 'sql/workbench/services/objectExplorer/browser/treeUpdateUtils';
|
import { TreeUpdateUtils } from 'sql/workbench/services/objectExplorer/browser/treeUpdateUtils';
|
||||||
import { UNSAVED_GROUP_ID } from 'sql/platform/connection/common/constants';
|
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
|
* Implements drag and drop for the server tree
|
||||||
@@ -27,24 +28,40 @@ export class ServerTreeDragAndDrop implements IDragAndDrop {
|
|||||||
* Returns null, otherwise.
|
* Returns null, otherwise.
|
||||||
*/
|
*/
|
||||||
public getDragURI(tree: ITree, element: any): string {
|
public getDragURI(tree: ITree, element: any): string {
|
||||||
if (element instanceof ConnectionProfile) {
|
if (element) {
|
||||||
return (<ConnectionProfile>element).id;
|
if (element instanceof ConnectionProfile) {
|
||||||
|
return (<ConnectionProfile>element).id;
|
||||||
|
} else if (element instanceof ConnectionProfileGroup) {
|
||||||
|
return (<ConnectionProfileGroup>element).id;
|
||||||
|
} else if (element.nodeTypeId === 'Table' || element.nodeTypeId === 'Column') {
|
||||||
|
return (<TreeNode>element).id;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (element instanceof ConnectionProfileGroup) {
|
else {
|
||||||
return (<ConnectionProfileGroup>element).id;
|
return undefined;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a label(name) to display when dragging the element.
|
* Returns a label(name) to display when dragging the element.
|
||||||
*/
|
*/
|
||||||
public getDragLabel(tree: ITree, elements: any[]): string {
|
public getDragLabel(tree: ITree, elements: any[]): string {
|
||||||
if (elements[0] instanceof ConnectionProfile) {
|
if (elements) {
|
||||||
return (<ConnectionProfile>elements[0]).serverName;
|
if (elements[0] instanceof ConnectionProfile) {
|
||||||
} else if (elements[0] instanceof ConnectionProfileGroup) {
|
return (<ConnectionProfile>elements[0]).serverName;
|
||||||
return (<ConnectionProfileGroup>elements[0]).name;
|
} else if (elements[0] instanceof ConnectionProfileGroup) {
|
||||||
} else {
|
return (<ConnectionProfileGroup>elements[0]).name;
|
||||||
|
} else if (elements[0].label) {
|
||||||
|
return elements[0].label;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,8 +69,15 @@ export class ServerTreeDragAndDrop implements IDragAndDrop {
|
|||||||
/**
|
/**
|
||||||
* Called when the drag operation starts.
|
* 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;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,9 +102,8 @@ export class ServerTreeDragAndDrop implements IDragAndDrop {
|
|||||||
// to avoid creating a circular structure.
|
// to avoid creating a circular structure.
|
||||||
canDragOver = source.id !== targetElement.id && !source.isAncestorOf(targetElement);
|
canDragOver = source.id !== targetElement.id && !source.isAncestorOf(targetElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
canDragOver = false;
|
canDragOver = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canDragOver) {
|
if (canDragOver) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
@@ -4,7 +4,8 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import 'vs/css!./media/editordroptarget';
|
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 { 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 { IEditorGroupsAccessor, EDITOR_TITLE_HEIGHT, IEditorGroupView, getActiveTextEditorOptions } from 'vs/workbench/browser/parts/editor/editor';
|
||||||
import { EDITOR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
|
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 { assertIsDefined, assertAllDefined } from 'vs/base/common/types';
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
import { localize } from 'vs/nls';
|
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 {
|
interface IDropOperation {
|
||||||
splitDirection?: GroupDirection;
|
splitDirection?: GroupDirection;
|
||||||
@@ -346,6 +350,20 @@ class DropOverlay extends Themable {
|
|||||||
// Check for URI transfer
|
// Check for URI transfer
|
||||||
else {
|
else {
|
||||||
const dropHandler = this.instantiationService.createInstance(ResourcesDropHandler, { allowWorkspaceOpen: true /* open workspace instead of file if dropped */ });
|
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 => {
|
dropHandler.handleDrop(event, () => ensureTargetGroup(), targetGroup => {
|
||||||
if (targetGroup) {
|
if (targetGroup) {
|
||||||
targetGroup.focus();
|
targetGroup.focus();
|
||||||
|
|||||||
Reference in New Issue
Block a user