Set db tree item context value to drive actions (#1920)

This commit is contained in:
Charis Kyriakou
2023-01-03 16:17:51 +00:00
committed by GitHub
parent ae3ed9402d
commit 8e848e3403
5 changed files with 208 additions and 9 deletions

View File

@@ -783,7 +783,7 @@
"view/item/context": [
{
"command": "codeQLDatabasesExperimental.setSelectedItemContextMenu",
"when": "view == codeQLDatabasesExperimental && viewItem == canBeSelected"
"when": "view == codeQLDatabasesExperimental && viewItem =~ /canBeSelected/"
},
{
"command": "codeQLDatabases.setCurrentDatabase",
@@ -812,7 +812,7 @@
},
{
"command": "codeQLDatabasesExperimental.setSelectedItem",
"when": "view == codeQLDatabasesExperimental && viewItem == canBeSelected",
"when": "view == codeQLDatabasesExperimental && viewItem =~ /canBeSelected/",
"group": "inline"
},
{

View File

@@ -0,0 +1,61 @@
import { DbItem, DbItemKind, isSelectableDbItem } from "../db-item";
export type DbTreeViewItemAction =
| "canBeSelected"
| "canBeRemoved"
| "canBeRenamed"
| "canBeOpenedOnGitHub";
export function getDbItemActions(dbItem: DbItem): DbTreeViewItemAction[] {
const actions: DbTreeViewItemAction[] = [];
if (canBeSelected(dbItem)) {
actions.push("canBeSelected");
}
if (canBeRemoved(dbItem)) {
actions.push("canBeRemoved");
}
if (canBeRenamed(dbItem)) {
actions.push("canBeRenamed");
}
if (canBeOpenedOnGitHub(dbItem)) {
actions.push("canBeOpenedOnGitHub");
}
return actions;
}
const dbItemKindsThatCanBeRemoved = [
DbItemKind.LocalList,
DbItemKind.RemoteUserDefinedList,
DbItemKind.LocalDatabase,
DbItemKind.RemoteRepo,
DbItemKind.RemoteOwner,
];
const dbItemKindsThatCanBeRenamed = [
DbItemKind.LocalList,
DbItemKind.RemoteUserDefinedList,
DbItemKind.LocalDatabase,
];
const dbItemKindsThatCanBeOpenedOnGitHub = [
DbItemKind.RemoteOwner,
DbItemKind.RemoteRepo,
];
function canBeSelected(dbItem: DbItem): boolean {
return isSelectableDbItem(dbItem) && !dbItem.selected;
}
function canBeRemoved(dbItem: DbItem): boolean {
return dbItemKindsThatCanBeRemoved.includes(dbItem.kind);
}
function canBeRenamed(dbItem: DbItem): boolean {
return dbItemKindsThatCanBeRenamed.includes(dbItem.kind);
}
function canBeOpenedOnGitHub(dbItem: DbItem): boolean {
return dbItemKindsThatCanBeOpenedOnGitHub.includes(dbItem.kind);
}

View File

@@ -11,6 +11,7 @@ import {
RootLocalDbItem,
RootRemoteDbItem,
} from "../db-item";
import { getDbItemActions } from "./db-tree-view-item-action";
export const SELECTED_DB_ITEM_RESOURCE_URI = "codeql://databases?selected=true";
@@ -32,18 +33,21 @@ export class DbTreeViewItem extends vscode.TreeItem {
) {
super(label, collapsibleState);
if (dbItem && isSelectableDbItem(dbItem)) {
if (dbItem.selected) {
if (dbItem) {
this.contextValue = getContextValue(dbItem);
if (isSelectableDbItem(dbItem) && dbItem.selected) {
// Define the resource id to drive the UI to render this item as selected.
this.resourceUri = vscode.Uri.parse(SELECTED_DB_ITEM_RESOURCE_URI);
} else {
// Define a context value to drive the UI to show an action to select the item.
this.contextValue = "canBeSelected";
}
}
}
}
function getContextValue(dbItem: DbItem): string | undefined {
const actions = getDbItemActions(dbItem);
return actions.length > 0 ? actions.join(",") : undefined;
}
export function createDbTreeViewItemError(
label: string,
tooltip: string,

View File

@@ -0,0 +1,109 @@
import { getDbItemActions } from "../../../../src/databases/ui/db-tree-view-item-action";
import {
createLocalDatabaseDbItem,
createLocalListDbItem,
createRemoteOwnerDbItem,
createRemoteRepoDbItem,
createRemoteSystemDefinedListDbItem,
createRemoteUserDefinedListDbItem,
createRootLocalDbItem,
createRootRemoteDbItem,
} from "../../../factories/db-item-factories";
describe("getDbItemActions", () => {
it("should return an empty array for root remote node", () => {
const dbItem = createRootRemoteDbItem();
const actions = getDbItemActions(dbItem);
expect(actions).toEqual([]);
});
it("should return an empty array for root local node", () => {
const dbItem = createRootLocalDbItem();
const actions = getDbItemActions(dbItem);
expect(actions).toEqual([]);
});
it("should set canBeSelected, canBeRemoved and canBeRenamed for local user defined db list", () => {
const dbItem = createLocalListDbItem();
const actions = getDbItemActions(dbItem);
expect(actions).toEqual(["canBeSelected", "canBeRemoved", "canBeRenamed"]);
});
it("should set canBeSelected, canBeRemoved and canBeRenamed for local db", () => {
const dbItem = createLocalDatabaseDbItem();
const actions = getDbItemActions(dbItem);
expect(actions).toEqual(["canBeSelected", "canBeRemoved", "canBeRenamed"]);
});
it("should set canBeSelected for remote system defined db list", () => {
const dbItem = createRemoteSystemDefinedListDbItem();
const actions = getDbItemActions(dbItem);
expect(actions).toEqual(["canBeSelected"]);
});
it("should not set canBeSelected for remote system defined list that is already selected", () => {
const dbItem = createRemoteSystemDefinedListDbItem({ selected: true });
const actions = getDbItemActions(dbItem);
expect(actions.length).toEqual(0);
});
it("should set canBeSelected, canBeRemoved and canBeRenamed for remote user defined db list", () => {
const dbItem = createRemoteUserDefinedListDbItem();
const actions = getDbItemActions(dbItem);
expect(actions).toEqual(["canBeSelected", "canBeRemoved", "canBeRenamed"]);
});
it("should not set canBeSelected for remote user defined db list that is already selected", () => {
const dbItem = createRemoteUserDefinedListDbItem({ selected: true });
const actions = getDbItemActions(dbItem);
expect(actions.includes("canBeSelected")).toBeFalsy();
});
it("should set canBeSelected, canBeRemoved, canBeOpenedOnGitHub for remote owner", () => {
const dbItem = createRemoteOwnerDbItem();
const actions = getDbItemActions(dbItem);
expect(actions).toEqual([
"canBeSelected",
"canBeRemoved",
"canBeOpenedOnGitHub",
]);
});
it("should set canBeSelected, canBeRemoved, canBeOpenedOnGitHub for remote db", () => {
const dbItem = createRemoteRepoDbItem();
const actions = getDbItemActions(dbItem);
expect(actions).toEqual([
"canBeSelected",
"canBeRemoved",
"canBeOpenedOnGitHub",
]);
});
it("should not set canBeSelected for remote db that is already selected", () => {
const dbItem = createRemoteRepoDbItem({ selected: true });
const actions = getDbItemActions(dbItem);
expect(actions.includes("canBeSelected")).toBeFalsy();
});
});

View File

@@ -772,6 +772,7 @@ describe("db panel", () => {
expect(item.tooltip).toBe(`Top ${n} repositories of a language`);
expect(item.iconPath).toEqual(new ThemeIcon("github"));
expect(item.collapsibleState).toBe(TreeItemCollapsibleState.None);
checkDbItemActions(item, ["canBeSelected"]);
}
function checkUserDefinedListItem(
@@ -783,6 +784,7 @@ describe("db panel", () => {
expect(item.tooltip).toBeUndefined();
expect(item.iconPath).toBeUndefined();
expect(item.collapsibleState).toBe(TreeItemCollapsibleState.Collapsed);
checkDbItemActions(item, ["canBeSelected", "canBeRenamed", "canBeRemoved"]);
expect(item.children).toBeTruthy();
expect(item.children.length).toBe(repos.length);
@@ -796,6 +798,11 @@ describe("db panel", () => {
expect(item.tooltip).toBeUndefined();
expect(item.iconPath).toEqual(new ThemeIcon("organization"));
expect(item.collapsibleState).toBe(TreeItemCollapsibleState.None);
checkDbItemActions(item, [
"canBeSelected",
"canBeRemoved",
"canBeOpenedOnGitHub",
]);
expect(item.children).toBeTruthy();
expect(item.children.length).toBe(0);
}
@@ -805,6 +812,11 @@ describe("db panel", () => {
expect(item.tooltip).toBeUndefined();
expect(item.iconPath).toEqual(new ThemeIcon("database"));
expect(item.collapsibleState).toBe(TreeItemCollapsibleState.None);
checkDbItemActions(item, [
"canBeSelected",
"canBeRemoved",
"canBeOpenedOnGitHub",
]);
}
function checkLocalListItem(
@@ -816,6 +828,7 @@ describe("db panel", () => {
expect(item.tooltip).toBeUndefined();
expect(item.iconPath).toBeUndefined();
expect(item.collapsibleState).toBe(TreeItemCollapsibleState.Collapsed);
checkDbItemActions(item, ["canBeSelected", "canBeRemoved", "canBeRenamed"]);
expect(item.children).toBeTruthy();
expect(item.children.length).toBe(databases.length);
@@ -832,6 +845,16 @@ describe("db panel", () => {
expect(item.tooltip).toBe(`Language: ${database.language}`);
expect(item.iconPath).toEqual(new ThemeIcon("database"));
expect(item.collapsibleState).toBe(TreeItemCollapsibleState.None);
checkDbItemActions(item, ["canBeSelected", "canBeRemoved", "canBeRenamed"]);
}
function checkDbItemActions(item: DbTreeViewItem, actions: string[]): void {
const itemActions = item.contextValue?.split(",");
expect(itemActions).toBeDefined();
expect(itemActions!.length).toBe(actions.length);
for (const action of actions) {
expect(itemActions).toContain(action);
}
}
function checkErrorItem(
@@ -852,14 +875,16 @@ describe("db panel", () => {
function isTreeViewItemSelectable(treeViewItem: DbTreeViewItem) {
return (
treeViewItem.resourceUri === undefined &&
treeViewItem.contextValue === "canBeSelected"
treeViewItem.contextValue?.includes("canBeSelected")
);
}
function isTreeViewItemSelected(treeViewItem: DbTreeViewItem) {
return (
treeViewItem.resourceUri?.toString(true) ===
SELECTED_DB_ITEM_RESOURCE_URI && treeViewItem.contextValue === undefined
SELECTED_DB_ITEM_RESOURCE_URI &&
(treeViewItem.contextValue === undefined ||
!treeViewItem.contextValue.includes("canBeSelected"))
);
}