Skip to content

Commit

Permalink
Proof of Concept for rewrite as finder
Browse files Browse the repository at this point in the history
  • Loading branch information
jrief committed Nov 22, 2023
1 parent d10c7e9 commit 0016f34
Show file tree
Hide file tree
Showing 79 changed files with 4,310 additions and 5 deletions.
4 changes: 1 addition & 3 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# editorconfig.org

root = true
# https://editorconfig.org

[*]
indent_style = space
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,6 @@ share/
.python-version
data
local.sqlite

workdir/
finder/static/admin/finder/
17 changes: 17 additions & 0 deletions client/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# https://editorconfig.org

root = true

[*.{ts,tsx,scss,svg}]
indent_size = 4
indent_style = tab
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.svg]
insert_final_newline = false
indent_size = 2

[*.scss]
indent_size = 2
33 changes: 33 additions & 0 deletions client/Droppable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';
import {useDroppable} from '@dnd-kit/core';


export function DroppableArea(props) {
const {id, className, currentId, dragging, children} = props;
const {
isOver,
over,
setNodeRef,
} = useDroppable({
id: id,
});

function cssClasses() {
const classes = [className];
if (dragging) {
classes.push('dragging');
}
if (isOver && over.id !== currentId) {
classes.push('drag-over');
}
return classes.join(' ');
}

console.log('DroppableArea', id, currentId);

return (
<div ref={setNodeRef} className={cssClasses()}>
{children}
</div>
);
}
11 changes: 11 additions & 0 deletions client/FileAdmin.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React, {useContext, useRef, useState} from 'react';
import {FinderSettings} from './FinderSettings';


export default function FileAdmin(props) {
const settings = useContext(FinderSettings);

return (
<div className="finder">Edit File</div>
);
}
156 changes: 156 additions & 0 deletions client/FileUploader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import React, {forwardRef, useContext, useEffect, useImperativeHandle, useRef, useState} from 'react';
import {FinderSettings} from './FinderSettings';


function ProgressOverlay(props) {
return (
<div className="progress-overlay">
<div className="progress-indicator">{
props.dragging ? (
<p>Drop files here</p>
) : (<>
<p>Uploading:</p>
<ul className="progress-bar">
{props.children}
</ul>
</>)
}</div>
</div>
);
}


function ProgressBar(props) {
const settings = useContext(FinderSettings);
const {file, folderId} = props;
const [complete, setComplete] = useState(0);

useEffect(() => {
const uploadFilesURL = `${settings.base_url}${folderId}/upload`;
const request = new XMLHttpRequest();
request.addEventListener('loadstart', transferStart);
request.upload.addEventListener('progress', transferProgress, false);
request.addEventListener('loadend', transferComplete);
request.open('POST', uploadFilesURL, true);
request.setRequestHeader('X-CSRFToken', settings.csrf_token);
request.responseType = 'json';
const body = new FormData();
body.append('upload_file', file);
request.send(body);

return () => {
request.removeEventListener('loadstart', transferStart);
request.removeEventListener('progress', transferProgress);
request.removeEventListener('loadend', transferComplete);
};
}, [file]);

function transferStart() {
setComplete(0);
}

function transferProgress(event: ProgressEvent) {
if (event.lengthComputable) {
setComplete(event.loaded / event.total * 0.98);
}
}

function transferComplete(event: ProgressEvent) {
if (event.lengthComputable) {
setComplete(1);
}
const request = event.target as XMLHttpRequest;
if (request.status === 200) {
file.resolve(request.response);
} else {
file.reject(request.response);
}
}

return (
<li>
<span>{file.name}:</span>
<progress value={complete} max="1"></progress>
</li>
);
}


export const FileUploader = forwardRef((props: any, forwardedRef) => {
const settings = useContext(FinderSettings);
const {folderId, handleUpload} = props;
const inputRef = useRef(null);
const [dragging, setDragging] = useState(false);
const [uploading, setUploading] = useState([]);

useImperativeHandle(forwardedRef, () => ({
openUploader() {
inputRef.current.click()
}
}));

function swallowEvent(event) {
event.stopPropagation();
event.preventDefault();
}

function handleDragEnter(event) {
swallowEvent(event);
setDragging(true);
}

function handleDragLeave(event) {
swallowEvent(event);
const {relatedTarget} = event;
if (!relatedTarget || !event.currentTarget.contains(relatedTarget)) {
setDragging(false);
}
}

function handleDrop(event) {
swallowEvent(event);
setDragging(false);
if (event.dataTransfer) {
uploadFiles(event.dataTransfer.files);
}
}

function handleFileSelect(event) {
uploadFiles(event.target.files);
}

function uploadFiles(files: FileList) {
const promises: Array<Promise<Response>> = [];
for (let k = 0; k < files.length; k++) {
promises.push(uploadFile(files.item(k)));
}
setUploading([...uploading, ...files]);
Promise.all(promises).catch((error) => {
alert(error);
}).finally( () => {
setUploading([]);
handleUpload(folderId);
});
}

function uploadFile(file) {
return new Promise<Response>((resolve, reject) => {
file.resolve = resolve;
file.reject = reject;
});
}

return (
<div className="file-uploader" onDragEnter={handleDragEnter} onDragOver={swallowEvent} onDragLeave={handleDragLeave} onDrop={handleDrop}>
{props.children}
<input type="file" name={`file:${folderId}`} multiple ref={inputRef} onChange={handleFileSelect} />
{dragging || uploading.length > 0 ? (
<ProgressOverlay dragging={dragging}>{
uploading.map((file, index) =>
<ProgressBar key={index} file={file} folderId={folderId} />
)
}</ProgressOverlay>
) : null}
</div>
)
});
3 changes: 3 additions & 0 deletions client/FinderSettings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import {createContext} from 'react';

export const FinderSettings = createContext(undefined);
Loading

0 comments on commit 0016f34

Please sign in to comment.