@mongoosejs/studio 0.2.13 → 0.3.1

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 (92) hide show
  1. package/backend/actions/ChatMessage/executeScript.js +5 -1
  2. package/backend/actions/ChatThread/createChatMessage.js +4 -1
  3. package/backend/actions/ChatThread/streamChatMessage.js +4 -2
  4. package/backend/actions/Dashboard/updateDashboard.js +2 -2
  5. package/backend/actions/Task/getTaskOverview.js +102 -0
  6. package/backend/actions/Task/getTasks.js +85 -45
  7. package/backend/actions/Task/index.js +1 -0
  8. package/eslint.config.js +4 -1
  9. package/frontend/public/app.js +25025 -762
  10. package/frontend/public/dark-theme.css +365 -0
  11. package/frontend/public/images/mongoose-studio.svg +4 -0
  12. package/frontend/public/index.html +21 -1
  13. package/frontend/public/style.css +5 -7
  14. package/frontend/public/theme-variables.css +294 -0
  15. package/frontend/public/tw.css +348 -213
  16. package/frontend/src/_util/dateRange.js +82 -0
  17. package/frontend/src/ace-editor/ace-editor.html +4 -0
  18. package/frontend/src/ace-editor/ace-editor.js +95 -0
  19. package/frontend/src/aceEditor.js +69 -0
  20. package/frontend/src/api.js +6 -0
  21. package/frontend/src/chat/chat-message/chat-message.html +1 -1
  22. package/frontend/src/chat/chat-message/chat-message.js +1 -1
  23. package/frontend/src/chat/chat-message-script/chat-message-script.html +54 -42
  24. package/frontend/src/chat/chat-message-script/chat-message-script.js +6 -55
  25. package/frontend/src/chat/chat.html +68 -39
  26. package/frontend/src/chat/chat.js +26 -2
  27. package/frontend/src/clone-document/clone-document.html +7 -2
  28. package/frontend/src/clone-document/clone-document.js +1 -8
  29. package/frontend/src/create-dashboard/create-dashboard.html +11 -6
  30. package/frontend/src/create-dashboard/create-dashboard.js +0 -7
  31. package/frontend/src/create-document/create-document.html +15 -9
  32. package/frontend/src/create-document/create-document.js +5 -12
  33. package/frontend/src/dashboard/dashboard.html +14 -12
  34. package/frontend/src/dashboard/dashboard.js +21 -4
  35. package/frontend/src/dashboard/edit-dashboard/edit-dashboard.html +13 -7
  36. package/frontend/src/dashboard/edit-dashboard/edit-dashboard.js +16 -23
  37. package/frontend/src/dashboard-result/dashboard-chart/dashboard-chart.html +19 -17
  38. package/frontend/src/dashboard-result/dashboard-chart/dashboard-chart.js +97 -2
  39. package/frontend/src/dashboard-result/dashboard-map/dashboard-map.js +27 -3
  40. package/frontend/src/dashboard-result/dashboard-result.html +3 -3
  41. package/frontend/src/dashboard-result/dashboard-result.js +3 -0
  42. package/frontend/src/dashboard-result/dashboard-table/dashboard-table.html +34 -0
  43. package/frontend/src/dashboard-result/dashboard-table/dashboard-table.js +37 -0
  44. package/frontend/src/dashboards/dashboards.html +101 -109
  45. package/frontend/src/dashboards/dashboards.js +25 -1
  46. package/frontend/src/detail-default/detail-default.html +2 -2
  47. package/frontend/src/detail-default/detail-default.js +24 -3
  48. package/frontend/src/document/confirm-changes/confirm-changes.html +1 -1
  49. package/frontend/src/document/confirm-delete/confirm-delete.html +1 -1
  50. package/frontend/src/document/document.css +1 -1
  51. package/frontend/src/document/document.html +28 -28
  52. package/frontend/src/document/execute-script/execute-script.html +20 -21
  53. package/frontend/src/document/execute-script/execute-script.js +1 -43
  54. package/frontend/src/document-details/document-details.css +4 -9
  55. package/frontend/src/document-details/document-details.html +34 -33
  56. package/frontend/src/document-details/document-details.js +2 -53
  57. package/frontend/src/document-details/document-property/document-property.html +12 -12
  58. package/frontend/src/edit-array/edit-array.html +7 -6
  59. package/frontend/src/edit-array/edit-array.js +10 -50
  60. package/frontend/src/edit-boolean/edit-boolean.html +12 -12
  61. package/frontend/src/edit-date/edit-date.html +2 -2
  62. package/frontend/src/edit-default/edit-default.html +1 -1
  63. package/frontend/src/edit-string/edit-string.html +3 -3
  64. package/frontend/src/edit-subdocument/edit-subdocument.html +5 -3
  65. package/frontend/src/edit-subdocument/edit-subdocument.js +1 -15
  66. package/frontend/src/export-query-results/export-query-results.html +3 -3
  67. package/frontend/src/json-node/json-node.html +3 -3
  68. package/frontend/src/list-json/json-node.html +1 -1
  69. package/frontend/src/models/document-search/document-search.html +3 -3
  70. package/frontend/src/models/model-switcher/model-switcher.html +53 -0
  71. package/frontend/src/models/model-switcher/model-switcher.js +123 -0
  72. package/frontend/src/models/models.css +3 -10
  73. package/frontend/src/models/models.html +146 -80
  74. package/frontend/src/models/models.js +116 -7
  75. package/frontend/src/navbar/navbar.html +157 -97
  76. package/frontend/src/navbar/navbar.js +31 -12
  77. package/frontend/src/routes.js +1 -1
  78. package/frontend/src/splash/splash.html +5 -5
  79. package/frontend/src/task-by-name/task-by-name.html +77 -7
  80. package/frontend/src/task-by-name/task-by-name.js +84 -9
  81. package/frontend/src/task-single/task-single.html +29 -29
  82. package/frontend/src/task-single/task-single.js +10 -10
  83. package/frontend/src/tasks/task-details/task-details.html +43 -43
  84. package/frontend/src/tasks/task-details/task-details.js +9 -3
  85. package/frontend/src/tasks/tasks.html +36 -35
  86. package/frontend/src/tasks/tasks.js +27 -143
  87. package/frontend/src/team/new-invitation/new-invitation.html +8 -8
  88. package/frontend/src/team/team.html +27 -27
  89. package/frontend/src/update-document/update-document.html +7 -2
  90. package/frontend/src/update-document/update-document.js +2 -11
  91. package/package.json +3 -1
  92. 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>
