Add 'rename' context menu action for dbs/lists (#1928)

This commit is contained in:
Charis Kyriakou
2023-01-05 13:29:10 +00:00
committed by GitHub
parent 4dba169412
commit 1c705da444
7 changed files with 331 additions and 3 deletions

View File

@@ -64,6 +64,7 @@
"onCommand:codeQLDatabasesExperimental.addNewList", "onCommand:codeQLDatabasesExperimental.addNewList",
"onCommand:codeQLDatabasesExperimental.setSelectedItem", "onCommand:codeQLDatabasesExperimental.setSelectedItem",
"onCommand:codeQLDatabasesExperimental.setSelectedItemContextMenu", "onCommand:codeQLDatabasesExperimental.setSelectedItemContextMenu",
"onCommand:codeQLDatabasesExperimental.renameItemContextMenu",
"onCommand:codeQLDatabasesExperimental.openOnGitHubContextMenu", "onCommand:codeQLDatabasesExperimental.openOnGitHubContextMenu",
"onCommand:codeQL.quickQuery", "onCommand:codeQL.quickQuery",
"onCommand:codeQL.restartQueryServer", "onCommand:codeQL.restartQueryServer",
@@ -383,6 +384,10 @@
"command": "codeQLDatabasesExperimental.setSelectedItemContextMenu", "command": "codeQLDatabasesExperimental.setSelectedItemContextMenu",
"title": "Select" "title": "Select"
}, },
{
"command": "codeQLDatabasesExperimental.renameItemContextMenu",
"title": "Rename"
},
{ {
"command": "codeQLDatabasesExperimental.openOnGitHubContextMenu", "command": "codeQLDatabasesExperimental.openOnGitHubContextMenu",
"title": "Open on GitHub" "title": "Open on GitHub"
@@ -790,6 +795,10 @@
"command": "codeQLDatabasesExperimental.setSelectedItemContextMenu", "command": "codeQLDatabasesExperimental.setSelectedItemContextMenu",
"when": "view == codeQLDatabasesExperimental && viewItem =~ /canBeSelected/" "when": "view == codeQLDatabasesExperimental && viewItem =~ /canBeSelected/"
}, },
{
"command": "codeQLDatabasesExperimental.renameItemContextMenu",
"when": "view == codeQLDatabasesExperimental && viewItem =~ /canBeRenamed/"
},
{ {
"command": "codeQLDatabasesExperimental.openOnGitHubContextMenu", "command": "codeQLDatabasesExperimental.openOnGitHubContextMenu",
"when": "view == codeQLDatabasesExperimental && viewItem =~ /canBeOpenedOnGitHub/" "when": "view == codeQLDatabasesExperimental && viewItem =~ /canBeOpenedOnGitHub/"
@@ -1026,6 +1035,10 @@
"command": "codeQLDatabasesExperimental.setSelectedItemContextMenu", "command": "codeQLDatabasesExperimental.setSelectedItemContextMenu",
"when": "false" "when": "false"
}, },
{
"command": "codeQLDatabasesExperimental.renameItemContextMenu",
"when": "false"
},
{ {
"command": "codeQLDatabasesExperimental.openOnGitHubContextMenu", "command": "codeQLDatabasesExperimental.openOnGitHubContextMenu",
"when": "false" "when": "false"

View File

@@ -50,6 +50,24 @@ export function updateItemInExpandedState(
} }
} }
export function replaceItemInExpandedState(
currentExpandedItems: ExpandedDbItem[],
currentDbItem: DbItem,
newDbItem: DbItem,
): ExpandedDbItem[] {
const newExpandedItems: ExpandedDbItem[] = [];
for (const item of currentExpandedItems) {
if (isDbItemEqualToExpandedDbItem(currentDbItem, item)) {
newExpandedItems.push(mapDbItemToExpandedDbItem(newDbItem));
} else {
newExpandedItems.push(item);
}
}
return newExpandedItems;
}
function mapDbItemToExpandedDbItem(dbItem: DbItem): ExpandedDbItem { function mapDbItemToExpandedDbItem(dbItem: DbItem): ExpandedDbItem {
switch (dbItem.kind) { switch (dbItem.kind) {
case DbItemKind.RootLocal: case DbItemKind.RootLocal:

View File

@@ -0,0 +1,19 @@
import { DbItem, DbItemKind } from "./db-item";
export function getDbItemName(dbItem: DbItem): string | undefined {
switch (dbItem.kind) {
case DbItemKind.RootLocal:
case DbItemKind.RootRemote:
return undefined;
case DbItemKind.LocalList:
case DbItemKind.RemoteUserDefinedList:
case DbItemKind.RemoteSystemDefinedList:
return dbItem.listName;
case DbItemKind.RemoteOwner:
return dbItem.ownerName;
case DbItemKind.LocalDatabase:
return dbItem.databaseName;
case DbItemKind.RemoteRepo:
return dbItem.repoFullName;
}
}

View File

@@ -2,8 +2,19 @@ import { App } from "../common/app";
import { AppEvent, AppEventEmitter } from "../common/events"; import { AppEvent, AppEventEmitter } from "../common/events";
import { ValueResult } from "../common/value-result"; import { ValueResult } from "../common/value-result";
import { DbConfigStore } from "./config/db-config-store"; import { DbConfigStore } from "./config/db-config-store";
import { DbItem, DbListKind } from "./db-item"; import {
import { updateItemInExpandedState, ExpandedDbItem } from "./db-item-expansion"; DbItem,
DbItemKind,
DbListKind,
LocalDatabaseDbItem,
LocalListDbItem,
RemoteUserDefinedListDbItem,
} from "./db-item";
import {
updateItemInExpandedState,
replaceItemInExpandedState,
ExpandedDbItem,
} from "./db-item-expansion";
import { import {
getSelectedDbItem, getSelectedDbItem,
mapDbItemToSelectedDbItem, mapDbItemToSelectedDbItem,
@@ -105,6 +116,37 @@ export class DbManager {
} }
} }
public async renameList(
currentDbItem: LocalListDbItem | RemoteUserDefinedListDbItem,
newName: string,
): Promise<void> {
if (currentDbItem.kind === DbItemKind.LocalList) {
await this.dbConfigStore.renameLocalList(currentDbItem, newName);
} else if (currentDbItem.kind === DbItemKind.RemoteUserDefinedList) {
await this.dbConfigStore.renameRemoteList(currentDbItem, newName);
}
const newDbItem = { ...currentDbItem, listName: newName };
const newExpandedItems = replaceItemInExpandedState(
this.getExpandedItems(),
currentDbItem,
newDbItem,
);
await this.setExpandedItems(newExpandedItems);
}
public async renameLocalDb(
currentDbItem: LocalDatabaseDbItem,
newName: string,
): Promise<void> {
await this.dbConfigStore.renameLocalDb(
currentDbItem,
newName,
currentDbItem.parentListName,
);
}
public doesListExist(listKind: DbListKind, listName: string): boolean { public doesListExist(listKind: DbListKind, listName: string): boolean {
switch (listKind) { switch (listKind) {
case DbListKind.Local: case DbListKind.Local:
@@ -124,6 +166,10 @@ export class DbManager {
return this.dbConfigStore.doesRemoteDbExist(nwo, listName); return this.dbConfigStore.doesRemoteDbExist(nwo, listName);
} }
public doesLocalDbExist(dbName: string, listName?: string): boolean {
return this.dbConfigStore.doesLocalDbExist(dbName, listName);
}
private getExpandedItems(): ExpandedDbItem[] { private getExpandedItems(): ExpandedDbItem[] {
const items = this.app.workspaceState.get<ExpandedDbItem[]>( const items = this.app.workspaceState.get<ExpandedDbItem[]>(
DbManager.DB_EXPANDED_STATE_KEY, DbManager.DB_EXPANDED_STATE_KEY,

View File

@@ -16,7 +16,16 @@ import {
} from "../../common/github-url-identifier-helper"; } from "../../common/github-url-identifier-helper";
import { showAndLogErrorMessage } from "../../helpers"; import { showAndLogErrorMessage } from "../../helpers";
import { DisposableObject } from "../../pure/disposable-object"; import { DisposableObject } from "../../pure/disposable-object";
import { DbItem, DbItemKind, DbListKind, remoteDbKinds } from "../db-item"; import {
DbItem,
DbItemKind,
DbListKind,
LocalDatabaseDbItem,
LocalListDbItem,
remoteDbKinds,
RemoteUserDefinedListDbItem,
} from "../db-item";
import { getDbItemName } from "../db-item-naming";
import { DbManager } from "../db-manager"; import { DbManager } from "../db-manager";
import { DbTreeDataProvider } from "./db-tree-data-provider"; import { DbTreeDataProvider } from "./db-tree-data-provider";
import { DbTreeViewItem } from "./db-tree-view-item"; import { DbTreeViewItem } from "./db-tree-view-item";
@@ -92,6 +101,12 @@ export class DbPanel extends DisposableObject {
(treeViewItem: DbTreeViewItem) => this.openOnGitHub(treeViewItem), (treeViewItem: DbTreeViewItem) => this.openOnGitHub(treeViewItem),
), ),
); );
this.push(
commandRunner(
"codeQLDatabasesExperimental.renameItemContextMenu",
(treeViewItem: DbTreeViewItem) => this.renameItem(treeViewItem),
),
);
} }
private async openConfigFile(): Promise<void> { private async openConfigFile(): Promise<void> {
@@ -266,6 +281,88 @@ export class DbPanel extends DisposableObject {
await this.dbManager.setSelectedDbItem(treeViewItem.dbItem); await this.dbManager.setSelectedDbItem(treeViewItem.dbItem);
} }
private async renameItem(treeViewItem: DbTreeViewItem): Promise<void> {
const dbItem = treeViewItem.dbItem;
if (dbItem === undefined) {
throw new Error(
"Not a database item that can be renamed. Please select a valid item.",
);
}
const oldName = getDbItemName(dbItem);
const newName = await window.showInputBox({
prompt: "Enter the new name",
value: oldName,
});
if (newName === undefined || newName === "") {
return;
}
switch (dbItem.kind) {
case DbItemKind.LocalList:
await this.renameLocalListItem(dbItem, newName);
break;
case DbItemKind.LocalDatabase:
await this.renameLocalDatabaseItem(dbItem, newName);
break;
case DbItemKind.RemoteUserDefinedList:
await this.renameRemoteUserDefinedListItem(dbItem, newName);
break;
default:
throw Error(`Action not allowed for the '${dbItem.kind}' db item kind`);
}
}
private async renameLocalListItem(
dbItem: LocalListDbItem,
newName: string,
): Promise<void> {
if (dbItem.listName === newName) {
return;
}
if (this.dbManager.doesListExist(DbListKind.Local, newName)) {
void showAndLogErrorMessage(`The list '${newName}' already exists`);
return;
}
await this.dbManager.renameList(dbItem, newName);
}
private async renameLocalDatabaseItem(
dbItem: LocalDatabaseDbItem,
newName: string,
): Promise<void> {
if (dbItem.databaseName === newName) {
return;
}
if (this.dbManager.doesLocalDbExist(newName, dbItem.parentListName)) {
void showAndLogErrorMessage(`The database '${newName}' already exists`);
return;
}
await this.dbManager.renameLocalDb(dbItem, newName);
}
private async renameRemoteUserDefinedListItem(
dbItem: RemoteUserDefinedListDbItem,
newName: string,
): Promise<void> {
if (dbItem.listName === newName) {
return;
}
if (this.dbManager.doesListExist(DbListKind.Remote, newName)) {
void showAndLogErrorMessage(`The list '${newName}' already exists`);
return;
}
await this.dbManager.renameList(dbItem, newName);
}
private async onDidCollapseElement( private async onDidCollapseElement(
event: TreeViewExpansionEvent<DbTreeViewItem>, event: TreeViewExpansionEvent<DbTreeViewItem>,
): Promise<void> { ): Promise<void> {

View File

@@ -6,6 +6,7 @@ import {
updateItemInExpandedState, updateItemInExpandedState,
ExpandedDbItem, ExpandedDbItem,
ExpandedDbItemKind, ExpandedDbItemKind,
replaceItemInExpandedState,
} from "../../../src/databases/db-item-expansion"; } from "../../../src/databases/db-item-expansion";
import { import {
createRemoteUserDefinedListDbItem, createRemoteUserDefinedListDbItem,
@@ -108,4 +109,59 @@ describe("db item expansion", () => {
expect(newExpandedItems).toEqual([]); expect(newExpandedItems).toEqual([]);
}); });
}); });
describe("replaceItemInExpandedState", () => {
it("should replace the db item", () => {
const currentExpandedItems: ExpandedDbItem[] = [
{
kind: ExpandedDbItemKind.RootRemote,
},
{
kind: ExpandedDbItemKind.RemoteUserDefinedList,
listName: "list1",
},
{
kind: ExpandedDbItemKind.RemoteUserDefinedList,
listName: "list2",
},
{
kind: ExpandedDbItemKind.LocalUserDefinedList,
listName: "list1",
},
];
const currentDbItem = createRemoteUserDefinedListDbItem({
listName: "list1",
});
const newDbItem: RemoteUserDefinedListDbItem = {
...currentDbItem,
listName: "list1 (renamed)",
};
const newExpandedItems = replaceItemInExpandedState(
currentExpandedItems,
currentDbItem,
newDbItem,
);
expect(newExpandedItems).toEqual([
{
kind: ExpandedDbItemKind.RootRemote,
},
{
kind: ExpandedDbItemKind.RemoteUserDefinedList,
listName: "list1 (renamed)",
},
{
kind: ExpandedDbItemKind.RemoteUserDefinedList,
listName: "list2",
},
{
kind: ExpandedDbItemKind.LocalUserDefinedList,
listName: "list1",
},
]);
});
});
}); });

