Skip to content

Commit f3f4ef6

Browse files
author
Aasim Khan
committed
Fixing recent connections in connection dialog
1 parent 85fa4ed commit f3f4ef6

3 files changed

Lines changed: 61 additions & 20 deletions

File tree

extensions/mssql/src/models/connectionStore.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -689,13 +689,15 @@ export class ConnectionStore {
689689
connResults = connResults.concat(recentConnections);
690690
}
691691

692-
// Deduplicate connections by ID
692+
// Deduplicate connections by ID and profile source.
693693
const uniqueConnections = new Map<string, IConnectionProfileWithSource>();
694694
let dupeCount = 0;
695695

696696
for (const conn of connResults) {
697-
if (!uniqueConnections.has(conn.id)) {
698-
uniqueConnections.set(conn.id, conn);
697+
const key = conn.id + "-" + conn.profileSource; // Use both ID and source as key to allow same profile in both lists
698+
const storedConn = uniqueConnections.get(key);
699+
if (storedConn === undefined || storedConn?.profileSource !== conn.profileSource) {
700+
uniqueConnections.set(key, conn);
699701
} else {
700702
dupeCount++;
701703
this._logger.verbose(

extensions/mssql/src/reactviews/pages/ConnectionDialog/connectionsListContainer.tsx

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ export const ConnectionsListContainer = () => {
144144
<div className={styles.listScrollArea}>
145145
<div className={styles.paneTitle}>
146146
<Text weight="semibold" className={styles.paneTitle}>
147-
{locConstants.connectionDialog.savedConnections}
147+
{locConstants.connectionDialog.recentConnections}
148148
</Text>
149149
<Button
150150
icon={<ArrowClockwise16Filled />}
@@ -153,27 +153,28 @@ export const ConnectionsListContainer = () => {
153153
title={locConstants.common.refresh}
154154
/>
155155
</div>
156-
<div className={styles.main}>
157-
{savedConnections?.map((connection, index) => {
156+
<Tree>
157+
{// state may not be initialized yet due to async loading of context
158+
recentConnections?.map((connection, index) => {
158159
return (
159160
<ConnectionCard
160161
connection={connection}
161-
key={"saved" + index}
162+
key={"mru" + index}
162163
actionButton={{
163164
icon: <Delete16Regular />,
164165
onClick: (e) => {
165-
context.deleteSavedConnection(connection);
166+
context.removeRecentConnection(connection);
166167
e.stopPropagation();
167168
},
168-
tooltip: locConstants.connectionDialog.deleteSavedConnection,
169+
tooltip: locConstants.connectionDialog.removeRecentConnection,
169170
}}
170171
/>
171172
);
172173
})}
173-
</div>
174+
</Tree>
174175
<div className={styles.paneTitle}>
175176
<Text weight="semibold" className={styles.paneTitle}>
176-
{locConstants.connectionDialog.recentConnections}
177+
{locConstants.connectionDialog.savedConnections}
177178
</Text>
178179
<Button
179180
icon={<ArrowClockwise16Filled />}
@@ -182,25 +183,24 @@ export const ConnectionsListContainer = () => {
182183
title={locConstants.common.refresh}
183184
/>
184185
</div>
185-
<Tree>
186-
{// state may not be initialized yet due to async loading of context
187-
recentConnections?.map((connection, index) => {
186+
<div className={styles.main}>
187+
{savedConnections?.map((connection, index) => {
188188
return (
189189
<ConnectionCard
190190
connection={connection}
191-
key={"mru" + index}
191+
key={"saved" + index}
192192
actionButton={{
193193
icon: <Delete16Regular />,
194194
onClick: (e) => {
195-
context.removeRecentConnection(connection);
195+
context.deleteSavedConnection(connection);
196196
e.stopPropagation();
197197
},
198-
tooltip: locConstants.connectionDialog.removeRecentConnection,
198+
tooltip: locConstants.connectionDialog.deleteSavedConnection,
199199
}}
200200
/>
201201
);
202202
})}
203-
</Tree>
203+
</div>
204204
</div>
205205
</div>
206206
);

extensions/mssql/test/unit/connectionStore.test.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ import { CredentialStore } from "../../src/credentialstore/credentialstore";
1111
import { Logger } from "../../src/models/logger";
1212
import { ConnectionConfig } from "../../src/connectionconfig/connectionconfig";
1313
import VscodeWrapper from "../../src/controllers/vscodeWrapper";
14-
import { IConnectionProfile, IConnectionProfileWithSource } from "../../src/models/interfaces";
14+
import {
15+
CredentialsQuickPickItemType,
16+
IConnectionProfile,
17+
IConnectionProfileWithSource,
18+
} from "../../src/models/interfaces";
1519
import { MatchScore } from "../../src/models/utils";
1620
import { Deferred } from "../../src/protocol";
1721
import { azureAuthConn, sqlAuthConn, connStringConn } from "./utils.test";
@@ -36,7 +40,7 @@ suite("ConnectionStore Tests", () => {
3640
mockLogger = sandbox.createStubInstance(Logger);
3741

3842
mockCredentialStore = sandbox.createStubInstance(CredentialStore);
39-
mockCredentialStore.readCredential.resolves(undefined as any);
43+
mockCredentialStore.readCredential.resolves(undefined);
4044
mockCredentialStore.saveCredential.resolves(true);
4145
mockCredentialStore.deleteCredential.resolves();
4246

@@ -138,4 +142,39 @@ suite("ConnectionStore Tests", () => {
138142
score: MatchScore.NotMatch,
139143
});
140144
});
145+
146+
test("readAllConnections preserves saved and recent entries that share the same id", async () => {
147+
const sharedId = "shared-connection-id";
148+
const savedConnection = {
149+
id: sharedId,
150+
profileSource: CredentialsQuickPickItemType.Profile,
151+
server: "saved-server",
152+
database: "saved-db",
153+
} as IConnectionProfileWithSource;
154+
const recentConnection = {
155+
id: sharedId,
156+
profileSource: CredentialsQuickPickItemType.Mru,
157+
server: "recent-server",
158+
database: "recent-db",
159+
} as IConnectionProfileWithSource;
160+
161+
mockConnectionConfig.getConnections.resolves([savedConnection]);
162+
163+
connectionStore = new ConnectionStore(
164+
mockContext,
165+
mockCredentialStore,
166+
mockLogger,
167+
mockConnectionConfig,
168+
mockVscodeWrapper,
169+
);
170+
171+
await connectionStore.initialized;
172+
sandbox.stub(connectionStore, "getRecentlyUsedConnections").returns([recentConnection]);
173+
174+
const connections = await connectionStore.readAllConnections(true);
175+
176+
expect(connections).to.have.lengthOf(2);
177+
expect(connections).to.deep.include(savedConnection);
178+
expect(connections).to.deep.include(recentConnection);
179+
});
141180
});

0 commit comments

Comments
 (0)