espial-0.0.1: src/Handler/Add.hs
{-# OPTIONS_GHC -fno-warn-unused-matches #-}
module Handler.Add where
import Import
import Database.Persist.Sql
import Data.List (nub)
import qualified Data.Time.ISO8601 as TI
getAddR :: Handler Html
getAddR = do
userId <- requireAuthId
murl <- lookupGetParam "url"
mexisting <- runDB $ runMaybeT $ do
bmark <- MaybeT . getBy . UniqueUserHref userId =<< (MaybeT $ pure murl)
btags <- MaybeT $ Just <$> withTags (entityKey bmark)
pure (bmark, btags)
mgetdefs <- aFormToMaybeGetSuccess (mkAddAForm Nothing)
(formWidget, _) <- generateFormPost $ renderTable $
mkAddAForm (maybe mgetdefs (Just . toAddDefs) mexisting)
viewAddWidget
formWidget
(mexisting $> $(widgetFile "add-exists-alert"))
(maybe "url" (const "tags") murl :: Text)
where
toAddDefs :: (Entity Bookmark, [Entity BookmarkTag]) -> AddForm
toAddDefs (Entity bid Bookmark {..}, tags) =
AddForm
{ url = bookmarkHref
, title = Just bookmarkDescription
, description = Just $ Textarea $ bookmarkExtended
, tags = Just $ unwords $ fmap (bookmarkTagTag . entityVal) tags
, private = Just $ not bookmarkShared
, toread = Just $ bookmarkToRead
, bid = Nothing
}
postAddR :: Handler Html
postAddR = do
userId <- requireAuthId
((formResult, formWidget), _) <- runFormPost $ renderTable $ mkAddAForm Nothing
case formResult of
FormSuccess addForm -> do
time <- liftIO getCurrentTime
newBid <- runDB $ upsertDB
(toSqlKey <$> bid addForm)
(toBookmark userId time addForm)
(maybe [] (nub . words) (tags addForm))
lookupGetParam "next" >>= \case
Just next -> redirect next
Nothing -> popupLayout Nothing [whamlet| <div .alert> Add Successful </div> <script> window.close() </script> |]
_ ->
lookupGetParam "inline" >>= \case
Just _ -> fail "invalid form"
Nothing -> viewAddWidget formWidget Nothing "Tags"
where
toBookmark :: UserId -> UTCTime -> AddForm -> Bookmark
toBookmark userId time AddForm {..} =
Bookmark userId url
(fromMaybe "" title)
(maybe "" unTextarea description)
time
(maybe True not private)
(fromMaybe False toread)
False
upsertDB :: Maybe (Key Bookmark) -> Bookmark -> [Text] -> DB (Key Bookmark)
upsertDB mbid bookmark tags = do
let userId = bookmarkUserId bookmark
url = bookmarkHref bookmark
bid' <- case mbid of
Just bid -> do
get bid >>= \case
Just bmark -> do
replace bid bookmark
update bid [BookmarkSelected =. bookmarkSelected bmark, BookmarkTime =. bookmarkTime bmark]
deleteWhere [BookmarkTagBookmarkId ==. bid]
pure bid
Nothing -> fail "not found"
Nothing -> do
getBy (UniqueUserHref userId url) >>= \case
Just (Entity bid _) -> deleteCascade bid
_ -> pure ()
insert bookmark
forM_ (zip [1 ..] tags) $
\(i, tag) -> void $ insert $ BookmarkTag userId tag bid' i
pure bid'
-- add widget
viewAddWidget :: Widget -> Maybe Widget -> Text -> Handler Html
viewAddWidget formWidget mexists focusEl = do
let submitText = (maybe "add bookmark" (const "update bookmark") mexists) :: Text
popupLayout mexists $ do
$(widgetFile "bm")
$(widgetFile "add")
-- AddForm
data AddForm = AddForm
{ url :: Text
, title :: Maybe Text
, description :: Maybe Textarea
, tags :: Maybe Text
, private :: Maybe Bool
, toread :: Maybe Bool
, bid :: Maybe Int64
} deriving (Show, Eq, Read, Generic)
mkAddAForm :: MonadHandlerForm m => Maybe AddForm -> AForm m AddForm
mkAddAForm defs = do
AddForm
<$> areq urlField (textAttrs $ named "url" "URL") (url <$> defs)
<*> aopt textField (textAttrs $ named "title" "title") (title <$> defs)
<*> aopt textareaField (textAreaAttrs $ named "description" "description") (description <$> defs)
<*> aopt textField (textAttrs $ named "tags" "tags") (tags <$> defs)
<*> aopt checkBoxField (named "private" "private") (private <$> defs)
<*> aopt checkBoxField (named "toread" "read later") (toread <$> defs)
<*> aopt hiddenField (named "bid" "") (bid <$> defs)
where
textAttrs = attr ("size", "70")
textAreaAttrs = attrs [("cols", "70"), ("rows", "4")]