Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRAFT PR - Edit Data #18533

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ async function generateReactWebviewsBundle() {
'objectExplorerFilter': 'src/reactviews/pages/ObjectExplorerFilter/index.tsx',
'queryResult': 'src/reactviews/pages/QueryResult/index.tsx',
'userSurvey': 'src/reactviews/pages/UserSurvey/index.tsx',
"editData": "src/reactviews/pages/EditData/index.tsx",
},
bundle: true,
outdir: 'out/src/reactviews/assets',
Expand Down
1 change: 1 addition & 0 deletions localization/l10n/bundle.l10n.json
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@
},
"Object Explorer Filter (Preview)": "Object Explorer Filter (Preview)",
"{0} (filtered)": "{0} (filtered)",
"Edit Data (Preview)": "Edit Data (Preview)",
"{0} (Preview)/{0} is the file name": {
"message": "{0} (Preview)",
"comment": [
Expand Down
6 changes: 6 additions & 0 deletions localization/xliff/vscode-mssql.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,9 @@
<trans-unit id="++CODE++464c4ffd019e1e9691dcf0537c797353ef2b1c1d4833d3d463e5b74ae4547344">
<source xml:lang="en">Edit</source>
</trans-unit>
<trans-unit id="++CODE++7b51f205866ab54cdf42089699d4b8d617c5a18ac8d82ee5bdfbe10533028f99">
<source xml:lang="en">Edit Data (Preview)</source>
</trans-unit>
<trans-unit id="++CODE++1e71b5c8f3211f1f01b27341d3ddc6a2ad651800264b495c12b50867f998662c">
<source xml:lang="en">Enable &apos;Trust Server Certificate&apos;</source>
</trans-unit>
Expand Down Expand Up @@ -1605,6 +1608,9 @@
<trans-unit id="mssql.editConnection">
<source xml:lang="en">Edit Connection (Preview)</source>
</trans-unit>
<trans-unit id="mssql.editData">
<source xml:lang="en">Edit Data</source>
</trans-unit>
<trans-unit id="mssql.editTable">
<source xml:lang="en">Edit Table</source>
</trans-unit>
Expand Down
14 changes: 14 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,11 @@
"when": "view == objectExplorer && viewItem =~ /\\btype=(AggregateFunction|PartitionFunction|ScalarValuedFunction|StoredProcedure|TableValuedFunction|View)\\b/",
"group": "MS_SQL@4"
},
{
"command": "mssql.editData",
"when": "view == objectExplorer && viewItem =~ /\\btype=(Table)\\b/",
"group": "MS_SQL@6"
},
{
"command": "mssql.newTable",
"when": "view == objectExplorer && viewItem =~ /\\bsubType=(Tables)\\b/ && config.mssql.enableRichExperiences",
Expand Down Expand Up @@ -531,6 +536,10 @@
"command": "mssql.scriptSelect",
"when": "view == objectExplorer && viewItem =~ /\\btype=(Table|View)\\b/"
},
{
"command": "mssql.editData",
"when": "view == objectExplorer && viewItem =~ /\\btype=(Table)\\b/"
},
{
"command": "mssql.scriptCreate",
"when": "view == objectExplorer && viewItem =~ /\\btype=(Table|View|AggregateFunction|PartitionFunction|ScalarValuedFunction|Schema|StoredProcedure|TableValuedFunction|User|UserDefinedTableType|Trigger|DatabaseTrigger|Index|Key|User|DatabaseRole|ApplicationRole)\\b/"
Expand Down Expand Up @@ -772,6 +781,11 @@
"title": "%mssql.scriptSelect%",
"category": "MS SQL"
},
{
"command": "mssql.editData",
"title": "%mssql.editData%",
"category": "MS SQL"
},
{
"command": "mssql.scriptCreate",
"title": "%mssql.scriptCreate%",
Expand Down
1 change: 1 addition & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"mssql.addObjectExplorer":"Add Connection",
"mssql.addObjectExplorerPreview":"Add Connection (Preview)",
"mssql.scriptSelect":"Select Top 1000",
"mssql.editData": "Edit Data",
"mssql.scriptCreate":"Script as Create",
"mssql.scriptDelete":"Script as Drop",
"mssql.scriptExecute":"Script as Execute",
Expand Down
1 change: 1 addition & 0 deletions src/constants/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export const cmdScriptCreate = "mssql.scriptCreate";
export const cmdScriptDelete = "mssql.scriptDelete";
export const cmdScriptExecute = "mssql.scriptExecute";
export const cmdScriptAlter = "mssql.scriptAlter";
export const cmdEditData = "mssql.editData";
export const cmdToggleSqlCmd = "mssql.toggleSqlCmd";
export const cmdCopyObjectName = "mssql.copyObjectName";
export const cmdFilterNode = "mssql.filterNode";
Expand Down
28 changes: 28 additions & 0 deletions src/controllers/mainController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ import { getErrorMessage, isIConnectionInfo } from "../utils/utils";
import { getStandardNPSQuestions, UserSurvey } from "../nps/userSurvey";
import { ExecutionPlanOptions } from "../models/contracts/queryExecute";
import { ObjectExplorerDragAndDropController } from "../objectExplorer/objectExplorerDragAndDropController";
import { EditDataWebViewController } from "../editData/editDataWebViewController";
import { EditDataService } from "../services/editDataService";

/**
* The main controller class that initializes the extension
Expand Down Expand Up @@ -97,6 +99,7 @@ export default class MainController implements vscode.Disposable {
public configuration: vscode.WorkspaceConfiguration;
public objectExplorerTree: vscode.TreeView<TreeNodeInfo>;
public executionPlanService: ExecutionPlanService;
public editDataService: EditDataService;

/**
* The main controller constructor
Expand Down Expand Up @@ -355,6 +358,9 @@ export default class MainController implements vscode.Disposable {
this.executionPlanService = new ExecutionPlanService(
SqlToolsServerClient.instance,
);
this.editDataService = new EditDataService(
SqlToolsServerClient.instance,
);

this._queryResultWebviewController.setExecutionPlanService(
this.executionPlanService,
Expand Down Expand Up @@ -1025,6 +1031,13 @@ export default class MainController implements vscode.Disposable {
),
);

this._context.subscriptions.push(
vscode.commands.registerCommand(
Constants.cmdEditData,
async (node: TreeNodeInfo) => await this.onEditData(node),
),
);

// Script as Create
this._context.subscriptions.push(
vscode.commands.registerCommand(
Expand Down Expand Up @@ -1935,6 +1948,21 @@ export default class MainController implements vscode.Disposable {
return false;
}

public async onEditData(node?: TreeNodeInfo): Promise<void> {
if (this.canRunCommand()) {
if (node) {
const editDataWebView = new EditDataWebViewController(
this._context,
node,
this._connectionMgr,
this.editDataService,
);

editDataWebView.revealToForeground();
}
}
}

/**
* Check if the extension launched file exists.
* This is to detect when we are running in a clean install scenario.
Expand Down
144 changes: 144 additions & 0 deletions src/editData/editDataWebViewController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as vscode from "vscode";
import * as ed from "../sharedInterfaces/editData";

import { ReactWebviewPanelController } from "../controllers/reactWebviewPanelController";
import {
EditDataReducers,
EditDataWebViewState,
} from "../sharedInterfaces/editData";
import ConnectionManager from "../controllers/connectionManager";
import { TreeNodeInfo } from "../objectExplorer/treeNodeInfo";
import { ObjectExplorerUtils } from "../objectExplorer/objectExplorerUtils";
import { Deferred } from "../protocol";
import { EditDataService } from "../services/editDataService";
import { EditSessionReadyNotification } from "../models/contracts/editData";
import { NotificationHandler } from "vscode-languageclient";

export class EditDataWebViewController extends ReactWebviewPanelController<
EditDataWebViewState,
EditDataReducers
> {
constructor(
context: vscode.ExtensionContext,
private node: TreeNodeInfo,
private readonly connectionManager: ConnectionManager,
private readonly editDataService: EditDataService,
data?: EditDataWebViewState,
) {
super(
context,
"editData",
data ?? {
ownerUri: "",
objectName: "",
objectType: "",
queryString: "",
schemaName: "",
subsetResult: { rowCount: 0, subset: [] },
},
{
title: vscode.l10n.t("Edit Data (Preview)"),
viewColumn: vscode.ViewColumn.Active,
iconPath: {
dark: vscode.Uri.joinPath(
context.extensionUri,
"media",
"tableDesignerEditor_dark.svg", // lewissanchez TODO - update icon for edit data
),
light: vscode.Uri.joinPath(
context.extensionUri,
"media",
"tableDesignerEditor_light.svg", // lewissanchez TODO - update icon for edit data
),
},
},
);

void this.initialize();
}

private async initialize() {
this.editDataService.sqlToolsClient.onNotification(
EditSessionReadyNotification.type,
this.handleEditSessionReadyNotification(),
);

const schemaName = this.node.metadata.schema;
const objectName = this.node.metadata.name;
const nodeUri = schemaName
? `untitled:${schemaName}.${objectName}`
: `untitled:${objectName}`;
const objectType = this.node.metadata.metadataTypeName.toUpperCase();
const limitResults = 200; // lewissanchez TODO: Make this configurable

let connectionCreds = Object.assign({}, this.node.connectionInfo);
const databaseName = ObjectExplorerUtils.getDatabaseName(this.node);

// if not connected or different database then make a new connection
if (
!this.connectionManager.isConnected(nodeUri) ||
connectionCreds.database !== databaseName
) {
connectionCreds.database = databaseName;
if (!this.connectionManager.isConnecting(nodeUri)) {
const promise = new Deferred<boolean>();
await this.connectionManager.connect(
nodeUri,
connectionCreds,
promise,
);
await promise;
}
}

await this.editDataService.Initialize(
nodeUri,
objectName,
schemaName,
objectType,
undefined,
limitResults,
);

this.registerRpcHandlers();
}

private handleEditSessionReadyNotification(): NotificationHandler<ed.EditSessionReadyParams> {
const self = this;
return (result: ed.EditSessionReadyParams): void => {
if (result.success) {
self.updateState({
...self.state,
ownerUri: result.ownerUri,
});

void self.loadResultSet();
}
};
}

private async loadResultSet() {
const subsetResult = await this.editDataService.subset(
this.state.ownerUri,
0,
200,
);

const result: ed.EditSubsetResult = {
rowCount: subsetResult.rowCount,
subset: [...subsetResult.subset],
};

this.updateState({
...this.state,
subsetResult: result,
});
}

private registerRpcHandlers() {}
}
104 changes: 104 additions & 0 deletions src/models/contracts/editData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as ed from "../../sharedInterfaces/editData";
import { NotificationType, RequestType } from "vscode-languageclient";

// edit/createRow -----------------------------------------------------------------------------
export namespace EditCreateRowRequest {
export const type = new RequestType<
ed.EditCreateRowParams,
ed.EditCreateRowResult,
void,
void
>("edit/createRow");
}

// edit/deleteRow -----------------------------------------------------------------------------
export namespace EditDeleteRowRequest {
export const type = new RequestType<
ed.EditDeleteRowParams,
ed.EditDeleteRowResult,
void,
void
>("edit/deleteRow");
}

// edit/dispose -------------------------------------------------------------------------------
export namespace EditDisposeRequest {
export const type = new RequestType<
ed.EditDisposeParams,
ed.EditDisposeResult,
void,
void
>("edit/dispose");
}

// edit/initialize ----------------------------------------------------------------------------
export namespace EditInitializeRequest {
export const type = new RequestType<
ed.EditInitializeParams,
ed.EditInitializeResult,
void,
void
>("edit/initialize");
}

// edit/revertCell --------------------------------------------------------------------------------
export namespace EditRevertCellRequest {
export const type = new RequestType<
ed.EditRevertCellParams,
ed.EditRevertCellResult,
void,
void
>("edit/revertCell");
}

// edit/revertRow -----------------------------------------------------------------------------
export namespace EditRevertRowRequest {
export const type = new RequestType<
ed.EditRevertRowParams,
ed.EditRevertRowResult,
void,
void
>("edit/revertRow");
}

// edit/subset ------------------------------------------------------------------------------------
export namespace EditSubsetRequest {
export const type = new RequestType<
ed.EditSubsetParams,
ed.EditSubsetResult,
void,
void
>("edit/subset");
}

// edit/updateCell ----------------------------------------------------------------------------
export namespace EditUpdateCellRequest {
export const type = new RequestType<
ed.EditUpdateCellParams,
ed.EditUpdateCellResult,
void,
void
>("edit/updateCell");
}

// edit/commit --------------------------------------------------------------------------------
export namespace EditCommitRequest {
export const type = new RequestType<
ed.EditCommitParams,
ed.EditCommitResult,
void,
void
>("edit/commit");
}

// edit/sessionReady Event --------------------------------------------------------------------
export namespace EditSessionReadyNotification {
export const type = new NotificationType<ed.EditSessionReadyParams, void>(
"edit/sessionReady",
);
}
Loading
Loading