Add 'rename' context menu action for dbs/lists (#1928)
This commit is contained in:
@@ -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"
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
19
extensions/ql-vscode/src/databases/db-item-naming.ts
Normal file
19
extensions/ql-vscode/src/databases/db-item-naming.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
|||||||
@@ -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",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user