mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Add Create Proj from DB to VS Code context menus (#16584)
* Add Create Proj from DB to VS Code context menus * Fix error * add comment * use constant
This commit is contained in:
@@ -351,6 +351,11 @@
|
|||||||
"command": "sqlDatabaseProjects.openContainingFolder",
|
"command": "sqlDatabaseProjects.openContainingFolder",
|
||||||
"when": "view == dataworkspace.views.main && viewItem == databaseProject.itemType.project",
|
"when": "view == dataworkspace.views.main && viewItem == databaseProject.itemType.project",
|
||||||
"group": "9_dbProjectsLast@8"
|
"group": "9_dbProjectsLast@8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "sqlDatabaseProjects.createProjectFromDatabase",
|
||||||
|
"when": "!azdataAvailable && view == objectExplorer && viewItem =~ /^(disconnectedServer|Server|Database)$/",
|
||||||
|
"group": "sqldbproj@1"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"objectExplorer/item/context": [
|
"objectExplorer/item/context": [
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import type * as azdataType from 'azdata';
|
import type * as azdataType from 'azdata';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
|
import * as vscodeMssql from 'vscode-mssql';
|
||||||
import * as templates from '../templates/templates';
|
import * as templates from '../templates/templates';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@ export default class MainController implements vscode.Disposable {
|
|||||||
vscode.commands.registerCommand('sqlDatabaseProjects.build', async (node: WorkspaceTreeItem) => { await this.projectsController.buildProject(node); });
|
vscode.commands.registerCommand('sqlDatabaseProjects.build', async (node: WorkspaceTreeItem) => { await this.projectsController.buildProject(node); });
|
||||||
vscode.commands.registerCommand('sqlDatabaseProjects.publish', async (node: WorkspaceTreeItem) => { this.projectsController.publishProject(node); });
|
vscode.commands.registerCommand('sqlDatabaseProjects.publish', async (node: WorkspaceTreeItem) => { this.projectsController.publishProject(node); });
|
||||||
vscode.commands.registerCommand('sqlDatabaseProjects.schemaCompare', async (node: WorkspaceTreeItem) => { await this.projectsController.schemaCompare(node); });
|
vscode.commands.registerCommand('sqlDatabaseProjects.schemaCompare', async (node: WorkspaceTreeItem) => { await this.projectsController.schemaCompare(node); });
|
||||||
vscode.commands.registerCommand('sqlDatabaseProjects.createProjectFromDatabase', async (profile: azdataType.IConnectionProfile) => { await this.projectsController.createProjectFromDatabase(profile); });
|
vscode.commands.registerCommand('sqlDatabaseProjects.createProjectFromDatabase', async (context: azdataType.IConnectionProfile | vscodeMssql.ITreeNodeInfo | undefined) => { await this.projectsController.createProjectFromDatabase(context); });
|
||||||
|
|
||||||
vscode.commands.registerCommand('sqlDatabaseProjects.newScript', async (node: WorkspaceTreeItem) => { await this.projectsController.addItemPromptFromNode(node, templates.script); });
|
vscode.commands.registerCommand('sqlDatabaseProjects.newScript', async (node: WorkspaceTreeItem) => { await this.projectsController.addItemPromptFromNode(node, templates.script); });
|
||||||
vscode.commands.registerCommand('sqlDatabaseProjects.newPreDeploymentScript', async (node: WorkspaceTreeItem) => { await this.projectsController.addItemPromptFromNode(node, templates.preDeployScript); });
|
vscode.commands.registerCommand('sqlDatabaseProjects.newPreDeploymentScript', async (node: WorkspaceTreeItem) => { await this.projectsController.addItemPromptFromNode(node, templates.preDeployScript); });
|
||||||
|
|||||||
@@ -863,10 +863,10 @@ export class ProjectsController {
|
|||||||
* Creates a new SQL database project from the existing database,
|
* Creates a new SQL database project from the existing database,
|
||||||
* prompting the user for a name, file path location and extract target
|
* prompting the user for a name, file path location and extract target
|
||||||
*/
|
*/
|
||||||
public async createProjectFromDatabase(context: azdataType.IConnectionProfile | any): Promise<CreateProjectFromDatabaseDialog | undefined> {
|
public async createProjectFromDatabase(context: azdataType.IConnectionProfile | mssqlVscode.ITreeNodeInfo | undefined): Promise<CreateProjectFromDatabaseDialog | undefined> {
|
||||||
const profile = this.getConnectionProfileFromContext(context);
|
const profile = this.getConnectionProfileFromContext(context);
|
||||||
if (utils.getAzdataApi()) {
|
if (utils.getAzdataApi()) {
|
||||||
let createProjectFromDatabaseDialog = this.getCreateProjectFromDatabaseDialog(profile);
|
let createProjectFromDatabaseDialog = this.getCreateProjectFromDatabaseDialog(profile as azdataType.IConnectionProfile);
|
||||||
|
|
||||||
createProjectFromDatabaseDialog.createProjectFromDatabaseCallback = async (model) => await this.createProjectFromDatabaseCallback(model);
|
createProjectFromDatabaseDialog.createProjectFromDatabaseCallback = async (model) => await this.createProjectFromDatabaseCallback(model);
|
||||||
|
|
||||||
@@ -874,7 +874,15 @@ export class ProjectsController {
|
|||||||
|
|
||||||
return createProjectFromDatabaseDialog;
|
return createProjectFromDatabaseDialog;
|
||||||
} else {
|
} else {
|
||||||
const model = await createNewProjectFromDatabaseWithQuickpick();
|
if (context) {
|
||||||
|
// The profile we get from VS Code is for the overall server connection and isn't updated based on the database node
|
||||||
|
// the command was launched from like it is in ADS. So get the actual database name from the MSSQL extension and
|
||||||
|
// update the connection info here.
|
||||||
|
const treeNodeContext = context as mssqlVscode.ITreeNodeInfo;
|
||||||
|
const databaseName = (await utils.getVscodeMssqlApi()).getDatabaseNameFromTreeNode(treeNodeContext);
|
||||||
|
(profile as mssqlVscode.IConnectionInfo).database = databaseName;
|
||||||
|
}
|
||||||
|
const model = await createNewProjectFromDatabaseWithQuickpick(profile as mssqlVscode.IConnectionInfo);
|
||||||
if (model) {
|
if (model) {
|
||||||
await this.createProjectFromDatabaseCallback(model);
|
await this.createProjectFromDatabaseCallback(model);
|
||||||
}
|
}
|
||||||
@@ -925,14 +933,14 @@ export class ProjectsController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getConnectionProfileFromContext(context: azdataType.IConnectionProfile | any): azdataType.IConnectionProfile | undefined {
|
private getConnectionProfileFromContext(context: azdataType.IConnectionProfile | mssqlVscode.ITreeNodeInfo | undefined): azdataType.IConnectionProfile | mssqlVscode.IConnectionInfo | undefined {
|
||||||
if (!context) {
|
if (!context) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// depending on where import new project is launched from, the connection profile could be passed as just
|
// depending on where import new project is launched from, the connection profile could be passed as just
|
||||||
// the profile or it could be wrapped in another object
|
// the profile or it could be wrapped in another object
|
||||||
return (<any>context).connectionProfile ? (<any>context).connectionProfile : context;
|
return (<any>context)?.connectionProfile ?? (context as mssqlVscode.ITreeNodeInfo).connectionInfo ?? context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createProjectFromDatabaseApiCall(model: ImportDataModel): Promise<void> {
|
public async createProjectFromDatabaseApiCall(model: ImportDataModel): Promise<void> {
|
||||||
|
|||||||
@@ -14,29 +14,46 @@ import { mapExtractTargetEnum } from './createProjectFromDatabaseDialog';
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Create flow for a New Project using only VS Code-native APIs such as QuickPick
|
* Create flow for a New Project using only VS Code-native APIs such as QuickPick
|
||||||
|
* @param connectionInfo Optional connection info to use instead of prompting the user for a connection
|
||||||
*/
|
*/
|
||||||
export async function createNewProjectFromDatabaseWithQuickpick(): Promise<ImportDataModel | undefined> {
|
export async function createNewProjectFromDatabaseWithQuickpick(connectionInfo?: IConnectionInfo): Promise<ImportDataModel | undefined> {
|
||||||
|
|
||||||
|
const vscodeMssqlApi = await getVscodeMssqlApi();
|
||||||
|
|
||||||
// 1. Select connection
|
// 1. Select connection
|
||||||
const vscodeMssqlApi = await getVscodeMssqlApi();
|
// Use passed in profile if we have one - otherwise prompt user to select one
|
||||||
let connectionProfile: IConnectionInfo | undefined = undefined;
|
let connectionProfile: IConnectionInfo | undefined = connectionInfo ?? await vscodeMssqlApi.promptForConnection(true);
|
||||||
let connectionUri: string = '';
|
|
||||||
let dbs: string[] | undefined = undefined;
|
|
||||||
while (!dbs) {
|
|
||||||
connectionProfile = await vscodeMssqlApi.promptForConnection(true);
|
|
||||||
if (!connectionProfile) {
|
if (!connectionProfile) {
|
||||||
// User cancelled
|
// User cancelled
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
let connectionUri: string = '';
|
||||||
|
let dbs: string[] | undefined = undefined;
|
||||||
|
while (!dbs) {
|
||||||
// Get the list of databases now to validate that the connection is valid and re-prompt them if it isn't
|
// Get the list of databases now to validate that the connection is valid and re-prompt them if it isn't
|
||||||
try {
|
try {
|
||||||
connectionUri = await vscodeMssqlApi.connect(connectionProfile);
|
connectionUri = await vscodeMssqlApi.connect(connectionProfile);
|
||||||
dbs = (await vscodeMssqlApi.listDatabases(connectionUri))
|
dbs = (await vscodeMssqlApi.listDatabases(connectionUri))
|
||||||
.filter(db => !constants.systemDbs.includes(db)); // Filter out system dbs
|
.filter(db => !constants.systemDbs.includes(db)); // Filter out system dbs
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// no-op, the mssql extension handles showing the error to the user. We'll just go
|
// The mssql extension handles showing the error to the user. Prompt the user
|
||||||
// back and prompt the user for a connection again
|
// for a new connection and then go and try getting the DBs again
|
||||||
|
connectionProfile = await vscodeMssqlApi.promptForConnection(true);
|
||||||
|
if (!connectionProfile) {
|
||||||
|
// User cancelled
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the database for the given connection up to the top
|
||||||
|
if (connectionProfile.database && connectionProfile.database !== constants.master) {
|
||||||
|
const index = dbs.indexOf(connectionProfile.database);
|
||||||
|
if (index >= 0) {
|
||||||
|
dbs.splice(index, 1);
|
||||||
|
}
|
||||||
|
dbs.unshift(connectionProfile.database);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Select database
|
// 2. Select database
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
declare module 'vscode-mssql' {
|
declare module 'vscode-mssql' {
|
||||||
|
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Covers defining what the vscode-mssql extension exports to other extensions
|
* Covers defining what the vscode-mssql extension exports to other extensions
|
||||||
*
|
*
|
||||||
@@ -51,6 +54,15 @@ declare module 'vscode-mssql' {
|
|||||||
* @returns The list of database names
|
* @returns The list of database names
|
||||||
*/
|
*/
|
||||||
listDatabases(connectionUri: string): Promise<string[]>;
|
listDatabases(connectionUri: string): Promise<string[]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the database name for the node - which is the database name of the connection for a server node, the database name
|
||||||
|
* for nodes at or under a database node or a default value if it's neither of those.
|
||||||
|
* @param node The node to get the database name of
|
||||||
|
* @returns The database name
|
||||||
|
*/
|
||||||
|
getDatabaseNameFromTreeNode(node: ITreeNodeInfo): string;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -490,4 +502,29 @@ declare module 'vscode-mssql' {
|
|||||||
defaultDeploymentOptions: DeploymentOptions;
|
defaultDeploymentOptions: DeploymentOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ITreeNodeInfo extends vscode.TreeItem {
|
||||||
|
readonly connectionInfo: IConnectionInfo;
|
||||||
|
nodeType: string;
|
||||||
|
metadata: ObjectMetadata;
|
||||||
|
parentNode: ITreeNodeInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const enum MetadataType {
|
||||||
|
Table = 0,
|
||||||
|
View = 1,
|
||||||
|
SProc = 2,
|
||||||
|
Function = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ObjectMetadata {
|
||||||
|
metadataType: MetadataType;
|
||||||
|
|
||||||
|
metadataTypeName: string;
|
||||||
|
|
||||||
|
urn: string;
|
||||||
|
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
schema: string;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user