@mongoosejs/studio 0.0.82 → 0.0.84

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.
@@ -914,6 +914,10 @@ video {
914
914
  max-width: 64rem;
915
915
  }
916
916
 
917
+ .max-w-\[70vw\] {
918
+ max-width: 70vw;
919
+ }
920
+
917
921
  .max-w-\[calc\(100\%-6\.5rem\)\] {
918
922
  max-width: calc(100% - 6.5rem);
919
923
  }
@@ -1231,6 +1235,16 @@ video {
1231
1235
  border-color: rgb(63 83 255 / var(--tw-border-opacity));
1232
1236
  }
1233
1237
 
1238
+ .border-red-500 {
1239
+ --tw-border-opacity: 1;
1240
+ border-color: rgb(239 68 68 / var(--tw-border-opacity));
1241
+ }
1242
+
1243
+ .bg-blue-200 {
1244
+ --tw-bg-opacity: 1;
1245
+ background-color: rgb(191 219 254 / var(--tw-bg-opacity));
1246
+ }
1247
+
1234
1248
  .bg-blue-500 {
1235
1249
  --tw-bg-opacity: 1;
1236
1250
  background-color: rgb(59 130 246 / var(--tw-bg-opacity));
@@ -1326,6 +1340,11 @@ video {
1326
1340
  background-color: rgb(239 68 68 / var(--tw-bg-opacity));
1327
1341
  }
1328
1342
 
1343
+ .bg-red-600 {
1344
+ --tw-bg-opacity: 1;
1345
+ background-color: rgb(220 38 38 / var(--tw-bg-opacity));
1346
+ }
1347
+
1329
1348
  .bg-slate-100 {
1330
1349
  --tw-bg-opacity: 1;
1331
1350
  background-color: rgb(241 245 249 / var(--tw-bg-opacity));
@@ -1380,6 +1399,11 @@ video {
1380
1399
  background-color: rgb(253 224 71 / var(--tw-bg-opacity));
1381
1400
  }
1382
1401
 
1402
+ .bg-ultramarine-500 {
1403
+ --tw-bg-opacity: 1;
1404
+ background-color: rgb(63 83 255 / var(--tw-bg-opacity));
1405
+ }
1406
+
1383
1407
  .p-1 {
1384
1408
  padding: 0.25rem;
1385
1409
  }
@@ -1722,6 +1746,12 @@ video {
1722
1746
  box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
1723
1747
  }
1724
1748
 
1749
+ .ring-2 {
1750
+ --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
1751
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
1752
+ box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
1753
+ }
1754
+
1725
1755
  .ring-inset {
1726
1756
  --tw-ring-inset: inset;
1727
1757
  }
@@ -1747,6 +1777,16 @@ video {
1747
1777
  --tw-ring-color: rgb(22 163 74 / 0.2);
1748
1778
  }
1749
1779
 
1780
+ .ring-yellow-800 {
1781
+ --tw-ring-opacity: 1;
1782
+ --tw-ring-color: rgb(133 77 14 / var(--tw-ring-opacity));
1783
+ }
1784
+
1785
+ .ring-yellow-300 {
1786
+ --tw-ring-opacity: 1;
1787
+ --tw-ring-color: rgb(253 224 71 / var(--tw-ring-opacity));
1788
+ }
1789
+
1750
1790
  .filter {
1751
1791
  filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
1752
1792
  }
@@ -1850,6 +1890,11 @@ video {
1850
1890
  background-color: rgb(22 163 74 / var(--tw-bg-opacity));
1851
1891
  }
1852
1892
 
1893
+ .hover\:bg-red-500:hover {
1894
+ --tw-bg-opacity: 1;
1895
+ background-color: rgb(239 68 68 / var(--tw-bg-opacity));
1896
+ }
1897
+
1853
1898
  .hover\:bg-red-600:hover {
1854
1899
  --tw-bg-opacity: 1;
1855
1900
  background-color: rgb(220 38 38 / var(--tw-bg-opacity));
@@ -1895,6 +1940,11 @@ video {
1895
1940
  background-color: rgb(220 73 73 / var(--tw-bg-opacity));
1896
1941
  }
1897
1942
 
1943
+ .hover\:bg-ultramarine-600:hover {
1944
+ --tw-bg-opacity: 1;
1945
+ background-color: rgb(24 35 255 / var(--tw-bg-opacity));
1946
+ }
1947
+
1898
1948
  .hover\:text-gray-700:hover {
1899
1949
  --tw-text-opacity: 1;
1900
1950
  color: rgb(55 65 81 / var(--tw-text-opacity));
@@ -2033,6 +2083,10 @@ video {
2033
2083
  outline-color: #fb923c;
2034
2084
  }
2035
2085
 
2086
+ .focus-visible\:outline-red-500:focus-visible {
2087
+ outline-color: #ef4444;
2088
+ }
2089
+
2036
2090
  .focus-visible\:outline-red-600:focus-visible {
2037
2091
  outline-color: #dc2626;
2038
2092
  }
@@ -2053,6 +2107,14 @@ video {
2053
2107
  outline-color: #1823ff;
2054
2108
  }
2055
2109
 
2110
+ .focus-visible\:outline-gray-600:focus-visible {
2111
+ outline-color: #4b5563;
2112
+ }
2113
+
2114
+ .focus-visible\:outline-gray-500:focus-visible {
2115
+ outline-color: #6b7280;
2116
+ }
2117
+
2056
2118
  .disabled\:cursor-not-allowed:disabled {
2057
2119
  cursor: not-allowed;
2058
2120
  }
@@ -75,6 +75,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
75
75
  deleteDocument(params) {
76
76
  return client.post('', { action: 'Model.deleteDocument', ...params}).then(res => res.data);
77
77
  },
78
+ deleteDocuments(params) {
79
+ return client.post('', { action: 'Model.deleteDocuments', ...params}).then(res => res.data);
80
+ },
78
81
  exportQueryResults(params) {
79
82
  const accessToken = window.localStorage.getItem('_mongooseStudioAccessToken') || null;
80
83
 
@@ -113,6 +116,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
113
116
  },
114
117
  updateDocument: function updateDocument(params) {
115
118
  return client.post('', { action: 'Model.updateDocument', ...params }).then(res => res.data);
119
+ },
120
+ updateDocuments: function updateDocuments(params) {
121
+ return client.post('', { action: 'Model.updateDocuments', ...params }).then(res => res.data);
116
122
  }
117
123
  };
118
124
  } else {
@@ -165,6 +171,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
165
171
  deleteDocument: function (params) {
166
172
  return client.post('/Model/deleteDocument', params).then(res => res.data);
167
173
  },
174
+ deleteDocuments: function(params) {
175
+ return client.post('/Model/deleteDocuments', params).then(res => res.data);
176
+ },
168
177
  exportQueryResults(params) {
169
178
  const accessToken = window.localStorage.getItem('_mongooseStudioAccessToken') || null;
170
179
 
@@ -206,6 +215,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
206
215
  },
207
216
  updateDocument: function updateDocument(params) {
208
217
  return client.post('/Model/updateDocument', params).then(res => res.data);
218
+ },
219
+ updateDocuments: function updateDocument(params) {
220
+ return client.post('/Model/updateDocuments', params).then(res => res.data);
209
221
  }
210
222
  };
211
223
  }
@@ -13,6 +13,14 @@
13
13
  Output
14
14
  </button>
15
15
  <div class="ml-auto mr-1 flex">
16
+ <button
17
+ v-if="activeTab === 'output'"
18
+ class="px-2 py-1 mr-1 text-xs bg-gray-500 text-white border-none rounded cursor-pointer hover:bg-gray-600 transition-colors flex items-center"
19
+ @click="copyOutput">
20
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
21
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" />
22
+ </svg>
23
+ </button>
16
24
  <button
17
25
  v-if="activeTab === 'output'"
18
26
  class="px-2 py-1 mr-1 text-xs bg-blue-500 text-white border-none rounded cursor-pointer hover:bg-blue-600 transition-colors flex items-center"
@@ -31,19 +39,17 @@
31
39
 
32
40
  <pre class="p-3 whitespace-pre-wrap max-h-[30vh] overflow-y-auto" v-show="activeTab === 'code'"><code v-text="script" ref="code" :class="'language-' + language"></code></pre>
33
41
 
34
- <pre class="p-3 whitespace-pre-wrap max-h-[30vh] overflow-y-auto bg-white border-t" v-show="activeTab === 'output'">
42
+ <div class="p-3 whitespace-pre-wrap max-h-[30vh] overflow-y-auto bg-white border-t max-w-[70vw] relative" v-show="activeTab === 'output'">
35
43
  <dashboard-chart v-if="message.executionResult?.output?.$chart" :value="message.executionResult?.output" />
36
- <div v-else>{{ message.executionResult?.output ? JSON.stringify(message.executionResult.output, null, 2) : 'No output' }}</div>
37
- </pre>
44
+ <pre v-else>{{ message.executionResult?.output || 'No output' }}</pre>
45
+ </div>
38
46
 
39
47
  <modal ref="outputModal" v-if="showDetailModal" containerClass="!h-[90vh] !w-[90vw]">
40
48
  <template #body>
41
49
  <div class="absolute font-mono right-1 top-1 cursor-pointer text-xl" @click="showDetailModal = false;">&times;</div>
42
50
  <div class="h-full overflow-auto">
43
51
  <dashboard-chart v-if="message.executionResult?.output?.$chart" :value="message.executionResult?.output" />
44
- <pre v-else class="whitespace-pre-wrap">
45
- {{ message.executionResult?.output ? JSON.stringify(message.executionResult.output, null, 2) : 'No output' }}
46
- </pre>
52
+ <pre v-else class="whitespace-pre-wrap">{{ message.executionResult?.output || 'No output' }}</pre>
47
53
  </div>
48
54
  </template>
49
55
  </modal>
@@ -3,6 +3,7 @@
3
3
  const api = require('../../api');
4
4
  const marked = require('marked').marked;
5
5
  const template = require('./chat-message-script.html');
6
+ const vanillatoasts = require('vanillatoasts');
6
7
 
7
8
  module.exports = app => app.component('chat-message-script', {
8
9
  template: template,
@@ -24,6 +25,16 @@ module.exports = app => app.component('chat-message-script', {
24
25
  },
25
26
  openDetailModal() {
26
27
  this.showDetailModal = true;
28
+ },
29
+ async copyOutput() {
30
+ await navigator.clipboard.writeText(this.message.executionResult.output);
31
+ vanillatoasts.create({
32
+ title: 'Text copied!',
33
+ type: 'success',
34
+ timeout: 3000,
35
+ icon: 'images/success.png',
36
+ positionClass: 'bottomRight'
37
+ });
27
38
  }
28
39
  },
29
40
  mounted() {
@@ -28,7 +28,7 @@
28
28
  <div class="documents-menu">
29
29
  <div class="flex flex-row items-center w-full gap-2">
30
30
  <form @submit.prevent="search" class="flex-grow m-0">
31
- <input ref="searchInput" class="w-full font-mono rounded-md p-1 border border-gray-300 outline-gray-300 text-lg focus:ring-1 focus:ring-ultramarine-200 focus:ring-offset-0 focus:outline-none" type="text" placeholder="Filter or text" v-model="searchText" />
31
+ <input ref="searchInput" class="w-full font-mono rounded-md p-1 border border-gray-300 outline-gray-300 text-lg focus:ring-1 focus:ring-ultramarine-200 focus:ring-offset-0 focus:outline-none" type="text" placeholder="Filter" v-model="searchText" @click="initFilter" />
32
32
  </form>
33
33
  <div>
34
34
  <span v-if="status === 'loading'">Loading ...</span>
@@ -37,24 +37,52 @@
37
37
  <button
38
38
  @click="shouldShowExportModal = true"
39
39
  type="button"
40
+ v-show="!selectMultiple"
40
41
  class="rounded bg-ultramarine-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600">
41
42
  Export
42
43
  </button>
44
+ <button
45
+ @click="stagingSelect"
46
+ type="button"
47
+ :class="{ 'bg-ultramarine-500 ring-inset ring-2 ring-gray-300 hover:bg-ultramarine-600': selectMultiple }"
48
+ class="rounded bg-ultramarine-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600"
49
+ >
50
+ Select
51
+ </button>
52
+ <button
53
+ v-show="selectMultiple"
54
+ @click="shouldShowUpdateMultipleModal=true;"
55
+ type="button"
56
+ class="rounded bg-green-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600"
57
+ >
58
+ Update
59
+ </button>
60
+ <button
61
+ @click="shouldShowDeleteMultipleModal=true;"
62
+ type="button"
63
+ v-show="selectMultiple"
64
+ class="rounded bg-red-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-500"
65
+ >
66
+ Delete
67
+ </button>
43
68
  <button
44
69
  @click="openIndexModal"
45
70
  type="button"
71
+ v-show="!selectMultiple"
46
72
  class="rounded bg-ultramarine-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600">
47
73
  Indexes
48
74
  </button>
49
75
  <button
50
76
  @click="shouldShowCreateModal = true;"
51
77
  type="button"
78
+ v-show="!selectMultiple"
52
79
  class="rounded bg-ultramarine-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600">
53
80
  Create
54
81
  </button>
55
82
  <button
56
83
  @click="openFieldSelection"
57
84
  type="button"
85
+ v-show="!selectMultiple"
58
86
  class="rounded bg-ultramarine-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600">
59
87
  Fields
60
88
  </button>
@@ -90,8 +118,8 @@
90
118
  </th>
91
119
  </thead>
92
120
  <tbody>
93
- <tr v-for="document in documents" @click="$router.push('/model/' + currentModel + '/document/' + document._id)" :key="document._id">
94
- <td v-for="schemaPath in filteredPaths">
121
+ <tr v-for="document in documents" @click="handleDocumentClick(document)" :key="document._id">
122
+ <td v-for="schemaPath in filteredPaths" :class="{ 'bg-blue-200': selectedDocuments.some(x => x._id.toString() === document._id.toString()) }">
95
123
  <component
96
124
  :is="getComponentForPath(schemaPath)"
97
125
  :value="getValueForPath(document, schemaPath.path)"
@@ -102,7 +130,7 @@
102
130
  </tbody>
103
131
  </table>
104
132
  <div v-if="outputType === 'json'">
105
- <div v-for="document in documents" @click="$router.push('/model/' + currentModel + '/document/' + document._id)" :key="document._id">
133
+ <div v-for="document in documents" @click="handleDocumentClick(document)" :key="document._id" :class="{ 'bg-blue-200': selectedDocuments.some(x => x._id.toString() === document._id.toString()) }">
106
134
  <list-json :value="filterDocument(document)">
107
135
  </list-json>
108
136
  </div>
@@ -162,4 +190,27 @@
162
190
  <create-document :currentModel="currentModel" :paths="schemaPaths" @close="closeCreationModal"></create-document>
163
191
  </template>
164
192
  </modal>
193
+ <modal v-if="shouldShowUpdateMultipleModal">
194
+ <template v-slot:body>
195
+ <div class="modal-exit" @click="shouldShowUpdateMultipleModal = false;">&times;</div>
196
+ <update-document :currentModel="currentModel" :document="selectedDocuments" :multiple="true" @update="updateDocuments" @close="shouldShowUpdateMultipleModal=false;"></update-document>
197
+ </template>
198
+ </modal>
199
+ <modal v-if="shouldShowDeleteMultipleModal">
200
+ <template v-slot:body>
201
+ <div class="modal-exit" @click="shouldShowDeleteMultipleModal = false;">&times;</div>
202
+ <h2>Are you sure you want to delete {{selectedDocuments.length}} documents?</h2>
203
+ <div>
204
+ <list-json :value="selectedDocuments"></list-json>
205
+ </div>
206
+ <div class="flex gap-4">
207
+ <async-button @click="deleteDocuments" class="rounded bg-red-500 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600">
208
+ Confirm
209
+ </async-button>
210
+ <button @click="shouldShowDeleteMultipleModal = false;" class="rounded bg-gray-400 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-gray-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-500">
211
+ Cancel
212
+ </button>
213
+ </div>
214
+ </template>
215
+ </modal>
165
216
  </div>
@@ -38,11 +38,15 @@ module.exports = app => app.component('models', {
38
38
  edittingDoc: null,
39
39
  docEdits: null,
40
40
  filter: null,
41
+ selectMultiple: false,
42
+ selectedDocuments: [],
41
43
  searchText: '',
42
44
  shouldShowExportModal: false,
43
45
  shouldShowCreateModal: false,
44
46
  shouldShowFieldModal: false,
45
47
  shouldShowIndexModal: false,
48
+ shouldShowUpdateMultipleModal: false,
49
+ shouldShowDeleteMultipleModal: false,
46
50
  shouldExport: {},
47
51
  sortBy: {},
48
52
  query: {},
@@ -89,6 +93,14 @@ module.exports = app => app.component('models', {
89
93
  this.status = 'loaded';
90
94
  },
91
95
  methods: {
96
+ initFilter(ev) {
97
+ if (!this.searchText) {
98
+ this.searchText = '{}';
99
+ this.$nextTick(() => {
100
+ ev.target.setSelectionRange(1, 1);
101
+ });
102
+ }
103
+ },
92
104
  clickFilter(path) {
93
105
  if (this.searchText) {
94
106
  if (this.searchText.endsWith('}')) {
@@ -319,6 +331,46 @@ module.exports = app => app.component('models', {
319
331
  this.documents[index] = res.doc;
320
332
  }
321
333
  this.edittingDoc = null;
334
+ },
335
+ handleDocumentClick(document) {
336
+ console.log(this.selectedDocuments);
337
+ if (this.selectMultiple) {
338
+ const exists = this.selectedDocuments.find(x => x._id.toString() == document._id.toString())
339
+ if (exists) {
340
+ const index = this.selectedDocuments.findIndex(x => x._id.toString() == document._id.toString());
341
+ if (index !== -1) {
342
+ this.selectedDocuments.splice(index, 1);
343
+ }
344
+ } else {
345
+ this.selectedDocuments.push(document);
346
+ }
347
+ } else {
348
+ this.$router.push('/model/' + this.currentModel + '/document/' + document._id)
349
+ }
350
+ },
351
+ async deleteDocuments() {
352
+ const documentIds = this.selectedDocuments.map(x => x._id);
353
+ await api.Model.deleteDocuments({
354
+ documentIds,
355
+ model: this.currentModel
356
+ });
357
+ await this.getDocuments();
358
+ this.selectedDocuments.length = 0;
359
+ this.shouldShowDeleteMultipleModal = false;
360
+ this.selectMultiple = false;
361
+ },
362
+ async updateDocuments() {
363
+ await this.getDocuments();
364
+ this.selectedDocuments.length = 0;
365
+ this.selectMultiple = false;
366
+ },
367
+ stagingSelect() {
368
+ if (this.selectMultiple) {
369
+ this.selectMultiple = false;
370
+ this.selectedDocuments.length = 0;
371
+ } else {
372
+ this.selectMultiple = true;
373
+ }
322
374
  }
323
375
  }
324
376
  });
@@ -0,0 +1,25 @@
1
+ <div>
2
+ <div class="mb-2">
3
+ <textarea class="border border-gray-200 p-2 h-[300px] w-full" ref="codeEditor"></textarea>
4
+ </div>
5
+ <button @click="updateDocument()" class="rounded-md bg-ultramarine-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600">Submit</button>
6
+ <div v-if="errors.length > 0" class="rounded-md bg-red-50 p-4 mt-1">
7
+ <div class="flex">
8
+ <div class="flex-shrink-0">
9
+ <svg class="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
10
+ <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.28 7.22a.75.75 0 00-1.06 1.06L8.94 10l-1.72 1.72a.75.75 0 101.06 1.06L10 11.06l1.72 1.72a.75.75 0 101.06-1.06L11.06 10l1.72-1.72a.75.75 0 00-1.06-1.06L10 8.94 8.28 7.22z" clip-rule="evenodd" />
11
+ </svg>
12
+ </div>
13
+ <div class="ml-3">
14
+ <h3 class="text-sm font-medium text-red-800">There were {{errors.length}} errors with your submission</h3>
15
+ <div class="mt-2 text-sm text-red-700">
16
+ <ul role="list" class="list-disc space-y-1 pl-5">
17
+ <li v-for="error in errors">
18
+ {{error}}
19
+ </li>
20
+ </ul>
21
+ </div>
22
+ </div>
23
+ </div>
24
+ </div>
25
+ </div>
@@ -0,0 +1,70 @@
1
+ 'use strict';
2
+
3
+ const api = require('../api');
4
+
5
+ const { BSON, EJSON } = require('bson');
6
+
7
+ const ObjectId = new Proxy(BSON.ObjectId, {
8
+ apply (target, thisArg, argumentsList) {
9
+ return new target(...argumentsList);
10
+ }
11
+ });
12
+
13
+ const appendCSS = require('../appendCSS');
14
+
15
+ appendCSS(require('./update-document.css'));
16
+
17
+ const template = require('./update-document.html')
18
+
19
+ module.exports = app => app.component('update-document', {
20
+ props: ['currentModel', 'document', 'multiple'],
21
+ template,
22
+ data: function() {
23
+ return {
24
+ editor: null,
25
+ errors: []
26
+ }
27
+ },
28
+ methods: {
29
+ async updateDocument() {
30
+ const data = EJSON.serialize(eval(`(${this.editor.getValue()})`));
31
+ if (this.multiple) {
32
+ const ids = this.document.map(x => x._id);
33
+ await api.Model.updateDocuments({ model: this.currentModel, _id: ids, update: data }).catch(err => {
34
+ if (err.response?.data?.message) {
35
+ console.log(err.response.data);
36
+ const message = err.response.data.message.split(": ").slice(1).join(": ");
37
+ this.errors = message.split(',').map(error => {
38
+ return error.split(': ').slice(1).join(': ').trim();
39
+ })
40
+ throw new Error(err.response?.data?.message);
41
+ }
42
+ throw err;
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;
55
+ });
56
+ }
57
+ this.errors.length = 0;
58
+ this.$emit('update');
59
+ this.$emit('close');
60
+ },
61
+ },
62
+ mounted: function() {
63
+ this.$refs.codeEditor.value = `{\n \n}`
64
+ this.editor = CodeMirror.fromTextArea(this.$refs.codeEditor, {
65
+ mode: 'javascript',
66
+ lineNumbers: true,
67
+ smartIndent: false
68
+ });
69
+ },
70
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mongoosejs/studio",
3
- "version": "0.0.82",
3
+ "version": "0.0.84",
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": {