@mongoosejs/studio 0.2.13 → 0.3.0

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 (81) hide show
  1. package/backend/actions/ChatMessage/executeScript.js +5 -1
  2. package/backend/actions/ChatThread/createChatMessage.js +2 -1
  3. package/backend/actions/ChatThread/streamChatMessage.js +2 -2
  4. package/eslint.config.js +4 -1
  5. package/frontend/public/app.js +24642 -543
  6. package/frontend/public/dark-theme.css +365 -0
  7. package/frontend/public/images/mongoose-studio.svg +4 -0
  8. package/frontend/public/index.html +21 -1
  9. package/frontend/public/style.css +5 -7
  10. package/frontend/public/theme-variables.css +294 -0
  11. package/frontend/public/tw.css +305 -252
  12. package/frontend/src/ace-editor/ace-editor.html +4 -0
  13. package/frontend/src/ace-editor/ace-editor.js +89 -0
  14. package/frontend/src/aceEditor.js +69 -0
  15. package/frontend/src/chat/chat-message/chat-message.html +1 -1
  16. package/frontend/src/chat/chat-message/chat-message.js +1 -1
  17. package/frontend/src/chat/chat-message-script/chat-message-script.html +51 -34
  18. package/frontend/src/chat/chat-message-script/chat-message-script.js +12 -55
  19. package/frontend/src/chat/chat.html +68 -39
  20. package/frontend/src/chat/chat.js +26 -2
  21. package/frontend/src/clone-document/clone-document.html +7 -2
  22. package/frontend/src/clone-document/clone-document.js +1 -8
  23. package/frontend/src/create-dashboard/create-dashboard.html +11 -6
  24. package/frontend/src/create-dashboard/create-dashboard.js +0 -7
  25. package/frontend/src/create-document/create-document.html +15 -9
  26. package/frontend/src/create-document/create-document.js +5 -12
  27. package/frontend/src/dashboard/dashboard.html +14 -12
  28. package/frontend/src/dashboard/dashboard.js +12 -4
  29. package/frontend/src/dashboard/edit-dashboard/edit-dashboard.html +13 -7
  30. package/frontend/src/dashboard/edit-dashboard/edit-dashboard.js +13 -21
  31. package/frontend/src/dashboard-result/dashboard-chart/dashboard-chart.html +19 -17
  32. package/frontend/src/dashboard-result/dashboard-chart/dashboard-chart.js +97 -2
  33. package/frontend/src/dashboard-result/dashboard-map/dashboard-map.js +27 -3
  34. package/frontend/src/dashboard-result/dashboard-result.html +3 -3
  35. package/frontend/src/dashboards/dashboards.html +101 -109
  36. package/frontend/src/dashboards/dashboards.js +25 -1
  37. package/frontend/src/detail-default/detail-default.html +2 -2
  38. package/frontend/src/detail-default/detail-default.js +24 -3
  39. package/frontend/src/document/confirm-changes/confirm-changes.html +1 -1
  40. package/frontend/src/document/confirm-delete/confirm-delete.html +1 -1
  41. package/frontend/src/document/document.css +1 -1
  42. package/frontend/src/document/document.html +28 -28
  43. package/frontend/src/document/execute-script/execute-script.html +20 -21
  44. package/frontend/src/document/execute-script/execute-script.js +1 -43
  45. package/frontend/src/document-details/document-details.css +4 -9
  46. package/frontend/src/document-details/document-details.html +34 -33
  47. package/frontend/src/document-details/document-details.js +2 -53
  48. package/frontend/src/document-details/document-property/document-property.html +12 -12
  49. package/frontend/src/edit-array/edit-array.html +7 -6
  50. package/frontend/src/edit-array/edit-array.js +10 -50
  51. package/frontend/src/edit-boolean/edit-boolean.html +12 -12
  52. package/frontend/src/edit-date/edit-date.html +2 -2
  53. package/frontend/src/edit-default/edit-default.html +1 -1
  54. package/frontend/src/edit-string/edit-string.html +3 -3
  55. package/frontend/src/edit-subdocument/edit-subdocument.html +5 -3
  56. package/frontend/src/edit-subdocument/edit-subdocument.js +1 -15
  57. package/frontend/src/export-query-results/export-query-results.html +3 -3
  58. package/frontend/src/json-node/json-node.html +3 -3
  59. package/frontend/src/list-json/json-node.html +1 -1
  60. package/frontend/src/models/document-search/document-search.html +3 -3
  61. package/frontend/src/models/model-switcher/model-switcher.html +53 -0
  62. package/frontend/src/models/model-switcher/model-switcher.js +123 -0
  63. package/frontend/src/models/models.css +3 -10
  64. package/frontend/src/models/models.html +146 -80
  65. package/frontend/src/models/models.js +108 -4
  66. package/frontend/src/navbar/navbar.html +157 -97
  67. package/frontend/src/navbar/navbar.js +31 -12
  68. package/frontend/src/routes.js +1 -1
  69. package/frontend/src/splash/splash.html +5 -5
  70. package/frontend/src/task-single/task-single.html +29 -29
  71. package/frontend/src/task-single/task-single.js +10 -10
  72. package/frontend/src/tasks/task-details/task-details.html +38 -38
  73. package/frontend/src/tasks/task-details/task-details.js +7 -2
  74. package/frontend/src/tasks/tasks.html +36 -35
  75. package/frontend/src/tasks/tasks.js +2 -25
  76. package/frontend/src/team/new-invitation/new-invitation.html +8 -8
  77. package/frontend/src/team/team.html +27 -27
  78. package/frontend/src/update-document/update-document.html +7 -2
  79. package/frontend/src/update-document/update-document.js +2 -11
  80. package/package.json +2 -1
  81. package/tailwind.config.js +75 -11
