Files
spacedrive/interface/app/$libraryId/Layout/Sidebar/JobManager/useGroupJobTimeText.tsx
Jamie Pine dd464a2953 [ENG-686, ENG-670, ENG-669] Improved Job Manager (#907)
* refactor job manager ui

* huge improvements to job ui api

* improve indexer errors

* minor improvements

* make icon bigger + improve styling

* Update useJobInfo.tsx

better

* improve job status reporting

* fix job indexer backend for ui responsiveness

* attempt at debugging job.getRunning slow invalidation during indexer's walk phase

* remove progress debounce, invalidate has its own throttle layer

* hotfix ghost jobs

* basic pause/resume

* pause functionality immaculate

* pause resume working for first job in group, testable on indexer phase two

* WIP
- refactored job manager
- added better job api

* fix merge issues

* add throttle to job update events and correct index

* improve front end job data handling

* move subscription to job

* wip active job indicator

* minor tweak

* Isolated subscriptions for job events + cleanup

Co-authored-by: Brendan Allan <Brendonovich@users.noreply.github.com>
Co-authored-by: Oscar Beaumont <oscar@otbeaumont.me>

* mutable ctx

* plz let me build rspc typesafe errors Jamie

* fix merge

* working job reporting

* fix thumbnail text

* faster tick speed

* fix error

---------

Co-authored-by: Brendan Allan <Brendonovich@users.noreply.github.com>
Co-authored-by: Oscar Beaumont <oscar@otbeaumont.me>
2023-06-16 03:49:02 +00:00

62 lines
1.7 KiB
TypeScript

import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration';
import { useEffect, useMemo } from 'react';
import { JobReport } from '@sd/client';
import { useForceUpdate } from '~/util';
dayjs.extend(duration);
// TODO: refactor this, its a mess.
export function useTotalElapsedTimeText(jobs: JobReport[] = []) {
const forceUpdate = useForceUpdate();
const elapsedTimeText = useMemo(() => {
let total = 0;
let text: string | null = '';
const groupedJobs = jobs.reduce((acc: Record<string, JobReport[]>, job) => {
const parentId = String(job.parent_id);
if (!acc[parentId]) {
acc[parentId] = [];
}
acc[parentId]?.push(job);
return acc;
}, {});
Object.values(groupedJobs).forEach((group: JobReport[]) => {
let groupTotal = 0;
group.forEach((job) => {
const start = dayjs(job.started_at);
const end = job.completed_at ? dayjs(job.completed_at) : dayjs();
groupTotal += end.diff(start, 'minutes');
});
total += groupTotal;
const lastJob = group[group.length - 1];
if (lastJob?.status === 'Failed' || lastJob?.status === 'Canceled') {
text = 'Job failed or canceled';
} else {
text = lastJob?.completed_at
? `Took ${dayjs.duration(groupTotal, 'minutes').humanize()}`
: null;
}
});
return text;
}, [jobs]);
useEffect(() => {
const allJobsCompleted = jobs.every((job) => job.completed_at);
const isJobsQueued = jobs.some((job) => job.status === 'Queued');
if (!allJobsCompleted || isJobsQueued) {
const interval = setInterval(forceUpdate, 1000);
return () => clearInterval(interval);
}
}, [jobs, forceUpdate]);
return elapsedTimeText === 'Took NaN years' ? null : elapsedTimeText;
}