@@ -69,7 +69,7 @@ import { getTimeAgoString, callAdminForthApi, getCustomComponent} from '@/utils'
6969import { useI18n } from ' vue-i18n' ;
7070import StateToIcon from ' ./StateToIcon.vue' ;
7171import { useAdminforth } from ' @/adminforth' ;
72- import { onBeforeUnmount , ref , watch } from ' vue' ;
72+ import { onBeforeUnmount , onMounted , ref , watch } from ' vue' ;
7373import websocket from ' @/websocket' ;
7474import { useBackgroundJobApi } from ' ./useBackgroundJobApi' ;
7575
@@ -115,13 +115,11 @@ function createStateFieldSubscription(
115115 callback : (data : any ) => void ,
116116) {
117117 const paths = getUniqueFieldNames (fieldNames ).map (pathFactory );
118- for (const path of paths ) {
119- websocket .subscribe (path , callback );
120- }
118+ const pathCleanups = paths .map ((path ) => websocket .subscribe (path , callback ));
121119
122120 const unsubscribe = () => {
123- for (const path of paths ) {
124- websocket . unsubscribe ( path );
121+ for (const cleanup of pathCleanups ) {
122+ cleanup ( );
125123 }
126124 subscriptionCleanups .delete (unsubscribe );
127125 };
@@ -155,6 +153,50 @@ function handleTaskStateFieldUpdate(data: TaskStateFieldUpdate) {
155153 };
156154}
157155
156+ function handleTaskStatusUpdate(data : { taskIndex: number ; status: string }) {
157+ if (! jobTasks .value [data .taskIndex ]) {
158+ return ;
159+ }
160+
161+ jobTasks .value [data .taskIndex ].status = data .status ;
162+ }
163+
164+ function handleJobUpdate(data : {
165+ jobId: string ;
166+ status? : IJob [' status' ];
167+ progress? : string ;
168+ finishedAt? : Date ;
169+ state? : Record <string , any >;
170+ }) {
171+ if (data .jobId !== props .job .id ) {
172+ return ;
173+ }
174+
175+ if (data .status ) {
176+ props .job .status = data .status ;
177+ }
178+ if (data .progress !== undefined ) {
179+ props .job .progress = data .progress ;
180+ }
181+ if (data .finishedAt ) {
182+ props .job .finishedAt = data .finishedAt ;
183+ }
184+ if (data .state ) {
185+ props .job .state = {
186+ ... props .job .state ,
187+ ... data .state ,
188+ };
189+ }
190+ if (jobStore .currentJob ?.id === props .job .id ) {
191+ jobStore .updateCurrentJob ({
192+ status: props .job .status ,
193+ progress: props .job .progress ,
194+ finishedAt: props .job .finishedAt ,
195+ state: props .job .state ,
196+ });
197+ }
198+ }
199+
158200function subscribeToJobStateFields(fieldNames : string []) {
159201 return createStateFieldSubscription (
160202 fieldNames ,
@@ -241,6 +283,13 @@ watch(
241283 { immediate: true }
242284);
243285
286+ onMounted (() => {
287+ const taskStatusPath = ` /background-jobs-task-update/${props .job .id } ` ;
288+ subscriptionCleanups .add (websocket .subscribe (taskStatusPath , handleTaskStatusUpdate ));
289+
290+ subscriptionCleanups .add (websocket .subscribe (' /background-jobs-job-update' , handleJobUpdate ));
291+ });
292+
244293onBeforeUnmount (() => {
245294 for (const unsubscribe of Array .from (subscriptionCleanups )) {
246295 unsubscribe ();
0 commit comments