alova - add interceptor

This commit is contained in:
Proddy
2023-06-18 16:35:32 +02:00
parent b1d666d7b9
commit ce1b9f22cb
24 changed files with 200 additions and 331 deletions

View File

@@ -1,9 +0,0 @@
// TODO extractErrorMessage function can be removed!
export const extractErrorMessage = (error: any, defaultMessage: string) => {
if (error.request) {
return defaultMessage + ' (' + error.request.status + ': ' + error.request.statusText + ')';
} else if (error instanceof Error) {
return defaultMessage + ' (' + error.message + ')';
}
return defaultMessage;
};

View File

@@ -1,9 +1,6 @@
export * from './binding';
export * from './endpoints';
export * from './route';
export * from './submit';
export * from './time';
export * from './useRest';
// TODO remove useRest2
export * from './useRest2';
export * from './props';

View File

@@ -1,85 +1,76 @@
import { useCallback, useEffect, useState } from 'react';
import { useRequest, type Method } from 'alova';
import { useState } from 'react';
import { unstable_useBlocker as useBlocker } from 'react-router-dom';
import { toast } from 'react-toastify';
import { extractErrorMessage } from '.';
import type { AxiosPromise } from 'axios';
import { useI18nContext } from 'i18n/i18n-react';
export interface RestRequestOptions<D> {
read: () => AxiosPromise<D>;
update?: (value: D) => AxiosPromise<D>;
export interface RestRequestOptions2<D> {
read: () => Method<any, any, any, any, any, any, any>;
update: (value: D) => Method<any, any, any, any, any, any, any>;
}
export const useRest = <D>({ read, update }: RestRequestOptions<D>) => {
export const useRest = <D>({ read, update }: RestRequestOptions2<D>) => {
const { LL } = useI18nContext();
const [data, setData] = useState<D>();
const [saving, setSaving] = useState<boolean>(false);
const [errorMessage, setErrorMessage] = useState<string>();
const [restartNeeded, setRestartNeeded] = useState<boolean>(false);
const [origData, setOrigData] = useState<D>();
const [dirtyFlags, setDirtyFlags] = useState<string[]>();
const blocker = useBlocker(dirtyFlags?.length !== 0);
const [dirtyFlags, setDirtyFlags] = useState<string[]>([]);
const blocker = useBlocker(dirtyFlags.length !== 0);
const loadData = useCallback(async () => {
setData(undefined);
const { data: data, send: readData, update: updateData, onComplete: onReadComplete } = useRequest(read());
const {
loading: saving,
send: writeData,
onSuccess: onWriteSuccess
} = useRequest((newData: D) => update(newData), { immediate: false });
const updateDataValue = (new_data: D) => {
updateData({ data: new_data });
};
onWriteSuccess(() => {
toast.success(LL.UPDATED_OF(LL.SETTINGS()));
setDirtyFlags([]);
});
onReadComplete((event) => {
setOrigData(event.data);
});
const loadData = async () => {
setDirtyFlags([]);
setErrorMessage(undefined);
try {
const fetch_data = (await read()).data;
setData(fetch_data);
setOrigData(fetch_data);
} catch (error) {
const message = extractErrorMessage(error, LL.PROBLEM_LOADING());
toast.error(message);
setErrorMessage(message);
await readData().catch((error) => {
toast.error(error.message);
setErrorMessage(error.message);
});
};
const saveData = async () => {
if (!data) {
return;
}
}, [read, LL]);
const save = useCallback(
async (toSave: D) => {
if (!update) {
return;
setRestartNeeded(false);
setErrorMessage(undefined);
await writeData(data).catch((error) => {
if (error.message === 'Reboot required') {
setRestartNeeded(true);
} else {
toast.error(error.message);
setErrorMessage(error.message);
}
setSaving(true);
setRestartNeeded(false);
setErrorMessage(undefined);
try {
const response = await update(toSave);
setOrigData(response.data);
setData(response.data);
if (response.status === 205) {
setRestartNeeded(true); // reboot required
} else {
toast.success(LL.UPDATED_OF(LL.SETTINGS()));
}
} catch (error) {
const message = extractErrorMessage(error, LL.PROBLEM_UPDATING());
toast.error(message);
setErrorMessage(message);
} finally {
setSaving(false);
setDirtyFlags([]);
}
},
[update, LL]
);
const saveData = () => data && save(data);
useEffect(() => {
void loadData();
}, [loadData]);
});
};
return {
loadData,
saveData,
saving,
setData,
updateDataValue,
data,
origData,
dirtyFlags,

View File

@@ -1,84 +0,0 @@
import { useRequest, type Method } from 'alova';
import { useState } from 'react';
import { unstable_useBlocker as useBlocker } from 'react-router-dom';
import { toast } from 'react-toastify';
import { useI18nContext } from 'i18n/i18n-react';
export interface RestRequestOptions2<D> {
read: () => Method<any, any, any, any, any, any, any>;
update: (value: D) => Method<any, any, any, any, any, any, any>;
}
// TODO rename back to useRest
export const useRest2 = <D>({ read, update }: RestRequestOptions2<D>) => {
const { LL } = useI18nContext();
const [errorMessage, setErrorMessage] = useState<string>();
const [restartNeeded, setRestartNeeded] = useState<boolean>(false);
const [origData, setOrigData] = useState<D>();
const [dirtyFlags, setDirtyFlags] = useState<string[]>([]);
const blocker = useBlocker(dirtyFlags.length !== 0);
const { data: data, send: readData, update: updateData, onComplete: onReadComplete } = useRequest(read());
const {
loading: saving,
send: writeData,
onSuccess: onWriteSuccess
} = useRequest((newData: D) => update(newData), { immediate: false });
const updateDataValue = (new_data: D) => {
updateData({ data: new_data });
};
onWriteSuccess(() => {
toast.success(LL.UPDATED_OF(LL.SETTINGS()));
setDirtyFlags([]);
});
onReadComplete((event) => {
setOrigData(event.data);
});
const loadData = async () => {
setDirtyFlags([]);
setErrorMessage(undefined);
await readData().catch((error) => {
toast.error(error.message);
setErrorMessage(error.message);
});
};
const saveData = async () => {
if (!data) {
return;
}
setRestartNeeded(false);
setErrorMessage(undefined);
await writeData(data).catch((error) => {
if (error.message === 'Reboot required') {
setRestartNeeded(true);
} else {
toast.error(error.message);
setErrorMessage(error.message);
}
});
};
return {
loadData,
saveData,
saving,
updateDataValue,
data,
origData,
dirtyFlags,
setDirtyFlags,
setOrigData,
blocker,
errorMessage,
restartNeeded
} as const;
};