@mongoosejs/studio 0.0.94 → 0.0.96

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.
Files changed (51) hide show
  1. package/.github/workflows/lint.yml +18 -0
  2. package/backend/actions/ChatThread/createChatMessage.js +1 -1
  3. package/backend/actions/ChatThread/createChatThread.js +2 -2
  4. package/backend/actions/Dashboard/getDashboards.js +1 -1
  5. package/backend/actions/Dashboard/updateDashboard.js +1 -1
  6. package/backend/actions/Model/createDocument.js +1 -1
  7. package/backend/actions/Model/deleteDocument.js +3 -3
  8. package/backend/actions/Model/deleteDocuments.js +2 -2
  9. package/backend/actions/Model/exportQueryResults.js +1 -1
  10. package/backend/actions/Model/getDocument.js +1 -1
  11. package/backend/actions/Model/getDocuments.js +2 -2
  12. package/backend/actions/Model/getIndexes.js +1 -1
  13. package/backend/actions/Model/index.js +1 -1
  14. package/backend/actions/Model/updateDocument.js +1 -1
  15. package/backend/actions/Model/updateDocuments.js +1 -1
  16. package/backend/authorize.js +1 -3
  17. package/backend/db/dashboardSchema.js +2 -2
  18. package/backend/helpers/removeSpecifiedPaths.js +1 -1
  19. package/backend/netlify.js +3 -3
  20. package/backend/next.js +1 -1
  21. package/eslint.config.js +46 -0
  22. package/frontend/index.js +1 -1
  23. package/frontend/public/app.js +128 -112
  24. package/frontend/public/tw.css +418 -31
  25. package/frontend/src/api.js +16 -16
  26. package/frontend/src/chat/chat-message/chat-message.html +1 -1
  27. package/frontend/src/chat/chat-message/chat-message.js +1 -1
  28. package/frontend/src/chat/chat-message-script/chat-message-script.html +2 -2
  29. package/frontend/src/chat/chat-message-script/chat-message-script.js +1 -2
  30. package/frontend/src/chat/chat.html +18 -6
  31. package/frontend/src/chat/chat.js +3 -2
  32. package/frontend/src/clone-document/clone-document.js +8 -8
  33. package/frontend/src/create-dashboard/create-dashboard.js +7 -7
  34. package/frontend/src/create-document/create-document.js +10 -10
  35. package/frontend/src/dashboard/dashboard.js +1 -1
  36. package/frontend/src/dashboard/edit-dashboard/edit-dashboard.js +3 -3
  37. package/frontend/src/dashboards/dashboards.js +1 -1
  38. package/frontend/src/document/confirm-changes/confirm-changes.js +2 -2
  39. package/frontend/src/document/confirm-delete/confirm-delete.js +2 -2
  40. package/frontend/src/document/document.js +2 -2
  41. package/frontend/src/document-details/document-details.js +3 -3
  42. package/frontend/src/document-details/document-property/document-property.js +3 -3
  43. package/frontend/src/edit-array/edit-array.js +1 -1
  44. package/frontend/src/edit-subdocument/edit-subdocument.js +1 -1
  45. package/frontend/src/list-default/list-default.js +3 -3
  46. package/frontend/src/models/models.js +11 -11
  47. package/frontend/src/navbar/navbar.css +0 -21
  48. package/frontend/src/navbar/navbar.html +62 -5
  49. package/frontend/src/navbar/navbar.js +19 -3
  50. package/frontend/src/update-document/update-document.js +25 -25
  51. package/package.json +4 -1
@@ -53,9 +53,9 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
53
53
  return client.post('', { action: 'Dashboard.getDashboards', ...params }).then(res => res.data);
54
54
  },
55
55
  updateDashboard(params) {
56
- return client.post('', { action: 'Dashboard.updateDashboard', ...params}).then(res => res.data);
56
+ return client.post('', { action: 'Dashboard.updateDashboard', ...params }).then(res => res.data);
57
57
  }
58
- }
58
+ };
59
59
  exports.ChatThread = {
60
60
  createChatMessage(params) {
61
61
  return client.post('', { action: 'ChatThread.createChatMessage', ...params }).then(res => res.data);
@@ -69,24 +69,24 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
69
69
  listChatThreads(params) {
70
70
  return client.post('', { action: 'ChatThread.listChatThreads', ...params }).then(res => res.data);
71
71
  }
72
- }
72
+ };
73
73
  exports.ChatMessage = {
74
74
  executeScript(params) {
75
75
  return client.post('', { action: 'ChatMessage.executeScript', ...params }).then(res => res.data);
76
76
  }
77
- }
77
+ };
78
78
  exports.Model = {
79
79
  createChart(params) {
80
- return client.post('', { action: 'Model.createChart', ...params}).then(res => res.data);
80
+ return client.post('', { action: 'Model.createChart', ...params }).then(res => res.data);
81
81
  },
82
82
  createDocument(params) {
83
- return client.post('', { action: 'Model.createDocument', ...params}).then(res => res.data);
83
+ return client.post('', { action: 'Model.createDocument', ...params }).then(res => res.data);
84
84
  },
85
85
  deleteDocument(params) {
86
- return client.post('', { action: 'Model.deleteDocument', ...params}).then(res => res.data);
86
+ return client.post('', { action: 'Model.deleteDocument', ...params }).then(res => res.data);
87
87
  },
88
88
  deleteDocuments(params) {
89
- return client.post('', { action: 'Model.deleteDocuments', ...params}).then(res => res.data);
89
+ return client.post('', { action: 'Model.deleteDocuments', ...params }).then(res => res.data);
90
90
  },
91
91
  exportQueryResults(params) {
92
92
  const accessToken = window.localStorage.getItem('_mongooseStudioAccessToken') || null;
@@ -94,8 +94,8 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
94
94
  return fetch(window.MONGOOSE_STUDIO_CONFIG.baseURL + new URLSearchParams({ ...params, action: 'Model.exportQueryResults' }).toString(), {
95
95
  method: 'GET',
96
96
  headers: {
97
- 'Authorization': `${accessToken}`, // Set your authorization token here
98
- 'Accept': 'text/csv'
97
+ Authorization: `${accessToken}`, // Set your authorization token here
98
+ Accept: 'text/csv'
99
99
  }
100
100
  })
101
101
  .then(response => {
@@ -146,7 +146,7 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
146
146
  return client.post('/Dashboard/createDashboard', params).then(res => res.data);
147
147
  },
148
148
  deleteDashboard: function deleteDashboard(params) {
149
- return client.post('/Dashboard/deleteDashboard', params).then(res => res.data)
149
+ return client.post('/Dashboard/deleteDashboard', params).then(res => res.data);
150
150
  },
151
151
  getDashboard: function getDashboard(params) {
152
152
  return client.put('/Dashboard/getDashboard', params).then(res => res.data);
@@ -157,7 +157,7 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
157
157
  updateDashboard: function updateDashboard(params) {
158
158
  return client.post('/Dashboard/updateDashboard', params).then(res => res.data);
159
159
  }
160
- }
160
+ };
161
161
  exports.ChatThread = {
162
162
  createChatMessage: function createChatMessage(params) {
163
163
  return client.post('/ChatThread/createChatMessage', params).then(res => res.data);
@@ -178,13 +178,13 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
178
178
  }
179
179
  };
180
180
  exports.Model = {
181
- createChart: function (params) {
181
+ createChart: function(params) {
182
182
  return client.post('/Model/createChart', params).then(res => res.data);
183
183
  },
184
184
  createDocument: function(params) {
185
185
  return client.post('/Model/createDocument', params).then(res => res.data);
186
186
  },
187
- deleteDocument: function (params) {
187
+ deleteDocument: function(params) {
188
188
  return client.post('/Model/deleteDocument', params).then(res => res.data);
189
189
  },
190
190
  deleteDocuments: function(params) {
@@ -196,8 +196,8 @@ if (window.MONGOOSE_STUDIO_CONFIG.isLambda) {
196
196
  return fetch(window.MONGOOSE_STUDIO_CONFIG.baseURL + '/Model/exportQueryResults?' + new URLSearchParams(params).toString(), {
197
197
  method: 'GET',
198
198
  headers: {
199
- 'Authorization': `${accessToken}`, // Set your authorization token here
200
- 'Accept': 'text/csv'
199
+ Authorization: `${accessToken}`, // Set your authorization token here
200
+ Accept: 'text/csv'
201
201
  }
202
202
  })
203
203
  .then(response => {
@@ -324,12 +324,11 @@ module.exports = app => app.component('async-button', {
324
324
 
325
325
 
326
326
  const api = __webpack_require__(/*! ../../api */ "./frontend/src/api.js");
327
- const marked = (__webpack_require__(/*! marked */ "./node_modules/marked/lib/marked.cjs").marked);
328
327
  const template = __webpack_require__(/*! ./chat-message-script.html */ "./frontend/src/chat/chat-message-script/chat-message-script.html");
329
328
  const vanillatoasts = __webpack_require__(/*! vanillatoasts */ "./node_modules/vanillatoasts/vanillatoasts.js");
330
329
 
331
330
  module.exports = app => app.component('chat-message-script', {
332
- template: template,
331
+ template,
333
332
  props: ['message', 'script', 'language'],
334
333
  data: () => ({ activeTab: 'code', showDetailModal: false }),
335
334
  computed: {
@@ -441,7 +440,7 @@ module.exports = app => app.component('chat-message', {
441
440
  });
442
441
  message.executionResult = chatMessage.executionResult;
443
442
  console.log(message);
444
- },
443
+ }
445
444
  }
446
445
  });
447
446
 
@@ -469,7 +468,8 @@ module.exports = app => app.component('chat', {
469
468
  newMessage: '',
470
469
  chatThreadId: null,
471
470
  chatThreads: [],
472
- chatMessages: []
471
+ chatMessages: [],
472
+ hideSidebar: null
473
473
  }),
474
474
  methods: {
475
475
  async sendMessage() {
@@ -543,7 +543,7 @@ module.exports = app => app.component('chat', {
543
543
  });
544
544
  });
545
545
  }
546
- },
546
+ }
547
547
  });
548
548
 
549
549
 
@@ -563,7 +563,7 @@ const api = __webpack_require__(/*! ../api */ "./frontend/src/api.js");
563
563
  const { BSON, EJSON } = __webpack_require__(/*! bson */ "./node_modules/bson/lib/bson.mjs");
564
564
 
565
565
  const ObjectId = new Proxy(BSON.ObjectId, {
566
- apply (target, thisArg, argumentsList) {
566
+ apply(target, thisArg, argumentsList) {
567
567
  return new target(...argumentsList);
568
568
  }
569
569
  });
@@ -572,7 +572,7 @@ const appendCSS = __webpack_require__(/*! ../appendCSS */ "./frontend/src/append
572
572
 
573
573
  appendCSS(__webpack_require__(/*! ./clone-document.css */ "./frontend/src/clone-document/clone-document.css"));
574
574
 
575
- const template = __webpack_require__(/*! ./clone-document.html */ "./frontend/src/clone-document/clone-document.html")
575
+ const template = __webpack_require__(/*! ./clone-document.html */ "./frontend/src/clone-document/clone-document.html");
576
576
 
577
577
  module.exports = app => app.component('clone-document', {
578
578
  props: ['currentModel', 'doc', 'schemaPaths'],
@@ -582,7 +582,7 @@ module.exports = app => app.component('clone-document', {
582
582
  documentData: '',
583
583
  editor: null,
584
584
  errors: []
585
- }
585
+ };
586
586
  },
587
587
  methods: {
588
588
  async cloneDocument() {
@@ -590,17 +590,17 @@ module.exports = app => app.component('clone-document', {
590
590
  const { doc } = await api.Model.createDocument({ model: this.currentModel, data }).catch(err => {
591
591
  if (err.response?.data?.message) {
592
592
  console.log(err.response.data);
593
- const message = err.response.data.message.split(": ").slice(1).join(": ");
593
+ const message = err.response.data.message.split(': ').slice(1).join(': ');
594
594
  this.errors = message.split(',').map(error => {
595
595
  return error.split(': ').slice(1).join(': ').trim();
596
- })
596
+ });
597
597
  throw new Error(err.response?.data?.message);
598
598
  }
599
599
  throw err;
600
600
  });
601
601
  this.errors.length = 0;
602
602
  this.$emit('close', doc);
603
- },
603
+ }
604
604
  },
605
605
  mounted: function() {
606
606
  const pathsToClone = this.schemaPaths.map(x => x.path);
@@ -626,8 +626,8 @@ module.exports = app => app.component('clone-document', {
626
626
  lineNumbers: true,
627
627
  smartIndent: false
628
628
  });
629
- },
630
- })
629
+ }
630
+ });
631
631
 
632
632
  /***/ }),
