{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
module Hledger.Web.Handler.UploadR
( getUploadR
, postUploadR
) where
import Control.Monad.Except (runExceptT)
import qualified Data.ByteString.Lazy as BL
import Data.Conduit (connect)
import Data.Conduit.Binary (sinkLbs)
import qualified Data.Text.Encoding as TE
import Hledger.Web.Import
import Hledger.Web.Widget.Common (fromFormSuccess, journalFile404, writeJournalTextIfValidAndChanged)
uploadForm :: FilePath -> Markup -> MForm Handler (FormResult FileInfo, Widget)
uploadForm :: FilePath -> Markup -> MForm Handler (FormResult FileInfo, Widget)
uploadForm FilePath
f =
Text
-> (Markup
-> RWST
(Maybe (Env, FileEnv), HandlerSite Handler, [Text])
Enctype
Ints
Handler
(FormResult FileInfo, WidgetFor (HandlerSite Handler) ()))
-> Markup
-> RWST
(Maybe (Env, FileEnv), HandlerSite Handler, [Text])
Enctype
Ints
Handler
(FormResult FileInfo, WidgetFor (HandlerSite Handler) ())
forall (m :: * -> *) a.
Monad m =>
Text
-> (Markup -> MForm m (FormResult a, WidgetFor (HandlerSite m) ()))
-> Markup
-> MForm m (FormResult a, WidgetFor (HandlerSite m) ())
identifyForm Text
"upload" ((Markup
-> RWST
(Maybe (Env, FileEnv), HandlerSite Handler, [Text])
Enctype
Ints
Handler
(FormResult FileInfo, WidgetFor (HandlerSite Handler) ()))
-> Markup
-> RWST
(Maybe (Env, FileEnv), HandlerSite Handler, [Text])
Enctype
Ints
Handler
(FormResult FileInfo, WidgetFor (HandlerSite Handler) ()))
-> (Markup
-> RWST
(Maybe (Env, FileEnv), HandlerSite Handler, [Text])
Enctype
Ints
Handler
(FormResult FileInfo, WidgetFor (HandlerSite Handler) ()))
-> Markup
-> RWST
(Maybe (Env, FileEnv), HandlerSite Handler, [Text])
Enctype
Ints
Handler
(FormResult FileInfo, WidgetFor (HandlerSite Handler) ())
forall a b. (a -> b) -> a -> b
$ \Markup
extra -> do
(res, _) <- Field Handler FileInfo
-> FieldSettings (HandlerSite Handler)
-> Maybe FileInfo
-> MForm
Handler (FormResult FileInfo, FieldView (HandlerSite Handler))
forall site (m :: * -> *) a.
(RenderMessage site FormMessage, HandlerSite m ~ site,
MonadHandler m) =>
Field m a
-> FieldSettings site
-> Maybe a
-> MForm m (FormResult a, FieldView site)
mreq Field Handler FileInfo
forall (m :: * -> *). Monad m => Field m FileInfo
fileField FieldSettings (HandlerSite Handler)
forall {master}. FieldSettings master
fs Maybe FileInfo
forall a. Maybe a
Nothing
pure (res, $(widgetFile "upload-form"))
where
fs :: FieldSettings master
fs = SomeMessage master
-> Maybe (SomeMessage master)
-> Maybe Text
-> Maybe Text
-> [(Text, Text)]
-> FieldSettings master
forall master.
SomeMessage master
-> Maybe (SomeMessage master)
-> Maybe Text
-> Maybe Text
-> [(Text, Text)]
-> FieldSettings master
FieldSettings SomeMessage master
"file" Maybe (SomeMessage master)
forall a. Maybe a
Nothing (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"file") (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"file") []
getUploadR :: FilePath -> Handler ()
getUploadR :: FilePath -> Handler ()
getUploadR FilePath
f = do
Handler ()
checkServerSideUiEnabled
FilePath -> Handler ()
postUploadR FilePath
f
postUploadR :: FilePath -> Handler ()
postUploadR :: FilePath -> Handler ()
postUploadR FilePath
f = do
Handler ()
checkServerSideUiEnabled
VD {j} <- Handler ViewData
getViewData
require EditPermission
(f', _) <- journalFile404 f j
((res, view), enctype) <- runFormPost (uploadForm f')
fi <- fromFormSuccess (showForm view enctype) res
lbs <- BL.toStrict <$> connect (fileSource fi) sinkLbs
newtxt <- case TE.decodeUtf8' lbs of
Left UnicodeException
e -> do
Markup -> Handler ()
forall (m :: * -> *). MonadHandler m => Markup -> m ()
setMessage (Markup -> Handler ()) -> Markup -> Handler ()
forall a b. (a -> b) -> a -> b
$
Markup
"Encoding error: '" Markup -> Markup -> Markup
forall a. Semigroup a => a -> a -> a
<> FilePath -> Markup
forall a. ToMarkup a => a -> Markup
toHtml (UnicodeException -> FilePath
forall a. Show a => a -> FilePath
show UnicodeException
e) Markup -> Markup -> Markup
forall a. Semigroup a => a -> a -> a
<> Markup
"'. " Markup -> Markup -> Markup
forall a. Semigroup a => a -> a -> a
<>
Markup
"If your file is not UTF-8 encoded, try the 'edit form', " Markup -> Markup -> Markup
forall a. Semigroup a => a -> a -> a
<>
Markup
"where the transcoding should be handled by the browser."
Widget -> Enctype -> HandlerFor App Text
forall {site} {a} {a} {c}.
(Yesod site, ToMarkup a, ToWidget site a) =>
a -> a -> HandlerFor site c
showForm Widget
view Enctype
enctype
Right Text
newtxt -> Text -> HandlerFor App Text
forall a. a -> HandlerFor App a
forall (m :: * -> *) a. Monad m => a -> m a
return Text
newtxt
runExceptT (writeJournalTextIfValidAndChanged f newtxt) >>= \case
Left FilePath
e -> do
Markup -> Handler ()
forall (m :: * -> *). MonadHandler m => Markup -> m ()
setMessage (Markup -> Handler ()) -> Markup -> Handler ()
forall a b. (a -> b) -> a -> b
$ Markup
"Failed to load journal: " Markup -> Markup -> Markup
forall a. Semigroup a => a -> a -> a
<> FilePath -> Markup
forall a. ToMarkup a => a -> Markup
toHtml FilePath
e
Widget -> Enctype -> Handler ()
forall {site} {a} {a} {c}.
(Yesod site, ToMarkup a, ToWidget site a) =>
a -> a -> HandlerFor site c
showForm Widget
view Enctype
enctype
Right () -> do
Markup -> Handler ()
forall (m :: * -> *). MonadHandler m => Markup -> m ()
setMessage (Markup -> Handler ()) -> Markup -> Handler ()
forall a b. (a -> b) -> a -> b
$ Markup
"File " Markup -> Markup -> Markup
forall a. Semigroup a => a -> a -> a
<> FilePath -> Markup
forall a. ToMarkup a => a -> Markup
toHtml FilePath
f Markup -> Markup -> Markup
forall a. Semigroup a => a -> a -> a
<> Markup
" uploaded successfully"
Route App -> Handler ()
forall (m :: * -> *) url a.
(MonadHandler m, RedirectUrl (HandlerSite m) url) =>
url -> m a
redirect Route App
JournalR
where
showForm :: a -> a -> HandlerFor site c
showForm a
view a
enctype =
Markup -> HandlerFor site c
forall (m :: * -> *) c a.
(MonadHandler m, ToTypedContent c) =>
c -> m a
sendResponse (Markup -> HandlerFor site c)
-> (WidgetFor site () -> HandlerFor site Markup)
-> WidgetFor site ()
-> HandlerFor site c
forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< WidgetFor site () -> HandlerFor site Markup
forall site.
Yesod site =>
WidgetFor site () -> HandlerFor site Markup
defaultLayout (WidgetFor site () -> HandlerFor site c)
-> WidgetFor site () -> HandlerFor site c
forall a b. (a -> b) -> a -> b
$ do
Markup -> WidgetFor site ()
forall (m :: * -> *). MonadWidget m => Markup -> m ()
setTitle Markup
"Upload journal"
[whamlet|<form method=post enctype=#{enctype}>^{view}|]