Skip to content

Commit

Permalink
add filepond, refactor savePictures to support progress callback.
Browse files Browse the repository at this point in the history
  • Loading branch information
lordbagel42 committed Sep 14, 2024
1 parent b3d70ba commit d2ed101
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 69 deletions.
20 changes: 17 additions & 3 deletions client/models/FIRST/team.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ export class FIRSTTeam extends Cache<FIRSTTeamEventData> {
window.history.pushState({}, '', url.toString());
}

public async savePictures(files: FileList): Promise<Result<void>> {
public async savePictures(files: FileList, onProgress: (progress: number) => void): Promise<Result<void>> {
return attemptAsync(async () => {
return new Promise((res, rej) => {
const stream = ServerRequest.streamFiles(
Expand All @@ -347,8 +347,22 @@ export class FIRSTTeam extends Cache<FIRSTTeamEventData> {
}
);

stream.on('error', rej);
stream.on('complete', () => res());
stream.on('progress', (e) => {
if (e.lengthComputable) {
const progress = (e.loaded / e.total) * 100;
onProgress(progress);
}
});

stream.on('complete', () => {
console.log('All files uploaded successfully');
res();
});

stream.on('error', (e) => {
console.error('Error uploading files:', e);
rej(e);
});
});
});
}
Expand Down
183 changes: 125 additions & 58 deletions client/views/components/robot-display/UploadTeamPicture.svelte
Original file line number Diff line number Diff line change
@@ -1,62 +1,129 @@
<script lang="ts">
import UploadPicture from '../main/UploadPicture.svelte';
import { FIRSTTeam } from '../../../models/FIRST/team';
import { onMount } from 'svelte';
import { Modal } from '../../../utilities/modals';
import { alert } from '../../../utilities/notifications';
export let team: FIRSTTeam | undefined = undefined;
let fileList: FileList;
let me: HTMLDivElement;
const open = () => {
if (!team) return alert('No team selected!');
const m = new Modal();
const upload = new UploadPicture({
target: m.target.querySelector('.modal-body') as HTMLElement
});
upload.$on('change', (e: CustomEvent) => {
fileList = e.detail.fileList;
});
m.show();
const close = document.createElement('button');
close.classList.add('btn', 'btn-secondary');
close.textContent = 'Close';
close.addEventListener('click', () => m.hide());
const submit = document.createElement('button');
submit.classList.add('btn', 'btn-success');
submit.textContent = 'Submit';
submit.addEventListener('click', () => {
if (fileList.length === 0) return;
if (!team) return console.error('No team');
team.savePictures(fileList);
m.hide();
});
const group = document.createElement('div');
group.classList.add('btn-group', 'd-flex', 'justify-content-between');
group.appendChild(close);
group.appendChild(submit);
m.setFooter(group);
m.on('hide', () => {
m.destroy();
upload.$destroy();
});
};
import { attemptAsync } from '../../../../shared/check';
import FilePond, { registerPlugin } from 'svelte-filepond';
import FilePondPluginImageExifOrientation from 'filepond-plugin-image-exif-orientation';
import FilePondPluginImagePreview from 'filepond-plugin-image-preview';
import FilePondPluginImageCrop from 'filepond-plugin-image-crop';
import FilePondPluginImageResize from 'filepond-plugin-image-resize';
import FilePondPluginImageTransform from 'filepond-plugin-image-transform';
import { FIRSTTeam } from '../../../models/FIRST/team';
import { alert } from '../../../utilities/notifications';
import { getContext } from 'svelte';
import { ActualFileObject } from 'filepond';
import { onMount } from 'svelte';
registerPlugin(
FilePondPluginImageExifOrientation,
FilePondPluginImagePreview,
FilePondPluginImageTransform,
FilePondPluginImageCrop,
FilePondPluginImageResize
);
export let team: FIRSTTeam | undefined = undefined;
let pond: FilePond;
let name = 'team-pictures';
const handleInit = async () => {
console.log('FilePond has initialised');
};
const uploadFile = async (file: ActualFileObject) => {
if (!team) {
alert('No team selected!');
return;
}
const fileList = new DataTransfer();
const realFile = new File([file], file.name, {
type: file.type,
lastModified: file.lastModified
});
fileList.items.add(realFile);
const result = await team.savePictures(fileList.files, progress => {});
if (result.isErr()) {
alert('Failed to upload picture. Please try again.');
console.error(result.error);
return;
}
if (result.isOk()) {
console.log(`Picture ${file.name} uploaded successfully`);
return true;
}
};
const handleAddFile = async (err: any, file: ActualFileObject) => {

Check failure on line 59 in client/views/components/robot-display/UploadTeamPicture.svelte

View workflow job for this annotation

GitHub Actions / format_and_lint

Unexpected any. Specify a different type
console.log('A file has been added', file);
await uploadFile(file);
};
onMount(() => {
const creditsElements = document.querySelectorAll('.filepond--credits');
creditsElements.forEach(element => element.remove());
// the credits don't want to style correctly, will add if I can figure out the styles
});
// TODO: https://pqina.nl/pintura/docs/v8/installation/filepond/
// filepond image editor, should be limitable to just cropping and rotation
</script>

<div bind:this="{me}">
<button
class="btn btn-primary"
type="button"
on:click="{open}"
>Upload Pictures</button>
<div class="bg-dark">
<FilePond
bind:this="{pond}"
{name}
allowMultiple="{true}"
labelIdle="Drag & Drop your team pictures or <span class='filepond--label-action'>Browse</span>"
oninit="{handleInit}"
allowImageTransform="{true}"
imageTransformOutputQuality="{25}"
imageTransformOutputMimeType="image/jpeg"
instantUpload="{true}"
server="{{
process: async (
fieldName,
file,
metadata,
load,
error,
progress,
abort,
transfer,
options
) => {
try {
const result = await uploadFile(file);
if (result) {
load(file);
} else {
error('Failed to upload picture. Please try again.');
}
} catch (err) {
console.error('Error during upload:', err);
error('Failed to upload picture. Please try again.');
}
}
}}"
/>
</div>

