1
0
mirror of https://github.com/immich-app/immich.git synced 2025-06-25 04:53:00 +02:00

fix(web/server) uploaded asset in shared link not loaded ()

* fix(web/server): Uploaded asset to shared link does not get added to the shared link/album

* remove unused code

* Add endpoints for each remove and add assets to shared link

* Update api

* Added deletion logic

* Convert callback to async/await

* Fix linter

* Fix test

* Fix server test

* added test

* Test coverage

* modify DTO

* Add notification

* fix test
This commit is contained in:
Alex
2023-02-15 15:21:22 -06:00
committed by GitHub
parent 125ec1e85f
commit b660240059
25 changed files with 583 additions and 526 deletions

@ -6,71 +6,65 @@ import { uploadAssetsStore } from '$lib/stores/upload';
import type { UploadAsset } from '../models/upload-asset';
import { api, AssetFileUploadResponseDto } from '@api';
import { addAssetsToAlbum, getFileMimeType, getFilenameExtension } from '$lib/utils/asset-utils';
import { Subject, mergeMap } from 'rxjs';
import { mergeMap, filter, firstValueFrom, from, of, combineLatestAll } from 'rxjs';
import axios from 'axios';
export const openFileUploadDialog = (
export const openFileUploadDialog = async (
albumId: string | undefined = undefined,
sharedKey: string | undefined = undefined,
onDone?: (id: string) => void
sharedKey: string | undefined = undefined
) => {
try {
const fileSelector = document.createElement('input');
return new Promise<(string | undefined)[]>((resolve, reject) => {
try {
const fileSelector = document.createElement('input');
fileSelector.type = 'file';
fileSelector.multiple = true;
fileSelector.type = 'file';
fileSelector.multiple = true;
// When adding a content type that is unsupported by browsers, make sure
// to also add it to getFileMimeType() otherwise the upload will fail.
fileSelector.accept = 'image/*,video/*,.heic,.heif,.dng,.3gp,.nef,.srw,.raf';
// When adding a content type that is unsupported by browsers, make sure
// to also add it to getFileMimeType() otherwise the upload will fail.
fileSelector.accept = 'image/*,video/*,.heic,.heif,.dng,.3gp,.nef,.srw,.raf';
fileSelector.onchange = async (e: Event) => {
const target = e.target as HTMLInputElement;
if (!target.files) {
return;
}
const files = Array.from<File>(target.files);
fileSelector.onchange = async (e: Event) => {
const target = e.target as HTMLInputElement;
if (!target.files) {
return;
}
const files = Array.from<File>(target.files);
await fileUploadHandler(files, albumId, sharedKey, onDone);
};
resolve(await fileUploadHandler(files, albumId, sharedKey));
};
fileSelector.click();
} catch (e) {
console.log('Error selecting file', e);
}
fileSelector.click();
} catch (e) {
console.log('Error selecting file', e);
reject(e);
}
});
};
export const fileUploadHandler = async (
files: File[],
albumId: string | undefined = undefined,
sharedKey: string | undefined = undefined,
onDone?: (id: string) => void
sharedKey: string | undefined = undefined
) => {
const files$ = new Subject<File>();
files$
.pipe(
mergeMap(async (file) => {
await fileUploader(file, albumId, sharedKey, onDone);
}, 2)
return firstValueFrom(
from(files).pipe(
filter((file) => {
const assetType = getFileMimeType(file).split('/')[0];
return assetType === 'video' || assetType === 'image';
}),
mergeMap(async (file) => of(await fileUploader(file, albumId, sharedKey)), 2),
combineLatestAll()
)
.subscribe();
const acceptedFile = files.filter((file) => {
const assetType = getFileMimeType(file).split('/')[0];
return assetType === 'video' || assetType === 'image';
});
for (const file of acceptedFile) {
files$.next(file);
}
);
};
//TODO: should probably use the @api SDK
async function fileUploader(
asset: File,
albumId: string | undefined = undefined,
sharedKey: string | undefined = undefined,
onDone?: (id: string) => void
) {
console.log('uploading', asset.name);
sharedKey: string | undefined = undefined
): Promise<string | undefined> {
const mimeType = getFileMimeType(asset);
const assetType = mimeType.split('/')[0].toUpperCase();
const fileExtension = getFilenameExtension(asset.name);
@ -121,67 +115,50 @@ async function fileUploader(
}
);
if (status === 200) {
if (data.isExist) {
const dataId = data.id;
if (albumId && dataId) {
addAssetsToAlbum(albumId, [dataId], sharedKey);
}
onDone && dataId && onDone(dataId);
return;
if (status === 200 && data.isExist && data.id) {
if (albumId) {
await addAssetsToAlbum(albumId, [data.id], sharedKey);
}
return data.id;
}
const request = new XMLHttpRequest();
request.upload.onloadstart = () => {
const newUploadAsset: UploadAsset = {
id: deviceAssetId,
file: asset,
progress: 0,
fileExtension: fileExtension
};
uploadAssetsStore.addNewUploadAsset(newUploadAsset);
const newUploadAsset: UploadAsset = {
id: deviceAssetId,
file: asset,
progress: 0,
fileExtension: fileExtension
};
request.upload.onload = () => {
uploadAssetsStore.removeUploadAsset(deviceAssetId);
const res: AssetFileUploadResponseDto = JSON.parse(request.response || '{}');
if (albumId) {
try {
if (res.id) {
addAssetsToAlbum(albumId, [res.id], sharedKey);
}
} catch (e) {
console.error('ERROR parsing data JSON in upload onload');
}
uploadAssetsStore.addNewUploadAsset(newUploadAsset);
const response = await axios.post(`/api/asset/upload`, formData, {
params: {
key: sharedKey
},
onUploadProgress: (event) => {
const percentComplete = Math.floor((event.loaded / event.total) * 100);
uploadAssetsStore.updateProgress(deviceAssetId, percentComplete);
}
onDone && onDone(res.id);
};
});
// listen for `error` event
request.upload.onerror = () => {
uploadAssetsStore.removeUploadAsset(deviceAssetId);
handleUploadError(asset, request.response);
};
if (response.status == 200 || response.status == 201) {
const res: AssetFileUploadResponseDto = response.data;
// listen for `abort` event
request.upload.onabort = () => {
uploadAssetsStore.removeUploadAsset(deviceAssetId);
handleUploadError(asset, request.response);
};
if (albumId && res.id) {
await addAssetsToAlbum(albumId, [res.id], sharedKey);
}
// listen for `progress` event
request.upload.onprogress = (event) => {
const percentComplete = Math.floor((event.loaded / event.total) * 100);
uploadAssetsStore.updateProgress(deviceAssetId, percentComplete);
};
setTimeout(() => {
uploadAssetsStore.removeUploadAsset(deviceAssetId);
}, 1000);
request.open('POST', `/api/asset/upload?key=${sharedKey ?? ''}`);
request.send(formData);
return res.id;
}
} catch (e) {
console.log('error uploading file ', e);
handleUploadError(asset, JSON.stringify(e));
uploadAssetsStore.removeUploadAsset(deviceAssetId);
}
}