on master help sign in
airlock/example/src/Sink.elm
199 lines 5.9 kB history raw
1port module Sink exposing (main)
3import BigInt exposing (BigInt)
4import Browser exposing (Document)
5import Element exposing (..)
6import Element.Border as Border
7import Heroicons.Outline
8import Json.Decode as JD
9import Task
10import Time
11import Ur
12import Ur.Cmd
13import Ur.Constructor as C
14import Ur.Deconstructor as D
15import Ur.Run
16import Ur.Sub
17import Widget
18import Widget.Icon as Icon
19import Widget.Material as Material
22url : String
23url =
24 "http://localhost:8080"
27main : Ur.Run.Program Model Msg
28main =
29 Ur.Run.application
30 { init =
31 \_ _ ->
32 ( { error = ""
33 , entries = Nothing
34 , newEntry = ""
35 , shipName = Nothing
36 }
37 , Cmd.batch
38 [ Ur.logIn url "lidlut-tabwed-pillex-ridrup"
39 |> Cmd.map (result (Debug.toString >> Error) (always Noop))
40 , Ur.getShipName url |> Cmd.map (result (always Noop) GotShipName)
41 ]
42 |> Ur.Cmd.cmd
43 )
44 , update = update
45 , view = view
46 , subscriptions = always Sub.none
47 , createEventSource = createEventSource
48 , urbitSubscriptions =
49 \{ shipName } ->
50 case shipName of
51 Just ship ->
52 Ur.Sub.batch
53 [ Ur.Sub.sink
54 { ship = ship
55 , app = "journal"
56 , path = [ "sync" ]
57 , deconstructor =
58 D.list (D.cell D.bigint D.cord)
59 |> D.map GotListings
60 }
61 ]
63 _ ->
64 Ur.Sub.none
65 , onEventSourceMsg = onEventSourceMessage
66 , onUrlChange = \_ -> Noop
67 , onUrlRequest = \_ -> Noop
68 , urbitUrl = \_ -> url
69 }
72type alias Model =
73 { error : String
74 , entries : Maybe (List ( BigInt, String ))
75 , newEntry : String
76 , shipName : Maybe String
77 }
80type Msg
81 = Noop
82 | Error String
83 | GotListings (List ( BigInt, String ))
84 | UpdateNewEntry String
85 | DeleteEntry BigInt
86 | AddEntry String
87 | RunCmd (Ur.Cmd.Cmd Msg)
88 | GotShipName String
91update : Msg -> Model -> ( Model, Ur.Cmd.Cmd Msg )
92update msg model =
93 case msg of
94 Noop ->
95 ( model, Ur.Cmd.none )
97 Error err ->
98 ( { model | error = err }, Ur.Cmd.none )
100 GotListings entries ->
101 ( { model | entries = Just entries }, Ur.Cmd.none )
103 UpdateNewEntry txt ->
104 ( { model | newEntry = txt }, Ur.Cmd.none )
106 DeleteEntry id ->
107 ( model
108 , Ur.Cmd.poke
109 { ship = "~zod"
110 , agent = "journal"
111 , mark = "journal-action"
112 , noun = C.cell (C.cord "del") (C.bigint id)
113 }
114 )
116 AddEntry txt ->
117 ( { model | newEntry = "" }
118 , Time.now
119 |> Task.perform
120 (\time ->
121 Ur.Cmd.poke
122 { ship = "~zod"
123 , agent = "journal"
124 , mark = "journal-action"
125 , noun = C.cell (C.cord "add") (C.cell (time |> Time.posixToMillis |> BigInt.fromInt |> C.bigint) (C.cord txt))
126 }
127 |> RunCmd
128 )
129 |> Ur.Cmd.cmd
130 )
132 RunCmd cmd ->
133 ( model, cmd )
135 GotShipName name ->
136 ( { model | shipName = Just name }, Ur.Cmd.none )
139view : Model -> Document Msg
140view model =
141 { body =
142 [ layout []
143 ([ el [ alignTop ] (text model.error)
144 , row [ spacing 8 ]
145 [ Widget.textInput (Material.textInput Material.defaultPalette)
146 { chips = []
147 , text = model.newEntry
148 , placeholder = Nothing
149 , label = "New entry"
150 , onChange = UpdateNewEntry
151 }
152 , Widget.iconButton (Material.containedButton Material.defaultPalette)
153 { text = "submit"
154 , icon = Icon.elmHeroicons Heroicons.Outline.check
155 , onPress = AddEntry model.newEntry |> Just
156 }
157 ]
158 , model.entries
159 |> Maybe.withDefault []
160 |> List.map
161 (\( id, txt ) ->
162 row
163 [ Border.rounded 10
164 , Border.shadow { offset = ( 0, 5 ), size = 1, blur = 10, color = rgba 0 0 0 0.3 }
165 , centerX
166 , padding 10
167 , spacing 12
168 ]
169 [ paragraph [] [ text txt ]
170 , Widget.iconButton (Material.containedButton Material.defaultPalette)
171 { text = "delete"
172 , icon = Icon.elmHeroicons Heroicons.Outline.trash
173 , onPress = DeleteEntry id |> Just
174 }
175 ]
176 )
177 |> column [ spacing 10, centerX ]
178 ]
179 |> column [ spacing 18, centerX ]
180 )
181 ]
182 , title = "Airlock"
183 }
186result : (a -> c) -> (b -> c) -> Result a b -> c
187result f g res =
188 case res of
189 Ok b ->
190 g b
192 Err a ->
193 f a
196port createEventSource : String -> Cmd msg
199port onEventSourceMessage : (JD.Value -> msg) -> Sub msg