<style>
@import 'filepond/dist/filepond.css';
@import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css';
:global(.filepond--panel-root) {
background-color: var(--bs-dark);
border: 1px solid var(--bs-gray-dark);
border-radius: var(--bs-border-radius);
padding: var(--bs-spacing);
box-shadow: var(--bs-box-shadow);
}
:global(.filepond--drop-label) {
color: var(--bs-light);
}
</style>
73 changes: 67 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@
"@typescript-eslint/eslint-plugin": "^6.19.0",
"@typescript-eslint/parser": "^6.19.0",
"callsite": "^1.0.0",
"chart.js": "^4.4.1",
"concurrently": "^8.2.2",
"esbuild": "^0.20.1",
"esbuild-sass-plugin": "^3.2.0",
"eslint": "^8.57.0",
"eslint-plugin-svelte": "^2.43.0",
"chart.js": "^4.4.1",
"prettier": "^3.2.2",
"prettier-plugin-svelte": "^3.1.2",
"svelte": "^4.2.19",
Expand Down Expand Up @@ -82,6 +82,11 @@
"esbuild-svelte": "^0.8.0",
"express": "^4.18.3",
"express-session": "^1.18.0",
"filepond-plugin-image-crop": "^2.0.6",
"filepond-plugin-image-exif-orientation": "^1.0.11",
"filepond-plugin-image-preview": "^4.6.12",
"filepond-plugin-image-resize": "^2.0.10",
"filepond-plugin-image-transform": "^3.8.7",
"fuzzy-search": "^3.2.1",
"icons": "^1.0.0",
"inquirer": "^9.2.15",
Expand All @@ -101,8 +106,9 @@
"prompts": "^2.4.2",
"socket.io": "^4.7.4",
"socket.io-client": "^4.7.4",
"systeminformation": "^5.22.11",
"svelte-chartjs": "^3.1.5",
"svelte-filepond": "^0.2.2",
"systeminformation": "^5.22.11",
"test": "^3.3.0",
"ts-node": "^10.9.2",
"uuid": "^9.0.1",
Expand Down

0 comments on commit d2ed101

Please sign in to comment.