@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,7 +1,7 @@
1
1
  <div class="w-full h-full flex items-center justify-center">
2
2
  <div class="text-center">
3
- <div class="rounded-full bg-gray-100 p-6 inline-block">
4
- <img src="images/logo.svg" class="w-48 h-48">
3
+ <div class="rounded-full bg-muted p-6 inline-block">
4
+ <img src="images/mongoose-studio.svg" class="w-48 h-48">
5
5
  </div>
6
6
  <div class="text-lg mt-2 font-bold">
7
7
  Mongoose Studio
@@ -9,7 +9,7 @@
9
9
  <div v-if="loading" class="mt-2">
10
10
  <img src="images/loader.gif" class="inline w-16 h-16">
11
11
  </div>
12
- <div class="mt-2 text-gray-700" v-if="!loading">
12
+ <div class="mt-2 text-content-secondary" v-if="!loading">
13
13
  {{workspaceName}}
14
14
  </div>
15
15
  <div class="mt-4 flex gap-4 justify-center" v-if="!loading">
@@ -17,7 +17,7 @@
17
17
  <async-button
18
18
  type="button"
19
19
  @click="loginWithGithub"
20
- 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 disabled:bg-gray-500">
20
+ class="rounded bg-primary px-2 py-2 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-primary disabled:bg-page0">
21
21
  <svg viewBox="0 0 98 98" class="inline mr-1" height="1.5em" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#fff"/></svg>
22
22
  Login With GitHub
23
23
  </async-button>
@@ -26,7 +26,7 @@
26
26
  <async-button
27
27
  type="button"
28
28
  @click="loginWithGoogle"
29
- 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 disabled:bg-gray-500">
29
+ class="rounded bg-primary px-2 py-2 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-primary disabled:bg-page0">
30
30
  <svg class="inline" xmlns="http://www.w3.org/2000/svg" height="1.5em" viewBox="0 0 512 512"><path fill="#fff" d="M386 400c45-42 65-112 53-179H260v74h102c-4 24-18 44-38 57z"/><path fill="#fff" d="M90 341a192 192 0 0 0 296 59l-62-48c-53 35-141 22-171-60z"/><path fill="#fff" d="M153 292c-8-25-8-48 0-73l-63-49c-23 46-30 111 0 171z"/><path fill="#fff" d="M153 219c22-69 116-109 179-50l55-54c-78-75-230-72-297 55z"/></svg>
31
31
  Login With Google
32
32
  </async-button>
@@ -9,18 +9,18 @@
9
9
  Task not found.
10
10
  </div>
11
11
  <div v-else-if="task" class="max-w-4xl">
12
- <button @click="goBack" class="text-gray-500 hover:text-gray-700 mb-4 flex items-center gap-1">
12
+ <button @click="goBack" class="text-content-tertiary hover:text-content-secondary mb-4 flex items-center gap-1">
13
13
  <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
14
14
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
15
15
  </svg>
16
16
  Back to {{ task.name }}
17
17
  </button>
18
- <h1 class="text-2xl font-bold text-gray-700 mb-1">{{ task.name }}</h1>
19
- <p class="text-gray-500 mb-6">Task details</p>
18
+ <h1 class="text-2xl font-bold text-content-secondary mb-1">{{ task.name }}</h1>
19
+ <p class="text-content-tertiary mb-6">Task details</p>
20
20
 
21
- <div class="bg-white rounded-lg shadow p-6 md:p-8">
21
+ <div class="bg-surface rounded-lg shadow p-6 md:p-8">
22
22
  <div class="flex items-center gap-3 mb-6">
23
- <span class="text-sm font-medium text-gray-900">ID: {{ task.id }}</span>
23
+ <span class="text-sm font-medium text-content">ID: {{ task.id }}</span>
24
24
  <span
25
25
  class="text-xs px-2 py-1 rounded-full font-medium"
26
26
  :class="getStatusColor(task.status)"
@@ -31,41 +31,41 @@
31
31
 
32
32
  <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
33
33
  <div>
