Skip to content

Commit 1c705da

Browse files
authored
Add 'rename' context menu action for dbs/lists (github#1928)
1 parent 4dba169 commit 1c705da

File tree

7 files changed

+331
-3
lines changed

7 files changed

+331
-3
lines changed

extensions/ql-vscode/package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"onCommand:codeQLDatabasesExperimental.addNewList",
6565
"onCommand:codeQLDatabasesExperimental.setSelectedItem",
6666
"onCommand:codeQLDatabasesExperimental.setSelectedItemContextMenu",
67+
"onCommand:codeQLDatabasesExperimental.renameItemContextMenu",
6768
"onCommand:codeQLDatabasesExperimental.openOnGitHubContextMenu",
6869
"onCommand:codeQL.quickQuery",
6970
"onCommand:codeQL.restartQueryServer",
@@ -383,6 +384,10 @@
383384
"command": "codeQLDatabasesExperimental.setSelectedItemContextMenu",
384385
"title": "Select"
385386
},
387+
{
388+
"command": "codeQLDatabasesExperimental.renameItemContextMenu",
389+
"title": "Rename"
390+
},
386391
{
387392
"command": "codeQLDatabasesExperimental.openOnGitHubContextMenu",
388393
"title": "Open on GitHub"
@@ -790,6 +795,10 @@
790795
"command": "codeQLDatabasesExperimental.setSelectedItemContextMenu",
791796
"when": "view == codeQLDatabasesExperimental && viewItem =~ /canBeSelected/"
792797
},
798+
{
799+
"command": "codeQLDatabasesExperimental.renameItemContextMenu",
800+
"when": "view == codeQLDatabasesExperimental && viewItem =~ /canBeRenamed/"
801+
},
793802
{
794803
"command": "codeQLDatabasesExperimental.openOnGitHubContextMenu",
795804
"when": "view == codeQLDatabasesExperimental && viewItem =~ /canBeOpenedOnGitHub/"
@@ -1026,6 +1035,10 @@
10261035
"command": "codeQLDatabasesExperimental.setSelectedItemContextMenu",
10271036
"when": "false"
10281037
},
1038+
{
1039+
"command": "codeQLDatabasesExperimental.renameItemContextMenu",
1040+
"when": "false"
1041+
},
10291042
{
10301043
"command": "codeQLDatabasesExperimental.openOnGitHubContextMenu",
10311044
"when": "false"

extensions/ql-vscode/src/databases/db-item-expansion.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,24 @@ export function updateItemInExpandedState(
5050
}
5151
}
5252

