Skip to content

Commit

Permalink
feat: display only 10 items in clickable lists with the show more opt…
Browse files Browse the repository at this point in the history
…ion VSCODE-589 (#785)
  • Loading branch information
alenakhineika authored Aug 22, 2024
1 parent acc745f commit 934e830
Show file tree
Hide file tree
Showing 5 changed files with 247 additions and 70 deletions.
5 changes: 5 additions & 0 deletions src/connectionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,12 @@ export default class ConnectionController {
this._currentConnectionId = connectionId;
this._connectionAttempt = null;
this._connectingConnectionId = null;

this._connections[connectionId].lastUsed = new Date();
this.eventEmitter.emit(DataServiceEventTypes.ACTIVE_CONNECTION_CHANGED);
await this._connectionStorage.saveConnection(
this._connections[connectionId]
);

// Send metrics to Segment
this.sendTelemetry(dataService, connectionType);
Expand Down
5 changes: 1 addition & 4 deletions src/explorer/connectionTreeItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,7 @@ export default class ConnectionTreeItem
}

try {
const dbs = await dataService.listDatabases({
nameOnly: true,
});

const dbs = await dataService.listDatabases();
return dbs.map((dbItem) => dbItem.name);
} catch (error) {
throw new Error(
Expand Down
162 changes: 126 additions & 36 deletions src/participant/participant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,19 @@ interface ChatResult extends vscode.ChatResult {
};
}

interface NamespaceQuickPicks {
label: string;
data: string;
}

const DB_NAME_ID = 'DATABASE_NAME';
const DB_NAME_REGEX = `${DB_NAME_ID}: (.*)\n`;

const COL_NAME_ID = 'COLLECTION_NAME';
const COL_NAME_REGEX = `${COL_NAME_ID}: (.*)`;

const MAX_MARKDOWN_LIST_LENGTH = 10;

export function parseForDatabaseAndCollectionName(text: string): {
databaseName?: string;
collectionName?: string;
Expand Down Expand Up @@ -226,7 +233,7 @@ export default class ParticipantController {

async connectWithParticipant(id?: string): Promise<boolean> {
if (!id) {
await this._connectionController.connectWithURI();
await this._connectionController.changeActiveConnection();
} else {
await this._connectionController.connectWithConnectionId(id);
}
Expand Down Expand Up @@ -259,47 +266,113 @@ export default class ParticipantController {
return connName;
}

// TODO (VSCODE-589): Evaluate the usability of displaying all existing connections in the list.
// Consider introducing a "recent connections" feature to display only a limited number of recent connections,
// with a "Show more" link that opens the Command Palette for access to the full list.
// If we implement this, the "Add new connection" link may become redundant,
// as this option is already available in the Command Palette dropdown.
getConnectionsTree(): vscode.MarkdownString[] {
return [
this._createMarkdownLink({
commandId: 'mdb.connectWithParticipant',
name: 'Add new connection',
}),
...this._connectionController
.getSavedConnections()
.sort((connectionA: LoadedConnection, connectionB: LoadedConnection) =>
(connectionA.name || '').localeCompare(connectionB.name || '')
)
.sort((a, b) => {
const aTime = a.lastUsed ? new Date(a.lastUsed).getTime() : 0;
const bTime = b.lastUsed ? new Date(b.lastUsed).getTime() : 0;
return bTime - aTime;
})
.slice(0, MAX_MARKDOWN_LIST_LENGTH)
.map((conn: LoadedConnection) =>
this._createMarkdownLink({
commandId: 'mdb.connectWithParticipant',
query: conn.id,
name: conn.name,
})
),
this._createMarkdownLink({
commandId: 'mdb.connectWithParticipant',
name: 'Show more',
}),
];
}

async getDatabaseQuickPicks(): Promise<NamespaceQuickPicks[]> {
const dataService = this._connectionController.getActiveDataService();
if (!dataService) {
this._queryGenerationState = QUERY_GENERATION_STATE.ASK_TO_CONNECT;
return [];
}

try {
const databases = await dataService.listDatabases();
return databases.map((db) => ({
label: db.name,
data: db.name,
}));
} catch (error) {
return [];
}
}

async _selectDatabaseWithCommandPalette(): Promise<string | undefined> {
const databases = await this.getDatabaseQuickPicks();
const selectedQuickPickItem = await vscode.window.showQuickPick(databases, {
placeHolder: 'Select a database...',
});
return selectedQuickPickItem?.data;
}

async selectDatabaseWithParticipant(name: string): Promise<boolean> {
this._databaseName = name;
if (!name) {
this._databaseName = await this._selectDatabaseWithCommandPalette();
} else {
this._databaseName = name;
}

return vscode.commands.executeCommand('workbench.action.chat.open', {
query: `@MongoDB /query ${name}`,
query: `@MongoDB /query ${this._databaseName || ''}`,
});
}

async getCollectionQuickPicks(): Promise<NamespaceQuickPicks[]> {
if (!this._databaseName) {
return [];
}

const dataService = this._connectionController.getActiveDataService();
if (!dataService) {
this._queryGenerationState = QUERY_GENERATION_STATE.ASK_TO_CONNECT;
return [];
}

try {
const collections = await dataService.listCollections(this._databaseName);
return collections.map((db) => ({
label: db.name,
data: db.name,
}));
} catch (error) {
return [];
}
}

async _selectCollectionWithCommandPalette(): Promise<string | undefined> {
const collections = await this.getCollectionQuickPicks();
const selectedQuickPickItem = await vscode.window.showQuickPick(
collections,
{
placeHolder: 'Select a collection...',
}
);
return selectedQuickPickItem?.data;
}

async selectCollectionWithParticipant(name: string): Promise<boolean> {
this._collectionName = name;
if (!name) {
this._collectionName = await this._selectCollectionWithCommandPalette();
} else {
this._collectionName = name;
}

return vscode.commands.executeCommand('workbench.action.chat.open', {
query: `@MongoDB /query ${name}`,
query: `@MongoDB /query ${this._collectionName || ''}`,
});
}

// TODO (VSCODE-589): Display only 10 items in clickable lists with the show more option.
async getDatabasesTree(): Promise<vscode.MarkdownString[]> {
const dataService = this._connectionController.getActiveDataService();
if (!dataService) {
Expand All @@ -308,23 +381,30 @@ export default class ParticipantController {
}

try {
const databases = await dataService.listDatabases({
nameOnly: true,
});
return databases.map((db) =>
this._createMarkdownLink({
commandId: 'mdb.selectDatabaseWithParticipant',
query: db.name,
name: db.name,
})
);
const databases = await dataService.listDatabases();
return [
...databases.slice(0, MAX_MARKDOWN_LIST_LENGTH).map((db) =>
this._createMarkdownLink({
commandId: 'mdb.selectDatabaseWithParticipant',
query: db.name,
name: db.name,
})
),
...(databases.length > MAX_MARKDOWN_LIST_LENGTH
? [
this._createMarkdownLink({
commandId: 'mdb.selectDatabaseWithParticipant',
name: 'Show more',
}),
]
: []),
];
} catch (error) {
// Users can always do this manually when asked to provide a database name.
return [];
}
}

// TODO (VSCODE-589): Display only 10 items in clickable lists with the show more option.
async getCollectionTree(): Promise<vscode.MarkdownString[]> {
if (!this._databaseName) {
return [];
Expand All @@ -338,13 +418,23 @@ export default class ParticipantController {

try {
const collections = await dataService.listCollections(this._databaseName);
return collections.map((coll) =>
this._createMarkdownLink({
commandId: 'mdb.selectCollectionWithParticipant',
query: coll.name,
name: coll.name,
})
);
return [
...collections.slice(0, MAX_MARKDOWN_LIST_LENGTH).map((coll) =>
this._createMarkdownLink({
commandId: 'mdb.selectCollectionWithParticipant',
query: coll.name,
name: coll.name,
})
),
...(collections.length > MAX_MARKDOWN_LIST_LENGTH
? [
this._createMarkdownLink({
commandId: 'mdb.selectCollectionWithParticipant',
name: 'Show more',
}),
]
: []),
];
} catch (error) {
// Users can always do this manually when asked to provide a collection name.
return [];
Expand Down
1 change: 1 addition & 0 deletions src/storage/connectionStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface StoreConnectionInfo {
storageLocation: StorageLocation;
secretStorageLocation?: SecretStorageLocationType;
connectionOptions?: ConnectionOptions;
lastUsed?: Date; // Date and time when the connection was last used, i.e. connected with.
}

type StoreConnectionInfoWithConnectionOptions = StoreConnectionInfo &
Expand Down
Loading

0 comments on commit 934e830

Please sign in to comment.