feat: expand import form with file upload via base64 JS
This commit is contained in:
+58
-3
@@ -546,6 +546,36 @@ indexPage _mode recipes =
|
|||||||
filterOk = filter (isRight . Idx.riRecipe)
|
filterOk = filter (isRight . Idx.riRecipe)
|
||||||
filterBad = filter (isLeft . Idx.riRecipe)
|
filterBad = filter (isLeft . Idx.riRecipe)
|
||||||
|
|
||||||
|
-- | Inline JavaScript for converting file uploads to base64 before form submission.
|
||||||
|
fileUploadJs :: Text
|
||||||
|
fileUploadJs =
|
||||||
|
T.unlines
|
||||||
|
[ "(function(){"
|
||||||
|
, "'use strict';"
|
||||||
|
, "var form = document.getElementById('import-form');"
|
||||||
|
, "var fileInput = document.getElementById('file-input');"
|
||||||
|
, "var b64Field = document.getElementById('file-b64');"
|
||||||
|
, "var nameField = document.getElementById('file-name');"
|
||||||
|
, "var mimeField = document.getElementById('file-mime');"
|
||||||
|
, ""
|
||||||
|
, "form.addEventListener('submit', function(e) {"
|
||||||
|
, " if (fileInput.files.length > 0) {"
|
||||||
|
, " e.preventDefault();"
|
||||||
|
, " var file = fileInput.files[0];"
|
||||||
|
, " var reader = new FileReader();"
|
||||||
|
, " reader.onload = function() {"
|
||||||
|
, " var b64 = reader.result.split(',')[1];"
|
||||||
|
, " b64Field.value = b64;"
|
||||||
|
, " nameField.value = file.name;"
|
||||||
|
, " mimeField.value = file.type;"
|
||||||
|
, " form.submit();"
|
||||||
|
, " };"
|
||||||
|
, " reader.readAsDataURL(file);"
|
||||||
|
, " }"
|
||||||
|
, "});"
|
||||||
|
, "})();"
|
||||||
|
]
|
||||||
|
|
||||||
-- ---------------------------------------------------------------------------
|
-- ---------------------------------------------------------------------------
|
||||||
-- Import page (form + result)
|
-- Import page (form + result)
|
||||||
-- ---------------------------------------------------------------------------
|
-- ---------------------------------------------------------------------------
|
||||||
@@ -560,16 +590,41 @@ importPage merror =
|
|||||||
case merror of
|
case merror of
|
||||||
Just err -> H.p ! A.style "color: var(--roux-accent);" $ H.toHtml err
|
Just err -> H.p ! A.style "color: var(--roux-accent);" $ H.toHtml err
|
||||||
Nothing -> pure ()
|
Nothing -> pure ()
|
||||||
H.form ! A.method "POST" ! A.action "/import" $ do
|
H.p ! A.style "font-size: 0.85rem; opacity: 0.7; margin-bottom: 1.5rem;" $
|
||||||
|
"Paste a recipe URL, upload a PDF or image, or paste recipe text directly."
|
||||||
|
H.form ! A.method "POST" ! A.action "/import" ! A.id "import-form" $ do
|
||||||
|
-- URL input
|
||||||
H.label ! A.for "url" $ "Recipe URL"
|
H.label ! A.for "url" $ "Recipe URL"
|
||||||
H.input
|
H.input
|
||||||
! A.type_ "url"
|
! A.type_ "url"
|
||||||
! A.id "url"
|
! A.id "url"
|
||||||
! A.name "url"
|
! A.name "url"
|
||||||
! A.placeholder "https://cooking.nytimes.com/recipes/..."
|
! A.placeholder "https://cooking.nytimes.com/recipes/..."
|
||||||
! A.required ""
|
! A.style "width: 100%; margin-bottom: 1.5rem;"
|
||||||
! A.style "width: 100%; margin-bottom: 1rem;"
|
-- File upload
|
||||||
|
H.label ! A.for "file-input" $ "Or upload a PDF or image"
|
||||||
|
H.input
|
||||||
|
! A.type_ "file"
|
||||||
|
! A.id "file-input"
|
||||||
|
! A.accept ".pdf,image/*"
|
||||||
|
! A.style "width: 100%; margin-bottom: 1.5rem;"
|
||||||
|
-- Hidden fields for base64 file data (set by JS)
|
||||||
|
H.input ! A.type_ "hidden" ! A.id "file-b64" ! A.name "file-b64" ! A.value ""
|
||||||
|
H.input ! A.type_ "hidden" ! A.id "file-name" ! A.name "file-name" ! A.value ""
|
||||||
|
H.input ! A.type_ "hidden" ! A.id "file-mime" ! A.name "file-mime" ! A.value ""
|
||||||
|
-- Text area
|
||||||
|
H.label ! A.for "text" $ "Or paste recipe text"
|
||||||
|
H.textarea
|
||||||
|
! A.id "text"
|
||||||
|
! A.name "text"
|
||||||
|
! A.rows "8"
|
||||||
|
! A.placeholder "Paste recipe text here..."
|
||||||
|
! A.style "width: 100%; margin-bottom: 1.5rem; font-family: monospace; font-size: 0.85rem;"
|
||||||
|
$ ""
|
||||||
|
-- Submit
|
||||||
H.button ! A.type_ "submit" $ "Import Recipe"
|
H.button ! A.type_ "submit" $ "Import Recipe"
|
||||||
|
-- Inline JS for base64 file conversion
|
||||||
|
H.script ! A.type_ "text/javascript" $ H.preEscapedText fileUploadJs
|
||||||
|
|
||||||
-- | Render the import result page with an error message.
|
-- | Render the import result page with an error message.
|
||||||
importResultPage :: ImportError -> ByteString
|
importResultPage :: ImportError -> ByteString
|
||||||
|
|||||||
Reference in New Issue
Block a user