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
|
import Html exposing (..)
import Html.Attributes exposing (..)
import Http
import Task
import Date
import Time exposing (..)
import Json.Decode as Decode
main = Html.program
{ init = (
{ lastFetch = 0
, state = Fetching
, feed = []
}, fetch)
, view = view
, update = update
, subscriptions = \_ -> Time.every minute Tick
}
type alias Article =
{ title : String
, feed : String
, ts : Time
, url : String
}
decodeArticle : Decode.Decoder Article
decodeArticle = Decode.map4 Article
(Decode.field "title" Decode.string)
(Decode.field "feed" Decode.string)
(Decode.field "ts" Decode.float)
(Decode.field "url" Decode.string)
type State
= Start
| Current
| Fetching
| FetchError
type alias Model =
{ lastFetch : Time
, state : State
, feed : List Article
}
type Msg
= Tick Time
| Data (Result Http.Error (List Article))
| SetTime Time
fetch : Cmd Msg
fetch = Http.send Data (Http.get "feeds.json" (Decode.list decodeArticle))
update : Msg -> Model -> (Model, Cmd Msg)
update msg model = case msg of
Tick _ -> ({ model | state = Fetching }, fetch)
Data (Err _) -> ({ model | state = FetchError }, Cmd.none)
SetTime t -> ({ model | lastFetch = t }, Cmd.none)
Data (Ok r) ->
( { model | state = Current, feed = r }
, Task.perform SetTime now
)
-- Surely there must be an easier way to do this
fmtts : Time -> String
fmtts t = let d = Date.fromTime t in
toString (Date.day d)
++ " "
++ toString (Date.month d)
++ " "
++ toString (Date.year d)
++ " "
++ String.padLeft 2 '0' (toString (Date.hour d))
++ ":"
++ String.padLeft 2 '0' (toString (Date.minute d))
view : Model -> Html Msg
view model =
let
state = em [ class (toString model.state) ]
[ if model.lastFetch == 0
then text "Loading feeds..."
else text (fmtts model.lastFetch) ]
item n = article []
[ a [href n.url] [ text n.title ]
, i []
[ text (fmtts (n.ts*1000))
, text " - "
, text n.feed
]
]
in div [] (state :: List.map item model.feed)
|