@mongoosejs/studio 0.5.13 → 0.5.14
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/AGENTS.md +7 -0
- package/CLAUDE.md +7 -0
- package/README.md +3 -0
- package/backend/actions/ChatMessage/executeScript.js +7 -5
- package/backend/actions/ChatThread/createChatMessage.js +4 -2
- package/backend/actions/ChatThread/getChatThread.js +5 -2
- package/backend/actions/ChatThread/listChatThreads.js +3 -1
- package/backend/actions/ChatThread/shareChatThread.js +5 -2
- package/backend/actions/ChatThread/streamChatMessage.js +4 -2
- package/backend/actions/ChatThread/toggleAgentMode.js +5 -2
- package/backend/actions/Dashboard/deleteDashboard.js +7 -3
- package/backend/actions/Dashboard/getDashboard.js +21 -10
- package/backend/actions/Dashboard/getDashboards.js +3 -1
- package/backend/actions/Dashboard/updateDashboard.js +3 -2
- package/backend/actions/Model/addField.js +3 -2
- package/backend/actions/Model/analyzeSchema.js +6 -4
- package/backend/actions/Model/deleteDocument.js +3 -3
- package/backend/actions/Model/deleteDocuments.js +3 -1
- package/backend/actions/Model/executeDocumentScript.js +25 -29
- package/backend/actions/Model/exportQueryResults.js +3 -1
- package/backend/actions/Model/getCollectionInfo.js +5 -3
- package/backend/actions/Model/getDocument.js +3 -2
- package/backend/actions/Model/getDocuments.js +15 -5
- package/backend/actions/Model/getDocumentsStream.js +28 -18
- package/backend/actions/Model/getEstimatedDocumentCounts.js +5 -2
- package/backend/actions/Model/updateDocument.js +4 -2
- package/backend/actions/Model/updateDocuments.js +4 -2
- package/backend/actions/Model/validateDocument.js +5 -2
- package/backend/actions/Task/cancelTask.js +6 -3
- package/backend/actions/Task/getTaskOverview.js +3 -2
- package/backend/actions/Task/getTasks.js +3 -2
- package/backend/actions/Task/getTasksOverTime.js +3 -2
- package/backend/actions/Task/rescheduleTask.js +6 -3
- package/backend/actions/Task/runTask.js +6 -3
- package/backend/helpers/omitNullish.js +5 -0
- package/backend/index.js +4 -4
- package/backend/sandbox/createSandbox.js +2 -2
- package/backend/sandbox/createScriptDb.js +42 -19
- package/frontend/public/app.js +319 -96
- package/frontend/public/tw.css +68 -0
- package/frontend/src/api.js +5 -1
- package/frontend/src/models/models.html +29 -8
- package/frontend/src/models/models.js +30 -2
- package/frontend/src/tooltip/tooltip.html +28 -0
- package/frontend/src/tooltip/tooltip.js +94 -0
- package/index.d.ts +1 -1
- package/local.js +2 -1
- package/nest.d.ts +1 -0
- package/package.json +1 -1
- package/vercel.d.ts +2 -0
package/frontend/public/app.js
CHANGED
|
@@ -1269,7 +1269,11 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
|
|
|
1269
1269
|
getDocumentsStream: async function* getDocumentsStream(params) {
|
|
1270
1270
|
const data = await client.post('', { action: 'Model.getDocuments', ...params }).then(res => res.data);
|
|
1271
1271
|
yield { schemaPaths: data.schemaPaths, suggestedFields: data.suggestedFields };
|
|
1272
|
-
|
|
1272
|
+
if (data.numDocsError) {
|
|
1273
|
+
yield { numDocsError: data.numDocsError };
|
|
1274
|
+
} else {
|
|
1275
|
+
yield { numDocs: data.numDocs };
|
|
1276
|
+
}
|
|
1273
1277
|
for (const doc of data.docs) {
|
|
1274
1278
|
yield { document: doc };
|
|
1275
1279
|
}
|
|
@@ -9621,6 +9625,8 @@ module.exports = app => app.component('models', {
|
|
|
9621
9625
|
filteredPaths: [],
|
|
9622
9626
|
selectedPaths: [],
|
|
9623
9627
|
numDocuments: null,
|
|
9628
|
+
numDocumentsError: null,
|
|
9629
|
+
documentsError: null,
|
|
9624
9630
|
mongoDBIndexes: [],
|
|
9625
9631
|
schemaIndexes: [],
|
|
9626
9632
|
status: 'loading',
|
|
@@ -10308,7 +10314,8 @@ module.exports = app => app.component('models', {
|
|
|
10308
10314
|
return filteredDoc;
|
|
10309
10315
|
},
|
|
10310
10316
|
async checkIfScrolledToBottom() {
|
|
10311
|
-
if
|
|
10317
|
+
// Stop infinite scroll if the last load failed, otherwise we would retry the same failing request forever.
|
|
10318
|
+
if (this.status === 'loading' || this.loadedAllDocs || this.documentsError) {
|
|
10312
10319
|
return;
|
|
10313
10320
|
}
|
|
10314
10321
|
// Infinite scroll only applies to table/json views.
|
|
@@ -10334,11 +10341,20 @@ module.exports = app => app.component('models', {
|
|
|
10334
10341
|
try {
|
|
10335
10342
|
const skip = this.documents.length;
|
|
10336
10343
|
const params = this.buildDocumentFetchParams({ skip });
|
|
10337
|
-
const { docs } = await api.Model.getDocuments(params);
|
|
10344
|
+
const { docs, numDocs, numDocsError } = await api.Model.getDocuments(params);
|
|
10345
|
+
if (numDocsError) {
|
|
10346
|
+
this.numDocumentsError = numDocsError;
|
|
10347
|
+
} else if (numDocs !== undefined) {
|
|
10348
|
+
this.numDocuments = numDocs;
|
|
10349
|
+
this.numDocumentsError = null;
|
|
10350
|
+
}
|
|
10338
10351
|
if (docs.length < limit) {
|
|
10339
10352
|
this.loadedAllDocs = true;
|
|
10340
10353
|
}
|
|
10341
10354
|
this.documents.push(...docs);
|
|
10355
|
+
this.documentsError = null;
|
|
10356
|
+
} catch (err) {
|
|
10357
|
+
this.documentsError = err?.message;
|
|
10342
10358
|
} finally {
|
|
10343
10359
|
this.loadingMore = false;
|
|
10344
10360
|
this.status = 'loaded';
|
|
@@ -10551,6 +10567,8 @@ module.exports = app => app.component('models', {
|
|
|
10551
10567
|
// Clear previous data
|
|
10552
10568
|
this.documents = [];
|
|
10553
10569
|
this.numDocuments = null;
|
|
10570
|
+
this.numDocumentsError = null;
|
|
10571
|
+
this.documentsError = null;
|
|
10554
10572
|
this.loadedAllDocs = false;
|
|
10555
10573
|
this.lastSelectedIndex = null;
|
|
10556
10574
|
|
|
@@ -10600,6 +10618,10 @@ module.exports = app => app.component('models', {
|
|
|
10600
10618
|
}
|
|
10601
10619
|
if (event.numDocs !== undefined) {
|
|
10602
10620
|
this.numDocuments = event.numDocs;
|
|
10621
|
+
this.numDocumentsError = null;
|
|
10622
|
+
}
|
|
10623
|
+
if (event.numDocsError) {
|
|
10624
|
+
this.numDocumentsError = event.numDocsError;
|
|
10603
10625
|
}
|
|
10604
10626
|
if (event.document) {
|
|
10605
10627
|
this.documents.push(event.document);
|
|
@@ -10613,6 +10635,9 @@ module.exports = app => app.component('models', {
|
|
|
10613
10635
|
if (docsCount < limit) {
|
|
10614
10636
|
this.loadedAllDocs = true;
|
|
10615
10637
|
}
|
|
10638
|
+
this.documentsError = null;
|
|
10639
|
+
} catch (err) {
|
|
10640
|
+
this.documentsError = err?.message;
|
|
10616
10641
|
} finally {
|
|
10617
10642
|
this.status = 'loaded';
|
|
10618
10643
|
}
|
|
@@ -10639,8 +10664,12 @@ module.exports = app => app.component('models', {
|
|
|
10639
10664
|
for await (const event of api.Model.getDocumentsStream(params)) {
|
|
10640
10665
|
if (event.numDocs !== undefined && !numDocsReceived) {
|
|
10641
10666
|
this.numDocuments = event.numDocs;
|
|
10667
|
+
this.numDocumentsError = null;
|
|
10642
10668
|
numDocsReceived = true;
|
|
10643
10669
|
}
|
|
10670
|
+
if (event.numDocsError) {
|
|
10671
|
+
this.numDocumentsError = event.numDocsError;
|
|
10672
|
+
}
|
|
10644
10673
|
if (event.document) {
|
|
10645
10674
|
this.documents.push(event.document);
|
|
10646
10675
|
docsCount++;
|
|
@@ -10653,6 +10682,9 @@ module.exports = app => app.component('models', {
|
|
|
10653
10682
|
if (docsCount < limit) {
|
|
10654
10683
|
this.loadedAllDocs = true;
|
|
10655
10684
|
}
|
|
10685
|
+
this.documentsError = null;
|
|
10686
|
+
} catch (err) {
|
|
10687
|
+
this.documentsError = err?.message;
|
|
10656
10688
|
} finally {
|
|
10657
10689
|
this.loadingMore = false;
|
|
10658
10690
|
this.status = 'loaded';
|
|
@@ -13175,6 +13207,111 @@ module.exports = app => app.component('team', {
|
|
|
13175
13207
|
});
|
|
13176
13208
|
|
|
13177
13209
|
|
|
13210
|
+
/***/ },
|
|
13211
|
+
|
|
13212
|
+
/***/ "./frontend/src/tooltip/tooltip.js"
|
|
13213
|
+
/*!*****************************************!*\
|
|
13214
|
+
!*** ./frontend/src/tooltip/tooltip.js ***!
|
|
13215
|
+
\*****************************************/
|
|
13216
|
+
(module, __unused_webpack_exports, __webpack_require__) {
|
|
13217
|
+
|
|
13218
|
+
"use strict";
|
|
13219
|
+
|
|
13220
|
+
|
|
13221
|
+
const template = __webpack_require__(/*! ./tooltip.html */ "./frontend/src/tooltip/tooltip.html");
|
|
13222
|
+
|
|
13223
|
+
let nextTooltipId = 0;
|
|
13224
|
+
|
|
13225
|
+
module.exports = app => app.component('tooltip', {
|
|
13226
|
+
props: {
|
|
13227
|
+
text: {
|
|
13228
|
+
type: String,
|
|
13229
|
+
required: true
|
|
13230
|
+
}
|
|
13231
|
+
},
|
|
13232
|
+
template,
|
|
13233
|
+
data() {
|
|
13234
|
+
return {
|
|
13235
|
+
isOpen: false,
|
|
13236
|
+
isPinned: false,
|
|
13237
|
+
placement: 'bottom',
|
|
13238
|
+
tooltipId: `tooltip-${++nextTooltipId}`,
|
|
13239
|
+
tooltipStyle: {
|
|
13240
|
+
visibility: 'hidden'
|
|
13241
|
+
}
|
|
13242
|
+
};
|
|
13243
|
+
},
|
|
13244
|
+
mounted() {
|
|
13245
|
+
document.addEventListener('click', this.handleOutsideClick);
|
|
13246
|
+
window.addEventListener('resize', this.updatePosition);
|
|
13247
|
+
window.addEventListener('scroll', this.updatePosition, true);
|
|
13248
|
+
},
|
|
13249
|
+
beforeUnmount() {
|
|
13250
|
+
document.removeEventListener('click', this.handleOutsideClick);
|
|
13251
|
+
window.removeEventListener('resize', this.updatePosition);
|
|
13252
|
+
window.removeEventListener('scroll', this.updatePosition, true);
|
|
13253
|
+
},
|
|
13254
|
+
methods: {
|
|
13255
|
+
show() {
|
|
13256
|
+
this.isOpen = true;
|
|
13257
|
+
this.tooltipStyle = { visibility: 'hidden' };
|
|
13258
|
+
this.$nextTick(this.updatePosition);
|
|
13259
|
+
},
|
|
13260
|
+
hide() {
|
|
13261
|
+
this.isOpen = false;
|
|
13262
|
+
this.isPinned = false;
|
|
13263
|
+
},
|
|
13264
|
+
hideUnlessPinned() {
|
|
13265
|
+
if (!this.isPinned) {
|
|
13266
|
+
this.isOpen = false;
|
|
13267
|
+
}
|
|
13268
|
+
},
|
|
13269
|
+
toggle() {
|
|
13270
|
+
if (this.isPinned) {
|
|
13271
|
+
this.hide();
|
|
13272
|
+
return;
|
|
13273
|
+
}
|
|
13274
|
+
|
|
13275
|
+
this.isPinned = true;
|
|
13276
|
+
this.show();
|
|
13277
|
+
},
|
|
13278
|
+
handleFocusOut(event) {
|
|
13279
|
+
if (!this.$el.contains(event.relatedTarget)) {
|
|
13280
|
+
this.hideUnlessPinned();
|
|
13281
|
+
}
|
|
13282
|
+
},
|
|
13283
|
+
handleOutsideClick(event) {
|
|
13284
|
+
if (!this.$el.contains(event.target)) {
|
|
13285
|
+
this.hide();
|
|
13286
|
+
}
|
|
13287
|
+
},
|
|
13288
|
+
updatePosition() {
|
|
13289
|
+
if (!this.isOpen || !this.$refs.trigger || !this.$refs.tooltip) {
|
|
13290
|
+
return;
|
|
13291
|
+
}
|
|
13292
|
+
|
|
13293
|
+
const gap = 8;
|
|
13294
|
+
const viewportPadding = 8;
|
|
13295
|
+
const triggerRect = this.$refs.trigger.getBoundingClientRect();
|
|
13296
|
+
const tooltipRect = this.$refs.tooltip.getBoundingClientRect();
|
|
13297
|
+
const fitsBelow = triggerRect.bottom + gap + tooltipRect.height <= window.innerHeight - viewportPadding;
|
|
13298
|
+
const top = fitsBelow ?
|
|
13299
|
+
triggerRect.bottom + gap :
|
|
13300
|
+
Math.max(viewportPadding, triggerRect.top - gap - tooltipRect.height);
|
|
13301
|
+
const centeredLeft = triggerRect.left + triggerRect.width / 2 - tooltipRect.width / 2;
|
|
13302
|
+
const maxLeft = Math.max(viewportPadding, window.innerWidth - tooltipRect.width - viewportPadding);
|
|
13303
|
+
const left = Math.min(Math.max(viewportPadding, centeredLeft), maxLeft);
|
|
13304
|
+
|
|
13305
|
+
this.placement = fitsBelow ? 'bottom' : 'top';
|
|
13306
|
+
this.tooltipStyle = {
|
|
13307
|
+
left: `${Math.round(left)}px`,
|
|
13308
|
+
top: `${Math.round(top)}px`
|
|
13309
|
+
};
|
|
13310
|
+
}
|
|
13311
|
+
}
|
|
13312
|
+
});
|
|
13313
|
+
|
|
13314
|
+
|
|
13178
13315
|
/***/ },
|
|
13179
13316
|
|
|
13180
13317
|
/***/ "./frontend/src/update-document/update-document.js"
|
|
@@ -13491,6 +13628,9 @@ const map = {
|
|
|
13491
13628
|
"./team/team": "./frontend/src/team/team.js",
|
|
13492
13629
|
"./team/team.html": "./frontend/src/team/team.html",
|
|
13493
13630
|
"./team/team.js": "./frontend/src/team/team.js",
|
|
13631
|
+
"./tooltip/tooltip": "./frontend/src/tooltip/tooltip.js",
|
|
13632
|
+
"./tooltip/tooltip.html": "./frontend/src/tooltip/tooltip.html",
|
|
13633
|
+
"./tooltip/tooltip.js": "./frontend/src/tooltip/tooltip.js",
|
|
13494
13634
|
"./update-document/update-document": "./frontend/src/update-document/update-document.js",
|
|
13495
13635
|
"./update-document/update-document.css": "./frontend/src/update-document/update-document.css",
|
|
13496
13636
|
"./update-document/update-document.html": "./frontend/src/update-document/update-document.html",
|
|
@@ -13581,7 +13721,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
13581
13721
|
/* harmony export */ });
|
|
13582
13722
|
/* harmony import */ var _vue_shared__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @vue/shared */ "./node_modules/@vue/shared/dist/shared.esm-bundler.js");
|
|
13583
13723
|
/**
|
|
13584
|
-
* @vue/reactivity v3.5.
|
|
13724
|
+
* @vue/reactivity v3.5.42
|
|
13585
13725
|
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
|
13586
13726
|
* @license MIT
|
|
13587
13727
|
**/
|
|
@@ -15754,7 +15894,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
15754
15894
|
/* harmony import */ var _vue_reactivity__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @vue/reactivity */ "./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js");
|
|
15755
15895
|
/* harmony import */ var _vue_shared__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @vue/shared */ "./node_modules/@vue/shared/dist/shared.esm-bundler.js");
|
|
15756
15896
|
/**
|
|
15757
|
-
* @vue/runtime-core v3.5.
|
|
15897
|
+
* @vue/runtime-core v3.5.42
|
|
15758
15898
|
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
|
15759
15899
|
* @license MIT
|
|
15760
15900
|
**/
|
|
@@ -17822,10 +17962,10 @@ function createHydrationFunctions(rendererInternals) {
|
|
|
17822
17962
|
getContainerType(container),
|
|
17823
17963
|
optimized
|
|
17824
17964
|
);
|
|
17825
|
-
if (isAsyncWrapper(vnode) && !vnode.
|
|
17965
|
+
if (isAsyncWrapper(vnode) && !vnode.component.subTree) {
|
|
17826
17966
|
let subTree;
|
|
17827
17967
|
if (isFragmentStart) {
|
|
17828
|
-
subTree = createVNode(
|
|
17968
|
+
subTree = createVNode(Static);
|
|
17829
17969
|
subTree.anchor = nextNode ? nextNode.previousSibling : container.lastChild;
|
|
17830
17970
|
} else {
|
|
17831
17971
|
subTree = node.nodeType === 3 ? createTextVNode("") : createVNode("div");
|
|
@@ -18736,7 +18876,10 @@ const KeepAliveImpl = {
|
|
|
18736
18876
|
if (pendingCacheKey != null) {
|
|
18737
18877
|
if (isSuspense(instance.subTree.type)) {
|
|
18738
18878
|
queuePostRenderEffect(() => {
|
|
18739
|
-
|
|
18879
|
+
const vnode = getInnerChild(instance.subTree);
|
|
18880
|
+
if (vnode.component) {
|
|
18881
|
+
cache.set(pendingCacheKey, vnode);
|
|
18882
|
+
}
|
|
18740
18883
|
}, instance.subTree.suspense);
|
|
18741
18884
|
} else {
|
|
18742
18885
|
cache.set(pendingCacheKey, getInnerChild(instance.subTree));
|
|
@@ -19137,12 +19280,41 @@ const getPublicInstance = (i) => {
|
|
|
19137
19280
|
if (isStatefulComponent(i)) return getComponentPublicInstance(i);
|
|
19138
19281
|
return getPublicInstance(i.parent);
|
|
19139
19282
|
};
|
|
19283
|
+
const resolveDevRootEl = (vnode) => {
|
|
19284
|
+
let found = false;
|
|
19285
|
+
while (true) {
|
|
19286
|
+
if (vnode.patchFlag > 0 && vnode.patchFlag & 2048) {
|
|
19287
|
+
const root = filterSingleRoot(vnode.children);
|
|
19288
|
+
if (!root) {
|
|
19289
|
+
return;
|
|
19290
|
+
}
|
|
19291
|
+
vnode = root;
|
|
19292
|
+
found = true;
|
|
19293
|
+
continue;
|
|
19294
|
+
}
|
|
19295
|
+
const component = vnode.component;
|
|
19296
|
+
if (component && component.subTree) {
|
|
19297
|
+
vnode = component.subTree;
|
|
19298
|
+
continue;
|
|
19299
|
+
}
|
|
19300
|
+
const suspense = vnode.suspense;
|
|
19301
|
+
if (suspense && suspense.activeBranch) {
|
|
19302
|
+
vnode = suspense.activeBranch;
|
|
19303
|
+
continue;
|
|
19304
|
+
}
|
|
19305
|
+
return found ? vnode.el : void 0;
|
|
19306
|
+
}
|
|
19307
|
+
};
|
|
19308
|
+
const getDevRootFragmentEl = (i) => {
|
|
19309
|
+
const el = i.subTree && resolveDevRootEl(i.subTree);
|
|
19310
|
+
return el === void 0 ? i.vnode.el : el;
|
|
19311
|
+
};
|
|
19140
19312
|
const publicPropertiesMap = (
|
|
19141
19313
|
// Move PURE marker to new line to workaround compiler discarding it
|
|
19142
19314
|
// due to type annotation
|
|
19143
19315
|
/* @__PURE__ */ (0,_vue_shared__WEBPACK_IMPORTED_MODULE_1__.extend)(/* @__PURE__ */ Object.create(null), {
|
|
19144
19316
|
$: (i) => i,
|
|
19145
|
-
$el: (i) => i
|
|
19317
|
+
$el: (i) => true ? getDevRootFragmentEl(i) : 0,
|
|
19146
19318
|
$data: (i) => i.data,
|
|
19147
19319
|
$props: (i) => true ? (0,_vue_reactivity__WEBPACK_IMPORTED_MODULE_0__.shallowReadonly)(i.props) : 0,
|
|
19148
19320
|
$attrs: (i) => true ? (0,_vue_reactivity__WEBPACK_IMPORTED_MODULE_0__.shallowReadonly)(i.attrs) : 0,
|
|
@@ -20248,7 +20420,7 @@ function emit(instance, event, ...rawArgs) {
|
|
|
20248
20420
|
args = rawArgs.map((a) => (0,_vue_shared__WEBPACK_IMPORTED_MODULE_1__.isString)(a) ? a.trim() : a);
|
|
20249
20421
|
}
|
|
20250
20422
|
if (modifiers.number) {
|
|
20251
|
-
args =
|
|
20423
|
+
args = args.map(_vue_shared__WEBPACK_IMPORTED_MODULE_1__.looseToNumber);
|
|
20252
20424
|
}
|
|
20253
20425
|
}
|
|
20254
20426
|
if (true) {
|
|
@@ -22917,7 +23089,7 @@ function patchSuspense(n1, n2, container, anchor, parentComponent, namespace, sl
|
|
|
22917
23089
|
if (suspense.deps <= 0) {
|
|
22918
23090
|
suspense.resolve();
|
|
22919
23091
|
} else if (isInFallback) {
|
|
22920
|
-
if (!isHydrating) {
|
|
23092
|
+
if (!isHydrating && !suspense.isFallbackMountPending) {
|
|
22921
23093
|
patch(
|
|
22922
23094
|
activeBranch,
|
|
22923
23095
|
newFallback,
|
|
@@ -22958,7 +23130,7 @@ function patchSuspense(n1, n2, container, anchor, parentComponent, namespace, sl
|
|
|
22958
23130
|
);
|
|
22959
23131
|
if (suspense.deps <= 0) {
|
|
22960
23132
|
suspense.resolve();
|
|
22961
|
-
} else {
|
|
23133
|
+
} else if (!suspense.isFallbackMountPending) {
|
|
22962
23134
|
patch(
|
|
22963
23135
|
activeBranch,
|
|
22964
23136
|
newFallback,
|
|
@@ -23199,9 +23371,10 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe
|
|
|
23199
23371
|
if (!suspense.isInFallback) {
|
|
23200
23372
|
return;
|
|
23201
23373
|
}
|
|
23374
|
+
const latestFallback = suspense.vnode.ssFallback;
|
|
23202
23375
|
patch(
|
|
23203
23376
|
null,
|
|
23204
|
-
|
|
23377
|
+
latestFallback,
|
|
23205
23378
|
container2,
|
|
23206
23379
|
anchor2,
|
|
23207
23380
|
parentComponent2,
|
|
@@ -23211,7 +23384,7 @@ function createSuspenseBoundary(vnode, parentSuspense, parentComponent, containe
|
|
|
23211
23384
|
slotScopeIds,
|
|
23212
23385
|
optimized
|
|
23213
23386
|
);
|
|
23214
|
-
setActiveBranch(suspense,
|
|
23387
|
+
setActiveBranch(suspense, latestFallback);
|
|
23215
23388
|
};
|
|
23216
23389
|
const delayEnter = fallbackVNode.transition && fallbackVNode.transition.mode === "out-in";
|
|
23217
23390
|
if (delayEnter) {
|
|
@@ -24479,7 +24652,7 @@ function isMemoSame(cached, memo) {
|
|
|
24479
24652
|
return true;
|
|
24480
24653
|
}
|
|
24481
24654
|
|
|
24482
|
-
const version = "3.5.
|
|
24655
|
+
const version = "3.5.42";
|
|
24483
24656
|
const warn = true ? warn$1 : 0;
|
|
24484
24657
|
const ErrorTypeStrings = ErrorTypeStrings$1 ;
|
|
24485
24658
|
const devtools = true ? devtools$1 : 0;
|
|
@@ -24690,7 +24863,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
24690
24863
|
/* harmony import */ var _vue_runtime_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @vue/runtime-core */ "./node_modules/@vue/reactivity/dist/reactivity.esm-bundler.js");
|
|
24691
24864
|
/* harmony import */ var _vue_runtime_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @vue/shared */ "./node_modules/@vue/shared/dist/shared.esm-bundler.js");
|
|
24692
24865
|
/**
|
|
24693
|
-
* @vue/runtime-dom v3.5.
|
|
24866
|
+
* @vue/runtime-dom v3.5.42
|
|
24694
24867
|
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
|
24695
24868
|
* @license MIT
|
|
24696
24869
|
**/
|
|
@@ -25273,7 +25446,11 @@ function setStyle(style, name, val) {
|
|
|
25273
25446
|
}
|
|
25274
25447
|
}
|
|
25275
25448
|
if (name.startsWith("--")) {
|
|
25276
|
-
|
|
25449
|
+
if (importantRE.test(val)) {
|
|
25450
|
+
style.setProperty(name, val.replace(importantRE, ""), "important");
|
|
25451
|
+
} else {
|
|
25452
|
+
style.setProperty(name, val);
|
|
25453
|
+
}
|
|
25277
25454
|
} else {
|
|
25278
25455
|
const prefixed = autoPrefix(style, name);
|
|
25279
25456
|
if (importantRE.test(val)) {
|
|
@@ -26407,13 +26584,21 @@ const vModelSelect = {
|
|
|
26407
26584
|
const selectedVal = Array.prototype.filter.call(el.options, (o) => o.selected).map(
|
|
26408
26585
|
(o) => number ? (0,_vue_runtime_core__WEBPACK_IMPORTED_MODULE_2__.looseToNumber)(getValue(o)) : getValue(o)
|
|
26409
26586
|
);
|
|
26410
|
-
el
|
|
26411
|
-
|
|
26412
|
-
|
|
26413
|
-
|
|
26414
|
-
|
|
26415
|
-
|
|
26416
|
-
|
|
26587
|
+
const multiple = el.multiple;
|
|
26588
|
+
const assignedValue = multiple ? (0,_vue_runtime_core__WEBPACK_IMPORTED_MODULE_2__.isSet)(el._modelValue) ? new Set(selectedVal) : selectedVal : selectedVal[0];
|
|
26589
|
+
const pending = el._pendingValue = [
|
|
26590
|
+
multiple,
|
|
26591
|
+
multiple ? (0,_vue_runtime_core__WEBPACK_IMPORTED_MODULE_2__.isArray)(assignedValue) ? selectedVal.slice() : selectedVal : assignedValue
|
|
26592
|
+
];
|
|
26593
|
+
try {
|
|
26594
|
+
el[assignKey](assignedValue);
|
|
26595
|
+
} finally {
|
|
26596
|
+
;(0,_vue_runtime_core__WEBPACK_IMPORTED_MODULE_0__.nextTick)(() => {
|
|
26597
|
+
if (el._pendingValue === pending) {
|
|
26598
|
+
el._pendingValue = void 0;
|
|
26599
|
+
}
|
|
26600
|
+
});
|
|
26601
|
+
}
|
|
26417
26602
|
});
|
|
26418
26603
|
el[assignKey] = getModelAssigner(vnode);
|
|
26419
26604
|
},
|
|
@@ -26427,11 +26612,25 @@ const vModelSelect = {
|
|
|
26427
26612
|
el[assignKey] = getModelAssigner(vnode);
|
|
26428
26613
|
},
|
|
26429
26614
|
updated(el, { value }) {
|
|
26430
|
-
|
|
26615
|
+
const pending = el._pendingValue;
|
|
26616
|
+
el._pendingValue = void 0;
|
|
26617
|
+
if (!pending || pending[0] !== el.multiple || !isSameSelectValue(value, pending[1], pending[0])) {
|
|
26431
26618
|
setSelected(el, value);
|
|
26432
26619
|
}
|
|
26433
26620
|
}
|
|
26434
26621
|
};
|
|
26622
|
+
function isSameSelectValue(value, assignedValue, multiple) {
|
|
26623
|
+
if (!multiple) return (0,_vue_runtime_core__WEBPACK_IMPORTED_MODULE_2__.looseEqual)(value, assignedValue);
|
|
26624
|
+
if ((0,_vue_runtime_core__WEBPACK_IMPORTED_MODULE_2__.isArray)(value)) return (0,_vue_runtime_core__WEBPACK_IMPORTED_MODULE_2__.looseEqual)(value, assignedValue);
|
|
26625
|
+
if ((0,_vue_runtime_core__WEBPACK_IMPORTED_MODULE_2__.isSet)(value)) {
|
|
26626
|
+
if (value.size !== assignedValue.length) return false;
|
|
26627
|
+
for (const item of assignedValue) {
|
|
26628
|
+
if (!value.has(item)) return false;
|
|
26629
|
+
}
|
|
26630
|
+
return true;
|
|
26631
|
+
}
|
|
26632
|
+
return false;
|
|
26633
|
+
}
|
|
26435
26634
|
function setSelected(el, value) {
|
|
26436
26635
|
const isMultiple = el.multiple;
|
|
26437
26636
|
const isArrayValue = (0,_vue_runtime_core__WEBPACK_IMPORTED_MODULE_2__.isArray)(value);
|
|
@@ -26812,7 +27011,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
26812
27011
|
/* harmony export */ toTypeString: () => (/* binding */ toTypeString)
|
|
26813
27012
|
/* harmony export */ });
|
|
26814
27013
|
/**
|
|
26815
|
-
* @vue/shared v3.5.
|
|
27014
|
+
* @vue/shared v3.5.42
|
|
26816
27015
|
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
|
26817
27016
|
* @license MIT
|
|
26818
27017
|
**/
|
|
@@ -27153,7 +27352,7 @@ const isBooleanAttr = /* @__PURE__ */ makeMap(
|
|
|
27153
27352
|
function includeBooleanAttr(value) {
|
|
27154
27353
|
return !!value || value === "";
|
|
27155
27354
|
}
|
|
27156
|
-
const unsafeAttrCharRE = /[>/="'\u0009\u000a\u000c\u0020]/;
|
|
27355
|
+
const unsafeAttrCharRE = /[>/="'\u0009\u000a\u000c\u000d\u0020]/;
|
|
27157
27356
|
const attrValidationCache = {};
|
|
27158
27357
|
function isSSRSafeAttrName(name) {
|
|
27159
27358
|
if (attrValidationCache.hasOwnProperty(name)) {
|
|
@@ -27252,6 +27451,23 @@ function looseCompareArrays(a, b) {
|
|
|
27252
27451
|
}
|
|
27253
27452
|
return equal;
|
|
27254
27453
|
}
|
|
27454
|
+
function looseCompareCollections(a, b) {
|
|
27455
|
+
if (a.size !== b.size) return false;
|
|
27456
|
+
const candidates = Array.from(b);
|
|
27457
|
+
const matched = new Uint8Array(candidates.length);
|
|
27458
|
+
for (const item of a) {
|
|
27459
|
+
let index = -1;
|
|
27460
|
+
for (let i = 0; i < candidates.length; i++) {
|
|
27461
|
+
if (!matched[i] && looseEqual(item, candidates[i])) {
|
|
27462
|
+
index = i;
|
|
27463
|
+
break;
|
|
27464
|
+
}
|
|
27465
|
+
}
|
|
27466
|
+
if (index < 0) return false;
|
|
27467
|
+
matched[index] = 1;
|
|
27468
|
+
}
|
|
27469
|
+
return true;
|
|
27470
|
+
}
|
|
27255
27471
|
function looseEqual(a, b) {
|
|
27256
27472
|
if (a === b) return true;
|
|
27257
27473
|
let aValidType = isDate(a);
|
|
@@ -27275,6 +27491,16 @@ function looseEqual(a, b) {
|
|
|
27275
27491
|
if (!aValidType || !bValidType) {
|
|
27276
27492
|
return false;
|
|
27277
27493
|
}
|
|
27494
|
+
aValidType = isMap(a);
|
|
27495
|
+
bValidType = isMap(b);
|
|
27496
|
+
if (aValidType || bValidType) {
|
|
27497
|
+
return aValidType && bValidType ? looseCompareCollections(a, b) : false;
|
|
27498
|
+
}
|
|
27499
|
+
aValidType = isSet(a);
|
|
27500
|
+
bValidType = isSet(b);
|
|
27501
|
+
if (aValidType || bValidType) {
|
|
27502
|
+
return aValidType && bValidType ? looseCompareCollections(a, b) : false;
|
|
27503
|
+
}
|
|
27278
27504
|
const aKeysCount = Object.keys(a).length;
|
|
27279
27505
|
const bKeysCount = Object.keys(b).length;
|
|
27280
27506
|
if (aKeysCount !== bKeysCount) {
|
|
@@ -52532,7 +52758,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
52532
52758
|
/* harmony import */ var _vue_runtime_dom__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @vue/runtime-dom */ "./node_modules/@vue/runtime-core/dist/runtime-core.esm-bundler.js");
|
|
52533
52759
|
/* harmony import */ var _vue_runtime_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @vue/runtime-dom */ "./node_modules/@vue/runtime-dom/dist/runtime-dom.esm-bundler.js");
|
|
52534
52760
|
/**
|
|
52535
|
-
* vue v3.5.
|
|
52761
|
+
* vue v3.5.42
|
|
52536
52762
|
* (c) 2018-present Yuxi (Evan) You and Vue contributors
|
|
52537
52763
|
* @license MIT
|
|
52538
52764
|
**/
|
|
@@ -54390,7 +54616,7 @@ module.exports = ".models {\n position: relative;\n display: flex;\n flex-dir
|
|
|
54390
54616
|
(module) {
|
|
54391
54617
|
|
|
54392
54618
|
"use strict";
|
|
54393
|
-
module.exports = "<div class=\"models flex\" style=\"height: calc(100vh - 55px); height: calc(100dvh - 55px)\">\n <aside class=\"bg-page border-r overflow-hidden transition-all duration-300 ease-in-out z-20 w-0 lg:w-64 fixed lg:relative shrink-0 flex flex-col top-[55px] bottom-0 lg:top-auto lg:bottom-auto lg:h-full\" :class=\"hideSidebar === true ? '!w-0' : hideSidebar === false ? '!w-64' : ''\">\n <!-- Search -->\n <div class=\"p-3 shrink-0\">\n <div class=\"relative\">\n <svg class=\"absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\" />\n </svg>\n <input\n v-model=\"modelSearch\"\n type=\"text\"\n placeholder=\"Find model...\"\n @keydown.esc=\"modelSearch = ''\"\n class=\"w-full rounded-md border border-edge bg-surface py-1.5 pl-8 pr-3 text-sm text-content placeholder:text-gray-400 focus:border-edge-strong focus:outline-none focus:ring-1 focus:ring-gray-300\"\n />\n </div>\n </div>\n <!-- Model list (scrollable) -->\n <nav class=\"flex-1 overflow-y-auto px-2 pb-2\">\n <!-- Recently Viewed -->\n <div v-if=\"filteredRecentModels.length > 0 && !modelSearch.trim()\">\n <div class=\"px-2 py-1 text-xs font-semibold text-gray-400 uppercase tracking-wider\">Recently Viewed</div>\n <ul role=\"list\">\n <li v-for=\"model in filteredRecentModels\" :key=\"'recent-' + model\">\n <router-link\n :to=\"'/model/' + model\"\n class=\"flex items-center rounded-md py-1.5 px-2 text-sm text-content-secondary\"\n :class=\"model === currentModel ? 'bg-gray-200 font-semibold text-content' : 'hover:bg-muted'\">\n <span class=\"truncate\" v-html=\"highlightMatch(model)\"></span>\n <span\n v-if=\"modelDocumentCounts && modelDocumentCounts[model] !== undefined && model !== currentModel\"\n class=\"ml-auto text-xs text-gray-400 bg-muted rounded px-1.5 py-[1px]\"\n >\n {{formatCompactCount(modelDocumentCounts[model])}}\n </span>\n </router-link>\n </li>\n </ul>\n <div class=\"border-b border-edge my-2\"></div>\n </div>\n <!-- All Models / Search Results -->\n <div class=\"px-2 py-1 text-xs font-semibold text-gray-400 uppercase tracking-wider\">{{ modelSearch.trim() ? 'Search Results' : 'All Models' }}</div>\n <ul role=\"list\">\n <li v-for=\"model in filteredModels\" :key=\"'all-' + model\">\n <router-link\n :to=\"'/model/' + model\"\n class=\"flex items-center rounded-md py-1.5 px-2 text-sm text-content-secondary\"\n :class=\"model === currentModel ? 'bg-gray-200 font-semibold text-content' : 'hover:bg-muted'\">\n <span class=\"truncate\" v-html=\"highlightMatch(model)\"></span>\n <span\n v-if=\"modelDocumentCounts && modelDocumentCounts[model] !== undefined && model !== currentModel\"\n class=\"ml-auto text-xs text-gray-400 bg-muted rounded px-1.5 py-[1px]\"\n >\n {{formatCompactCount(modelDocumentCounts[model])}}\n </span>\n </router-link>\n </li>\n </ul>\n <div v-if=\"filteredModels.length === 0 && modelSearch.trim()\" class=\"px-2 py-2 text-sm text-content-tertiary\">\n No models match \"{{modelSearch}}\"\n </div>\n <div v-if=\"models.length === 0 && status === 'loaded'\" class=\"p-2 bg-red-100 rounded-md\">\n No models found\n </div>\n </nav>\n <!-- Bottom toolbar -->\n <div class=\"shrink-0 border-t border-edge bg-page px-2 py-1.5 flex items-center gap-1\">\n <button\n type=\"button\"\n @click=\"hideSidebar = true\"\n class=\"rounded p-1.5 text-gray-400 hover:text-gray-600 hover:bg-muted\"\n title=\"Hide sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5\" />\n </svg>\n </button>\n <button\n type=\"button\"\n @click=\"openModelSwitcher\"\n class=\"rounded p-1.5 text-gray-400 hover:text-gray-600 hover:bg-muted\"\n title=\"Quick switch (Ctrl+P)\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\" />\n </svg>\n </button>\n </div>\n </aside>\n <div class=\"documents bg-slate-50 min-w-0\" ref=\"documentsList\">\n <div class=\"documents-menu bg-slate-50\">\n <div class=\"flex flex-row items-center w-full gap-2\">\n <button\n v-if=\"hideSidebar === true || hideSidebar === null\"\n type=\"button\"\n @click=\"hideSidebar = false\"\n class=\"shrink-0 rounded-md p-1.5 text-gray-400 hover:text-gray-600 hover:bg-muted\"\n :class=\"hideSidebar === null ? 'lg:hidden' : ''\"\n title=\"Show sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5\" />\n </svg>\n </button>\n <document-search\n ref=\"documentSearch\"\n :value=\"searchText\"\n :schema-paths=\"schemaPaths\"\n @search=\"search\"\n >\n </document-search>\n <div>\n <span v-if=\"numDocuments == null\">Loading ...</span>\n <span v-else-if=\"typeof numDocuments === 'number'\">{{documents.length}}/{{numDocuments === 1 ? numDocuments + ' document' : numDocuments + ' documents'}}</span>\n </div>\n <button\n @click=\"stagingSelect\"\n type=\"button\"\n :class=\"{\n 'bg-gray-700 ring-inset ring-2 ring-gray-300 text-white hover:bg-gray-600': selectMultiple,\n 'bg-primary hover:bg-primary-hover text-primary-text': !selectMultiple\n }\"\n class=\"rounded px-2 py-2 text-sm font-semibold shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {{ selectMultiple ? 'Cancel' : 'Select' }}\n </button>\n <button\n v-show=\"selectMultiple\"\n @click=\"shouldShowUpdateMultipleModal=true;\"\n type=\"button\"\n 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\"\n >\n Update\n </button>\n <button\n @click=\"shouldShowDeleteMultipleModal=true;\"\n type=\"button\"\n v-show=\"selectMultiple\"\n 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\"\n >\n Delete\n </button>\n <div class=\"relative\" v-show=\"!selectMultiple\" ref=\"actionsMenuContainer\" @keyup.esc.prevent=\"closeActionsMenu\">\n <button\n @click=\"toggleActionsMenu\"\n type=\"button\"\n aria-label=\"More actions\"\n class=\"rounded bg-surface px-2 py-2 text-sm font-semibold text-content-secondary shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-page focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 6.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5Zm0 6a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5Zm0 6a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5Z\" />\n </svg>\n </button>\n <div\n v-if=\"showActionsMenu\"\n class=\"absolute right-0 mt-2 w-48 origin-top-right rounded-md bg-surface shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none z-50\"\n >\n <div class=\"py-1\">\n <button\n @click=\"shouldShowExportModal = true; showActionsMenu = false\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Export\n </button>\n <button\n @click=\"shouldShowCreateModal = true; showActionsMenu = false\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Create\n </button>\n <button\n @click=\"openIndexModal\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Indexes\n </button>\n <button\n @click=\"openAnalyzeSchemaModal\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Analyze Schema\n </button>\n <button\n @click=\"openCollectionInfo\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Collection Info\n </button>\n <button\n @click=\"toggleRowNumbers()\"\n :disabled=\"outputType !== 'table'\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm\"\n :class=\"outputType === 'table' ? 'text-content-secondary hover:bg-muted' : 'text-content-tertiary cursor-not-allowed opacity-50'\"\n >\n {{ showRowNumbers ? 'Hide row numbers' : 'Show row numbers' }}\n </button>\n <button\n @click=\"resetFilter()\"\n :disabled=\"searchText.trim().length === 0\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm\"\n :class=\"searchText.trim().length > 0 ? 'text-content-secondary hover:bg-muted' : 'text-content-tertiary cursor-not-allowed opacity-50'\"\n >\n Reset Filter\n </button>\n <button\n @click=\"toggleProjectionMenu(); showActionsMenu = false\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm hover:bg-muted\"\n :class=\"isProjectionMenuSelected ? 'text-primary font-semibold' : 'text-content-secondary'\"\n >\n {{ isProjectionMenuSelected ? 'Projection (On)' : 'Projection' }}\n </button>\n <button\n v-if=\"isProjectionMenuSelected\"\n @click=\"clearProjection()\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Reset Projection\n </button>\n <async-button\n v-if=\"isProjectionMenuSelected\"\n type=\"button\"\n @click=\"applyDefaultProjectionColumns()\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Default Projection\n </async-button>\n <button\n @click=\"openDropCollectionModal\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-red-700 hover:bg-red-50\"\n >\n Drop Collection\n </button>\n </div>\n </div>\n </div>\n <span class=\"isolate inline-flex rounded-md shadow-sm\">\n <button\n @click=\"setOutputType('table')\"\n type=\"button\"\n class=\"relative inline-flex items-center rounded-none rounded-l-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-page focus:z-10\"\n :class=\"outputType === 'table' ? 'bg-gray-200' : 'bg-surface'\">\n <img class=\"h-5 w-5\" src=\"images/table.svg\">\n </button>\n <button\n @click=\"setOutputType('json')\"\n type=\"button\"\n class=\"relative -ml-px inline-flex items-center px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-page focus:z-10\"\n :class=\"outputType === 'json' ? 'bg-gray-200' : 'bg-surface'\">\n <img class=\"h-5 w-5\" src=\"images/json.svg\">\n </button>\n <button\n @click=\"setOutputType('map')\"\n :disabled=\"geoJsonFields.length === 0\"\n type=\"button\"\n :title=\"geoJsonFields.length > 0 ? 'Map view' : 'No GeoJSON fields detected'\"\n class=\"relative -ml-px inline-flex items-center rounded-none rounded-r-md px-2 py-2 ring-1 ring-inset ring-gray-300 focus:z-10\"\n :class=\"[\n geoJsonFields.length === 0 ? 'text-gray-300 cursor-not-allowed bg-muted' : 'text-gray-400 hover:bg-page',\n outputType === 'map' ? 'bg-gray-200' : (geoJsonFields.length > 0 ? 'bg-surface' : '')\n ]\">\n <svg class=\"h-5 w-5\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 6.75V15m6-6v8.25m.503 3.498 4.875-2.437c.381-.19.622-.58.622-1.006V4.82c0-.836-.88-1.38-1.628-1.006l-3.869 1.934c-.317.159-.69.159-1.006 0L9.503 3.252a1.125 1.125 0 0 0-1.006 0L3.622 5.689C3.24 5.88 3 6.27 3 6.695V19.18c0 .836.88 1.38 1.628 1.006l3.869-1.934c.317-.159.69-.159 1.006 0l4.994 2.497c.317.158.69.158 1.006 0Z\" />\n </svg>\n </button>\n </span>\n </div>\n <div v-if=\"isProjectionMenuSelected && (outputType === 'table' || outputType === 'json')\" class=\"flex items-center gap-2 w-full mt-2 flex-shrink-0\">\n <projection-search\n ref=\"projectionSearch\"\n :value=\"projectionText\"\n :schema-paths=\"schemaPaths\"\n @projection-input=\"projectionText = $event\"\n @apply=\"applyProjectionFromInput\"\n />\n </div>\n </div>\n <!-- In JSON view, this container is the scrollable element used for infinite scroll. -->\n <div class=\"documents-container relative\" ref=\"documentsContainerScroll\" @scroll=\"checkIfScrolledToBottom\">\n <div v-if=\"error\">\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 relative m-4 rounded-md\" role=\"alert\">\n <span class=\"block font-bold\">Error</span>\n <span class=\"block\">{{ error }}</span>\n <span class=\"block mt-2\">\n Need help?\n <a\n href=\"https://discord.gg/P3YCfKYxpy\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"underline font-medium text-red-800 hover:text-red-900\"\n >Ask in Discord</a>\n or\n <a\n href=\"https://github.com/mongoosejs/studio/issues\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"underline font-medium text-red-800 hover:text-red-900\"\n >\n open a GitHub issue.\n </a>\n </span>\n </div>\n </div>\n <div v-else-if=\"outputType === 'table'\" class=\"flex-1 min-h-0 flex flex-col overflow-hidden\">\n <div\n ref=\"documentsScrollContainer\"\n class=\"overflow-x-auto overflow-y-auto flex-1 min-h-0 border border-edge rounded-lg bg-surface\"\n @scroll=\"checkIfScrolledToBottom\"\n >\n <table class=\"min-w-full border-collapse text-sm\">\n <thead class=\"sticky top-0 z-10 bg-slate-100 dark:bg-shark-800 border-b border-edge\">\n <tr>\n <th v-if=\"showRowNumbers\" class=\"px-3 py-2.5 text-left font-medium text-content border-r border-edge whitespace-nowrap align-middle w-0\">\n #\n </th>\n <th\n v-for=\"path in tableDisplayPaths\"\n :key=\"path.path\"\n class=\"px-3 py-2.5 text-left font-medium text-content border-r border-edge last:border-r-0 whitespace-nowrap align-middle\"\n >\n <div class=\"flex items-center gap-2\">\n <span\n @click=\"addPathFilter(path.path)\"\n class=\"cursor-pointer hover:text-primary truncate min-w-0\"\n :title=\"path.path\"\n >\n {{ path.path }}\n </span>\n <span class=\"text-xs text-content-tertiary shrink-0\">({{ path.instance || 'unknown' }})</span>\n <span class=\"inline-flex shrink-0 gap-0.5 items-center\">\n <button\n type=\"button\"\n @click.stop=\"sortDocs(1, path.path)\"\n class=\"p-0.5 rounded text-content-tertiary hover:text-content hover:bg-muted\"\n :class=\"{ 'text-primary font-semibold': sortBy[path.path] === 1 }\"\n :title=\"sortBy[path.path] === 1 ? 'Clear sort' : 'Sort ascending'\"\n >\n ↑\n </button>\n <button\n type=\"button\"\n @click.stop=\"sortDocs(-1, path.path)\"\n class=\"p-0.5 rounded text-content-tertiary hover:text-content hover:bg-muted\"\n :class=\"{ 'text-primary font-semibold': sortBy[path.path] === -1 }\"\n :title=\"sortBy[path.path] === -1 ? 'Clear sort' : 'Sort descending'\"\n >\n ↓\n </button>\n <button\n v-if=\"filteredPaths.length > 0\"\n type=\"button\"\n @click.stop=\"removeField(path)\"\n class=\"p-1.5 rounded-md border border-transparent text-content-tertiary hover:text-valencia-600 hover:bg-valencia-50 hover:border-valencia-200 focus:outline-none focus:ring-2 focus:ring-valencia-500/30\"\n title=\"Remove column\"\n aria-label=\"Remove column\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18 18 6M6 6l12 12\" />\n </svg>\n </button>\n </span>\n </div>\n </th>\n <th v-if=\"filteredPaths.length > 0\" class=\"px-2 py-2.5 border-r border-edge last:border-r-0 align-middle w-0 bg-slate-50 dark:bg-shark-800/80\">\n <div class=\"relative\" ref=\"addFieldContainer\">\n <button\n type=\"button\"\n @click=\"toggleAddFieldDropdown()\"\n class=\"flex items-center justify-center w-8 h-8 rounded border border-dashed border-edge text-content-tertiary hover:border-primary hover:text-primary hover:bg-primary-subtle/30\"\n title=\"Add column\"\n aria-label=\"Add column\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\" class=\"w-5 h-5\"> <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 4.5v15m7.5-7.5h-15\" /> </svg>\n </button>\n <div\n v-if=\"showAddFieldDropdown\"\n class=\"absolute right-0 top-full mt-1 z-[100] min-w-[180px] max-w-[280px] rounded-md border border-edge bg-surface shadow-lg py-1 max-h-48 overflow-y-auto\"\n >\n <input\n v-if=\"availablePathsToAdd.length > 5\"\n ref=\"addFieldFilterInput\"\n v-model=\"addFieldFilterText\"\n type=\"text\"\n placeholder=\"Filter fields...\"\n class=\"mx-2 mb-1 w-[calc(100%-1rem)] rounded border border-edge px-2 py-1 text-sm\"\n @click.stop\n />\n <button\n v-for=\"p in filteredPathsToAdd\"\n :key=\"p.path\"\n type=\"button\"\n class=\"w-full px-3 py-1.5 text-left text-sm hover:bg-muted\"\n @click.stop=\"addField(p)\"\n >\n {{ p.path }}\n </button>\n <p v-if=\"filteredPathsToAdd.length === 0\" class=\"px-3 py-2 text-sm text-content-tertiary\">\n {{ addFieldFilterText.trim() ? 'No matching fields' : 'All fields added' }}\n </p>\n </div>\n </div>\n </th>\n </tr>\n </thead>\n <tbody class=\"bg-surface\">\n <tr\n v-for=\"(document, docIndex) in documents\"\n :key=\"document._id\"\n @click=\"handleDocumentClick(document, $event)\"\n class=\"border-b border-edge cursor-pointer transition-colors\"\n :class=\"selectedDocuments.some(x => x._id.toString() === document._id.toString())\n ? 'bg-blue-200'\n : 'hover:bg-muted'\"\n >\n <td v-if=\"showRowNumbers\" class=\"px-3 py-2 border-r border-edge align-top text-content-tertiary whitespace-nowrap\">\n {{ docIndex + 1 }}\n </td>\n <td\n v-for=\"schemaPath in tableDisplayPaths\"\n :key=\"schemaPath.path\"\n class=\"px-3 py-2 border-r border-edge last:border-r-0 align-top max-w-[280px]\"\n >\n <div class=\"table-cell-content flex items-center gap-1.5 min-w-0 group\">\n <span class=\"min-w-0 overflow-hidden text-ellipsis flex-1\">\n <component\n :is=\"getComponentForPath(schemaPath)\"\n :value=\"getValueForPath(document, schemaPath.path)\"\n :allude=\"getReferenceModel(schemaPath)\"\n />\n </span>\n <button\n type=\"button\"\n class=\"table-cell-copy shrink-0 p-1 rounded text-content-tertiary hover:text-content hover:bg-muted focus:outline-none focus:ring-1 focus:ring-edge\"\n aria-label=\"Copy cell value\"\n @click.stop=\"copyCellValue(getValueForPath(document, schemaPath.path))\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M8 5H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-1M8 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M8 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m0 0h2a2 2 0 0 1 2 2v3m2 4H10m0 0l3-3m-3 3l3 3\" />\n </svg>\n </button>\n </div>\n </td>\n <td v-if=\"filteredPaths.length > 0\" class=\"w-0 px-0 py-0 border-r border-edge last:border-r-0 bg-slate-50/50 dark:bg-shark-800/30\"></td>\n </tr>\n </tbody>\n </table>\n </div>\n <div v-if=\"outputType === 'table' && (loadingMore || (status === 'loading' && documents.length > 0))\" class=\"flex items-center justify-center gap-2 py-3 text-sm text-content-tertiary border-t border-edge bg-surface\">\n <img src=\"images/loader.gif\" alt=\"\" class=\"h-5 w-5\">\n <span>Loading documents…</span>\n </div>\n <p v-if=\"outputType === 'table' && documents.length === 0 && status === 'loaded'\" class=\"mt-2 text-sm text-content-tertiary px-1\">\n No documents to show. Use Projection in the menu to choose columns.\n </p>\n </div>\n <div v-else-if=\"outputType === 'json'\" class=\"flex min-w-0 flex-col space-y-2 p-1 mt-1\">\n <div\n v-for=\"document in documents\"\n :key=\"document._id\"\n @click=\"handleDocumentContainerClick(document, $event)\"\n :class=\"[\n 'group relative min-w-0 max-w-full transition-colors rounded-md border border-slate-100',\n selectedDocuments.some(x => x._id.toString() === document._id.toString()) ? 'bg-blue-200' : 'hover:shadow-sm hover:border-slate-300 bg-surface'\n ]\"\n >\n <router-link\n class=\"absolute top-2 right-2 z-10 inline-flex items-center rounded bg-primary px-2 py-1 text-xs font-semibold text-primary-text shadow-sm transition-opacity duration-150 opacity-0 group-hover:opacity-100 focus-visible:opacity-100 hover:bg-primary-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n :to=\"{ path: '/model/' + currentModel + '/document/' + document._id, query: $route.query }\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n @click.stop\n >\n Open\n </router-link>\n <list-json :value=\"filterDocument(document)\" :references=\"referenceMap\">\n </list-json>\n </div>\n <div v-if=\"outputType === 'json' && (loadingMore || (status === 'loading' && documents.length > 0))\" class=\"flex items-center justify-center gap-2 py-3 text-sm text-content-tertiary\">\n <img src=\"images/loader.gif\" alt=\"\" class=\"h-5 w-5\">\n <span>Loading documents…</span>\n </div>\n </div>\n <div v-else-if=\"outputType === 'map'\" class=\"flex flex-col h-full\">\n <div class=\"p-2 bg-surface border-b flex items-center gap-2\">\n <label class=\"text-sm font-medium text-content-secondary\">GeoJSON Field:</label>\n <select\n :value=\"selectedGeoField\"\n @change=\"setSelectedGeoField($event.target.value)\"\n class=\"rounded-md border border-edge-strong py-1 px-2 text-sm focus:border-primary focus:ring-primary\"\n >\n <option v-for=\"field in geoJsonFields\" :key=\"field.path\" :value=\"field.path\">\n {{ field.label }}\n </option>\n </select>\n <async-button\n @click=\"loadMoreDocuments\"\n :disabled=\"loadedAllDocs\"\n type=\"button\"\n class=\"rounded px-2 py-1 text-xs font-semibold text-primary-text shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n :class=\"loadedAllDocs ? 'bg-gray-400 cursor-not-allowed' : 'bg-primary hover:bg-primary-hover'\"\n >\n Load more\n </async-button>\n </div>\n <div class=\"flex-1 min-h-[400px]\" ref=\"modelsMap\"></div>\n </div>\n <div v-if=\"status === 'loading' && !loadingMore && documents.length === 0\" class=\"loader loader-overlay\" aria-busy=\"true\">\n <img src=\"images/loader.gif\" alt=\"Loading\">\n </div>\n </div>\n </div>\n <modal v-if=\"shouldShowExportModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowExportModal = false\">×</div>\n <export-query-results\n :schemaPaths=\"schemaPaths\"\n :search-text=\"searchText\"\n :currentModel=\"currentModel\"\n @done=\"shouldShowExportModal = false\">\n </export-query-results>\n </template>\n </modal>\n <modal v-if=\"shouldShowIndexModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowIndexModal = false\">×</div>\n <div class=\"text-xl font-bold mb-2\">Indexes</div>\n <div v-for=\"index in mongoDBIndexes\" class=\"w-full flex items-center\">\n <div class=\"grow shrink text-left flex justify-between items-center\" v-if=\"index.name != '_id_'\">\n <div>\n <div class=\"font-bold flex items-center gap-2\">\n <div>{{ index.name }}</div>\n <div v-if=\"isTTLIndex(index)\" class=\"rounded-full bg-primary-subtle px-2 py-0.5 text-xs font-semibold text-primary\">\n TTL: {{ formatTTL(index.expireAfterSeconds) }}\n </div>\n </div>\n <div class=\"text-sm font-mono\">{{ JSON.stringify(index.key) }}</div>\n </div>\n <div>\n <async-button\n type=\"button\"\n @click=\"dropIndex(index.name)\"\n class=\"rounded-md bg-valencia-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-valencia-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600 disabled:bg-gray-400 disabled:cursor-not-allowed\">\n Drop\n </async-button>\n </div>\n </div>\n </div>\n </template>\n </modal>\n <modal v-if=\"shouldShowAnalyzeSchemaModal\" containerClass=\"md:!w-[70vw]\">\n <template v-slot:body>\n <analyze-schema-modal\n :current-model=\"currentModel\"\n @close=\"shouldShowAnalyzeSchemaModal = false\"\n ></analyze-schema-modal>\n </template>\n </modal>\n <modal v-if=\"shouldShowCollectionInfoModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowCollectionInfoModal = false\">×</div>\n <div class=\"text-xl font-bold mb-2\">Collection Info</div>\n <div v-if=\"!collectionInfo\" class=\"text-gray-600\">Loading collection details...</div>\n <div v-else class=\"space-y-3\">\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Documents</div>\n <div class=\"text-content\">{{ formatNumber(collectionInfo.documentCount) }}</div>\n </div>\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Indexes</div>\n <div class=\"text-content\">{{ formatNumber(collectionInfo.indexCount) }}</div>\n </div>\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Total Index Size</div>\n <div class=\"text-content\">{{ formatCollectionSize(collectionInfo.totalIndexSize) }}</div>\n </div>\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Total Storage Size</div>\n <div class=\"text-content\">{{ formatCollectionSize(collectionInfo.size) }}</div>\n </div>\n <div class=\"flex flex-col gap-1\">\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Collation</div>\n <div class=\"text-content\">{{ collectionInfo.hasCollation ? 'Yes' : 'No' }}</div>\n </div>\n <div v-if=\"collectionInfo.hasCollation\" class=\"rounded bg-muted p-3 text-sm text-gray-800 overflow-x-auto\">\n <pre class=\"whitespace-pre-wrap\">{{ JSON.stringify(collectionInfo.collation, null, 2) }}</pre>\n </div>\n </div>\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Capped</div>\n <div class=\"text-content\">{{ collectionInfo.capped ? 'Yes' : 'No' }}</div>\n </div>\n </div>\n </template>\n </modal>\n <modal v-if=\"shouldShowCreateModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowCreateModal = false;\">×</div>\n <create-document :currentModel=\"currentModel\" :paths=\"schemaPaths\" @close=\"closeCreationModal\"></create-document>\n </template>\n </modal>\n <modal v-if=\"shouldShowUpdateMultipleModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowUpdateMultipleModal = false;\">×</div>\n <update-document :currentModel=\"currentModel\" :document=\"selectedDocuments\" :multiple=\"true\" @update=\"updateDocuments\" @close=\"shouldShowUpdateMultipleModal=false;\"></update-document>\n </template>\n </modal>\n <modal v-if=\"shouldShowDeleteMultipleModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowDeleteMultipleModal = false;\">×</div>\n <h2>Are you sure you want to delete {{selectedDocuments.length}} documents?</h2>\n <div>\n <list-json :value=\"selectedDocuments\"></list-json>\n </div>\n <div class=\"flex gap-4\">\n <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\">\n Confirm\n </async-button>\n <button @click=\"shouldShowDeleteMultipleModal = false;\" class=\"rounded bg-gray-400 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-page0 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-500\">\n Cancel\n </button>\n </div>\n </template>\n </modal>\n <modal v-if=\"shouldShowDropCollectionModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowDropCollectionModal = false\">×</div>\n <h2 class=\"text-xl font-bold mb-3\">Are you sure?</h2>\n <p class=\"text-content-secondary mb-3\">\n This will permanently drop the <span class=\"font-semibold\">{{ currentModel }}</span> collection and all its documents.\n </p>\n <div v-if=\"requiresDropCollectionNameConfirmation()\" class=\"rounded border border-red-300 bg-red-50 px-3 py-2 mb-4\">\n <p class=\"text-sm font-semibold text-red-700\">Danger zone</p>\n <p class=\"text-sm text-red-700 mb-2\">Type <span class=\"font-mono font-semibold\">{{ currentModel }}</span> to confirm.</p>\n <input\n v-model=\"dropCollectionConfirmName\"\n type=\"text\"\n :placeholder=\"currentModel\"\n class=\"w-full rounded border border-red-300 px-2 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-red-200\"\n />\n </div>\n <div class=\"flex gap-4\">\n <async-button\n @click=\"dropCollection\"\n :disabled=\"requiresDropCollectionNameConfirmation() && dropCollectionConfirmName !== currentModel\"\n class=\"rounded bg-red-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Drop Collection\n </async-button>\n <button @click=\"shouldShowDropCollectionModal = false\" class=\"rounded bg-gray-400 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-page0\">\n Cancel\n </button>\n </div>\n </template>\n </modal>\n <model-switcher\n :show=\"showModelSwitcher\"\n :models=\"models\"\n :recently-viewed-models=\"recentlyViewedModels\"\n :model-document-counts=\"modelDocumentCounts\"\n @close=\"showModelSwitcher = false\"\n @select=\"selectSwitcherModel\"\n ></model-switcher>\n</div>\n";
|
|
54619
|
+
module.exports = "<div class=\"models flex\" style=\"height: calc(100vh - 55px); height: calc(100dvh - 55px)\">\n <aside class=\"bg-page border-r overflow-hidden transition-all duration-300 ease-in-out z-20 w-0 lg:w-64 fixed lg:relative shrink-0 flex flex-col top-[55px] bottom-0 lg:top-auto lg:bottom-auto lg:h-full\" :class=\"hideSidebar === true ? '!w-0' : hideSidebar === false ? '!w-64' : ''\">\n <!-- Search -->\n <div class=\"p-3 shrink-0\">\n <div class=\"relative\">\n <svg class=\"absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\" />\n </svg>\n <input\n v-model=\"modelSearch\"\n type=\"text\"\n placeholder=\"Find model...\"\n @keydown.esc=\"modelSearch = ''\"\n class=\"w-full rounded-md border border-edge bg-surface py-1.5 pl-8 pr-3 text-sm text-content placeholder:text-gray-400 focus:border-edge-strong focus:outline-none focus:ring-1 focus:ring-gray-300\"\n />\n </div>\n </div>\n <!-- Model list (scrollable) -->\n <nav class=\"flex-1 overflow-y-auto px-2 pb-2\">\n <!-- Recently Viewed -->\n <div v-if=\"filteredRecentModels.length > 0 && !modelSearch.trim()\">\n <div class=\"px-2 py-1 text-xs font-semibold text-gray-400 uppercase tracking-wider\">Recently Viewed</div>\n <ul role=\"list\">\n <li v-for=\"model in filteredRecentModels\" :key=\"'recent-' + model\">\n <router-link\n :to=\"'/model/' + model\"\n class=\"flex items-center rounded-md py-1.5 px-2 text-sm text-content-secondary\"\n :class=\"model === currentModel ? 'bg-gray-200 font-semibold text-content' : 'hover:bg-muted'\">\n <span class=\"truncate\" v-html=\"highlightMatch(model)\"></span>\n <span\n v-if=\"modelDocumentCounts && modelDocumentCounts[model] !== undefined && model !== currentModel\"\n class=\"ml-auto text-xs text-gray-400 bg-muted rounded px-1.5 py-[1px]\"\n >\n {{formatCompactCount(modelDocumentCounts[model])}}\n </span>\n </router-link>\n </li>\n </ul>\n <div class=\"border-b border-edge my-2\"></div>\n </div>\n <!-- All Models / Search Results -->\n <div class=\"px-2 py-1 text-xs font-semibold text-gray-400 uppercase tracking-wider\">{{ modelSearch.trim() ? 'Search Results' : 'All Models' }}</div>\n <ul role=\"list\">\n <li v-for=\"model in filteredModels\" :key=\"'all-' + model\">\n <router-link\n :to=\"'/model/' + model\"\n class=\"flex items-center rounded-md py-1.5 px-2 text-sm text-content-secondary\"\n :class=\"model === currentModel ? 'bg-gray-200 font-semibold text-content' : 'hover:bg-muted'\">\n <span class=\"truncate\" v-html=\"highlightMatch(model)\"></span>\n <span\n v-if=\"modelDocumentCounts && modelDocumentCounts[model] !== undefined && model !== currentModel\"\n class=\"ml-auto text-xs text-gray-400 bg-muted rounded px-1.5 py-[1px]\"\n >\n {{formatCompactCount(modelDocumentCounts[model])}}\n </span>\n </router-link>\n </li>\n </ul>\n <div v-if=\"filteredModels.length === 0 && modelSearch.trim()\" class=\"px-2 py-2 text-sm text-content-tertiary\">\n No models match \"{{modelSearch}}\"\n </div>\n <div v-if=\"models.length === 0 && status === 'loaded'\" class=\"p-2 bg-red-100 rounded-md\">\n No models found\n </div>\n </nav>\n <!-- Bottom toolbar -->\n <div class=\"shrink-0 border-t border-edge bg-page px-2 py-1.5 flex items-center gap-1\">\n <button\n type=\"button\"\n @click=\"hideSidebar = true\"\n class=\"rounded p-1.5 text-gray-400 hover:text-gray-600 hover:bg-muted\"\n title=\"Hide sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5\" />\n </svg>\n </button>\n <button\n type=\"button\"\n @click=\"openModelSwitcher\"\n class=\"rounded p-1.5 text-gray-400 hover:text-gray-600 hover:bg-muted\"\n title=\"Quick switch (Ctrl+P)\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z\" />\n </svg>\n </button>\n </div>\n </aside>\n <div class=\"documents bg-slate-50 min-w-0\" ref=\"documentsList\">\n <div class=\"documents-menu bg-slate-50\">\n <div class=\"flex flex-row items-center w-full gap-2\">\n <button\n v-if=\"hideSidebar === true || hideSidebar === null\"\n type=\"button\"\n @click=\"hideSidebar = false\"\n class=\"shrink-0 rounded-md p-1.5 text-gray-400 hover:text-gray-600 hover:bg-muted\"\n :class=\"hideSidebar === null ? 'lg:hidden' : ''\"\n title=\"Show sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5\" />\n </svg>\n </button>\n <document-search\n ref=\"documentSearch\"\n :value=\"searchText\"\n :schema-paths=\"schemaPaths\"\n @search=\"search\"\n >\n </document-search>\n <div>\n <tooltip\n v-if=\"numDocumentsError\"\n :text=\"'Error counting documents: ' + numDocumentsError\"\n >\n <span\n class=\"inline-flex rounded-md bg-red-50 px-2 py-2 text-sm text-red-700 ring-1 ring-inset ring-red-200\"\n role=\"alert\"\n >\n Count Error\n </span>\n </tooltip>\n <span v-else-if=\"numDocuments == null\">Loading...</span>\n <span v-else-if=\"typeof numDocuments === 'number'\">{{documents.length}}/{{numDocuments === 1 ? numDocuments + ' document' : numDocuments + ' documents'}}</span>\n </div>\n <button\n @click=\"stagingSelect\"\n type=\"button\"\n :class=\"{\n 'bg-gray-700 ring-inset ring-2 ring-gray-300 text-white hover:bg-gray-600': selectMultiple,\n 'bg-primary hover:bg-primary-hover text-primary-text': !selectMultiple\n }\"\n class=\"rounded px-2 py-2 text-sm font-semibold shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {{ selectMultiple ? 'Cancel' : 'Select' }}\n </button>\n <button\n v-show=\"selectMultiple\"\n @click=\"shouldShowUpdateMultipleModal=true;\"\n type=\"button\"\n 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\"\n >\n Update\n </button>\n <button\n @click=\"shouldShowDeleteMultipleModal=true;\"\n type=\"button\"\n v-show=\"selectMultiple\"\n 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\"\n >\n Delete\n </button>\n <div class=\"relative\" v-show=\"!selectMultiple\" ref=\"actionsMenuContainer\" @keyup.esc.prevent=\"closeActionsMenu\">\n <button\n @click=\"toggleActionsMenu\"\n type=\"button\"\n aria-label=\"More actions\"\n class=\"rounded bg-surface px-2 py-2 text-sm font-semibold text-content-secondary shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-page focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 6.75a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5Zm0 6a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5Zm0 6a.75.75 0 1 1 0-1.5.75.75 0 0 1 0 1.5Z\" />\n </svg>\n </button>\n <div\n v-if=\"showActionsMenu\"\n class=\"absolute right-0 mt-2 w-48 origin-top-right rounded-md bg-surface shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none z-50\"\n >\n <div class=\"py-1\">\n <button\n @click=\"shouldShowExportModal = true; showActionsMenu = false\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Export\n </button>\n <button\n @click=\"shouldShowCreateModal = true; showActionsMenu = false\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Create\n </button>\n <button\n @click=\"openIndexModal\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Indexes\n </button>\n <button\n @click=\"openAnalyzeSchemaModal\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Analyze Schema\n </button>\n <button\n @click=\"openCollectionInfo\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Collection Info\n </button>\n <button\n @click=\"toggleRowNumbers()\"\n :disabled=\"outputType !== 'table'\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm\"\n :class=\"outputType === 'table' ? 'text-content-secondary hover:bg-muted' : 'text-content-tertiary cursor-not-allowed opacity-50'\"\n >\n {{ showRowNumbers ? 'Hide row numbers' : 'Show row numbers' }}\n </button>\n <button\n @click=\"resetFilter()\"\n :disabled=\"searchText.trim().length === 0\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm\"\n :class=\"searchText.trim().length > 0 ? 'text-content-secondary hover:bg-muted' : 'text-content-tertiary cursor-not-allowed opacity-50'\"\n >\n Reset Filter\n </button>\n <button\n @click=\"toggleProjectionMenu(); showActionsMenu = false\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm hover:bg-muted\"\n :class=\"isProjectionMenuSelected ? 'text-primary font-semibold' : 'text-content-secondary'\"\n >\n {{ isProjectionMenuSelected ? 'Projection (On)' : 'Projection' }}\n </button>\n <button\n v-if=\"isProjectionMenuSelected\"\n @click=\"clearProjection()\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Reset Projection\n </button>\n <async-button\n v-if=\"isProjectionMenuSelected\"\n type=\"button\"\n @click=\"applyDefaultProjectionColumns()\"\n class=\"block w-full px-4 py-2 text-left text-sm text-content-secondary hover:bg-muted\"\n >\n Default Projection\n </async-button>\n <button\n @click=\"openDropCollectionModal\"\n type=\"button\"\n class=\"block w-full px-4 py-2 text-left text-sm text-red-700 hover:bg-red-50\"\n >\n Drop Collection\n </button>\n </div>\n </div>\n </div>\n <span class=\"isolate inline-flex rounded-md shadow-sm\">\n <button\n @click=\"setOutputType('table')\"\n type=\"button\"\n class=\"relative inline-flex items-center rounded-none rounded-l-md px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-page focus:z-10\"\n :class=\"outputType === 'table' ? 'bg-gray-200' : 'bg-surface'\">\n <img class=\"h-5 w-5\" src=\"images/table.svg\">\n </button>\n <button\n @click=\"setOutputType('json')\"\n type=\"button\"\n class=\"relative -ml-px inline-flex items-center px-2 py-2 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-page focus:z-10\"\n :class=\"outputType === 'json' ? 'bg-gray-200' : 'bg-surface'\">\n <img class=\"h-5 w-5\" src=\"images/json.svg\">\n </button>\n <button\n @click=\"setOutputType('map')\"\n :disabled=\"geoJsonFields.length === 0\"\n type=\"button\"\n :title=\"geoJsonFields.length > 0 ? 'Map view' : 'No GeoJSON fields detected'\"\n class=\"relative -ml-px inline-flex items-center rounded-none rounded-r-md px-2 py-2 ring-1 ring-inset ring-gray-300 focus:z-10\"\n :class=\"[\n geoJsonFields.length === 0 ? 'text-gray-300 cursor-not-allowed bg-muted' : 'text-gray-400 hover:bg-page',\n outputType === 'map' ? 'bg-gray-200' : (geoJsonFields.length > 0 ? 'bg-surface' : '')\n ]\">\n <svg class=\"h-5 w-5\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 6.75V15m6-6v8.25m.503 3.498 4.875-2.437c.381-.19.622-.58.622-1.006V4.82c0-.836-.88-1.38-1.628-1.006l-3.869 1.934c-.317.159-.69.159-1.006 0L9.503 3.252a1.125 1.125 0 0 0-1.006 0L3.622 5.689C3.24 5.88 3 6.27 3 6.695V19.18c0 .836.88 1.38 1.628 1.006l3.869-1.934c.317-.159.69-.159 1.006 0l4.994 2.497c.317.158.69.158 1.006 0Z\" />\n </svg>\n </button>\n </span>\n </div>\n <div v-if=\"isProjectionMenuSelected && (outputType === 'table' || outputType === 'json')\" class=\"flex items-center gap-2 w-full mt-2 flex-shrink-0\">\n <projection-search\n ref=\"projectionSearch\"\n :value=\"projectionText\"\n :schema-paths=\"schemaPaths\"\n @projection-input=\"projectionText = $event\"\n @apply=\"applyProjectionFromInput\"\n />\n </div>\n </div>\n <!-- In JSON view, this container is the scrollable element used for infinite scroll. -->\n <div class=\"documents-container relative\" ref=\"documentsContainerScroll\" @scroll=\"checkIfScrolledToBottom\">\n <div v-if=\"error\">\n <div class=\"bg-red-100 border border-red-400 text-red-700 px-4 py-3 relative m-4 rounded-md\" role=\"alert\">\n <span class=\"block font-bold\">Error</span>\n <span class=\"block\">{{ error }}</span>\n <span class=\"block mt-2\">\n Need help?\n <a\n href=\"https://discord.gg/P3YCfKYxpy\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"underline font-medium text-red-800 hover:text-red-900\"\n >Ask in Discord</a>\n or\n <a\n href=\"https://github.com/mongoosejs/studio/issues\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"underline font-medium text-red-800 hover:text-red-900\"\n >\n open a GitHub issue.\n </a>\n </span>\n </div>\n </div>\n <div v-else-if=\"outputType === 'table'\" class=\"flex-1 min-h-0 flex flex-col overflow-hidden\">\n <div\n ref=\"documentsScrollContainer\"\n class=\"overflow-x-auto overflow-y-auto flex-1 min-h-0 border border-edge rounded-lg bg-surface\"\n @scroll=\"checkIfScrolledToBottom\"\n >\n <table class=\"min-w-full border-collapse text-sm\">\n <thead class=\"sticky top-0 z-10 bg-slate-100 dark:bg-shark-800 border-b border-edge\">\n <tr>\n <th v-if=\"showRowNumbers\" class=\"px-3 py-2.5 text-left font-medium text-content border-r border-edge whitespace-nowrap align-middle w-0\">\n #\n </th>\n <th\n v-for=\"path in tableDisplayPaths\"\n :key=\"path.path\"\n class=\"px-3 py-2.5 text-left font-medium text-content border-r border-edge last:border-r-0 whitespace-nowrap align-middle\"\n >\n <div class=\"flex items-center gap-2\">\n <span\n @click=\"addPathFilter(path.path)\"\n class=\"cursor-pointer hover:text-primary truncate min-w-0\"\n :title=\"path.path\"\n >\n {{ path.path }}\n </span>\n <span class=\"text-xs text-content-tertiary shrink-0\">({{ path.instance || 'unknown' }})</span>\n <span class=\"inline-flex shrink-0 gap-0.5 items-center\">\n <button\n type=\"button\"\n @click.stop=\"sortDocs(1, path.path)\"\n class=\"p-0.5 rounded text-content-tertiary hover:text-content hover:bg-muted\"\n :class=\"{ 'text-primary font-semibold': sortBy[path.path] === 1 }\"\n :title=\"sortBy[path.path] === 1 ? 'Clear sort' : 'Sort ascending'\"\n >\n ↑\n </button>\n <button\n type=\"button\"\n @click.stop=\"sortDocs(-1, path.path)\"\n class=\"p-0.5 rounded text-content-tertiary hover:text-content hover:bg-muted\"\n :class=\"{ 'text-primary font-semibold': sortBy[path.path] === -1 }\"\n :title=\"sortBy[path.path] === -1 ? 'Clear sort' : 'Sort descending'\"\n >\n ↓\n </button>\n <button\n v-if=\"filteredPaths.length > 0\"\n type=\"button\"\n @click.stop=\"removeField(path)\"\n class=\"p-1.5 rounded-md border border-transparent text-content-tertiary hover:text-valencia-600 hover:bg-valencia-50 hover:border-valencia-200 focus:outline-none focus:ring-2 focus:ring-valencia-500/30\"\n title=\"Remove column\"\n aria-label=\"Remove column\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-4 h-4\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18 18 6M6 6l12 12\" />\n </svg>\n </button>\n </span>\n </div>\n </th>\n <th v-if=\"filteredPaths.length > 0\" class=\"px-2 py-2.5 border-r border-edge last:border-r-0 align-middle w-0 bg-slate-50 dark:bg-shark-800/80\">\n <div class=\"relative\" ref=\"addFieldContainer\">\n <button\n type=\"button\"\n @click=\"toggleAddFieldDropdown()\"\n class=\"flex items-center justify-center w-8 h-8 rounded border border-dashed border-edge text-content-tertiary hover:border-primary hover:text-primary hover:bg-primary-subtle/30\"\n title=\"Add column\"\n aria-label=\"Add column\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"2\" stroke=\"currentColor\" class=\"w-5 h-5\"> <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 4.5v15m7.5-7.5h-15\" /> </svg>\n </button>\n <div\n v-if=\"showAddFieldDropdown\"\n class=\"absolute right-0 top-full mt-1 z-[100] min-w-[180px] max-w-[280px] rounded-md border border-edge bg-surface shadow-lg py-1 max-h-48 overflow-y-auto\"\n >\n <input\n v-if=\"availablePathsToAdd.length > 5\"\n ref=\"addFieldFilterInput\"\n v-model=\"addFieldFilterText\"\n type=\"text\"\n placeholder=\"Filter fields...\"\n class=\"mx-2 mb-1 w-[calc(100%-1rem)] rounded border border-edge px-2 py-1 text-sm\"\n @click.stop\n />\n <button\n v-for=\"p in filteredPathsToAdd\"\n :key=\"p.path\"\n type=\"button\"\n class=\"w-full px-3 py-1.5 text-left text-sm hover:bg-muted\"\n @click.stop=\"addField(p)\"\n >\n {{ p.path }}\n </button>\n <p v-if=\"filteredPathsToAdd.length === 0\" class=\"px-3 py-2 text-sm text-content-tertiary\">\n {{ addFieldFilterText.trim() ? 'No matching fields' : 'All fields added' }}\n </p>\n </div>\n </div>\n </th>\n </tr>\n </thead>\n <tbody class=\"bg-surface\">\n <tr\n v-for=\"(document, docIndex) in documents\"\n :key=\"document._id\"\n @click=\"handleDocumentClick(document, $event)\"\n class=\"border-b border-edge cursor-pointer transition-colors\"\n :class=\"selectedDocuments.some(x => x._id.toString() === document._id.toString())\n ? 'bg-blue-200'\n : 'hover:bg-muted'\"\n >\n <td v-if=\"showRowNumbers\" class=\"px-3 py-2 border-r border-edge align-top text-content-tertiary whitespace-nowrap\">\n {{ docIndex + 1 }}\n </td>\n <td\n v-for=\"schemaPath in tableDisplayPaths\"\n :key=\"schemaPath.path\"\n class=\"px-3 py-2 border-r border-edge last:border-r-0 align-top max-w-[280px]\"\n >\n <div class=\"table-cell-content flex items-center gap-1.5 min-w-0 group\">\n <span class=\"min-w-0 overflow-hidden text-ellipsis flex-1\">\n <component\n :is=\"getComponentForPath(schemaPath)\"\n :value=\"getValueForPath(document, schemaPath.path)\"\n :allude=\"getReferenceModel(schemaPath)\"\n />\n </span>\n <button\n type=\"button\"\n class=\"table-cell-copy shrink-0 p-1 rounded text-content-tertiary hover:text-content hover:bg-muted focus:outline-none focus:ring-1 focus:ring-edge\"\n aria-label=\"Copy cell value\"\n @click.stop=\"copyCellValue(getValueForPath(document, schemaPath.path))\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M8 5H6a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-1M8 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M8 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m0 0h2a2 2 0 0 1 2 2v3m2 4H10m0 0l3-3m-3 3l3 3\" />\n </svg>\n </button>\n </div>\n </td>\n <td v-if=\"filteredPaths.length > 0\" class=\"w-0 px-0 py-0 border-r border-edge last:border-r-0 bg-slate-50/50 dark:bg-shark-800/30\"></td>\n </tr>\n </tbody>\n </table>\n </div>\n <div\n v-if=\"outputType === 'table' && (documentsError || loadingMore || (status === 'loading' && documents.length > 0))\"\n class=\"flex items-center justify-center gap-2 py-3 text-sm border-t\"\n :class=\"documentsError ? 'border-red-200 bg-red-50 text-red-700' : 'border-edge bg-surface text-content-tertiary'\"\n :role=\"documentsError ? 'alert' : null\"\n >\n <img v-if=\"!documentsError\" src=\"images/loader.gif\" alt=\"\" class=\"h-5 w-5\">\n <span>{{documentsError || 'Loading documents…'}}</span>\n </div>\n <p v-if=\"outputType === 'table' && documents.length === 0 && status === 'loaded' && !documentsError\" class=\"mt-2 text-sm text-content-tertiary px-1\">\n No documents to show. Use Projection in the menu to choose columns.\n </p>\n </div>\n <div v-else-if=\"outputType === 'json'\" class=\"flex min-w-0 flex-col space-y-2 p-1 mt-1\">\n <div\n v-for=\"document in documents\"\n :key=\"document._id\"\n @click=\"handleDocumentContainerClick(document, $event)\"\n :class=\"[\n 'group relative min-w-0 max-w-full transition-colors rounded-md border border-slate-100',\n selectedDocuments.some(x => x._id.toString() === document._id.toString()) ? 'bg-blue-200' : 'hover:shadow-sm hover:border-slate-300 bg-surface'\n ]\"\n >\n <router-link\n class=\"absolute top-2 right-2 z-10 inline-flex items-center rounded bg-primary px-2 py-1 text-xs font-semibold text-primary-text shadow-sm transition-opacity duration-150 opacity-0 group-hover:opacity-100 focus-visible:opacity-100 hover:bg-primary-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n :to=\"{ path: '/model/' + currentModel + '/document/' + document._id, query: $route.query }\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n @click.stop\n >\n Open\n </router-link>\n <list-json :value=\"filterDocument(document)\" :references=\"referenceMap\">\n </list-json>\n </div>\n <div\n v-if=\"outputType === 'json' && (documentsError || loadingMore || (status === 'loading' && documents.length > 0))\"\n class=\"flex items-center justify-center gap-2 py-3 text-sm\"\n :class=\"documentsError ? 'rounded-md border border-red-200 bg-red-50 text-red-700' : 'text-content-tertiary'\"\n :role=\"documentsError ? 'alert' : null\"\n >\n <img v-if=\"!documentsError\" src=\"images/loader.gif\" alt=\"\" class=\"h-5 w-5\">\n <span>{{documentsError || 'Loading documents…'}}</span>\n </div>\n </div>\n <div v-else-if=\"outputType === 'map'\" class=\"flex flex-col h-full\">\n <div class=\"p-2 bg-surface border-b flex items-center gap-2\">\n <label class=\"text-sm font-medium text-content-secondary\">GeoJSON Field:</label>\n <select\n :value=\"selectedGeoField\"\n @change=\"setSelectedGeoField($event.target.value)\"\n class=\"rounded-md border border-edge-strong py-1 px-2 text-sm focus:border-primary focus:ring-primary\"\n >\n <option v-for=\"field in geoJsonFields\" :key=\"field.path\" :value=\"field.path\">\n {{ field.label }}\n </option>\n </select>\n <async-button\n @click=\"loadMoreDocuments\"\n :disabled=\"loadedAllDocs\"\n type=\"button\"\n class=\"rounded px-2 py-1 text-xs font-semibold text-primary-text shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n :class=\"loadedAllDocs ? 'bg-gray-400 cursor-not-allowed' : 'bg-primary hover:bg-primary-hover'\"\n >\n Load more\n </async-button>\n </div>\n <div class=\"flex-1 min-h-[400px]\" ref=\"modelsMap\"></div>\n </div>\n <div v-if=\"status === 'loading' && !loadingMore && documents.length === 0\" class=\"loader loader-overlay\" aria-busy=\"true\">\n <img src=\"images/loader.gif\" alt=\"Loading\">\n </div>\n </div>\n </div>\n <modal v-if=\"shouldShowExportModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowExportModal = false\">×</div>\n <export-query-results\n :schemaPaths=\"schemaPaths\"\n :search-text=\"searchText\"\n :currentModel=\"currentModel\"\n @done=\"shouldShowExportModal = false\">\n </export-query-results>\n </template>\n </modal>\n <modal v-if=\"shouldShowIndexModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowIndexModal = false\">×</div>\n <div class=\"text-xl font-bold mb-2\">Indexes</div>\n <div v-for=\"index in mongoDBIndexes\" class=\"w-full flex items-center\">\n <div class=\"grow shrink text-left flex justify-between items-center\" v-if=\"index.name != '_id_'\">\n <div>\n <div class=\"font-bold flex items-center gap-2\">\n <div>{{ index.name }}</div>\n <div v-if=\"isTTLIndex(index)\" class=\"rounded-full bg-primary-subtle px-2 py-0.5 text-xs font-semibold text-primary\">\n TTL: {{ formatTTL(index.expireAfterSeconds) }}\n </div>\n </div>\n <div class=\"text-sm font-mono\">{{ JSON.stringify(index.key) }}</div>\n </div>\n <div>\n <async-button\n type=\"button\"\n @click=\"dropIndex(index.name)\"\n class=\"rounded-md bg-valencia-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-valencia-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600 disabled:bg-gray-400 disabled:cursor-not-allowed\">\n Drop\n </async-button>\n </div>\n </div>\n </div>\n </template>\n </modal>\n <modal v-if=\"shouldShowAnalyzeSchemaModal\" containerClass=\"md:!w-[70vw]\">\n <template v-slot:body>\n <analyze-schema-modal\n :current-model=\"currentModel\"\n @close=\"shouldShowAnalyzeSchemaModal = false\"\n ></analyze-schema-modal>\n </template>\n </modal>\n <modal v-if=\"shouldShowCollectionInfoModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowCollectionInfoModal = false\">×</div>\n <div class=\"text-xl font-bold mb-2\">Collection Info</div>\n <div v-if=\"!collectionInfo\" class=\"text-gray-600\">Loading collection details...</div>\n <div v-else class=\"space-y-3\">\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Documents</div>\n <div class=\"text-content\">{{ formatNumber(collectionInfo.documentCount) }}</div>\n </div>\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Indexes</div>\n <div class=\"text-content\">{{ formatNumber(collectionInfo.indexCount) }}</div>\n </div>\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Total Index Size</div>\n <div class=\"text-content\">{{ formatCollectionSize(collectionInfo.totalIndexSize) }}</div>\n </div>\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Total Storage Size</div>\n <div class=\"text-content\">{{ formatCollectionSize(collectionInfo.size) }}</div>\n </div>\n <div class=\"flex flex-col gap-1\">\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Collation</div>\n <div class=\"text-content\">{{ collectionInfo.hasCollation ? 'Yes' : 'No' }}</div>\n </div>\n <div v-if=\"collectionInfo.hasCollation\" class=\"rounded bg-muted p-3 text-sm text-gray-800 overflow-x-auto\">\n <pre class=\"whitespace-pre-wrap\">{{ JSON.stringify(collectionInfo.collation, null, 2) }}</pre>\n </div>\n </div>\n <div class=\"flex justify-between gap-4\">\n <div class=\"font-semibold text-content-secondary\">Capped</div>\n <div class=\"text-content\">{{ collectionInfo.capped ? 'Yes' : 'No' }}</div>\n </div>\n </div>\n </template>\n </modal>\n <modal v-if=\"shouldShowCreateModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowCreateModal = false;\">×</div>\n <create-document :currentModel=\"currentModel\" :paths=\"schemaPaths\" @close=\"closeCreationModal\"></create-document>\n </template>\n </modal>\n <modal v-if=\"shouldShowUpdateMultipleModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowUpdateMultipleModal = false;\">×</div>\n <update-document :currentModel=\"currentModel\" :document=\"selectedDocuments\" :multiple=\"true\" @update=\"updateDocuments\" @close=\"shouldShowUpdateMultipleModal=false;\"></update-document>\n </template>\n </modal>\n <modal v-if=\"shouldShowDeleteMultipleModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowDeleteMultipleModal = false;\">×</div>\n <h2>Are you sure you want to delete {{selectedDocuments.length}} documents?</h2>\n <div>\n <list-json :value=\"selectedDocuments\"></list-json>\n </div>\n <div class=\"flex gap-4\">\n <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\">\n Confirm\n </async-button>\n <button @click=\"shouldShowDeleteMultipleModal = false;\" class=\"rounded bg-gray-400 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-page0 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-500\">\n Cancel\n </button>\n </div>\n </template>\n </modal>\n <modal v-if=\"shouldShowDropCollectionModal\">\n <template v-slot:body>\n <div class=\"modal-exit\" @click=\"shouldShowDropCollectionModal = false\">×</div>\n <h2 class=\"text-xl font-bold mb-3\">Are you sure?</h2>\n <p class=\"text-content-secondary mb-3\">\n This will permanently drop the <span class=\"font-semibold\">{{ currentModel }}</span> collection and all its documents.\n </p>\n <div v-if=\"requiresDropCollectionNameConfirmation()\" class=\"rounded border border-red-300 bg-red-50 px-3 py-2 mb-4\">\n <p class=\"text-sm font-semibold text-red-700\">Danger zone</p>\n <p class=\"text-sm text-red-700 mb-2\">Type <span class=\"font-mono font-semibold\">{{ currentModel }}</span> to confirm.</p>\n <input\n v-model=\"dropCollectionConfirmName\"\n type=\"text\"\n :placeholder=\"currentModel\"\n class=\"w-full rounded border border-red-300 px-2 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-red-200\"\n />\n </div>\n <div class=\"flex gap-4\">\n <async-button\n @click=\"dropCollection\"\n :disabled=\"requiresDropCollectionNameConfirmation() && dropCollectionConfirmName !== currentModel\"\n class=\"rounded bg-red-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n Drop Collection\n </async-button>\n <button @click=\"shouldShowDropCollectionModal = false\" class=\"rounded bg-gray-400 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-page0\">\n Cancel\n </button>\n </div>\n </template>\n </modal>\n <model-switcher\n :show=\"showModelSwitcher\"\n :models=\"models\"\n :recently-viewed-models=\"recentlyViewedModels\"\n :model-document-counts=\"modelDocumentCounts\"\n @close=\"showModelSwitcher = false\"\n @select=\"selectSwitcherModel\"\n ></model-switcher>\n</div>\n";
|
|
54394
54620
|
|
|
54395
54621
|
/***/ },
|
|
54396
54622
|
|
|
@@ -54526,6 +54752,17 @@ module.exports = "<div class=\"mx-auto max-w-5xl py-6 px-2 flex flex-col gap-8\"
|
|
|
54526
54752
|
|
|
54527
54753
|
/***/ },
|
|
54528
54754
|
|
|
54755
|
+
/***/ "./frontend/src/tooltip/tooltip.html"
|
|
54756
|
+
/*!*******************************************!*\
|
|
54757
|
+
!*** ./frontend/src/tooltip/tooltip.html ***!
|
|
54758
|
+
\*******************************************/
|
|
54759
|
+
(module) {
|
|
54760
|
+
|
|
54761
|
+
"use strict";
|
|
54762
|
+
module.exports = "<span\n ref=\"trigger\"\n class=\"inline-flex outline-none focus-visible:rounded-md focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600\"\n tabindex=\"0\"\n :aria-describedby=\"isOpen ? tooltipId : null\"\n @mouseenter=\"show\"\n @mouseleave=\"hideUnlessPinned\"\n @focusin=\"show\"\n @focusout=\"handleFocusOut\"\n @click=\"toggle\"\n @keydown.esc.stop=\"hide\"\n>\n <slot></slot>\n <span\n v-show=\"isOpen\"\n ref=\"tooltip\"\n :id=\"tooltipId\"\n class=\"pointer-events-none fixed z-[1000] w-max max-w-[min(20rem,calc(100vw-1rem))] whitespace-normal rounded-md bg-gray-900 px-2.5 py-1.5 text-xs font-normal leading-4 text-white shadow-lg\"\n :style=\"tooltipStyle\"\n role=\"tooltip\"\n >\n {{ text }}\n <span\n class=\"absolute left-1/2 h-2 w-2 -translate-x-1/2 rotate-45 bg-gray-900\"\n :class=\"placement === 'bottom' ? '-top-1' : '-bottom-1'\"\n ></span>\n </span>\n</span>\n";
|
|
54763
|
+
|
|
54764
|
+
/***/ },
|
|
54765
|
+
|
|
54529
54766
|
/***/ "./frontend/src/update-document/update-document.css"
|
|
54530
54767
|
/*!**********************************************************!*\
|
|
54531
54768
|
!*** ./frontend/src/update-document/update-document.css ***!
|
|
@@ -62994,11 +63231,20 @@ class ObjectId extends BSONValue {
|
|
|
62994
63231
|
|
|
62995
63232
|
function internalCalculateObjectSize(object, serializeFunctions, ignoreUndefined) {
|
|
62996
63233
|
const objectStack = [
|
|
62997
|
-
{
|
|
63234
|
+
{ object, ignoreUndefined: ignoreUndefined ?? false, exit: false }
|
|
62998
63235
|
];
|
|
63236
|
+
const path = new Set();
|
|
62999
63237
|
let total = 0;
|
|
63000
63238
|
while (objectStack.length > 0) {
|
|
63001
|
-
const
|
|
63239
|
+
const frame = objectStack.pop();
|
|
63240
|
+
if (frame.exit) {
|
|
63241
|
+
path.delete(frame.object);
|
|
63242
|
+
continue;
|
|
63243
|
+
}
|
|
63244
|
+
const { object: obj, ignoreUndefined: frameIgnoreUndefined } = frame;
|
|
63245
|
+
path.add(obj);
|
|
63246
|
+
frame.exit = true;
|
|
63247
|
+
objectStack.push(frame);
|
|
63002
63248
|
total += 5;
|
|
63003
63249
|
const isObjArray = Array.isArray(obj);
|
|
63004
63250
|
const isObjMap = !isObjArray && (obj instanceof Map || isMap(obj));
|
|
@@ -63009,23 +63255,23 @@ function internalCalculateObjectSize(object, serializeFunctions, ignoreUndefined
|
|
|
63009
63255
|
if (isObjArray) {
|
|
63010
63256
|
const array = target;
|
|
63011
63257
|
for (let i = 0; i < array.length; i++) {
|
|
63012
|
-
total += calculateElementSize(i.toString(), array[i], serializeFunctions, true, frameIgnoreUndefined, objectStack);
|
|
63258
|
+
total += calculateElementSize(i.toString(), array[i], serializeFunctions, true, frameIgnoreUndefined, objectStack, path);
|
|
63013
63259
|
}
|
|
63014
63260
|
}
|
|
63015
63261
|
else if (isObjMap) {
|
|
63016
63262
|
for (const [key, value] of target) {
|
|
63017
|
-
total += calculateElementSize(key, value, serializeFunctions, false, frameIgnoreUndefined, objectStack);
|
|
63263
|
+
total += calculateElementSize(key, value, serializeFunctions, false, frameIgnoreUndefined, objectStack, path);
|
|
63018
63264
|
}
|
|
63019
63265
|
}
|
|
63020
63266
|
else {
|
|
63021
63267
|
for (const key of Object.keys(target)) {
|
|
63022
|
-
total += calculateElementSize(key, target[key], serializeFunctions, false, frameIgnoreUndefined, objectStack);
|
|
63268
|
+
total += calculateElementSize(key, target[key], serializeFunctions, false, frameIgnoreUndefined, objectStack, path);
|
|
63023
63269
|
}
|
|
63024
63270
|
}
|
|
63025
63271
|
}
|
|
63026
63272
|
return total;
|
|
63027
63273
|
}
|
|
63028
|
-
function calculateElementSize(name, value, serializeFunctions = false, isArray = false, ignoreUndefined = false, objectStack) {
|
|
63274
|
+
function calculateElementSize(name, value, serializeFunctions = false, isArray = false, ignoreUndefined = false, objectStack, path) {
|
|
63029
63275
|
if (typeof value?.toBSON === 'function') {
|
|
63030
63276
|
value = value.toBSON();
|
|
63031
63277
|
}
|
|
@@ -63085,7 +63331,10 @@ function calculateElementSize(name, value, serializeFunctions = false, isArray =
|
|
|
63085
63331
|
}
|
|
63086
63332
|
else if (value._bsontype === 'Code') {
|
|
63087
63333
|
if (value.scope != null && Object.keys(value.scope).length > 0) {
|
|
63088
|
-
|
|
63334
|
+
if (path.has(value.scope)) {
|
|
63335
|
+
throw new BSONError('Cannot convert circular structure to BSON');
|
|
63336
|
+
}
|
|
63337
|
+
objectStack.push({ object: value.scope, ignoreUndefined, exit: false });
|
|
63089
63338
|
return (ByteUtils.utf8ByteLength(name) +
|
|
63090
63339
|
1 +
|
|
63091
63340
|
1 +
|
|
@@ -63123,7 +63372,7 @@ function calculateElementSize(name, value, serializeFunctions = false, isArray =
|
|
|
63123
63372
|
if (value.db != null) {
|
|
63124
63373
|
ordered_values['$db'] = value.db;
|
|
63125
63374
|
}
|
|
63126
|
-
objectStack.push({
|
|
63375
|
+
objectStack.push({ object: ordered_values, ignoreUndefined: true, exit: false });
|
|
63127
63376
|
return ByteUtils.utf8ByteLength(name) + 1 + 1;
|
|
63128
63377
|
}
|
|
63129
63378
|
else if (value instanceof RegExp || isRegExp(value)) {
|
|
@@ -63147,7 +63396,10 @@ function calculateElementSize(name, value, serializeFunctions = false, isArray =
|
|
|
63147
63396
|
1);
|
|
63148
63397
|
}
|
|
63149
63398
|
else {
|
|
63150
|
-
|
|
63399
|
+
if (path.has(value)) {
|
|
63400
|
+
throw new BSONError('Cannot convert circular structure to BSON');
|
|
63401
|
+
}
|
|
63402
|
+
objectStack.push({ object: value, ignoreUndefined, exit: false });
|
|
63151
63403
|
return ByteUtils.utf8ByteLength(name) + 1 + 1;
|
|
63152
63404
|
}
|
|
63153
63405
|
case 'function':
|
|
@@ -66010,7 +66262,7 @@ var src_default = VueToastificationPlugin;
|
|
|
66010
66262
|
(module) {
|
|
66011
66263
|
|
|
66012
66264
|
"use strict";
|
|
66013
|
-
module.exports = /*#__PURE__*/JSON.parse('{"name":"@mongoosejs/studio","version":"0.5.
|
|
66265
|
+
module.exports = /*#__PURE__*/JSON.parse('{"name":"@mongoosejs/studio","version":"0.5.14","description":"AI-Powered Data Workspace for MongoDB: Turn your MongoDB data into dashboards, maps, and interactive workflows - powered by your Mongoose models and AI.","homepage":"https://mongoosestudio.app/","repository":{"type":"git","url":"https://github.com/mongoosejs/studio"},"license":"Apache-2.0","dependencies":{"@ai-sdk/anthropic":"2.x","@ai-sdk/google":"2.x","@ai-sdk/openai":"2.x","ace-builds":"^1.43.6","ai":"5.x","archetype":"0.13.1","csv-stringify":"6.3.0","ejson":"^2.2.3","extrovert":"^0.2.0","marked":"15.0.12","mpath":"^0.9.0","node-inspect-extracted":"3.x","regexp.escape":"^2.0.1","tailwindcss":"3.4.0","time-commando":"1.0.1","typescript":"^6.0.2","vue":"3.x","vue-toastification":"^2.0.0-rc.5","webpack":"5.x","xss":"^1.0.15"},"peerDependencies":{"@nestjs/common":"10.x || 11.x","mongoose":"7.x || 8.x || ^9.0.0"},"peerDependenciesMeta":{"@nestjs/common":{"optional":true}},"optionalPeerDependencies":{"@mongoosejs/task":"0.5.x || 0.6.x"},"devDependencies":{"@masteringjs/eslint-config":"0.1.1","axios":"1.2.2","dedent":"^1.6.0","eslint":"9.30.0","@nestjs/common":"^11.1.9","express":"4.x","mocha":"10.2.0","mongodb-memory-server":"^11.0.1","mongoose":"9.x","sinon":"^21.0.1"},"scripts":{"lint":"eslint .","seed":"node seed/index.js","start":"node ./local.js","tailwind":"tailwindcss -o ./frontend/public/tw.css","tailwind:watch":"tailwindcss -o ./frontend/public/tw.css --watch","test":"mocha test/*.test.js","test:frontend":"mocha test/frontend/*.test.js","eval:agent":"node eval/agent/run.js"}}');
|
|
66014
66266
|
|
|
66015
66267
|
/***/ }
|
|
66016
66268
|
|
|
@@ -66051,75 +66303,46 @@ module.exports = /*#__PURE__*/JSON.parse('{"name":"@mongoosejs/studio","version"
|
|
|
66051
66303
|
/******/
|
|
66052
66304
|
/************************************************************************/
|
|
66053
66305
|
/******/ /* webpack/runtime/amd define */
|
|
66054
|
-
/******/ (
|
|
66055
|
-
/******/
|
|
66056
|
-
/******/
|
|
66057
|
-
/******/ };
|
|
66058
|
-
/******/ })();
|
|
66306
|
+
/******/ __webpack_require__.amdD = function () {
|
|
66307
|
+
/******/ throw new Error('define cannot be used indirect');
|
|
66308
|
+
/******/ };
|
|
66059
66309
|
/******/
|
|
66060
66310
|
/******/ /* webpack/runtime/define property getters */
|
|
66061
|
-
/******/
|
|
66062
|
-
/******/
|
|
66063
|
-
/******/
|
|
66064
|
-
/******/ if(
|
|
66065
|
-
/******/
|
|
66066
|
-
/******/ while(i < definition.length) {
|
|
66067
|
-
/******/ var key = definition[i++];
|
|
66068
|
-
/******/ var binding = definition[i++];
|
|
66069
|
-
/******/ if(!__webpack_require__.o(exports, key)) {
|
|
66070
|
-
/******/ if(binding === 0) {
|
|
66071
|
-
/******/ Object.defineProperty(exports, key, { enumerable: true, value: definition[i++] });
|
|
66072
|
-
/******/ } else {
|
|
66073
|
-
/******/ Object.defineProperty(exports, key, { enumerable: true, get: binding });
|
|
66074
|
-
/******/ }
|
|
66075
|
-
/******/ } else if(binding === 0) { i++; }
|
|
66076
|
-
/******/ }
|
|
66077
|
-
/******/ } else {
|
|
66078
|
-
/******/ for(var key in definition) {
|
|
66079
|
-
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
|
66080
|
-
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
|
66081
|
-
/******/ }
|
|
66082
|
-
/******/ }
|
|
66311
|
+
/******/ // define getter/value functions for harmony exports
|
|
66312
|
+
/******/ __webpack_require__.d = (exports, definition) => {
|
|
66313
|
+
/******/ for(var key in definition) {
|
|
66314
|
+
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
|
|
66315
|
+
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
|
|
66083
66316
|
/******/ }
|
|
66084
|
-
/******/ }
|
|
66085
|
-
/******/ }
|
|
66317
|
+
/******/ }
|
|
66318
|
+
/******/ };
|
|
66086
66319
|
/******/
|
|
66087
66320
|
/******/ /* webpack/runtime/global */
|
|
66088
|
-
/******/ (()
|
|
66089
|
-
/******/
|
|
66090
|
-
/******/
|
|
66091
|
-
/******/
|
|
66092
|
-
/******/
|
|
66093
|
-
/******/
|
|
66094
|
-
/******/
|
|
66095
|
-
/******/ }
|
|
66096
|
-
/******/ })();
|
|
66321
|
+
/******/ __webpack_require__.g = (function() {
|
|
66322
|
+
/******/ if (typeof globalThis === 'object') return globalThis;
|
|
66323
|
+
/******/ try {
|
|
66324
|
+
/******/ return this || new Function('return this')();
|
|
66325
|
+
/******/ } catch (e) {
|
|
66326
|
+
/******/ if (typeof window === 'object') return window;
|
|
66327
|
+
/******/ }
|
|
66097
66328
|
/******/ })();
|
|
66098
66329
|
/******/
|
|
66099
66330
|
/******/ /* webpack/runtime/hasOwnProperty shorthand */
|
|
66100
|
-
/******/ (
|
|
66101
|
-
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
|
66102
|
-
/******/ })();
|
|
66331
|
+
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop));
|
|
66103
66332
|
/******/
|
|
66104
66333
|
/******/ /* webpack/runtime/make namespace object */
|
|
66105
|
-
/******/
|
|
66106
|
-
/******/
|
|
66107
|
-
/******/
|
|
66108
|
-
/******/
|
|
66109
|
-
/******/
|
|
66110
|
-
/******/ }
|
|
66111
|
-
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
66112
|
-
/******/ };
|
|
66113
|
-
/******/ })();
|
|
66334
|
+
/******/ // define __esModule on exports
|
|
66335
|
+
/******/ __webpack_require__.r = (exports) => {
|
|
66336
|
+
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
66337
|
+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
66338
|
+
/******/ };
|
|
66114
66339
|
/******/
|
|
66115
66340
|
/******/ /* webpack/runtime/node module decorator */
|
|
66116
|
-
/******/ (
|
|
66117
|
-
/******/
|
|
66118
|
-
/******/
|
|
66119
|
-
/******/
|
|
66120
|
-
/******/
|
|
66121
|
-
/******/ };
|
|
66122
|
-
/******/ })();
|
|
66341
|
+
/******/ __webpack_require__.nmd = (module) => {
|
|
66342
|
+
/******/ module.paths = [];
|
|
66343
|
+
/******/ if (!module.children) module.children = [];
|
|
66344
|
+
/******/ return module;
|
|
66345
|
+
/******/ };
|
|
66123
66346
|
/******/
|
|
66124
66347
|
/************************************************************************/
|
|
66125
66348
|
/******/
|