53+
export function replaceItemInExpandedState(
54+
currentExpandedItems: ExpandedDbItem[],
55+
currentDbItem: DbItem,
56+
newDbItem: DbItem,
57+
): ExpandedDbItem[] {
58+
const newExpandedItems: ExpandedDbItem[] = [];
59+
60+
for (const item of currentExpandedItems) {
61+
if (isDbItemEqualToExpandedDbItem(currentDbItem, item)) {
62+
newExpandedItems.push(mapDbItemToExpandedDbItem(newDbItem));
63+
} else {
64+
newExpandedItems.push(item);
65+
}
66+
}
67+
68+
return newExpandedItems;
69+
}
70+
5371
function mapDbItemToExpandedDbItem(dbItem: DbItem): ExpandedDbItem {
5472
switch (dbItem.kind) {
5573
case DbItemKind.RootLocal:
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { DbItem, DbItemKind } from "./db-item";
2+
3+
export function getDbItemName(dbItem: DbItem): string | undefined {
4+
switch (dbItem.kind) {
5+
case DbItemKind.RootLocal:
6+
case DbItemKind.RootRemote:
7+
return undefined;
8+
case DbItemKind.LocalList:
9+
case DbItemKind.RemoteUserDefinedList:
10+
case DbItemKind.RemoteSystemDefinedList:
11+
return dbItem.listName;
12+
case DbItemKind.RemoteOwner:
13+
return dbItem.ownerName;
14+
case DbItemKind.LocalDatabase:
15+
return dbItem.databaseName;
16+
case DbItemKind.RemoteRepo:
17+
return dbItem.repoFullName;
18+
}
19+
}

extensions/ql-vscode/src/databases/db-manager.ts

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,19 @@ import { App } from "../common/app";
22
import { AppEvent, AppEventEmitter } from "../common/events";
33
import { ValueResult } from "../common/value-result";
44
import { DbConfigStore } from "./config/db-config-store";
5-
import { DbItem, DbListKind } from "./db-item";
6-
import { updateItemInExpandedState, ExpandedDbItem } from "./db-item-expansion";
5+
import {
6+
DbItem,
7+
DbItemKind,
8+
DbListKind,
9+
LocalDatabaseDbItem,
10+
LocalListDbItem,
11+
RemoteUserDefinedListDbItem,
12+
} from "./db-item";
13+
import {
14+
updateItemInExpandedState,
15+
replaceItemInExpandedState,
16+
ExpandedDbItem,
17+
} from "./db-item-expansion";
718
import {
819
getSelectedDbItem,
920
mapDbItemToSelectedDbItem,
@@ -105,6 +116,37 @@ export class DbManager {
105116
}
106117
}
107118

119+
public async renameList(
120+
currentDbItem: LocalListDbItem | RemoteUserDefinedListDbItem,
121+
newName: string,
122+
): Promise<void> {
123+
if (currentDbItem.kind === DbItemKind.LocalList) {
124+
await this.dbConfigStore.renameLocalList(currentDbItem, newName);
125+
} else if (currentDbItem.kind === DbItemKind.RemoteUserDefinedList) {
126+
await this.dbConfigStore.renameRemoteList(currentDbItem, newName);
127+
}
128+
129+
const newDbItem = { ...currentDbItem, listName: newName };
130+
const newExpandedItems = replaceItemInExpandedState(
131+
this.getExpandedItems(),
132+
currentDbItem,
133+
newDbItem,
134+
);
135+
136+
await this.setExpandedItems(newExpandedItems);
137+
}
138+
139+
public async renameLocalDb(
140+
currentDbItem: LocalDatabaseDbItem,
141+
newName: string,
142+
): Promise<void> {
143+
await this.dbConfigStore.renameLocalDb(
144+
currentDbItem,
145+
newName,
146+
currentDbItem.parentListName,
147+
);
148+
}
149+
108150
public doesListExist(listKind: DbListKind, listName: string): boolean {
109151
switch (listKind) {
110152
case DbListKind.Local:
@@ -124,6 +166,10 @@ export class DbManager {
124166
return this.dbConfigStore.doesRemoteDbExist(nwo, listName);
125167
}
126168

169+
public doesLocalDbExist(dbName: string, listName?: string): boolean {
170+
return this.dbConfigStore.doesLocalDbExist(dbName, listName);
171+
}
172+
127173
private getExpandedItems(): ExpandedDbItem[] {
128174
const items = this.app.workspaceState.get<ExpandedDbItem[]>(
129175
DbManager.DB_EXPANDED_STATE_KEY,

extensions/ql-vscode/src/databases/ui/db-panel.ts

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,16 @@ import {
1616
} from "../../common/github-url-identifier-helper";
1717
import { showAndLogErrorMessage } from "../../helpers";
1818
import { DisposableObject } from "../../pure/disposable-object";
19-
import { DbItem, DbItemKind, DbListKind, remoteDbKinds } from "../db-item";
19+
import {
20+
DbItem,
21+
DbItemKind,
22+
DbListKind,
23+
LocalDatabaseDbItem,
24+
LocalListDbItem,
25+
remoteDbKinds,
26+
RemoteUserDefinedListDbItem,
27+
} from "../db-item";
28+
import { getDbItemName } from "../db-item-naming";
2029
import { DbManager } from "../db-manager";
2130
import { DbTreeDataProvider } from "./db-tree-data-provider";
2231
import { DbTreeViewItem } from "./db-tree-view-item";
@@ -92,6 +101,12 @@ export class DbPanel extends DisposableObject {
92101
(treeViewItem: DbTreeViewItem) => this.openOnGitHub(treeViewItem),
93102
),
94103
);
104+
this.push(
105+
commandRunner(
106+
"codeQLDatabasesExperimental.renameItemContextMenu",
107+
(treeViewItem: DbTreeViewItem) => this.renameItem(treeViewItem),
108+
),
109+
);
95110
}
96111

97112
private async openConfigFile(): Promise<void> {
@@ -266,6 +281,88 @@ export class DbPanel extends DisposableObject {
266281
await this.dbManager.setSelectedDbItem(treeViewItem.dbItem);
267282
}
268283

284+
private async renameItem(treeViewItem: DbTreeViewItem): Promise<void> {
285+
const dbItem = treeViewItem.dbItem;
286+
if (dbItem === undefined) {
287+
throw new Error(
288+
"Not a database item that can be renamed. Please select a valid item.",
289+
);
290+
}
291+
292+
const oldName = getDbItemName(dbItem);
293+
294+
const newName = await window.showInputBox({
295+
prompt: "Enter the new name",
296+
value: oldName,
297+
});
298+
299+
if (newName === undefined || newName === "") {
300+
return;
301+
}
302+
303+
switch (dbItem.kind) {
304+
case DbItemKind.LocalList:
305+
await this.renameLocalListItem(dbItem, newName);
306+
break;
307+
case DbItemKind.LocalDatabase:
308+
await this.renameLocalDatabaseItem(dbItem, newName);
309+
break;
310+
case DbItemKind.RemoteUserDefinedList:
311+
await this.renameRemoteUserDefinedListItem(dbItem, newName);
312+
break;
313+
default:
314+
throw Error(`Action not allowed for the '${dbItem.kind}' db item kind`);
315+
}
316+
}
317+
318+
private async renameLocalListItem(
319+
dbItem: LocalListDbItem,
320+
newName: string,
321+
): Promise<void> {
322+
if (dbItem.listName === newName) {
323+
return;
324+
}
325+
326+
if (this.dbManager.doesListExist(DbListKind.Local, newName)) {
327+
void showAndLogErrorMessage(`The list '${newName}' already exists`);
328+
return;
329+
}
330+
331+
await this.dbManager.renameList(dbItem, newName);
332+
}
333+
334+
private async renameLocalDatabaseItem(
335+
dbItem: LocalDatabaseDbItem,
336+
newName: string,
337+
): Promise<void> {
338+
if (dbItem.databaseName === newName) {
339+
return;
340+
}
341+
342+
if (this.dbManager.doesLocalDbExist(newName, dbItem.parentListName)) {
343+
void showAndLogErrorMessage(`The database '${newName}' already exists`);
344+
return;
345+
}
346+
347+
await this.dbManager.renameLocalDb(dbItem, newName);
348+
}
349+
350+
private async renameRemoteUserDefinedListItem(
351+
dbItem: RemoteUserDefinedListDbItem,
352+
newName: string,
353+
): Promise<void> {
354+
if (dbItem.listName === newName) {
355+
return;
356+
}
357+
358+
if (this.dbManager.doesListExist(DbListKind.Remote, newName)) {
359+
void showAndLogErrorMessage(`The list '${newName}' already exists`);
360+
return;
361+
}
362+
363+
await this.dbManager.renameList(dbItem, newName);
364+
}
365+
269366
private async onDidCollapseElement(
270367
event: TreeViewExpansionEvent<DbTreeViewItem>,
271368
): Promise<void> {

extensions/ql-vscode/test/unit-tests/databases/db-item-expansion.test.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
updateItemInExpandedState,
77
ExpandedDbItem,
88
ExpandedDbItemKind,
9+
replaceItemInExpandedState,
910
} from "../../../src/databases/db-item-expansion";
1011
import {
1112
createRemoteUserDefinedListDbItem,
@@ -108,4 +109,59 @@ describe("db item expansion", () => {
108109
expect(newExpandedItems).toEqual([]);
109110
});
110111
});
112+
113+
describe("replaceItemInExpandedState", () => {
114+
it("should replace the db item", () => {
115+
const currentExpandedItems: ExpandedDbItem[] = [
116+
{
117+
kind: ExpandedDbItemKind.RootRemote,
118+
},
119+
{
120+
kind: ExpandedDbItemKind.RemoteUserDefinedList,
121+
listName: "list1",
122+
},
123+
{
124+
kind: ExpandedDbItemKind.RemoteUserDefinedList,
125+
listName: "list2",
126+
},
127+
{
128+
kind: ExpandedDbItemKind.LocalUserDefinedList,
129+
listName: "list1",
130+
},
131+
];
132+
133+
const currentDbItem = createRemoteUserDefinedListDbItem({
134+
listName: "list1",
135+
});
136+
137+
const newDbItem: RemoteUserDefinedListDbItem = {
138+
...currentDbItem,
139+
listName: "list1 (renamed)",
140+
};
141+
142+
const newExpandedItems = replaceItemInExpandedState(
143+
currentExpandedItems,
144+
currentDbItem,
145+
newDbItem,
146+
);
147+
148+
expect(newExpandedItems).toEqual([
149+
{
150+
kind: ExpandedDbItemKind.RootRemote,
151+
},
152+
{
153+
kind: ExpandedDbItemKind.RemoteUserDefinedList,
154+
listName: "list1 (renamed)",
155+
},
156+
{
157+
kind: ExpandedDbItemKind.RemoteUserDefinedList,
158+
listName: "list2",
159+
},
160+
{
161+
kind: ExpandedDbItemKind.LocalUserDefinedList,
162+
listName: "list1",
163+
},
164+
]);
165+
});
166+
});
111167
});

0 commit comments

Comments
 (0)