feat(ui): useUploadJar uses XHR and exposes onProgress
This commit is contained in:
@@ -140,21 +140,47 @@ export function useAppVersions(envSlug: string | undefined, appSlug: string | un
|
|||||||
export function useUploadJar() {
|
export function useUploadJar() {
|
||||||
const qc = useQueryClient();
|
const qc = useQueryClient();
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async ({ envSlug, appSlug, file }: { envSlug: string; appSlug: string; file: File }) => {
|
mutationFn: ({ envSlug, appSlug, file, onProgress }: {
|
||||||
|
envSlug: string;
|
||||||
|
appSlug: string;
|
||||||
|
file: File;
|
||||||
|
onProgress?: (pct: number) => void;
|
||||||
|
}) => {
|
||||||
const token = useAuthStore.getState().accessToken;
|
const token = useAuthStore.getState().accessToken;
|
||||||
const form = new FormData();
|
const form = new FormData();
|
||||||
form.append('file', file);
|
form.append('file', file);
|
||||||
const res = await fetch(
|
|
||||||
`${config.apiBaseUrl}${envBase(envSlug)}/${encodeURIComponent(appSlug)}/versions`, {
|
return new Promise<AppVersion>((resolve, reject) => {
|
||||||
method: 'POST',
|
const xhr = new XMLHttpRequest();
|
||||||
headers: {
|
xhr.open(
|
||||||
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
'POST',
|
||||||
'X-Cameleer-Protocol-Version': '1',
|
`${config.apiBaseUrl}${envBase(envSlug)}/${encodeURIComponent(appSlug)}/versions`,
|
||||||
},
|
);
|
||||||
body: form,
|
if (token) xhr.setRequestHeader('Authorization', `Bearer ${token}`);
|
||||||
|
xhr.setRequestHeader('X-Cameleer-Protocol-Version', '1');
|
||||||
|
|
||||||
|
xhr.upload.onprogress = (e) => {
|
||||||
|
if (!onProgress || !e.lengthComputable) return;
|
||||||
|
onProgress(Math.round((e.loaded / e.total) * 100));
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onload = () => {
|
||||||
|
if (xhr.status < 200 || xhr.status >= 300) {
|
||||||
|
reject(new Error(`Upload failed: ${xhr.status}`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
resolve(JSON.parse(xhr.responseText) as AppVersion);
|
||||||
|
} catch (err) {
|
||||||
|
reject(err instanceof Error ? err : new Error('Invalid response'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onerror = () => reject(new Error('Upload network error'));
|
||||||
|
xhr.onabort = () => reject(new Error('Upload aborted'));
|
||||||
|
|
||||||
|
xhr.send(form);
|
||||||
});
|
});
|
||||||
if (!res.ok) throw new Error(`Upload failed: ${res.status}`);
|
|
||||||
return res.json() as Promise<AppVersion>;
|
|
||||||
},
|
},
|
||||||
onSuccess: (_data, { envSlug, appSlug }) =>
|
onSuccess: (_data, { envSlug, appSlug }) =>
|
||||||
qc.invalidateQueries({ queryKey: ['apps', envSlug, appSlug, 'versions'] }),
|
qc.invalidateQueries({ queryKey: ['apps', envSlug, appSlug, 'versions'] }),
|
||||||
|
|||||||
Reference in New Issue
Block a user