34
- <label class="block text-sm font-medium text-gray-700 mb-1">Scheduled At</label>
35
- <div class="text-sm text-gray-900">{{ formatDate(task.scheduledAt) }}</div>
34
+ <label class="block text-sm font-medium text-content-secondary mb-1">Scheduled At</label>
35
+ <div class="text-sm text-content">{{ formatDate(task.scheduledAt) }}</div>
36
36
  </div>
37
37
  <div v-if="task?.startedAt">
38
- <label class="block text-sm font-medium text-gray-700 mb-1">Started At</label>
39
- <div class="text-sm text-gray-900">{{ formatDate(task.startedAt) }}</div>
38
+ <label class="block text-sm font-medium text-content-secondary mb-1">Started At</label>
39
+ <div class="text-sm text-content">{{ formatDate(task.startedAt) }}</div>
40
40
  </div>
41
41
  <div v-if="task?.completedAt">
42
- <label class="block text-sm font-medium text-gray-700 mb-1">Completed At</label>
43
- <div class="text-sm text-gray-900">{{ formatDate(task.completedAt) }}</div>
42
+ <label class="block text-sm font-medium text-content-secondary mb-1">Completed At</label>
43
+ <div class="text-sm text-content">{{ formatDate(task.completedAt) }}</div>
44
44
  </div>
45
45
  </div>
46
46
 
47
47
  <div v-if="task?.params" class="mb-6">
48
- <label class="block text-sm font-medium text-gray-700 mb-2">Params</label>
49
- <div class="bg-gray-50 rounded-md p-4">
48
+ <label class="block text-sm font-medium text-content-secondary mb-2">Params</label>
49
+ <div class="bg-page rounded-md p-4">
50
50
  <list-json :value="task.params"></list-json>
51
51
  </div>
52
52
  </div>
53
53
 
54
54
  <div v-if="task?.result" class="mb-6">
55
- <label class="block text-sm font-medium text-gray-700 mb-2">Result</label>
56
- <div class="bg-gray-50 rounded-md p-4">
55
+ <label class="block text-sm font-medium text-content-secondary mb-2">Result</label>
56
+ <div class="bg-page rounded-md p-4">
57
57
  <list-json :value="task.result"></list-json>
58
58
  </div>
59
59
  </div>
60
60
 
61
61
  <div v-if="task?.error" class="mb-6">
62
- <label class="block text-sm font-medium text-gray-700 mb-2">Error</label>
63
- <div class="bg-gray-50 rounded-md p-4">
62
+ <label class="block text-sm font-medium text-content-secondary mb-2">Error</label>
63
+ <div class="bg-page rounded-md p-4">
64
64
  <list-json :value="task.error"></list-json>
65
65
  </div>
66
66
  </div>
67
67
 
68
- <div class="flex flex-wrap gap-3 pt-4 border-t border-gray-200">
68
+ <div class="flex flex-wrap gap-3 pt-4 border-t border-edge">
69
69
  <button
70
70
  @click="showRescheduleConfirmation(task)"
71
71
  class="flex items-center justify-center gap-2 bg-gradient-to-r from-blue-500 to-blue-600 text-white px-4 py-2 rounded-lg text-sm font-medium hover:from-blue-600 hover:to-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
@@ -105,19 +105,19 @@
105
105
  <template #body>
106
106
  <div class="absolute font-mono right-1 top-1 cursor-pointer text-xl" @click="showRescheduleModal = false" role="button" aria-label="Close modal">&times;</div>
107
107
  <div class="p-6">
108
- <h3 class="text-lg font-medium text-gray-900 mb-4">Reschedule Task</h3>
108
+ <h3 class="text-lg font-medium text-content mb-4">Reschedule Task</h3>
109
109
  <p class="text-sm text-gray-600 mb-2">Reschedule task <strong>{{ selectedTask?.id }}</strong>?</p>
110
- <p class="text-sm text-gray-500 mb-4">This will reset the task's status and schedule it to run again.</p>
111
- <label for="newScheduledTime" class="block text-sm font-medium text-gray-700 mb-2">New Scheduled Time</label>
110
+ <p class="text-sm text-content-tertiary mb-4">This will reset the task's status and schedule it to run again.</p>
111
+ <label for="newScheduledTime" class="block text-sm font-medium text-content-secondary mb-2">New Scheduled Time</label>
112
112
  <input
113
113
  id="newScheduledTime"