@@ -1,41 +1,41 @@
1
1
  <div class="p-4 space-y-6">
2
2
  <div>
3
- <h1 class="text-2xl font-bold text-gray-700 mb-4">Task Overview</h1>
3
+ <h1 class="text-2xl font-bold text-content-secondary mb-4">Task Overview</h1>
4
4
  <div v-if="status == 'init'">
5
5
  <img src="images/loader.gif" />
6
6
  </div>
7
7
  <!-- Task List -->
8
- <div class="bg-white p-4 rounded-lg shadow" v-if="status == 'loaded'">
8
+ <div class="bg-surface p-4 rounded-lg shadow" v-if="status == 'loaded'">
9
9
  <div class="mb-4">
10
- <label class="block text-sm font-medium text-gray-700 mb-1">Filter by Date:</label>
11
- <select v-model="selectedRange" @change="updateDateRange" class="border-gray-300 rounded-md shadow-sm w-full p-2">
10
+ <label class="block text-sm font-medium text-content-secondary mb-1">Filter by Date:</label>
11
+ <select v-model="selectedRange" @change="updateDateRange" class="border-edge-strong rounded-md shadow-sm w-full p-2">
12
12
  <option v-for="option in dateFilters" :key="option.value" :value="option.value">
13
13
  {{ option.label }}
14
14
  </option>
15
15
  </select>
16
16
  </div>
17
17
  <div class="mb-4">
18
- <label class="block text-sm font-medium text-gray-700 mb-1">Filter by Status:</label>
19
- <select v-model="selectedStatus" @change="getTasks" class="border-gray-300 rounded-md shadow-sm w-full p-2">
18
+ <label class="block text-sm font-medium text-content-secondary mb-1">Filter by Status:</label>
19
+ <select v-model="selectedStatus" @change="getTasks" class="border-edge-strong rounded-md shadow-sm w-full p-2">
20
20
  <option v-for="option in statusFilters" :key="option.value" :value="option.value">
21
21
  {{ option.label }}
22
22
  </option>
23
23
  </select>
24
24
  </div>
25
25
  <div class="mb-4">
26
- <label class="block text-sm font-medium text-gray-700 mb-1">Search by Task Name:</label>
26
+ <label class="block text-sm font-medium text-content-secondary mb-1">Search by Task Name:</label>
27
27
  <input
28
28
  v-model="searchQuery"
29
29
  type="text"
30
30
  @input="onSearchInput"
31
- class="border-gray-300 rounded-md shadow-sm w-full p-2"
31
+ class="border-edge-strong rounded-md shadow-sm w-full p-2"
32
32
  placeholder="Enter task name to search..."
33
33
  >
34
34
  </div>
35
35
  <div class="mb-4">
36
36
  <button
37
37
  @click="resetFilters"
38
- class="w-full bg-gray-200 text-gray-700 hover:bg-gray-300 font-medium py-2 px-4 rounded-md transition"
38
+ class="w-full bg-gray-200 text-content-secondary hover:bg-gray-300 font-medium py-2 px-4 rounded-md transition"
39
39
  >
40
40
  Reset Filters
41
41
  </button>
@@ -43,7 +43,7 @@
43
43
  <div class="mb-6">
44
44
  <button
45
45
  @click="openCreateTaskModal"
46
- class="w-full bg-ultramarine-600 text-white hover:bg-ultramarine-700 font-medium py-2 px-4 rounded-md transition"
46
+ class="w-full bg-primary text-primary-text hover:bg-primary-hover font-medium py-2 px-4 rounded-md transition"
47
47
  >
48
48
  Create New Task
