-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a form to allow panorama uploads to Pano #90
Draft
WillNilges
wants to merge
35
commits into
main
Choose a base branch
from
wdn/upload
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 32 commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
75fccf1
first wack
WillNilges f795754
Aha I think I got it
WillNilges 9b2b576
Well I got a 200 but it's not working
WillNilges ceb0bd4
IDK how to use computers
WillNilges 260624b
Works for one file
WillNilges 39c50a9
dropzone maybe
WillNilges 99264cb
wait hold on
WillNilges c05610a
thumbs are too big
WillNilges 53b7fd3
Rawdogging the styling works tho, still get errors
WillNilges 933e31e
Now, to combine them.
WillNilges 7f72f01
Getting somewhere
WillNilges 05f444c
Now that's what I call a high pass filter
WillNilges bc770c9
Previews are so back plus jsx lol
WillNilges 393dc78
Checkpoint
WillNilges 4f7bfe9
styling and code cleanup
WillNilges aa6bee7
Delete old submit handler
WillNilges 670dc20
Frontend is hard
WillNilges 9762523
ok getting there
WillNilges 981921b
Good enough for government work
WillNilges 3302ee0
Checkpoint
WillNilges f45bf52
No wrap
WillNilges e0b930f
chom
WillNilges c6ef17a
Ugh I hate it when I do that
WillNilges 6ce5c73
Jesus that took way too long
WillNilges eb57ca9
comments
WillNilges 7962fa7
cleanup
WillNilges 9e54346
Ah fuck I broke it
WillNilges 18798ac
thanks chatgpt
WillNilges 9bbf180
Jesus christ I can't believe that worked
WillNilges 3c5d3b6
We're almost there
WillNilges a27c4e1
Fucking sweet dude we got it working
WillNilges 2d7fe61
Cleanup
WillNilges a6e30cd
Fix race condition and stub tests
WillNilges a818349
Throbber
WillNilges 97f1527
Stub test
WillNilges File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// Idea: Have people validate their panoramas with their email? | ||
|
||
import PanoramaUploadForm from "@/components/PanoramaUpload/PanoramaUpload"; | ||
|
||
export default async function PanoramaUpload() { | ||
return ( | ||
<> | ||
<main> | ||
<PanoramaUploadForm /> | ||
</main> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
components/PanoramaDuplicateDialog/PanoramaDuplicateDialog.module.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
.alertTable table { | ||
font-family: arial, sans-serif; | ||
border-collapse: collapse; | ||
width: 100%; | ||
margin: 10px 0 0 0; | ||
} | ||
|
||
.alertTable th { | ||
background: #eeeee; | ||
} | ||
|
||
.alertTable td, | ||
th { | ||
border: 1px solid #dddddd; | ||
text-align: left; | ||
padding: 8px; | ||
} |
122 changes: 122 additions & 0 deletions
122
components/PanoramaDuplicateDialog/PanoramaDuplicateDialog.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import * as React from "react"; | ||
import Button from "@mui/material/Button"; | ||
import Dialog from "@mui/material/Dialog"; | ||
import DialogActions from "@mui/material/DialogActions"; | ||
import DialogContent from "@mui/material/DialogContent"; | ||
import DialogContentText from "@mui/material/DialogContentText"; | ||
import DialogTitle from "@mui/material/DialogTitle"; | ||
import styles from "./PanoramaDuplicateDialog.module.scss"; | ||
import { FormValues } from "../PanoramaUpload/PanoramaUpload"; | ||
|
||
interface PanoramaDuplicateDialogProps { | ||
formSubmission: FormValues; | ||
possibleDuplicates: Array<[string, string]>; | ||
isDialogOpened: boolean; | ||
handleClickUpload: () => void; | ||
handleClickCancel: () => void; | ||
} | ||
|
||
// https://mui.com/material-ui/react-dialog/#alerts | ||
export default function PanoramaDuplicateDialog({ | ||
formSubmission, | ||
possibleDuplicates, | ||
isDialogOpened, | ||
handleClickUpload, | ||
handleClickCancel, | ||
}: PanoramaDuplicateDialogProps) { | ||
return ( | ||
<React.Fragment> | ||
<Dialog | ||
open={isDialogOpened} | ||
onClose={handleClickCancel} | ||
aria-labelledby="alert-dialog-title" | ||
aria-describedby="alert-dialog-description" | ||
> | ||
<DialogTitle color="error" id="alert-dialog-title"> | ||
{"Possible duplicates detected"} | ||
</DialogTitle> | ||
<DialogContent> | ||
<DialogContentText id="alert-dialog-description"> | ||
The following images submitted seem to be duplicates of existing | ||
images for Install #{formSubmission.installNumber}. Would you like | ||
to upload these anyway? | ||
<br /> | ||
<div className={styles.alertTable}> | ||
<table> | ||
<tr> | ||
<th>Uploaded</th> | ||
<th>Existing Image</th> | ||
</tr> | ||
{possibleDuplicates.map(([k, v], _) => ( | ||
<tr> | ||
<td> | ||
<div | ||
style={{ | ||
display: "flex", | ||
flexDirection: "column", | ||
alignItems: "center", | ||
}} | ||
> | ||
<img | ||
src={URL.createObjectURL( | ||
formSubmission.dropzoneImages.find( | ||
(file: File) => file.name === k, | ||
), | ||
)} | ||
style={{ | ||
display: "block", | ||
marginLeft: "auto", | ||
marginRight: "auto", | ||
height: "100px", | ||
}} | ||
/> | ||
{ | ||
formSubmission.dropzoneImages.find( | ||
(file: File) => file.name === k, | ||
).name | ||
} | ||
</div> | ||
</td> | ||
<td> | ||
<div | ||
style={{ | ||
display: "flex", | ||
flexDirection: "column", | ||
alignItems: "center", | ||
}} | ||
> | ||
<img | ||
src={v} | ||
style={{ | ||
display: "block", | ||
marginLeft: "auto", | ||
marginRight: "auto", | ||
height: "100px", | ||
}} | ||
/> | ||
<a href={new URL(v).origin + new URL(v).pathname}> | ||
{new URL(v).origin + new URL(v).pathname} | ||
</a> | ||
</div> | ||
</td> | ||
</tr> | ||
))} | ||
</table> | ||
</div> | ||
</DialogContentText> | ||
</DialogContent> | ||
<DialogActions> | ||
<Button onClick={handleClickCancel}>Cancel</Button> | ||
<Button | ||
color="error" | ||
variant="contained" | ||
onClick={handleClickUpload} | ||
autoFocus | ||
> | ||
Upload | ||
</Button> | ||
</DialogActions> | ||
</Dialog> | ||
</React.Fragment> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
.container { | ||
display: flex; | ||
flex-direction: row; | ||
font-family: sans-serif; | ||
justify-content: center; | ||
|
||
margin: 10px; | ||
padding: 10px; | ||
} | ||
|
||
.subContainer { | ||
width: 75%; | ||
} | ||
|
||
.container > p { | ||
font-size: 1rem; | ||
} | ||
|
||
.container > em { | ||
font-size: 0.8rem; | ||
} | ||
|
||
.dropzone { | ||
flex: 1; | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
flex-grow: 1; | ||
padding: 20px; | ||
border-width: 2px; | ||
border-radius: 5px; | ||
border-color: #bbbbbb; | ||
border-style: dashed; | ||
background-color: #eaeaea; | ||
color: #adadad; | ||
outline: none; | ||
transition: border 0.24s ease-in-out; | ||
} | ||
|
||
.dropzone:hover { | ||
border-color: #8bc8ff; | ||
} | ||
|
||
.dropzone:focus { | ||
border-color: #2196f3; | ||
} | ||
|
||
.dropzone.disabled { | ||
opacity: 0.6; | ||
} | ||
|
||
.thumbsContainer { | ||
display: "flex"; | ||
flexdirection: "row"; | ||
flexwrap: "wrap"; | ||
margintop: 16; | ||
backgroundcolor: red; | ||
} | ||
|
||
.thumb { | ||
display: "inline-flex"; | ||
borderradius: 2; | ||
border: "1px solid #eaeaea"; | ||
marginbottom: 8; | ||
marginright: 8; | ||
width: 100; | ||
height: 100; | ||
padding: 4; | ||
boxsizing: "border-box"; | ||
} | ||
|
||
.thumbInner { | ||
display: "flex"; | ||
minwidth: 0; | ||
overflow: "hidden"; | ||
} | ||
|
||
.img { | ||
display: "block"; | ||
width: "auto"; | ||
height: "100%"; | ||
} | ||
|
||
.itemList { | ||
display: flex; | ||
flex-direction: column; | ||
padding: 5px; | ||
} | ||
|
||
/*Janky*/ | ||
.itemList h4 { | ||
margin: 0px; | ||
padding: 0 0 0 24px; | ||
} | ||
|
||
.itemList ul { | ||
margin: 0px; | ||
white-space: nowrap; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
"use client"; | ||
import React, { useCallback, useEffect, useState } from "react"; | ||
import { useDropzone } from "react-dropzone"; | ||
import styles from "./PanoramaDropzone.module.scss"; | ||
|
||
const thumbsContainer = { | ||
display: "flex", | ||
flexDirection: "row", | ||
flexWrap: "wrap", | ||
marginTop: 16, | ||
}; | ||
|
||
const thumb = { | ||
display: "inline-flex", | ||
borderRadius: 2, | ||
border: "1px solid #eaeaea", | ||
marginBottom: 8, | ||
marginRight: 8, | ||
width: 100, | ||
height: 100, | ||
padding: 4, | ||
boxSizing: "border-box", | ||
}; | ||
|
||
const thumbInner = { | ||
display: "flex", | ||
minWidth: 0, | ||
overflow: "hidden", | ||
}; | ||
|
||
const img = { | ||
display: "block", | ||
width: "auto", | ||
height: "100%", | ||
}; | ||
|
||
interface PanoramaDropzoneProps { | ||
onFileDrop: (dropzoneImages: File[]) => void; | ||
} | ||
|
||
const PanoramaDropzone: React.FC<PanoramaDropzoneProps> = ({ onFileDrop }) => { | ||
const [files, setFiles] = useState<File[]>([]); | ||
|
||
const onDrop = useCallback( | ||
(acceptedFiles: File[]) => { | ||
setFiles(acceptedFiles); // Store files locally | ||
onFileDrop(acceptedFiles); // Pass files to main form via callback | ||
}, | ||
[onFileDrop], | ||
); | ||
|
||
const { getRootProps, getInputProps } = useDropzone({ onDrop }); | ||
|
||
const filenames = files.map((file) => ( | ||
<li key={file.path}> | ||
{file.path} - {file.size} bytes | ||
</li> | ||
)); | ||
|
||
const thumbs = files.map((file) => ( | ||
<div style={thumb} key={file.name}> | ||
<div style={thumbInner}> | ||
<img | ||
src={URL.createObjectURL(file)} | ||
style={img} | ||
// Revoke data uri after image is loaded | ||
onLoad={() => { | ||
URL.revokeObjectURL(file.preview); | ||
}} | ||
name={file.path} | ||
/> | ||
</div> | ||
</div> | ||
)); | ||
|
||
useEffect(() => { | ||
// Make sure to revoke the data uris to avoid memory leaks, will run on unmount | ||
return () => files.forEach((file) => URL.revokeObjectURL(file.preview)); | ||
}, [files]); | ||
|
||
return ( | ||
<div className={styles.container}> | ||
<div className={styles.subContainer}> | ||
<div {...getRootProps({ className: styles.dropzone })}> | ||
<input {...getInputProps()} /> | ||
<p> | ||
Drag and drop panoramas here; | ||
<br /> | ||
Or click to open the file dialog | ||
</p> | ||
</div> | ||
<div className={styles.thumbsContainer}>{thumbs}</div> | ||
</div> | ||
{/*XXX (wdn): It would be very cool if I could integrate the file names into the photos.*/} | ||
<div className={styles.itemList}> | ||
<h4>Files</h4> | ||
<ul>{filenames}</ul> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default PanoramaDropzone; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
.formBody { | ||
display: flex; | ||
flex-direction: row; | ||
gap: 10px; | ||
justify-content: center; | ||
} | ||
|
||
.formBody input[type="number"] { | ||
border: 1px solid #ccc; | ||
padding: 10px; | ||
font-size: 16px; | ||
box-sizing: border-box; | ||
margin-bottom: 10px; | ||
border-radius: 4px; | ||
outline-offset: 4px; | ||
} | ||
|
||
.formBody button { | ||
margin-top: 2px; /* Graphic Design Is My Passion */ | ||
} | ||
|
||
.formBody button:hover { | ||
opacity: 0.8; | ||
} | ||
|
||
.formBody button[aria-disabled="true"] { | ||
opacity: 0.5; | ||
cursor: not-allowed; | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Check warning
Code scanning / CodeQL
DOM text reinterpreted as HTML Medium
Copilot Autofix AI 29 days ago
To fix the problem, we need to ensure that any data used in the DOM is properly sanitized or validated. Specifically, we should:
formSubmission.dropzoneImages
before using them withURL.createObjectURL
.possibleDuplicates
array are sanitized before being used in the DOM.We can use a library like
DOMPurify
to sanitize URLs and ensure that they do not contain any malicious content.