yggdrasil/pages/admin/system/backup/
row.rs1use crate::api::database::backup::BackupInfo;
2use crate::components::ui::{
3 button_class, ButtonSize, ButtonVariant, ConfirmDialog, IconName, StatusDot,
4};
5use crate::utils::format_bytes;
6use leptos::prelude::*;
7
8#[component]
12pub(super) fn BackupRow(
13 info: BackupInfo,
14 #[prop(into)] busy: Signal<bool>,
15 #[prop(into)] on_restore: Callback<String>,
16 #[prop(into)] on_delete: Callback<String>,
17) -> impl IntoView {
18 let fname_for_restore = info.filename.clone();
19 let fname_for_delete = info.filename.clone();
20
21 let dl_url = format!(
23 "/api/database/backups/{}",
24 super::super::urlencode(&info.filename)
25 );
26 let size_str = format_bytes(info.size_bytes as i64);
27 let (origin_label, origin_tone) = if info.origin == "auto" {
28 ("自动", "clay")
29 } else {
30 ("手动", "muted")
31 };
32 let uploads_dl = info.uploads_filename.as_ref().map(|f| {
33 (
34 format_bytes(info.uploads_size_bytes.unwrap_or(0) as i64),
35 format!("/api/database/backups/{}", super::super::urlencode(f)),
36 )
37 });
38 let up_size = uploads_dl.as_ref().map(|(size, _)| size.clone());
39 let up_url = uploads_dl.map(|(_, url)| url);
40
41 let confirm_restore = RwSignal::new(false);
42 let confirm_delete = RwSignal::new(false);
43 let restore_description = format!(
44 "现有数据会被「{}」覆盖。只恢复数据库,素材不随之还原,需要从配对的压缩包手动恢复。",
45 info.filename
46 );
47 let delete_description = format!("「{}」会从磁盘上删除,无法恢复。", info.filename);
48
49 view! {
50 <tr>
51 <td class="sys-mono">{info.filename.clone()}</td>
52 <td>
53 <StatusDot label=origin_label tone=origin_tone/>
54 </td>
55 <td class="admin-table-muted">{info.mode.clone()}</td>
56 <td class="admin-table-num">
57 {size_str}
58 {up_size.map(|up_size| view! { <div class="sys-sub">{format!("素材 {up_size}")}</div> })}
59 </td>
60 <td class="sys-row-actions">
61 <a
62 class=button_class(ButtonVariant::Ghost, ButtonSize::Xs)
63 href=dl_url
64 rel="external"
65 download=""
66 >
67 "下载"
68 </a>
69 {up_url
70 .map(|up_url| {
71 view! {
72 <a
73 class=button_class(ButtonVariant::Ghost, ButtonSize::Xs)
74 href=up_url
75 rel="external"
76 download=""
77 >
78 "素材"
79 </a>
80 }
81 })}
82 <button
83 class=button_class(ButtonVariant::Ghost, ButtonSize::Xs)
84 type="button"
85 disabled=move || busy.get()
86 on:click=move |_| confirm_restore.set(true)
87 >
88 "恢复"
89 </button>
90 <button
91 class=format!("{} sys-danger", button_class(ButtonVariant::Ghost, ButtonSize::Xs))
92 type="button"
93 disabled=move || busy.get()
94 on:click=move |_| confirm_delete.set(true)
95 >
96 "删除"
97 </button>
98 <ConfirmDialog
99 visible=confirm_restore
100 title="用这份备份恢复数据库?"
101 description=restore_description
102 confirm_label="确认恢复"
103 icon=IconName::RotateCcw
104 on_confirm=move |_| on_restore.run(fname_for_restore.clone())
105 />
106 <ConfirmDialog
107 visible=confirm_delete
108 title="删除这份备份?"
109 description=delete_description
110 confirm_label="确认删除"
111 on_confirm=move |_| on_delete.run(fname_for_delete.clone())
112 />
113 </td>
114 </tr>
115 }
116}