49
49
  </button>
@@ -73,7 +73,7 @@
73
73
  </button>
74
74
  <button
75
75
  @click="setStatusFilter('cancelled')"
76
- :class="getStatusColor('cancelled') + ' p-4 rounded-lg shadow-lg hover:shadow-xl transform hover:-translate-y-1 transition-all duration-200 cursor-pointer border-2 border-gray-200 hover:border-gray-300'"
76
+ :class="getStatusColor('cancelled') + ' p-4 rounded-lg shadow-lg hover:shadow-xl transform hover:-translate-y-1 transition-all duration-200 cursor-pointer border-2 border-edge hover:border-edge-strong'"
77
77
  >
78
78
  <div class="text-sm">Cancelled</div>
79
79
  <div class="text-2xl font-bold">{{cancelledCount}}</div>
@@ -82,23 +82,23 @@
82
82
 
83
83
  <!-- Grouped Task List -->
84
84
  <div class="mt-6">
85
- <h2 class="text-lg font-semibold text-gray-700 mb-4">Tasks by Name</h2>
85
+ <h2 class="text-lg font-semibold text-content-secondary mb-4">Tasks by Name</h2>
86
86
  <ul class="divide-y divide-gray-200">
87
87
  <li v-for="group in tasksByName" :key="group.name" class="p-4 group hover:border hover:rounded-lg hover:shadow-xl transform hover:-translate-y-1 transition-all duration-200">
88
88
  <div class="flex items-center justify-between mb-3 ">
89
89
  <div class="flex-1 cursor-pointer" @click="openTaskGroupDetails(group)">
90
90
  <div class="flex items-center gap-2">
91
- <div class="font-medium text-lg group-hover:text-ultramarine-600 transition-colors">{{ group.name }}</div>
92
- <svg class="w-4 h-4 text-gray-400 group-hover:text-ultramarine-600 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
91
+ <div class="font-medium text-lg group-hover:text-primary transition-colors">{{ group.name }}</div>
92
+ <svg class="w-4 h-4 text-gray-400 group-hover:text-primary transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
93
93
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
94
94
  </svg>
95
95
  </div>
96
- <div class="text-sm text-gray-500 group-hover:text-gray-700 transition-colors">Total: {{ group.totalCount }} tasks</div>
97
- <div class="text-xs text-ultramarine-600 opacity-0 group-hover:opacity-100 transition-opacity mt-1">
96
+ <div class="text-sm text-content-tertiary group-hover:text-content-secondary transition-colors">Total: {{ group.totalCount }} tasks</div>
97
+ <div class="text-xs text-primary opacity-0 group-hover:opacity-100 transition-opacity mt-1">
98
98
  Click to view details
99
99
  </div>
100
100
  </div>
101
- <div class="text-sm text-gray-500">
101
+ <div class="text-sm text-content-tertiary">
102
102
  Last run: {{ group.lastRun ? new Date(group.lastRun).toLocaleString() : 'Never' }}
103
103
  </div>
104
104
  </div>
@@ -128,10 +128,10 @@
128
128
  </button>
129
129
  <button
130
130
  @click.stop="openTaskGroupDetailsWithFilter(group, 'cancelled')"
131
- class="bg-gray-50 border border-gray-200 rounded-md p-2 text-center shadow-sm hover:shadow-md transform hover:-translate-y-1 transition-all duration-200 cursor-pointer hover:border-gray-300"
131
+ class="bg-page border border-edge rounded-md p-2 text-center shadow-sm hover:shadow-md transform hover:-translate-y-1 transition-all duration-200 cursor-pointer hover:border-edge-strong"
132
132
  >
133
133
  <div class="text-xs text-gray-600 font-medium">Cancelled</div>
134
- <div class="text-lg font-bold text-gray-700">{{ group.statusCounts.cancelled || 0 }}</div>
134
+ <div class="text-lg font-bold text-content-secondary">{{ group.statusCounts.cancelled || 0 }}</div>
135
135
  </button>
136
136
  </div>
137
137
  </li>
@@ -145,59 +145,60 @@
145
145
  <template #body>
146
146
  <div class="absolute font-mono right-1 top-1 cursor-pointer text-xl" @click="closeCreateTaskModal" role="button" aria-label="Close modal">&times;</div>
147
147
  <div class="space-y-4">
148
- <h3 class="text-lg font-semibold text-gray-700 mb-4">Create New Task</h3>
148
+ <h3 class="text-lg font-semibold text-content-secondary mb-4">Create New Task</h3>
149
149
 
150
150
  <div>
151
- <label class="block text-sm font-medium text-gray-700 mb-1">Task Name:</label>
151
+ <label class="block text-sm font-medium text-content-secondary mb-1">Task Name:</label>
152
152
  <input
