start implementing models for Mi API integration
This commit is contained in:
parent
a3d722e2ed
commit
b06a90ccc5
|
@ -1,2 +1,3 @@
|
|||
index.html
|
||||
index.js
|
||||
elm-stuff
|
|
@ -11,14 +11,14 @@
|
|||
"elm/html": "1.0.0",
|
||||
"elm/http": "2.0.0",
|
||||
"elm/json": "1.1.3",
|
||||
"elm/time": "1.0.0",
|
||||
"elm/url": "1.0.0",
|
||||
"rtfeldman/elm-iso8601-date-strings": "1.1.3"
|
||||
},
|
||||
"indirect": {
|
||||
"elm/bytes": "1.0.8",
|
||||
"elm/file": "1.0.5",
|
||||
"elm/parser": "1.1.0",
|
||||
"elm/time": "1.0.0",
|
||||
"elm/url": "1.0.0",
|
||||
"elm/virtual-dom": "1.0.2"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,7 +1,79 @@
|
|||
module Main exposing (main)
|
||||
|
||||
import Html exposing (Html, text)
|
||||
import Browser exposing (sandbox)
|
||||
import Html exposing (Html, button, div, ul, li, span, input, text)
|
||||
import Html.Attributes exposing (autofocus, class, value)
|
||||
import Html.Events exposing (onClick, onInput)
|
||||
import Mi
|
||||
import Mi.Switch
|
||||
|
||||
main : Html msg
|
||||
|
||||
-- We added a new AddTodo message type.
|
||||
|
||||
|
||||
type Msg
|
||||
= UpdateText String
|
||||
| AddTodo
|
||||
| RemoveTodo Int
|
||||
|
||||
|
||||
|
||||
-- We added a new property called todos, which is a list of strings.
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ text : String
|
||||
, todos : List String
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- We added (autofocus True), which is like the native HTML autofocus attribute.
|
||||
-- We also added a button that triggers an onClick event when clicked which
|
||||
-- passes an AddTodo message to the update function.
|
||||
|
||||
|
||||
view : Model -> Html Msg
|
||||
view model =
|
||||
div [ class "text-center" ]
|
||||
[ input [ onInput UpdateText, value model.text, autofocus True ] []
|
||||
, button [ onClick AddTodo, class "btn btn-primary" ] [ text "Add Todo" ]
|
||||
, ul [] (List.indexedMap (\index todo -> li [] [ text todo, span [onClick (RemoveTodo index)] [text " X"] ]) model.todos)
|
||||
]
|
||||
|
||||
|
||||
update : Msg -> Model -> Model
|
||||
update msg model =
|
||||
case msg of
|
||||
UpdateText newText ->
|
||||
{ model | text = newText }
|
||||
|
||||
-- We append the model.text value to the end of our list of todo strings.
|
||||
AddTodo ->
|
||||
{ model | text = "", todos = model.todos ++ [ model.text ] }
|
||||
|
||||
RemoveTodo index ->
|
||||
let
|
||||
beforeTodos =
|
||||
List.take index model.todos
|
||||
|
||||
afterTodos =
|
||||
List.drop (index + 1) model.todos
|
||||
|
||||
newTodos =
|
||||
beforeTodos ++ afterTodos
|
||||
in
|
||||
{ model | todos = newTodos }
|
||||
|
||||
|
||||
|
||||
-- We set the todos property so that it's initially an empty list.
|
||||
|
||||
|
||||
main : Program () Model Msg
|
||||
main =
|
||||
text "Hello, World!"
|
||||
sandbox
|
||||
{ init = { text = "", todos = [] }
|
||||
, view = view
|
||||
, update = update
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
module Mi exposing (TokenData, errorToString, expectJson, request, tokenDecoder)
|
||||
|
||||
import Http exposing (Error(..))
|
||||
import Json.Decode as D
|
||||
|
||||
|
||||
type alias TokenData =
|
||||
{ sub : String
|
||||
, jti : String, aud: String, iss: String
|
||||
}
|
||||
|
||||
|
||||
tokenDecoder : D.Decoder TokenData
|
||||
tokenDecoder =
|
||||
D.map4 TokenData
|
||||
(D.field "sub" D.string)
|
||||
(D.field "jti" D.string)
|
||||
(D.field "aud" D.string)
|
||||
(D.field "iss" D.string)
|
||||
|
||||
|
||||
request method token path body expect =
|
||||
Http.request
|
||||
{ method = method
|
||||
, body = body
|
||||
, headers =
|
||||
[ Http.header "Authorization" token
|
||||
]
|
||||
, url = path
|
||||
, expect = expect
|
||||
, timeout = Nothing
|
||||
, tracker = Nothing
|
||||
}
|
||||
|
||||
|
||||
expectJson : (Result Http.Error a -> msg) -> D.Decoder a -> Http.Expect msg
|
||||
expectJson toMsg decoder =
|
||||
Http.expectStringResponse toMsg <|
|
||||
\response ->
|
||||
case response of
|
||||
Http.BadUrl_ url ->
|
||||
Err (Http.BadUrl url)
|
||||
|
||||
Http.Timeout_ ->
|
||||
Err Http.Timeout
|
||||
|
||||
Http.NetworkError_ ->
|
||||
Err Http.NetworkError
|
||||
|
||||
Http.BadStatus_ metadata body ->
|
||||
Err (Http.BadStatus metadata.statusCode)
|
||||
|
||||
Http.GoodStatus_ metadata body ->
|
||||
case D.decodeString decoder body of
|
||||
Ok value ->
|
||||
Ok value
|
||||
|
||||
Err err ->
|
||||
Err (Http.BadBody (D.errorToString err))
|
||||
|
||||
|
||||
errorToString : Http.Error -> String
|
||||
errorToString err =
|
||||
case err of
|
||||
Timeout ->
|
||||
"Timeout exceeded"
|
||||
|
||||
NetworkError ->
|
||||
"Network error"
|
||||
|
||||
BadStatus st ->
|
||||
"Bad status code: " ++ String.fromInt st
|
||||
|
||||
BadBody text ->
|
||||
"Unexpected response from api: " ++ text
|
||||
|
||||
BadUrl url ->
|
||||
"Malformed url: " ++ url
|
|
@ -0,0 +1,56 @@
|
|||
module Mi.Switch exposing (..)
|
||||
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Iso8601
|
||||
import Json.Decode exposing (Decoder, field, int, map5, nullable, string)
|
||||
import Time exposing (..)
|
||||
import Url.Builder as UB
|
||||
|
||||
type alias Switch =
|
||||
{ id : String
|
||||
, who : String
|
||||
, started_at : Posix
|
||||
, ended_at : Maybe Posix
|
||||
, duration : Maybe Int
|
||||
}
|
||||
|
||||
|
||||
decoder : Decoder Switch
|
||||
decoder =
|
||||
map5 Switch
|
||||
(field "id" string)
|
||||
(field "who" string)
|
||||
(field "started_at" Iso8601.decoder)
|
||||
(field "ended_at" (nullable Iso8601.decoder))
|
||||
(field "duration" (nullable int))
|
||||
|
||||
|
||||
switchURL : String
|
||||
switchURL =
|
||||
UB.absolute
|
||||
[ "api", "switches", "switch" ]
|
||||
[]
|
||||
|
||||
|
||||
idURL : String -> String
|
||||
idURL id =
|
||||
UB.absolute
|
||||
[ "api","switches", "id", id ]
|
||||
[]
|
||||
|
||||
|
||||
frontURL : String
|
||||
frontURL =
|
||||
UB.absolute
|
||||
["api", "switches", "current" ]
|
||||
[]
|
||||
|
||||
|
||||
listURL : Int -> Int -> String
|
||||
listURL limit page =
|
||||
UB.absolute
|
||||
["api", "switches", "" ]
|
||||
[ UB.int "limit" limit
|
||||
, UB.int "page" page
|
||||
]
|
|
@ -1,4 +1,16 @@
|
|||
{
|
||||
"gruvbox-css": {
|
||||
"branch": "master",
|
||||
"description": "My minimal Gruvbox CSS file I've been keeping multiple places",
|
||||
"homepage": null,
|
||||
"owner": "Xe",
|
||||
"repo": "gruvbox-css",
|
||||
"rev": "6e1841c94190a1e06e63a2596767e66c35671320",
|
||||
"sha256": "0s7whnin63558i70wp3by3rydsdx0qdzh5553km1s29w81npmgj6",
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/Xe/gruvbox-css/archive/6e1841c94190a1e06e63a2596767e66c35671320.tar.gz",
|
||||
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
|
||||
},
|
||||
"naersk": {
|
||||
"branch": "master",
|
||||
"description": "Build rust crates in Nix. No configuration, no code generation, no IFD. Sandbox friendly.",
|
||||
|
|
Loading…
Reference in New Issue