aboutsummaryrefslogtreecommitdiff
path: root/client/src/Util/Ajax.hs
blob: 47f4f3c105308efca803ff68f6d26883dcafc8a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
module Util.Ajax
  ( getNow
  , get
  , post
  , put
  , delete
  ) where

import           Control.Arrow        (left)
import           Data.Aeson           (FromJSON, ToJSON)
import qualified Data.Aeson           as Aeson
import           Data.ByteString      (ByteString)
import qualified Data.ByteString.Lazy as LBS
import           Data.Default         (def)
import qualified Data.Map.Lazy        as LM
import           Data.Text            (Text)
import qualified Data.Text            as T
import qualified Data.Text.Encoding   as T
import           Reflex.Dom           (Dynamic, Event, IsXhrPayload,
                                       MonadWidget, XhrRequest,
                                       XhrRequestConfig (..), XhrResponse,
                                       XhrResponseHeaders (..))
import qualified Reflex.Dom           as R

import           Loadable             (Loadable)
import qualified Loadable

getNow :: forall t m a. (MonadWidget t m, FromJSON a) => Text -> m (Dynamic t (Loadable a))
getNow url = do
  postBuild <- R.getPostBuild
  get (R.tag (R.constant url) postBuild) >>= Loadable.fromEvent

get
  :: forall t m a. (MonadWidget t m, FromJSON a)
  => Event t Text
  -> m (Event t (Either Text a))
get url =
  fmap getJsonResult <$>
    R.performRequestAsync (R.ffor url $ \u -> jsonRequest "GET" u (Aeson.String ""))

post
  :: forall t m a b. (MonadWidget t m, ToJSON a, FromJSON b)
  => Text
  -> Event t a
  -> m (Event t (Either Text b))
post url input =
  fmap getJsonResult <$>
    R.performRequestAsync (jsonRequest "POST" url <$> input)

put
  :: forall t m a b. (MonadWidget t m, ToJSON a, FromJSON b)
  => Text
  -> Event t a
  -> m (Event t (Either Text b))
put url input =
  fmap getJsonResult <$>
    R.performRequestAsync (jsonRequest "PUT" url <$> input)

delete
  :: forall t m a. (MonadWidget t m)
  => Dynamic t Text
  -> Event t ()
  -> m (Event t (Either Text Text))
delete url fire = do
  fmap getResult <$>
    (R.performRequestAsync $
      R.attachWith (\u _ -> request "DELETE" u ()) (R.current url) fire)

getJsonResult :: forall a. (FromJSON a) => XhrResponse -> Either Text a
getJsonResult response =
  case getResult response of
    Left l  -> Left l
    Right r -> left T.pack . Aeson.eitherDecodeStrict $ (T.encodeUtf8 r)

getResult :: XhrResponse -> Either Text Text
getResult response =
  case R._xhrResponse_responseText response of
    Just responseText ->
      if R._xhrResponse_status response == 200
        then Right responseText
        else Left responseText
    _ -> Left "NoKey"

request :: forall a. (IsXhrPayload a) => Text -> Text -> a -> XhrRequest a
request method url payload =
  let
    config = XhrRequestConfig
      { _xhrRequestConfig_headers = def
      , _xhrRequestConfig_user = def
      , _xhrRequestConfig_password = def
      , _xhrRequestConfig_responseType = def
      , _xhrRequestConfig_responseHeaders = def
      , _xhrRequestConfig_withCredentials = False
      , _xhrRequestConfig_sendData = payload
      }
  in
    R.xhrRequest method url config

jsonRequest :: forall a. (ToJSON a) => Text -> Text -> a -> XhrRequest ByteString
jsonRequest method url payload =
  let
    config = XhrRequestConfig
      { _xhrRequestConfig_headers = def
      , _xhrRequestConfig_user = def
      , _xhrRequestConfig_password = def
      , _xhrRequestConfig_responseType = def
      , _xhrRequestConfig_responseHeaders = def
      , _xhrRequestConfig_withCredentials = False
      , _xhrRequestConfig_sendData = LBS.toStrict $ Aeson.encode payload
      }
  in
    R.xhrRequest method url config