153
153
  v-model="newTask.name"
154
154
  type="text"
155
- class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-ultramarine-500"
155
+ class="w-full border border-edge-strong rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary"
156
156
  placeholder="Enter task name"
157
157
  >
158
158
  </div>
159
159
 
160
160
  <div>
161
- <label class="block text-sm font-medium text-gray-700 mb-1">Scheduled Time:</label>
161
+ <label class="block text-sm font-medium text-content-secondary mb-1">Scheduled Time:</label>
162
162
  <input
163
163
  v-model="newTask.scheduledAt"
164
164
  type="datetime-local"
165
- class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-ultramarine-500"
165
+ class="w-full border border-edge-strong rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary"
166
166
  >
167
167
  </div>
168
168
 
169
169
  <div>
170
- <label class="block text-sm font-medium text-gray-700 mb-1">Parameters (JSON):</label>
171
- <textarea
172
- ref="parametersEditor"
173
- class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-ultramarine-500"
174
- placeholder='{"key": "value"}'
175
- ></textarea>
170
+ <label class="block text-sm font-medium text-content-secondary mb-1">Parameters (JSON):</label>
171
+ <ace-editor
172
+ v-model="newTask.parameters"
173
+ mode="json"
174
+ :line-numbers="true"
175
+ class="min-h-[120px]"
176
+ />
176
177
  </div>
177
178
 
178
179
  <div>
179
- <label class="block text-sm font-medium text-gray-700 mb-1">Repeat Interval (ms):</label>
180
+ <label class="block text-sm font-medium text-content-secondary mb-1">Repeat Interval (ms):</label>
180
181
  <input
181
182
  v-model="newTask.repeatInterval"
182
183
  type="number"
183
184
  min="0"
184
185
  step="1000"
185
- class="w-full border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-ultramarine-500"
186
+ class="w-full border border-edge-strong rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary"
186
187
  placeholder="0 for no repetition"
187
188
  >
188
- <p class="text-xs text-gray-500 mt-1">Enter 0 or leave empty for no repetition. Use 1000 for 1 second, 60000 for 1 minute, etc.</p>
189
+ <p class="text-xs text-content-tertiary mt-1">Enter 0 or leave empty for no repetition. Use 1000 for 1 second, 60000 for 1 minute, etc.</p>
189
190
  </div>
190
191
 
191
192
  <div class="flex gap-2 pt-4">
192
193
  <button
193
194
  @click="createTask"
194
- class="flex-1 bg-ultramarine-600 text-white px-4 py-2 rounded-md hover:bg-ultramarine-700"
195
+ class="flex-1 bg-primary text-primary-text px-4 py-2 rounded-md hover:bg-primary-hover"
195
196
  >
196
197
  Create Task
197
198
  </button>
198
199
  <button
199
200
  @click="closeCreateTaskModal"
200
- class="flex-1 bg-gray-300 text-gray-700 px-4 py-2 rounded-md hover:bg-gray-400"
201
+ class="flex-1 bg-gray-300 text-content-secondary px-4 py-2 rounded-md hover:bg-gray-400"
201
202
  >
202
203
  Cancel
203
204
  </button>
@@ -39,8 +39,7 @@ module.exports = app => app.component('tasks', {
39
39
  scheduledAt: '',
40
40
  parameters: '',
41
41
  repeatInterval: ''
42
- },
43
- parametersEditor: null
42
+ }
44
43
  }),
