Преглед на файлове

support creating new posts

Lucas Stadler преди 11 години
родител
ревизия
1b689fe4a8
променени са 3 файла, в които са добавени 68 реда и са изтрити 5 реда
  1. 38 1
      elm/Post.elm
  2. 28 3
      elm/Stream.elm
  3. 2 1
      elm/elm-package.json

+ 38 - 1
elm/Post.elm

4
import Date (Date)
4
import Date (Date)
5
import List
5
import List
6
import Html (..)
6
import Html (..)
7
import Html.Attributes as Attr
8
import Html.Events (on, targetValue, onClick)
7
import Util.Compare (compareBy, flipCompare)
9
import Util.Compare (compareBy, flipCompare)
8
import Util.Html (viewDate)
10
import Util.Html (viewDate)
9
import String
11
import String
12
import Signal
13
import LocalChannel as LC
14
import LocalChannel (LocalChannel)
10
15
11
type alias Post = { title:String, content:String, created:Date }
16
type alias Post = { title:String, content:String, created:Date }
12
17
18
empty : Post
19
empty = {title = "", content = "", created = Date.fromTime 0}
20
13
compareByDate = compareBy (.created >> Date.toTime)
21
compareByDate = compareBy (.created >> Date.toTime)
14
compareByDateReverse = flipCompare <| compareBy (.created >> Date.toTime)
22
compareByDateReverse = flipCompare <| compareBy (.created >> Date.toTime)
15
23
20
            h3 [] [text post.title],
28
            h3 [] [text post.title],
21
            section [] (List.map (\par -> p [] [text par]) paragraphs),
29
            section [] (List.map (\par -> p [] [text par]) paragraphs),
22
            span [] [text "Written ", viewDate ref post.created]
30
            span [] [text "Written ", viewDate ref post.created]
23
           ]
31
           ]
32
33
-- an editing interface ...
34
35
type alias Model = Post
36
37
type Action = NoOp
38
            | UpdateTitle String
39
            | UpdateContent String
40
41
update : Action -> Model -> Model
42
update action model =
43
    case action of
44
      NoOp -> model
45
46
      UpdateTitle title -> { model | title <- title }
47
48
      UpdateContent content -> { model | content <- content }
49
50
type alias Context = { actions : LocalChannel Action
51
                     , publish : LocalChannel () }
52
53
editingView : Context -> Model -> Html
54
editingView context model = div [] [
55
                             input [Attr.type' "text", Attr.placeholder "title",
56
                                    on "input" targetValue (LC.send context.actions << UpdateTitle)] [text model.title],
57
                             textarea [Attr.placeholder "write something!",
58
                                       on "input" targetValue (LC.send context.actions << UpdateContent)] [text model.content],
59
                             button [onClick (LC.send context.publish ())] [text "publish"]
60
                            ]

+ 28 - 3
elm/Stream.elm

9
import String
9
import String
10
import Time
10
import Time
11
import Signal
11
import Signal
12
import LocalChannel
12
13
13
import Post
14
import Post
14
import Post (Post)
15
import Post (Post)
15
16
16
type alias Model =
17
type alias Model =
17
    { posts         : List Post
18
    { isEditing     : Bool
19
    , newPost       : Post.Model
20
    , posts         : List Post
18
    , referenceDate : Date
21
    , referenceDate : Date
19
    }
22
    }
20
23
21
type Action = NoOp
24
type Action = NoOp
25
            | CreatePost
26
            | AddPost ()
27
            | CancelPost
28
            | EditPost Post.Action
22
            | UpdateDate Date
29
            | UpdateDate Date
23
30
24
date s = case (Date.fromString s) of
31
date s = case (Date.fromString s) of
36
43
37
-- view
44
-- view
38
45
39
view model = div [] (List.map (Post.view model.referenceDate) (List.sortWith Post.compareByDateReverse model.posts))
46
view model = div [] [
47
              if model.isEditing
48
              then Post.editingView (Post.Context
49
                                             (LocalChannel.create EditPost updates)
50
                                             (LocalChannel.create AddPost updates)) Post.empty
51
              else button [onClick (Signal.send updates CreatePost)] [text "create new post"],
52
              div [] (List.map (Post.view model.referenceDate) (List.sortWith Post.compareByDateReverse model.posts))
53
             ]
40
54
41
-- wiring it all up
55
-- wiring it all up
42
56
43
initialModel = { posts = posts, referenceDate = date "0" }
57
initialModel = { isEditing = False, newPost = Post.empty, posts = posts, referenceDate = date "0" }
44
58
45
update : Action -> Model -> Model
59
update : Action -> Model -> Model
46
update action model =
60
update action model =
47
    case action of
61
    case action of
48
      NoOp -> model
62
      NoOp -> model
49
63
64
      CreatePost -> { model | isEditing <- True }
65
66
      AddPost _ -> { model |
67
                      isEditing <- False,
68
                      posts <- let p = model.newPost
69
                               in { p | created <- model.referenceDate } :: posts }
70
71
      CancelPost -> { model | isEditing <- False, newPost <- Post.empty }
72
50
      UpdateDate d -> { model | referenceDate <- d }
73
      UpdateDate d -> { model | referenceDate <- d }
51
74
75
      EditPost action' -> { model | newPost <- Post.update action' model.newPost }
76
52
model : Signal Model
77
model : Signal Model
53
model = Signal.foldp update initialModel <| Signal.merge (Signal.subscribe updates) (Signal.map UpdateDate currentDate)
78
model = Signal.foldp update initialModel <| Signal.merge (Signal.subscribe updates) (Signal.map UpdateDate currentDate)
54
79

+ 2 - 1
elm/elm-package.json

10
    "dependencies": {
10
    "dependencies": {
11
        "elm-lang/core": "1.1.1 <= v < 2.0.0",
11
        "elm-lang/core": "1.1.1 <= v < 2.0.0",
12
        "evancz/elm-html": "2.0.0 <= v < 3.0.0",
12
        "evancz/elm-html": "2.0.0 <= v < 3.0.0",
13
        "evancz/local-channel": "1.0.0 <= v < 2.0.0",
13
        "heyLu/elm-format-date": "1.0.0 <= v < 2.0.0"
14
        "heyLu/elm-format-date": "1.0.0 <= v < 2.0.0"
14
    }
15
    }
15
}
16
}