Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tree-explorer): add buttons to ask Copilot and create playgrounds from tree view VSCODE-651 #890

Merged
merged 39 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
86d25b7
WIP
gagik Nov 21, 2024
6feac32
add query codelens and shorten wording
gagik Nov 22, 2024
b1adb2a
Merge branch 'main' of github.com:mongodb-js/vscode into gagik/query-…
gagik Nov 22, 2024
474beb3
revert vscode change
gagik Nov 22, 2024
e915b3f
wording change
gagik Nov 22, 2024
e17008f
Add icons to connect to MongoDB
gagik Nov 25, 2024
27f0aad
Fix tests
gagik Nov 25, 2024
a8bcf84
Merge branch 'main' of github.com:mongodb-js/vscode into gagik/query-…
gagik Nov 25, 2024
bce4de9
check for copilot extension, not chat
gagik Nov 25, 2024
99128f5
Add namespacing
gagik Nov 26, 2024
b7f9618
add codelens telemetry
gagik Nov 27, 2024
245121f
WIP demo icons
gagik Nov 27, 2024
a9c2836
Update src/editors/queryWithCopilotCodeLensProvider.ts
gagik Nov 27, 2024
d4c9d6d
WIP
gagik Nov 28, 2024
b0ca543
use DocumentSource
gagik Nov 28, 2024
c870786
use document source
gagik Nov 28, 2024
145af8d
use sendMessage in extensionController
gagik Nov 28, 2024
692dc1c
change srv text
gagik Nov 28, 2024
fb02705
Merge branch 'gagik/query-codelens' of github.com:mongodb-js/vscode i…
gagik Nov 28, 2024
1d1f0a3
Merge branch 'gagik/query-codelens' of github.com:mongodb-js/vscode i…
gagik Nov 28, 2024
f827164
Merge branch 'gagik/add-icons' of github.com:mongodb-js/vscode into g…
gagik Nov 28, 2024
3e8bd0e
WIP
gagik Nov 28, 2024
2b079ce
Merge branch 'main' of github.com:mongodb-js/vscode into gagik/add-pl…
gagik Nov 28, 2024
f22248f
move to participant
gagik Nov 28, 2024
44a7eea
remove test related changes
gagik Nov 28, 2024
68c4482
remove more test code
gagik Nov 29, 2024
efb1432
fix test
gagik Nov 29, 2024
93fb8f8
add tests
gagik Nov 29, 2024
aeee828
only range
gagik Nov 29, 2024
f30c1f4
use Promise<void>
gagik Dec 2, 2024
e7a1d08
Apply changes from feedback
gagik Dec 3, 2024
8c9347e
remove playground shortcut
gagik Dec 3, 2024
7fa46fe
use new database name
gagik Dec 3, 2024
4a6df5a
Remove redundant changes
gagik Dec 3, 2024
09c68ee
changes from feedback
gagik Dec 4, 2024
9c9ffc0
expect one call
gagik Dec 4, 2024
11cf234
fix tests
gagik Dec 4, 2024
1bb6491
Merge branch 'main' into gagik/add-playground-buttons
gagik Dec 6, 2024
a805fd2
remove line and use COPILOT_EXTENSION_ID
gagik Dec 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Place your settings in this file to overwrite default and user settings.
{
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
Expand Down
Binary file modified fonts/mongodb-icons.woff
Binary file not shown.
1 change: 1 addition & 0 deletions images/icons/playground.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
72 changes: 52 additions & 20 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,11 @@
"dark": "images/dark/add.svg"
}
},
{
"command": "mdb.createNewPlaygroundFromConnectionTreeView",
"title": "Create MongoDB Playground",
"icon": "$(mdb-playground)"
},
{
"command": "mdb.changeActiveConnection",
"title": "MongoDB: Change Active Connection"
Expand Down Expand Up @@ -330,10 +335,7 @@
{
"command": "mdb.addDatabase",
"title": "Add Database...",
"icon": {
"light": "images/light/plus-circle.svg",
"dark": "images/dark/plus-circle.svg"
}
"icon": "$(mdb-plus-circle)"
},
{
"command": "mdb.searchForDocuments",
Expand Down Expand Up @@ -371,13 +373,15 @@
"command": "mdb.refreshDatabase",
"title": "Refresh"
},
{
"command": "mdb.askCopilotFromTreeItem",
"title": "Ask MongoDB Copilot",
"icon": "$(copilot)"
},
{
"command": "mdb.addCollection",
"title": "Add Collection...",
"icon": {
"light": "images/light/plus-circle.svg",
"dark": "images/dark/plus-circle.svg"
}
"icon": "$(mdb-plus-circle)"
},
{
"command": "mdb.viewCollectionDocuments",
Expand Down Expand Up @@ -422,10 +426,7 @@
{
"command": "mdb.createIndexFromTreeView",
"title": "Create New Index...",
"icon": {
"light": "images/light/plus-circle.svg",
"dark": "images/dark/plus-circle.svg"
}
"icon": "$(mdb-plus-circle)"
},
{
"command": "mdb.insertObjectIdToEditor",
Expand Down Expand Up @@ -454,10 +455,7 @@
{
"command": "mdb.addStreamProcessor",
"title": "Add StreamProcessor...",
"icon": {
"light": "images/light/plus-circle.svg",
"dark": "images/dark/plus-circle.svg"
}
"icon": "$(mdb-plus-circle)"
},
{
"command": "mdb.startStreamProcessor",
Expand Down Expand Up @@ -587,7 +585,7 @@
{
"command": "mdb.addCollection",
"when": "view == mongoDBConnectionExplorer && viewItem == databaseTreeItem",
"group": "inline"
"group": "inline@3"
},
{
"command": "mdb.addCollection",
Expand All @@ -604,10 +602,30 @@
"when": "view == mongoDBConnectionExplorer && viewItem == databaseTreeItem",
"group": "2@1"
},
{
"command": "mdb.askCopilotFromTreeItem",
"when": "mdb.isCopilotActive == true && view == mongoDBConnectionExplorer && (viewItem == databaseTreeItem || viewItem == collectionTreeItem)",
"group": "inline@1"
},
{
"command": "mdb.askCopilotFromTreeItem",
"when": "mdb.isCopilotActive == true && view == mongoDBConnectionExplorer && (viewItem == databaseTreeItem || viewItem == collectionTreeItem)",
"group": "3@1"
},
{
"command": "mdb.createNewPlaygroundFromConnectionTreeView",
"when": "view == mongoDBConnectionExplorer && (viewItem == databaseTreeItem || viewItem == collectionTreeItem)",
"group": "inline@2"
},
{
"command": "mdb.createNewPlaygroundFromConnectionTreeView",
"when": "view == mongoDBConnectionExplorer && (viewItem == databaseTreeItem || viewItem == collectionTreeItem)",
"group": "3@2"
},
{
"command": "mdb.dropDatabase",
"when": "view == mongoDBConnectionExplorer && viewItem == databaseTreeItem",
"group": "3@1"
"group": "4@1"
},
{
"command": "mdb.viewCollectionDocuments",
Expand Down Expand Up @@ -1157,19 +1175,33 @@
}
},
"icons": {
"mdb-connection-active": {
"mdb-playground": {
"description": "MongoDB Icon",
"default": {
"fontPath": "./fonts/mongodb-icons.woff",
"fontCharacter": "\\ea01"
}
},
"mdb-connection-inactive": {
"mdb-plus-circle": {
"description": "MongoDB Icon",
"default": {
"fontPath": "./fonts/mongodb-icons.woff",
"fontCharacter": "\\ea02"
}
},
"mdb-connection-active": {
"description": "MongoDB Icon",
"default": {
"fontPath": "./fonts/mongodb-icons.woff",
"fontCharacter": "\\ea03"
}
},
"mdb-connection-inactive": {
"description": "MongoDB Icon",
"default": {
"fontPath": "./fonts/mongodb-icons.woff",
"fontCharacter": "\\ea04"
}
}
}
},
Expand Down
15 changes: 13 additions & 2 deletions scripts/generate-icon-font.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import fs from 'fs/promises';
import { GlyphData } from 'webfont/dist/src/types';

/** Icons to include in the generated icon font */
const INCLUDED_ICONS = ['connection-active', 'connection-inactive'];
const INCLUDED_ICONS = [
'light/connection-active',
'light/connection-inactive',
'playground',
'plus-circle',
];

/**
* Generates an icon font from the included icons and outputs package.json
Expand All @@ -12,7 +17,13 @@ const INCLUDED_ICONS = ['connection-active', 'connection-inactive'];
*/
async function main(): Promise<void> {
const font = await webfont({
files: INCLUDED_ICONS.map((icon) => `./images/light/${icon}.svg`),
files: INCLUDED_ICONS.map((icon) => {
// Legacy support for icons inside light and dark folders.
if (icon.startsWith('light/')) {
return `./images/${icon}.svg`;
}
return `./images/icons/${icon}.svg`;
}),
fontName: 'MongoDB Icons',
formats: ['woff'],
normalize: true,
Expand Down
2 changes: 2 additions & 0 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ enum EXTENSION_COMMANDS {
MDB_OPEN_PLAYGROUND_FROM_TREE_VIEW = 'mdb.openPlaygroundFromTreeView',
MDB_CONNECT_TO_CONNECTION_TREE_VIEW = 'mdb.connectToConnectionTreeItem',
MDB_CREATE_PLAYGROUND_FROM_TREE_VIEW = 'mdb.createNewPlaygroundFromTreeView',
MDB_CREATE_PLAYGROUND_FROM_CONNECTION_TREE_VIEW = 'mdb.createNewPlaygroundFromConnectionTreeView',
MDB_DISCONNECT_FROM_CONNECTION_TREE_VIEW = 'mdb.disconnectFromConnectionTreeItem',
MDB_EDIT_CONNECTION = 'mdb.editConnection',
MDB_REFRESH_CONNECTION = 'mdb.refreshConnection',
Expand Down Expand Up @@ -75,6 +76,7 @@ enum EXTENSION_COMMANDS {
OPEN_PARTICIPANT_CODE_IN_PLAYGROUND = 'mdb.openParticipantCodeInPlayground',
SEND_MESSAGE_TO_PARTICIPANT = 'mdb.sendMessageToParticipant',
SEND_MESSAGE_TO_PARTICIPANT_FROM_INPUT = 'mdb.sendMessageToParticipantFromInput',
ASK_COPILOT_FROM_TREE_ITEM = 'mdb.askCopilotFromTreeItem',
RUN_PARTICIPANT_CODE = 'mdb.runParticipantCode',
CONNECT_WITH_PARTICIPANT = 'mdb.connectWithParticipant',
SELECT_DATABASE_WITH_PARTICIPANT = 'mdb.selectDatabaseWithParticipant',
Expand Down
32 changes: 29 additions & 3 deletions src/editors/playgroundController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type ConnectionController from '../connectionController';
import { DataServiceEventTypes } from '../connectionController';
import { createLogger } from '../logging';
import type { ConnectionTreeItem } from '../explorer';
import { CollectionTreeItem } from '../explorer';
import { DatabaseTreeItem } from '../explorer';
import formatError from '../utils/formatError';
import type { LanguageServerController } from '../language';
Expand Down Expand Up @@ -41,6 +42,8 @@ import {
getPlaygroundExtensionForTelemetry,
} from '../utils/playground';
import type ExportToLanguageCodeLensProvider from './exportToLanguageCodeLensProvider';
import { playgroundFromDatabaseTreeItemTemplate } from '../templates/playgroundFromDatabaseTreeItemTemplate';
import { playgroundFromCollectionTreeItemTemplate } from '../templates/playgroundFromCollectionTreeItemTemplate';

const log = createLogger('playground controller');

Expand Down Expand Up @@ -316,13 +319,36 @@ export default class PlaygroundController {
return this._createPlaygroundFileWithContent(content);
}

async createPlaygroundFromTreeView(
treeItem: DatabaseTreeItem | CollectionTreeItem
): Promise<boolean> {
let content = '';
if (treeItem instanceof DatabaseTreeItem) {
content = playgroundFromDatabaseTreeItemTemplate(treeItem.databaseName);
this._telemetryService.trackPlaygroundCreated('fromDatabaseTreeItem');
} else if (treeItem instanceof CollectionTreeItem) {
content = playgroundFromCollectionTreeItemTemplate(
treeItem.databaseName,
treeItem.collectionName
);
this._telemetryService.trackPlaygroundCreated('fromCollectionTreeItem');
}

return this._createPlaygroundFileWithContent(content);
}

async createPlayground(): Promise<boolean> {
const useDefaultTemplate = !!vscode.workspace
.getConfiguration('mdb')
.get('useDefaultTemplateForPlayground');
const isStreams = this._connectionController.isConnectedToAtlasStreams();
const template = isStreams ? playgroundStreamsTemplate : playgroundTemplate;
const content = useDefaultTemplate ? template : '';
let content = '';
if (useDefaultTemplate) {
const isStreams = this._connectionController.isConnectedToAtlasStreams();
const template = isStreams
? playgroundStreamsTemplate
: playgroundTemplate;
content = template;
}

this._telemetryService.trackPlaygroundCreated('crud');
return this._createPlaygroundFileWithContent(content);
Expand Down
3 changes: 2 additions & 1 deletion src/editors/playgroundSelectionCodeActionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as vscode from 'vscode';

import EXTENSION_COMMANDS from '../commands';
import { isPlayground, getSelectedText } from '../utils/playground';
import { COPILOT_CHAT_EXTENSION_ID } from '../participant/constants';

export const EXPORT_TO_LANGUAGE_ALIASES = [
{ id: 'csharp', alias: 'C#' },
Expand Down Expand Up @@ -42,7 +43,7 @@ export default class PlaygroundSelectionCodeActionProvider

provideCodeActions(): vscode.CodeAction[] | undefined {
const editor = vscode.window.activeTextEditor;
const copilot = vscode.extensions.getExtension('github.copilot-chat');
const copilot = vscode.extensions.getExtension(COPILOT_CHAT_EXTENSION_ID);
let codeActions: vscode.CodeAction[] = [
this.createCodeAction({
title: 'Run selected playground blocks',
Expand Down
28 changes: 27 additions & 1 deletion src/mdbExtensionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import type {
SendMessageToParticipantOptions,
SendMessageToParticipantFromInputOptions,
} from './participant/participantTypes';
import { COPILOT_CHAT_EXTENSION_ID } from './participant/constants';

// This class is the top-level controller for our extension.
// Commands which the extensions handles are defined in the function `activate`.
Expand Down Expand Up @@ -183,6 +184,19 @@ export default class MDBExtensionController implements vscode.Disposable {
'mdb.isCopilotActive',
copilot?.isActive
);

// TODO: This is a workaround related to https://github.com/microsoft/vscode/issues/234426
// If the extension was found but is not activated, there is a chance that the MongoDB extension
// was activated before the Copilot one, so we check again after a delay.
if (copilot && !copilot?.isActive) {
setTimeout(() => {
void vscode.commands.executeCommand(
'setContext',
'mdb.isCopilotActive',
copilot?.isActive === true
);
}, 3000);
}
}

registerCommands = (): void => {
Expand Down Expand Up @@ -330,6 +344,13 @@ export default class MDBExtensionController implements vscode.Disposable {
return true;
}
);
this.registerParticipantCommand(
EXTENSION_COMMANDS.ASK_COPILOT_FROM_TREE_ITEM,
async (treeItem: DatabaseTreeItem) => {
gagik marked this conversation as resolved.
Show resolved Hide resolved
await this._participantController.askCopilotFromTreeItem(treeItem);
return true;
}
);
this.registerParticipantCommand(
EXTENSION_COMMANDS.RUN_PARTICIPANT_CODE,
({ runnableContent }: RunParticipantCodeCommandArgs) => {
Expand Down Expand Up @@ -742,6 +763,11 @@ export default class MDBExtensionController implements vscode.Disposable {
EXTENSION_COMMANDS.MDB_CREATE_PLAYGROUND_FROM_TREE_VIEW,
() => this._playgroundController.createPlayground()
);
this.registerCommand(
EXTENSION_COMMANDS.MDB_CREATE_PLAYGROUND_FROM_CONNECTION_TREE_VIEW,
(treeItem: DatabaseTreeItem | CollectionTreeItem) =>
this._playgroundController.createPlaygroundFromTreeView(treeItem)
gagik marked this conversation as resolved.
Show resolved Hide resolved
);
this.registerCommand(
EXTENSION_COMMANDS.MDB_REFRESH_PLAYGROUNDS_FROM_TREE_VIEW,
() => this._playgroundsExplorer.refresh()
Expand Down Expand Up @@ -972,7 +998,7 @@ export default class MDBExtensionController implements vscode.Disposable {
}
);

const copilot = vscode.extensions.getExtension('github.copilot-chat');
const copilot = vscode.extensions.getExtension(COPILOT_CHAT_EXTENSION_ID);
if (result?.title === action) {
await this._participantController.sendMessageToParticipant({
message: '',
Expand Down
1 change: 1 addition & 0 deletions src/participant/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ChatMetadataStore } from './chatMetadata';
export const CHAT_PARTICIPANT_ID = 'mongodb.participant';
export const CHAT_PARTICIPANT_MODEL = 'gpt-4o';
export const COPILOT_EXTENSION_ID = 'GitHub.copilot';
export const COPILOT_CHAT_EXTENSION_ID = 'GitHub.copilot-chat';

export type ParticipantResponseType =
| 'query'
Expand Down
Loading
Loading