packages feed

espial-0.0.26: src/Handler/Add.hs

module Handler.Add where

import Data.List (nub)
import qualified Data.Text as T (replace)
import Handler.Archive
import Import

-- View

getAddViewR :: Handler Html
getAddViewR = do
  Entity userId user <- requireAuth
  frontendBundleName <- appFrontendBundleName <$> getYesod

  murl <- lookupGetParam "url"
  mBookmarkDb <- runDB (fetchBookmarkByUrl userId murl)
  let mformdb = fmap _toBookmarkForm mBookmarkDb
  formurl <- bookmarkFormUrl

  let renderEl = "addForm" :: Text

  popupLayout do
    toWidget
      [whamlet|
      <div id="#{ renderEl }">
    |]
    toWidgetBody
      [julius|
      app.dat.bmark = #{ toJSON (fromMaybe formurl mformdb) }; 
      app.dat.suggestTags = #{ userSuggestTags user };
    |]
    toWidget
      [hamlet|
      <script type="module">
        import { renderAddForm } from '@{StaticR (StaticRoute ["js", frontendBundleName] [])}'
        renderAddForm('##{renderEl}')(app.dat.bmark)();
    |]

bookmarkFormUrl :: Handler BookmarkForm
bookmarkFormUrl = do
  Entity _ user <- requireAuth
  url <- lookupGetParam "url" <&> fromMaybe ""
  title <- lookupGetParam "title"
  description <- lookupGetParam "description" <&> fmap Textarea
  tags <- lookupGetParam "tags"
  private <- lookupGetParam "private" <&> fmap parseChk <&> (<|> Just (userPrivateDefault user))
  toread <- lookupGetParam "toread" <&> fmap parseChk
  pure
    $ BookmarkForm
      { _url = url,
        _title = title,
        _description = description,
        _tags = tags,
        _private = private,
        _toread = toread,
        _bid = Nothing,
        _slug = Nothing,
        _selected = Nothing,
        _time = Nothing,
        _archiveUrl = Nothing
      }
  where
    parseChk s = s == "yes" || s == "on" || s == "true" || s == "1"

-- API

postAddR :: Handler Text
postAddR = do
  bookmarkForm <- requireCheckJsonBody
  _handleFormSuccess bookmarkForm >>= \case
    Created bid -> sendStatusJSON created201 bid
    Updated _ -> sendResponseStatus noContent204 ()
    Failed s -> sendResponseStatus status400 s

_handleFormSuccess :: BookmarkForm -> Handler (UpsertResult (Key Bookmark))
_handleFormSuccess bookmarkForm = do
  (userId, user) <- requireAuthPair
  appSettings <- appSettings <$> getYesod
  case (appAllowNonHttpUrlSchemes appSettings, (parseRequest . unpack . _url) bookmarkForm) of
    (False, Nothing) -> pure $ Failed "Invalid URL"
    (_, _) -> do
      let mkbid = toSqlKey <$> _bid bookmarkForm
          tags = maybe [] (nub . words . T.replace "," " ") (_tags bookmarkForm)
      bm <- liftIO $ _toBookmark userId bookmarkForm
      res <- runDB (upsertBookmark userId mkbid bm tags)
      forM_ (maybeUpsertResult res) $ \kbid ->
        whenM (shouldArchiveBookmark user kbid)
          $ void
          $ async (archiveBookmarkUrl kbid (unpack (bookmarkHref bm)))
      pure res

postLookupTitleR :: Handler ()
postLookupTitleR = do
  void requireAuthId
  bookmarkForm <- (requireCheckJsonBody :: Handler BookmarkForm)
  fetchPageTitle (unpack (_url bookmarkForm)) >>= \case
    Left _ -> sendResponseStatus noContent204 ()
    Right title -> sendResponseStatus ok200 title

postTagSuggestionsR :: Handler Text
postTagSuggestionsR = do
  userId <- requireAuthId
  tagSuggestionRequest <- requireCheckJsonBody
  let suggestion_limit = 10
  tagSuggestions <- runDB $ getTagSuggestions userId tagSuggestionRequest suggestion_limit
  sendStatusJSON ok200 tagSuggestions