@@ -9,7 +9,8 @@ <h1 class="text-xl flex-1">{{ module_name }} ({{ project_name }})</h1>
99 < button id ="openOutputFolder " class ="px-2 py-1 bg-white shadow text-xs hover:bg-gray-100 "> Open output folder</ button >
1010 < div >
1111 < button id ="openAppdataFolder " class ="px-2 py-1 bg-white shadow text-xs hover:bg-gray-100 mr-2 "> Open appdata folder</ button >
12- < button id ="openLogsFolder " class ="px-2 py-1 bg-white shadow text-xs hover:bg-gray-100 "> Open logs folder</ button >
12+ < button id ="openLogsFolder " class ="px-2 py-1 bg-white shadow text-xs hover:bg-gray-100 mr-2 "> Open logs folder</ button >
13+ < button id ="cancelTask " class ="px-2 py-1 bg-white shadow text-xs hover:bg-gray-100 text-orange-600 hover:text-orange-900 hidden "> Cancel task</ button >
1314 </ div >
1415 </ div >
1516 < div id ="errorPopup " class ="hidden fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full ">
@@ -27,6 +28,21 @@ <h3 class="text-lg leading-6 font-medium text-gray-900">Error</h3>
2728 </ div >
2829 </ div >
2930 </ div >
31+ < div id ="cancelledPopup " class ="hidden fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full ">
32+ < div class ="relative top-20 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white ">
33+ < div class ="mt-3 text-center ">
34+ < h3 id ="cancelledTitle " class ="text-lg leading-6 font-medium text-gray-900 "> Task Cancelled</ h3 >
35+ < div class ="mt-2 px-7 py-3 ">
36+ < p id ="cancelledMessage " class ="text-sm text-gray-500 "> </ p >
37+ </ div >
38+ < div class ="items-center px-4 py-3 ">
39+ < button id ="closeCancelled " class ="px-4 py-2 bg-green-500 text-white text-base font-medium rounded-md shadow-sm hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-300 ">
40+ Close
41+ </ button >
42+ </ div >
43+ </ div >
44+ </ div >
45+ </ div >
3046 < pre class ="bg-black text-white p-4 font-mono text-xs h-[calc(100vh-13rem-45px)] overflow-y-auto whitespace-pre-wrap " id ="logContent ">
3147 </ pre >
3248</ div >
@@ -42,6 +58,7 @@ <h3 class="text-lg leading-6 font-medium text-gray-900">Error</h3>
4258 let sameContentCount = 0 ;
4359 let pollInterval ;
4460 let hasError = false ;
61+ let taskStatus = null ;
4562
4663 // List of error messages from validate_config
4764 const errorMessages = [
@@ -68,6 +85,8 @@ <h3 class="text-lg leading-6 font-medium text-gray-900">Error</h3>
6885 const response = await fetch ( `/api/task_status/${ projectId } ` ) ;
6986 const data = await response . json ( ) ;
7087
88+ taskStatus = data . status ;
89+
7190 if ( data . log_path && data . log_path !== '' && data . log_path !== logPath ) {
7291 logPath = data . log_path ;
7392 console . log ( 'Log path updated to:' , logPath ) ;
@@ -84,6 +103,7 @@ <h3 class="text-lg leading-6 font-medium text-gray-900">Error</h3>
84103 }
85104
86105 updateFolderLinks ( ) ;
106+ updateCancelButton ( ) ;
87107
88108 if ( data . status === 'FAILED' ) {
89109 hasError = true ;
@@ -96,6 +116,18 @@ <h3 class="text-lg leading-6 font-medium text-gray-900">Error</h3>
96116 } , 3000 ) ;
97117 return ;
98118 }
119+
120+ if ( data . status === 'CANCELLED' ) {
121+ hasError = true ;
122+ document . getElementById ( 'cancelledMessage' ) . textContent = "Task has been cancelled." ;
123+ document . getElementById ( 'cancelledPopup' ) . classList . remove ( 'hidden' ) ;
124+ clearInterval ( pollInterval ) ;
125+ clearInterval ( statusInterval ) ;
126+ setTimeout ( ( ) => {
127+ window . location . href = '/task_list' ;
128+ } , 3000 ) ;
129+ return ;
130+ }
99131 } catch ( error ) {
100132 console . error ( 'Error checking task status:' , error ) ;
101133 }
@@ -151,6 +183,53 @@ <h3 class="text-lg leading-6 font-medium text-gray-900">Error</h3>
151183 }
152184 }
153185
186+ function updateCancelButton ( ) {
187+ const cancelBtn = document . getElementById ( 'cancelTask' ) ;
188+
189+ if ( taskStatus === 'PENDING' || taskStatus === 'RUNNING' ) {
190+ cancelBtn . classList . remove ( 'hidden' ) ;
191+ } else {
192+ cancelBtn . classList . add ( 'hidden' ) ;
193+ }
194+ }
195+
196+ function getCsrfToken ( ) {
197+ return document . querySelector ( 'meta[name="csrf_token"]' ) . getAttribute ( 'content' ) ;
198+ }
199+
200+ async function cancelTask ( ) {
201+ if ( ! confirm ( 'Are you sure you want to cancel this task?' ) ) {
202+ return ;
203+ }
204+
205+ try {
206+ const response = await fetch ( `/cancel_task/${ projectId } /` , {
207+ method : 'POST' ,
208+ headers : {
209+ 'X-CSRFToken' : getCsrfToken ( ) ,
210+ } ,
211+ } ) ;
212+
213+ if ( response . ok ) {
214+ hasError = true ;
215+ document . getElementById ( 'cancelledTitle' ) . textContent = "Cancelling Task" ;
216+ document . getElementById ( 'cancelledMessage' ) . textContent = "Task is being cancelled..." ;
217+ document . getElementById ( 'cancelledPopup' ) . classList . remove ( 'hidden' ) ;
218+ clearInterval ( pollInterval ) ;
219+ clearInterval ( statusInterval ) ;
220+ setTimeout ( ( ) => {
221+ window . location . href = '/task_list' ;
222+ } , 2000 ) ;
223+ } else {
224+ const result = await response . json ( ) ;
225+ alert ( 'Failed to cancel task: ' + ( result . message || 'Unknown error' ) ) ;
226+ }
227+ } catch ( error ) {
228+ console . error ( 'Error:' , error ) ;
229+ alert ( 'Failed to cancel task: ' + error . message ) ;
230+ }
231+ }
232+
154233 async function fetchLogContent ( ) {
155234 if ( hasError ) return ;
156235
@@ -187,6 +266,9 @@ <h3 class="text-lg leading-6 font-medium text-gray-900">Error</h3>
187266 document . getElementById ( 'errorPopup' ) . classList . add ( 'hidden' ) ;
188267 window . history . back ( ) ; // Return to previous page
189268 } ) ;
269+
270+ // Handle cancel button click
271+ document . getElementById ( 'cancelTask' ) . addEventListener ( 'click' , cancelTask ) ;
190272
191273 // Initial fetch
192274 fetchLogContent ( ) ;
0 commit comments