Skip to content

Commit 64b2aba

Browse files
VSCODE-183: Edit documents from collection (#239)
* feat: edit documents from the collection view (VSCODE-183) * feat: track document edited from collectionview * refactor: update public and private functions for editors * feat: handle identical namespaces for different connections * test: import sinon and mock active editor
1 parent 07827e3 commit 64b2aba

33 files changed

+1318
-688
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ MongoDB for VS Code makes it easy to work with MongoDB, whether your own instanc
88

99
### Navigate your MongoDB Data
1010

11-
- Navigate your database, collections and read-only views
11+
- Navigate your databases, collections, and read-only views
1212
- See the documents in your collections
1313
- Edit documents and save changes to the database
1414
- Get a quick overview of your schema and your indexes
@@ -21,8 +21,9 @@ MongoDB Playgrounds are the most convenient way to prototype and execute CRUD op
2121

2222
- Prototype your queries, aggregations, and MongoDB commands with MongoDB syntax highlighting and intelligent autocomplete for MongoDB shell API, MongoDB operators, and for database, collection, and field names.
2323
- Run your playgrounds and see the results instantly. Click the play button in the tab bar to see the output.
24-
- Save your playgrounds in your workspace and use them to document how your application interacts with MongoDB
25-
- Build aggregations quickly with helpful and well-commented stage snippets
24+
- Edit documents returned by your playground.
25+
- Save your playgrounds in your workspace and use them to document how your application interacts with MongoDB.
26+
- Build aggregations quickly with helpful and well-commented stage snippets.
2627

2728
![Playgrounds](resources/screenshots/playground.png)
2829

src/commands/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ enum EXTENSION_COMMANDS {
1414
MDB_RUN_ALL_PLAYGROUND_BLOCKS = 'mdb.runAllPlaygroundBlocks',
1515
MDB_RUN_ALL_OR_SELECTED_PLAYGROUND_BLOCKS = 'mdb.runPlayground',
1616

17-
MDB_OPEN_MONGODB_DOCUMENT_FROM_PLAYGROUND = 'mdb.openMongoDBDocumentFromPlayground',
17+
MDB_OPEN_MONGODB_DOCUMENT_FROM_CODE_LENS = 'mdb.openMongoDBDocumentFromCodeLens',
1818
MDB_OPEN_MONGODB_DOCUMENT_FROM_TREE = 'mdb.openMongoDBDocumentFromTree',
1919
MDB_SAVE_MONGODB_DOCUMENT = 'mdb.saveMongoDBDocument',
2020

src/editors/collectionDocumentsCodeLensProvider.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ import {
1010
} from './collectionDocumentsProvider';
1111

1212
export default class CollectionDocumentsCodeLensProvider implements vscode.CodeLensProvider {
13-
private _codeLenses: vscode.CodeLens[] = [];
14-
private _activeOperationsStore: CollectionDocumentsOperationStore;
15-
private uri: vscode.Uri = vscode.Uri.parse('');
16-
private _onDidChangeCodeLenses: vscode.EventEmitter<
13+
_codeLenses: vscode.CodeLens[] = [];
14+
_activeOperationsStore: CollectionDocumentsOperationStore;
15+
_uri: vscode.Uri = vscode.Uri.parse('');
16+
_onDidChangeCodeLenses: vscode.EventEmitter<
1717
void
1818
> = new vscode.EventEmitter<void>();
19-
public readonly onDidChangeCodeLenses: vscode.Event<void> = this
19+
readonly onDidChangeCodeLenses: vscode.Event<void> = this
2020
._onDidChangeCodeLenses.event;
2121

2222
constructor(operationsStore: CollectionDocumentsOperationStore) {
@@ -27,9 +27,10 @@ export default class CollectionDocumentsCodeLensProvider implements vscode.CodeL
2727
});
2828
}
2929

30-
public provideCodeLenses(document: vscode.TextDocument): vscode.CodeLens[] {
30+
provideCodeLenses(document: vscode.TextDocument): vscode.CodeLens[] {
3131
const uriParams = new URLSearchParams(document.uri.query);
3232
const operationId = uriParams.get(OPERATION_ID_URI_IDENTIFIER);
33+
3334
if (!operationId) {
3435
return [];
3536
}
@@ -52,27 +53,27 @@ export default class CollectionDocumentsCodeLensProvider implements vscode.CodeL
5253
)
5354
];
5455

55-
this.uri = document.uri;
56+
this._uri = document.uri;
5657

5758
return this._codeLenses;
5859
}
5960

60-
public resolveCodeLens?(codeLens: vscode.CodeLens): vscode.CodeLens {
61-
const uriParams = new URLSearchParams(this.uri.query);
62-
61+
resolveCodeLens?(codeLens: vscode.CodeLens): vscode.CodeLens {
62+
const uriParams = new URLSearchParams(this._uri.query);
6363
const namespace = uriParams.get(NAMESPACE_URI_IDENTIFIER);
6464
const connectionId = uriParams.get(CONNECTION_ID_URI_IDENTIFIER);
6565
const operationId = uriParams.get(OPERATION_ID_URI_IDENTIFIER);
6666

6767
if (!operationId) {
6868
return codeLens;
6969
}
70-
const operation = this._activeOperationsStore.operations[operationId];
7170

71+
const operation = this._activeOperationsStore.operations[operationId];
7272
const amountOfDocs = operation.currentLimit;
7373

7474
let commandTitle;
7575
let commandTooltip;
76+
7677
if (operation.isCurrentlyFetchingMoreDocuments) {
7778
commandTitle = `... Fetching ${amountOfDocs} documents...`;
7879
commandTooltip =

src/editors/collectionDocumentsProvider.ts

Lines changed: 74 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import * as vscode from 'vscode';
44
import CollectionDocumentsOperationsStore from './collectionDocumentsOperationsStore';
55
import ConnectionController from '../connectionController';
66
import { StatusView } from '../views';
7+
import * as util from 'util';
8+
import EditDocumentCodeLensProvider from './editDocumentCodeLensProvider';
79

810
export const NAMESPACE_URI_IDENTIFIER = 'namespace';
911
export const OPERATION_ID_URI_IDENTIFIER = 'operationId';
@@ -13,84 +15,102 @@ export const VIEW_COLLECTION_SCHEME = 'VIEW_COLLECTION_SCHEME';
1315

1416
export default class CollectionViewProvider
1517
implements vscode.TextDocumentContentProvider {
18+
_context: vscode.ExtensionContext;
1619
_connectionController: ConnectionController;
1720
_operationsStore: CollectionDocumentsOperationsStore;
1821
_statusView: StatusView;
22+
_editDocumentCodeLensProvider: EditDocumentCodeLensProvider;
1923

2024
constructor(
25+
context: vscode.ExtensionContext,
2126
connectionController: ConnectionController,
2227
operationsStore: CollectionDocumentsOperationsStore,
23-
statusView: StatusView
28+
statusView: StatusView,
29+
editDocumentCodeLensProvider: EditDocumentCodeLensProvider
2430
) {
31+
this._context = context;
2532
this._connectionController = connectionController;
2633
this._operationsStore = operationsStore;
2734
this._statusView = statusView;
35+
this._editDocumentCodeLensProvider = editDocumentCodeLensProvider;
2836
}
2937

3038
onDidChangeEmitter = new vscode.EventEmitter<vscode.Uri>();
3139
onDidChange = this.onDidChangeEmitter.event;
3240

33-
provideTextDocumentContent(uri: vscode.Uri): Promise<string> {
34-
return new Promise((resolve, reject) => {
35-
const uriParams = new URLSearchParams(uri.query);
36-
const namespace = String(uriParams.get(NAMESPACE_URI_IDENTIFIER));
37-
const connectionId = uriParams.get(CONNECTION_ID_URI_IDENTIFIER);
38-
const operationId = uriParams.get(OPERATION_ID_URI_IDENTIFIER);
39-
40-
if (!operationId) {
41-
vscode.window.showErrorMessage(
42-
'Unable to list documents: invalid operation'
43-
);
44-
return reject(new Error('Unable to list documents: invalid operation'));
45-
}
41+
async provideTextDocumentContent(uri: vscode.Uri): Promise<string> {
42+
const uriParams = new URLSearchParams(uri.query);
43+
const namespace = String(uriParams.get(NAMESPACE_URI_IDENTIFIER));
44+
const connectionId = uriParams.get(CONNECTION_ID_URI_IDENTIFIER);
45+
const operationId = uriParams.get(OPERATION_ID_URI_IDENTIFIER);
4646

47-
const operation = this._operationsStore.operations[operationId];
48-
const documentLimit = operation.currentLimit;
49-
50-
// Ensure we're still connected to the correct connection.
51-
if (connectionId !== this._connectionController.getActiveConnectionId()) {
52-
operation.isCurrentlyFetchingMoreDocuments = false;
53-
vscode.window.showErrorMessage(
54-
`Unable to list documents: no longer connected to ${connectionId}`
55-
);
56-
return reject(
57-
new Error(
58-
`Unable to list documents: no longer connected to ${connectionId}`
59-
)
60-
);
61-
}
47+
if (!operationId) {
48+
vscode.window.showErrorMessage(
49+
'Unable to list documents: invalid operation'
50+
);
6251

63-
this._statusView.showMessage('Fetching documents...');
52+
throw new Error('Unable to list documents: invalid operation');
53+
}
6454

65-
const dataservice = this._connectionController.getActiveDataService();
66-
if (dataservice === null) {
67-
const errorMessage = `Unable to list documents: no longer connected to ${connectionId}`;
68-
vscode.window.showErrorMessage(errorMessage);
69-
return reject(new Error(errorMessage));
70-
}
71-
dataservice.find(
55+
const operation = this._operationsStore.operations[operationId];
56+
const documentLimit = operation.currentLimit;
57+
58+
// Ensure we're still connected to the correct connection.
59+
if (connectionId !== this._connectionController.getActiveConnectionId()) {
60+
operation.isCurrentlyFetchingMoreDocuments = false;
61+
vscode.window.showErrorMessage(
62+
`Unable to list documents: no longer connected to ${connectionId}`
63+
);
64+
65+
throw new Error(
66+
`Unable to list documents: no longer connected to ${connectionId}`
67+
);
68+
}
69+
70+
this._statusView.showMessage('Fetching documents...');
71+
72+
const dataservice = this._connectionController.getActiveDataService();
73+
74+
if (dataservice === null) {
75+
const errorMessage = `Unable to list documents: no longer connected to ${connectionId}`;
76+
77+
vscode.window.showErrorMessage(errorMessage);
78+
79+
throw new Error(errorMessage);
80+
}
81+
82+
const find = util.promisify(dataservice.find.bind(dataservice));
83+
84+
try {
85+
const documents = await find(
7286
namespace,
7387
{}, // No filter.
7488
{
7589
limit: documentLimit
76-
},
77-
(err: Error | undefined, documents: object[]) => {
78-
operation.isCurrentlyFetchingMoreDocuments = false;
79-
this._statusView.hideMessage();
80-
81-
if (err) {
82-
const errorMessage = `Unable to list documents: ${err.message}`;
83-
vscode.window.showErrorMessage(errorMessage);
84-
return reject(new Error(errorMessage));
85-
}
86-
87-
if (documents.length !== documentLimit) {
88-
operation.hasMoreDocumentsToShow = false;
89-
}
90-
91-
return resolve(JSON.stringify(documents, null, 2));
9290
}
9391
);
94-
});
92+
93+
operation.isCurrentlyFetchingMoreDocuments = false;
94+
this._statusView.hideMessage();
95+
96+
if (documents.length !== documentLimit) {
97+
operation.hasMoreDocumentsToShow = false;
98+
}
99+
100+
this._editDocumentCodeLensProvider.updateCodeLensesForCollection({
101+
content: documents,
102+
namespace,
103+
uri
104+
});
105+
106+
return JSON.stringify(documents, null, 2);
107+
} catch (error) {
108+
const printableError = error as { message: string };
109+
const errorMessage = `Unable to list documents: ${printableError.message}`;
110+
111+
vscode.window.showErrorMessage(errorMessage);
112+
113+
throw Error(errorMessage);
114+
}
95115
}
96116
}

0 commit comments

Comments
 (0)