114
114
  v-model="newScheduledTime"
115
115
  type="datetime-local"
116
- class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 mb-4"
116
+ class="w-full px-3 py-2 border border-edge-strong rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500 mb-4"
117
117
  />
118
118
  <div class="flex gap-3">
119
119
  <button @click="confirmRescheduleTask" class="flex-1 bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 font-medium">Reschedule</button>
120
- <button @click="showRescheduleModal = false" class="flex-1 bg-gray-300 text-gray-700 px-4 py-2 rounded-md hover:bg-gray-400 font-medium">Cancel</button>
120
+ <button @click="showRescheduleModal = false" class="flex-1 bg-gray-300 text-content-secondary px-4 py-2 rounded-md hover:bg-gray-400 font-medium">Cancel</button>
121
121
  </div>
122
122
  </div>
123
123
  </template>
@@ -128,12 +128,12 @@
128
128
  <template #body>
129
129
  <div class="absolute font-mono right-1 top-1 cursor-pointer text-xl" @click="showRunModal = false" role="button" aria-label="Close modal">&times;</div>
130
130
  <div class="p-6">
131
- <h3 class="text-lg font-medium text-gray-900 mb-4">Run Task Now</h3>
131
+ <h3 class="text-lg font-medium text-content mb-4">Run Task Now</h3>
132
132
  <p class="text-sm text-gray-600 mb-2">Run task <strong>{{ selectedTask?.id }}</strong> immediately?</p>
133
- <p class="text-sm text-gray-500 mb-4">This will execute the task right away, bypassing its scheduled time.</p>
133
+ <p class="text-sm text-content-tertiary mb-4">This will execute the task right away, bypassing its scheduled time.</p>
134
134
  <div class="flex gap-3">
135
135
  <button @click="confirmRunTask" class="flex-1 bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700 font-medium">Run Now</button>
136
- <button @click="showRunModal = false" class="flex-1 bg-gray-300 text-gray-700 px-4 py-2 rounded-md hover:bg-gray-400 font-medium">Cancel</button>
136
+ <button @click="showRunModal = false" class="flex-1 bg-gray-300 text-content-secondary px-4 py-2 rounded-md hover:bg-gray-400 font-medium">Cancel</button>
137
137
  </div>
138
138
  </div>
139
139
  </template>
@@ -144,12 +144,12 @@
144
144
  <template #body>
145
145
  <div class="absolute font-mono right-1 top-1 cursor-pointer text-xl" @click="showCancelModal = false" role="button" aria-label="Close modal">&times;</div>
146
146
  <div class="p-6">
147
- <h3 class="text-lg font-medium text-gray-900 mb-4">Cancel Task</h3>
147
+ <h3 class="text-lg font-medium text-content mb-4">Cancel Task</h3>
148
148
  <p class="text-sm text-gray-600 mb-2">Cancel task <strong>{{ selectedTask?.id }}</strong>?</p>
149
- <p class="text-sm text-gray-500 mb-4">This will permanently cancel the task and it cannot be undone.</p>
149
+ <p class="text-sm text-content-tertiary mb-4">This will permanently cancel the task and it cannot be undone.</p>
150
150
  <div class="flex gap-3">
151
151
  <button @click="confirmCancelTask" class="flex-1 bg-red-600 text-white px-4 py-2 rounded-md hover:bg-red-700 font-medium">Cancel Task</button>
152
- <button @click="showCancelModal = false" class="flex-1 bg-gray-300 text-gray-700 px-4 py-2 rounded-md hover:bg-gray-400 font-medium">Keep Task</button>
152
+ <button @click="showCancelModal = false" class="flex-1 bg-gray-300 text-content-secondary px-4 py-2 rounded-md hover:bg-gray-400 font-medium">Keep Task</button>
153
153
  </div>
154
154
  </div>
155
155
  </template>
@@ -25,7 +25,7 @@ module.exports = app => app.component('task-single', {
25
25
  const path = `/tasks/${encodeURIComponent(name || '')}`;
26
26
  const query = this.$route.query?.status ? { status: this.$route.query.status } : {};
27
27
  return { path, query };
28
- },
28
+ }
29
29
  },
