Skip to content

Commit c4df8bf

Browse files
committed
Handle expanded state
1 parent 29c29f0 commit c4df8bf

File tree

4 files changed

+190
-10
lines changed

4 files changed

+190
-10
lines changed

extensions/ql-vscode/src/databases/config/db-config-store.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
SelectedDbItem,
1010
SelectedDbItemKind,
1111
} from "./db-config";
12-
import * as lodash from "lodash";
1312
import * as chokidar from "chokidar";
1413
import { DisposableObject, DisposeHandler } from "../../pure/disposable-object";
1514
import { DbConfigValidator } from "./db-config-validator";
@@ -27,7 +26,10 @@ import {
2726
DbItem,
2827
DbItemKind,
2928
} from "../db-item";
30-
import { mapDbItemToSelectedDbItem } from "../db-item-selection";
29+
import {
30+
compareSelectedKindIsEqual,
31+
mapDbItemToSelectedDbItem,
32+
} from "../db-item-selection";
3133

3234
export class DbConfigStore extends DisposableObject {
3335
public readonly onDidChangeConfig: AppEvent<void>;
@@ -98,7 +100,7 @@ export class DbConfigStore extends DisposableObject {
98100
throw Error("Cannot remove item if config is not loaded");
99101
}
100102

101-
const config: DbConfig = cloneDbConfig(this.config);
103+
const config = cloneDbConfig(this.config);
102104
const selectedItem: SelectedDbItem | undefined = config.selected;
103105

104106
// Remove item from databases
@@ -115,7 +117,7 @@ export class DbConfigStore extends DisposableObject {
115117
);
116118
break;
117119
case DbItemKind.LocalDatabase:
118-
// TODO: Remove databases from Disk once implemented
120+
// When we start using local databases these need to be removed from disk as well.
119121
if (dbItem.parentListName) {
120122
const parent = config.databases.local.lists.find(
121123
(list) => list.name === dbItem.parentListName,
@@ -162,12 +164,11 @@ export class DbConfigStore extends DisposableObject {
162164

163165
// Remove item from selected
164166
const removedItem = mapDbItemToSelectedDbItem(dbItem);
165-
if (selectedItem) {
167+
if (selectedItem && removedItem) {
166168
// if removedItem has a parentList, check if parentList is selectedItem
167169
if (
168-
removedItem &&
169-
(removedItem.kind === SelectedDbItemKind.LocalUserDefinedList ||
170-
removedItem.kind === SelectedDbItemKind.RemoteUserDefinedList)
170+
removedItem.kind === SelectedDbItemKind.LocalUserDefinedList ||
171+
removedItem.kind === SelectedDbItemKind.RemoteUserDefinedList
171172
) {
172173
if (
173174
(selectedItem.kind === SelectedDbItemKind.LocalDatabase ||
@@ -176,7 +177,8 @@ export class DbConfigStore extends DisposableObject {
176177
) {
177178
config.selected = undefined;
178179
}
179-
} else if (lodash.isEqual(removedItem, selectedItem)) {
180+
}
181+
if (compareSelectedKindIsEqual(removedItem, selectedItem)) {
180182
config.selected = undefined;
181183
}
182184
}

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

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import { DbItem, DbItemKind, LocalDbItem, RemoteDbItem } from "./db-item";
2-
import { SelectedDbItem, SelectedDbItemKind } from "./config/db-config";
2+
import {
3+
SelectedDbItem,
4+
SelectedDbItemKind,
5+
SelectedLocalDatabase,
6+
SelectedLocalUserDefinedList,
7+
SelectedRemoteOwner,
8+
SelectedRemoteRepository,
9+
} from "./config/db-config";
310

411
export function getSelectedDbItem(dbItems: DbItem[]): DbItem | undefined {
512
for (const dbItem of dbItems) {
@@ -92,3 +99,39 @@ export function mapDbItemToSelectedDbItem(
9299
};
93100
}
94101
}
102+
103+
export function compareSelectedKindIsEqual(
104+
item1: SelectedDbItem,
105+
item2: SelectedDbItem,
106+
): boolean {
107+
if (item1.kind === item2.kind) {
108+
switch (item1.kind) {
109+
case SelectedDbItemKind.LocalUserDefinedList:
110+
case SelectedDbItemKind.RemoteUserDefinedList:
111+
case SelectedDbItemKind.RemoteSystemDefinedList:
112+
return (
113+
item1.listName === (item2 as SelectedLocalUserDefinedList).listName
114+
);
115+
case SelectedDbItemKind.RemoteOwner:
116+
return item1.ownerName === (item2 as SelectedRemoteOwner).ownerName;
117+
case SelectedDbItemKind.LocalDatabase: {
118+
const selectedItem = item2 as SelectedLocalDatabase;
119+
return (
120+
item1.databaseName === selectedItem.databaseName &&
121+
item1.listName === selectedItem.listName
122+
);
123+
}
124+
case SelectedDbItemKind.RemoteRepository: {
125+
const selectedItem = item2 as SelectedRemoteRepository;
126+
return (
127+
item1.repositoryName === selectedItem.repositoryName &&
128+
item1.listName === selectedItem.listName
129+
);
130+
}
131+
default:
132+
return false;
133+
}
134+
} else {
135+
return false;
136+
}
137+
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ export class DbManager {
7777

7878
public async removeDbItem(dbItem: DbItem): Promise<void> {
7979
await this.dbConfigStore.removeDbItem(dbItem);
80+
81+
// Updating the expanded items takes care of cleaning up
82+
// any non-existent items.
83+
await this.updateExpandedItems(this.getExpandedItems());
8084
}
8185

8286
public async updateDbItemExpandedState(

extensions/ql-vscode/test/unit-tests/databases/config/db-config-store.test.ts

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {
1313
import {
1414
createLocalDatabaseDbItem,
1515
createLocalListDbItem,
16+
createRemoteOwnerDbItem,
17+
createRemoteRepoDbItem,
1618
createRemoteUserDefinedListDbItem,
1719
} from "../../../factories/db-item-factories";
1820
import { createMockApp } from "../../../__mocks__/appMock";
@@ -365,4 +367,133 @@ describe("db config store", () => {
365367
configStore.dispose();
366368
});
367369
});
370+
371+
describe("db and list deletion", () => {
372+
let app: App;
373+
let configPath: string;
374+
375+
beforeEach(async () => {
376+
app = createMockApp({
377+
extensionPath,
378+
workspaceStoragePath: tempWorkspaceStoragePath,
379+
});
380+
381+
configPath = join(tempWorkspaceStoragePath, "workspace-databases.json");
382+
});
383+
384+
it("should remove a single db item", async () => {
385+
// Initial set up
386+
const dbConfig = createDbConfig({
387+
remoteOwners: ["owner1", "owner2"],
388+
selected: {
389+
kind: SelectedDbItemKind.RemoteOwner,
390+
ownerName: "owner1",
391+
},
392+
});
393+
394+
await writeJSON(configPath, dbConfig);
395+
396+
const configStore = new DbConfigStore(app);
397+
await configStore.initialize();
398+
399+
// Remove
400+
const currentDbItem = createRemoteOwnerDbItem({
401+
ownerName: "owner1",
402+
});
403+
await configStore.removeDbItem(currentDbItem);
404+
405+
// Read the config file
406+
const updatedDbConfig = (await readJSON(configPath)) as DbConfig;
407+
408+
// Check that the config file has been updated
409+
const updatedRemoteDbs = updatedDbConfig.databases.remote;
410+
expect(updatedRemoteDbs.owners).toHaveLength(1);
411+
expect(updatedRemoteDbs.owners[0]).toEqual("owner2");
412+
413+
expect(updatedDbConfig.selected).toEqual(undefined);
414+
415+
configStore.dispose();
416+
});
417+
418+
it("should remove a list db item", async () => {
419+
// Initial set up
420+
const dbConfig = createDbConfig({
421+
remoteLists: [
422+
{
423+
name: "list1",
424+
repositories: ["owner/repo1", "owner/repo2"],
425+
},
426+
],
427+
selected: {
428+
kind: SelectedDbItemKind.RemoteUserDefinedList,
429+
listName: "list1",
430+
},
431+
});
432+
433+
await writeJSON(configPath, dbConfig);
434+
435+
const configStore = new DbConfigStore(app);
436+
await configStore.initialize();
437+
438+
// Remove
439+
const currentDbItem = createRemoteUserDefinedListDbItem({
440+
listName: "list1",
441+
});
442+
await configStore.removeDbItem(currentDbItem);
443+
444+
// Read the config file
445+
const updatedDbConfig = (await readJSON(configPath)) as DbConfig;
446+
447+
// Check that the config file has been updated
448+
const updatedRemoteDbs = updatedDbConfig.databases.remote;
449+
expect(updatedRemoteDbs.repositoryLists).toHaveLength(0);
450+
451+
expect(updatedDbConfig.selected).toEqual(undefined);
452+
453+
configStore.dispose();
454+
});
455+
456+
it("should remove a db item in a list", async () => {
457+
// Initial set up
458+
const dbConfig = createDbConfig({
459+
remoteLists: [
460+
{
461+
name: "list1",
462+
repositories: ["owner/repo1", "owner/repo2"],
463+
},
464+
],
465+
selected: {
466+
kind: SelectedDbItemKind.RemoteRepository,
467+
repositoryName: "owner/repo1",
468+
listName: "list1",
469+
},
470+
});
471+
472+
await writeJSON(configPath, dbConfig);
473+
474+
const configStore = new DbConfigStore(app);
475+
await configStore.initialize();
476+
477+
// Remove
478+
const currentDbItem = createRemoteRepoDbItem({
479+
repoFullName: "owner/repo1",
480+
parentListName: "list1",
481+
});
482+
await configStore.removeDbItem(currentDbItem);
483+
484+
// Read the config file
485+
const updatedDbConfig = (await readJSON(configPath)) as DbConfig;
486+
487+
// Check that the config file has been updated
488+
const updatedRemoteDbs = updatedDbConfig.databases.remote;
489+
expect(updatedRemoteDbs.repositoryLists[0].repositories).toHaveLength(1);
490+
expect(updatedRemoteDbs.repositoryLists[0].repositories[0]).toEqual(
491+
"owner/repo2",
492+
);
493+
494+
expect(updatedDbConfig.selected).toEqual(undefined);
495+
496+
configStore.dispose();
497+
});
498+
});
368499
});

0 commit comments

Comments
 (0)