633
633
 
@@ -642,7 +642,7 @@ module.exports = app => app.component('clone-document', {
642
642
 
643
643
  const api = __webpack_require__(/*! ../api */ "./frontend/src/api.js");
644
644
 
645
- const template = __webpack_require__(/*! ./create-dashboard.html */ "./frontend/src/create-dashboard/create-dashboard.html")
645
+ const template = __webpack_require__(/*! ./create-dashboard.html */ "./frontend/src/create-dashboard/create-dashboard.html");
646
646
 
647
647
  module.exports = app => app.component('create-dashboard', {
648
648
  template,
@@ -651,7 +651,7 @@ module.exports = app => app.component('create-dashboard', {
651
651
  title: '',
652
652
  code: '',
653
653
  errors: []
654
- }
654
+ };
655
655
  },
656
656
  methods: {
657
657
  async createDashboard() {
@@ -659,25 +659,25 @@ module.exports = app => app.component('create-dashboard', {
659
659
  const { dashboard } = await api.Dashboard.createDashboard({ code: this.code, title: this.title }).catch(err => {
660
660
  if (err.response?.data?.message) {
661
661
  console.log(err.response.data);
662
- const message = err.response.data.message.split(": ").slice(1).join(": ");
662
+ const message = err.response.data.message.split(': ').slice(1).join(': ');
663
663
  this.errors = message.split(',').map(error => {
664
664
  return error.split(': ').slice(1).join(': ').trim();
665
- })
665
+ });
666
666
  throw new Error(err.response?.data?.message);
667
667
  }
668
668
  throw err;
669
669
  });
670
670
  this.errors.length = 0;
671
671
  this.$emit('close', dashboard);
672
- },
672
+ }
673
673
  },
674
674
  mounted: function() {
675
675
  this._editor = CodeMirror.fromTextArea(this.$refs.codeEditor, {
676
676
  mode: 'javascript',
677
677
  lineNumbers: true
678
678
  });
679
- },
680
- })
679
+ }
680
+ });
681
681
 
682
682
  /***/ }),
683
683
 
@@ -695,7 +695,7 @@ const api = __webpack_require__(/*! ../api */ "./frontend/src/api.js");
695
695
  const { BSON, EJSON } = __webpack_require__(/*! bson */ "./node_modules/bson/lib/bson.mjs");
696
696
 
697
697
  const ObjectId = new Proxy(BSON.ObjectId, {
698
- apply (target, thisArg, argumentsList) {
698
+ apply(target, thisArg, argumentsList) {
699
699
  return new target(...argumentsList);
700
700
  }
701
701
  });
@@ -704,7 +704,7 @@ const appendCSS = __webpack_require__(/*! ../appendCSS */ "./frontend/src/append
704
704
 
705
705
  appendCSS(__webpack_require__(/*! ./create-document.css */ "./frontend/src/create-document/create-document.css"));
706
706
 
707
- const template = __webpack_require__(/*! ./create-document.html */ "./frontend/src/create-document/create-document.html")
707
+ const template = __webpack_require__(/*! ./create-document.html */ "./frontend/src/create-document/create-document.html");
708
708
 
709
709
  module.exports = app => app.component('create-document', {
710
710
  props: ['currentModel', 'paths'],
@@ -714,7 +714,7 @@ module.exports = app => app.component('create-document', {
714
714
  documentData: '',
715
715
  editor: null,
716
716
  errors: []
717
- }
717
+ };
718
718
  },
719
719
  methods: {
720
720
  async createDocument() {
@@ -722,24 +722,24 @@ module.exports = app => app.component('create-document', {
722
722
  const { doc } = await api.Model.createDocument({ model: this.currentModel, data }).catch(err => {
723
723
  if (err.response?.data?.message) {
724
724
  console.log(err.response.data);
725
- const message = err.response.data.message.split(": ").slice(1).join(": ");
725
+ const message = err.response.data.message.split(': ').slice(1).join(': ');
726
726
  this.errors = message.split(',').map(error => {
727
727
  return error.split(': ').slice(1).join(': ').trim();
728
- })
728
+ });
729
729
  throw new Error(err.response?.data?.message);
730
730
  }
731
731
  throw err;
732
732
  });
733
733
  this.errors.length = 0;
734
734
  this.$emit('close', doc);
735
- },
735
+ }
736
736
  },
737
737
  mounted: function() {
738
738
  const requiredPaths = this.paths.filter(x => x.required);
739
- this.documentData = `{\n`;
739
+ this.documentData = '{\n';
740
740
  for (let i = 0; i < requiredPaths.length; i++) {
741
741
  const isLast = i + 1 >= requiredPaths.length;
742
- this.documentData += ` ${requiredPaths[i].path}: ${isLast ? '': ','}\n`
742
+ this.documentData += ` ${requiredPaths[i].path}: ${isLast ? '' : ','}\n`;
743
743
  }
744
744
  this.documentData += '}';
745
745
  this.$refs.codeEditor.value = this.documentData;
@@ -748,8 +748,8 @@ module.exports = app => app.component('create-document', {
748
748
  lineNumbers: true,
749
749
  smartIndent: false
750
750
  });
751
- },
752
- })
751
+ }
752
+ });
753
753
 