45
44
  methods: {
46
45
  async getTasks() {
@@ -83,7 +82,7 @@ module.exports = app => app.component('tasks', {
83
82
  async createTask() {
84
83
  try {
85
84
  let parameters = {};
86
- const parametersText = this.parametersEditor ? this.parametersEditor.getValue() : '';
85
+ const parametersText = this.newTask.parameters || '';
87
86
  if (parametersText.trim()) {
88
87
  try {
89
88
  parameters = JSON.parse(parametersText);
@@ -160,9 +159,6 @@ module.exports = app => app.component('tasks', {
160
159
  parameters: '',
161
160
  repeatInterval: ''
162
161
  };
163
- if (this.parametersEditor) {
164
- this.parametersEditor.setValue('');
165
- }
166
162
  },
167
163
  setDefaultCreateTaskValues() {
168
164
  // Set default scheduled time to 1 hour from now
@@ -175,21 +171,8 @@ module.exports = app => app.component('tasks', {
175
171
  this.resetCreateTaskForm();
176
172
  this.setDefaultCreateTaskValues();
177
173
  },
178
- initializeParametersEditor() {
179
- if (this.$refs.parametersEditor && !this.parametersEditor) {
180
- this.parametersEditor = CodeMirror.fromTextArea(this.$refs.parametersEditor, {
181
- mode: 'javascript',
182
- lineNumbers: true,
183
- smartIndent: false,
184
- theme: 'default'
185
- });
186
- }
187
- },
188
174
  openCreateTaskModal() {
189
175
  this.showCreateTaskModal = true;
190
- this.$nextTick(() => {
191
- this.initializeParametersEditor();
192
- });
193
176
  },
194
177
  getStatusColor(status) {
195
178
  if (status === 'succeeded') {
@@ -346,11 +329,5 @@ module.exports = app => app.component('tasks', {
346
329
  this.status = 'loaded';
347
330
  this.setDefaultCreateTaskValues();
348
331
  },
349
- beforeDestroy() {
350
- if (this.parametersEditor) {
351
- this.parametersEditor.toTextArea();
352
- }
353
- },
354
-
355
332
  template: template
356
333
  });
@@ -5,33 +5,33 @@
5
5
  </div>
6
6
 
7
7
  <div>
8
- <label for="githubUsername" class="block text-sm/6 font-medium text-gray-900">GitHub Username</label>
8
+ <label for="githubUsername" class="block text-sm/6 font-medium text-content">GitHub Username</label>
9
9
  <div class="mt-2">
10
- <input type="githubUsername" name="githubUsername" id="githubUsername" v-model="githubUsername" class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-ultramarine-600 sm:text-sm/6" placeholder="johnsmith12">
10
+ <input type="githubUsername" name="githubUsername" id="githubUsername" v-model="githubUsername" class="block w-full rounded-md bg-surface px-3 py-1.5 text-base text-content outline outline-1 -outline-offset-1 outline-edge-strong placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-primary sm:text-sm/6" placeholder="johnsmith12">
11
11
  </div>
12
12
  </div>
13
13
 
14
14
  <div>
15
- <label for="email" class="block text-sm/6 font-medium text-gray-900">Email (Optional)</label>
15
+ <label for="email" class="block text-sm/6 font-medium text-content">Email (Optional)</label>
16
16
  <div class="mt-2">
17
- <input type="email" name="email" id="email" v-model="email" class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-ultramarine-600 sm:text-sm/6" placeholder="you@example.com">
17
+ <input type="email" name="email" id="email" v-model="email" class="block w-full rounded-md bg-surface px-3 py-1.5 text-base text-content outline outline-1 -outline-offset-1 outline-edge-strong placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-primary sm:text-sm/6" placeholder="you@example.com">
18
18
  </div>
19
19
  </div>
20
20
 
21
21
  <div>
22
- <label for="location" class="block text-sm/6 font-medium text-gray-900">Role</label>
22
+ <label for="location" class="block text-sm/6 font-medium text-content">Role</label>
23
23
  <div class="mt-2 grid grid-cols-1">
24
- <select id="role" :disabled="tier == null" name="role" v-model="role" class="col-start-1 row-start-1 w-full appearance-none rounded-md bg-white py-1.5 pl-3 pr-8 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6">
24
+ <select id="role" :disabled="tier == null" name="role" v-model="role" class="col-start-1 row-start-1 w-full appearance-none rounded-md bg-surface py-1.5 pl-3 pr-8 text-base text-content outline outline-1 -outline-offset-1 outline-edge-strong focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6">
25
25
  <option value="admin">Admin</option>
26
26
  <option value="member">Member</option>
27
27
  <option value="readonly">Read-only</option>
28
28
  <option value="dashboards">Dashboards Only</option>
29
29
  </select>
30
- <svg class="pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-gray-500 sm:size-4" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" data-slot="icon">
30
+ <svg class="pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-content-tertiary sm:size-4" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" data-slot="icon">
31
31
  <path fill-rule="evenodd" d="M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" />
32
32
  </svg>
33
33
  </div>
34
- <div v-if="tier == null" class="text-sm text-gray-700">
34
+ <div v-if="tier == null" class="text-sm text-content-secondary">
35
35
  You can only invite "Dashboards Only" users until you set up a subscription.
36
36
  </div>
37
37
  </div>
@@ -14,7 +14,7 @@
14
14
  <async-button
15
15
  type="submit"
16
16
  @click="getWorkspaceCustomerPortalLink"
17
- class="inline-flex items-center justify-center rounded-md border border-transparent bg-ultramarine-600 py-1 px-2 text-sm font-medium text-white shadow-sm hover:bg-ultramarine-500 focus:outline-none focus:ring-2 focus:ring-forest-green-500 focus:ring-offset-2">
17
+ class="inline-flex items-center justify-center rounded-md border border-transparent bg-primary py-1 px-2 text-sm font-medium text-primary-text shadow-sm hover:bg-primary-hover focus:outline-none focus:ring-2 focus:ring-forest-green-500 focus:ring-offset-2">
18
18
  View in Stripe
19
19
  <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 ml-1">
20
20
  <path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25" />
@@ -25,7 +25,7 @@
25
25
  <div v-else-if="workspace && !workspace.subscriptionTier" class="mt-4 flex justify-between items-center">
26
26
  <div>
27
27
  <span class="font-bold">No active subscription</span>
28
- <div class="text-sm text-gray-700">
28
+ <div class="text-sm text-content-secondary">
29
29
  You won't be able to invite your team until you activate a subscription
30
30
  </div>
31
31
  </div>
@@ -33,7 +33,7 @@
33
33
  <a
34
34
  :href="paymentLink"
35
35
  target="_blank"
36
- class="inline-flex items-center justify-center rounded-md border border-transparent bg-ultramarine-600 py-1 px-2 text-sm font-medium text-white shadow-sm hover:bg-ultramarine-500 focus:outline-none focus:ring-2 focus:ring-ultramarine-500 focus:ring-offset-2">
36
+ class="inline-flex items-center justify-center rounded-md border border-transparent bg-primary py-1 px-2 text-sm font-medium text-primary-text shadow-sm hover:bg-primary-hover focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2">
37
37
  Subscribe With Stripe
38
38
  <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 ml-1">
39
39
  <path stroke-linecap="round" stroke-linejoin="round" d="M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25" />
@@ -52,21 +52,21 @@
52
52
  <ul v-else role="list" class="divide-y divide-gray-100">
53
53
  <li class="flex justify-between gap-x-6 py-5" v-for="user in users">
54
54
  <div class="flex min-w-0 gap-x-4">
55
- <img class="size-12 flex-none rounded-full bg-gray-50" :src="user.picture ?? 'images/logo.svg'" alt="">
55
+ <img class="size-12 flex-none rounded-full bg-page" :src="user.picture ?? 'images/logo.svg'" alt="">
56
56
  <div class="min-w-0 flex-auto">
57
- <p class="text-sm/6 font-semibold text-gray-900">
57
+ <p class="text-sm/6 font-semibold text-content">
58
58
  {{user.name || user.githubUsername}}
59
59
  <span v-if="user.isFreeUser" class="ml-1 inline-flex items-center rounded-md bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-600/20">Free</span>
60
60
  </p>
61
- <p class="mt-1 truncate text-xs/5 text-gray-500">{{user.email ?? 'No Email'}}</p>
61
+ <p class="mt-1 truncate text-xs/5 text-content-tertiary">{{user.email ?? 'No Email'}}</p>
62
62
  </div>
63
63
  </div>
64
64
  <div class="hidden shrink-0 sm:flex sm:flex-col sm:items-end">
65
- <p class="text-sm/6 text-gray-900 capitalize">{{getRolesForUser(user).join(', ')}}</p>
65
+ <p class="text-sm/6 text-content capitalize">{{getRolesForUser(user).join(', ')}}</p>
66
66
  <div class="flex gap-3">
67
67
  <button
68
68
  type="button"
69
- class="mt-1 text-xs/5 text-gray-500 cursor-pointer disabled:cursor-not-allowed disabled:text-gray-300"
69
+ class="mt-1 text-xs/5 text-content-tertiary cursor-pointer disabled:cursor-not-allowed disabled:text-gray-300"
70
70
  :disabled="getRolesForUser(user).includes('owner')"
71
71
  @click="openEditModal(user)">
72
72
  Edit
@@ -93,7 +93,7 @@
93
93
  @click="showNewInvitationModal = true"
94
94
  :disabled="status === 'loading'"
95
95
  :tier="workspace?.subscriptionTier"
96
- class="block rounded-md bg-ultramarine-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 disabled:bg-gray-500 disabled:cursor-not-allowed focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-600">
96
+ class="block rounded-md bg-primary px-3 py-2 text-center text-sm font-semibold text-primary-text shadow-sm hover:bg-primary-hover disabled:bg-page0 disabled:cursor-not-allowed focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
97
97
  New Invitation
98
98
  <svg class="inline w-4 h-4 ml-1" v-if="workspace && !workspace.subscriptionTier" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
99
99
  <path fill-rule="evenodd" d="M12 1.5a5.25 5.25 0 00-5.25 5.25v3a3 3 0 00-3 3v6.75a3 3 0 003 3h10.5a3 3 0 003-3v-6.75a3 3 0 00-3-3v-3c0-2.9-2.35-5.25-5.25-5.25zm3.75 8.25v-3a3.75 3.75 0 10-7.5 0v3h7.5z" clip-rule="evenodd" />
@@ -110,26 +110,26 @@
110
110
  <table class="min-w-full divide-y divide-gray-300">
111
111
  <thead>
112
112
  <tr>
113
- <th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-0">GitHub Username</th>
114
- <th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Email</th>
115
- <th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Status</th>
116
- <th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">Role</th>
113
+ <th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-content sm:pl-0">GitHub Username</th>
114
+ <th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-content">Email</th>
115
+ <th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-content">Status</th>
116
+ <th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-content">Role</th>
117
117
  </tr>
118
118
  </thead>
119
- <tbody class="divide-y divide-gray-200 bg-white">
119
+ <tbody class="divide-y divide-gray-200 bg-surface">
120
120
  <tr v-for="invitation in invitations">
121
121
  <td class="whitespace-nowrap py-5 pl-4 pr-3 text-sm sm:pl-0">
122
122
  {{invitation.githubUsername}}
123
123
  </td>
124
- <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-500">
124
+ <td class="whitespace-nowrap px-3 py-5 text-sm text-content-tertiary">
125
125
  {{invitation.email}}
126
126
  </td>
127
- <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-500">
128
- <span class="inline-flex items-center rounded-md bg-gray-50 px-2 py-1 text-xs font-medium text-gray-700 ring-1 ring-inset ring-gray-600/20">
127
+ <td class="whitespace-nowrap px-3 py-5 text-sm text-content-tertiary">
128
+ <span class="inline-flex items-center rounded-md bg-page px-2 py-1 text-xs font-medium text-content-secondary ring-1 ring-inset ring-gray-600/20">
129
129
  Pending
130
130
  </span>
131
131
  </td>
132
- <td class="whitespace-nowrap px-3 py-5 text-sm text-gray-500">
132
+ <td class="whitespace-nowrap px-3 py-5 text-sm text-content-tertiary">
133
133
  {{invitation.roles.join(', ')}}
134
134
  </td>
135
135
  </tr>
@@ -143,8 +143,8 @@
143
143
  <svg class="mx-auto size-12 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
144
144
  <path vector-effect="non-scaling-stroke" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 13h6m-3-3v6m-9 1V7a2 2 0 012-2h6l2 2h6a2 2 0 012 2v8a2 2 0 01-2 2H5a2 2 0 01-2-2z" />
145
145
  </svg>
146
- <h3 class="mt-2 text-sm font-semibold text-gray-900">No invitations</h3>
147
- <p class="mt-1 text-sm text-gray-500">You have no outstanding invitations</p>
146
+ <h3 class="mt-2 text-sm font-semibold text-content">No invitations</h3>
147
+ <p class="mt-1 text-sm text-content-tertiary">You have no outstanding invitations</p>
148
148
  </div>
149
149
  </div>
150
150
  </div>
@@ -165,32 +165,32 @@
165
165
  </div>
166
166
 
167
167
  <div>
168
- <div class="text-sm/6 font-semibold text-gray-900">
168
+ <div class="text-sm/6 font-semibold text-content">
169
169
  {{showEditModal.user.name || showEditModal.user.githubUsername}}
170
170
  </div>
171
- <div class="text-xs/5 text-gray-500">
171
+ <div class="text-xs/5 text-content-tertiary">
172
172
  {{showEditModal.user.email ?? 'No Email'}}
173
173
  </div>
174
174
  </div>
175
175
 
176
176
  <div>
177
- <label for="editRole" class="block text-sm/6 font-medium text-gray-900">Role</label>
177
+ <label for="editRole" class="block text-sm/6 font-medium text-content">Role</label>
178
178
  <div class="mt-2 grid grid-cols-1">
179
179
  <select
180
180
  id="editRole"
181
181
  name="editRole"
182
182
  v-model="showEditModal.role"
183
- class="col-start-1 row-start-1 w-full appearance-none rounded-md bg-white py-1.5 pl-3 pr-8 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-ultramarine-600 sm:text-sm/6">
183
+ class="col-start-1 row-start-1 w-full appearance-none rounded-md bg-surface py-1.5 pl-3 pr-8 text-base text-content outline outline-1 -outline-offset-1 outline-edge-strong focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-primary sm:text-sm/6">
184
184
  <option value="admin" :disabled="disableRoleOption('admin')">Admin</option>
185
185
  <option value="member" :disabled="disableRoleOption('member')">Member</option>
186
186
  <option value="readonly" :disabled="disableRoleOption('readonly')">Read-only</option>
187
187
  <option value="dashboards" :disabled="disableRoleOption('dashboards')">Dashboards Only</option>
188
188
  </select>
189
- <svg class="pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-gray-500 sm:size-4" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" data-slot="icon">
189
+ <svg class="pointer-events-none col-start-1 row-start-1 mr-2 size-5 self-center justify-self-end text-content-tertiary sm:size-4" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" data-slot="icon">
190
190
  <path fill-rule="evenodd" d="M4.22 6.22a.75.75 0 0 1 1.06 0L8 8.94l2.72-2.72a.75.75 0 1 1 1.06 1.06l-3.25 3.25a.75.75 0 0 1-1.06 0L4.22 7.28a.75.75 0 0 1 0-1.06Z" clip-rule="evenodd" />
191
191
  </svg>
192
192
  </div>
193
- <div v-if="!workspace?.subscriptionTier" class="mt-2 text-sm text-gray-700">
193
+ <div v-if="!workspace?.subscriptionTier" class="mt-2 text-sm text-content-secondary">
194
194
  You can only assign the "Dashboards Only" role until you activate a subscription.
195
195
  </div>
196
196
  </div>
@@ -199,7 +199,7 @@
199
199
  <async-button
200
200
  @click="updateWorkspaceMember"
201
201
  :disabled="showEditModal.role === showEditModal.originalRole"
202
- class="border-0 mt-0 flex w-full items-center justify-center gap-3 rounded-md bg-ultramarine-600 hover:bg-ultramarine-500 px-3 py-1.5 text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ultramarine-500">
202
+ class="border-0 mt-0 flex w-full items-center justify-center gap-3 rounded-md bg-primary hover:bg-primary-hover px-3 py-1.5 text-primary-text focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
203
203
  <span class="text-sm font-semibold leading-6">Save</span>
204
204
  </async-button>
205
205
 
@@ -1,8 +1,13 @@
1
1
  <div>
2
2
  <div class="mb-2">
3
- <textarea class="border border-gray-200 p-2 h-[300px] w-full" ref="codeEditor"></textarea>
3
+ <ace-editor
4
+ v-model="editorValue"
5
+ mode="javascript"
6
+ :line-numbers="true"
7
+ class="h-[300px] w-full"
8
+ />
4
9
  </div>
5
- <button @click="updateDocument()" class="rounded-md bg-ultramarine-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600">Submit</button>
10
+ <button @click="updateDocument()" class="rounded-md bg-primary px-2.5 py-1.5 text-sm font-semibold text-primary-text shadow-sm hover:bg-primary-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600">Submit</button>
6
11
  <div v-if="errors.length > 0" class="rounded-md bg-red-50 p-4 mt-1">
7
12
  <div class="flex">
8
13
  <div class="flex-shrink-0">
@@ -1,7 +1,6 @@
1
1
  'use strict';
2
2
 
3
3
  const api = require('../api');
4
-
5
4
  const { BSON, EJSON } = require('mongodb/lib/bson');
6
5
 
7
6
  const ObjectId = new Proxy(BSON.ObjectId, {
@@ -21,13 +20,13 @@ module.exports = app => app.component('update-document', {
21
20
  template,
22
21
  data: function() {
23
22
  return {
24
- editor: null,
23
+ editorValue: '{\n \n}',
25
24
  errors: []
26
25
  };
27
26
  },
28
27
  methods: {
29
28
  async updateDocument() {
30
- const data = EJSON.serialize(eval(`(${this.editor.getValue()})`));
29
+ const data = EJSON.serialize(eval(`(${this.editorValue})`));
31
30
  try {
32
31
  if (this.multiple) {
33
32
  const ids = this.document.map(x => x._id);
@@ -52,13 +51,5 @@ module.exports = app => app.component('update-document', {
52
51
  throw err;
53
52
  }
54
53
  }
55
- },
56
- mounted: function() {
57
- this.$refs.codeEditor.value = '{\n \n}';
58
- this.editor = CodeMirror.fromTextArea(this.$refs.codeEditor, {
59
- mode: 'javascript',
60
- lineNumbers: true,
61
- smartIndent: false
62
- });
63
54
  }
64
55
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mongoosejs/studio",
3
- "version": "0.2.13",
3
+ "version": "0.3.0",
4
4
  "description": "A Mongoose-native MongoDB UI with schema-aware autocomplete, AI-assisted queries, and dashboards that understand your models - not just your data.",
5
5
  "homepage": "https://mongoosestudio.app/",
6
6
  "repository": {
@@ -12,6 +12,7 @@
12
12
  "@ai-sdk/anthropic": "2.x",
13
13
  "@ai-sdk/google": "2.x",
14
14
  "@ai-sdk/openai": "2.x",
15
+ "ace-builds": "^1.43.6",
15
16
  "ai": "5.x",
16
17
  "archetype": "0.13.1",
17
18
  "csv-stringify": "6.3.0",