30
30
  watch: {
31
31
  '$route.params': {
@@ -82,11 +82,11 @@ module.exports = app => app.component('task-single', {
82
82
  async confirmRescheduleTask() {
83
83
  if (!this.newScheduledTime) return;
84
84
  await api.Task.rescheduleTask({ taskId: this.selectedTask.id, scheduledAt: this.newScheduledTime });
85
- this.$toast.success({ title: 'Task Rescheduled', text: `Task ${this.selectedTask.id} has been rescheduled`, });
86
- this.showRescheduleModal = false;
87
- this.selectedTask = null;
88
- this.newScheduledTime = '';
89
- await this.loadTask();
85
+ this.$toast.success({ title: 'Task Rescheduled', text: `Task ${this.selectedTask.id} has been rescheduled` });
86
+ this.showRescheduleModal = false;
87
+ this.selectedTask = null;
88
+ this.newScheduledTime = '';
89
+ await this.loadTask();
90
90
  },
91
91
  async confirmRunTask() {
92
92
  await api.Task.runTask({ taskId: this.selectedTask.id });
@@ -104,10 +104,10 @@ module.exports = app => app.component('task-single', {
104
104
  },
105
105
  async confirmCancelTask() {
106
106
  await api.Task.cancelTask({ taskId: this.selectedTask.id });
107
- this.$toast.success({ title: 'Task Cancelled', text: `Task ${this.selectedTask.id} has been cancelled` });
108
- this.showCancelModal = false;
109
- this.selectedTask = null;
110
- this.goBack();
107
+ this.$toast.success({ title: 'Task Cancelled', text: `Task ${this.selectedTask.id} has been cancelled` });
108
+ this.showCancelModal = false;
109
+ this.selectedTask = null;
110
+ this.goBack();
111
111
  }
112
112
  },
113
113
  mounted() {
@@ -1,14 +1,14 @@
1
1
  <div class="p-4 space-y-6">
2
2
  <div class="flex items-center justify-between">
3
3
  <div>
4
- <button @click="goBack" class="text-gray-500 hover:text-gray-700 mb-2">
4
+ <button @click="goBack" class="text-content-tertiary hover:text-content-secondary mb-2">
5
5
  <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
6
6
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
7
7
  </svg>
8
8
  {{ backLabel }}
9
9
  </button>
10
- <h1 class="text-2xl font-bold text-gray-700">{{ taskGroup.name }}</h1>
11
- <p class="text-gray-500">Total: {{ taskGroup.totalCount }} tasks</p>
10
+ <h1 class="text-2xl font-bold text-content-secondary">{{ taskGroup.name }}</h1>
11
+ <p class="text-content-tertiary">Total: {{ taskGroup.totalCount }} tasks</p>
12
12
  </div>
13
13
 
14
14
  </div>
@@ -16,13 +16,13 @@
16
16
  <!-- Status Summary -->
17
17
  <div class="space-y-3">
18
18
  <div class="flex items-center justify-between">
19
- <span class="text-sm font-medium text-gray-700">Status</span>
19
+ <span class="text-sm font-medium text-content-secondary">Status</span>
20
20
  <div class="flex rounded-md shadow-sm" role="group">
21
21
  <button
22
22
  type="button"
23
23
  @click="statusView = 'summary'"
24
24
  class="px-3 py-1.5 text-sm font-medium rounded-l-md border transition-colors"
25
- :class="statusView === 'summary' ? 'bg-ultramarine-600 text-white border-ultramarine-600' : 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50'"
25
+ :class="statusView === 'summary' ? 'bg-primary text-primary-text border-primary' : 'bg-surface text-content-secondary border-edge-strong hover:bg-page'"
26
26
  >
27
27
  Summary
28
28
  </button>
@@ -30,7 +30,7 @@
30
30
  type="button"
31
31
  @click="statusView = 'chart'"
32
32
  class="px-3 py-1.5 text-sm font-medium rounded-r-md border border-l-0 transition-colors"
33
- :class="statusView === 'chart' ? 'bg-ultramarine-600 text-white border-ultramarine-600' : 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50'"
33
+ :class="statusView === 'chart' ? 'bg-primary text-primary-text border-primary' : 'bg-surface text-content-secondary border-edge-strong hover:bg-page'"
34
34
  >
35
35
  Chart
36
36
  </button>
@@ -64,19 +64,19 @@
64
64
  </button>
65
65
  <button
66
66
  @click="filterByStatus('cancelled')"
67
- class="bg-gray-50 border border-gray-200 rounded-md p-3 text-center hover:bg-gray-100 transition-colors cursor-pointer"
67
+ class="bg-page border border-edge rounded-md p-3 text-center hover:bg-muted transition-colors cursor-pointer"
68
68
  :class="{ 'ring-2 ring-gray-400': currentFilter === 'cancelled' }"
69
69
  >
70
70
  <div class="text-xs text-gray-600 font-medium">Cancelled</div>
71
- <div class="text-lg font-bold text-gray-700">{{ taskGroup.statusCounts.cancelled || 0 }}</div>
71
+ <div class="text-lg font-bold text-content-secondary">{{ taskGroup.statusCounts.cancelled || 0 }}</div>
72
72
  </button>
73
73
  </div>
74
74
  <!-- Chart view -->
75
- <div v-show="statusView === 'chart'" class="flex flex-col items-center justify-center bg-white border border-gray-200 rounded-lg p-4 gap-3" style="min-height: 280px;">
75
+ <div v-show="statusView === 'chart'" class="flex flex-col items-center justify-center bg-surface border border-edge rounded-lg p-4 gap-3" style="min-height: 280px;">
76
76
  <div v-if="taskGroup.totalCount > 0" class="w-[240px] h-[240px] shrink-0">
77
77
  <canvas ref="statusPieChart" width="240" height="240" class="block"></canvas>
78
78
  </div>
79
- <p v-else class="text-gray-500 text-sm py-8">No tasks to display</p>
79
+ <p v-else class="text-content-tertiary text-sm py-8">No tasks to display</p>
80
80
  <!-- Selection labels: show which segment is selected (click to filter) -->
81
81
  <div v-if="taskGroup.totalCount > 0" class="flex flex-wrap justify-center gap-2">
82
82
  <button
@@ -84,7 +84,7 @@
84
84
  :key="status"
85
85
  type="button"
86
86
  class="text-xs px-2 py-1 rounded-full font-medium transition-all cursor-pointer"
87
- :class="currentFilter === status ? getStatusPillClass(status) : 'bg-gray-100 text-gray-500 hover:bg-gray-200'"
87
+ :class="currentFilter === status ? getStatusPillClass(status) : 'bg-muted text-content-tertiary hover:bg-muted'"
88
88
  @click="filterByStatus(status)"
89
89
  >
90
90
  {{ statusLabel(status) }}
@@ -94,18 +94,18 @@
94
94
  </div>
95
95
 
96
96
  <!-- Task List -->
97
- <div class="bg-white rounded-lg shadow">
98
- <div class="px-6 py-6 border-b border-gray-200 flex items-center justify-between bg-gray-50">
99
- <h2 class="text-xl font-bold text-gray-900">
97
+ <div class="bg-surface rounded-lg shadow">
98
+ <div class="px-6 py-6 border-b border-edge flex items-center justify-between bg-page">
99
+ <h2 class="text-xl font-bold text-content">
100
100
  Individual Tasks
101
- <span v-if="currentFilter" class="ml-3 text-base font-semibold text-ultramarine-700">
101
+ <span v-if="currentFilter" class="ml-3 text-base font-semibold text-primary">
102
102
  (Filtered by {{ currentFilter }})
103
103
  </span>
104
104
  </h2>
105
105
  <button
106
106
  v-if="currentFilter"
107
107
  @click="clearFilter"
108
- class="text-sm font-semibold text-ultramarine-600 hover:text-ultramarine-700"
108
+ class="text-sm font-semibold text-primary hover:text-primary"
109
109
  >
110
110
  Show All
111
111
  </button>
@@ -115,11 +115,11 @@
115
115
  <div class="flex items-start justify-between">
116
116
  <div class="flex-1">
117
117
  <div class="flex items-center gap-3 mb-2">
118
- <span class="text-sm font-medium text-gray-900">Task ID: {{ task.id }}</span>
118
+ <span class="text-sm font-medium text-content">Task ID: {{ task.id }}</span>
119
119
  <router-link
120
120
  v-if="backTo"
121
121
  :to="taskDetailRoute(task)"
122
- class="text-sm text-ultramarine-600 hover:text-ultramarine-700 font-medium"
122
+ class="text-sm text-primary hover:text-primary font-medium"
123
123
  >
124
124
  View details
125
125
  </router-link>
@@ -133,27 +133,27 @@
133
133
 
134
134
  <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
135
135
  <div>
136
- <label class="block text-sm font-medium text-gray-700 mb-1">Scheduled At</label>
137
- <div class="text-sm text-gray-900">{{ formatDate(task.scheduledAt) }}</div>
136
+ <label class="block text-sm font-medium text-content-secondary mb-1">Scheduled At</label>
137
+ <div class="text-sm text-content">{{ formatDate(task.scheduledAt) }}</div>
138
138
  </div>
139
139
  <div v-if="task.startedAt">
140
- <label class="block text-sm font-medium text-gray-700 mb-1">Started At</label>
141
- <div class="text-sm text-gray-900">{{ formatDate(task.startedAt) }}</div>
140
+ <label class="block text-sm font-medium text-content-secondary mb-1">Started At</label>
141
+ <div class="text-sm text-content">{{ formatDate(task.startedAt) }}</div>
142
142
  </div>
143
143
  <div v-if="task.completedAt">
144
- <label class="block text-sm font-medium text-gray-700 mb-1">Completed At</label>
145
- <div class="text-sm text-gray-900">{{ formatDate(task.completedAt) }}</div>
144
+ <label class="block text-sm font-medium text-content-secondary mb-1">Completed At</label>
145
+ <div class="text-sm text-content">{{ formatDate(task.completedAt) }}</div>
146
146
  </div>
147
147
  <div v-if="task.error">
148
- <label class="block text-sm font-medium text-gray-700 mb-1">Error</label>
148
+ <label class="block text-sm font-medium text-content-secondary mb-1">Error</label>
149
149
  <div class="text-sm text-red-600">{{ task.error }}</div>
150
150
  </div>
151
151
  </div>
152
152
 
153
153
  <!-- Task Parameters -->
154
154
  <div v-if="task.parameters && Object.keys(task.parameters).length > 0">
155
- <label class="block text-sm font-medium text-gray-700 mb-2">Parameters</label>
156
- <div class="bg-gray-50 rounded-md p-3">
155
+ <label class="block text-sm font-medium text-content-secondary mb-2">Parameters</label>
156
+ <div class="bg-page rounded-md p-3">
157
157
  <pre class="text-sm text-gray-800 whitespace-pre-wrap">{{ JSON.stringify(task.parameters, null, 2) }}</pre>
158
158
  </div>
159
159
  </div>
@@ -208,26 +208,26 @@
208
208
  </svg>
209
209
  </div>
210
210
  <div class="ml-3">
211
- <h3 class="text-lg font-medium text-gray-900">Reschedule Task</h3>
211
+ <h3 class="text-lg font-medium text-content">Reschedule Task</h3>
212
212
  </div>
213
213
  </div>
214
214
  <div class="mb-4">
215
215
  <p class="text-sm text-gray-600">
216
216
  Are you sure you want to reschedule task <strong>{{ selectedTask?.id }}</strong>?
217
217
  </p>
218
- <p class="text-sm text-gray-500 mt-2">
218
+ <p class="text-sm text-content-tertiary mt-2">
219
219
  This will reset the task's status and schedule it to run again.
220
220
  </p>
221
221
 
222
222
  <div class="mt-4">
223
- <label for="newScheduledTime" class="block text-sm font-medium text-gray-700 mb-2">
223
+ <label for="newScheduledTime" class="block text-sm font-medium text-content-secondary mb-2">
224
224
  New Scheduled Time
225
225
  </label>
226
226
  <input
227
227
  id="newScheduledTime"
228
228
  v-model="newScheduledTime"
229
229
  type="datetime-local"
230
- class="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
230
+ class="w-full px-3 py-2 border border-edge-strong rounded-md shadow-sm focus:outline-none focus:ring-blue-500 focus:border-blue-500"
231
231
  required
232
232
  />
233
233
  </div>
@@ -241,7 +241,7 @@
241
241
  </button>
242
242
  <button
243
243
  @click="showRescheduleModal = false"
244
- class="flex-1 bg-gray-300 text-gray-700 px-4 py-2 rounded-md hover:bg-gray-400 font-medium"
244
+ class="flex-1 bg-gray-300 text-content-secondary px-4 py-2 rounded-md hover:bg-gray-400 font-medium"
245
245
  >
246
246
  Cancel
247
247
  </button>
@@ -262,14 +262,14 @@
262
262
  </svg>
263
263
  </div>
264
264
  <div class="ml-3">
265
- <h3 class="text-lg font-medium text-gray-900">Run Task Now</h3>
265
+ <h3 class="text-lg font-medium text-content">Run Task Now</h3>
266
266
  </div>
267
267
  </div>
268
268
  <div class="mb-4">
269
269
  <p class="text-sm text-gray-600">
270
270
  Are you sure you want to run task <strong>{{ selectedTask?.id }}</strong> immediately?
271
271
  </p>
272
- <p class="text-sm text-gray-500 mt-2">
272
+ <p class="text-sm text-content-tertiary mt-2">
273
273
  This will execute the task right away, bypassing its scheduled time.
274
274
  </p>
275
275
  </div>
@@ -282,7 +282,7 @@
282
282
  </button>
283
283
  <button
284
284
  @click="showRunModal = false"
285
- class="flex-1 bg-gray-300 text-gray-700 px-4 py-2 rounded-md hover:bg-gray-400 font-medium"
285
+ class="flex-1 bg-gray-300 text-content-secondary px-4 py-2 rounded-md hover:bg-gray-400 font-medium"
286
286
  >
287
287
  Cancel
288
288
  </button>
@@ -303,14 +303,14 @@
303
303
  </svg>
304
304
  </div>
305
305
  <div class="ml-3">
306
- <h3 class="text-lg font-medium text-gray-900">Cancel Task</h3>
306
+ <h3 class="text-lg font-medium text-content">Cancel Task</h3>
307
307
  </div>
308
308
  </div>
309
309
  <div class="mb-4">
310
310
  <p class="text-sm text-gray-600">
311
311
  Are you sure you want to cancel task <strong>{{ selectedTask?.id }}</strong>?
312
312
  </p>
313
- <p class="text-sm text-gray-500 mt-2">
313
+ <p class="text-sm text-content-tertiary mt-2">
314
314
  This will permanently cancel the task and it cannot be undone.
315
315
  </p>
316
316
  </div>
@@ -323,7 +323,7 @@
323
323
  </button>
324
324
  <button
325
325
  @click="showCancelModal = false"
326
- class="flex-1 bg-gray-300 text-gray-700 px-4 py-2 rounded-md hover:bg-gray-400 font-medium"
326
+ class="flex-1 bg-gray-300 text-content-secondary px-4 py-2 rounded-md hover:bg-gray-400 font-medium"
327
327
  >
328
328
  Keep Task
329
329
  </button>
@@ -80,7 +80,7 @@ module.exports = app => app.component('task-details', {
80
80
  requestAnimationFrame(() => this.ensureStatusChart());
81
81
  });
82
82
  }
83
- },
83
+ }
84
84
  },
85
85
  methods: {
86
86
  destroyStatusChart() {
@@ -117,6 +117,10 @@ module.exports = app => app.component('task-details', {
117
117
  return;
118
118
  }
119
119
  try {
120
+ const isDark = typeof document !== 'undefined' && document.documentElement.classList.contains('dark');
121
+ const legendColor = isDark
122
+ ? (getComputedStyle(document.documentElement).getPropertyValue('--studio-text-primary')?.trim() || 'rgba(255,255,255,0.9)')
123
+ : undefined;
120
124
  this.statusChart = new Chart(canvas, {
121
125
  type: 'doughnut',
122
126
  data,
@@ -136,7 +140,8 @@ module.exports = app => app.component('task-details', {
136
140
  plugins: {
137
141
  legend: {
138
142
  display: true,
139
- position: 'bottom'
143
+ position: 'bottom',
144
+ ...(legendColor && { labels: { color: legendColor } })
140
145
  }
141
146
  }
142
147
  }