@mongoosejs/studio 0.2.10 → 0.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/backend/actions/Model/executeDocumentScript.js +61 -0
- package/backend/actions/Model/index.js +1 -0
- package/backend/actions/Task/cancelTask.js +24 -0
- package/backend/actions/Task/createTask.js +33 -0
- package/backend/actions/Task/getTasks.js +62 -0
- package/backend/actions/Task/index.js +7 -0
- package/backend/actions/Task/rescheduleTask.js +39 -0
- package/backend/actions/Task/runTask.js +25 -0
- package/backend/actions/index.js +1 -0
- package/backend/authorize.js +1 -0
- package/eslint.config.js +1 -0
- package/express.js +1 -0
- package/frontend/public/app.js +14306 -13379
- package/frontend/public/tw.css +311 -4
- package/frontend/src/api.js +40 -0
- package/frontend/src/document/document.html +22 -0
- package/frontend/src/document/document.js +13 -1
- package/frontend/src/document/execute-script/execute-script.css +35 -0
- package/frontend/src/document/execute-script/execute-script.html +67 -0
- package/frontend/src/document/execute-script/execute-script.js +142 -0
- package/frontend/src/index.js +36 -1
- package/frontend/src/navbar/navbar.html +15 -2
- package/frontend/src/navbar/navbar.js +11 -0
- package/frontend/src/routes.js +13 -5
- package/frontend/src/tasks/task-details/task-details.html +284 -0
- package/frontend/src/tasks/task-details/task-details.js +182 -0
- package/frontend/src/tasks/tasks.css +0 -0
- package/frontend/src/tasks/tasks.html +220 -0
- package/frontend/src/tasks/tasks.js +372 -0
- package/package.json +4 -1
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
<div class="p-4 space-y-6">
|
|
2
|
+
<div class="flex items-center justify-between">
|
|
3
|
+
<div>
|
|
4
|
+
<button @click="$emit('back')" class="text-gray-500 hover:text-gray-700 mb-2">
|
|
5
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
6
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
|
|
7
|
+
</svg>
|
|
8
|
+
Back to Task Groups
|
|
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>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<!-- Status Summary -->
|
|
17
|
+
<div class="grid grid-cols-2 sm:grid-cols-4 gap-4">
|
|
18
|
+
<button
|
|
19
|
+
@click="filterByStatus('pending')"
|
|
20
|
+
class="bg-yellow-50 border border-yellow-200 rounded-md p-3 text-center hover:bg-yellow-100 transition-colors cursor-pointer"
|
|
21
|
+
:class="{ 'ring-2 ring-yellow-400': currentFilter === 'pending' }"
|
|
22
|
+
>
|
|
23
|
+
<div class="text-xs text-yellow-600 font-medium">Pending</div>
|
|
24
|
+
<div class="text-lg font-bold text-yellow-700">{{ taskGroup.statusCounts.pending || 0 }}</div>
|
|
25
|
+
</button>
|
|
26
|
+
<button
|
|
27
|
+
@click="filterByStatus('succeeded')"
|
|
28
|
+
class="bg-green-50 border border-green-200 rounded-md p-3 text-center hover:bg-green-100 transition-colors cursor-pointer"
|
|
29
|
+
:class="{ 'ring-2 ring-green-400': currentFilter === 'succeeded' }"
|
|
30
|
+
>
|
|
31
|
+
<div class="text-xs text-green-600 font-medium">Succeeded</div>
|
|
32
|
+
<div class="text-lg font-bold text-green-700">{{ taskGroup.statusCounts.succeeded || 0 }}</div>
|
|
33
|
+
</button>
|
|
34
|
+
<button
|
|
35
|
+
@click="filterByStatus('failed')"
|
|
36
|
+
class="bg-red-50 border border-red-200 rounded-md p-3 text-center hover:bg-red-100 transition-colors cursor-pointer"
|
|
37
|
+
:class="{ 'ring-2 ring-red-400': currentFilter === 'failed' }"
|
|
38
|
+
>
|
|
39
|
+
<div class="text-xs text-red-600 font-medium">Failed</div>
|
|
40
|
+
<div class="text-lg font-bold text-red-700">{{ taskGroup.statusCounts.failed || 0 }}</div>
|
|
41
|
+
</button>
|
|
42
|
+
<button
|
|
43
|
+
@click="filterByStatus('cancelled')"
|
|
44
|
+
class="bg-gray-50 border border-gray-200 rounded-md p-3 text-center hover:bg-gray-100 transition-colors cursor-pointer"
|
|
45
|
+
:class="{ 'ring-2 ring-gray-400': currentFilter === 'cancelled' }"
|
|
46
|
+
>
|
|
47
|
+
<div class="text-xs text-gray-600 font-medium">Cancelled</div>
|
|
48
|
+
<div class="text-lg font-bold text-gray-700">{{ taskGroup.statusCounts.cancelled || 0 }}</div>
|
|
49
|
+
</button>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<!-- Task List -->
|
|
53
|
+
<div class="bg-white rounded-lg shadow">
|
|
54
|
+
<div class="px-6 py-4 border-b border-gray-200 flex items-center justify-between">
|
|
55
|
+
<h2 class="text-lg font-semibold text-gray-700">
|
|
56
|
+
Individual Tasks
|
|
57
|
+
<span v-if="currentFilter" class="text-sm font-normal text-gray-500 ml-2">
|
|
58
|
+
(Filtered by {{ currentFilter }})
|
|
59
|
+
</span>
|
|
60
|
+
</h2>
|
|
61
|
+
<button
|
|
62
|
+
v-if="currentFilter"
|
|
63
|
+
@click="clearFilter"
|
|
64
|
+
class="text-sm text-ultramarine-600 hover:text-ultramarine-700 font-medium"
|
|
65
|
+
>
|
|
66
|
+
Show All
|
|
67
|
+
</button>
|
|
68
|
+
</div>
|
|
69
|
+
<div class="divide-y divide-gray-200">
|
|
70
|
+
<div v-for="task in sortedTasks" :key="task.id" class="p-6">
|
|
71
|
+
<div class="flex items-start justify-between">
|
|
72
|
+
<div class="flex-1">
|
|
73
|
+
<div class="flex items-center gap-3 mb-2">
|
|
74
|
+
<span class="text-sm font-medium text-gray-900">Task ID: {{ task.id }}</span>
|
|
75
|
+
<span
|
|
76
|
+
class="text-xs px-2 py-1 rounded-full font-medium"
|
|
77
|
+
:class="getStatusColor(task.status)"
|
|
78
|
+
>
|
|
79
|
+
{{ task.status }}
|
|
80
|
+
</span>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
|
|
84
|
+
<div>
|
|
85
|
+
<label class="block text-sm font-medium text-gray-700 mb-1">Scheduled At</label>
|
|
86
|
+
<div class="text-sm text-gray-900">{{ formatDate(task.scheduledAt) }}</div>
|
|
87
|
+
</div>
|
|
88
|
+
<div v-if="task.startedAt">
|
|
89
|
+
<label class="block text-sm font-medium text-gray-700 mb-1">Started At</label>
|
|
90
|
+
<div class="text-sm text-gray-900">{{ formatDate(task.startedAt) }}</div>
|
|
91
|
+
</div>
|
|
92
|
+
<div v-if="task.completedAt">
|
|
93
|
+
<label class="block text-sm font-medium text-gray-700 mb-1">Completed At</label>
|
|
94
|
+
<div class="text-sm text-gray-900">{{ formatDate(task.completedAt) }}</div>
|
|
95
|
+
</div>
|
|
96
|
+
<div v-if="task.error">
|
|
97
|
+
<label class="block text-sm font-medium text-gray-700 mb-1">Error</label>
|
|
98
|
+
<div class="text-sm text-red-600">{{ task.error }}</div>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<!-- Task Parameters -->
|
|
103
|
+
<div v-if="task.parameters && Object.keys(task.parameters).length > 0">
|
|
104
|
+
<label class="block text-sm font-medium text-gray-700 mb-2">Parameters</label>
|
|
105
|
+
<div class="bg-gray-50 rounded-md p-3">
|
|
106
|
+
<pre class="text-sm text-gray-800 whitespace-pre-wrap">{{ JSON.stringify(task.parameters, null, 2) }}</pre>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<div class="flex flex-col gap-3 ml-6">
|
|
112
|
+
<button
|
|
113
|
+
@click="showRescheduleConfirmation(task)"
|
|
114
|
+
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 transform hover:scale-105 transition-all duration-200 shadow-md hover:shadow-lg disabled:opacity-50 disabled:cursor-not-allowed disabled:transform-none"
|
|
115
|
+
:disabled="task.status === 'in_progress'"
|
|
116
|
+
>
|
|
117
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
118
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
|
119
|
+
</svg>
|
|
120
|
+
Reschedule
|
|
121
|
+
</button>
|
|
122
|
+
<button
|
|
123
|
+
@click="showRunConfirmation(task)"
|
|
124
|
+
class="flex items-center justify-center gap-2 bg-gradient-to-r from-green-500 to-green-600 text-white px-4 py-2 rounded-lg text-sm font-medium hover:from-green-600 hover:to-green-700 transform hover:scale-105 transition-all duration-200 shadow-md hover:shadow-lg disabled:opacity-50 disabled:cursor-not-allowed disabled:transform-none"
|
|
125
|
+
:disabled="task.status === 'in_progress'"
|
|
126
|
+
>
|
|
127
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
128
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 3l14 9-14 9V3z"></path>
|
|
129
|
+
</svg>
|
|
130
|
+
Run Now
|
|
131
|
+
</button>
|
|
132
|
+
<button
|
|
133
|
+
v-if="task.status === 'pending'"
|
|
134
|
+
@click="showCancelConfirmation(task)"
|
|
135
|
+
class="flex items-center justify-center gap-2 bg-gradient-to-r from-red-500 to-red-600 text-white px-4 py-2 rounded-lg text-sm font-medium hover:from-red-600 hover:to-red-700 transform hover:scale-105 transition-all duration-200 shadow-md hover:shadow-lg"
|
|
136
|
+
>
|
|
137
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
138
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
|
139
|
+
</svg>
|
|
140
|
+
Cancel
|
|
141
|
+
</button>
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
|
|
148
|
+
<!-- Reschedule Confirmation Modal -->
|
|
149
|
+
<modal v-if="showRescheduleModal" containerClass="!max-w-md">
|
|
150
|
+
<template #body>
|
|
151
|
+
<div class="absolute font-mono right-1 top-1 cursor-pointer text-xl" @click="showRescheduleModal = false;" role="button" aria-label="Close modal">×</div>
|
|
152
|
+
<div class="p-6">
|
|
153
|
+
<div class="flex items-center mb-4">
|
|
154
|
+
<div class="flex-shrink-0">
|
|
155
|
+
<svg class="w-6 h-6 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
156
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
|
157
|
+
</svg>
|
|
158
|
+
</div>
|
|
159
|
+
<div class="ml-3">
|
|
160
|
+
<h3 class="text-lg font-medium text-gray-900">Reschedule Task</h3>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
<div class="mb-4">
|
|
164
|
+
<p class="text-sm text-gray-600">
|
|
165
|
+
Are you sure you want to reschedule task <strong>{{ selectedTask?.id }}</strong>?
|
|
166
|
+
</p>
|
|
167
|
+
<p class="text-sm text-gray-500 mt-2">
|
|
168
|
+
This will reset the task's status and schedule it to run again.
|
|
169
|
+
</p>
|
|
170
|
+
|
|
171
|
+
<div class="mt-4">
|
|
172
|
+
<label for="newScheduledTime" class="block text-sm font-medium text-gray-700 mb-2">
|
|
173
|
+
New Scheduled Time
|
|
174
|
+
</label>
|
|
175
|
+
<input
|
|
176
|
+
id="newScheduledTime"
|
|
177
|
+
v-model="newScheduledTime"
|
|
178
|
+
type="datetime-local"
|
|
179
|
+
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"
|
|
180
|
+
required
|
|
181
|
+
/>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
<div class="flex gap-3">
|
|
185
|
+
<button
|
|
186
|
+
@click="confirmRescheduleTask"
|
|
187
|
+
class="flex-1 bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 font-medium"
|
|
188
|
+
>
|
|
189
|
+
Reschedule
|
|
190
|
+
</button>
|
|
191
|
+
<button
|
|
192
|
+
@click="showRescheduleModal = false"
|
|
193
|
+
class="flex-1 bg-gray-300 text-gray-700 px-4 py-2 rounded-md hover:bg-gray-400 font-medium"
|
|
194
|
+
>
|
|
195
|
+
Cancel
|
|
196
|
+
</button>
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
199
|
+
</template>
|
|
200
|
+
</modal>
|
|
201
|
+
|
|
202
|
+
<!-- Run Task Confirmation Modal -->
|
|
203
|
+
<modal v-if="showRunModal" containerClass="!max-w-md">
|
|
204
|
+
<template #body>
|
|
205
|
+
<div class="absolute font-mono right-1 top-1 cursor-pointer text-xl" @click="showRunModal = false;" role="button" aria-label="Close modal">×</div>
|
|
206
|
+
<div class="p-6">
|
|
207
|
+
<div class="flex items-center mb-4">
|
|
208
|
+
<div class="flex-shrink-0">
|
|
209
|
+
<svg class="w-6 h-6 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
210
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h1m4 0h1m-6 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
|
211
|
+
</svg>
|
|
212
|
+
</div>
|
|
213
|
+
<div class="ml-3">
|
|
214
|
+
<h3 class="text-lg font-medium text-gray-900">Run Task Now</h3>
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
<div class="mb-4">
|
|
218
|
+
<p class="text-sm text-gray-600">
|
|
219
|
+
Are you sure you want to run task <strong>{{ selectedTask?.id }}</strong> immediately?
|
|
220
|
+
</p>
|
|
221
|
+
<p class="text-sm text-gray-500 mt-2">
|
|
222
|
+
This will execute the task right away, bypassing its scheduled time.
|
|
223
|
+
</p>
|
|
224
|
+
</div>
|
|
225
|
+
<div class="flex gap-3">
|
|
226
|
+
<button
|
|
227
|
+
@click="confirmRunTask"
|
|
228
|
+
class="flex-1 bg-green-600 text-white px-4 py-2 rounded-md hover:bg-green-700 font-medium"
|
|
229
|
+
>
|
|
230
|
+
Run Now
|
|
231
|
+
</button>
|
|
232
|
+
<button
|
|
233
|
+
@click="showRunModal = false"
|
|
234
|
+
class="flex-1 bg-gray-300 text-gray-700 px-4 py-2 rounded-md hover:bg-gray-400 font-medium"
|
|
235
|
+
>
|
|
236
|
+
Cancel
|
|
237
|
+
</button>
|
|
238
|
+
</div>
|
|
239
|
+
</div>
|
|
240
|
+
</template>
|
|
241
|
+
</modal>
|
|
242
|
+
|
|
243
|
+
<!-- Cancel Task Confirmation Modal -->
|
|
244
|
+
<modal v-if="showCancelModal" containerClass="!max-w-md">
|
|
245
|
+
<template #body>
|
|
246
|
+
<div class="absolute font-mono right-1 top-1 cursor-pointer text-xl" @click="showCancelModal = false;" role="button" aria-label="Close modal">×</div>
|
|
247
|
+
<div class="p-6">
|
|
248
|
+
<div class="flex items-center mb-4">
|
|
249
|
+
<div class="flex-shrink-0">
|
|
250
|
+
<svg class="w-6 h-6 text-red-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
251
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
|
252
|
+
</svg>
|
|
253
|
+
</div>
|
|
254
|
+
<div class="ml-3">
|
|
255
|
+
<h3 class="text-lg font-medium text-gray-900">Cancel Task</h3>
|
|
256
|
+
</div>
|
|
257
|
+
</div>
|
|
258
|
+
<div class="mb-4">
|
|
259
|
+
<p class="text-sm text-gray-600">
|
|
260
|
+
Are you sure you want to cancel task <strong>{{ selectedTask?.id }}</strong>?
|
|
261
|
+
</p>
|
|
262
|
+
<p class="text-sm text-gray-500 mt-2">
|
|
263
|
+
This will permanently cancel the task and it cannot be undone.
|
|
264
|
+
</p>
|
|
265
|
+
</div>
|
|
266
|
+
<div class="flex gap-3">
|
|
267
|
+
<button
|
|
268
|
+
@click="confirmCancelTask"
|
|
269
|
+
class="flex-1 bg-red-600 text-white px-4 py-2 rounded-md hover:bg-red-700 font-medium"
|
|
270
|
+
>
|
|
271
|
+
Cancel Task
|
|
272
|
+
</button>
|
|
273
|
+
<button
|
|
274
|
+
@click="showCancelModal = false"
|
|
275
|
+
class="flex-1 bg-gray-300 text-gray-700 px-4 py-2 rounded-md hover:bg-gray-400 font-medium"
|
|
276
|
+
>
|
|
277
|
+
Keep Task
|
|
278
|
+
</button>
|
|
279
|
+
</div>
|
|
280
|
+
</div>
|
|
281
|
+
</template>
|
|
282
|
+
</modal>
|
|
283
|
+
</div>
|
|
284
|
+
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const template = require('./task-details.html');
|
|
4
|
+
const api = require('../../api');
|
|
5
|
+
|
|
6
|
+
module.exports = app => app.component('task-details', {
|
|
7
|
+
props: ['taskGroup', 'currentFilter'],
|
|
8
|
+
data: () => ({
|
|
9
|
+
showRescheduleModal: false,
|
|
10
|
+
showRunModal: false,
|
|
11
|
+
showCancelModal: false,
|
|
12
|
+
selectedTask: null,
|
|
13
|
+
newScheduledTime: ''
|
|
14
|
+
}),
|
|
15
|
+
computed: {
|
|
16
|
+
sortedTasks() {
|
|
17
|
+
let tasks = this.taskGroup.tasks;
|
|
18
|
+
|
|
19
|
+
// Apply filter if one is set
|
|
20
|
+
if (this.currentFilter) {
|
|
21
|
+
tasks = tasks.filter(task => task.status === this.currentFilter);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return tasks.sort((a, b) => {
|
|
25
|
+
const dateA = new Date(a.scheduledAt || a.createdAt || 0);
|
|
26
|
+
const dateB = new Date(b.scheduledAt || b.createdAt || 0);
|
|
27
|
+
return dateB - dateA; // Most recent first
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
methods: {
|
|
32
|
+
getStatusColor(status) {
|
|
33
|
+
if (status === 'succeeded') {
|
|
34
|
+
return 'bg-green-100 text-green-800';
|
|
35
|
+
} else if (status === 'pending') {
|
|
36
|
+
return 'bg-yellow-100 text-yellow-800';
|
|
37
|
+
} else if (status === 'cancelled') {
|
|
38
|
+
return 'bg-gray-100 text-gray-800';
|
|
39
|
+
} else if (status === 'failed') {
|
|
40
|
+
return 'bg-red-100 text-red-800';
|
|
41
|
+
} else if (status === 'in_progress') {
|
|
42
|
+
return 'bg-blue-100 text-blue-800';
|
|
43
|
+
} else {
|
|
44
|
+
return 'bg-slate-100 text-slate-800';
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
formatDate(dateString) {
|
|
48
|
+
if (!dateString) return 'N/A';
|
|
49
|
+
return new Date(dateString).toLocaleString();
|
|
50
|
+
},
|
|
51
|
+
async rescheduleTask(task) {
|
|
52
|
+
if (!this.newScheduledTime) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
console.log('Rescheduling task:', task.id, 'to:', this.newScheduledTime);
|
|
56
|
+
await api.Task.rescheduleTask({ taskId: task.id, scheduledAt: this.newScheduledTime });
|
|
57
|
+
},
|
|
58
|
+
async runTask(task) {
|
|
59
|
+
console.log('Running task:', task.id);
|
|
60
|
+
await api.Task.runTask({ taskId: task.id });
|
|
61
|
+
},
|
|
62
|
+
async cancelTask(task) {
|
|
63
|
+
await api.Task.cancelTask({ taskId: task.id });
|
|
64
|
+
// Refresh the task data by emitting an event to the parent
|
|
65
|
+
this.$emit('task-cancelled');
|
|
66
|
+
},
|
|
67
|
+
filterByStatus(status) {
|
|
68
|
+
// If clicking the same status, clear the filter
|
|
69
|
+
if (this.currentFilter === status) {
|
|
70
|
+
this.$emit('update:currentFilter', null);
|
|
71
|
+
} else {
|
|
72
|
+
this.$emit('update:currentFilter', status);
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
clearFilter() {
|
|
76
|
+
this.$emit('update:currentFilter', null);
|
|
77
|
+
},
|
|
78
|
+
showRescheduleConfirmation(task) {
|
|
79
|
+
this.selectedTask = task;
|
|
80
|
+
// Set default time to 1 hour from now
|
|
81
|
+
const defaultTime = new Date();
|
|
82
|
+
defaultTime.setHours(defaultTime.getHours() + 1);
|
|
83
|
+
this.newScheduledTime = defaultTime.toISOString().slice(0, 16);
|
|
84
|
+
this.showRescheduleModal = true;
|
|
85
|
+
},
|
|
86
|
+
showRunConfirmation(task) {
|
|
87
|
+
this.selectedTask = task;
|
|
88
|
+
this.showRunModal = true;
|
|
89
|
+
},
|
|
90
|
+
showCancelConfirmation(task) {
|
|
91
|
+
this.selectedTask = task;
|
|
92
|
+
this.showCancelModal = true;
|
|
93
|
+
},
|
|
94
|
+
async confirmRescheduleTask() {
|
|
95
|
+
try {
|
|
96
|
+
await this.rescheduleTask(this.selectedTask);
|
|
97
|
+
|
|
98
|
+
// Show success message
|
|
99
|
+
this.$toast.create({
|
|
100
|
+
title: 'Task Rescheduled Successfully!',
|
|
101
|
+
text: `Task ${this.selectedTask.id} has been rescheduled`,
|
|
102
|
+
type: 'success',
|
|
103
|
+
timeout: 3000,
|
|
104
|
+
positionClass: 'bottomRight'
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
this.showRescheduleModal = false;
|
|
108
|
+
this.selectedTask = null;
|
|
109
|
+
this.newScheduledTime = '';
|
|
110
|
+
} catch (error) {
|
|
111
|
+
console.error('Error in confirmRescheduleTask:', error);
|
|
112
|
+
this.$toast.create({
|
|
113
|
+
title: 'Failed to Reschedule Task',
|
|
114
|
+
text: error?.response?.data?.message || error.message || 'An unexpected error occurred',
|
|
115
|
+
type: 'error',
|
|
116
|
+
timeout: 5000,
|
|
117
|
+
positionClass: 'bottomRight'
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
async confirmRunTask() {
|
|
122
|
+
try {
|
|
123
|
+
await this.runTask(this.selectedTask);
|
|
124
|
+
|
|
125
|
+
// Show success message
|
|
126
|
+
this.$toast.create({
|
|
127
|
+
title: 'Task Started Successfully!',
|
|
128
|
+
text: `Task ${this.selectedTask.id} is now running`,
|
|
129
|
+
type: 'success',
|
|
130
|
+
timeout: 3000,
|
|
131
|
+
positionClass: 'bottomRight'
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
this.showRunModal = false;
|
|
135
|
+
this.selectedTask = null;
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.error('Error in confirmRunTask:', error);
|
|
138
|
+
this.$toast.create({
|
|
139
|
+
title: 'Failed to Run Task',
|
|
140
|
+
text: error?.response?.data?.message || error.message || 'An unexpected error occurred',
|
|
141
|
+
type: 'error',
|
|
142
|
+
timeout: 5000,
|
|
143
|
+
positionClass: 'bottomRight'
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
async confirmCancelTask() {
|
|
148
|
+
try {
|
|
149
|
+
await this.cancelTask(this.selectedTask);
|
|
150
|
+
|
|
151
|
+
// Show success message
|
|
152
|
+
this.$toast.create({
|
|
153
|
+
title: 'Task Cancelled Successfully!',
|
|
154
|
+
text: `Task ${this.selectedTask.id} has been cancelled`,
|
|
155
|
+
type: 'success',
|
|
156
|
+
timeout: 3000,
|
|
157
|
+
positionClass: 'bottomRight'
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
this.showCancelModal = false;
|
|
161
|
+
this.selectedTask = null;
|
|
162
|
+
} catch (error) {
|
|
163
|
+
console.error('Error in confirmCancelTask:', error);
|
|
164
|
+
this.$toast.create({
|
|
165
|
+
title: 'Failed to Cancel Task',
|
|
166
|
+
text: error?.response?.data?.message || error.message || 'An unexpected error occurred',
|
|
167
|
+
type: 'error',
|
|
168
|
+
timeout: 5000,
|
|
169
|
+
positionClass: 'bottomRight'
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
},
|
|
175
|
+
mounted() {
|
|
176
|
+
// Check if the task group was already filtered when passed from parent
|
|
177
|
+
if (this.taskGroup.filteredStatus && !this.currentFilter) {
|
|
178
|
+
this.$emit('update:currentFilter', this.taskGroup.filteredStatus);
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
template: template
|
|
182
|
+
});
|
|
File without changes
|