View File

@@ -0,0 +1,79 @@
import { getDbItemName } from "../../../src/databases/db-item-naming";
import {
createLocalDatabaseDbItem,
createLocalListDbItem,
createRemoteOwnerDbItem,
createRemoteRepoDbItem,
createRemoteSystemDefinedListDbItem,
createRemoteUserDefinedListDbItem,
createRootLocalDbItem,
createRootRemoteDbItem,
} from "../../factories/db-item-factories";
describe("db item naming", () => {
describe("getDbItemName", () => {
it("return undefined for root local db item", () => {
const dbItem = createRootLocalDbItem();
const name = getDbItemName(dbItem);
expect(name).toBeUndefined();
});
it("return undefined for root remote db item", () => {
const dbItem = createRootRemoteDbItem();
const name = getDbItemName(dbItem);
expect(name).toBeUndefined();
});
it("return list name for local list db item", () => {
const dbItem = createLocalListDbItem();
const name = getDbItemName(dbItem);
expect(name).toEqual(dbItem.listName);
});
it("return list name for remote user defined list db item", () => {
const dbItem = createRemoteUserDefinedListDbItem();
const name = getDbItemName(dbItem);
expect(name).toEqual(dbItem.listName);
});
it("return list name for remote system defined list db item", () => {
const dbItem = createRemoteSystemDefinedListDbItem();
const name = getDbItemName(dbItem);
expect(name).toEqual(dbItem.listName);
});
it("return owner name for owner db item", () => {
const dbItem = createRemoteOwnerDbItem();
const name = getDbItemName(dbItem);
expect(name).toEqual(dbItem.ownerName);
});
it("return database name for local db item", () => {
const dbItem = createLocalDatabaseDbItem();
const name = getDbItemName(dbItem);
expect(name).toEqual(dbItem.databaseName);
});
it("return repo name for remote repo db item", () => {
const dbItem = createRemoteRepoDbItem();
const name = getDbItemName(dbItem);
expect(name).toEqual(dbItem.repoFullName);
});
});
});