754
754
  /***/ }),
755
755
 
@@ -946,7 +946,7 @@ module.exports = app => app.component('dashboard', {
946
946
  dashboard: null,
947
947
  result: null,
948
948
  errorMessage: null
949
- }
949
+ };
950
950
  },
951
951
  methods: {
952
952
  toggleEditor() {
@@ -1005,11 +1005,11 @@ module.exports = app => app.component('edit-dashboard', {
1005
1005
  editor: null,
1006
1006
  title: '',
1007
1007
  description: ''
1008
- }
1008
+ };
1009
1009
  },
1010
1010
  methods: {
1011
1011
  closeEditor() {
1012
- this.$emit('close')
1012
+ this.$emit('close');
1013
1013
  },
1014
1014
  async updateCode() {
1015
1015
  this.status = 'loading';
@@ -1040,7 +1040,7 @@ module.exports = app => app.component('edit-dashboard', {
1040
1040
  indentWithTabs: true,
1041
1041
  cursorBlinkRate: 300,
1042
1042
  lineWrapping: true,
1043
- showCursorWhenSelecting: true,
1043
+ showCursorWhenSelecting: true
1044
1044
  });
1045
1045
  // this.editor.focus();
1046
1046
  // this.editor.refresh(); // if anything weird happens on load, this usually fixes it. However, this breaks it in this case.
@@ -1092,7 +1092,7 @@ module.exports = app => app.component('dashboards', {
1092
1092
  const { dashboards } = await api.Dashboard.getDashboards();
1093
1093
  this.dashboards = dashboards;
1094
1094
  this.status = 'loaded';
1095
- },
1095
+ }
1096
1096
  });
1097
1097
 
1098
1098
 
@@ -1167,7 +1167,7 @@ module.exports = app => app.component('detail-default', {
1167
1167
 
1168
1168
 
1169
1169
  const mpath = __webpack_require__(/*! mpath */ "./node_modules/mpath/index.js");
1170
- const template = __webpack_require__(/*! ./document-details.html */ "./frontend/src/document-details/document-details.html")
1170
+ const template = __webpack_require__(/*! ./document-details.html */ "./frontend/src/document-details/document-details.html");
1171
1171
 
1172
1172
  const appendCSS = __webpack_require__(/*! ../appendCSS */ "./frontend/src/appendCSS.js");
1173
1173
 
@@ -1194,9 +1194,9 @@ module.exports = app => app.component('document-details', {
1194
1194
  }
1195
1195
 
1196
1196
  return result;
1197
- },
1197
+ }
1198
1198
  }
1199
- })
1199
+ });
1200
1200
 
1201
1201
  /***/ }),
1202
1202
 
@@ -1210,7 +1210,7 @@ module.exports = app => app.component('document-details', {
1210
1210
 
1211
1211
 
1212
1212
  const mpath = __webpack_require__(/*! mpath */ "./node_modules/mpath/index.js");
1213
- const template = __webpack_require__(/*! ./document-property.html */ "./frontend/src/document-details/document-property/document-property.html")
1213
+ const template = __webpack_require__(/*! ./document-property.html */ "./frontend/src/document-details/document-property/document-property.html");
1214
1214
 
1215
1215
  const appendCSS = __webpack_require__(/*! ../../appendCSS */ "./frontend/src/appendCSS.js");
1216
1216
 
@@ -1221,7 +1221,7 @@ module.exports = app => app.component('document-property', {
1221
1221
  data: function() {
1222
1222
  return {
1223
1223
  dateType: 'picker' // picker, iso
1224
- }
1224
+ };
1225
1225
  },
1226
1226
  props: ['path', 'document', 'schemaPaths', 'editting', 'changes', 'invalid'],
1227
1227
  methods: {
@@ -1262,7 +1262,7 @@ module.exports = app => app.component('document-property', {
1262
1262
  return path in this.changes ? this.changes[path] : mpath.get(path, this.document);
1263
1263
  }
1264
1264
  }
1265
- })
1265
+ });
1266
1266
 
1267
1267
  /***/ }),
1268
1268
 
@@ -1287,10 +1287,10 @@ module.exports = app => app.component('confirm-changes', {
1287
1287
  },
1288
1288
  methods: {
1289
1289
  closeConfirm() {
1290
- this.$emit('close')
1290
+ this.$emit('close');
1291
1291
  },
1292
1292
  startSave() {
1293
- this.$emit('save');
1293
+ this.$emit('save');
1294
1294
  }
1295
1295
  },
1296
1296
  mounted() {
@@ -1321,10 +1321,10 @@ module.exports = app => app.component('confirm-delete', {
1321
1321
  },
1322
1322
  methods: {
1323
1323
  closeDelete() {
1324
- this.$emit('close')
1324
+ this.$emit('close');
1325
1325
  },
1326
1326
  startDelete() {
1327
- this.$emit('remove');
1327
+ this.$emit('remove');
1328
1328
  }
1329
1329
  },
1330
1330
  mounted() {
@@ -1427,11 +1427,11 @@ module.exports = app => app.component('document', {
1427
1427
  timeout: 3000,
1428
1428
  positionClass: 'bottomRight'
1429
1429
  });
1430
- this.$router.push({ path: `/model/${this.model}`});
1430
+ this.$router.push({ path: `/model/${this.model}` });
1431
1431
  }
1432
1432
  },
1433
1433
  showClonedDocument(doc) {
1434
- this.$router.push({ path: `/model/${this.model}/document/${doc._id}`});
1434
+ this.$router.push({ path: `/model/${this.model}/document/${doc._id}` });
1435
1435
  }
1436
1436
  }
1437
1437
  });
