feat: Добавлена вкладка управления резервными копиями

This commit is contained in:
Андрей Дувакин 2025-07-01 18:44:18 +05:00
parent 22c1a9ca80
commit 039d7cb0cb
2 changed files with 120 additions and 0 deletions

View File

@ -0,0 +1,116 @@
import {
useCreateBackupMutation,
useDeleteBackupMutation,
useGetBackupsQuery
} from "../../../../../Api/backupsApi.js";
import {useDispatch} from "react-redux";
import {notification} from "antd";
import {baseQueryWithAuth} from "../../../../../Api/baseQuery.js";
import {useState} from "react";
const useBackupManageTab = () => {
const dispatch = useDispatch();
const {data: backups, isLoading: isLoadingBackups, isError: isErrorBackups} = useGetBackupsQuery(undefined, {
pollingInterval: 60000,
});
const [createBackup, {isLoading: isCreatingBackup}] = useCreateBackupMutation();
const [deleteBackup, {isLoading: isDeletingBackup}] = useDeleteBackupMutation();
const [isDownloadingBackup, setDownloadingFiles] = useState(false);
const createBackupHandler = async () => {
try {
await createBackup().unwrap();
notification.success({
message: "Успех",
description: "Резервная копия успешно создана",
placement: "topRight",
});
} catch (e) {
notification.error({
message: "Ошибка",
description: e?.data?.detail || "Не удалось создать резервную копию",
placement: "topRight",
});
}
};
const downloadBackupHandler = async (backupId, fileName) => {
try {
setDownloadingFiles(true);
const {url, ...options} = await baseQueryWithAuth(
{
url: `/backups/${backupId}/`,
method: 'GET',
credentials: 'include',
},
{},
{}
);
const response = await fetch(url, {
...options,
method: 'GET',
credentials: 'include',
});
if (!response.ok) {
notification.error({
message: "Ошибка при скачивании файла",
description: "Не удалось загрузить файл.",
placement: "topRight",
});
}
const blob = await response.blob();
const downloadUrl = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = downloadUrl;
link.setAttribute("download", fileName || "file");
document.body.appendChild(link);
link.click();
link.remove();
window.URL.revokeObjectURL(downloadUrl);
setDownloadingFiles(false);
} catch (e) {
console.log(e)
notification.error({
message: "Ошибка",
description: e?.data?.detail || "Не удалось загрузить резервную копию",
placement: "topRight",
});
}
};
const deleteBackupHandler = async (backupId) => {
try {
await deleteBackup(backupId).unwrap();
notification.success({
message: "Успех",
description: "Резервная копия успешно удалена",
placement: "topRight",
});
} catch (e) {
notification.error({
message: "Ошибка",
description: e?.data?.detail || "Не удалось удалить резервную копию",
placement: "topRight",
});
}
};
return {
backups,
isLoadingBackups,
isErrorBackups,
isCreatingBackup,
isDownloadingBackup,
isDeletingBackup,
createBackupHandler,
downloadBackupHandler,
deleteBackupHandler,
}
};
export default useBackupManageTab;

View File

@ -21,6 +21,7 @@ import {rolesApi} from "../Api/rolesApi.js";
import adminReducer from "./Slices/adminSlice.js";
import {registerApi} from "../Api/registerApi.js";
import {appointmentFilesApi} from "../Api/appointmentFilesApi.js";
import {backupsApi} from "../Api/backupsApi.js";
export const store = configureStore({
reducer: {
@ -60,6 +61,8 @@ export const store = configureStore({
[registerApi.reducerPath]: registerApi.reducer,
[appointmentFilesApi.reducerPath]: appointmentFilesApi.reducer,
[backupsApi.reducerPath]: backupsApi.reducer
},
middleware: (getDefaultMiddleware) => (
getDefaultMiddleware().concat(
@ -77,6 +80,7 @@ export const store = configureStore({
rolesApi.middleware,
registerApi.middleware,
appointmentFilesApi.middleware,
backupsApi.middleware,
)
),
});