Files
spacedrive/interface/app/$libraryId/Layout/Sidebar/JobManager/Job.tsx
Consoli 9e09d92f03 [ENG-1159] Report progress when copying files (#2538)
* Copy ephemeral files by chunks

* Improving buffered writer

* Report progress

* Copy and emit progress as two separated tasks

* Simplify for-if-return with `Iterator::any`

* Docs and use structured tracing

* Simplify code using paths

* wip

* wip

* wip

* wip

* Add report of messages while copying files

* Add info field to job report

* Group paths from OldFileCopierJobStep into a single struct

* Improve progress information

* Remove the need for synchronization

* Error handling for copy

* Clean up frontend

* Make watcher only consider new files

* Fix concurrent renaming of multiple files that have the same name

* Add documentation for file strategist

* Remove editions to ephemeral file copies

* Remove experimental/nightly features from Cargo.toml

* Fix no-case-declarations

* Remove dead comments

* Format code

* Use "Duplicate" instead of "Copy" in the frontend messages

* Remove inline always to make clippy happy

* icons for deleter and copier

* Fix JobManager for copy jobs
 - Fix some types definitions

* Fix Job icon choosing logic
 - Fix Copier job showing two progress bars

* Log which files are not formatted in the Type and style check CI

* fmt

* Forgot an import

* autoformat

---------

Co-authored-by: ameer2468 <33054370+ameer2468@users.noreply.github.com>
Co-authored-by: Vítor Vasconcellos <vasconcellos.dev@gmail.com>
2024-08-17 02:00:59 +00:00

117 lines
2.7 KiB
TypeScript

import {
Copy,
Fingerprint,
Folder,
Icon,
Image,
Info,
Lightning,
Scissors,
Trash
} from '@phosphor-icons/react';
import { memo } from 'react';
import { JobName, JobProgressEvent, Report, useJobInfo } from '@sd/client';
import { ProgressBar } from '@sd/ui';
import { showAlertDialog } from '~/components';
import { useLocale } from '~/hooks';
import JobContainer from './JobContainer';
interface JobProps {
job: Report;
className?: string;
isChild?: boolean;
progress: JobProgressEvent | null;
eta: number;
}
export const JobIcon: Record<JobName, Icon> = {
Indexer: Folder,
MediaProcessor: Image,
FileIdentifier: Fingerprint,
Copy: Copy,
Delete: Trash,
Erase: Trash,
Move: Scissors,
FileValidator: Fingerprint
};
// Jobs like deleting and copying files do not have simplied job names
// so we need to use the metadata to display an icon
const MetaDataJobIcon = {
deleter: Trash,
copier: Copy
};
function Job({ job, className, isChild, progress, eta }: JobProps) {
const jobData = useJobInfo(job, progress);
const { t } = useLocale();
// I don't like sending TSX as a prop due to lack of hot-reload, but it's the only way to get the error log to show up
if (job.status === 'CompletedWithErrors') {
const JobError = (
<pre className="custom-scroll inspector-scroll max-h-[300px] rounded border border-app-darkBox bg-app-darkBox/80 p-3">
{job.non_critical_errors.map((error, i) => (
<p
className="mb-1 w-full overflow-auto whitespace-normal break-words text-sm"
key={i}
>
{/* TODO: Report errors in a nicer way */}
{JSON.stringify(error)}
</p>
))}
</pre>
);
jobData.textItems?.push([
{
text: t('completed_with_errors'),
icon: Info,
onClick: () => {
showAlertDialog({
title: t('error'),
description: t('job_error_description'),
children: JobError
});
}
}
]);
}
let jobIcon = Lightning;
if (job.name in JobIcon) {
jobIcon = JobIcon[job.name];
} else {
const meta = [...jobData.meta, ...jobData.output].find(
(meta) => meta.type in MetaDataJobIcon
);
if (meta) {
jobIcon = MetaDataJobIcon[meta.type as keyof typeof MetaDataJobIcon];
}
}
return (
<JobContainer
className={className}
name={jobData.name}
icon={jobIcon}
eta={eta}
status={job.status}
textItems={
['Queued'].includes(job.status) ? [[{ text: job.status }]] : jobData.textItems
}
isChild={isChild}
>
{(jobData.isRunning || jobData.isPaused) && (
<div className="my-1 ml-1.5 w-[335px]">
<ProgressBar
pending={jobData.taskCount == 0}
value={jobData.completedTaskCount}
total={jobData.taskCount}
/>
</div>
)}
</JobContainer>
);
}
export default memo(Job);