@@ -1453,7 +1453,7 @@ const template = __webpack_require__(/*! ./edit-array.html */ "./frontend/src/ed
1453
1453
  const { BSON } = __webpack_require__(/*! bson */ "./node_modules/bson/lib/bson.mjs");
1454
1454
 
1455
1455
  const ObjectId = new Proxy(BSON.ObjectId, {
1456
- apply (target, thisArg, argumentsList) {
1456
+ apply(target, thisArg, argumentsList) {
1457
1457
  return new target(...argumentsList);
1458
1458
  }
1459
1459
  });
@@ -1647,7 +1647,7 @@ const template = __webpack_require__(/*! ./edit-subdocument.html */ "./frontend/
1647
1647
  const { BSON, EJSON } = __webpack_require__(/*! bson */ "./node_modules/bson/lib/bson.mjs");
1648
1648
 
1649
1649
  const ObjectId = new Proxy(BSON.ObjectId, {
1650
- apply (target, thisArg, argumentsList) {
1650
+ apply(target, thisArg, argumentsList) {
1651
1651
  return new target(...argumentsList);
1652
1652
  }
1653
1653
  });
@@ -1941,7 +1941,7 @@ module.exports = app => app.component('list-default', {
1941
1941
  copyText(value) {
1942
1942
  const storage = document.createElement('textarea');
1943
1943
  storage.value = value;
1944
- const elem = this.$refs.itemData
1944
+ const elem = this.$refs.itemData;
1945
1945
  elem.appendChild(storage);
1946
1946
  storage.select();
1947
1947
  storage.setSelectionRange(0, 99999);
@@ -1956,7 +1956,7 @@ module.exports = app => app.component('list-default', {
1956
1956
  });
1957
1957
  },
1958
1958
  goToDoc(id) {
1959
- this.$router.push({ path: `/model/${this.allude}/document/${id}`});
1959
+ this.$router.push({ path: `/model/${this.allude}/document/${id}` });
1960
1960
  }
1961
1961
  },
1962
1962
  computed: {
@@ -1968,7 +1968,7 @@ module.exports = app => app.component('list-default', {
1968
1968
  return 'undefined';
1969
1969
  }
1970
1970
  if (this.value.length > 30) {
1971
- return this.value.substring(0,30) + '...';
1971
+ return this.value.substring(0, 30) + '...';
1972
1972
  }
1973
1973
  return this.value;
1974
1974
  },
@@ -2224,7 +2224,7 @@ const { BSON, EJSON } = __webpack_require__(/*! bson */ "./node_modules/bson/lib
2224
2224
 
2225
2225
 
2226
2226
  const ObjectId = new Proxy(BSON.ObjectId, {
2227
- apply (target, thisArg, argumentsList) {
2227
+ apply(target, thisArg, argumentsList) {
2228
2228
  return new target(...argumentsList);
2229
2229
  }
2230
2230
  });
@@ -2302,7 +2302,7 @@ module.exports = app => app.component('models', {
2302
2302
  }
2303
2303
  if (this.$route.query?.fields) {
2304
2304
  const filter = this.$route.query.fields.split(',');
2305
- this.filteredPaths = this.filteredPaths.filter(x => filter.includes(x.path))
2305
+ this.filteredPaths = this.filteredPaths.filter(x => filter.includes(x.path));
2306
2306
  }
2307
2307
 
2308
2308
 
@@ -2337,7 +2337,7 @@ module.exports = app => app.component('models', {
2337
2337
 
2338
2338
  this.$nextTick(() => {
2339
2339
  const input = this.$refs.searchInput;
2340
- const cursorIndex = this.searchText.lastIndexOf(":") + 2; // Move cursor after ": "
2340
+ const cursorIndex = this.searchText.lastIndexOf(':') + 2; // Move cursor after ": "
2341
2341
 
2342
2342
  input.focus();
2343
2343
  input.setSelectionRange(cursorIndex, cursorIndex);
@@ -2352,7 +2352,7 @@ module.exports = app => app.component('models', {
2352
2352
  },
2353
2353
  filterDocument(doc) {
2354
2354
  const filteredDoc = {};
2355
- console.log(doc, this.filteredPaths)
2355
+ console.log(doc, this.filteredPaths);
2356
2356
  for (let i = 0; i < this.filteredPaths.length; i++) {
2357
2357
  filteredDoc[this.filteredPaths[i].path] = doc[this.filteredPaths[i].path];
2358
2358
  }
@@ -2391,7 +2391,7 @@ module.exports = app => app.component('models', {
2391
2391
  }
2392
2392
  if (!sorted) {
2393
2393
  this.sortBy[path] = num;
2394
- this.query.sort = `{${path}:${num}}`
2394
+ this.query.sort = `{${path}:${num}}`;
2395
2395
  this.$router.push({ query: this.query });
2396
2396
  }
2397
2397
  await this.loadMoreDocuments();
@@ -2417,11 +2417,11 @@ module.exports = app => app.component('models', {
2417
2417
  },
2418
2418
  checkIndexLocation(indexName) {
2419
2419
  if (this.schemaIndexes.find(x => x.name == indexName) && this.mongoDBIndexes.find(x => x.name == indexName)) {
2420
- return 'text-gray-500'
2420
+ return 'text-gray-500';
2421
2421
  } else if (this.schemaIndexes.find(x => x.name == indexName)) {
2422
- return 'text-forest-green-500'
2422
+ return 'text-forest-green-500';
2423
2423
  } else {
2424
- return 'text-valencia-500'
2424
+ return 'text-valencia-500';
2425
2425
  }
2426
2426
  },
2427
2427
  async getDocuments() {
@@ -2485,7 +2485,7 @@ module.exports = app => app.component('models', {
2485
2485
  openFieldSelection() {
2486
2486
  if (this.$route.query?.fields) {
2487
2487
  this.selectedPaths.length = 0;
2488
- console.log('there are fields in play', this.$route.query.fields)
2488
+ console.log('there are fields in play', this.$route.query.fields);
2489
2489
  const fields = this.$route.query.fields.split(',');
2490
2490
  for (let i = 0; i < fields.length; i++) {
2491
2491
  this.selectedPaths.push({ path: fields[i] });
@@ -2558,7 +2558,7 @@ module.exports = app => app.component('models', {
2558
2558
  handleDocumentClick(document) {
2559
2559
  console.log(this.selectedDocuments);
2560
2560
  if (this.selectMultiple) {
2561
- const exists = this.selectedDocuments.find(x => x._id.toString() == document._id.toString())
2561
+ const exists = this.selectedDocuments.find(x => x._id.toString() == document._id.toString());
2562
2562
  if (exists) {
2563
2563
  const index = this.selectedDocuments.findIndex(x => x._id.toString() == document._id.toString());
2564
2564
  if (index !== -1) {
@@ -2568,7 +2568,7 @@ module.exports = app => app.component('models', {
2568
2568
  this.selectedDocuments.push(document);
2569
2569
  }
2570
2570
  } else {
2571
- this.$router.push('/model/' + this.currentModel + '/document/' + document._id)
2571
+ this.$router.push('/model/' + this.currentModel + '/document/' + document._id);
2572
2572
  }
2573
2573
  },
2574
2574
  async deleteDocuments() {
@@ -2681,7 +2681,7 @@ exports.hasAPIKey = client.hasAPIKey;
2681
2681
  const api = __webpack_require__(/*! ../api */ "./frontend/src/api.js");
2682
2682
  const mothership = __webpack_require__(/*! ../mothership */ "./frontend/src/mothership.js");
2683
2683
  const template = __webpack_require__(/*! ./navbar.html */ "./frontend/src/navbar/navbar.html");
2684
- const { routes, hasAccess } = __webpack_require__(/*! ../routes */ "./frontend/src/routes.js");
2684
+ const { routes, hasAccess } = __webpack_require__(/*! ../routes */ "./frontend/src/routes.js");
2685
2685
 
2686
2686
  const appendCSS = __webpack_require__(/*! ../appendCSS */ "./frontend/src/appendCSS.js");
2687
2687
 
@@ -2700,10 +2700,26 @@ module.exports = app => app.component('navbar', {
2700
2700
  this.$router.push({ name: firstAllowedRoute.name });
2701
2701
  }
2702
2702
  }
2703
+
2704
+ const mobileMenuMask = document.querySelector('#mobile-menu-mask');
2705
+ const mobileMenu = document.querySelector('#mobile-menu');
2706
+
2707
+ document.querySelector('#open-mobile-menu').addEventListener('click', (event) => {
2708
+ event.stopPropagation();
2709
+ mobileMenuMask.style.display = 'block';
2710
+ mobileMenu.classList.remove('translate-x-full');
2711
+ mobileMenu.classList.add('translate-x-0');
2712
+ });
2713
+
2714
+ document.querySelector('body').addEventListener('click', () => {
2715
+ mobileMenuMask.style.display = 'none';
2716
+ mobileMenu.classList.remove('translate-x-0');
2717
+ mobileMenu.classList.add('translate-x-full');
2718
+ });
2703
2719
  },
2704
2720
  computed: {
2705
2721
  dashboardView() {
2706
- return routes.filter(x => x.name.startsWith('dashboard')).map(x => x.name).includes(this.$route.name)
2722
+ return routes.filter(x => x.name.startsWith('dashboard')).map(x => x.name).includes(this.$route.name);
2707
2723
  },
2708
2724
  documentView() {
2709
2725
  return ['root', 'model', 'document'].includes(this.$route.name);
@@ -2744,7 +2760,7 @@ module.exports = app => app.component('navbar', {
2744
2760
  logout() {
2745
2761
  window.localStorage.setItem('_mongooseStudioAccessToken', '');
2746
2762
  window.location.reload();
2747
- },
2763
+ }
2748
2764
  },
2749
2765
  directives: {
2750
2766
  clickOutside: {
@@ -3015,7 +3031,7 @@ const api = __webpack_require__(/*! ../api */ "./frontend/src/api.js");
3015
3031
  const { BSON, EJSON } = __webpack_require__(/*! bson */ "./node_modules/bson/lib/bson.mjs");
3016
3032
 
3017
3033
  const ObjectId = new Proxy(BSON.ObjectId, {
3018
- apply (target, thisArg, argumentsList) {
3034
+ apply(target, thisArg, argumentsList) {
3019
3035
  return new target(...argumentsList);
3020
3036
  }
3021
3037
  });
@@ -3024,7 +3040,7 @@ const appendCSS = __webpack_require__(/*! ../appendCSS */ "./frontend/src/append
3024
3040
 
3025
3041
  appendCSS(__webpack_require__(/*! ./update-document.css */ "./frontend/src/update-document/update-document.css"));
3026
3042
 
3027
- const template = __webpack_require__(/*! ./update-document.html */ "./frontend/src/update-document/update-document.html")
3043
+ const template = __webpack_require__(/*! ./update-document.html */ "./frontend/src/update-document/update-document.html");
3028
3044
 
3029
3045
  module.exports = app => app.component('update-document', {
3030
3046
  props: ['currentModel', 'document', 'multiple'],
@@ -3033,7 +3049,7 @@ module.exports = app => app.component('update-document', {
3033
3049
  return {
3034
3050
  editor: null,
3035
3051
  errors: []
3036
- }
3052
+ };
3037
3053
  },
3038
3054
  methods: {
3039
3055
  async updateDocument() {
@@ -3041,43 +3057,43 @@ module.exports = app => app.component('update-document', {
3041
3057
  if (this.multiple) {
3042
3058
  const ids = this.document.map(x => x._id);
3043
3059
  await api.Model.updateDocuments({ model: this.currentModel, _id: ids, update: data }).catch(err => {
3044
- if (err.response?.data?.message) {
3045
- console.log(err.response.data);
3046
- const message = err.response.data.message.split(": ").slice(1).join(": ");
3047
- this.errors = message.split(',').map(error => {
3048
- return error.split(': ').slice(1).join(': ').trim();
3049
- })
3050
- throw new Error(err.response?.data?.message);
3051
- }
3052
- throw err;
3060
+ if (err.response?.data?.message) {
3061
+ console.log(err.response.data);
3062
+ const message = err.response.data.message.split(': ').slice(1).join(': ');
3063
+ this.errors = message.split(',').map(error => {
3064
+ return error.split(': ').slice(1).join(': ').trim();
3065
+ });
3066
+ throw new Error(err.response?.data?.message);
3067
+ }
3068
+ throw err;
3053
3069
  });
3054
3070
  } else {
3055
3071
  await api.Model.updateDocument({ model: this.currentModel, _id: this.document._id, update: data }).catch(err => {
3056
- if (err.response?.data?.message) {
3057
- console.log(err.response.data);
3058
- const message = err.response.data.message.split(": ").slice(1).join(": ");
3059
- this.errors = message.split(',').map(error => {
3060
- return error.split(': ').slice(1).join(': ').trim();
3061
- })
3062
- throw new Error(err.response?.data?.message);
3063
- }
3064
- throw err;
3072
+ if (err.response?.data?.message) {
3073
+ console.log(err.response.data);
3074
+ const message = err.response.data.message.split(': ').slice(1).join(': ');
3075
+ this.errors = message.split(',').map(error => {
3076
+ return error.split(': ').slice(1).join(': ').trim();
3077
+ });
3078
+ throw new Error(err.response?.data?.message);
3079
+ }
3080
+ throw err;
3065
3081
  });
3066
3082
  }
3067
3083
  this.errors.length = 0;
3068
3084
  this.$emit('update');
3069
3085
  this.$emit('close');
3070
- },
3086
+ }
3071
3087
  },
3072
3088
  mounted: function() {
3073
- this.$refs.codeEditor.value = `{\n \n}`
3089
+ this.$refs.codeEditor.value = '{\n \n}';
3074
3090
  this.editor = CodeMirror.fromTextArea(this.$refs.codeEditor, {
3075
3091
  mode: 'javascript',
3076
3092
  lineNumbers: true,
3077
3093
  smartIndent: false
3078
3094
  });
3079
- },
3080
- })
3095
+ }
3096
+ });
3081
3097
 
3082
3098
  /***/ }),
3083
3099
 
@@ -3881,7 +3897,7 @@ module.exports = "<button v-bind=\"attrsToBind\" :disabled=\"isDisabled\" @click
3881
3897
  /***/ ((module) => {
3882
3898
 
3883
3899
  "use strict";
3884
- module.exports = "<div class=\"relative border rounded bg-gray-100 text-black text-sm overflow-hidden\">\n <div class=\"flex border-b pt-[1px] text-xs font-medium bg-gray-200\">\n <button\n class=\"px-3 py-1 border-r border-gray-300 hover:bg-green-300\"\n :class=\"{'bg-gray-300': activeTab === 'code', 'bg-green-300': activeTab === 'code'}\"\n @click=\"activeTab = 'code'\">\n Code\n </button>\n <button\n class=\"px-3 py-1 hover:bg-green-300\"\n :class=\"{'bg-green-300': activeTab === 'output'}\"\n @click=\"activeTab = 'output'\">\n Output\n </button>\n <div class=\"ml-auto mr-1 flex\">\n <button\n v-if=\"activeTab === 'output'\"\n class=\"px-2 py-1 mr-1 text-xs bg-gray-500 text-white border-none rounded cursor-pointer hover:bg-gray-600 transition-colors flex items-center\"\n @click=\"copyOutput\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3\" />\n </svg>\n </button>\n <button\n v-if=\"activeTab === 'output'\"\n class=\"px-2 py-1 mr-1 text-xs bg-blue-500 text-white border-none rounded cursor-pointer hover:bg-blue-600 transition-colors flex items-center\"\n @click=\"openDetailModal\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 1v4m0 0h-4m4 0l-5-5\" />\n </svg>\n </button>\n <async-button\n class=\"px-2 py-1 text-xs bg-green-500 text-white border-none rounded cursor-pointer hover:bg-green-600 transition-colors disabled:bg-gray-400\"\n @click=\"executeScript(message, script)\">\n Execute\n </async-button>\n </div>\n </div>\n\n <pre class=\"p-3 whitespace-pre-wrap max-h-[30vh] max-w-[calc(100vw-25rem)] overflow-y-auto\" v-show=\"activeTab === 'code'\"><code v-text=\"script\" ref=\"code\" :class=\"'language-' + language\"></code></pre>\n\n <div class=\"p-3 whitespace-pre-wrap max-h-[30vh] overflow-y-auto bg-white border-t max-w-[calc(100vw-25rem)] relative\" v-show=\"activeTab === 'output'\">\n <dashboard-chart v-if=\"message.executionResult?.output?.$chart\" :value=\"message.executionResult?.output\" />\n <pre v-else>{{ message.executionResult?.output || 'No output' }}</pre>\n </div>\n\n <modal ref=\"outputModal\" v-if=\"showDetailModal\" containerClass=\"!h-[90vh] !w-[90vw]\">\n <template #body>\n <div class=\"absolute font-mono right-1 top-1 cursor-pointer text-xl\" @click=\"showDetailModal = false;\">&times;</div>\n <div class=\"h-full overflow-auto\">\n <dashboard-chart v-if=\"message.executionResult?.output?.$chart\" :value=\"message.executionResult?.output\" />\n <pre v-else class=\"whitespace-pre-wrap\">{{ message.executionResult?.output || 'No output' }}</pre>\n </div>\n </template>\n </modal>\n</div>\n";
3900
+ module.exports = "<div class=\"relative border rounded bg-gray-100 text-black text-sm overflow-hidden\">\n <div class=\"flex border-b pt-[1px] text-xs font-medium bg-gray-200\">\n <button\n class=\"px-3 py-1 border-r border-gray-300 hover:bg-green-300\"\n :class=\"{'bg-gray-300': activeTab === 'code', 'bg-green-300': activeTab === 'code'}\"\n @click=\"activeTab = 'code'\">\n Code\n </button>\n <button\n class=\"px-3 py-1 hover:bg-green-300\"\n :class=\"{'bg-green-300': activeTab === 'output'}\"\n @click=\"activeTab = 'output'\">\n Output\n </button>\n <div class=\"ml-auto mr-1 flex\">\n <button\n v-if=\"activeTab === 'output'\"\n class=\"px-2 py-1 mr-1 text-xs bg-gray-500 text-white border-none rounded cursor-pointer hover:bg-gray-600 transition-colors flex items-center\"\n @click=\"copyOutput\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3\" />\n </svg>\n </button>\n <button\n v-if=\"activeTab === 'output'\"\n class=\"px-2 py-1 mr-1 text-xs bg-blue-500 text-white border-none rounded cursor-pointer hover:bg-blue-600 transition-colors flex items-center\"\n @click=\"openDetailModal\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"h-3 w-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 8V4m0 0h4M4 4l5 5m11-1V4m0 0h-4m4 0l-5 5M4 16v4m0 0h4m-4 0l5-5m11 1v4m0 0h-4m4 0l-5-5\" />\n </svg>\n </button>\n <async-button\n class=\"px-2 py-1 text-xs bg-green-500 text-white border-none rounded cursor-pointer hover:bg-green-600 transition-colors disabled:bg-gray-400\"\n @click=\"executeScript(message, script)\">\n Execute\n </async-button>\n </div>\n </div>\n\n <pre class=\"p-3 whitespace-pre-wrap max-h-[30vh] max-w-[calc(100vw-4rem)] overflow-y-auto\" v-show=\"activeTab === 'code'\"><code v-text=\"script\" ref=\"code\" :class=\"'language-' + language\"></code></pre>\n\n <div class=\"p-3 whitespace-pre-wrap max-h-[30vh] overflow-y-auto bg-white border-t max-w-[calc(100vw-4rem)] relative\" v-show=\"activeTab === 'output'\">\n <dashboard-chart v-if=\"message.executionResult?.output?.$chart\" :value=\"message.executionResult?.output\" />\n <pre v-else>{{ message.executionResult?.output || 'No output' }}</pre>\n </div>\n\n <modal ref=\"outputModal\" v-if=\"showDetailModal\" containerClass=\"!h-[90vh] !w-[90vw]\">\n <template #body>\n <div class=\"absolute font-mono right-1 top-1 cursor-pointer text-xl\" @click=\"showDetailModal = false;\">&times;</div>\n <div class=\"h-full overflow-auto\">\n <dashboard-chart v-if=\"message.executionResult?.output?.$chart\" :value=\"message.executionResult?.output\" />\n <pre v-else class=\"whitespace-pre-wrap\">{{ message.executionResult?.output || 'No output' }}</pre>\n </div>\n </template>\n </modal>\n</div>\n";
3885
3901
 
3886
3902
  /***/ }),
3887
3903
 
@@ -3892,7 +3908,7 @@ module.exports = "<div class=\"relative border rounded bg-gray-100 text-black te
3892
3908
  /***/ ((module) => {
3893
3909
 
3894
3910
  "use strict";
3895
- module.exports = "<div class=\"relative flex items-start space-x-3\" :class=\"{'justify-end': message.role === 'user'}\">\n <div\n class=\"min-w-0 max-w-[calc(100%-6.5rem)]\"\n :class=\"{'text-right': message.role === 'user'}\">\n\n <div class=\"text-sm text-gray-900 p-3 rounded-md inline-block\" :class=\"styleForMessage\">\n <div v-for=\"part in contentSplitByScripts\">\n <div v-if=\"part.type === 'text'\" v-html=\"marked(part.content)\">\n </div>\n <div v-else-if=\"part.type === 'code'\">\n <chat-message-script :message=\"message\" :script=\"part.content\" :language=\"part.language\"></chat-message-script>\n </div>\n </div>\n </div>\n </div>\n</div>\n";
3911
+ module.exports = "<div class=\"relative flex items-start space-x-3\" :class=\"{'justify-end': message.role === 'user'}\">\n <div\n class=\"min-w-0 max-w-[calc(100vw-4rem)]\"\n :class=\"{'text-right': message.role === 'user'}\">\n\n <div class=\"text-sm text-gray-900 p-3 rounded-md inline-block\" :class=\"styleForMessage\">\n <div v-for=\"part in contentSplitByScripts\">\n <div v-if=\"part.type === 'text'\" v-html=\"marked(part.content)\">\n </div>\n <div v-else-if=\"part.type === 'code'\">\n <chat-message-script :message=\"message\" :script=\"part.content\" :language=\"part.language\"></chat-message-script>\n </div>\n </div>\n </div>\n </div>\n</div>\n";
3896
3912
 
3897
3913
  /***/ }),
3898
3914
 
@@ -3903,7 +3919,7 @@ module.exports = "<div class=\"relative flex items-start space-x-3\" :class=\"{'
3903
3919
  /***/ ((module) => {
3904
3920
 
3905
3921
  "use strict";
3906
- module.exports = "<div class=\"flex\" style=\"height: calc(100vh - 55px)\">\n <!-- Sidebar: Chat Threads -->\n <aside class=\"w-64 bg-gray-100 border-r overflow-y-auto h-full\">\n <div class=\"p-4 font-bold text-lg border-b\">Chat Threads</div>\n <div class=\"p-4\">\n <async-button\n @click=\"createNewThread\"\n class=\"w-full bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700\"\n >\n Create New Thread\n </async-button>\n </div>\n <div v-if=\"status === 'loaded' && chatThreads.length === 0\" class=\"p-4 text-sm text-gray-700\">\n No threads yet\n </div>\n <ul vif=\"status === 'loaded'\">\n <li\n v-for=\"thread in chatThreads\"\n :key=\"thread._id\"\n @click=\"selectThread(thread._id)\"\n class=\"p-4 hover:bg-gray-200 cursor-pointer\"\n :class=\"{ 'bg-gray-300': thread._id === chatThreadId }\"\n >\n {{ thread.title || 'Untitled Thread' }}\n </li>\n </ul>\n </aside>\n\n <!-- Main Chat Area -->\n <main class=\"flex-1 flex flex-col\">\n <div class=\"flex-1 overflow-y-auto p-6 space-y-4\" ref=\"messagesContainer\">\n <ul role=\"list\" class=\"space-y-4\">\n <div v-if=\"true\">\n <div class=\"flex items-center justify-center py-3 mb-4\">\n <div class=\"bg-gray-300 h-px flex-grow max-w-xs\"></div>\n <p class=\"mx-4 text-sm font-medium text-gray-500\">This is the beginning of the message thread</p>\n <div class=\"bg-gray-300 h-px flex-grow max-w-xs\"></div>\n </div>\n </div>\n <li v-for=\"message in chatMessages\" :key=\"message._id\">\n <chat-message :message=\"message\"></chat-message>\n </li>\n </ul>\n </div>\n\n\n <!-- Input Area -->\n <div class=\"border-t p-4\">\n <form @submit.prevent=\"sendMessage\" :disabled=\"sendingMessage\" class=\"flex gap-2\">\n <input\n v-model=\"newMessage\"\n placeholder=\"Ask something...\"\n class=\"flex-1 border rounded px-4 py-2\"\n />\n <button class=\"bg-blue-600 text-white px-4 py-2 rounded disabled:bg-gray-600\" :disabled=\"sendingMessage\">\n <svg v-if=\"sendingMessage\" style=\"height: 1em\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <g>\n <circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" opacity=\"0.3\" />\n <path d=\"M12 2a10 10 0 0 1 10 10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 12 12\" to=\"360 12 12\" dur=\"1s\" repeatCount=\"indefinite\" />\n </path>\n </g>\n </svg>\n <span v-else>Send</span>\n </button>\n </form>\n </div>\n </main>\n</div>\n";
3922
+ module.exports = "<div class=\"flex\" style=\"height: calc(100vh - 55px)\">\n <div class=\"fixed top-[65px] cursor-pointer bg-gray-100 rounded-r-md z-10\" @click=\"hideSidebar = false\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" style=\"h-5 w-5\" viewBox=\"0 -960 960 960\" width=\"24px\" fill=\"#5f6368\"><path d=\"M360-120v-720h80v720h-80Zm160-160v-400l200 200-200 200Z\"/></svg>\n </div>\n <!-- Sidebar: Chat Threads -->\n <aside class=\"bg-gray-50 border-r overflow-y-auto overflow-x-hidden h-full transition-all duration-300 ease-in-out z-20 w-0 md:w-64 fixed md:relative\" :class=\"hideSidebar === true ? '!w-0' : hideSidebar === false ? '!w-64' : ''\">\n <div class=\"flex items-center border-b border-gray-100 w-64 overflow-x-hidden\">\n <div class=\"p-4 font-bold text-lg\">Chat Threads</div>\n <button\n @click=\"hideSidebar = true\"\n class=\"ml-auto mr-2 p-2 rounded hover:bg-gray-200 focus:outline-none\"\n aria-label=\"Close sidebar\"\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" style=\"h-5 w-5\" viewBox=\"0 -960 960 960\" width=\"24px\" fill=\"currentColor\"><path d=\"M660-320v-320L500-480l160 160ZM200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm120-80v-560H200v560h120Zm80 0h360v-560H400v560Zm-80 0H200h120Z\"/></svg>\n </button>\n </div>\n <div class=\"p-4 w-64\">\n <async-button\n @click=\"createNewThread\"\n class=\"w-full bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700\"\n >\n Create New Thread\n </async-button>\n </div>\n <div v-if=\"status === 'loaded' && chatThreads.length === 0\" class=\"p-4 text-sm text-gray-700\">\n No threads yet\n </div>\n <ul v-if=\"status === 'loaded'\" class=\"w-64\">\n <li\n v-for=\"thread in chatThreads\"\n :key=\"thread._id\"\n @click=\"selectThread(thread._id)\"\n class=\"p-4 hover:bg-gray-200 cursor-pointer w-64\"\n :class=\"{ 'bg-gray-300': thread._id === chatThreadId }\"\n >\n {{ thread.title || 'Untitled Thread' }}\n </li>\n </ul>\n </aside>\n\n <!-- Main Chat Area -->\n <main class=\"flex-1 flex flex-col\">\n <div class=\"flex-1 overflow-y-auto p-6 space-y-4\" ref=\"messagesContainer\">\n <ul role=\"list\" class=\"space-y-4\">\n <div v-if=\"true\">\n <div class=\"flex items-center justify-center py-3 mb-4\">\n <div class=\"bg-gray-300 h-px flex-grow max-w-xs\"></div>\n <p class=\"mx-4 text-sm font-medium text-gray-500\">This is the beginning of the message thread</p>\n <div class=\"bg-gray-300 h-px flex-grow max-w-xs\"></div>\n </div>\n </div>\n <li v-for=\"message in chatMessages\" :key=\"message._id\">\n <chat-message :message=\"message\"></chat-message>\n </li>\n </ul>\n </div>\n\n\n <!-- Input Area -->\n <div class=\"border-t p-4\">\n <form @submit.prevent=\"sendMessage\" :disabled=\"sendingMessage\" class=\"flex gap-2\">\n <input\n v-model=\"newMessage\"\n placeholder=\"Ask something...\"\n class=\"flex-1 border rounded px-4 py-2\"\n />\n <button class=\"bg-blue-600 text-white px-4 py-2 rounded disabled:bg-gray-600\" :disabled=\"sendingMessage\">\n <svg v-if=\"sendingMessage\" style=\"height: 1em\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <g>\n <circle cx=\"12\" cy=\"12\" r=\"10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" opacity=\"0.3\" />\n <path d=\"M12 2a10 10 0 0 1 10 10\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 12 12\" to=\"360 12 12\" dur=\"1s\" repeatCount=\"indefinite\" />\n </path>\n </g>\n </svg>\n <span v-else>Send</span>\n </button>\n </form>\n </div>\n </main>\n</div>\n";
3907
3923
 
3908
3924
  /***/ }),
3909
3925
 
@@ -4431,7 +4447,7 @@ module.exports = "<div class=\"models\">\n <div>\n <div class=\"flex grow fl
4431
4447
  /***/ ((module) => {
4432
4448
 
4433
4449
  "use strict";
4434
- module.exports = ".navbar {\n width: 100%;\n background-color: #eee;\n}\n\n.active {\n text-decoration: underline;\n}\n\n.spacing {\n margin-right: 10px;\n}\n\n.navbar .nav-left {\n float: left;\n line-height: 54px;\n font-size: 20px;\n padding-left: 20px;\n}\n\n.navbar .nav-left a {\n color: #232323;\n}\n\n.navbar {\n border-bottom: 1px solid #ddd;\n height: 55px;\n}\n\n.navbar .nav-left img {\n height: 32px;\n vertical-align: middle;\n margin-right: 0.5em;\n margin-top: 8px;\n}\n\n.navbar .nav-right {\n float: right;\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n font-size: 16px;\n line-height: 54px;\n padding-right: 20px;\n}\n\n.navbar .nav-right .nav-item {\n flex-grow: 1;\n padding: 0px 12px;\n position: relative;\n z-index: 21000;\n}\n\n.navbar .nav-right .nav-item:hover {\n flex-grow: 1;\n padding: 0px 12px;\n border-bottom: 1px solid #E1B9A0;\n}\n\n.navbar .nav-right .nav-item.active {\n border-bottom: 1px solid #E1B9A0;\n}\n\n.navbar .nav-action {\n cursor: pointer;\n color: #E1B9A0;\n}\n\n.navbar .nav-action svg {\n height: 1em;\n vertical-align: middle;\n}\n\n.navbar .nav-right .nav-item .flyout {\n position: absolute;\n top: 55px;\n right: 0px;\n visibility: hidden;\n opacity: 0;\n transition: opacity .25s,visibility .25s,transform .25s;\n width: auto;\n box-shadow: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);\n background-color: #393944;\n padding-left: 0.5em;\n padding-right: 0.5em;\n z-index: 1000;\n min-width: 192px;\n font-size: 0.9em;\n}\n\n.navbar .nav-right .nav-item:hover .flyout a {\n color: #E1B9A0;\n margin-top: 0.25em;\n margin-bottom: 0.25em;\n}\n\n.navbar .nav-right .nav-item:hover .flyout a:hover {\n color: #E1B9A0;\n}\n\n.navbar .nav-right .nav-item:hover .flyout .nav-action {\n color: #E1B9A0;\n margin-top: 0.25em;\n margin-bottom: 0.25em;\n}\n\n.navbar .nav-right .nav-item:hover .flyout .nav-action:hover {\n color: #E1B9A0;\n}\n\n.navbar .nav-right .nav-item:hover .flyout {\n visibility: visible;\n opacity: 1;\n}\n\n#bar-1 {\n\ttransform: translateY(-4px);\n}\n#bar-3 {\n\ttransform: translateY(4px);\n}\n.menu {\n display: none;\n}\n.menu {\n\twidth: 35px;\n\theight: 30px;\n\tmargin: 18px 2px 0px 0px;\n\tcursor: pointer;\n float: right;\n}\n.bar {\n\theight: 5px;\n\twidth: 100%;\n\tbackground-color: #fff;\n\tdisplay: block;\n\tborder-radius: 5px;\n\ttransition: 0.4s ease;\n}\n.change-icon #bar-1 {\n transform: translateY(4px) rotateZ(-405deg);\n}\n.change-icon #bar-2 {\n opacity: 0;\n}\n.change-icon #bar-3 {\n transform: translateY(-6px) rotateZ(405deg);\n}\n\n@media (max-width: 767px) {\n .menu {\n display: block;\n }\n\n .change-icon ~ div.nav-right {\n left: 0;\n }\n\n .navbar .nav-right {\n\t\tposition: fixed;\n\t\ttop: 55px;\n\t\tleft: -130%;\n\t\tbackground: #111;\n\t\theight: 100vh;\n\t\twidth: 100%;\n\t\ttext-align: center;\n\t\tdisplay: block;\n\t\ttransition: all 0.3s ease;\n z-index: 10000;\n\t}\n}\n";
4450
+ module.exports = ".active {\n text-decoration: underline;\n}\n\n.navbar .nav-left {\n float: left;\n line-height: 54px;\n font-size: 20px;\n padding-left: 20px;\n}\n\n.navbar .nav-left a {\n color: #232323;\n}\n\n.navbar .nav-right {\n float: right;\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n font-size: 16px;\n line-height: 54px;\n padding-right: 20px;\n}\n\n.navbar .nav-right .nav-item {\n flex-grow: 1;\n padding: 0px 12px;\n position: relative;\n z-index: 21000;\n}\n\n.navbar .nav-right .nav-item:hover {\n flex-grow: 1;\n padding: 0px 12px;\n border-bottom: 1px solid #E1B9A0;\n}\n\n.navbar .nav-right .nav-item.active {\n border-bottom: 1px solid #E1B9A0;\n}\n\n.navbar .nav-action {\n cursor: pointer;\n color: #E1B9A0;\n}\n\n.navbar .nav-action svg {\n height: 1em;\n vertical-align: middle;\n}\n\n.navbar .nav-right .nav-item .flyout {\n position: absolute;\n top: 55px;\n right: 0px;\n visibility: hidden;\n opacity: 0;\n transition: opacity .25s,visibility .25s,transform .25s;\n width: auto;\n box-shadow: 0 12px 32px rgba(0, 0, 0, .1), 0 2px 6px rgba(0, 0, 0, .08);\n background-color: #393944;\n padding-left: 0.5em;\n padding-right: 0.5em;\n z-index: 1000;\n min-width: 192px;\n font-size: 0.9em;\n}\n\n.navbar .nav-right .nav-item:hover .flyout a {\n color: #E1B9A0;\n margin-top: 0.25em;\n margin-bottom: 0.25em;\n}\n\n.navbar .nav-right .nav-item:hover .flyout a:hover {\n color: #E1B9A0;\n}\n\n.navbar .nav-right .nav-item:hover .flyout .nav-action {\n color: #E1B9A0;\n margin-top: 0.25em;\n margin-bottom: 0.25em;\n}\n\n.navbar .nav-right .nav-item:hover .flyout .nav-action:hover {\n color: #E1B9A0;\n}\n\n.navbar .nav-right .nav-item:hover .flyout {\n visibility: visible;\n opacity: 1;\n}\n\n#bar-1 {\n\ttransform: translateY(-4px);\n}\n#bar-3 {\n\ttransform: translateY(4px);\n}\n.menu {\n display: none;\n}\n.menu {\n\twidth: 35px;\n\theight: 30px;\n\tmargin: 18px 2px 0px 0px;\n\tcursor: pointer;\n float: right;\n}\n.bar {\n\theight: 5px;\n\twidth: 100%;\n\tbackground-color: #fff;\n\tdisplay: block;\n\tborder-radius: 5px;\n\ttransition: 0.4s ease;\n}\n.change-icon #bar-1 {\n transform: translateY(4px) rotateZ(-405deg);\n}\n.change-icon #bar-2 {\n opacity: 0;\n}\n.change-icon #bar-3 {\n transform: translateY(-6px) rotateZ(405deg);\n}\n\n@media (max-width: 767px) {\n .menu {\n display: block;\n }\n\n .change-icon ~ div.nav-right {\n left: 0;\n }\n\n .navbar .nav-right {\n\t\tposition: fixed;\n\t\ttop: 55px;\n\t\tleft: -130%;\n\t\tbackground: #111;\n\t\theight: 100vh;\n\t\twidth: 100%;\n\t\ttext-align: center;\n\t\tdisplay: block;\n\t\ttransition: all 0.3s ease;\n z-index: 10000;\n\t}\n}\n";
4435
4451
 
4436
4452
  /***/ }),
4437
4453
 
@@ -4442,7 +4458,7 @@ module.exports = ".navbar {\n width: 100%;\n background-color: #eee;\n}\n\n.ac
4442
4458
  /***/ ((module) => {
4443
4459
 
4444
4460
  "use strict";
4445
- module.exports = "<div class=\"navbar\">\n <div class=\"nav-left flex items-center gap-4 h-full\">\n <router-link :to=\"{ name: defaultRoute }\">\n <img src=\"images/logo.svg\" alt=\"Mongoose Studio Logo\" />\n </router-link>\n <div v-if=\"!!state.nodeEnv\" class=\"inline-flex items-center rounded-md px-2 py-1 text-sm font-medium text-gray-900\" :class=\"warnEnv ? 'bg-red-300' : 'bg-yellow-300'\">\n {{state.nodeEnv}}\n </div>\n </div>\n <div class=\"nav-right h-full\">\n <div class=\"sm:ml-6 sm:flex sm:space-x-8 h-full\">\n <a v-if=\"hasAccess(roles, 'root')\"\n href=\"#/\"\n class=\"inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium\"\n :class=\"documentView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Documents</a>\n <a v-if=\"hasAccess(roles, 'dashboards')\"\n href=\"#/dashboards\"\n class=\"inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium\"\n :class=\"dashboardView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Dashboards</a>\n <a v-if=\"hasAccess(roles, 'chat')\"\n href=\"#/chat\"\n class=\"inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium\"\n :class=\"chatView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Chat</a>\n\n <div class=\"h-full flex items-center\" v-if=\"!user && hasAPIKey\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"rounded bg-ultramarine-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"h-full flex items-center relative\" v-clickOutside=\"hideFlyout\">\n <div>\n <button type=\"button\" @click=\"showFlyout = !showFlyout\" class=\"relative flex rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800\" id=\"user-menu-button\" aria-expanded=\"false\" aria-haspopup=\"true\">\n <span class=\"absolute -inset-1.5\"></span>\n <span class=\"sr-only\">Open user menu</span>\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n </button>\n </div>\n\n <div v-if=\"showFlyout\" class=\"absolute right-0 z-10 top-[90%] w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black/5 focus:outline-none\" role=\"menu\" aria-orientation=\"vertical\" aria-labelledby=\"user-menu-button\" tabindex=\"-1\">\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" @click=\"showFlyout = false\" class=\"cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Team</router-link>\n <span @click=\"logout\" class=\"cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Sign out</span>\n </div>\n </div>\n\n </div>\n </div>\n <div style=\"clear: both\"></div>\n</div>\n";
4461
+ module.exports = "<div class=\"navbar w-full bg-gray-50 flex justify-between border-b border-gray-200 !h-[55px]\">\n <div class=\"flex items-center gap-4 h-full pl-4\">\n <router-link :to=\"{ name: defaultRoute }\">\n <img src=\"images/logo.svg\" class=\"h-[32px] mr-1\" alt=\"Mongoose Studio Logo\" />\n </router-link>\n <div v-if=\"!!state.nodeEnv\" class=\"inline-flex items-center rounded-md px-2 py-1 text-sm font-medium text-gray-900\" :class=\"warnEnv ? 'bg-red-300' : 'bg-yellow-300'\">\n {{state.nodeEnv}}\n </div>\n </div>\n <div class=\"h-full pr-4 hidden md:block\">\n <div class=\"sm:ml-6 sm:flex sm:space-x-8 h-full\">\n <a v-if=\"hasAccess(roles, 'root')\"\n href=\"#/\"\n class=\"inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium\"\n :class=\"documentView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Documents</a>\n <a v-if=\"hasAccess(roles, 'dashboards')\"\n href=\"#/dashboards\"\n class=\"inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium\"\n :class=\"dashboardView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Dashboards</a>\n <a v-if=\"hasAccess(roles, 'chat')\"\n href=\"#/chat\"\n class=\"inline-flex items-center border-b-2 px-1 pt-1 text-sm font-medium\"\n :class=\"chatView ? 'text-gray-900 border-ultramarine-500' : 'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700'\">Chat</a>\n\n <div class=\"h-full flex items-center\" v-if=\"!user && hasAPIKey\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"rounded bg-ultramarine-600 px-2 py-2 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"h-full flex items-center relative\" v-clickOutside=\"hideFlyout\">\n <div>\n <button type=\"button\" @click=\"showFlyout = !showFlyout\" class=\"relative flex rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800\" id=\"user-menu-button\" aria-expanded=\"false\" aria-haspopup=\"true\">\n <span class=\"absolute -inset-1.5\"></span>\n <span class=\"sr-only\">Open user menu</span>\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n </button>\n </div>\n\n <div v-if=\"showFlyout\" class=\"absolute right-0 z-10 top-[90%] w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black/5 focus:outline-none\" role=\"menu\" aria-orientation=\"vertical\" aria-labelledby=\"user-menu-button\" tabindex=\"-1\">\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" @click=\"showFlyout = false\" class=\"cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Team</router-link>\n <span @click=\"logout\" class=\"cursor-pointer block px-4 py-2 text-sm text-gray-700 hover:bg-ultramarine-200\" role=\"menuitem\" tabindex=\"-1\" id=\"user-menu-item-2\">Sign out</span>\n </div>\n </div>\n\n </div>\n </div>\n <div class=\"md:hidden flex items-center\">\n <!-- Mobile menu toggle, controls the 'mobileMenuOpen' state. -->\n <button type=\"button\" id=\"open-mobile-menu\" class=\"-ml-2 rounded-md p-2 pr-4 text-gray-400\">\n <span class=\"sr-only\">Open menu</span>\n <svg class=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5\" />\n </svg>\n </button>\n </div>\n\n <!-- Mobile menu mask -->\n <div id=\"mobile-menu-mask\" class=\"fixed inset-0 bg-black bg-opacity-40 z-40 hidden\"></div>\n <!-- Mobile menu drawer -->\n <div id=\"mobile-menu\" class=\"fixed inset-0 bg-white shadow-lg z-50 transform translate-x-full transition-transform duration-200 ease-in-out flex flex-col\">\n <div class=\"flex items-center justify-between px-4 !h-[55px] border-b border-gray-200\">\n <router-link :to=\"{ name: defaultRoute }\">\n <img src=\"images/logo.svg\" class=\"h-[32px]\" alt=\"Mongoose Studio Logo\" />\n </router-link>\n <button type=\"button\" id=\"close-mobile-menu\" class=\"text-gray-400 p-2 rounded-md\">\n <span class=\"sr-only\">Close menu</span>\n <svg class=\"h-6 w-6\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n <nav class=\"flex-1 px-4 py-4 space-y-2\">\n <a v-if=\"hasAccess(roles, 'root')\"\n href=\"#/\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"documentView ? 'text-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'\">Documents</a>\n <a v-if=\"hasAccess(roles, 'dashboards')\"\n href=\"#/dashboards\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"dashboardView ? 'text-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'\">Dashboards</a>\n <a v-if=\"hasAccess(roles, 'chat')\"\n href=\"#/chat\"\n class=\"block px-3 py-2 rounded-md text-base font-medium\"\n :class=\"chatView ? 'text-ultramarine-700 bg-ultramarine-100' : 'text-gray-700 hover:bg-gray-100'\">Chat</a>\n <div v-if=\"!user && hasAPIKey\" class=\"mt-4\">\n <button\n type=\"button\"\n @click=\"loginWithGithub\"\n class=\"w-full rounded bg-ultramarine-600 px-3 py-2 text-base font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600\">\n Login\n </button>\n </div>\n <div v-if=\"user && hasAPIKey\" class=\"mt-4\">\n <div class=\"flex items-center gap-3 px-3 py-2 bg-gray-50 rounded-md\">\n <img class=\"size-8 rounded-full\" :src=\"user.picture\" alt=\"\">\n <span class=\"text-gray-900 font-medium\">{{ user.name }}</span>\n </div>\n <div class=\"mt-2 space-y-1\">\n <router-link to=\"/team\" v-if=\"hasAccess(roles, 'team')\" class=\"block px-3 py-2 rounded-md text-base text-gray-700 hover:bg-ultramarine-100\">Team</router-link>\n <span @click=\"logout\" class=\"block px-3 py-2 rounded-md text-base text-gray-700 hover:bg-ultramarine-100 cursor-pointer\">Sign out</span>\n </div>\n </div>\n </nav>\n </div>\n</div>\n";
4446
4462
 
4447
4463
  /***/ }),
4448
4464