@@ -2,25 +2,17 @@
2
2
 
3
3
  const template = require('./tasks.html');
4
4
  const api = require('../api');
5
+ const { DATE_FILTERS, getDateRangeForRange } = require('../_util/dateRange');
5
6
 
6
7
  module.exports = app => app.component('tasks', {
7
8
  data: () => ({
8
9
  status: 'init',
9
- tasks: [],
10
- groupedTasks: {},
10
+ statusCounts: { pending: 0, succeeded: 0, failed: 0, cancelled: 0 },
11
+ tasksByName: [],
11
12
  selectedRange: 'last_hour',
12
13
  start: null,
13
14
  end: null,
14
- dateFilters: [
15
- { value: 'all', label: 'All Time' },
16
- { value: 'last_hour', label: 'Last Hour' },
17
- { value: 'today', label: 'Today' },
18
- { value: 'yesterday', label: 'Yesterday' },
19
- { value: 'thisWeek', label: 'This Week' },
20
- { value: 'lastWeek', label: 'Last Week' },
21
- { value: 'thisMonth', label: 'This Month' },
22
- { value: 'lastMonth', label: 'Last Month' }
23
- ],
15
+ dateFilters: DATE_FILTERS,
24
16
  selectedStatus: 'all',
25
17
  statusFilters: [
26
18
  { label: 'All', value: 'all' },
@@ -39,8 +31,7 @@ module.exports = app => app.component('tasks', {
39
31
  scheduledAt: '',
40
32
  parameters: '',
41
33
  repeatInterval: ''
42
- },
43
- parametersEditor: null
34
+ }
44
35
  }),
45
36
  methods: {
46
37
  async getTasks() {
@@ -51,26 +42,31 @@ module.exports = app => app.component('tasks', {
51
42
  params.status = this.selectedStatus;
52
43
  }
53
44
 
54
- if (this.start && this.end) {
55
- params.start = this.start;
56
- params.end = this.end;
57
- } else if (this.start) {
58
- params.start = this.start;
45
+ if (this.start != null && this.end != null) {
46
+ params.start = this.start instanceof Date ? this.start.toISOString() : this.start;
47
+ params.end = this.end instanceof Date ? this.end.toISOString() : this.end;
48
+ } else if (this.start != null) {
49
+ params.start = this.start instanceof Date ? this.start.toISOString() : this.start;
59
50
  }
60
51
 
61
52
  if (this.searchQuery.trim()) {
62
53
  params.name = this.searchQuery.trim();
63
54
  }
64
55
 
65
- const { tasks, groupedTasks } = await api.Task.getTasks(params);
66
- this.tasks = tasks;
67
- this.groupedTasks = groupedTasks;
56
+ const { statusCounts, tasksByName } = await api.Task.getTaskOverview(params);
57
+ this.statusCounts = statusCounts || this.statusCounts;
58
+ this.tasksByName = tasksByName || [];
68
59
  },
69
60
  openTaskGroupDetails(group) {
70
- this.$router.push({ path: `/tasks/${encodeURIComponent(group.name || '')}` });
61
+ const query = { dateRange: this.selectedRange || 'last_hour' };
62
+ if (this.selectedStatus && this.selectedStatus !== 'all') query.status = this.selectedStatus;
63
+ this.$router.push({ path: `/tasks/${encodeURIComponent(group.name || '')}`, query });
71
64
  },
72
65
  openTaskGroupDetailsWithFilter(group, status) {
73
- this.$router.push({ path: `/tasks/${encodeURIComponent(group.name || '')}`, query: status ? { status } : {} });
66
+ const query = { dateRange: this.selectedRange || 'last_hour' };
67
+ if (status) query.status = status;
68
+ else if (this.selectedStatus && this.selectedStatus !== 'all') query.status = this.selectedStatus;
69
+ this.$router.push({ path: `/tasks/${encodeURIComponent(group.name || '')}`, query });
74
70
  },
75
71
  async onTaskCreated() {
76
72
  // Refresh the task data when a new task is created
@@ -83,7 +79,7 @@ module.exports = app => app.component('tasks', {
83
79
  async createTask() {
84
80
  try {
85
81
  let parameters = {};
86
- const parametersText = this.parametersEditor ? this.parametersEditor.getValue() : '';
82
+ const parametersText = this.newTask.parameters || '';
87
83
  if (parametersText.trim()) {
88
84
  try {
89
85
  parameters = JSON.parse(parametersText);
@@ -160,9 +156,6 @@ module.exports = app => app.component('tasks', {
160
156
  parameters: '',
161
157
  repeatInterval: ''
162
158
  };
163
- if (this.parametersEditor) {
164
- this.parametersEditor.setValue('');
165
- }
166
159
  },
167
160
  setDefaultCreateTaskValues() {
168
161
  // Set default scheduled time to 1 hour from now
@@ -175,21 +168,8 @@ module.exports = app => app.component('tasks', {
175
168
  this.resetCreateTaskForm();
176
169
  this.setDefaultCreateTaskValues();
177
170
  },
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
171
  openCreateTaskModal() {
189
172
  this.showCreateTaskModal = true;
190
- this.$nextTick(() => {
191
- this.initializeParametersEditor();
192
- });
193
173
  },
194
174
  getStatusColor(status) {
195
175
  if (status === 'succeeded') {
@@ -230,114 +210,24 @@ module.exports = app => app.component('tasks', {
230
210
  }, 300);
231
211
  },
232
212
  async updateDateRange() {
233
- const now = new Date();
234
- let start, end;
235
-
236
- switch (this.selectedRange) {
237
- case 'last_hour':
238
- start = new Date();
239
- start.setHours(start.getHours() - 1);
240
- end = new Date();
241
- break;
242
- case 'today':
243
- start = new Date();
244
- start.setHours(0, 0, 0, 0);
245
- end = new Date();
246
- end.setHours(23, 59, 59, 999);
247
- break;
248
- case 'yesterday':
249
- start = new Date();
250
- start.setDate(start.getDate() - 1);
251
- start.setHours(0, 0, 0, 0);
252
- end = new Date();
253
- break;
254
- case 'thisWeek':
255
- start = new Date(now.getTime() - (7 * 86400000));
256
- start.setHours(0, 0, 0, 0);
257
- end = new Date();
258
- end.setHours(23, 59, 59, 999);
259
- break;
260
- case 'lastWeek':
261
- start = new Date(now.getTime() - (14 * 86400000));
262
- start.setHours(0, 0, 0, 0);
263
- end = new Date(now.getTime() - (7 * 86400000));
264
- end.setHours(23, 59, 59, 999);
265
- break;
266
- case 'thisMonth':
267
- start = new Date(now.getFullYear(), now.getMonth(), 1);
268
- end = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59, 999);
269
- break;
270
- case 'lastMonth':
271
- start = new Date(now.getFullYear(), now.getMonth() - 1, 1);
272
- end = new Date(now.getFullYear(), now.getMonth(), 0, 23, 59, 59, 999);
273
- break;
274
- case 'all':
275
- default:
276
- this.start = null;
277
- this.end = null;
278
- break;
279
- }
280
-
213
+ const { start, end } = getDateRangeForRange(this.selectedRange);
281
214
  this.start = start;
282
215
  this.end = end;
283
-
284
216
  await this.getTasks();
285
217
  }
286
218
  },
287
219
  computed: {
288
- tasksByName() {
289
- const groups = {};
290
-
291
- // Process tasks from groupedTasks to create name-based groups
292
- Object.entries(this.groupedTasks).forEach(([status, tasks]) => {
293
- tasks.forEach(task => {
294
- if (!groups[task.name]) {
295
- groups[task.name] = {
296
- name: task.name,
297
- tasks: [],
298
- statusCounts: {
299
- pending: 0,
300
- succeeded: 0,
301
- failed: 0,
302
- cancelled: 0
303
- },
304
- totalCount: 0,
305
- lastRun: null
306
- };
307
- }
308
-
309
- groups[task.name].tasks.push(task);
310
- groups[task.name].totalCount++;
311
-
312
- // Count status using the status from groupedTasks
313
- if (groups[task.name].statusCounts.hasOwnProperty(status)) {
314
- groups[task.name].statusCounts[status]++;
315
- }
316
-
317
- // Track last run time
318
- const taskTime = new Date(task.scheduledAt || task.createdAt || 0);
319
- if (!groups[task.name].lastRun || taskTime > new Date(groups[task.name].lastRun)) {
320
- groups[task.name].lastRun = taskTime;
321
- }
322
- });
323
- });
324
-
325
- // Convert to array and sort alphabetically by name
326
- return Object.values(groups).sort((a, b) => {
327
- return a.name.localeCompare(b.name);
328
- });
220
+ pendingCount() {
221
+ return this.statusCounts.pending || 0;
329
222
  },
330
223
  succeededCount() {
331
- return this.groupedTasks.succeeded ? this.groupedTasks.succeeded.length : 0;
224
+ return this.statusCounts.succeeded || 0;
332
225
  },
333
226
  failedCount() {
334
- return this.groupedTasks.failed ? this.groupedTasks.failed.length : 0;
227
+ return this.statusCounts.failed || 0;
335
228
  },
336
229
  cancelledCount() {
337
- return this.groupedTasks.cancelled ? this.groupedTasks.cancelled.length : 0;
338
- },
339
- pendingCount() {
340
- return this.groupedTasks.pending ? this.groupedTasks.pending.length : 0;
230
+ return this.statusCounts.cancelled || 0;
341
231
  }
342
232
  },
343
233
  mounted: async function() {
@@ -346,11 +236,5 @@ module.exports = app => app.component('tasks', {
346
236
  this.status = 'loaded';
347
237
  this.setDefaultCreateTaskValues();
348
238
  },
349
- beforeDestroy() {
350
- if (this.parametersEditor) {
351
- this.parametersEditor.toTextArea();
352
- }
353
- },
354
-
355
239
  template: template
356
240
  });
@@ -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>