-
Notifications
You must be signed in to change notification settings - Fork 61
fix: delete multiple tables from lib pane #1705
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ import { | |
| Uri, | ||
| commands, | ||
| env, | ||
| l10n, | ||
| window, | ||
| workspace, | ||
| } from "vscode"; | ||
|
|
@@ -24,6 +25,7 @@ import LibraryAdapterFactory from "./LibraryAdapterFactory"; | |
| import LibraryDataProvider from "./LibraryDataProvider"; | ||
| import LibraryModel from "./LibraryModel"; | ||
| import PaginatedResultSet from "./PaginatedResultSet"; | ||
| import { Messages } from "./const"; | ||
| import { LibraryAdapter, LibraryItem, TableData } from "./types"; | ||
|
|
||
| class LibraryNavigator implements SubscriptionProvider { | ||
|
|
@@ -66,8 +68,35 @@ class LibraryNavigator implements SubscriptionProvider { | |
| ), | ||
| commands.registerCommand("SAS.refreshLibraries", () => this.refresh()), | ||
| commands.registerCommand("SAS.deleteTable", async (item: LibraryItem) => { | ||
| const selectedItems = this.treeViewSelections(item); | ||
|
|
||
| if (selectedItems.length === 0) { | ||
| return; | ||
| } | ||
|
|
||
| try { | ||
| await this.libraryDataProvider.deleteTable(item); | ||
| if (selectedItems.length === 1) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of having two different paths here, how about we:
|
||
| await this.libraryDataProvider.deleteTable(selectedItems[0]); | ||
| } else { | ||
| const tableNames = selectedItems | ||
| .map((table) => `${table.library}.${table.name}`) | ||
| .join(", "); | ||
|
|
||
| const result = await window.showWarningMessage( | ||
| l10n.t(Messages.TablesDeletionWarning, { | ||
| tableNames: tableNames, | ||
| count: selectedItems.length, | ||
| }), | ||
| { modal: true }, | ||
| "Delete", | ||
| ); | ||
|
|
||
| if (result !== "Delete") { | ||
| return; | ||
| } | ||
|
|
||
| await this.libraryDataProvider.deleteTables(selectedItems); | ||
| } | ||
| } catch (error) { | ||
| window.showErrorMessage(error.message); | ||
| } | ||
|
|
@@ -128,6 +157,15 @@ class LibraryNavigator implements SubscriptionProvider { | |
| this.libraryDataProvider.useAdapter(this.libraryAdapterForConnectionType()); | ||
| } | ||
|
|
||
| private treeViewSelections(item: LibraryItem): LibraryItem[] { | ||
| const items = | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see this was copy/pasted from Right now, I think there's a bug with this (here and in content navigator). Putting this functionality in one place will make it easier to resolve. In case you're curious, or want to tackle this in your PR (definitely out of scope), here's the bug:
In this scenario, I would expect Like I said, this also happens with sas content and server files, so feel free to not resolve it in this PR and I can file a bug. |
||
| this.libraryDataProvider.treeView.selection.length > 1 || !item | ||
| ? this.libraryDataProvider.treeView.selection | ||
| : [item]; | ||
|
|
||
| return items.filter(Boolean); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there ever a case where its would be |
||
| } | ||
|
|
||
| private async displayTableProperties( | ||
| item: LibraryItem, | ||
| showPropertiesTab: boolean = false, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -270,4 +270,87 @@ describe("LibraryDataProvider", async function () { | |
|
|
||
| deleteTableStub.restore(); | ||
| }); | ||
|
|
||
| it("deleteTables - deletes multiple tables successfully", async () => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🙌 |
||
| const items: LibraryItem[] = [ | ||
| { | ||
| uid: "lib.table1", | ||
| id: "table1", | ||
| name: "table1", | ||
| type: "table", | ||
| readOnly: false, | ||
| library: "lib", | ||
| }, | ||
| { | ||
| uid: "lib.table2", | ||
| id: "table2", | ||
| name: "table2", | ||
| type: "table", | ||
| readOnly: false, | ||
| library: "lib", | ||
| }, | ||
| ]; | ||
|
|
||
| const api = dataAccessApi(); | ||
| const deleteTableStub = sinon.stub(api, "deleteTable"); | ||
|
|
||
| const provider = libraryDataProvider(api); | ||
| await provider.deleteTables(items); | ||
|
|
||
| expect(deleteTableStub.callCount).to.equal(2); | ||
| deleteTableStub.restore(); | ||
| }); | ||
|
|
||
| it("deleteTables - reports failures when some tables fail to delete", async () => { | ||
| const items: LibraryItem[] = [ | ||
| { | ||
| uid: "lib.table1", | ||
| id: "table1", | ||
| name: "table1", | ||
| type: "table", | ||
| readOnly: false, | ||
| library: "lib", | ||
| }, | ||
| { | ||
| uid: "lib.table2", | ||
| id: "table2", | ||
| name: "table2", | ||
| type: "table", | ||
| readOnly: false, | ||
| library: "lib", | ||
| }, | ||
| { | ||
| uid: "lib.table3", | ||
| id: "table3", | ||
| name: "table3", | ||
| type: "table", | ||
| readOnly: false, | ||
| library: "lib", | ||
| }, | ||
| ]; | ||
|
|
||
| const api = dataAccessApi(); | ||
| const deleteTableStub = sinon.stub(api, "deleteTable"); | ||
|
|
||
| // First table succeeds | ||
| deleteTableStub.onFirstCall().resolves(); | ||
| // Second table fails | ||
| deleteTableStub | ||
| .onSecondCall() | ||
| .throwsException(new Error("Failed to delete")); | ||
| // Third table succeeds | ||
| deleteTableStub.onThirdCall().resolves(); | ||
|
|
||
| const provider = libraryDataProvider(api); | ||
|
|
||
| try { | ||
| await provider.deleteTables(items); | ||
| expect.fail("Should have thrown an error"); | ||
| } catch (error) { | ||
| expect(error.message).to.contain("lib.table2"); | ||
| expect(deleteTableStub.callCount).to.equal(3); | ||
| } | ||
|
|
||
| deleteTableStub.restore(); | ||
| }); | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be worth asking @skyeaussie what message to use here. We may not need the count or extra parens around the s. Maybe something like...
It looks like studio uses the following two messages: