@mongoosejs/studio 0.1.17 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/backend/actions/Model/getCollectionInfo.js +49 -0
- package/backend/actions/Model/index.js +1 -0
- package/frontend/public/app.js +15088 -480
- package/frontend/public/tw.css +6 -0
- package/frontend/src/api.js +7 -1
- package/frontend/src/chat/chat-message/chat-message.js +2 -8
- package/frontend/src/chat/chat-message-script/chat-message-script.js +4 -8
- package/frontend/src/chat/chat.js +5 -8
- package/frontend/src/clone-document/clone-document.js +7 -5
- package/frontend/src/create-dashboard/create-dashboard.js +1 -0
- package/frontend/src/create-document/create-document.js +7 -5
- package/frontend/src/dashboard/dashboard.js +1 -0
- package/frontend/src/dashboard/edit-dashboard/edit-dashboard.js +1 -0
- package/frontend/src/dashboards/dashboards.js +1 -0
- package/frontend/src/document/document.js +21 -29
- package/frontend/src/document-details/document-details.js +1 -13
- package/frontend/src/export-query-results/export-query-results.js +1 -1
- package/frontend/src/index.js +13 -7
- package/frontend/src/list-default/list-default.js +1 -8
- package/frontend/src/list-mixed/list-mixed.js +1 -8
- package/frontend/src/list-string/list-string.js +1 -8
- package/frontend/src/list-subdocument/list-subdocument.js +1 -8
- package/frontend/src/models/models.html +77 -7
- package/frontend/src/models/models.js +75 -2
- package/frontend/src/update-document/update-document.js +21 -27
- package/package.json +3 -3
|
@@ -34,6 +34,7 @@ module.exports = app => app.component('models', {
|
|
|
34
34
|
shouldShowCreateModal: false,
|
|
35
35
|
shouldShowFieldModal: false,
|
|
36
36
|
shouldShowIndexModal: false,
|
|
37
|
+
shouldShowCollectionInfoModal: false,
|
|
37
38
|
shouldShowUpdateMultipleModal: false,
|
|
38
39
|
shouldShowDeleteMultipleModal: false,
|
|
39
40
|
shouldExport: {},
|
|
@@ -44,7 +45,9 @@ module.exports = app => app.component('models', {
|
|
|
44
45
|
outputType: 'table', // json, table
|
|
45
46
|
hideSidebar: null,
|
|
46
47
|
lastSelectedIndex: null,
|
|
47
|
-
error: null
|
|
48
|
+
error: null,
|
|
49
|
+
showActionsMenu: false,
|
|
50
|
+
collectionInfo: null
|
|
48
51
|
}),
|
|
49
52
|
created() {
|
|
50
53
|
this.currentModel = this.model;
|
|
@@ -53,12 +56,23 @@ module.exports = app => app.component('models', {
|
|
|
53
56
|
beforeDestroy() {
|
|
54
57
|
document.removeEventListener('scroll', this.onScroll, true);
|
|
55
58
|
window.removeEventListener('popstate', this.onPopState, true);
|
|
59
|
+
document.removeEventListener('click', this.onOutsideActionsMenuClick, true);
|
|
56
60
|
},
|
|
57
61
|
async mounted() {
|
|
58
62
|
this.onScroll = () => this.checkIfScrolledToBottom();
|
|
59
63
|
document.addEventListener('scroll', this.onScroll, true);
|
|
60
64
|
this.onPopState = () => this.initSearchFromUrl();
|
|
61
65
|
window.addEventListener('popstate', this.onPopState, true);
|
|
66
|
+
this.onOutsideActionsMenuClick = event => {
|
|
67
|
+
if (!this.showActionsMenu) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const actionsMenu = this.$refs.actionsMenuContainer;
|
|
71
|
+
if (actionsMenu && !actionsMenu.contains(event.target)) {
|
|
72
|
+
this.closeActionsMenu();
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
document.addEventListener('click', this.onOutsideActionsMenuClick, true);
|
|
62
76
|
const { models, readyState } = await api.Model.listModels();
|
|
63
77
|
this.models = models;
|
|
64
78
|
if (this.currentModel == null && this.models.length > 0) {
|
|
@@ -71,7 +85,7 @@ module.exports = app => app.component('models', {
|
|
|
71
85
|
this.error = 'No models found and Mongoose is not connected. Check our documentation for more information.';
|
|
72
86
|
}
|
|
73
87
|
}
|
|
74
|
-
|
|
88
|
+
|
|
75
89
|
await this.initSearchFromUrl();
|
|
76
90
|
},
|
|
77
91
|
computed: {
|
|
@@ -160,6 +174,7 @@ module.exports = app => app.component('models', {
|
|
|
160
174
|
async dropIndex(name) {
|
|
161
175
|
const { mongoDBIndexes } = await api.Model.dropIndex({ model: this.currentModel, name });
|
|
162
176
|
this.mongoDBIndexes = mongoDBIndexes;
|
|
177
|
+
this.$toast.success('Index dropped!');
|
|
163
178
|
},
|
|
164
179
|
async closeCreationModal() {
|
|
165
180
|
this.shouldShowCreateModal = false;
|
|
@@ -232,11 +247,38 @@ module.exports = app => app.component('models', {
|
|
|
232
247
|
}
|
|
233
248
|
},
|
|
234
249
|
async openIndexModal() {
|
|
250
|
+
this.closeActionsMenu();
|
|
235
251
|
this.shouldShowIndexModal = true;
|
|
236
252
|
const { mongoDBIndexes, schemaIndexes } = await api.Model.getIndexes({ model: this.currentModel });
|
|
237
253
|
this.mongoDBIndexes = mongoDBIndexes;
|
|
238
254
|
this.schemaIndexes = schemaIndexes;
|
|
239
255
|
},
|
|
256
|
+
toggleActionsMenu() {
|
|
257
|
+
this.showActionsMenu = !this.showActionsMenu;
|
|
258
|
+
},
|
|
259
|
+
closeActionsMenu() {
|
|
260
|
+
this.showActionsMenu = false;
|
|
261
|
+
},
|
|
262
|
+
async openCollectionInfo() {
|
|
263
|
+
this.closeActionsMenu();
|
|
264
|
+
this.shouldShowCollectionInfoModal = true;
|
|
265
|
+
this.collectionInfo = null;
|
|
266
|
+
const { info } = await api.Model.getCollectionInfo({ model: this.currentModel });
|
|
267
|
+
this.collectionInfo = info;
|
|
268
|
+
},
|
|
269
|
+
async findOldestDocument() {
|
|
270
|
+
this.closeActionsMenu();
|
|
271
|
+
const { docs } = await api.Model.getDocuments({
|
|
272
|
+
model: this.currentModel,
|
|
273
|
+
limit: 1,
|
|
274
|
+
sortKey: '_id',
|
|
275
|
+
sortDirection: 1
|
|
276
|
+
});
|
|
277
|
+
if (!Array.isArray(docs) || docs.length === 0) {
|
|
278
|
+
throw new Error('No documents found');
|
|
279
|
+
}
|
|
280
|
+
this.openDocument(docs[0]);
|
|
281
|
+
},
|
|
240
282
|
isTTLIndex(index) {
|
|
241
283
|
return index != null && index.expireAfterSeconds != null;
|
|
242
284
|
},
|
|
@@ -269,6 +311,35 @@ module.exports = app => app.component('models', {
|
|
|
269
311
|
|
|
270
312
|
return parts.join(', ');
|
|
271
313
|
},
|
|
314
|
+
formatCollectionSize(size) {
|
|
315
|
+
if (typeof size !== 'number') {
|
|
316
|
+
return 'Unknown';
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const KB = 1024;
|
|
320
|
+
const MB = KB * 1024;
|
|
321
|
+
const GB = MB * 1024;
|
|
322
|
+
const TB = GB * 1024;
|
|
323
|
+
|
|
324
|
+
if (size >= TB) {
|
|
325
|
+
return `${(size / TB).toFixed(3)} TB`;
|
|
326
|
+
} else if (size >= GB) {
|
|
327
|
+
return `${(size / GB).toFixed(3)} GB`;
|
|
328
|
+
} else if (size >= MB) {
|
|
329
|
+
return `${(size / MB).toFixed(3)} MB`;
|
|
330
|
+
} else if (size >= KB) {
|
|
331
|
+
return `${(size / KB).toFixed(3)} KB`;
|
|
332
|
+
} else {
|
|
333
|
+
return `${size.toLocaleString()} bytes`;
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
formatNumber(value) {
|
|
337
|
+
if (typeof value !== 'number') {
|
|
338
|
+
return 'Unknown';
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return value.toLocaleString();
|
|
342
|
+
},
|
|
272
343
|
checkIndexLocation(indexName) {
|
|
273
344
|
if (this.schemaIndexes.find(x => x.name == indexName) && this.mongoDBIndexes.find(x => x.name == indexName)) {
|
|
274
345
|
return 'text-gray-500';
|
|
@@ -442,6 +513,7 @@ module.exports = app => app.component('models', {
|
|
|
442
513
|
this.documents[index] = res.doc;
|
|
443
514
|
}
|
|
444
515
|
this.edittingDoc = null;
|
|
516
|
+
this.$toast.success('Document updated!');
|
|
445
517
|
},
|
|
446
518
|
handleDocumentClick(document, event) {
|
|
447
519
|
if (this.selectMultiple) {
|
|
@@ -505,6 +577,7 @@ module.exports = app => app.component('models', {
|
|
|
505
577
|
this.lastSelectedIndex = null;
|
|
506
578
|
this.shouldShowDeleteMultipleModal = false;
|
|
507
579
|
this.selectMultiple = false;
|
|
580
|
+
this.$toast.success('Documents deleted!');
|
|
508
581
|
},
|
|
509
582
|
async updateDocuments() {
|
|
510
583
|
await this.getDocuments();
|
|
@@ -28,35 +28,29 @@ module.exports = app => app.component('update-document', {
|
|
|
28
28
|
methods: {
|
|
29
29
|
async updateDocument() {
|
|
30
30
|
const data = EJSON.serialize(eval(`(${this.editor.getValue()})`));
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
});
|
|
44
|
-
} else {
|
|
45
|
-
await api.Model.updateDocument({ model: this.currentModel, _id: this.document._id, update: data }).catch(err => {
|
|
46
|
-
if (err.response?.data?.message) {
|
|
47
|
-
console.log(err.response.data);
|
|
48
|
-
const message = err.response.data.message.split(': ').slice(1).join(': ');
|
|
49
|
-
this.errors = message.split(',').map(error => {
|
|
50
|
-
return error.split(': ').slice(1).join(': ').trim();
|
|
51
|
-
});
|
|
52
|
-
throw new Error(err.response?.data?.message);
|
|
53
|
-
}
|
|
54
|
-
throw err;
|
|
31
|
+
try {
|
|
32
|
+
if (this.multiple) {
|
|
33
|
+
const ids = this.document.map(x => x._id);
|
|
34
|
+
await api.Model.updateDocuments({ model: this.currentModel, _id: ids, update: data });
|
|
35
|
+
} else {
|
|
36
|
+
await api.Model.updateDocument({ model: this.currentModel, _id: this.document._id, update: data });
|
|
37
|
+
}
|
|
38
|
+
this.errors.length = 0;
|
|
39
|
+
this.$emit('update');
|
|
40
|
+
this.$emit('close');
|
|
41
|
+
this.$nextTick(() => {
|
|
42
|
+
this.$toast.success(this.multiple ? 'Documents updated!' : 'Document updated!');
|
|
55
43
|
});
|
|
44
|
+
} catch (err) {
|
|
45
|
+
if (err.response?.data?.message) {
|
|
46
|
+
console.log(err.response.data);
|
|
47
|
+
const message = err.response.data.message.split(': ').slice(1).join(': ');
|
|
48
|
+
this.errors = message.split(',').map(error => {
|
|
49
|
+
return error.split(': ').slice(1).join(': ').trim();
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
throw err;
|
|
56
53
|
}
|
|
57
|
-
this.errors.length = 0;
|
|
58
|
-
this.$emit('update');
|
|
59
|
-
this.$emit('close');
|
|
60
54
|
}
|
|
61
55
|
},
|
|
62
56
|
mounted: function() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mongoosejs/studio",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "A sleek, powerful MongoDB UI with built-in dashboarding and auth, seamlessly integrated with your Express, Vercel, or Netlify app.",
|
|
5
5
|
"homepage": "https://studio.mongoosejs.io/",
|
|
6
6
|
"repository": {
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
},
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
|
+
"@ai-sdk/anthropic": "2.x",
|
|
12
13
|
"@ai-sdk/google": "2.x",
|
|
13
14
|
"@ai-sdk/openai": "2.x",
|
|
14
|
-
"@ai-sdk/anthropic": "2.x",
|
|
15
15
|
"ai": "5.x",
|
|
16
16
|
"archetype": "0.13.1",
|
|
17
17
|
"csv-stringify": "6.3.0",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"marked": "15.0.12",
|
|
21
21
|
"node-inspect-extracted": "3.x",
|
|
22
22
|
"tailwindcss": "3.4.0",
|
|
23
|
-
"vanillatoasts": "^1.6.0",
|
|
24
23
|
"vue": "3.x",
|
|
24
|
+
"vue-toastification": "^2.0.0-rc.5",
|
|
25
25
|
"webpack": "5.x"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|