1
1
-----------------------------------------------------------------------------
2
2
{-# LANGUAGE CPP #-}
3
+ {-# LANGUAGE DataKinds #-}
3
4
{-# LANGUAGE DeriveGeneric #-}
4
- {-# LANGUAGE OverloadedStrings #-}
5
5
{-# LANGUAGE RecordWildCards #-}
6
+ {-# LANGUAGE TypeApplications #-}
7
+ {-# LANGUAGE OverloadedStrings #-}
6
8
-----------------------------------------------------------------------------
7
9
-- |
8
10
-- Module : Main
14
16
----------------------------------------------------------------------------
15
17
module Main where
16
18
----------------------------------------------------------------------------
17
- import Control.Monad.Writer
18
19
import Data.Aeson
19
20
import qualified Data.Map as M
20
21
import Data.Maybe
21
22
import GHC.Generics
23
+ import Language.Javascript.JSaddle (JSM )
24
+ import Data.Proxy
25
+ import Servant.API
22
26
----------------------------------------------------------------------------
23
27
import Miso hiding (defaultOptions )
24
28
import Miso.String
@@ -39,19 +43,21 @@ main = run $ startApp app
39
43
----------------------------------------------------------------------------
40
44
-- | Model
41
45
newtype Model = Model
42
- { _info :: Maybe APIInfo
46
+ { _info :: Maybe GitHub
43
47
} deriving (Eq , Show )
44
48
----------------------------------------------------------------------------
45
49
-- | Lens for info field
46
- info :: Lens Model (Maybe APIInfo )
50
+ info :: Lens Model (Maybe GitHub )
47
51
info = lens _info $ \ r x -> r { _info = x }
48
52
----------------------------------------------------------------------------
49
53
-- | Action
50
54
data Action
51
- = FetchGitHub
52
- | SetGitHub APIInfo
53
- deriving (Show , Eq )
55
+ = FetchGitHub
56
+ | SetGitHub GitHub
57
+ | ErrorHandler MisoString
58
+ deriving (Show , Eq )
54
59
----------------------------------------------------------------------------
60
+ -- | WASM support
55
61
#ifdef WASM
56
62
foreign export javascript " hs_start" main :: IO ()
57
63
#endif
@@ -62,15 +68,24 @@ app = defaultApp emptyModel updateModel viewModel
62
68
emptyModel :: Model
63
69
emptyModel = Model Nothing
64
70
----------------------------------------------------------------------------
71
+ -- | GitHub API method
72
+ type GithubAPI = Get '[JSON ] GitHub
73
+ ----------------------------------------------------------------------------
74
+ -- | Uses servant to reify type-safe calls to the Fetch API
75
+ getGithubAPI
76
+ :: (GitHub -> JSM () )
77
+ -- ^ Successful callback
78
+ -> (MisoString -> JSM () )
79
+ -- ^ Errorful callback
80
+ -> JSM ()
81
+ getGithubAPI = fetch (Proxy @ GithubAPI ) " https://api.github.com"
82
+ ----------------------------------------------------------------------------
65
83
updateModel :: Action -> Effect Model Action ()
66
- updateModel FetchGitHub
67
- = tell
68
- [ \ snk ->
69
- fetchJSON " https://api.github.com"
70
- (snk . SetGitHub )
71
- ]
84
+ updateModel FetchGitHub = withSink $ \ snk -> getGithubAPI (snk . SetGitHub ) (snk . ErrorHandler )
72
85
updateModel (SetGitHub apiInfo) =
73
86
info ?= apiInfo
87
+ updateModel (ErrorHandler msg) =
88
+ io (consoleError msg)
74
89
----------------------------------------------------------------------------
75
90
-- | View function, with routing
76
91
viewModel :: Model -> View Action
@@ -86,19 +101,19 @@ viewModel m = view
86
101
[ h1_
87
102
[ class_ $ pack " title"
88
103
]
89
- [ text $ pack " Miso Fetch Example "
104
+ [ " 🍜 Miso Fetch API "
90
105
]
91
106
, button_
92
107
attrs
93
- [ text $ pack " Fetch JSON from https://api.github.com via Fetch API "
108
+ [ " Fetch JSON from https://api.github.com"
94
109
]
95
110
, case m ^. info of
96
111
Nothing ->
97
112
div_
98
113
[]
99
114
[ " No data"
100
115
]
101
- Just APIInfo {.. } ->
116
+ Just GitHub {.. } ->
102
117
table_
103
118
[ class_ " table is-striped" ]
104
119
[ thead_
@@ -113,14 +128,14 @@ viewModel m = view
113
128
]
114
129
, tbody_
115
130
[]
116
- [ tr current_user_url
117
- , tr emojis_url
118
- , tr emails_url
119
- , tr events_url
120
- , tr gists_url
121
- , tr feeds_url
122
- , tr followers_url
123
- , tr following_url
131
+ [ tr currentUserUrl
132
+ , tr emojisUrl
133
+ , tr emailsUrl
134
+ , tr eventsUrl
135
+ , tr gistsUrl
136
+ , tr feedsUrl
137
+ , tr followersUrl
138
+ , tr followingUrl
124
139
]
125
140
]
126
141
]
@@ -138,40 +153,40 @@ viewModel m = view
138
153
]
139
154
----------------------------------------------------------------------------
140
155
-- | Structure to capture the JSON returned from https://api.github.com
141
- data APIInfo
142
- = APIInfo
143
- { current_user_url :: MisoString
144
- , current_user_authorizations_html_url :: MisoString
145
- , authorizations_url :: MisoString
146
- , code_search_url :: MisoString
147
- , commit_search_url :: MisoString
148
- , emails_url :: MisoString
149
- , emojis_url :: MisoString
150
- , events_url :: MisoString
151
- , feeds_url :: MisoString
152
- , followers_url :: MisoString
153
- , following_url :: MisoString
154
- , gists_url :: MisoString
155
- , hub_url :: MisoString
156
- , issue_search_url :: MisoString
157
- , issues_url :: MisoString
158
- , keys_url :: MisoString
159
- , notifications_url :: MisoString
160
- , organization_repositories_url :: MisoString
161
- , organization_url :: MisoString
162
- , public_gists_url :: MisoString
163
- , rate_limit_url :: MisoString
164
- , repository_url :: MisoString
165
- , repository_search_url :: MisoString
166
- , current_user_repositories_url :: MisoString
167
- , starred_url :: MisoString
168
- , starred_gists_url :: MisoString
169
- , user_url :: MisoString
170
- , user_organizations_url :: MisoString
171
- , user_repositories_url :: MisoString
172
- , user_search_url :: MisoString
156
+ data GitHub
157
+ = GitHub
158
+ { currentUserUrl :: MisoString
159
+ , currentUserAuthorizationsHtmlUrl :: MisoString
160
+ , authorizationsUrl :: MisoString
161
+ , codeSearchUrl :: MisoString
162
+ , commitSearchUrl :: MisoString
163
+ , emailsUrl :: MisoString
164
+ , emojisUrl :: MisoString
165
+ , eventsUrl :: MisoString
166
+ , feedsUrl :: MisoString
167
+ , followersUrl :: MisoString
168
+ , followingUrl :: MisoString
169
+ , gistsUrl :: MisoString
170
+ , hubUrl :: MisoString
171
+ , issueSearchUrl :: MisoString
172
+ , issuesUrl :: MisoString
173
+ , keysUrl :: MisoString
174
+ , notificationsUrl :: MisoString
175
+ , organizationRepositoriesUrl :: MisoString
176
+ , organizationUrl :: MisoString
177
+ , publicGistsUrl :: MisoString
178
+ , rateLimitUrl :: MisoString
179
+ , repositoryUrl :: MisoString
180
+ , repositorySearchUrl :: MisoString
181
+ , currentUserRepositoriesUrl :: MisoString
182
+ , starredUrl :: MisoString
183
+ , starredGistsUrl :: MisoString
184
+ , userUrl :: MisoString
185
+ , userOrganizationsUrl :: MisoString
186
+ , userRepositoriesUrl :: MisoString
187
+ , userSearchUrl :: MisoString
173
188
} deriving (Show , Eq , Generic )
174
189
----------------------------------------------------------------------------
175
- instance FromJSON APIInfo where
176
- parseJSON = genericParseJSON defaultOptions{ fieldLabelModifier = camelTo2 ' _' }
190
+ instance FromJSON GitHub where
191
+ parseJSON = genericParseJSON defaultOptions { fieldLabelModifier = camelTo2 ' _' }
177
192
----------------------------------------------------------------------------
0 commit comments