mirror of
https://github.com/lifegpc/eh-downloader.git
synced 2026-07-08 01:31:00 +08:00
Update task render
This commit is contained in:
85
components/Progress.tsx
Normal file
85
components/Progress.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
import {
|
||||
Component,
|
||||
ComponentChildren,
|
||||
ContextType,
|
||||
createContext,
|
||||
} from "preact";
|
||||
|
||||
type CtxProps = {
|
||||
min: number;
|
||||
max: number;
|
||||
striped: boolean;
|
||||
animated: boolean;
|
||||
};
|
||||
|
||||
const PCtx = createContext<CtxProps | null>(null);
|
||||
|
||||
type BarProps = {
|
||||
value: number;
|
||||
striped?: boolean;
|
||||
animated?: boolean;
|
||||
class?: string;
|
||||
};
|
||||
|
||||
class ProgressBar extends Component<BarProps> {
|
||||
static contextType = PCtx;
|
||||
declare context: ContextType<typeof PCtx>;
|
||||
render() {
|
||||
let cls = "progress-bar";
|
||||
const striped = this.props.striped === undefined
|
||||
? this.context?.striped
|
||||
: this.props.striped;
|
||||
const animated = this.props.animated === undefined
|
||||
? this.context?.animated
|
||||
: this.props.animated;
|
||||
if (striped || animated) cls += " progress-bar-striped";
|
||||
if (animated) cls += " progress-bar-animated";
|
||||
if (this.props.class) cls += " " + this.props.class;
|
||||
const max = this.context?.max || 100;
|
||||
const min = this.context?.min || 0;
|
||||
const v = this.props.value;
|
||||
const style = `width: ${(v - min) / (max - min) * 100}%;`;
|
||||
return (
|
||||
<div
|
||||
class={cls}
|
||||
style={style}
|
||||
role="progressbar"
|
||||
aria-valuenow={v}
|
||||
aria-valuemin={min}
|
||||
aria-valuemax={max}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
type Props = {
|
||||
/**@default {0} */
|
||||
min?: number;
|
||||
/**@default {100} */
|
||||
max?: number;
|
||||
/**@default {false} */
|
||||
striped?: boolean;
|
||||
/**@default {false} */
|
||||
animated?: boolean;
|
||||
children: ComponentChildren;
|
||||
};
|
||||
|
||||
export default class Progress extends Component<Props> {
|
||||
static readonly Bar = ProgressBar;
|
||||
render() {
|
||||
return (
|
||||
<div class="progress">
|
||||
<PCtx.Provider
|
||||
value={{
|
||||
min: this.props.min || 0,
|
||||
max: this.props.max || 100,
|
||||
striped: this.props.striped || false,
|
||||
animated: this.props.animated || false,
|
||||
}}
|
||||
>
|
||||
{this.props.children}
|
||||
</PCtx.Provider>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,10 @@
|
||||
import { Component } from "preact";
|
||||
import Icon from "preact-material-components/Icon";
|
||||
import type { TaskDetail } from "../task.ts";
|
||||
import type { TaskDetail, TaskProgressBasicType } from "../task.ts";
|
||||
import { TaskStatus, TaskType } from "../task.ts";
|
||||
import t from "../server/i18n.ts";
|
||||
import { tw } from "twind";
|
||||
import Progress from "./Progress.tsx";
|
||||
|
||||
type Props = {
|
||||
task: TaskDetail;
|
||||
@@ -11,6 +14,20 @@ type State = {
|
||||
task_changed: (d: Event) => void;
|
||||
};
|
||||
|
||||
const Types: Record<TaskType, string> = {
|
||||
[TaskType.Download]: "download",
|
||||
[TaskType.ExportZip]: "export_zip",
|
||||
[TaskType.UpdateMeiliSearchData]: "update_meilisearch_data",
|
||||
[TaskType.FixGalleryPage]: "fix_gallery_page",
|
||||
};
|
||||
|
||||
const Status: Record<TaskStatus, string> = {
|
||||
[TaskStatus.Wait]: "waiting",
|
||||
[TaskStatus.Running]: "running",
|
||||
[TaskStatus.Finished]: "finished",
|
||||
[TaskStatus.Failed]: "failed",
|
||||
};
|
||||
|
||||
export default class Task extends Component<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
@@ -28,11 +45,39 @@ export default class Task extends Component<Props, State> {
|
||||
render() {
|
||||
const task = this.props.task;
|
||||
console.log(task);
|
||||
let error_div = null;
|
||||
if (task.status === TaskStatus.Failed) {
|
||||
error_div = (
|
||||
<div class="error">
|
||||
{t("task.error_msg")}
|
||||
<div class={tw`text-red-500`}>{task.error}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
let progress_div = null;
|
||||
if (task.status === TaskStatus.Running && task.progress) {
|
||||
if (task.base.type === TaskType.Download) {
|
||||
const d = task
|
||||
.progress as TaskProgressBasicType[TaskType.Download];
|
||||
progress_div = (
|
||||
<Progress max={d.total_page} animated={true}>
|
||||
<Progress.Bar
|
||||
class="bg-success"
|
||||
value={d.downloaded_page}
|
||||
/>
|
||||
<Progress.Bar class="bg-danger" value={d.failed_page} />
|
||||
</Progress>
|
||||
);
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div data-id={task.base.id}>
|
||||
<Icon class="task_handle">unfold_more</Icon>
|
||||
{t("task.id")}
|
||||
{task.base.id}
|
||||
<div>{t("task.id")}{task.base.id}</div>
|
||||
<div>{t("task.type")}{t(`task.${Types[task.base.type]}`)}</div>
|
||||
<div>{t("task.status")}{t(`task.${Status[task.status]}`)}</div>
|
||||
{error_div}
|
||||
{progress_div}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user