From 7e7ac424a6bc5ee3d6ebf25fe50857625939ee42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hern=C3=A1ndez?= Date: Wed, 28 Sep 2016 17:35:25 +0200 Subject: [PATCH 01/10] Upgrades the elm packages to the right versions or the appropiate new library --- elm-package.json | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/elm-package.json b/elm-package.json index 7019013..c9891af 100644 --- a/elm-package.json +++ b/elm-package.json @@ -12,15 +12,12 @@ "exposed-modules": [], "native-modules": true, "dependencies": { - "deadfoxygrandpa/elm-test": "3.0.1 <= v < 4.0.0", - "elm-lang/core": "3.0.0 <= v < 4.0.0", - "evancz/elm-effects": "2.0.1 <= v < 3.0.0", - "evancz/elm-html": "4.0.2 <= v < 5.0.0", - "evancz/elm-http": "3.0.0 <= v < 4.0.0", - "evancz/start-app": "2.0.2 <= v < 3.0.0", - "evancz/task-tutorial": "1.0.3 <= v < 2.0.0", - "rgrempel/elm-route-hash": "1.0.5 <= v < 2.0.0", + "elm-community/elm-test": "2.1.0 <= v < 3.0.0", + "elm-lang/core": "4.0.5 <= v < 5.0.0", + "elm-lang/html": "1.1.0 <= v < 2.0.0", + "evancz/elm-http": "3.0.1 <= v < 4.0.0", + "rgrempel/elm-route-url": "2.0.1 <= v < 3.0.0", "truqu/elm-base64": "1.0.3 <= v < 2.0.0" }, - "elm-version": "0.16.0 <= v < 0.17.0" + "elm-version": "0.17.0 <= v < 0.18.0" } From 3f0723ee574ba6b64efdc9f13e0fa52382d41dec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hern=C3=A1ndez?= Date: Wed, 28 Sep 2016 17:36:04 +0200 Subject: [PATCH 02/10] Updates the module declaration replacing the where with the exposing(..). Replaces all the 0.16 Actions with the 0.17 Msg --- src/elm/App/Model.elm | 2 +- src/elm/App/Router.elm | 6 ++--- src/elm/App/Update.elm | 38 +++++++++++++-------------- src/elm/App/View.elm | 12 ++++----- src/elm/Article/Decoder.elm | 2 +- src/elm/Article/Model.elm | 2 +- src/elm/ArticleForm/Model.elm | 2 +- src/elm/ArticleForm/Update.elm | 10 +++---- src/elm/ArticleForm/View.elm | 8 +++--- src/elm/ArticleList/Model.elm | 2 +- src/elm/ArticleList/Update.elm | 17 ++++++------ src/elm/ArticleList/View.elm | 6 ++--- src/elm/Company/Model.elm | 2 +- src/elm/Config.elm | 2 +- src/elm/Config/Model.elm | 2 +- src/elm/Config/Test.elm | 8 +++--- src/elm/Config/Update.elm | 17 ++++++------ src/elm/Config/View.elm | 2 +- src/elm/Event/Decoder.elm | 2 +- src/elm/Event/Model.elm | 2 +- src/elm/EventAuthorFilter/Model.elm | 2 +- src/elm/EventAuthorFilter/Update.elm | 6 ++--- src/elm/EventAuthorFilter/View.elm | 8 +++--- src/elm/EventCompanyFilter/Model.elm | 2 +- src/elm/EventCompanyFilter/Test.elm | 4 +-- src/elm/EventCompanyFilter/Update.elm | 6 ++--- src/elm/EventCompanyFilter/View.elm | 8 +++--- src/elm/EventList/Model.elm | 2 +- src/elm/EventList/Update.elm | 6 ++--- src/elm/EventList/Utils.elm | 2 +- src/elm/EventList/View.elm | 10 +++---- src/elm/Leaflet/Model.elm | 2 +- src/elm/Leaflet/Update.elm | 6 ++--- src/elm/Leaflet/View.elm | 6 ++--- src/elm/Main.elm | 10 +++---- src/elm/Pages/Article/Model.elm | 2 +- src/elm/Pages/Article/Update.elm | 16 +++++------ src/elm/Pages/Article/View.elm | 6 ++--- src/elm/Pages/Event/Model.elm | 2 +- src/elm/Pages/Event/Router.elm | 2 +- src/elm/Pages/Event/Update.elm | 33 +++++++++++------------ src/elm/Pages/Event/Utils.elm | 2 +- src/elm/Pages/Event/View.elm | 8 +++--- src/elm/Pages/GithubAuth/Model.elm | 2 +- src/elm/Pages/GithubAuth/Update.elm | 12 ++++----- src/elm/Pages/GithubAuth/View.elm | 6 ++--- src/elm/Pages/Login/Model.elm | 2 +- src/elm/Pages/Login/Test.elm | 12 ++++----- src/elm/Pages/Login/Update.elm | 12 ++++----- src/elm/Pages/Login/View.elm | 6 ++--- src/elm/Pages/PageNotFound/View.elm | 2 +- src/elm/Pages/User/Decoder.elm | 2 +- src/elm/Pages/User/Model.elm | 2 +- src/elm/Pages/User/Update.elm | 8 +++--- src/elm/Pages/User/View.elm | 6 ++--- src/elm/TestRunner.elm | 2 +- src/elm/Utils/Http.elm | 2 +- 57 files changed, 184 insertions(+), 187 deletions(-) diff --git a/src/elm/App/Model.elm b/src/elm/App/Model.elm index 614e1a6..b5f5c01 100644 --- a/src/elm/App/Model.elm +++ b/src/elm/App/Model.elm @@ -1,4 +1,4 @@ -module App.Model where +module App.Model exposing (..) import Config.Model as Config exposing (initialModel, Model) import Company.Model as Company exposing (Model) diff --git a/src/elm/App/Router.elm b/src/elm/App/Router.elm index 826ecbb..4694d88 100644 --- a/src/elm/App/Router.elm +++ b/src/elm/App/Router.elm @@ -1,7 +1,7 @@ -module App.Router where +module App.Router exposing (..) import App.Model as App exposing (Model) -import App.Update exposing (Action) +import App.Update exposing (Msg) import Pages.Event.Router as Event exposing (delta2update, location2company) import RouteHash exposing (HashUpdate) @@ -39,7 +39,7 @@ delta2update previous current = -- Here, we basically do the reverse of what delta2update does -location2action : List String -> List Action +location2action : List String -> List Msg location2action list = case list of ["auth", "github"] -> diff --git a/src/elm/App/Update.elm b/src/elm/App/Update.elm index 3c45f4b..e9cee41 100644 --- a/src/elm/App/Update.elm +++ b/src/elm/App/Update.elm @@ -1,8 +1,8 @@ -module App.Update where +module App.Update exposing (..) import App.Model as App exposing (initialModel, Model) -import Config.Update exposing (init, Action) +import Config.Update exposing (init, Msg) import Company.Model as Company exposing (Model) import Effects exposing (Effects) import Json.Encode as JE exposing (string, Value) @@ -12,35 +12,35 @@ import Task exposing (succeed) -- Pages import -import Pages.Article.Update exposing (Action) -import Pages.Event.Update exposing (Action) -import Pages.GithubAuth.Update exposing (Action) -import Pages.Login.Update exposing (Action) +import Pages.Article.Update exposing (Msg) +import Pages.Event.Update exposing (Msg) +import Pages.GithubAuth.Update exposing (Msg) +import Pages.Login.Update exposing (Msg) import Pages.User.Model exposing (User) -import Pages.User.Update exposing (Action) +import Pages.User.Update exposing (Msg) type alias AccessToken = String type alias Model = App.Model -initialEffects : List (Effects Action) +initialEffects : List (Effects Msg) initialEffects = [ Effects.map ChildConfigAction <| snd Config.Update.init , Effects.map ChildLoginAction <| snd Pages.Login.Update.init ] -init : (Model, Effects Action) +init : (Model, Effects Msg) init = ( App.initialModel , Effects.batch initialEffects ) -type Action - = ChildArticleAction Pages.Article.Update.Action - | ChildConfigAction Config.Update.Action - | ChildEventAction Pages.Event.Update.Action - | ChildGithubAuthAction Pages.GithubAuth.Update.Action - | ChildLoginAction Pages.Login.Update.Action - | ChildUserAction Pages.User.Update.Action +type Msg + = ChildArticleAction Pages.Article.Update.Msg + | ChildConfigAction Config.Update.Msg + | ChildEventAction Pages.Event.Update.Msg + | ChildGithubAuthAction Pages.GithubAuth.Update.Msg + | ChildLoginAction Pages.Login.Update.Msg + | ChildUserAction Pages.User.Update.Msg | Logout | SetAccessToken AccessToken | SetActivePage App.Page @@ -53,7 +53,7 @@ type Action | NoOpSetAccessToken (Result AccessToken ()) -update : Action -> Model -> (Model, Effects Action) +update : Msg -> Model -> (Model, Effects Msg) update action model = case action of ChildArticleAction act -> @@ -353,7 +353,7 @@ update action model = -- EFFECTS -sendInputToStorage : String -> Effects Action +sendInputToStorage : String -> Effects Msg sendInputToStorage val = Storage.setItem "access_token" (JE.string val) |> Task.toResult @@ -361,7 +361,7 @@ sendInputToStorage val = |> Effects.task -- Task to remove the access token from localStorage. -removeStorageItem : Effects Action +removeStorageItem : Effects Msg removeStorageItem = Storage.removeItem "access_token" |> Task.toMaybe diff --git a/src/elm/App/View.elm b/src/elm/App/View.elm index f536b64..964e56b 100644 --- a/src/elm/App/View.elm +++ b/src/elm/App/View.elm @@ -1,7 +1,7 @@ -module App.View where +module App.View exposing (..) import App.Model as App exposing (initialModel, Model) -import App.Update exposing (init, Action) +import App.Update exposing (init, Msg) import Config.View exposing (view) import Html exposing (a, div, h2, i, li, node, span, text, ul, button, Html) @@ -28,7 +28,7 @@ isActivePage activePage page = _-> activePage == page -view : Signal.Address Action -> Model -> Html +view : Signal.Address Msg -> Model -> Html view address model = if model.configError == True then @@ -42,7 +42,7 @@ view address model = , footer ] -mainContent : Signal.Address Action -> Model -> Html +mainContent : Signal.Address Msg -> Model -> Html mainContent address model = case model.activePage of App.Article -> @@ -91,7 +91,7 @@ mainContent address model = in div [ style myStyle ] [ Pages.User.View.view childAddress model.user ] -navbar : Signal.Address Action -> Model -> Html +navbar : Signal.Address Msg -> Model -> Html navbar address model = case model.user.name of Pages.User.Model.Anonymous -> @@ -120,7 +120,7 @@ footer = ] -- Navbar for Auth user. -navbarLoggedIn : Signal.Address Action -> Model -> Html +navbarLoggedIn : Signal.Address Msg -> Model -> Html navbarLoggedIn address model = let activeClass page = diff --git a/src/elm/Article/Decoder.elm b/src/elm/Article/Decoder.elm index 9be9d04..07f1c6c 100644 --- a/src/elm/Article/Decoder.elm +++ b/src/elm/Article/Decoder.elm @@ -1,4 +1,4 @@ -module Article.Decoder where +module Article.Decoder exposing (..) import Article.Model as Article exposing (Model) diff --git a/src/elm/Article/Model.elm b/src/elm/Article/Model.elm index 71f6f33..0355928 100644 --- a/src/elm/Article/Model.elm +++ b/src/elm/Article/Model.elm @@ -1,4 +1,4 @@ -module Article.Model where +module Article.Model exposing (..) type alias Id = Int diff --git a/src/elm/ArticleForm/Model.elm b/src/elm/ArticleForm/Model.elm index 52fe2d6..69c5b73 100644 --- a/src/elm/ArticleForm/Model.elm +++ b/src/elm/ArticleForm/Model.elm @@ -1,4 +1,4 @@ -module ArticleForm.Model where +module ArticleForm.Model exposing (..) type PostStatus = Busy | Done | Ready diff --git a/src/elm/ArticleForm/Update.elm b/src/elm/ArticleForm/Update.elm index 79b8e93..d1c7c66 100644 --- a/src/elm/ArticleForm/Update.elm +++ b/src/elm/ArticleForm/Update.elm @@ -1,4 +1,4 @@ -module ArticleForm.Update where +module ArticleForm.Update exposing (..) import Article.Decoder exposing (decode) import Article.Model as Article exposing (Author, Model) @@ -12,13 +12,13 @@ import Json.Encode as JE exposing (string) import Task exposing (andThen, Task) import Utils.Http exposing (getErrorMessageFromHttpResponse) -init : (ArticleForm.Model, Effects Action) +init : (ArticleForm.Model, Effects Msg) init = ( initialModel , Effects.none ) -type Action +type Msg = ResetForm | SubmitForm | SetImageId (Maybe Int) @@ -35,7 +35,7 @@ type alias Context = , backendConfig : BackendConfig } -update : Context -> Action -> Model -> (Model, Effects Action, Maybe Article.Model) +update : Context -> Msg -> Model -> (Model, Effects Msg, Maybe Article.Model) update context action model = case action of ResetForm -> @@ -134,7 +134,7 @@ update context action model = -- EFFECTS -postArticle : String -> String -> ArticleForm.ArticleForm -> Effects Action +postArticle : String -> String -> ArticleForm.ArticleForm -> Effects Msg postArticle url accessToken data = let params = diff --git a/src/elm/ArticleForm/View.elm b/src/elm/ArticleForm/View.elm index 9872289..9de8fb2 100644 --- a/src/elm/ArticleForm/View.elm +++ b/src/elm/ArticleForm/View.elm @@ -1,13 +1,13 @@ -module ArticleForm.View where +module ArticleForm.View exposing (..) import ArticleForm.Model exposing (initialModel, Model, UserMessage) -import ArticleForm.Update exposing (Action) +import ArticleForm.Update exposing (Msg) import Html exposing (i, button, div, label, h2, h3, input, img, li, text, textarea, span, ul, Html) import Html.Attributes exposing (action, class, id, disabled, name, placeholder, property, required, size, src, style, type', value) import Html.Events exposing (on, onClick, onSubmit, targetValue) import String exposing (toInt, toFloat) -view : Signal.Address Action -> Model -> Html +view : Signal.Address Msg -> Model -> Html view address model = div [ class "wrapper -suffix"] @@ -23,7 +23,7 @@ viewUserMessage userMessage = ArticleForm.Model.Error message -> div [ style [("text-align", "center")] ] [ text message ] -viewForm :Signal.Address Action -> Model -> Html +viewForm :Signal.Address Msg -> Model -> Html viewForm address model = Html.form [ onSubmit address ArticleForm.Update.SubmitForm diff --git a/src/elm/ArticleList/Model.elm b/src/elm/ArticleList/Model.elm index 2409cc6..c7f61ef 100644 --- a/src/elm/ArticleList/Model.elm +++ b/src/elm/ArticleList/Model.elm @@ -1,4 +1,4 @@ -module ArticleList.Model where +module ArticleList.Model exposing (..) import Article.Model as Article exposing (Model) import Http exposing (Error) diff --git a/src/elm/ArticleList/Update.elm b/src/elm/ArticleList/Update.elm index 58755d1..ffc32cd 100644 --- a/src/elm/ArticleList/Update.elm +++ b/src/elm/ArticleList/Update.elm @@ -1,4 +1,4 @@ -module ArticleList.Update where +module ArticleList.Update exposing (..) import Article.Decoder exposing (decode) import Article.Model as Article exposing (Model) @@ -9,16 +9,15 @@ import Effects exposing (Effects) import Http exposing (post, Error) import Json.Decode as JD exposing ((:=)) import Task exposing (andThen, Task) -import TaskTutorial exposing (getCurrentTime) import Time exposing (Time) -init : (ArticleList.Model.Model, Effects Action) +init : (ArticleList.Model.Model, Effects Msg) init = ( initialModel , Effects.none ) -type Action +type Msg = AppendArticle Article.Model | GetData | GetDataFromServer @@ -32,7 +31,7 @@ type alias UpdateContext = , backendConfig : BackendConfig } -update : UpdateContext -> Action -> ArticleList.Model.Model -> (ArticleList.Model.Model, Effects Action) +update : UpdateContext -> Msg -> ArticleList.Model.Model -> (ArticleList.Model.Model, Effects Msg) update context action model = case action of AppendArticle article -> @@ -88,7 +87,7 @@ update context action model = -- EFFECTS -getDataFromCache : ArticleList.Model.Status -> Effects Action +getDataFromCache : ArticleList.Model.Status -> Effects Msg getDataFromCache status = let actionTask = @@ -98,7 +97,7 @@ getDataFromCache status = if fetchTime + Config.cacheTtl > currentTime then NoOp else GetDataFromServer - ) getCurrentTime + ) Time.now _ -> Task.succeed GetDataFromServer @@ -107,7 +106,7 @@ getDataFromCache status = Effects.task actionTask -getJson : String -> String -> Effects Action +getJson : String -> String -> Effects Msg getJson url accessToken = let params = @@ -125,7 +124,7 @@ getJson url accessToken = httpTask `andThen` (\result -> Task.map (\timestamp' -> UpdateDataFromServer result timestamp' - ) getCurrentTime + ) Time.now ) in diff --git a/src/elm/ArticleList/View.elm b/src/elm/ArticleList/View.elm index 16805cb..9a2aa66 100644 --- a/src/elm/ArticleList/View.elm +++ b/src/elm/ArticleList/View.elm @@ -1,9 +1,9 @@ -module ArticleList.View where +module ArticleList.View exposing (..) import Article.Model exposing (Model) import ArticleList.Model exposing (initialModel, Model) -import ArticleList.Update exposing (Action) +import ArticleList.Update exposing (Msg) import Html exposing (i, button, div, label, h2, h3, input, img, li, text, textarea, span, ul, Html) import Html.Attributes exposing (action, class, id, disabled, name, placeholder, property, required, size, src, style, type', value) @@ -16,7 +16,7 @@ type alias Article = Article.Model.Model type alias Model = ArticleList.Model.Model -view : Signal.Address Action -> Model -> Html +view : Signal.Address Msg -> Model -> Html view address model = viewRecentArticles model.articles diff --git a/src/elm/Company/Model.elm b/src/elm/Company/Model.elm index c0fb4d5..c53e81e 100644 --- a/src/elm/Company/Model.elm +++ b/src/elm/Company/Model.elm @@ -1,4 +1,4 @@ -module Company.Model where +module Company.Model exposing (..) type alias CompanyId = Int diff --git a/src/elm/Config.elm b/src/elm/Config.elm index 1f619ea..691a2b1 100644 --- a/src/elm/Config.elm +++ b/src/elm/Config.elm @@ -1,4 +1,4 @@ -module Config where +module Config exposing (..) import Config.Model as Config exposing (BackendConfig) import Time exposing (Time) diff --git a/src/elm/Config/Model.elm b/src/elm/Config/Model.elm index e04e030..cea811e 100644 --- a/src/elm/Config/Model.elm +++ b/src/elm/Config/Model.elm @@ -1,4 +1,4 @@ -module Config.Model where +module Config.Model exposing (..) type alias BackendConfig = { backendUrl : String diff --git a/src/elm/Config/Test.elm b/src/elm/Config/Test.elm index 7088993..bfaf147 100644 --- a/src/elm/Config/Test.elm +++ b/src/elm/Config/Test.elm @@ -1,19 +1,19 @@ -module Config.Test where +module Config.Test exposing (..) import ElmTest exposing (..) import Config.Model exposing (initialBackendConfig, initialModel, Model) -import Config.Update exposing (update, Action) +import Config.Update exposing (update, Msg) import Effects exposing (Effects) -type alias Action = Config.Update.Action +type alias Msg = Config.Update.Msg type alias Model = Config.Model.Model setErrorTest : Test setErrorTest = test "set error action" (assertEqual True (.error <| fst(setError))) -setError : (Model, Effects Action) +setError : (Model, Effects Msg) setError = Config.Update.update Config.Update.SetError initialModel diff --git a/src/elm/Config/Update.elm b/src/elm/Config/Update.elm index 72d3dc5..59510f5 100644 --- a/src/elm/Config/Update.elm +++ b/src/elm/Config/Update.elm @@ -1,38 +1,37 @@ -module Config.Update where +module Config.Update exposing (..) import Config exposing (backends) import Config.Model exposing (initialModel, Model) -import Effects exposing (Effects) import Task exposing (map) import WebAPI.Location exposing (location) -init : (Model, Effects Action) +init : (Model, Cmd Msg) init = ( initialModel , getConfigFromUrl ) -type Action +type Msg = SetConfig Config.Model.BackendConfig | SetError -update : Action -> Model -> (Model, Effects Action) +update : Msg -> Model -> (Model, Cmd Msg) update action model = case action of SetConfig backendConfig -> ( { model | backendConfig = backendConfig } - , Effects.none + , Cmd.none ) SetError -> ( { model | error = True } - , Effects.none + , Cmd.none ) -- EFFECTS -getConfigFromUrl : Effects Action +getConfigFromUrl : Cmd Msg getConfigFromUrl = let getAction location = @@ -48,4 +47,4 @@ getConfigFromUrl = actionTask = Task.map getAction WebAPI.Location.location in - Effects.task actionTask + Cmd.task actionTask diff --git a/src/elm/Config/View.elm b/src/elm/Config/View.elm index f880f05..5397298 100644 --- a/src/elm/Config/View.elm +++ b/src/elm/Config/View.elm @@ -1,4 +1,4 @@ -module Config.View where +module Config.View exposing (..) import Html exposing (div, h2, text, Html) import Html.Attributes exposing (class) diff --git a/src/elm/Event/Decoder.elm b/src/elm/Event/Decoder.elm index 05f062d..35a0682 100644 --- a/src/elm/Event/Decoder.elm +++ b/src/elm/Event/Decoder.elm @@ -1,4 +1,4 @@ -module Event.Decoder where +module Event.Decoder exposing (..) import Event.Model as Event exposing (Author, Event, Marker) import Json.Decode as JD exposing ((:=)) diff --git a/src/elm/Event/Model.elm b/src/elm/Event/Model.elm index f9205ed..06a63bd 100644 --- a/src/elm/Event/Model.elm +++ b/src/elm/Event/Model.elm @@ -1,4 +1,4 @@ -module Event.Model where +module Event.Model exposing (..) type alias Id = Int diff --git a/src/elm/EventAuthorFilter/Model.elm b/src/elm/EventAuthorFilter/Model.elm index 273bd12..051a6c1 100644 --- a/src/elm/EventAuthorFilter/Model.elm +++ b/src/elm/EventAuthorFilter/Model.elm @@ -1,4 +1,4 @@ -module EventAuthorFilter.Model where +module EventAuthorFilter.Model exposing (..) type alias Model = Maybe Int diff --git a/src/elm/EventAuthorFilter/Update.elm b/src/elm/EventAuthorFilter/Update.elm index 850521e..f99ce85 100644 --- a/src/elm/EventAuthorFilter/Update.elm +++ b/src/elm/EventAuthorFilter/Update.elm @@ -1,15 +1,15 @@ -module EventAuthorFilter.Update where +module EventAuthorFilter.Update exposing (..) import EventAuthorFilter.Model as EventAuthorFilter exposing (initialModel, Model) init : EventAuthorFilter.Model init = initialModel -type Action +type Msg = SelectAuthor Int | UnSelectAuthor -update : Action -> Model -> Model +update : Msg -> Model -> Model update action model = case action of SelectAuthor id -> diff --git a/src/elm/EventAuthorFilter/View.elm b/src/elm/EventAuthorFilter/View.elm index 916e17b..80ce379 100644 --- a/src/elm/EventAuthorFilter/View.elm +++ b/src/elm/EventAuthorFilter/View.elm @@ -1,7 +1,7 @@ -module EventAuthorFilter.View where +module EventAuthorFilter.View exposing (..) import EventAuthorFilter.Model as EventAuthorFilter exposing (initialModel, Model) -import EventAuthorFilter.Update exposing (Action) +import EventAuthorFilter.Update exposing (Msg) import Dict exposing (Dict) import Event.Model as Event exposing (Author, Event) @@ -11,7 +11,7 @@ import Html.Events exposing (on, onClick, targetValue) type alias Model = EventAuthorFilter.Model -view : List Event -> Signal.Address Action -> Model -> Html +view : List Event -> Signal.Address Msg -> Model -> Html view events address eventAuthorFilter = div [ class "wrapper -suffix" ] @@ -23,7 +23,7 @@ view events address eventAuthorFilter = , ul [ class "authors" ] (viewEventsByAuthors events address eventAuthorFilter) ] -viewEventsByAuthors : List Event -> Signal.Address Action -> Maybe Int -> List Html +viewEventsByAuthors : List Event -> Signal.Address Msg -> Maybe Int -> List Html viewEventsByAuthors events address eventAuthorFilter = let getText : Author -> Int -> Html diff --git a/src/elm/EventCompanyFilter/Model.elm b/src/elm/EventCompanyFilter/Model.elm index 42643d5..f6cab69 100644 --- a/src/elm/EventCompanyFilter/Model.elm +++ b/src/elm/EventCompanyFilter/Model.elm @@ -1,4 +1,4 @@ -module EventCompanyFilter.Model where +module EventCompanyFilter.Model exposing (..) type alias Model = Maybe Int diff --git a/src/elm/EventCompanyFilter/Test.elm b/src/elm/EventCompanyFilter/Test.elm index ad75fa4..42bdada 100644 --- a/src/elm/EventCompanyFilter/Test.elm +++ b/src/elm/EventCompanyFilter/Test.elm @@ -1,10 +1,10 @@ -module EventCompanyFilter.Test where +module EventCompanyFilter.Test exposing (..) import ElmTest exposing (..) import Company.Model as Company exposing (Model) import EventCompanyFilter.Model as EventCompanyFilter exposing (initialModel, Model) -import EventCompanyFilter.Update exposing (Action) +import EventCompanyFilter.Update exposing (Msg) type alias Model = EventCompanyFilter.Model diff --git a/src/elm/EventCompanyFilter/Update.elm b/src/elm/EventCompanyFilter/Update.elm index 0d34d30..5e21796 100644 --- a/src/elm/EventCompanyFilter/Update.elm +++ b/src/elm/EventCompanyFilter/Update.elm @@ -1,4 +1,4 @@ -module EventCompanyFilter.Update where +module EventCompanyFilter.Update exposing (..) import EventCompanyFilter.Model as EventCompanyFilter exposing (initialModel, Model) @@ -8,12 +8,12 @@ import Company.Model as Company exposing (Model) init : Model init = initialModel -type Action +type Msg = SelectCompany (Maybe Int) type alias Model = EventCompanyFilter.Model -update : List Company.Model -> Action -> Model -> Model +update : List Company.Model -> Msg -> Model -> Model update companies action model = case action of SelectCompany maybeCompanyId -> diff --git a/src/elm/EventCompanyFilter/View.elm b/src/elm/EventCompanyFilter/View.elm index 3e7a57d..f462b35 100644 --- a/src/elm/EventCompanyFilter/View.elm +++ b/src/elm/EventCompanyFilter/View.elm @@ -1,7 +1,7 @@ -module EventCompanyFilter.View where +module EventCompanyFilter.View exposing (..) import EventCompanyFilter.Model as EventCompanyFilter exposing (initialModel, Model) -import EventCompanyFilter.Update exposing (Action) +import EventCompanyFilter.Update exposing (Msg) import Company.Model as Company exposing (Model) import Html exposing (h3, a, i, div, input, text, select, span, li, option, ul, Html) @@ -11,7 +11,7 @@ import String exposing (toInt) type alias Model = EventCompanyFilter.Model -view : List Company.Model -> Signal.Address Action -> Model -> Html +view : List Company.Model -> Signal.Address Msg -> Model -> Html view companies address model = div [ class "wrapper -suffix" ] @@ -23,7 +23,7 @@ view companies address model = , companyListForSelect address companies model ] -companyListForSelect : Signal.Address Action -> List Company.Model -> Model -> Html +companyListForSelect : Signal.Address Msg -> List Company.Model -> Model -> Html companyListForSelect address companies eventCompanyFilter = let selectedText = diff --git a/src/elm/EventList/Model.elm b/src/elm/EventList/Model.elm index 19ac5d4..1da0fb4 100644 --- a/src/elm/EventList/Model.elm +++ b/src/elm/EventList/Model.elm @@ -1,4 +1,4 @@ -module EventList.Model where +module EventList.Model exposing (..) type alias Model = { filterString : String diff --git a/src/elm/EventList/Update.elm b/src/elm/EventList/Update.elm index 806bfee..7537a6d 100644 --- a/src/elm/EventList/Update.elm +++ b/src/elm/EventList/Update.elm @@ -1,9 +1,9 @@ -module EventList.Update where +module EventList.Update exposing (..) import Event.Model exposing (Event) import EventList.Model as EventList exposing (initialModel, Model) -type Action +type Msg = FilterEvents String -- Select event might get values from JS (i.e. selecting a leaflet marker) -- so we allow passing a Maybe Int, instead of just Int. @@ -16,7 +16,7 @@ init : Model init = initialModel -update : List Event -> Action -> Model -> Model +update : List Event -> Msg -> Model -> Model update events action model = case action of FilterEvents val -> diff --git a/src/elm/EventList/Utils.elm b/src/elm/EventList/Utils.elm index e29774a..f0ceab3 100644 --- a/src/elm/EventList/Utils.elm +++ b/src/elm/EventList/Utils.elm @@ -1,4 +1,4 @@ -module EventList.Utils (filterEventsByString) where +module EventList.Utils exposing (filterEventsByString) import Event.Model exposing (Event) import String exposing (isEmpty, trim, toLower) diff --git a/src/elm/EventList/View.elm b/src/elm/EventList/View.elm index 24aff04..a30027c 100644 --- a/src/elm/EventList/View.elm +++ b/src/elm/EventList/View.elm @@ -1,8 +1,8 @@ -module EventList.View (view) where +module EventList.View exposing (view) import Event.Model as Event exposing (Event) import EventList.Model as EventList exposing (initialModel, Model) -import EventList.Update exposing (Action) +import EventList.Update exposing (Msg) import EventList.Utils exposing (filterEventsByString) import Html exposing (h3, a, i, div, input, text, select, span, li, option, ul, Html) @@ -11,7 +11,7 @@ import Html.Events exposing (on, onClick, targetValue) type alias Model = EventList.Model -view : List Event -> Signal.Address Action -> Model -> Html +view : List Event -> Signal.Address Msg -> Model -> Html view events address model = div [ id "events" @@ -26,7 +26,7 @@ view events address model = ] -viewFilterString : Signal.Address Action -> Model -> Html +viewFilterString : Signal.Address Msg -> Model -> Html viewFilterString address model = div [] [ input @@ -39,7 +39,7 @@ viewFilterString address model = ] -viewListEvents : List Event -> Signal.Address Action -> Model -> Html +viewListEvents : List Event -> Signal.Address Msg -> Model -> Html viewListEvents events address model = let filteredEvents = diff --git a/src/elm/Leaflet/Model.elm b/src/elm/Leaflet/Model.elm index cbd5f13..b6d1b58 100644 --- a/src/elm/Leaflet/Model.elm +++ b/src/elm/Leaflet/Model.elm @@ -1,4 +1,4 @@ -module Leaflet.Model where +module Leaflet.Model exposing (..) type alias Marker = { id : Int diff --git a/src/elm/Leaflet/Update.elm b/src/elm/Leaflet/Update.elm index 6bd2309..1b74327 100644 --- a/src/elm/Leaflet/Update.elm +++ b/src/elm/Leaflet/Update.elm @@ -1,4 +1,4 @@ -module Leaflet.Update where +module Leaflet.Update exposing (..) import Event.Model exposing (Event) import Leaflet.Model as Leaflet exposing (initialModel, Marker, Model) @@ -7,14 +7,14 @@ init : Model init = initialModel -type Action +type Msg = SelectMarker (Maybe Int) | SetMarkers (List Event) | ToggleMap | UnselectMarker -update : Action -> Model -> Model +update : Msg -> Model -> Model update action model = case action of SelectMarker val -> diff --git a/src/elm/Leaflet/View.elm b/src/elm/Leaflet/View.elm index 374c044..7c872c9 100644 --- a/src/elm/Leaflet/View.elm +++ b/src/elm/Leaflet/View.elm @@ -1,12 +1,12 @@ -module Leaflet.View where +module Leaflet.View exposing (..) import Leaflet.Model exposing (initialModel, Model) -import Leaflet.Update exposing (Action) +import Leaflet.Update exposing (Msg) import Html exposing (div, span, Html) import Html.Attributes exposing (id, style) -view : Signal.Address Action -> Model -> Html +view : Signal.Address Msg -> Model -> Html view address model = if model.showMap then div [ style myStyle, id "map" ] [] diff --git a/src/elm/Main.elm b/src/elm/Main.elm index 2bdbb4a..c9d462d 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -3,12 +3,12 @@ import App.Router exposing (delta2update, location2action) import App.Update exposing (init, update) import App.View exposing (view) import ArticleForm.Model exposing (PostStatus) -import ArticleForm.Update exposing (Action) +import ArticleForm.Update exposing (Msg) import Effects exposing (Never) -import EventList.Update exposing (Action) -import Pages.Event.Update exposing (Action) +import EventList.Update exposing (Msg) +import Pages.Event.Update exposing (Msg) import Leaflet.Model exposing (Model) -import Pages.Article.Update exposing (Action) +import Pages.Article.Update exposing (Msg) import RouteHash import StartApp as StartApp import Task exposing (Task) @@ -30,7 +30,7 @@ app = main = app.html -messages : Signal.Mailbox App.Update.Action +messages : Signal.Mailbox App.Update.Msg messages = Signal.mailbox App.Update.NoOp diff --git a/src/elm/Pages/Article/Model.elm b/src/elm/Pages/Article/Model.elm index 29f1633..dbcccc3 100644 --- a/src/elm/Pages/Article/Model.elm +++ b/src/elm/Pages/Article/Model.elm @@ -1,4 +1,4 @@ -module Pages.Article.Model where +module Pages.Article.Model exposing (..) import ArticleForm.Model as ArticleForm exposing (initialModel, Model) import ArticleList.Model as ArticleList exposing (initialModel, Model) diff --git a/src/elm/Pages/Article/Update.elm b/src/elm/Pages/Article/Update.elm index d0a6359..44213ec 100644 --- a/src/elm/Pages/Article/Update.elm +++ b/src/elm/Pages/Article/Update.elm @@ -1,29 +1,29 @@ -module Pages.Article.Update where +module Pages.Article.Update exposing (..) -import ArticleForm.Update exposing (Action) -import ArticleList.Update exposing (Action) +import ArticleForm.Update exposing (Msg) +import ArticleList.Update exposing (Msg) import Config.Model exposing (BackendConfig) import Effects exposing (Effects) import Pages.Article.Model exposing (Model) import Task exposing (succeed) -type Action +type Msg = Activate - | ChildArticleFormAction ArticleForm.Update.Action - | ChildArticleListAction ArticleList.Update.Action + | ChildArticleFormAction ArticleForm.Update.Msg + | ChildArticleListAction ArticleList.Update.Msg type alias UpdateContext = { accessToken : String , backendConfig : BackendConfig } -init : (Model, Effects Action) +init : (Model, Effects Msg) init = ( Pages.Article.Model.initialModel , Effects.none ) -update : UpdateContext -> Action -> Pages.Article.Model.Model -> (Pages.Article.Model.Model, Effects Action) +update : UpdateContext -> Msg -> Pages.Article.Model.Model -> (Pages.Article.Model.Model, Effects Msg) update context action model = case action of Activate -> diff --git a/src/elm/Pages/Article/View.elm b/src/elm/Pages/Article/View.elm index e2a6e8e..6657a80 100644 --- a/src/elm/Pages/Article/View.elm +++ b/src/elm/Pages/Article/View.elm @@ -1,14 +1,14 @@ -module Pages.Article.View where +module Pages.Article.View exposing (..) import ArticleForm.View as ArticleForm exposing (view) import ArticleList.View as ArticleList exposing (view) import Html exposing (i, button, div, label, h2, h3, input, img, li, text, textarea, span, ul, Html) import Html.Attributes exposing (action, class, id, disabled, name, placeholder, property, required, size, src, style, type', value) import Pages.Article.Model as Article exposing (Model) -import Pages.Article.Update exposing (Action) +import Pages.Article.Update exposing (Msg) -view : Signal.Address Action -> Article.Model -> Html +view : Signal.Address Msg -> Article.Model -> Html view address model = let childArticleFormAddress = diff --git a/src/elm/Pages/Event/Model.elm b/src/elm/Pages/Event/Model.elm index 4109637..00fd557 100644 --- a/src/elm/Pages/Event/Model.elm +++ b/src/elm/Pages/Event/Model.elm @@ -1,4 +1,4 @@ -module Pages.Event.Model where +module Pages.Event.Model exposing (..) import Event.Model exposing (Event) import EventAuthorFilter.Model as EventAuthorFilter exposing (initialModel, Model) diff --git a/src/elm/Pages/Event/Router.elm b/src/elm/Pages/Event/Router.elm index 201009e..a7d7ad8 100644 --- a/src/elm/Pages/Event/Router.elm +++ b/src/elm/Pages/Event/Router.elm @@ -1,4 +1,4 @@ -module Pages.Event.Router where +module Pages.Event.Router exposing (..) import Pages.Event.Model as Event exposing (Model) import RouteHash exposing (HashUpdate) diff --git a/src/elm/Pages/Event/Update.elm b/src/elm/Pages/Event/Update.elm index 57b6850..b27ba20 100644 --- a/src/elm/Pages/Event/Update.elm +++ b/src/elm/Pages/Event/Update.elm @@ -1,4 +1,4 @@ -module Pages.Event.Update where +module Pages.Event.Update exposing (..) import Config exposing (cacheTtl) import Config.Model exposing (BackendConfig) @@ -6,39 +6,38 @@ import Company.Model as Company exposing (Model) import Effects exposing (Effects) import Event.Decoder exposing (decode) import Event.Model exposing (Event) -import EventAuthorFilter.Update exposing (Action) -import EventCompanyFilter.Update exposing (Action) -import EventList.Update exposing (Action) +import EventAuthorFilter.Update exposing (Msg) +import EventCompanyFilter.Update exposing (Msg) +import EventList.Update exposing (Msg) import EventList.Utils exposing (filterEventsByString) import Http exposing (Error) -import Leaflet.Update exposing (Action) +import Leaflet.Update exposing (Msg) import Pages.Event.Model as Event exposing (Model) import Pages.Event.Utils exposing (filterEventsByAuthor) import Task exposing (andThen, succeed) -import TaskTutorial exposing (getCurrentTime) import Time exposing (Time) type alias Id = Int type alias CompanyId = Int type alias Model = Event.Model -init : (Model, Effects Action) +init : (Model, Effects Msg) init = ( Event.initialModel , Effects.none ) -type Action +type Msg = NoOp | GetData (Maybe CompanyId) | GetDataFromServer (Maybe CompanyId) | UpdateDataFromServer (Result Http.Error (List Event)) (Maybe CompanyId) Time.Time -- Child actions - | ChildEventAuthorFilterAction EventAuthorFilter.Update.Action - | ChildEventCompanyFilterAction EventCompanyFilter.Update.Action - | ChildEventListAction EventList.Update.Action - | ChildLeafletAction Leaflet.Update.Action + | ChildEventAuthorFilterAction EventAuthorFilter.Update.Msg + | ChildEventCompanyFilterAction EventCompanyFilter.Update.Msg + | ChildEventListAction EventList.Update.Msg + | ChildLeafletAction Leaflet.Update.Msg -- Page | Activate (Maybe CompanyId) @@ -51,7 +50,7 @@ type alias Context = , companies : List Company.Model } -update : Context -> Action -> Model -> (Model, Effects Action) +update : Context -> Msg -> Model -> (Model, Effects Msg) update context action model = case action of ChildEventAuthorFilterAction act -> @@ -202,7 +201,7 @@ update context action model = -- EFFECTS -getDataFromCache : Event.Status -> Maybe CompanyId -> Effects Action +getDataFromCache : Event.Status -> Maybe CompanyId -> Effects Msg getDataFromCache status maybeCompanyId = let getFx = @@ -217,7 +216,7 @@ getDataFromCache status maybeCompanyId = if fetchTime + Config.cacheTtl > currentTime then NoOp else GetDataFromServer maybeCompanyId - ) getCurrentTime + ) Time.now else getFx @@ -228,7 +227,7 @@ getDataFromCache status maybeCompanyId = Effects.task actionTask -getJson : String -> Maybe CompanyId -> String -> Effects Action +getJson : String -> Maybe CompanyId -> String -> Effects Msg getJson url maybeCompanyId accessToken = let params = @@ -255,7 +254,7 @@ getJson url maybeCompanyId accessToken = httpTask `andThen` (\result -> Task.map (\timestamp -> UpdateDataFromServer result maybeCompanyId timestamp - ) getCurrentTime + ) Time.now ) in diff --git a/src/elm/Pages/Event/Utils.elm b/src/elm/Pages/Event/Utils.elm index 1a57aec..bc8ebdd 100644 --- a/src/elm/Pages/Event/Utils.elm +++ b/src/elm/Pages/Event/Utils.elm @@ -1,4 +1,4 @@ -module Pages.Event.Utils where +module Pages.Event.Utils exposing (..) import EventAuthorFilter.Model as EventAuthorFilter exposing (Model) import Event.Model exposing (Event) diff --git a/src/elm/Pages/Event/View.elm b/src/elm/Pages/Event/View.elm index 70d366f..4710d84 100644 --- a/src/elm/Pages/Event/View.elm +++ b/src/elm/Pages/Event/View.elm @@ -1,4 +1,4 @@ -module Pages.Event.View where +module Pages.Event.View exposing (..) import Company.Model as Company exposing (Model) import EventAuthorFilter.View exposing (view) @@ -7,17 +7,17 @@ import EventList.View exposing (view) import Html exposing (h3, a, i, div, input, text, select, span, li, option, ul, Html) import Html.Attributes exposing (class, hidden, href, id, placeholder, selected, style, value) import Pages.Event.Model exposing (initialModel, Model) -import Pages.Event.Update exposing (Action) +import Pages.Event.Update exposing (Msg) import Pages.Event.Utils exposing (filterEventsByAuthor) -type alias Action = Pages.Event.Update.Action +type alias Msg = Pages.Event.Update.Msg type alias CompanyId = Int type alias Model = Pages.Event.Model.Model type alias Context = { companies : List Company.Model } -view : Context -> Signal.Address Action -> Model -> Html +view : Context -> Signal.Address Msg -> Model -> Html view context address model = let diff --git a/src/elm/Pages/GithubAuth/Model.elm b/src/elm/Pages/GithubAuth/Model.elm index 95b1766..a289d4f 100644 --- a/src/elm/Pages/GithubAuth/Model.elm +++ b/src/elm/Pages/GithubAuth/Model.elm @@ -1,4 +1,4 @@ -module Pages.GithubAuth.Model where +module Pages.GithubAuth.Model exposing (..) import Http exposing (Error) diff --git a/src/elm/Pages/GithubAuth/Update.elm b/src/elm/Pages/GithubAuth/Update.elm index ee8990d..779101c 100644 --- a/src/elm/Pages/GithubAuth/Update.elm +++ b/src/elm/Pages/GithubAuth/Update.elm @@ -1,4 +1,4 @@ -module Pages.GithubAuth.Update where +module Pages.GithubAuth.Update exposing (..) import Config.Model exposing (BackendConfig) import Dict exposing (get) @@ -13,14 +13,14 @@ import WebAPI.Location exposing (location) type alias AccessToken = String -init : (Model, Effects Action) +init : (Model, Effects Msg) init = ( initialModel , Effects.none ) -type Action +type Msg = Activate | AuthorizeUser String | SetError String @@ -31,7 +31,7 @@ type alias UpdateContext = { backendConfig : BackendConfig } -update : UpdateContext -> Action -> Model -> (Model, Effects Action) +update : UpdateContext -> Msg -> Model -> (Model, Effects Msg) update context action model = case action of Activate -> @@ -70,7 +70,7 @@ update context action model = -- EFFECTS -getCodeFromUrl : Effects Action +getCodeFromUrl : Effects Msg getCodeFromUrl = let errAction = @@ -94,7 +94,7 @@ getCodeFromUrl = Effects.task actionTask -getJson : String -> String -> Effects Action +getJson : String -> String -> Effects Msg getJson backendUrl code = Http.post decodeAccessToken diff --git a/src/elm/Pages/GithubAuth/View.elm b/src/elm/Pages/GithubAuth/View.elm index 50a1689..04f6879 100644 --- a/src/elm/Pages/GithubAuth/View.elm +++ b/src/elm/Pages/GithubAuth/View.elm @@ -1,4 +1,4 @@ -module Pages.GithubAuth.View where +module Pages.GithubAuth.View exposing (..) -- import Config.Model exposing (BackendConfig) -- import Dict exposing (get) @@ -9,10 +9,10 @@ import Html.Attributes exposing (class, href, id) -- import Json.Decode as JD exposing ((:=)) -- import Json.Encode as JE exposing (..) import Pages.GithubAuth.Model as GithubAuth exposing (initialModel, Model) -import Pages.GithubAuth.Update exposing (Action) +import Pages.GithubAuth.Update exposing (Msg) -view : Signal.Address Action -> Model -> Html +view : Signal.Address Msg -> Model -> Html view address model = let spinner = diff --git a/src/elm/Pages/Login/Model.elm b/src/elm/Pages/Login/Model.elm index 0c4324c..6030077 100644 --- a/src/elm/Pages/Login/Model.elm +++ b/src/elm/Pages/Login/Model.elm @@ -1,4 +1,4 @@ -module Pages.Login.Model where +module Pages.Login.Model exposing (..) import Http exposing (Error) diff --git a/src/elm/Pages/Login/Test.elm b/src/elm/Pages/Login/Test.elm index 95f0189..a6616cf 100644 --- a/src/elm/Pages/Login/Test.elm +++ b/src/elm/Pages/Login/Test.elm @@ -1,4 +1,4 @@ -module Pages.Login.Test where +module Pages.Login.Test exposing (..) import ElmTest exposing (..) @@ -6,7 +6,7 @@ import Config.Model exposing (initialBackendConfig) import Effects exposing (Effects) import Http exposing (Error) import Pages.Login.Model exposing (initialModel, Model) -import Pages.Login.Update exposing (Action) +import Pages.Login.Update exposing (Msg) type alias Model = Pages.Login.Model.Model @@ -45,15 +45,15 @@ formSuite = , test "submit after another submit with errors" (assertEqual Pages.Login.Model.Fetching (.status <| fst(submitForm <| Pages.Login.Model.HttpError Http.NetworkError))) ] -updateName : String -> (Model, Effects Action) +updateName : String -> (Model, Effects Msg) updateName val = Pages.Login.Update.update updateContext (Pages.Login.Update.UpdateName val) Pages.Login.Model.initialModel -updatePass : String -> (Model, Effects Action) +updatePass : String -> (Model, Effects Msg) updatePass val = Pages.Login.Update.update updateContext (Pages.Login.Update.UpdatePass val) Pages.Login.Model.initialModel -submitForm : Pages.Login.Model.Status -> (Model, Effects Action) +submitForm : Pages.Login.Model.Status -> (Model, Effects Msg) submitForm status = let model = @@ -65,7 +65,7 @@ submitForm status = in Pages.Login.Update.update updateContext Pages.Login.Update.SubmitForm model' -setAccessToken : String -> (Model, Effects Action) +setAccessToken : String -> (Model, Effects Msg) setAccessToken val = Pages.Login.Update.update updateContext (Pages.Login.Update.SetAccessToken val) Pages.Login.Model.initialModel diff --git a/src/elm/Pages/Login/Update.elm b/src/elm/Pages/Login/Update.elm index 52200e5..ece3a3e 100644 --- a/src/elm/Pages/Login/Update.elm +++ b/src/elm/Pages/Login/Update.elm @@ -1,4 +1,4 @@ -module Pages.Login.Update where +module Pages.Login.Update exposing (..) import Pages.Login.Model exposing (initialModel, Model) @@ -13,14 +13,14 @@ import Utils.Http exposing (getErrorMessageFromHttpResponse) type alias AccessToken = String -init : (Model, Effects Action) +init : (Model, Effects Msg) init = ( initialModel -- Try to get an existing access token. , getInputFromStorage ) -type Action +type Msg = UpdateAccessTokenFromServer (Result Http.Error AccessToken) | UpdateAccessTokenFromStorage (Result String AccessToken) | UpdateName String @@ -33,7 +33,7 @@ type alias Context = { backendConfig : BackendConfig } -update : Context -> Action -> Model -> (Model, Effects Action) +update : Context -> Msg -> Model -> (Model, Effects Msg) update context action model = case action of UpdateName name -> @@ -118,7 +118,7 @@ update context action model = ) -getInputFromStorage : Effects Action +getInputFromStorage : Effects Msg getInputFromStorage = Storage.getItem "access_token" JD.string |> Task.toResult @@ -137,7 +137,7 @@ encodeCredentials (name, pass) = Ok result -> result Err err -> "" -getJson : String -> String -> Effects Action +getJson : String -> String -> Effects Msg getJson url credentials = Http.send Http.defaultSettings { verb = "GET" diff --git a/src/elm/Pages/Login/View.elm b/src/elm/Pages/Login/View.elm index 00b8b7c..73d0819 100644 --- a/src/elm/Pages/Login/View.elm +++ b/src/elm/Pages/Login/View.elm @@ -1,7 +1,7 @@ -module Pages.Login.View where +module Pages.Login.View exposing (..) import Pages.Login.Model exposing (initialModel, Model) -import Pages.Login.Update exposing (Action) +import Pages.Login.Update exposing (Msg) import Config.Model exposing (BackendConfig) import Html exposing (a, button, div, i, input, h2, hr, span, text, Html) @@ -13,7 +13,7 @@ type alias ViewContext = { backendConfig : BackendConfig } -view : ViewContext -> Signal.Address Action -> Model -> Html +view : ViewContext -> Signal.Address Msg -> Model -> Html view context address model = let modelForm = diff --git a/src/elm/Pages/PageNotFound/View.elm b/src/elm/Pages/PageNotFound/View.elm index 0bb34b7..587efc7 100644 --- a/src/elm/Pages/PageNotFound/View.elm +++ b/src/elm/Pages/PageNotFound/View.elm @@ -1,4 +1,4 @@ -module Pages.PageNotFound.View where +module Pages.PageNotFound.View exposing (..) import Html exposing (a, i, div, h2, text, Html) import Html.Attributes exposing (class, id, href, style) diff --git a/src/elm/Pages/User/Decoder.elm b/src/elm/Pages/User/Decoder.elm index 0c482db..39efd52 100644 --- a/src/elm/Pages/User/Decoder.elm +++ b/src/elm/Pages/User/Decoder.elm @@ -1,4 +1,4 @@ -module Pages.User.Decoder where +module Pages.User.Decoder exposing (..) import Company.Model as Company exposing (Model) import Effects exposing (Effects, Never) diff --git a/src/elm/Pages/User/Model.elm b/src/elm/Pages/User/Model.elm index 8e1a2ea..acc38c7 100644 --- a/src/elm/Pages/User/Model.elm +++ b/src/elm/Pages/User/Model.elm @@ -1,4 +1,4 @@ -module Pages.User.Model where +module Pages.User.Model exposing (..) import Company.Model as Company exposing (initialModel, Model) import Http exposing (Error) diff --git a/src/elm/Pages/User/Update.elm b/src/elm/Pages/User/Update.elm index 566c3fe..a751108 100644 --- a/src/elm/Pages/User/Update.elm +++ b/src/elm/Pages/User/Update.elm @@ -1,4 +1,4 @@ -module Pages.User.Update where +module Pages.User.Update exposing (..) import Config.Model exposing (BackendConfig) import Company.Model as Company exposing (initialModel, Model) @@ -17,19 +17,19 @@ type alias UpdateContext = , backendConfig : BackendConfig } -type Action +type Msg = GetDataFromServer | NoOp (Maybe ()) | SetAccessToken AccessToken | UpdateDataFromServer (Result Http.Error (Id, String, List Company.Model)) -init : (Model, Effects Action) +init : (Model, Effects Msg) init = ( User.initialModel , Effects.none ) -update : UpdateContext -> Action -> Model -> (Model, Effects Action) +update : UpdateContext -> Msg -> Model -> (Model, Effects Msg) update context action model = case action of NoOp _ -> diff --git a/src/elm/Pages/User/View.elm b/src/elm/Pages/User/View.elm index 29e2371..46ab35d 100644 --- a/src/elm/Pages/User/View.elm +++ b/src/elm/Pages/User/View.elm @@ -1,13 +1,13 @@ -module Pages.User.View where +module Pages.User.View exposing (..) import Company.Model as Company exposing (Model) import Html exposing (..) import Html.Attributes exposing (..) import Pages.User.Model as User exposing (Model) -import Pages.User.Update exposing (Action) +import Pages.User.Update exposing (Msg) -view : Signal.Address Action -> User.Model -> Html +view : Signal.Address Msg -> User.Model -> Html view address model = case model.name of User.Anonymous -> diff --git a/src/elm/TestRunner.elm b/src/elm/TestRunner.elm index 074e845..5db5a74 100644 --- a/src/elm/TestRunner.elm +++ b/src/elm/TestRunner.elm @@ -1,4 +1,4 @@ -module Main where +module Main exposing (..) import Graphics.Element exposing (Element) diff --git a/src/elm/Utils/Http.elm b/src/elm/Utils/Http.elm index f9d0545..e5a648b 100644 --- a/src/elm/Utils/Http.elm +++ b/src/elm/Utils/Http.elm @@ -1,4 +1,4 @@ -module Utils.Http where +module Utils.Http exposing (..) import Http exposing (Error) From a38c42398dd8ce54f3601c2315cf8d9f321d4cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hern=C3=A1ndez?= Date: Wed, 28 Sep 2016 17:54:24 +0200 Subject: [PATCH 03/10] Removes calls to the Effects and replaces it with the 0.17 alternative: Cmd --- src/elm/App/Update.elm | 141 ++++++++++++++-------------- src/elm/ArticleForm/Update.elm | 27 +++--- src/elm/ArticleList/Update.elm | 25 +++-- src/elm/Config/Test.elm | 3 +- src/elm/Main.elm | 25 ++--- src/elm/Pages/Article/Update.elm | 27 +++--- src/elm/Pages/Event/Update.elm | 45 +++++---- src/elm/Pages/GithubAuth/Update.elm | 23 +++-- src/elm/Pages/GithubAuth/View.elm | 1 - src/elm/Pages/Login/Test.elm | 9 +- src/elm/Pages/Login/Update.elm | 35 ++++--- src/elm/Pages/User/Decoder.elm | 1 - src/elm/Pages/User/Update.elm | 27 +++--- 13 files changed, 185 insertions(+), 204 deletions(-) diff --git a/src/elm/App/Update.elm b/src/elm/App/Update.elm index e9cee41..08d0016 100644 --- a/src/elm/App/Update.elm +++ b/src/elm/App/Update.elm @@ -4,7 +4,6 @@ import App.Model as App exposing (initialModel, Model) import Config.Update exposing (init, Msg) import Company.Model as Company exposing (Model) -import Effects exposing (Effects) import Json.Encode as JE exposing (string, Value) import String exposing (isEmpty) import Storage exposing (removeItem, setItem) @@ -22,16 +21,16 @@ import Pages.User.Update exposing (Msg) type alias AccessToken = String type alias Model = App.Model -initialEffects : List (Effects Msg) -initialEffects = - [ Effects.map ChildConfigAction <| snd Config.Update.init - , Effects.map ChildLoginAction <| snd Pages.Login.Update.init +initialCmd : List (Cmd Msg) +initialCmd = + [ Cmd.map ChildConfigAction <| snd Config.Update.init + , Cmd.map ChildLoginAction <| snd Pages.Login.Update.init ] -init : (Model, Effects Msg) +init : (Model, Cmd Msg) init = ( App.initialModel - , Effects.batch initialEffects + , Cmd.batch initialCmd ) type Msg @@ -53,7 +52,7 @@ type Msg | NoOpSetAccessToken (Result AccessToken ()) -update : Msg -> Model -> (Model, Effects Msg) +update : Msg -> Model -> (Model, Cmd Msg) update action model = case action of ChildArticleAction act -> @@ -64,34 +63,34 @@ update action model = , backendConfig = (.config >> .backendConfig) model } - (childModel, childEffects) = Pages.Article.Update.update context act model.article + (childModel, childCmd) = Pages.Article.Update.update context act model.article in ( {model | article = childModel } - , Effects.map ChildArticleAction childEffects + , Cmd.map ChildArticleAction childCmd ) ChildConfigAction act -> let - (childModel, childEffects) = Config.Update.update act model.config + (childModel, childCmd) = Config.Update.update act model.config - defaultEffects = - [ Effects.map ChildConfigAction childEffects ] + defaultCmd = + [ Cmd.map ChildConfigAction childCmd ] effects' = case act of Config.Update.SetError -> -- Set configuration error. - (Task.succeed SetConfigError |> Effects.task) + (Task.succeed SetConfigError |> Cmd.task) :: - defaultEffects + defaultCmd _ -> - defaultEffects + defaultCmd in ( { model | config = childModel } - , Effects.batch effects' + , Cmd.batch effects' ) ChildEventAction act -> @@ -103,10 +102,10 @@ update action model = , companies = model.companies } - (childModel, childEffects) = Pages.Event.Update.update context act model.events + (childModel, childCmd) = Pages.Event.Update.update context act model.events in ( {model | events = childModel } - , Effects.map ChildEventAction childEffects + , Cmd.map ChildEventAction childCmd ) ChildGithubAuthAction act -> @@ -115,13 +114,13 @@ update action model = context = { backendConfig = (.config >> .backendConfig) model } - (childModel, childEffects) = Pages.GithubAuth.Update.update context act model.githubAuth + (childModel, childCmd) = Pages.GithubAuth.Update.update context act model.githubAuth defaultEffect = - Effects.map ChildGithubAuthAction childEffects + Cmd.map ChildGithubAuthAction childCmd -- A convinence variable to hold the default effect as a list. - defaultEffects = + defaultCmd = [ defaultEffect ] effects' = @@ -130,16 +129,16 @@ update action model = -- root property, and also get the user info, which will in turn -- redirect the user from the login page. Pages.GithubAuth.Update.SetAccessToken token -> - (Task.succeed (SetAccessToken token) |> Effects.task) + (Task.succeed (SetAccessToken token) |> Cmd.task) :: - defaultEffects + defaultCmd _ -> - defaultEffects + defaultCmd in ( {model | githubAuth = childModel } - , Effects.batch effects' + , Cmd.batch effects' ) ChildLoginAction act -> @@ -147,13 +146,13 @@ update action model = context = { backendConfig = (.config >> .backendConfig) model } - (childModel, childEffects) = Pages.Login.Update.update context act model.login + (childModel, childCmd) = Pages.Login.Update.update context act model.login defaultEffect = - Effects.map ChildLoginAction childEffects + Cmd.map ChildLoginAction childCmd -- A convinence variable to hold the default effect as a list. - defaultEffects = + defaultCmd = [ defaultEffect ] effects' = @@ -162,18 +161,18 @@ update action model = -- -- root property, and also get the user info, which will in turn -- -- redirect the user from the login page. Pages.Login.Update.SetAccessToken token -> - (Task.succeed (SetAccessToken token) |> Effects.task) + (Task.succeed (SetAccessToken token) |> Cmd.task) :: - (Task.succeed (ChildUserAction Pages.User.Update.GetDataFromServer) |> Effects.task) + (Task.succeed (ChildUserAction Pages.User.Update.GetDataFromServer) |> Cmd.task) :: - defaultEffects + defaultCmd _ -> - defaultEffects + defaultCmd in ( {model | login = childModel } - , Effects.batch effects' + , Cmd.batch effects' ) @@ -184,12 +183,12 @@ update action model = , backendConfig = (.config >> .backendConfig) model } - (childModel, childEffects) = Pages.User.Update.update context act model.user + (childModel, childCmd) = Pages.User.Update.update context act model.user defaultEffect = - Effects.map ChildUserAction childEffects + Cmd.map ChildUserAction childCmd - defaultEffects = + defaultCmd = [ defaultEffect ] model' = @@ -200,9 +199,9 @@ update action model = -- Bubble up the SetAccessToken to the App level. Pages.User.Update.SetAccessToken token -> ( model' - , (Task.succeed (SetAccessToken token) |> Effects.task) + , (Task.succeed (SetAccessToken token) |> Cmd.task) :: - defaultEffects + defaultCmd ) -- Act when user was successfully fetched from the server. @@ -223,51 +222,51 @@ update action model = -- User data was successfully fetched, so we can redirect to -- the next page, and update their companies. ( { model' | nextPage = Nothing } - , (Task.succeed (UpdateCompanies companies) |> Effects.task) + , (Task.succeed (UpdateCompanies companies) |> Cmd.task) :: - (Task.succeed (SetActivePage nextPage) |> Effects.task) + (Task.succeed (SetActivePage nextPage) |> Cmd.task) :: - defaultEffects + defaultCmd ) Err _ -> ( model' - , defaultEffects + , defaultCmd ) _ -> ( model' - , defaultEffects + , defaultCmd ) in - (model'', Effects.batch effects') + (model'', Cmd.batch effects') Logout -> ( App.initialModel - , Effects.batch <| removeStorageItem :: initialEffects + , Cmd.batch <| removeStorageItem :: initialCmd ) SetAccessToken accessToken -> let - defaultEffects = + defaultCmd = [sendInputToStorage accessToken] effects' = if (String.isEmpty accessToken) then -- Setting an empty access token should result with a logout. - (Task.succeed Logout |> Effects.task) + (Task.succeed Logout |> Cmd.task) :: - defaultEffects + defaultCmd else - (Task.succeed (ChildUserAction Pages.User.Update.GetDataFromServer) |> Effects.task) + (Task.succeed (ChildUserAction Pages.User.Update.GetDataFromServer) |> Cmd.task) :: - defaultEffects + defaultCmd in ( { model | accessToken = accessToken} - , Effects.batch effects' + , Cmd.batch effects' ) SetActivePage page -> @@ -297,27 +296,27 @@ update action model = -- Authenticated user. else (page, Nothing) - currentPageEffects = + currentPageCmd = case model.activePage of App.Event companyId -> - Task.succeed (ChildEventAction Pages.Event.Update.Deactivate) |> Effects.task + Task.succeed (ChildEventAction Pages.Event.Update.Deactivate) |> Cmd.task _ -> - Effects.none + Cmd.none - newPageEffects = + newPageCmd = case page' of App.Article -> - Task.succeed (ChildArticleAction Pages.Article.Update.Activate) |> Effects.task + Task.succeed (ChildArticleAction Pages.Article.Update.Activate) |> Cmd.task App.Event companyId -> - Task.succeed (ChildEventAction <| Pages.Event.Update.Activate companyId) |> Effects.task + Task.succeed (ChildEventAction <| Pages.Event.Update.Activate companyId) |> Cmd.task App.GithubAuth -> - Task.succeed (ChildGithubAuthAction Pages.GithubAuth.Update.Activate) |> Effects.task + Task.succeed (ChildGithubAuthAction Pages.GithubAuth.Update.Activate) |> Cmd.task _ -> - Effects.none + Cmd.none in if model.activePage == page' @@ -325,45 +324,45 @@ update action model = -- Requesting the same page, so don't do anything. -- @todo: Because login and myAccount are under the same page (User) -- we set the nextPage here as-well. - ( { model | nextPage = nextPage }, Effects.none) + ( { model | nextPage = nextPage }, Cmd.none) else ( { model | activePage = page' , nextPage = nextPage } - , Effects.batch - [ currentPageEffects - , newPageEffects + , Cmd.batch + [ currentPageCmd + , newPageCmd ] ) SetConfigError -> ( { model | configError = True} - , Effects.none + , Cmd.none ) UpdateCompanies companies -> ( { model | companies = companies} - , Effects.none + , Cmd.none ) -- NoOp actions _ -> - ( model, Effects.none ) + ( model, Cmd.none ) -- EFFECTS -sendInputToStorage : String -> Effects Msg +sendInputToStorage : String -> Cmd Msg sendInputToStorage val = Storage.setItem "access_token" (JE.string val) |> Task.toResult |> Task.map NoOpSetAccessToken - |> Effects.task + |> Cmd.task -- Task to remove the access token from localStorage. -removeStorageItem : Effects Msg +removeStorageItem : Cmd Msg removeStorageItem = Storage.removeItem "access_token" |> Task.toMaybe |> Task.map NoOpLogout - |> Effects.task + |> Cmd.task diff --git a/src/elm/ArticleForm/Update.elm b/src/elm/ArticleForm/Update.elm index d1c7c66..0dbb685 100644 --- a/src/elm/ArticleForm/Update.elm +++ b/src/elm/ArticleForm/Update.elm @@ -5,17 +5,16 @@ import Article.Model as Article exposing (Author, Model) import ArticleForm.Model as ArticleForm exposing (initialArticleForm, initialModel, ArticleForm, Model, UserMessage) import Config.Model exposing (BackendConfig) -import Effects exposing (Effects) import Http exposing (post, Error) import Json.Decode as JD exposing ((:=)) import Json.Encode as JE exposing (string) import Task exposing (andThen, Task) import Utils.Http exposing (getErrorMessageFromHttpResponse) -init : (ArticleForm.Model, Effects Msg) +init : (ArticleForm.Model, Cmd Msg) init = ( initialModel - , Effects.none + , Cmd.none ) type Msg @@ -35,7 +34,7 @@ type alias Context = , backendConfig : BackendConfig } -update : Context -> Msg -> Model -> (Model, Effects Msg, Maybe Article.Model) +update : Context -> Msg -> Model -> (Model, Cmd Msg, Maybe Article.Model) update context action model = case action of ResetForm -> @@ -43,7 +42,7 @@ update context action model = | articleForm = initialArticleForm , postStatus = ArticleForm.Ready } - , Effects.none + , Cmd.none , Nothing ) @@ -56,13 +55,13 @@ update context action model = { articleForm | image = maybeVal } in ( { model | articleForm = articleForm' } - , Effects.none + , Cmd.none , Nothing ) SetUserMessage userMessage -> ( { model | userMessage = userMessage } - , Effects.none + , Cmd.none , Nothing ) @@ -83,7 +82,7 @@ update context action model = else ( model - , Effects.none + , Cmd.none , Nothing ) @@ -97,7 +96,7 @@ update context action model = { articleForm | body = val } in ( { model | articleForm = articleForm' } - , Effects.none + , Cmd.none , Nothing ) @@ -110,7 +109,7 @@ update context action model = { articleForm | label = val } in ( { model | articleForm = articleForm' } - , Effects.none + , Cmd.none , Nothing ) @@ -120,21 +119,21 @@ update context action model = -- Append the new article to the articles list. ( { model | postStatus = ArticleForm.Done } -- We can reset the form, as it was posted successfully. - , Task.succeed ResetForm |> Effects.task + , Task.succeed ResetForm |> Cmd.task -- Return the article to the parent component. , Just article ) Err err -> ( model - , Task.succeed (SetUserMessage <| ArticleForm.Error (getErrorMessageFromHttpResponse err)) |> Effects.task + , Task.succeed (SetUserMessage <| ArticleForm.Error (getErrorMessageFromHttpResponse err)) |> Cmd.task , Nothing ) -- EFFECTS -postArticle : String -> String -> ArticleForm.ArticleForm -> Effects Msg +postArticle : String -> String -> ArticleForm.ArticleForm -> Cmd Msg postArticle url accessToken data = let params = @@ -149,7 +148,7 @@ postArticle url accessToken data = (Http.string <| dataToJson data ) |> Task.toResult |> Task.map UpdatePostArticle - |> Effects.task + |> Cmd.task dataToJson : ArticleForm.ArticleForm -> String diff --git a/src/elm/ArticleList/Update.elm b/src/elm/ArticleList/Update.elm index ffc32cd..210ed0f 100644 --- a/src/elm/ArticleList/Update.elm +++ b/src/elm/ArticleList/Update.elm @@ -5,16 +5,15 @@ import Article.Model as Article exposing (Model) import ArticleList.Model exposing (initialModel, Model) import Config exposing (cacheTtl) import Config.Model exposing (BackendConfig) -import Effects exposing (Effects) import Http exposing (post, Error) import Json.Decode as JD exposing ((:=)) import Task exposing (andThen, Task) import Time exposing (Time) -init : (ArticleList.Model.Model, Effects Msg) +init : (ArticleList.Model.Model, Cmd Msg) init = ( initialModel - , Effects.none + , Cmd.none ) type Msg @@ -31,12 +30,12 @@ type alias UpdateContext = , backendConfig : BackendConfig } -update : UpdateContext -> Msg -> ArticleList.Model.Model -> (ArticleList.Model.Model, Effects Msg) +update : UpdateContext -> Msg -> ArticleList.Model.Model -> (ArticleList.Model.Model, Cmd Msg) update context action model = case action of AppendArticle article -> ( { model | articles = article :: model.articles } - , Effects.none + , Cmd.none ) GetData -> @@ -44,7 +43,7 @@ update context action model = effects = case model.status of ArticleList.Model.Fetching -> - Effects.none + Cmd.none _ -> getDataFromCache model.status @@ -74,20 +73,20 @@ update context action model = | articles = articles , status = ArticleList.Model.Fetched timestamp' } - , Effects.none + , Cmd.none ) Err err -> ( { model | status = ArticleList.Model.HttpError err } - , Effects.none + , Cmd.none ) NoOp -> - (model, Effects.none) + (model, Cmd.none) -- EFFECTS -getDataFromCache : ArticleList.Model.Status -> Effects Msg +getDataFromCache : ArticleList.Model.Status -> Cmd Msg getDataFromCache status = let actionTask = @@ -103,10 +102,10 @@ getDataFromCache status = Task.succeed GetDataFromServer in - Effects.task actionTask + Cmd.task actionTask -getJson : String -> String -> Effects Msg +getJson : String -> String -> Cmd Msg getJson url accessToken = let params = @@ -128,7 +127,7 @@ getJson url accessToken = ) in - Effects.task actionTask + Cmd.task actionTask decodeData : JD.Decoder (List Article.Model) diff --git a/src/elm/Config/Test.elm b/src/elm/Config/Test.elm index bfaf147..de4693d 100644 --- a/src/elm/Config/Test.elm +++ b/src/elm/Config/Test.elm @@ -4,7 +4,6 @@ import ElmTest exposing (..) import Config.Model exposing (initialBackendConfig, initialModel, Model) import Config.Update exposing (update, Msg) -import Effects exposing (Effects) type alias Msg = Config.Update.Msg type alias Model = Config.Model.Model @@ -13,7 +12,7 @@ setErrorTest : Test setErrorTest = test "set error action" (assertEqual True (.error <| fst(setError))) -setError : (Model, Effects Msg) +setError : (Model, Cmd Msg) setError = Config.Update.update Config.Update.SetError initialModel diff --git a/src/elm/Main.elm b/src/elm/Main.elm index c9d462d..67de012 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -4,7 +4,6 @@ import App.Update exposing (init, update) import App.View exposing (view) import ArticleForm.Model exposing (PostStatus) import ArticleForm.Update exposing (Msg) -import Effects exposing (Never) import EventList.Update exposing (Msg) import Pages.Event.Update exposing (Msg) import Leaflet.Model exposing (Model) @@ -14,18 +13,12 @@ import StartApp as StartApp import Task exposing (Task) -app = - StartApp.start - { init = App.Update.init - , update = App.Update.update - , view = App.View.view - , inputs = - [ messages.signal - , Signal.map (App.Update.ChildArticleAction << Pages.Article.Update.ChildArticleFormAction << ArticleForm.Update.SetImageId) dropzoneUploadedFile - , Signal.map (App.Update.ChildArticleAction << Pages.Article.Update.ChildArticleFormAction << ArticleForm.Update.UpdateBody) ckeditor - , Signal.map (App.Update.ChildEventAction << Pages.Event.Update.ChildEventListAction << EventList.Update.SelectEvent) selectEvent - ] - } +inputs = + [ messages.signal + , Signal.map (App.Update.ChildArticleAction << Pages.Article.Update.ChildArticleFormAction << ArticleForm.Update.SetImageId) dropzoneUploadedFile + , Signal.map (App.Update.ChildArticleAction << Pages.Article.Update.ChildArticleFormAction << ArticleForm.Update.UpdateBody) ckeditor + , Signal.map (App.Update.ChildEventAction << Pages.Event.Update.ChildEventListAction << EventList.Update.SelectEvent) selectEvent + ] main = app.html @@ -34,9 +27,9 @@ messages : Signal.Mailbox App.Update.Msg messages = Signal.mailbox App.Update.NoOp -port tasks : Signal (Task.Task Never ()) -port tasks = - app.tasks +main = + Html.program + { init = App.Update.init, update = App.Update.update, view = App.View.view, subscriptions = inputs } port routeTasks : Signal (Task () ()) port routeTasks = diff --git a/src/elm/Pages/Article/Update.elm b/src/elm/Pages/Article/Update.elm index 44213ec..c017e29 100644 --- a/src/elm/Pages/Article/Update.elm +++ b/src/elm/Pages/Article/Update.elm @@ -3,7 +3,6 @@ module Pages.Article.Update exposing (..) import ArticleForm.Update exposing (Msg) import ArticleList.Update exposing (Msg) import Config.Model exposing (BackendConfig) -import Effects exposing (Effects) import Pages.Article.Model exposing (Model) import Task exposing (succeed) @@ -17,46 +16,46 @@ type alias UpdateContext = , backendConfig : BackendConfig } -init : (Model, Effects Msg) +init : (Model, Cmd Msg) init = ( Pages.Article.Model.initialModel - , Effects.none + , Cmd.none ) -update : UpdateContext -> Msg -> Pages.Article.Model.Model -> (Pages.Article.Model.Model, Effects Msg) +update : UpdateContext -> Msg -> Pages.Article.Model.Model -> (Pages.Article.Model.Model, Cmd Msg) update context action model = case action of Activate -> ( model - , Task.succeed (ChildArticleListAction ArticleList.Update.GetData) |> Effects.task + , Task.succeed (ChildArticleListAction ArticleList.Update.GetData) |> Cmd.task ) ChildArticleFormAction act -> let - (childModel, childEffects, maybeArticle) = ArticleForm.Update.update context act model.articleForm + (childModel, childCmd, maybeArticle) = ArticleForm.Update.update context act model.articleForm - defaultEffects = - [ Effects.map ChildArticleFormAction childEffects ] + defaultCmd = + [ Cmd.map ChildArticleFormAction childCmd ] effects' = case maybeArticle of Just article -> - (Task.succeed (ChildArticleListAction <| ArticleList.Update.AppendArticle article) |> Effects.task) + (Task.succeed (ChildArticleListAction <| ArticleList.Update.AppendArticle article) |> Cmd.task) :: - defaultEffects + defaultCmd Nothing -> - defaultEffects + defaultCmd in ( { model | articleForm = childModel } - , Effects.batch effects' + , Cmd.batch effects' ) ChildArticleListAction act -> let - (childModel, childEffects) = ArticleList.Update.update context act model.articleList + (childModel, childCmd) = ArticleList.Update.update context act model.articleList in ( { model | articleList = childModel } - , Effects.map ChildArticleListAction childEffects + , Cmd.map ChildArticleListAction childCmd ) diff --git a/src/elm/Pages/Event/Update.elm b/src/elm/Pages/Event/Update.elm index b27ba20..3756ac9 100644 --- a/src/elm/Pages/Event/Update.elm +++ b/src/elm/Pages/Event/Update.elm @@ -3,7 +3,6 @@ module Pages.Event.Update exposing (..) import Config exposing (cacheTtl) import Config.Model exposing (BackendConfig) import Company.Model as Company exposing (Model) -import Effects exposing (Effects) import Event.Decoder exposing (decode) import Event.Model exposing (Event) import EventAuthorFilter.Update exposing (Msg) @@ -21,10 +20,10 @@ type alias Id = Int type alias CompanyId = Int type alias Model = Event.Model -init : (Model, Effects Msg) +init : (Model, Cmd Msg) init = ( Event.initialModel - , Effects.none + , Cmd.none ) type Msg @@ -50,7 +49,7 @@ type alias Context = , companies : List Company.Model } -update : Context -> Msg -> Model -> (Model, Effects Msg) +update : Context -> Msg -> Model -> (Model, Cmd Msg) update context action model = case action of ChildEventAuthorFilterAction act -> @@ -61,7 +60,7 @@ update context action model = in ( { model | eventAuthorFilter = childModel } -- Filter out the events, before sending the events' markers. - , Task.succeed (ChildLeafletAction <| Leaflet.Update.SetMarkers (filterEventsByAuthor model.events childModel)) |> Effects.task + , Task.succeed (ChildLeafletAction <| Leaflet.Update.SetMarkers (filterEventsByAuthor model.events childModel)) |> Cmd.task ) ChildEventCompanyFilterAction act -> @@ -78,7 +77,7 @@ update context action model = in ( { model | eventCompanyFilter = childModel } - , Task.succeed (GetData maybeCompanyId) |> Effects.task + , Task.succeed (GetData maybeCompanyId) |> Cmd.task ) ChildEventListAction act -> @@ -103,7 +102,7 @@ update context action model = Leaflet.Update.UnselectMarker in ( { model | eventList = childModel } - , Task.succeed (ChildLeafletAction <| childAction) |> Effects.task + , Task.succeed (ChildLeafletAction <| childAction) |> Cmd.task ) ChildLeafletAction act -> @@ -112,13 +111,13 @@ update context action model = Leaflet.Update.update act model.leaflet in ( {model | leaflet = childModel } - , Effects.none + , Cmd.none ) GetData maybeCompanyId -> let noFx = - (model, Effects.none) + (model, Cmd.none) getFx = (model, getDataFromCache model.status maybeCompanyId) @@ -148,7 +147,7 @@ update context action model = ) NoOp -> - (model, Effects.none) + (model, Cmd.none) UpdateDataFromServer result maybeCompanyId timestamp -> case result of @@ -164,16 +163,16 @@ update context action model = | events = events , status = Event.Fetched maybeCompanyId timestamp } - , Effects.batch - [ Task.succeed (ChildEventAuthorFilterAction EventAuthorFilter.Update.UnSelectAuthor) |> Effects.task - , Task.succeed (ChildEventListAction EventList.Update.UnSelectEvent) |> Effects.task - , Task.succeed (ChildEventListAction <| EventList.Update.FilterEvents "") |> Effects.task + , Cmd.batch + [ Task.succeed (ChildEventAuthorFilterAction EventAuthorFilter.Update.UnSelectAuthor) |> Cmd.task + , Task.succeed (ChildEventListAction EventList.Update.UnSelectEvent) |> Cmd.task + , Task.succeed (ChildEventListAction <| EventList.Update.FilterEvents "") |> Cmd.task ] ) Err msg -> ( { model | status = Event.HttpError msg } - , Effects.none + , Cmd.none ) Activate maybeCompanyId -> @@ -183,9 +182,9 @@ update context action model = in ( { model | leaflet = childModel } - , Effects.batch - [ Task.succeed (GetData maybeCompanyId) |> Effects.task - , Task.succeed (ChildEventCompanyFilterAction <| EventCompanyFilter.Update.SelectCompany maybeCompanyId) |> Effects.task + , Cmd.batch + [ Task.succeed (GetData maybeCompanyId) |> Cmd.task + , Task.succeed (ChildEventCompanyFilterAction <| EventCompanyFilter.Update.SelectCompany maybeCompanyId) |> Cmd.task ] ) @@ -195,13 +194,13 @@ update context action model = Leaflet.Update.update Leaflet.Update.ToggleMap model.leaflet in ( { model | leaflet = childModel } - , Effects.none + , Cmd.none ) -- EFFECTS -getDataFromCache : Event.Status -> Maybe CompanyId -> Effects Msg +getDataFromCache : Event.Status -> Maybe CompanyId -> Cmd Msg getDataFromCache status maybeCompanyId = let getFx = @@ -224,10 +223,10 @@ getDataFromCache status maybeCompanyId = getFx in - Effects.task actionTask + Cmd.task actionTask -getJson : String -> Maybe CompanyId -> String -> Effects Msg +getJson : String -> Maybe CompanyId -> String -> Cmd Msg getJson url maybeCompanyId accessToken = let params = @@ -258,4 +257,4 @@ getJson url maybeCompanyId accessToken = ) in - Effects.task actionTask + Cmd.task actionTask diff --git a/src/elm/Pages/GithubAuth/Update.elm b/src/elm/Pages/GithubAuth/Update.elm index 779101c..1364add 100644 --- a/src/elm/Pages/GithubAuth/Update.elm +++ b/src/elm/Pages/GithubAuth/Update.elm @@ -2,7 +2,6 @@ module Pages.GithubAuth.Update exposing (..) import Config.Model exposing (BackendConfig) import Dict exposing (get) -import Effects exposing (Effects) import Http exposing (Error) import Json.Decode as JD exposing ((:=)) import Json.Encode as JE exposing (..) @@ -13,10 +12,10 @@ import WebAPI.Location exposing (location) type alias AccessToken = String -init : (Model, Effects Msg) +init : (Model, Cmd Msg) init = ( initialModel - , Effects.none + , Cmd.none ) @@ -31,7 +30,7 @@ type alias UpdateContext = { backendConfig : BackendConfig } -update : UpdateContext -> Msg -> Model -> (Model, Effects Msg) +update : UpdateContext -> Msg -> Model -> (Model, Cmd Msg) update context action model = case action of Activate -> @@ -48,29 +47,29 @@ update context action model = SetError msg -> ( { model | status = GithubAuth.Error msg } - , Effects.none + , Cmd.none ) SetAccessToken token -> ( { model | accessToken = token } - , Effects.none + , Cmd.none ) UpdateAccessTokenFromServer result -> case result of Ok token -> ( { model | status = GithubAuth.Fetched } - , Task.succeed (SetAccessToken token) |> Effects.task + , Task.succeed (SetAccessToken token) |> Cmd.task ) Err msg -> ( { model | status = GithubAuth.HttpError msg } -- @todo: Improve. - , Task.succeed (SetError "HTTP error") |> Effects.task + , Task.succeed (SetError "HTTP error") |> Cmd.task ) -- EFFECTS -getCodeFromUrl : Effects Msg +getCodeFromUrl : Cmd Msg getCodeFromUrl = let errAction = @@ -91,10 +90,10 @@ getCodeFromUrl = actionTask = Task.map getAction WebAPI.Location.location in - Effects.task actionTask + Cmd.task actionTask -getJson : String -> String -> Effects Msg +getJson : String -> String -> Cmd Msg getJson backendUrl code = Http.post decodeAccessToken @@ -102,7 +101,7 @@ getJson backendUrl code = (Http.string <| dataToJson code ) |> Task.toResult |> Task.map UpdateAccessTokenFromServer - |> Effects.task + |> Cmd.task dataToJson : String -> String diff --git a/src/elm/Pages/GithubAuth/View.elm b/src/elm/Pages/GithubAuth/View.elm index 04f6879..837b77f 100644 --- a/src/elm/Pages/GithubAuth/View.elm +++ b/src/elm/Pages/GithubAuth/View.elm @@ -2,7 +2,6 @@ module Pages.GithubAuth.View exposing (..) -- import Config.Model exposing (BackendConfig) -- import Dict exposing (get) --- import Effects exposing (Effects) import Html exposing (a, div, i, text, Html) import Html.Attributes exposing (class, href, id) -- import Http exposing (Error) diff --git a/src/elm/Pages/Login/Test.elm b/src/elm/Pages/Login/Test.elm index a6616cf..3c85375 100644 --- a/src/elm/Pages/Login/Test.elm +++ b/src/elm/Pages/Login/Test.elm @@ -3,7 +3,6 @@ module Pages.Login.Test exposing (..) import ElmTest exposing (..) import Config.Model exposing (initialBackendConfig) -import Effects exposing (Effects) import Http exposing (Error) import Pages.Login.Model exposing (initialModel, Model) import Pages.Login.Update exposing (Msg) @@ -45,15 +44,15 @@ formSuite = , test "submit after another submit with errors" (assertEqual Pages.Login.Model.Fetching (.status <| fst(submitForm <| Pages.Login.Model.HttpError Http.NetworkError))) ] -updateName : String -> (Model, Effects Msg) +updateName : String -> (Model, Cmd Msg) updateName val = Pages.Login.Update.update updateContext (Pages.Login.Update.UpdateName val) Pages.Login.Model.initialModel -updatePass : String -> (Model, Effects Msg) +updatePass : String -> (Model, Cmd Msg) updatePass val = Pages.Login.Update.update updateContext (Pages.Login.Update.UpdatePass val) Pages.Login.Model.initialModel -submitForm : Pages.Login.Model.Status -> (Model, Effects Msg) +submitForm : Pages.Login.Model.Status -> (Model, Cmd Msg) submitForm status = let model = @@ -65,7 +64,7 @@ submitForm status = in Pages.Login.Update.update updateContext Pages.Login.Update.SubmitForm model' -setAccessToken : String -> (Model, Effects Msg) +setAccessToken : String -> (Model, Cmd Msg) setAccessToken val = Pages.Login.Update.update updateContext (Pages.Login.Update.SetAccessToken val) Pages.Login.Model.initialModel diff --git a/src/elm/Pages/Login/Update.elm b/src/elm/Pages/Login/Update.elm index ece3a3e..c97d560 100644 --- a/src/elm/Pages/Login/Update.elm +++ b/src/elm/Pages/Login/Update.elm @@ -4,7 +4,6 @@ import Pages.Login.Model exposing (initialModel, Model) import Base64 exposing (encode) import Config.Model exposing (BackendConfig) -import Effects exposing (Effects) import Http exposing (Error) import Json.Decode as JD exposing ((:=)) import Storage exposing (getItem) @@ -13,7 +12,7 @@ import Utils.Http exposing (getErrorMessageFromHttpResponse) type alias AccessToken = String -init : (Model, Effects Msg) +init : (Model, Cmd Msg) init = ( initialModel -- Try to get an existing access token. @@ -33,7 +32,7 @@ type alias Context = { backendConfig : BackendConfig } -update : Context -> Msg -> Model -> (Model, Effects Msg) +update : Context -> Msg -> Model -> (Model, Cmd Msg) update context action model = case action of UpdateName name -> @@ -42,7 +41,7 @@ update context action model = updatedLoginForm = { loginForm | name = name } in ( { model | loginForm = updatedLoginForm } - , Effects.none + , Cmd.none ) UpdatePass pass -> @@ -51,7 +50,7 @@ update context action model = updatedLoginForm = { loginForm | pass = pass } in ( {model | loginForm = updatedLoginForm } - , Effects.none + , Cmd.none ) SubmitForm -> @@ -67,11 +66,11 @@ update context action model = in if model.status == Pages.Login.Model.Fetching || model.status == Pages.Login.Model.Fetched then - (model, Effects.none) + (model, Cmd.none) else ( { model | status = Pages.Login.Model.Fetching } - , Effects.batch - [ Task.succeed (SetUserMessage Pages.Login.Model.None) |> Effects.task + , Cmd.batch + [ Task.succeed (SetUserMessage Pages.Login.Model.None) |> Cmd.task , getJson url credentials ] ) @@ -82,19 +81,19 @@ update context action model = -- This is a good time also to hide the password. , loginForm = Pages.Login.Model.LoginForm model.loginForm.name "" } - , Effects.none + , Cmd.none ) SetUserMessage userMessage -> ( { model | userMessage = userMessage } - , Effects.none + , Cmd.none ) UpdateAccessTokenFromServer result -> case result of Ok token -> ( { model | status = Pages.Login.Model.Fetched } - , Task.succeed (SetAccessToken token) |> Effects.task + , Task.succeed (SetAccessToken token) |> Cmd.task ) Err err -> let @@ -102,28 +101,28 @@ update context action model = getErrorMessageFromHttpResponse err in ( { model | status = Pages.Login.Model.HttpError err } - , Task.succeed (SetUserMessage <| Pages.Login.Model.Error message) |> Effects.task + , Task.succeed (SetUserMessage <| Pages.Login.Model.Error message) |> Cmd.task ) UpdateAccessTokenFromStorage result -> case result of Ok token -> ( model - , Task.succeed (SetAccessToken token) |> Effects.task + , Task.succeed (SetAccessToken token) |> Cmd.task ) Err err -> -- There was no access token in the storage, so show the login form ( { model | hasAccessTokenInStorage = False } - , Effects.none + , Cmd.none ) -getInputFromStorage : Effects Msg +getInputFromStorage : Cmd Msg getInputFromStorage = Storage.getItem "access_token" JD.string |> Task.toResult |> Task.map UpdateAccessTokenFromStorage - |> Effects.task + |> Cmd.task -- EFFECTS @@ -137,7 +136,7 @@ encodeCredentials (name, pass) = Ok result -> result Err err -> "" -getJson : String -> String -> Effects Msg +getJson : String -> String -> Cmd Msg getJson url credentials = Http.send Http.defaultSettings { verb = "GET" @@ -148,7 +147,7 @@ getJson url credentials = |> Http.fromJson decodeAccessToken |> Task.toResult |> Task.map UpdateAccessTokenFromServer - |> Effects.task + |> Cmd.task decodeAccessToken : JD.Decoder AccessToken diff --git a/src/elm/Pages/User/Decoder.elm b/src/elm/Pages/User/Decoder.elm index 39efd52..63b931c 100644 --- a/src/elm/Pages/User/Decoder.elm +++ b/src/elm/Pages/User/Decoder.elm @@ -1,7 +1,6 @@ module Pages.User.Decoder exposing (..) import Company.Model as Company exposing (Model) -import Effects exposing (Effects, Never) import Http exposing (Error) import Json.Decode as Json exposing ((:=)) import String diff --git a/src/elm/Pages/User/Update.elm b/src/elm/Pages/User/Update.elm index a751108..c23e6af 100644 --- a/src/elm/Pages/User/Update.elm +++ b/src/elm/Pages/User/Update.elm @@ -2,7 +2,6 @@ module Pages.User.Update exposing (..) import Config.Model exposing (BackendConfig) import Company.Model as Company exposing (initialModel, Model) -import Effects exposing (Effects, Never) import Http exposing (Error) import Pages.User.Model as User exposing (Model) import Pages.User.Decoder exposing (decode) @@ -23,17 +22,17 @@ type Msg | SetAccessToken AccessToken | UpdateDataFromServer (Result Http.Error (Id, String, List Company.Model)) -init : (Model, Effects Msg) +init : (Model, Cmd Msg) init = ( User.initialModel - , Effects.none + , Cmd.none ) -update : UpdateContext -> Msg -> Model -> (Model, Effects Msg) +update : UpdateContext -> Msg -> Model -> (Model, Cmd Msg) update context action model = case action of NoOp _ -> - (model, Effects.none) + (model, Cmd.none) GetDataFromServer -> let @@ -45,7 +44,7 @@ update context action model = in if model.status == User.Fetching || model.status == User.Fetched then - (model, Effects.none) + (model, Cmd.none) else ( { model | status = User.Fetching } , getJson url context.accessToken @@ -63,7 +62,7 @@ update context action model = , name = User.LoggedIn name , companies = companies } - , Effects.none + , Cmd.none ) Err msg -> let @@ -72,11 +71,11 @@ update context action model = Http.BadResponse code _ -> if (code == 401) -- Token is wrong, so remove any existing one. - then Task.succeed (SetAccessToken "") |> Effects.task - else Effects.none + then Task.succeed (SetAccessToken "") |> Cmd.task + else Cmd.none _ -> - Effects.none + Cmd.none in ( { model' | status = User.HttpError msg } @@ -85,12 +84,12 @@ update context action model = SetAccessToken accessToken -> ( {model | accessToken = accessToken} - , Effects.none + , Cmd.none ) --- Effects +-- Cmd -getJson : String -> AccessToken -> Effects Action +getJson : String -> AccessToken -> Cmd Action getJson url accessToken = let encodedUrl = Http.url url [ ("access_token", accessToken) ] @@ -98,4 +97,4 @@ getJson url accessToken = Http.get decode encodedUrl |> Task.toResult |> Task.map UpdateDataFromServer - |> Effects.task + |> Cmd.task From 93bc78b876773674e2f39a0f1effebcb86f403a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hern=C3=A1ndez?= Date: Wed, 9 Nov 2016 18:02:53 +0100 Subject: [PATCH 04/10] Removes all previous code to start from zero. --- README.md | 22 - bower.json | 20 - elm-package.json | 23 - gulpfile.js | 240 -- package.json | 44 - runTests.js | 18 - src/assets/images/default@2x.png | Bin 2565 -> 0 bytes src/assets/images/selected@2x.png | Bin 2446 -> 0 bytes src/assets/scss/_article-page.scss | 84 - src/assets/scss/_events-page.scss | 90 - src/assets/scss/_footer.scss | 41 - src/assets/scss/_header.scss | 128 - src/assets/scss/_login.scss | 71 - src/assets/scss/_mixin.scss | 13 - src/assets/scss/_my-account.scss | 35 - src/assets/scss/_page-not-found.scss | 17 - src/assets/scss/style.scss | 103 - src/elm/App/Model.elm | 53 - src/elm/App/Router.elm | 65 - src/elm/App/Update.elm | 368 --- src/elm/App/View.elm | 200 -- src/elm/Article/Decoder.elm | 36 - src/elm/Article/Model.elm | 16 - src/elm/ArticleForm/Model.elm | 35 - src/elm/ArticleForm/Update.elm | 171 -- src/elm/ArticleForm/View.elm | 80 - src/elm/ArticleList/Model.elm | 25 - src/elm/ArticleList/Update.elm | 135 - src/elm/ArticleList/View.elm | 50 - src/elm/Company/Model.elm | 14 - src/elm/Config.elm | 29 - src/elm/Config/Model.elm | 28 - src/elm/Config/Test.elm | 24 - src/elm/Config/Update.elm | 50 - src/elm/Config/View.elm | 13 - src/elm/Event/Decoder.elm | 36 - src/elm/Event/Model.elm | 20 - src/elm/EventAuthorFilter/Model.elm | 6 - src/elm/EventAuthorFilter/Update.elm | 19 - src/elm/EventAuthorFilter/View.elm | 80 - src/elm/EventCompanyFilter/Model.elm | 6 - src/elm/EventCompanyFilter/Test.elm | 34 - src/elm/EventCompanyFilter/Update.elm | 37 - src/elm/EventCompanyFilter/View.elm | 66 - src/elm/EventList/Model.elm | 12 - src/elm/EventList/Update.elm | 29 - src/elm/EventList/Utils.elm | 19 - src/elm/EventList/View.elm | 82 - src/elm/Leaflet/Model.elm | 20 - src/elm/Leaflet/Update.elm | 35 - src/elm/Leaflet/View.elm | 20 - src/elm/Main.elm | 108 - src/elm/Pages/Article/Model.elm | 15 - src/elm/Pages/Article/Update.elm | 61 - src/elm/Pages/Article/View.elm | 26 - src/elm/Pages/Event/Model.elm | 38 - src/elm/Pages/Event/Router.elm | 28 - src/elm/Pages/Event/Update.elm | 260 -- src/elm/Pages/Event/Utils.elm | 13 - src/elm/Pages/Event/View.elm | 63 - src/elm/Pages/GithubAuth/Model.elm | 25 - src/elm/Pages/GithubAuth/Update.elm | 115 - src/elm/Pages/GithubAuth/View.elm | 35 - src/elm/Pages/Login/Model.elm | 39 - src/elm/Pages/Login/Test.elm | 82 - src/elm/Pages/Login/Update.elm | 155 - src/elm/Pages/Login/View.elm | 134 - src/elm/Pages/PageNotFound/View.elm | 23 - src/elm/Pages/User/Decoder.elm | 28 - src/elm/Pages/User/Model.elm | 37 - src/elm/Pages/User/Update.elm | 100 - src/elm/Pages/User/View.elm | 42 - src/elm/TestRunner.elm | 22 - src/elm/Utils/Http.elm | 23 - src/index.html | 38 - src/js/elm-interop.js | 270 -- src/vendor/elm-param-parsing/.gitignore | 7 - src/vendor/elm-param-parsing/README.md | 46 - src/vendor/elm-param-parsing/build | 1 - src/vendor/elm-param-parsing/elm-package.json | 16 - .../src/UrlParameterParser.elm | 68 - .../elm-param-parsing/src/UrlParseUtil.elm | 20 - src/vendor/elm-param-parsing/test.sh | 4 - src/vendor/elm-storage/Example.elm | 49 - src/vendor/elm-storage/README.md | 11 - src/vendor/elm-storage/elm-package.json | 16 - src/vendor/elm-storage/example/.gitignore | 2 - src/vendor/elm-storage/example/App.elm | 92 - src/vendor/elm-storage/example/Main.elm | 24 - .../elm-storage/example/elm-package.json | 19 - src/vendor/elm-storage/src/Native/Storage.js | 2595 ----------------- src/vendor/elm-storage/src/Storage.elm | 39 - src/vendor/elm-web-api/.gitignore | 6 - src/vendor/elm-web-api/.travis.yml | 20 - src/vendor/elm-web-api/README.md | 1271 -------- src/vendor/elm-web-api/elm-package.json | 26 - .../elm-web-api/examples/elm-package.json | 19 - src/vendor/elm-web-api/examples/package.json | 24 - .../examples/src/LocationExample.elm | 78 - .../examples/src/StorageExample.elm | 669 ----- .../examples/src/WindowExample.elm | 123 - .../src/Native/WebAPI/AnimationFrame.js | 79 - .../elm-web-api/src/Native/WebAPI/Cookie.js | 41 - .../elm-web-api/src/Native/WebAPI/Date.js | 148 - .../elm-web-api/src/Native/WebAPI/Document.js | 58 - .../elm-web-api/src/Native/WebAPI/Location.js | 63 - .../elm-web-api/src/Native/WebAPI/Math.js | 30 - .../elm-web-api/src/Native/WebAPI/Number.js | 71 - .../elm-web-api/src/Native/WebAPI/Screen.js | 51 - .../elm-web-api/src/Native/WebAPI/Storage.js | 109 - .../elm-web-api/src/Native/WebAPI/Window.js | 53 - .../elm-web-api/src/WebAPI/AnimationFrame.elm | 63 - src/vendor/elm-web-api/src/WebAPI/Cookie.elm | 140 - src/vendor/elm-web-api/src/WebAPI/Date.elm | 426 --- .../elm-web-api/src/WebAPI/Document.elm | 62 - .../elm-web-api/src/WebAPI/Location.elm | 63 - src/vendor/elm-web-api/src/WebAPI/Math.elm | 83 - src/vendor/elm-web-api/src/WebAPI/Number.elm | 160 - src/vendor/elm-web-api/src/WebAPI/Screen.elm | 52 - src/vendor/elm-web-api/src/WebAPI/Storage.elm | 271 -- src/vendor/elm-web-api/src/WebAPI/Window.elm | 57 - .../elm-web-api/test/0.15/elm-package.json | 23 - src/vendor/elm-web-api/test/0.15/package.json | 27 - .../elm-web-api/test/0.16/elm-package.json | 20 - src/vendor/elm-web-api/test/0.16/package.json | 24 - src/vendor/elm-web-api/test/ci.sh | 12 - src/vendor/elm-web-api/test/package.json | 32 - src/vendor/elm-web-api/test/src/config.js | 33 - .../elm-web-api/test/src/elm/Browser.elm | 25 - src/vendor/elm-web-api/test/src/elm/CI.elm | 31 - .../elm-web-api/test/src/elm/CommandLine.elm | 27 - .../test/src/elm/Native/TestUtil.js | 40 - .../elm-web-api/test/src/elm/TestMailbox.elm | 9 - .../elm-web-api/test/src/elm/TestUtil.elm | 17 - src/vendor/elm-web-api/test/src/elm/Tests.elm | 42 - .../src/elm/WebAPI/AnimationFrameTest.elm | 111 - .../test/src/elm/WebAPI/CookieTest.elm | 158 - .../test/src/elm/WebAPI/DateTest.elm | 386 --- .../test/src/elm/WebAPI/DocumentTest.elm | 77 - .../test/src/elm/WebAPI/LocationTest.elm | 45 - .../test/src/elm/WebAPI/MathTest.elm | 46 - .../test/src/elm/WebAPI/NumberTest.elm | 73 - .../test/src/elm/WebAPI/ScreenTest.elm | 55 - .../test/src/elm/WebAPI/StorageTest.elm | 104 - src/vendor/elm-web-api/test/src/elm/shim.js | 14 - .../elm-web-api/test/src/mocha/browser.js | 41 - .../elm-web-api/test/src/mocha/elmTest.js | 30 - .../test/src/mocha/locationTest.js | 40 - .../elm-web-api/test/src/mocha/storageTest.js | 116 - .../elm-web-api/test/src/mocha/windowTest.js | 166 -- src/vendor/elm-web-api/test/src/remote.js | 131 - src/vendor/elm-web-api/test/src/run.js | 23 - .../elm-web-api/test/src/selenium-sauce.js | 238 -- 153 files changed, 14183 deletions(-) delete mode 100644 README.md delete mode 100644 bower.json delete mode 100644 elm-package.json delete mode 100644 gulpfile.js delete mode 100644 package.json delete mode 100644 runTests.js delete mode 100644 src/assets/images/default@2x.png delete mode 100644 src/assets/images/selected@2x.png delete mode 100644 src/assets/scss/_article-page.scss delete mode 100644 src/assets/scss/_events-page.scss delete mode 100644 src/assets/scss/_footer.scss delete mode 100644 src/assets/scss/_header.scss delete mode 100644 src/assets/scss/_login.scss delete mode 100644 src/assets/scss/_mixin.scss delete mode 100644 src/assets/scss/_my-account.scss delete mode 100644 src/assets/scss/_page-not-found.scss delete mode 100644 src/assets/scss/style.scss delete mode 100644 src/elm/App/Model.elm delete mode 100644 src/elm/App/Router.elm delete mode 100644 src/elm/App/Update.elm delete mode 100644 src/elm/App/View.elm delete mode 100644 src/elm/Article/Decoder.elm delete mode 100644 src/elm/Article/Model.elm delete mode 100644 src/elm/ArticleForm/Model.elm delete mode 100644 src/elm/ArticleForm/Update.elm delete mode 100644 src/elm/ArticleForm/View.elm delete mode 100644 src/elm/ArticleList/Model.elm delete mode 100644 src/elm/ArticleList/Update.elm delete mode 100644 src/elm/ArticleList/View.elm delete mode 100644 src/elm/Company/Model.elm delete mode 100644 src/elm/Config.elm delete mode 100644 src/elm/Config/Model.elm delete mode 100644 src/elm/Config/Test.elm delete mode 100644 src/elm/Config/Update.elm delete mode 100644 src/elm/Config/View.elm delete mode 100644 src/elm/Event/Decoder.elm delete mode 100644 src/elm/Event/Model.elm delete mode 100644 src/elm/EventAuthorFilter/Model.elm delete mode 100644 src/elm/EventAuthorFilter/Update.elm delete mode 100644 src/elm/EventAuthorFilter/View.elm delete mode 100644 src/elm/EventCompanyFilter/Model.elm delete mode 100644 src/elm/EventCompanyFilter/Test.elm delete mode 100644 src/elm/EventCompanyFilter/Update.elm delete mode 100644 src/elm/EventCompanyFilter/View.elm delete mode 100644 src/elm/EventList/Model.elm delete mode 100644 src/elm/EventList/Update.elm delete mode 100644 src/elm/EventList/Utils.elm delete mode 100644 src/elm/EventList/View.elm delete mode 100644 src/elm/Leaflet/Model.elm delete mode 100644 src/elm/Leaflet/Update.elm delete mode 100644 src/elm/Leaflet/View.elm delete mode 100644 src/elm/Main.elm delete mode 100644 src/elm/Pages/Article/Model.elm delete mode 100644 src/elm/Pages/Article/Update.elm delete mode 100644 src/elm/Pages/Article/View.elm delete mode 100644 src/elm/Pages/Event/Model.elm delete mode 100644 src/elm/Pages/Event/Router.elm delete mode 100644 src/elm/Pages/Event/Update.elm delete mode 100644 src/elm/Pages/Event/Utils.elm delete mode 100644 src/elm/Pages/Event/View.elm delete mode 100644 src/elm/Pages/GithubAuth/Model.elm delete mode 100644 src/elm/Pages/GithubAuth/Update.elm delete mode 100644 src/elm/Pages/GithubAuth/View.elm delete mode 100644 src/elm/Pages/Login/Model.elm delete mode 100644 src/elm/Pages/Login/Test.elm delete mode 100644 src/elm/Pages/Login/Update.elm delete mode 100644 src/elm/Pages/Login/View.elm delete mode 100644 src/elm/Pages/PageNotFound/View.elm delete mode 100644 src/elm/Pages/User/Decoder.elm delete mode 100644 src/elm/Pages/User/Model.elm delete mode 100644 src/elm/Pages/User/Update.elm delete mode 100644 src/elm/Pages/User/View.elm delete mode 100644 src/elm/TestRunner.elm delete mode 100644 src/elm/Utils/Http.elm delete mode 100644 src/index.html delete mode 100644 src/js/elm-interop.js delete mode 100644 src/vendor/elm-param-parsing/.gitignore delete mode 100644 src/vendor/elm-param-parsing/README.md delete mode 100755 src/vendor/elm-param-parsing/build delete mode 100644 src/vendor/elm-param-parsing/elm-package.json delete mode 100644 src/vendor/elm-param-parsing/src/UrlParameterParser.elm delete mode 100644 src/vendor/elm-param-parsing/src/UrlParseUtil.elm delete mode 100755 src/vendor/elm-param-parsing/test.sh delete mode 100644 src/vendor/elm-storage/Example.elm delete mode 100644 src/vendor/elm-storage/README.md delete mode 100644 src/vendor/elm-storage/elm-package.json delete mode 100644 src/vendor/elm-storage/example/.gitignore delete mode 100644 src/vendor/elm-storage/example/App.elm delete mode 100644 src/vendor/elm-storage/example/Main.elm delete mode 100644 src/vendor/elm-storage/example/elm-package.json delete mode 100644 src/vendor/elm-storage/src/Native/Storage.js delete mode 100644 src/vendor/elm-storage/src/Storage.elm delete mode 100644 src/vendor/elm-web-api/.gitignore delete mode 100644 src/vendor/elm-web-api/.travis.yml delete mode 100644 src/vendor/elm-web-api/README.md delete mode 100644 src/vendor/elm-web-api/elm-package.json delete mode 100644 src/vendor/elm-web-api/examples/elm-package.json delete mode 100644 src/vendor/elm-web-api/examples/package.json delete mode 100644 src/vendor/elm-web-api/examples/src/LocationExample.elm delete mode 100644 src/vendor/elm-web-api/examples/src/StorageExample.elm delete mode 100644 src/vendor/elm-web-api/examples/src/WindowExample.elm delete mode 100644 src/vendor/elm-web-api/src/Native/WebAPI/AnimationFrame.js delete mode 100644 src/vendor/elm-web-api/src/Native/WebAPI/Cookie.js delete mode 100644 src/vendor/elm-web-api/src/Native/WebAPI/Date.js delete mode 100644 src/vendor/elm-web-api/src/Native/WebAPI/Document.js delete mode 100644 src/vendor/elm-web-api/src/Native/WebAPI/Location.js delete mode 100644 src/vendor/elm-web-api/src/Native/WebAPI/Math.js delete mode 100644 src/vendor/elm-web-api/src/Native/WebAPI/Number.js delete mode 100644 src/vendor/elm-web-api/src/Native/WebAPI/Screen.js delete mode 100644 src/vendor/elm-web-api/src/Native/WebAPI/Storage.js delete mode 100644 src/vendor/elm-web-api/src/Native/WebAPI/Window.js delete mode 100644 src/vendor/elm-web-api/src/WebAPI/AnimationFrame.elm delete mode 100644 src/vendor/elm-web-api/src/WebAPI/Cookie.elm delete mode 100644 src/vendor/elm-web-api/src/WebAPI/Date.elm delete mode 100644 src/vendor/elm-web-api/src/WebAPI/Document.elm delete mode 100644 src/vendor/elm-web-api/src/WebAPI/Location.elm delete mode 100644 src/vendor/elm-web-api/src/WebAPI/Math.elm delete mode 100644 src/vendor/elm-web-api/src/WebAPI/Number.elm delete mode 100644 src/vendor/elm-web-api/src/WebAPI/Screen.elm delete mode 100644 src/vendor/elm-web-api/src/WebAPI/Storage.elm delete mode 100644 src/vendor/elm-web-api/src/WebAPI/Window.elm delete mode 100644 src/vendor/elm-web-api/test/0.15/elm-package.json delete mode 100644 src/vendor/elm-web-api/test/0.15/package.json delete mode 100644 src/vendor/elm-web-api/test/0.16/elm-package.json delete mode 100644 src/vendor/elm-web-api/test/0.16/package.json delete mode 100644 src/vendor/elm-web-api/test/ci.sh delete mode 100644 src/vendor/elm-web-api/test/package.json delete mode 100644 src/vendor/elm-web-api/test/src/config.js delete mode 100644 src/vendor/elm-web-api/test/src/elm/Browser.elm delete mode 100644 src/vendor/elm-web-api/test/src/elm/CI.elm delete mode 100644 src/vendor/elm-web-api/test/src/elm/CommandLine.elm delete mode 100644 src/vendor/elm-web-api/test/src/elm/Native/TestUtil.js delete mode 100644 src/vendor/elm-web-api/test/src/elm/TestMailbox.elm delete mode 100644 src/vendor/elm-web-api/test/src/elm/TestUtil.elm delete mode 100644 src/vendor/elm-web-api/test/src/elm/Tests.elm delete mode 100644 src/vendor/elm-web-api/test/src/elm/WebAPI/AnimationFrameTest.elm delete mode 100644 src/vendor/elm-web-api/test/src/elm/WebAPI/CookieTest.elm delete mode 100644 src/vendor/elm-web-api/test/src/elm/WebAPI/DateTest.elm delete mode 100644 src/vendor/elm-web-api/test/src/elm/WebAPI/DocumentTest.elm delete mode 100644 src/vendor/elm-web-api/test/src/elm/WebAPI/LocationTest.elm delete mode 100644 src/vendor/elm-web-api/test/src/elm/WebAPI/MathTest.elm delete mode 100644 src/vendor/elm-web-api/test/src/elm/WebAPI/NumberTest.elm delete mode 100644 src/vendor/elm-web-api/test/src/elm/WebAPI/ScreenTest.elm delete mode 100644 src/vendor/elm-web-api/test/src/elm/WebAPI/StorageTest.elm delete mode 100644 src/vendor/elm-web-api/test/src/elm/shim.js delete mode 100644 src/vendor/elm-web-api/test/src/mocha/browser.js delete mode 100644 src/vendor/elm-web-api/test/src/mocha/elmTest.js delete mode 100644 src/vendor/elm-web-api/test/src/mocha/locationTest.js delete mode 100644 src/vendor/elm-web-api/test/src/mocha/storageTest.js delete mode 100644 src/vendor/elm-web-api/test/src/mocha/windowTest.js delete mode 100644 src/vendor/elm-web-api/test/src/remote.js delete mode 100644 src/vendor/elm-web-api/test/src/run.js delete mode 100644 src/vendor/elm-web-api/test/src/selenium-sauce.js diff --git a/README.md b/README.md deleted file mode 100644 index 1e2db69..0000000 --- a/README.md +++ /dev/null @@ -1,22 +0,0 @@ -[![Build Status](https://travis-ci.org/Gizra/elm-hedley.svg?branch=master)](https://travis-ci.org/Gizra/elm-hedley) - -# elm-hedley - -An Elm single page application. The server side code is [here](https://github.com/Gizra/hedley-server). - -[Read more](http://www.gizra.com/content/elm-hedley-overview/) about this project. - -## Install - -Install Elm v0.16.0 (`npm install -g elm@0.16.0`) - -``` -npm install && bower install -elm-package install -y -``` - -Execute with `gulp` - -## Testing - -In order to view the tests on the browser Start elm reactor (`elm-reactor`) and navigate to [http://localhost:8000/src/elm/TestRunner.elm](http://localhost:8000/src/elm/TestRunner.elm) diff --git a/bower.json b/bower.json deleted file mode 100644 index 5d5724e..0000000 --- a/bower.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "elm-hedley", - "version": "0.1.0", - "homepage": "https://github.com/amitaibu/elm-login", - "authors": [ - "Amitai Burstein " - ], - "license": "MIT", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "test", - "tests" - ], - "dependencies": { - "dropzone": "~4.2.0", - "leaflet": "~0.7.5" - } -} diff --git a/elm-package.json b/elm-package.json deleted file mode 100644 index c9891af..0000000 --- a/elm-package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "version": "1.0.0", - "summary": "helpful summary of your project, less than 80 characters", - "repository": "https://github.com/gizra/elm-hedley.git", - "license": "BSD3", - "source-directories": [ - "src/elm", - "src/vendor/elm-param-parsing/src", - "src/vendor/elm-storage/src", - "src/vendor/elm-web-api/src" - ], - "exposed-modules": [], - "native-modules": true, - "dependencies": { - "elm-community/elm-test": "2.1.0 <= v < 3.0.0", - "elm-lang/core": "4.0.5 <= v < 5.0.0", - "elm-lang/html": "1.1.0 <= v < 2.0.0", - "evancz/elm-http": "3.0.1 <= v < 4.0.0", - "rgrempel/elm-route-url": "2.0.1 <= v < 3.0.0", - "truqu/elm-base64": "1.0.3 <= v < 2.0.0" - }, - "elm-version": "0.17.0 <= v < 0.18.0" -} diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index 6b4ac25..0000000 --- a/gulpfile.js +++ /dev/null @@ -1,240 +0,0 @@ -// Generated on 2015-05-04 using generator-jekyllized 0.7.3 -"use strict"; - -var gulp = require("gulp"); - -var gulpSequence = require('gulp-sequence'); - -// Loads the plugins without having to list all of them, but you need -// to call them as $.pluginname -var $ = require("gulp-load-plugins")(); -// "del" is used to clean out directories and such -var del = require("del"); -// BrowserSync isn"t a gulp package, and needs to be loaded manually -var browserSync = require("browser-sync"); - -var elm = require('gulp-elm'); - -var fs = require('fs'); - -var ga = require('gulp-ga'); - -// merge is used to merge the output from two different streams into the same stream -var merge = require("merge-stream"); -// Need a command for reloading webpages using BrowserSync - -var plumber = require("gulp-plumber"); - -var reload = browserSync.reload; -// And define a variable that BrowserSync uses in its function -var bs; - -var wiredep = require('wiredep').stream; - -// Deletes the directory that is used to serve the site during development -gulp.task("clean:dev", function(cb) { - return del(["serve"], cb); -}); - - -// Deletes the directory that the optimized site is output to -gulp.task("clean:prod", function(cb) { - return del(["dist"], cb); -}); - - -// Compiles the SASS files and moves them into the "assets/stylesheets" directory -gulp.task("styles", function () { - // Looks at the style.scss file for what to include and creates a style.css file - return gulp.src("src/assets/scss/style.scss") - .pipe(plumber()) - .pipe($.sass()) - .on('error', function(err){ - browserSync.notify("SASS error"); - - console.error(err.message); - - // Save the error to index.html, with a simple HTML wrapper - // so browserSync can inject itself in. - fs.writeFileSync('serve/index.html', "
" + err.message + "
"); - - // No need to continue processing. - this.emit('end'); - }) - // AutoPrefix your CSS so it works between browsers - .pipe($.autoprefixer("last 1 version", { cascade: true })) - // Directory your CSS file goes to - .pipe(gulp.dest("serve/assets/stylesheets/")) - // Outputs the size of the CSS file - .pipe($.size({title: "styles"})) - // Injects the CSS changes to your browser since Jekyll doesn"t rebuild the CSS - .pipe(reload({stream: true})); -}); - -// Optimizes the images that exists -gulp.task("images", function () { - return gulp.src("src/assets/images/**") - .pipe($.changed("dist/assets/images")) - .pipe($.imagemin({ - // Lossless conversion to progressive JPGs - progressive: true, - // Interlace GIFs for progressive rendering - interlaced: true - })) - .pipe(gulp.dest("dist/assets/images")) - .pipe($.size({title: "images"})); -}); - -// Copy over fonts to the "dist" directory -gulp.task("fonts", function () { - return gulp.src("src/assets/fonts/**") - .pipe(gulp.dest("dist/assets/fonts")) - .pipe($.size({ title: "fonts" })); -}); - -// Copy index.html and CNAME files to the "serve" directory -gulp.task("copy:dev", ["copy:bower"], function () { - return gulp.src(["src/index.html", "src/CNAME", "src/js/**/*", "src/assets/images/**/*"]) - .pipe(gulp.dest("serve")) - .pipe($.size({ title: "index.html & CNAME" })) -}); - -// Copy bower. -gulp.task("copy:bower", function () { - return gulp.src(["bower_components/**/*"]) - .pipe(gulp.dest("serve/bower_components")) - .pipe($.size({ title: "Bower" })) -}); - -// Copy images. -gulp.task("copy:images", function () { - return gulp.src([]) - .pipe(gulp.dest("serve/assets/images")) - .pipe($.size({ title: "Assets images" })) -}); - - -gulp.task("cname", function () { - return gulp.src(["serve/CNAME"]) - .pipe(gulp.dest("dist")) - .pipe($.size({ title: "CNAME" })) -}); - -gulp.task('bower', function () { - gulp.src("src/index.html") - .pipe(wiredep()) - .pipe(gulp.dest("serve")); -}); - -gulp.task('ga', function(){ - gulp.src('src/index.html') - .pipe(ga({ - anonymizeIp: false, - sendPageView: true, - url: 'auto', - uid: 'UA-6558346-13' - })) - .pipe(gulp.dest('serve')); -}); - - -// Optimizes all the CSS, HTML and concats the JS etc -gulp.task("minify", ["styles"], function () { - var assets = $.useref.assets({searchPath: "serve"}); - - return gulp.src("serve/**/*.*") - // Concatenate JavaScript files and preserve important comments - .pipe($.if("*.js", $.uglify({preserveComments: "some"}))) - // Minify CSS - .pipe($.if("*.css", $.minifyCss())) - // Start cache busting the files - .pipe($.revAll({ ignore: ["index.html", ".eot", ".svg", ".ttf", ".woff"] })) - .pipe(assets.restore()) - // Replace the asset names with their cache busted names - .pipe($.revReplace()) - // Minify HTML - .pipe($.if("*.html", $.htmlmin({ - removeComments: true, - removeCommentsFromCDATA: true, - removeCDATASectionsFromCDATA: true, - collapseWhitespace: true, - collapseBooleanAttributes: true, - removeAttributeQuotes: true, - removeRedundantAttributes: true - }))) - // Send the output to the correct folder - .pipe(gulp.dest("dist")) - .pipe($.size({title: "optimizations"})); -}); - - -// Task to upload your site to your GH Pages repo -gulp.task("deploy", [], function () { - // Deploys your optimized site, you can change the settings in the html task if you want to - return gulp.src("dist/**/*") - .pipe($.ghPages({branch: "gh-pages", cacheDir: ".publish"})); -}); - -gulp.task('elm-init', elm.init); -gulp.task('elm', ['elm-init'], function(){ - return gulp.src('src/elm/Main.elm') - .pipe(plumber()) - .pipe(elm()) - .on('error', function(err) { - console.error(err.message); - - browserSync.notify("Elm compile error", 5000); - - // Save the error to index.html, with a simple HTML wrapper - // so browserSync can inject itself in. - fs.writeFileSync('serve/index.html', "
" + err.message + "
"); - }) - .pipe(gulp.dest('serve')); -}); - -// BrowserSync will serve our site on a local server for us and other devices to use -// It will also autoreload across all devices as well as keep the viewport synchronized -// between them. -gulp.task("serve:dev", ["build"], function () { - bs = browserSync({ - notify: true, - // tunnel: "", - server: { - baseDir: "serve" - } - }); -}); - - -// These tasks will look for files that change while serving and will auto-regenerate or -// reload the website accordingly. Update or add other files you need to be watched. -gulp.task("watch", function () { - // We need to copy dev, so index.html may be replaced by error messages. - gulp.watch(["src/index.html", "src/js/**/*.js"], ["copy:dev", reload]); - gulp.watch(["src/elm/**/*.elm"], ["elm", "copy:dev", reload]); - gulp.watch(["src/assets/scss/**/*.scss"], ["styles", "copy:dev", reload]); -}); - -// Serve the site after optimizations to see that everything looks fine -gulp.task("serve:prod", function () { - bs = browserSync({ - notify: false, - // tunnel: true, - server: { - baseDir: "dist" - } - }); -}); - -// Default task, run when just writing "gulp" in the terminal -gulp.task("default", ["serve:dev", "watch"]); - -// Builds the site but doesnt serve it to you -// @todo: Add "bower" here -gulp.task("build", gulpSequence("clean:dev", ["styles", "copy:dev", "elm"], "ga")); - -// Builds your site with the "build" command and then runs all the optimizations on -// it and outputs it to "./dist" -gulp.task("publish", ["build", "clean:prod"], function () { - gulp.start("minify", "cname", "images", "fonts"); -}); diff --git a/package.json b/package.json deleted file mode 100644 index c48cddc..0000000 --- a/package.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "generated-elm", - "private": false, - "version": "0.1.0", - "description": "Generated elm", - "dependencies": {}, - "devDependencies": { - "browser-sync": "1.9.2", - "del": "1.2.1", - "gulp": "~3.9.0", - "gulp-autoprefixer": "2.3.1", - "gulp-cache": "0.2.10", - "gulp-cached": "1.0.1", - "gulp-changed": "1.0.0", - "gulp-elm": "0.2.0", - "gulp-filter": "2.0.2", - "gulp-ga": "0.0.7", - "gulp-gh-pages": "0.4.0", - "gulp-gzip": "0.0.8", - "gulp-htmlmin": "0.2.0", - "gulp-if": "1.2.5", - "gulp-imagemin": "2.3.0", - "gulp-jshint": "1.11.2", - "gulp-load-plugins": "0.8.1", - "gulp-minify-css": "0.3.13", - "gulp-plumber": "1.0.1", - "gulp-rev-all": "0.7.6", - "gulp-rev-replace": "0.3.4", - "gulp-sass": "2.1.0", - "gulp-sequence": "0.4.1", - "gulp-shell": "0.2.11", - "gulp-size": "1.3.0", - "gulp-uglify": "1.4.1", - "gulp-uncss": "0.5.2", - "gulp-useref": "1.3.0", - "jshint-stylish": "1.0.2", - "merge-stream": "0.1.8", - "wiredep": "2.2.2" - }, - "engines": { - "node": ">0.10.0" - }, - "scripts": {} -} diff --git a/runTests.js b/runTests.js deleted file mode 100644 index 1d82418..0000000 --- a/runTests.js +++ /dev/null @@ -1,18 +0,0 @@ -var url = 'http://127.0.0.1:8080/test.html'; - -casper.options.waitTimeout = 60000; - -casper.test.begin('Run the Elm tests', function suite(test) { - casper.start(url).then(function() { - // The test runner doesn't provide a class, so we have to do this query - // selector. - casper.waitForSelector('body > div > div > div', function() { - test.assertSelectorHasText('body > div > div > div', 'All tests passed'); - }); - - }); - - casper.run(function() { - test.done(); - }); -}); diff --git a/src/assets/images/default@2x.png b/src/assets/images/default@2x.png deleted file mode 100644 index 06cfe3a37cc5fcf609c5ec60ba13b05dd2d38db7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2565 zcmY*bc|6oxAO0zdDZ81lXxwY;+c5UQ7~6GGAxm7wGWIQ{wBRP| zwWheCyct`zq)?>Njmq+ly6=78_k2F*e81;8&v~Bj_xyEIZO@(I2SGpp0PtIw6YMxq zfisc3M>uQMnTixn;Py4LHUfZ#tYbSKJe)n$%iPWy0AiE@AmI`KeC0q1D*zCI27ov2 z0DxryfCR0ijfmqM@X^f4;Q(+<^k8xUMJ18|z(w{WInW)ft*~ApK}Zkp5Kjs+Du~8m z0{|`x%SnSMbPs4$P+)L4HcB7%oq^@#2QUf-{Z63==))YWZJ{P1VH79^sf|R#3_wsQ z6c^_0gS8`={e7LY(}z*%bQ%_gij0gzMrt8L!hBI0y1Ke3v?fYZ6Tx91!lQ%f9#M$k zaD^Wt|Ir~(!o9-$Xmr1jVCaFahi6CxT^|NJF#2cwsFUvJ^Ixan@W0#QG>AGlL1`e- zsDHFMS8)d@)+Wr4!f`&(H_*U+XZ|1dw+{|=VE#YF{OI&M%4yXAghT!FYz82!-jiei z;1#zZ7?B+Kh8R^-(DF%MbWmx<{b8ha-2#LH%4 z3XoSMZTG5FGt=VQQ8S{`p(78t-S~z1sTj%IcoHc0P>tZbskgK5GP*(-TWu2(N#YUH zv!%1qzjSSE>HEBv{3ZwfHO(Q)nqO2j*n6>~&uZ5oUA5@CzsSq=SgDP|Zf_HQW=8wG z4e{YXUlmcAR=9$(PC+?(}o~PbT1)0dtC#GMnZGWg9nje$%LZDah!WJ8Sd7>BOhcoRp z=ENwU^S1I_9CT9<$jtZc>BhgPl??$lX#{uWOiOGAn`?anO z^96DJ=7+Y(JVxO=jJ{;U7ia?PqyteA66&tDm3n)}f$&=}d1IxW{2Sr755N7{r*V@OcpbW^(G=s4M2SuJs337a|9OU~) zis0jO_ilYs`&e3J^Ub6SIKK1XYAw0`8eKKP`J{}Wr~*>@>Pr&eVoY2fi(>LTB0P1VM)N5=#8#^>KwPo*ne{ z(?i!uBbev+aiz25D@&8p54_6?r?I7Ec1GRpSj!O+@KfGfwqrso8o&oIG?`aSad9!Z ze@aR;!<33F{nV}w6-?Gtgup5f`X#Nw*|oJ^NaJ!@MAO8QdMtS?nI|FruA z=mg>vgdLFC5$YG!WdxQbz^O;k%+X|qAA1`0^3SHGEvN=xp8XWr-0 zZWeuq1g*Y#7f3x8si6`oXTF4poo;fkSsoefInVkOSkoB8!)PdFXkXQU`=pbgMFXyi zx=fm5xD=h31brk89#{W^-a{H1{IEMIqbzKF=kQwuOpzhuZAghFL+sa>)Ebj3&e0v| zmZ>=v(Bf=E_peq4McsK-7*8h`f15i$uj9v+7*F%eu6QMSIvUPU14gBp@F~?UWxm{H zy7p*#vzfP+Mbq4fFiO(=Vr?icU0PZ|^|<=lWCymDDIy!@vLE(Tj4j2A??QHJ#Ffb4 zzhV;1+AcrrA(eSL8qtEi?oLSiZWuqg*L+@uMlvmaci&~rHpIAdqp>&pp38)ko~d`t zkWx=V&lP&s%xpbu-27G)K`g-|qG{-e-Q2%&;{@;Hdcisxa};0r3)xTLh0yM^RhEAU zkY{Dpr=>p{RL>p?HeTClQ~e#4N1KB(gsj~kZOZ5qws5P(J`SoM!3tA|c=A4}qZ8tE zv>aSiFLd01%D~TF&r*6T;u41XiOj5JcZRF2Z6^YT9yyzxS3Mg9mU%k*Ly3cRr+JSj zMK`towPwzE&t}M(id$Lh6sSg~jn3$srGmwzZ(Sy3`Omaywk8TN+>>TtZbvQ}iAGe3 z8ozw@$nZi?mo^?Dj#*wRoeFnckDRfh-*j+F--Hv)L-uoz8t2LP*!J=0$E2^dXT9q=b{r0+29^J@&6#ebbYt1=b!s^5&aE>T^H+Es+=P@V8-||9pw|}v| z6Z9I>Z`R`Mob{w0tBNlM0Ehtdl%SHeCZajC5&bgd)p$hK!-B-nhA&gbo7+_>lw|CJ zN_JiHqxcTop8p~%@S1r-z5t=c^}0(>x!N}O*#bg~fezC}E%d$4x6n@mF&TooVFa|~ znqXSweeC0Br*--w%}y1B$OgJJMc4nH89CtF8K>7|Sq^KM=kFC5Pr)$fQ!|CM2Oml_ z#t*aH0$(iA5Ys1E)cV$sgTt6Cu1$J#9e+7I3z1ST`BxTykgVHyDrmGnx0KOKD{M@dYG%@>p{AdS%1tRAI1TR}n1$W2h~-UT?0{C+l{fo8z36<(gUVx1+(O1O zxnt*(om9>#+^=<|4vs0c7!Sqm3npx17cafBUtOKp9p7KlMMC$uT+S+O?s?9vnU=BP2@NGL~F5iQIaS~oX6Ya0pR{6$Tme%w1-h`ob3T1N(%sZ@c^(Xf_O6k z5RL|bIWhoXasc2kqd@3{6&-*XHts9{fE?JHVnAMj5&(#~2fC2hBzq!;N~a+yzH}cy zB$vhzu>k(n3O67%mR}m4OlEdoT(P`$}O4taPR;&n}I>0I2;a=V~C_P&!hBBO-)f~1C)V*o`|8xiVS5_ zxO$_B=bY)_ZsLl0-;;P5@8zsH|-vIG79>lDiRt1VH3sJ#=E zJ`#=kTU&G$yN6;oh@viWHE1eeVoM%`SqcLWxZk)aN49;_*=x z@c`mCC@sV|zNAYc4Vw)1hJ}rbJtI$u+i@L>GV_f!-920;T`Tlx1Gwq-^^2^C>LKAR zy8*3N-X97K4R?2UMt3{ScPpT~C0f>TM~}v@xERbbXa>1X@S|*@|n<*CU~wlEc8=yO^L=KXNN1!y}?J3 z0fJW>wmVrp6HilV*PkE1#xL?c8{ajuG=ri9+t6pVJm!;&gC&St-0&BrX@pSNRsC;DH}jDF({q1(5* zT@T3|%9&p8J~3^CEN4x+ah_8@KX$f_m2n%3COfdtRKAG-ZUMG+&Ro-5%?THlnpsj0 z+U^wGw?1MQvlK-_?`x&{tpOjR<)zcC76r>GW`Jdl)j{yLpwy+C?9Rz; zTxo?c_1*EXVyR0r19+L-dG}+Ne*^ov^{n>ECcjk~4j?*{W@F@=bj>qdDkZM9z=wvW zdnd{8{-^i5W7@V~B(HBLg6FIeg8e>|zx$|4v~)ju5IAVaX`*WAlp7=9efuS^#cJDX zvnVmS>Zz5kAWs?m^+J~e(abLe%Bmf|_ma_;zJz4eofqxVbN+AA&6#e)!QVBjBMd{x z;bBZ=z$A)r?lmnVsi^;LU<2;`blzc&Ps4%Wu}v}mO4jlq*S zTU$Z+KaS6qH|EItQcK0iBs{w`PirI_y5La-5+^->Go!2t9ZFLZ%Iv#x9jyPQ>s$Mt zY{rGt3W5axr%RsW9SEse9x zx`pb`-yT)~>-ofA3|D>I)eVM9>Cd(gVL8j!?=-xEE9vwEUgc#F)O{;s6v;{uC97(A zzRk%6c~06-$x@6Lai=jCTGs~N%RWr!r9#oIi%yjU3+iXt=!eDkCTvgNiY4xwZ4AmA z>y1&uX}&A~s7{06GxM72^htEgZ%P`;4puR3`J_%o|0cDT6926RTKEZPjj3;&8>?T} z%-efJeDc(&_DmAk=54zuDPMJ1@m-Y5YE6RM$$A|y#71POd7Q23G)~Drr;H$LN3mQL zRdMtN;IOY)?mF=tvD(?vPGwpH)y=)X5%Vsg;a3RBJFk**Za$FgCu(0x zZrWKHyqj6S>#bX36WJXW)lgYpTOKz>xSTf8@8EBsb+;7-fdcAcr7h1)ay21}|TAV`7G%dLOWAd8Lc>S>P$`Op(m z+Pqk}jUrr|n96&~CN+M?(OLj(v6VFBa^1RrK`{F_OsRfLiYP5z?Dk<^2_Zxo!9RR1X}eVB*angM}KyaTwNuM zpPV`~{sG#@8_H_it^S9}P-c*IMVxnHlVkH#jy@~rMr4@NOF7~4vr}bj8C)WI*ZL*& zPNL!k#o_m!vY@U5@r%%J_z0BO1 z;en|U>NA5Q0?XDvI_ZUH(~j! z^#ec8IdhciN0L;UYEm|f-U2)$NYjG)u^GtfUCX2sXRVoX)4%g)ZU?Aj3O-QA(+h8Z zR8=t6<<~)bw+Dh%OH`dS$Ze6On=9ss<2hau8Gf8}ub&1lwGzXa7+S=ef7LhLWtr}3 zD>8=^coc1rLN}j1Jv%m-?^(B|B~zg!lbPe26GZPk2afe?y&c&iX`(!mh>b_+4!8ZR zE!-i`eoX3&=)&pLDCZmtQj8NA`P&~G+YNsrIQyaq{1oy_hQP!&x^WCw$DbdiD{4Nw zDVF3W1g#Kra}?%EYYl%GRlS4~x7-QS3GV!`LqDX}inJ)GOe@Qgzn5pdZf}w+&xPO~ zt-TsC)_=IPmSZBhYrC`TxujiDd1EJzaa_qkW DSf)*m diff --git a/src/assets/scss/_article-page.scss b/src/assets/scss/_article-page.scss deleted file mode 100644 index b5cb523..0000000 --- a/src/assets/scss/_article-page.scss +++ /dev/null @@ -1,84 +0,0 @@ -$br: 2px; - -#article-page { - - h3 { - margin-bottom: 20px; - } - - form { - .input-group { - width: 100%; - - &:nth-child(n+3) { - margin-top: 25px; - } - } - - label { - margin-bottom: 5px; - color: $blue; - font-weight: 400; - } - - button { - margin: 18px 0; - transition: all 0.4s ease-in; - @extend .blue-pill ; - - &:hover:not([disabled]) { - color: white; - background: $blue; - } - } - } - - .articles { - margin-bottom: 20px; - padding: 0; - list-style: none; - - > li { - padding: 12px; - border-radius: 2px; - border: 1px solid #ccc; - @extend .shadow; - - &:nth-child(n+2) { - margin-top: 30px; - } - - .title { - margin-bottom: 12px; - @extend .blue-pill ; - } - } - } - - input, - .dropzone, - #cke_body { - border-radius: $br; - @extend .shadow; - } - - #cke_body { - - .cke_inner { - border-radius: $br; - - #cke_1_top { - border-radius: $br $br 0 0; - } - - #cke_1_contents { - border-radius: 0 0 $br $br; - } - } - } - - .dropzone, - #cke_body { - border: 1px solid #ccc; - } -} diff --git a/src/assets/scss/_events-page.scss b/src/assets/scss/_events-page.scss deleted file mode 100644 index c9c4c0b..0000000 --- a/src/assets/scss/_events-page.scss +++ /dev/null @@ -1,90 +0,0 @@ -#events-page { - - #events { - margin-bottom: 35px; - } - - .unselect { - position: absolute; - top: 0; - bottom: 0; - right: 7px; - color: $error; - line-height: 36px; - font-size: 18px; - text-decoration: none; - border-left: 1px solid #E2E2E2; - padding-left: 8px; - transition: color 0.2s ease-in; - - &:hover { - color: $error-light; - } - } - - .first .wrapper:nth-child(n+2) { - margin-top: 30px; - } - - .companies { - margin: 10px 0; - padding: 4px; - width: 100%; - border-radius: 3px; - color:$blue; - background: white; - } - - input.search { - margin-top: 18px; - border-radius: 3px; - color: $blue; - } - - .authors, - .events { - list-style: none; - margin: 15px 0; - padding: 0; - - li { - position: relative; - margin-top: 10px; - padding: 5px 9px; - border: 1px solid #E2E2E2; - border-radius: 5px; - transition: background 0.2s ease-in; - - &:first-child { - margin-top: 0; - } - - &.-active { - background: $light-blue; - border-bottom: 1px solid #BFD7EB; - - .unselect { - border-left: 1px solid #BFD7EB; - } - } - } - } - - .map-container { - padding-bottom: 26px; - - .map-wrapper { - position: relative; - padding-top: 6px; - height: 600px; - - #map { - position: absolute; - height: 100%; - width: 100%; - padding: 0px; - margin: 0px; - } - } - } -} diff --git a/src/assets/scss/_footer.scss b/src/assets/scss/_footer.scss deleted file mode 100644 index 293ef65..0000000 --- a/src/assets/scss/_footer.scss +++ /dev/null @@ -1,41 +0,0 @@ -.main-footer { - position: absolute; - left: 0px; - right: 0px; - bottom: 0px; - text-align: center; - padding: 9px; - border-top: 7px solid white; - color: white; - background-color: #2D2D38; - font-size: 15px; - - &:before { - content: ""; - position: absolute; - width: 100%; - left: 0px; - top: -7px; - border-top: 1px solid #C8C8CB; - } - - .divider { - color: rgba(255, 255, 255, 0.38); - display: inline-block; - padding-left: 8px; - padding-right: 8px; - } - - a { - color: white; - - &.gizra-logo { - padding-left: 2px; - font-size: 17px; - } - } - - i.fa.fa-heart { - font-size: 14px; - } -} diff --git a/src/assets/scss/_header.scss b/src/assets/scss/_header.scss deleted file mode 100644 index a42caae..0000000 --- a/src/assets/scss/_header.scss +++ /dev/null @@ -1,128 +0,0 @@ -#main-header { - margin-bottom: 50px; - position: relative; - padding: 17px 9px 9px 9px; - border-bottom: 7px solid white; - color: white; - background-color: #2D2D38; - font-size: 15px; - - &:before { - content: ""; - position: absolute; - width: 100%; - left: 0px; - bottom: -7px; - border-bottom: 1px solid #C8C8CB; - } - - .brand { - color: $blue; - font-size: 30px; - font-family: 'Fjalla One', sans-serif; - transition: color 0.3s ease-in; - - &:hover { - color: $dark-blue; - } - } - - .navbar-header { - a { - margin-top: 2px; - text-decoration: none; - } - - .navbar-toggle { - border-color: $blue; - margin-right: 0; - transition: all 0.3s ease-in; - - &:hover, - &:focus { - background: $dark-blue; - border-color: $dark-blue; - - .icon-bar { - background: white; - } - } - - .icon-bar { - background: $blue; - transition: all 0.3s ease-in; - } - } - } - - .main-nav { - - ul.nav { - li { - padding: 8px; - - &:hover { - a, - i { - color: $blue; - } - } - - a, - i { - transition: color 0.3s ease-in; - } - - a { - padding: 0 12px 0 10px; - display: inline-block; - color: white; - - &.brand { - @extend .brand; - } - } - - &.active { - - a, - i { - color: $blue; - background: none; - } - } - } - } - } - - .main-nav { - @media only screen and (max-width : 767px) { - border: none; - box-shadow: none; - } - - ul.nav { - li { - - @media only screen and (min-width : 768px) { - a { - border-right: 1px solid $blue; - } - - &:first-child a, - &:last-child a { - border-right: none; - } - } - - @media only screen and (max-width : 767px) { - border-bottom: 1px solid rgba(255, 255, 255, 0.12); - a { - padding-top: 4px; - padding-bottom: 8px; - } - } - } - } - } -} diff --git a/src/assets/scss/_login.scss b/src/assets/scss/_login.scss deleted file mode 100644 index 0c53e3c..0000000 --- a/src/assets/scss/_login.scss +++ /dev/null @@ -1,71 +0,0 @@ -#login-page { - margin-top: 15%; - - .wrapper { - margin: 55px auto; - max-width: 380px; - } - - .form-signin { - @extend .box; - max-width: 380px; - - h2 { - margin-top: 0px; - margin-bottom: 20px; - text-transform: capitalize; - } - - .btn, - .input-group-addon { - color: white; - border: none; - } - - .btn a { - color: white; - } - - .input-group, - .input-group-addon, - .form-control, - .btn { - border-radius: 0px; - } - - .btn { - transition: background 0.4s ease-in; - background: $blue; - - &[disabled], - &[disabled]:hover { - background: $light-gray; - } - - &:hover { - background: $dark-blue; - } - } - - .input-group { - margin-bottom: 15px; - - .input-group-addon { - min-width: 45px; - background: $light-gray; - - .form-control { - border-radius: 0px; - position: relative; - font-size: 16px; - height: auto; - padding: 10px; - - &:focus { - z-index: 2; - } - } - } - } - } -} diff --git a/src/assets/scss/_mixin.scss b/src/assets/scss/_mixin.scss deleted file mode 100644 index ecab79b..0000000 --- a/src/assets/scss/_mixin.scss +++ /dev/null @@ -1,13 +0,0 @@ -/* Variables */ -$main-bg: rgb(234, 233, 227); -$light-blue: #E1EAF2; -$blue: #5F90BB; -$dark-blue: darken($blue, 15%); -$dark-gray: #2D2D38; -$light-gray: #606071; -$gray: #989898; -$text-gray: #B1B1B1; -$gizra: #e27058; -$gizra-dark: darken(#e27058, 3.5%); -$error: #D25263; -$error-light: #D81630; diff --git a/src/assets/scss/_my-account.scss b/src/assets/scss/_my-account.scss deleted file mode 100644 index 0fd7d34..0000000 --- a/src/assets/scss/_my-account.scss +++ /dev/null @@ -1,35 +0,0 @@ -#my-account { - - .name { - margin-top: 25px; - @extend .blue-pill; - } - - .company-title { - margin-top: 10px 0; - } - - .companies { - max-width: 141px; - margin-top: 15px; - margin-bottom: 20px; - padding-left: 22px; - - li { - position: relative; - margin-top: 11px; - padding-bottom: 7px; - - &:before { - content: ""; - position: absolute; - bottom: 0; - left: -17px; - right: 0; - height: 1px; - margin-left: -4px; - border-bottom: 1px solid rgba(0, 0, 0, 0.07); - } - } - } -} diff --git a/src/assets/scss/_page-not-found.scss b/src/assets/scss/_page-not-found.scss deleted file mode 100644 index d42247b..0000000 --- a/src/assets/scss/_page-not-found.scss +++ /dev/null @@ -1,17 +0,0 @@ -#page-not-found { - - a { - display: inline-block; - margin-top: 5px; - padding: 7px; - color: white; - background: $blue; - border-radius: 2px; - text-decoration: none; - transition: background 0.4s ease-in; - - &:hover { - background: $dark-blue; - } - } -} diff --git a/src/assets/scss/style.scss b/src/assets/scss/style.scss deleted file mode 100644 index 583a0a6..0000000 --- a/src/assets/scss/style.scss +++ /dev/null @@ -1,103 +0,0 @@ -@import "mixin"; -@import "footer"; -@import "header"; -@import "login"; -@import "page-not-found"; -@import "my-account"; -@import "article-page"; -@import "events-page"; - -html { - position: relative; - min-height: 100%; -} - -body { - font-family: 'Roboto Condensed', arial, sans-serif; - font-weight: 300; - background: $main-bg; - padding-bottom: 100px; -} - -h4 { - font-weight: 300; -} - -hr { - display: block; - margin: 11px 0px; - height: 1px; - border-bottom: 1px solid rgb(218, 217, 209); - background: #EAE9E3; -} - -.shadow { - box-shadow: 0px 7px 2px 0px rgba(0, 0, 0, 0.05); -} - -.blue-pill { - display: inline-block; - padding: 2px 7px; - color: $blue; - background: rgba(186, 219, 249, 0.28); - border-radius: 2px; - border: 1px solid rgba(186, 219, 249, 0.63); -} - -.container .wrapper:nth-child(n+2) { - margin-top: 45px; -} - -.wrapper { - padding: 12px; - border: 1px solid #C8C8CB; - border-radius: 5px; - background: white; - @extend .shadow; - - &.-suffix { - position: relative; - - &:after { - content: ""; - position: absolute; - bottom: 9px; - left: 0; - right: 0; - height: 1px; - background: rgba(200, 200, 203, 0.64); - } - } -} - -h3.title { - margin: -13px -13px 5px -13px; - padding: 12px; - color: $text-gray; - background: $dark-gray; - font-size: 18px; - border-radius: 5px 5px 0 0; - - .icon { - margin-right: 5px - } - -} - -.box { - padding: 15px; - color: white; - background: $dark-gray; - border: 1px solid rgba(0,0,0,0.1); -} - -a.gizra-logo { - text-decoration: none; - text-transform: lowercase; - font-family: Abril Fatface; - color: $gizra; - - &:hover { - color: $gizra-dark; - } -} diff --git a/src/elm/App/Model.elm b/src/elm/App/Model.elm deleted file mode 100644 index b5f5c01..0000000 --- a/src/elm/App/Model.elm +++ /dev/null @@ -1,53 +0,0 @@ -module App.Model exposing (..) - -import Config.Model as Config exposing (initialModel, Model) -import Company.Model as Company exposing (Model) - --- Pages import - -import Pages.Article.Model as Article exposing (initialModel, Model) -import Pages.Event.Model as Event exposing (initialModel, Model) -import Pages.GithubAuth.Model as GithubAuth exposing (Model) -import Pages.Login.Model as Login exposing (initialModel, Model) -import Pages.User.Model as User exposing (initialModel, Model) - -type alias AccessToken = String -type alias CompanyId = Int - -type Page - = Article - | Event (Maybe CompanyId) - | GithubAuth - | Login - | PageNotFound - | User - -type alias Model = - { accessToken : AccessToken - , activePage : Page - , article : Article.Model - , config : Config.Model - , configError : Bool - , companies : List Company.Model - , events : Event.Model - , githubAuth: GithubAuth.Model - , login: Login.Model - -- If the user is anonymous, we want to know where to redirect them. - , nextPage : Maybe Page - , user : User.Model - } - -initialModel : Model -initialModel = - { accessToken = "" - , activePage = Login - , article = Article.initialModel - , config = Config.initialModel - , configError = False - , companies = [] - , events = Event.initialModel - , githubAuth = GithubAuth.initialModel - , login = Login.initialModel - , nextPage = Nothing - , user = User.initialModel - } diff --git a/src/elm/App/Router.elm b/src/elm/App/Router.elm deleted file mode 100644 index 4694d88..0000000 --- a/src/elm/App/Router.elm +++ /dev/null @@ -1,65 +0,0 @@ -module App.Router exposing (..) - -import App.Model as App exposing (Model) -import App.Update exposing (Msg) -import Pages.Event.Router as Event exposing (delta2update, location2company) -import RouteHash exposing (HashUpdate) - -type alias Model = App.Model - -delta2update : Model -> Model -> Maybe HashUpdate -delta2update previous current = - case current.activePage of - App.Article -> - Just <| RouteHash.set ["articles"] - - App.Event companyId -> - -- First, we ask the submodule for a HashUpdate. Then, we use - -- `map` to prepend something to the URL. - RouteHash.map ((::) "events") <| - Event.delta2update previous.events current.events - - App.GithubAuth -> - RouteHash.map (\_ -> ["auth", "github"]) Nothing - - App.Login -> - if current.login.hasAccessTokenInStorage - -- The user has access token, but not yet logged in, so we don't change - -- the url to "login", as we are just waiting for the server to fetch - -- the user info. - then Nothing - else Just <| RouteHash.set ["login"] - - - App.PageNotFound -> - Nothing - - App.User -> - Just <| RouteHash.set ["my-account"] - - --- Here, we basically do the reverse of what delta2update does -location2action : List String -> List Msg -location2action list = - case list of - ["auth", "github"] -> - ( App.Update.SetActivePage App.GithubAuth ) :: [] - - "articles" :: rest -> - ( App.Update.SetActivePage App.Article ) :: [] - - "login" :: rest -> - ( App.Update.SetActivePage App.Login ) :: [] - - "my-account" :: rest -> - ( App.Update.SetActivePage App.User ) :: [] - - "events" :: rest -> - ( App.Update.SetActivePage <| App.Event (Event.location2company rest) ) :: [] - - - "" :: rest -> - ( App.Update.SetActivePage <| App.Event Nothing ) :: [] - - _ -> - ( App.Update.SetActivePage App.PageNotFound ) :: [] diff --git a/src/elm/App/Update.elm b/src/elm/App/Update.elm deleted file mode 100644 index 08d0016..0000000 --- a/src/elm/App/Update.elm +++ /dev/null @@ -1,368 +0,0 @@ -module App.Update exposing (..) - -import App.Model as App exposing (initialModel, Model) - -import Config.Update exposing (init, Msg) -import Company.Model as Company exposing (Model) -import Json.Encode as JE exposing (string, Value) -import String exposing (isEmpty) -import Storage exposing (removeItem, setItem) -import Task exposing (succeed) - --- Pages import - -import Pages.Article.Update exposing (Msg) -import Pages.Event.Update exposing (Msg) -import Pages.GithubAuth.Update exposing (Msg) -import Pages.Login.Update exposing (Msg) -import Pages.User.Model exposing (User) -import Pages.User.Update exposing (Msg) - -type alias AccessToken = String -type alias Model = App.Model - -initialCmd : List (Cmd Msg) -initialCmd = - [ Cmd.map ChildConfigAction <| snd Config.Update.init - , Cmd.map ChildLoginAction <| snd Pages.Login.Update.init - ] - -init : (Model, Cmd Msg) -init = - ( App.initialModel - , Cmd.batch initialCmd - ) - -type Msg - = ChildArticleAction Pages.Article.Update.Msg - | ChildConfigAction Config.Update.Msg - | ChildEventAction Pages.Event.Update.Msg - | ChildGithubAuthAction Pages.GithubAuth.Update.Msg - | ChildLoginAction Pages.Login.Update.Msg - | ChildUserAction Pages.User.Update.Msg - | Logout - | SetAccessToken AccessToken - | SetActivePage App.Page - | SetConfigError - | UpdateCompanies (List Company.Model) - - -- NoOp actions - | NoOp - | NoOpLogout (Maybe ()) - | NoOpSetAccessToken (Result AccessToken ()) - - -update : Msg -> Model -> (Model, Cmd Msg) -update action model = - case action of - ChildArticleAction act -> - let - -- Pass the access token along to the child components. - context = - { accessToken = model.accessToken - , backendConfig = (.config >> .backendConfig) model - } - - (childModel, childCmd) = Pages.Article.Update.update context act model.article - in - ( {model | article = childModel } - , Cmd.map ChildArticleAction childCmd - ) - - ChildConfigAction act -> - let - (childModel, childCmd) = Config.Update.update act model.config - - defaultCmd = - [ Cmd.map ChildConfigAction childCmd ] - - effects' = - case act of - Config.Update.SetError -> - -- Set configuration error. - (Task.succeed SetConfigError |> Cmd.task) - :: - defaultCmd - _ -> - defaultCmd - - in - ( { model - | config = childModel - } - , Cmd.batch effects' - ) - - ChildEventAction act -> - let - -- Pass the access token along to the child components. - context = - { accessToken = model.accessToken - , backendConfig = (.config >> .backendConfig) model - , companies = model.companies - } - - (childModel, childCmd) = Pages.Event.Update.update context act model.events - in - ( {model | events = childModel } - , Cmd.map ChildEventAction childCmd - ) - - ChildGithubAuthAction act -> - let - - context = - { backendConfig = (.config >> .backendConfig) model } - - (childModel, childCmd) = Pages.GithubAuth.Update.update context act model.githubAuth - - defaultEffect = - Cmd.map ChildGithubAuthAction childCmd - - -- A convinence variable to hold the default effect as a list. - defaultCmd = - [ defaultEffect ] - - effects' = - case act of - -- User's token was fetched, so we can set it in the accessToken - -- root property, and also get the user info, which will in turn - -- redirect the user from the login page. - Pages.GithubAuth.Update.SetAccessToken token -> - (Task.succeed (SetAccessToken token) |> Cmd.task) - :: - defaultCmd - - _ -> - defaultCmd - - in - ( {model | githubAuth = childModel } - , Cmd.batch effects' - ) - - ChildLoginAction act -> - let - context = - { backendConfig = (.config >> .backendConfig) model } - - (childModel, childCmd) = Pages.Login.Update.update context act model.login - - defaultEffect = - Cmd.map ChildLoginAction childCmd - - -- A convinence variable to hold the default effect as a list. - defaultCmd = - [ defaultEffect ] - - effects' = - case act of - -- -- User's token was fetched, so we can set it in the accessToken - -- -- root property, and also get the user info, which will in turn - -- -- redirect the user from the login page. - Pages.Login.Update.SetAccessToken token -> - (Task.succeed (SetAccessToken token) |> Cmd.task) - :: - (Task.succeed (ChildUserAction Pages.User.Update.GetDataFromServer) |> Cmd.task) - :: - defaultCmd - - _ -> - defaultCmd - - in - ( {model | login = childModel } - , Cmd.batch effects' - ) - - - ChildUserAction act -> - let - context = - { accessToken = model.accessToken - , backendConfig = (.config >> .backendConfig) model - } - - (childModel, childCmd) = Pages.User.Update.update context act model.user - - defaultEffect = - Cmd.map ChildUserAction childCmd - - defaultCmd = - [ defaultEffect ] - - model' = - { model | user = childModel } - - (model'', effects') = - case act of - -- Bubble up the SetAccessToken to the App level. - Pages.User.Update.SetAccessToken token -> - ( model' - , (Task.succeed (SetAccessToken token) |> Cmd.task) - :: - defaultCmd - ) - - -- Act when user was successfully fetched from the server. - Pages.User.Update.UpdateDataFromServer result -> - case result of - -- We reach out into the companies that is passed to the child - -- action. - Ok (id, name, companies) -> - let - nextPage = - case model.nextPage of - Just page -> - page - Nothing -> - App.Event Nothing - - in - -- User data was successfully fetched, so we can redirect to - -- the next page, and update their companies. - ( { model' | nextPage = Nothing } - , (Task.succeed (UpdateCompanies companies) |> Cmd.task) - :: - (Task.succeed (SetActivePage nextPage) |> Cmd.task) - :: - defaultCmd - ) - - Err _ -> - ( model' - , defaultCmd - ) - - _ -> - ( model' - , defaultCmd - ) - - in - (model'', Cmd.batch effects') - - Logout -> - ( App.initialModel - , Cmd.batch <| removeStorageItem :: initialCmd - ) - - SetAccessToken accessToken -> - let - defaultCmd = - [sendInputToStorage accessToken] - - effects' = - if (String.isEmpty accessToken) - then - -- Setting an empty access token should result with a logout. - (Task.succeed Logout |> Cmd.task) - :: - defaultCmd - else - (Task.succeed (ChildUserAction Pages.User.Update.GetDataFromServer) |> Cmd.task) - :: - defaultCmd - - in - ( { model | accessToken = accessToken} - , Cmd.batch effects' - ) - - SetActivePage page -> - let - (page', nextPage) = - if model.user.name == Pages.User.Model.Anonymous - then - case page of - App.GithubAuth -> - (App.GithubAuth, model.nextPage) - - -- The user is anonymous and we are asked to set the active page - -- to login, then we make sure that the next page doesn't - -- change, so they won't be rediected back to the login page. - App.Login -> - (App.Login, model.nextPage) - - -- When the page is not found, we should keep the URL as is, - -- and even after the user info was fetched, we should keep it - -- so we set the next Page also to the error page. - App.PageNotFound -> - (page, Just page) - - _ -> - (App.Login, Just page) - - -- Authenticated user. - else (page, Nothing) - - currentPageCmd = - case model.activePage of - App.Event companyId -> - Task.succeed (ChildEventAction Pages.Event.Update.Deactivate) |> Cmd.task - - _ -> - Cmd.none - - newPageCmd = - case page' of - App.Article -> - Task.succeed (ChildArticleAction Pages.Article.Update.Activate) |> Cmd.task - - App.Event companyId -> - Task.succeed (ChildEventAction <| Pages.Event.Update.Activate companyId) |> Cmd.task - - App.GithubAuth -> - Task.succeed (ChildGithubAuthAction Pages.GithubAuth.Update.Activate) |> Cmd.task - - _ -> - Cmd.none - - in - if model.activePage == page' - then - -- Requesting the same page, so don't do anything. - -- @todo: Because login and myAccount are under the same page (User) - -- we set the nextPage here as-well. - ( { model | nextPage = nextPage }, Cmd.none) - else - ( { model - | activePage = page' - , nextPage = nextPage - } - , Cmd.batch - [ currentPageCmd - , newPageCmd - ] - ) - - SetConfigError -> - ( { model | configError = True} - , Cmd.none - ) - - UpdateCompanies companies -> - ( { model | companies = companies} - , Cmd.none - ) - - -- NoOp actions - _ -> - ( model, Cmd.none ) - --- EFFECTS - -sendInputToStorage : String -> Cmd Msg -sendInputToStorage val = - Storage.setItem "access_token" (JE.string val) - |> Task.toResult - |> Task.map NoOpSetAccessToken - |> Cmd.task - --- Task to remove the access token from localStorage. -removeStorageItem : Cmd Msg -removeStorageItem = - Storage.removeItem "access_token" - |> Task.toMaybe - |> Task.map NoOpLogout - |> Cmd.task diff --git a/src/elm/App/View.elm b/src/elm/App/View.elm deleted file mode 100644 index 964e56b..0000000 --- a/src/elm/App/View.elm +++ /dev/null @@ -1,200 +0,0 @@ -module App.View exposing (..) - -import App.Model as App exposing (initialModel, Model) -import App.Update exposing (init, Msg) - -import Config.View exposing (view) -import Html exposing (a, div, h2, i, li, node, span, text, ul, button, Html) -import Html.Attributes exposing (class, classList, id, href, style, target, attribute) -import Html.Events exposing (onClick) - --- Pages import - -import Pages.Article.View exposing (view) -import Pages.Event.View exposing (view) -import Pages.GithubAuth.View exposing (view) -import Pages.Login.View exposing (view) -import Pages.PageNotFound.View exposing (view) -import Pages.User.Model exposing (User) -import Pages.User.View exposing (view) - -type alias Page = App.Page - -isActivePage : Page -> Page -> Bool -isActivePage activePage page = - case activePage of - App.Event companyId -> - page == (App.Event Nothing) - _-> - activePage == page - -view : Signal.Address Msg -> Model -> Html -view address model = - if model.configError == True - then - Config.View.view - - else - div - [] - [ (navbar address model) - , (mainContent address model) - , footer - ] - -mainContent : Signal.Address Msg -> Model -> Html -mainContent address model = - case model.activePage of - App.Article -> - let - childAddress = - Signal.forwardTo address App.Update.ChildArticleAction - in - div [ style myStyle ] [ Pages.Article.View.view childAddress model.article ] - - App.Event companyId -> - let - childAddress = - Signal.forwardTo address App.Update.ChildEventAction - - context = - { companies = model.companies } - in - div [ style myStyle ] [ Pages.Event.View.view context childAddress model.events ] - - App.GithubAuth -> - let - childAddress = - Signal.forwardTo address App.Update.ChildGithubAuthAction - in - div [ style myStyle ] [ Pages.GithubAuth.View.view childAddress model.githubAuth ] - - App.Login -> - let - childAddress = - Signal.forwardTo address App.Update.ChildLoginAction - - context = - { backendConfig = (.config >> .backendConfig) model } - - in - div [ style myStyle ] [ Pages.Login.View.view context childAddress model.login ] - - App.PageNotFound -> - div [] [ Pages.PageNotFound.View.view ] - - - App.User -> - let - childAddress = - Signal.forwardTo address App.Update.ChildUserAction - in - div [ style myStyle ] [ Pages.User.View.view childAddress model.user ] - -navbar : Signal.Address Msg -> Model -> Html -navbar address model = - case model.user.name of - Pages.User.Model.Anonymous -> - div [] [] - - Pages.User.Model.LoggedIn name -> - navbarLoggedIn address model - -footer : Html -footer = - - div [class "main-footer"] - [ div [class "container"] - [ span [] - [ text "With " - , i [ class "fa fa-heart" ] [] - , text " from " - , a [ href "http://gizra.com", target "_blank", class "gizra-logo" ] [text "gizra"] - , span [ class "divider" ] [ text "|" ] - , text "Backend powered by " - , a [ href "https://pantheon.io/", target "_blank" ] [ text "Pantheon" ] - , span [ class "divider" ] [text "|"] - , a [href "https://github.com/Gizra/elm-hedley", target "_blank"] [text "Github repo"] - ] - ] - ] - --- Navbar for Auth user. -navbarLoggedIn : Signal.Address Msg -> Model -> Html -navbarLoggedIn address model = - let - activeClass page = - [ ("active", isActivePage model.activePage page) ] - - childAddress = - Signal.forwardTo address App.Update.ChildUserAction - - hrefVoid = - href "javascript:void(0);" - - - navCollapseButton = - let - iconBar index = - span [ class "icon-bar" ] [] - - in - button - [ class "navbar-toggle" - , attribute "data-toggle" "collapse" - , attribute "data-target" ".main-nav" - ] - [ span [ class "sr-only"] [ text "Menu" ] - , span [] ( List.map iconBar [0..2] ) - ] - - in - node "nav" - [ id "main-header" - , class "navbar navbar-default" ] - [ div - [ class "container" ] - [ div - [ class "navbar-header" ] - [ a [ class "brand visible-xs pull-left", href "#!/" ] [ text "Hedley" ] - , navCollapseButton - ] - , div - [ class "collapse navbar-collapse main-nav" ] - [ ul - [ class "nav navbar-nav"] - [ li [] [ a [ class "brand hidden-xs", href "#!/" ] [ text "Hedley" ] ] - , li - [ classList (activeClass App.User) ] - [ i [ class "glyphicon glyphicon-user" ] [] - , a [ hrefVoid, onClick address (App.Update.SetActivePage App.User) ] [ text "My account" ] - ] - , li - [ classList (activeClass (App.Event Nothing)) ] - [ i [ class "fa fa-map-marker" ] [] - , a [ hrefVoid, onClick address (App.Update.SetActivePage <| App.Event Nothing) ] [ text "Events" ] - ] - , li - [ classList (activeClass App.Article) ] - [ i [ class "fa fa-file-o" ] [] - , a [ hrefVoid, onClick address (App.Update.SetActivePage App.Article) ] [ text "Articles"] - ] - , li - [ classList (activeClass App.PageNotFound) ] - [ i [ class "fa fa-exclamation-circle" ] [] - , a [ href "#!/error-page" ] [ text "PageNotFound (404)" ] - ] - , li - [] - [ i [ class "fa fa-sign-out" ] [] - , a [ hrefVoid, onClick address App.Update.Logout ] [ text "Logout" ] - ] - ] - ] - ] - ] - - -myStyle : List (String, String) -myStyle = - [ ("font-size", "1.2em") ] diff --git a/src/elm/Article/Decoder.elm b/src/elm/Article/Decoder.elm deleted file mode 100644 index 07f1c6c..0000000 --- a/src/elm/Article/Decoder.elm +++ /dev/null @@ -1,36 +0,0 @@ -module Article.Decoder exposing (..) - -import Article.Model as Article exposing (Model) - -import Json.Decode as JD exposing ((:=)) -import String exposing (toInt, toFloat) - -decode : JD.Decoder Article.Model -decode = - let - -- Cast String to Int. - number : JD.Decoder Int - number = - JD.oneOf [ JD.int, JD.customDecoder JD.string String.toInt ] - - - numberFloat : JD.Decoder Float - numberFloat = - JD.oneOf [ JD.float, JD.customDecoder JD.string String.toFloat ] - - decodeAuthor = - JD.object2 Article.Author - ("id" := number) - ("label" := JD.string) - - decodeImage = - JD.at ["styles"] - ("thumbnail" := JD.string) - - in - JD.object5 Article.Model - ("user" := decodeAuthor) - (JD.oneOf [ "body" := JD.string, JD.succeed "" ]) - ("id" := number) - (JD.maybe ("image" := decodeImage)) - ("label" := JD.string) diff --git a/src/elm/Article/Model.elm b/src/elm/Article/Model.elm deleted file mode 100644 index 0355928..0000000 --- a/src/elm/Article/Model.elm +++ /dev/null @@ -1,16 +0,0 @@ -module Article.Model exposing (..) - -type alias Id = Int - -type alias Model = - { author : Author - , body : String - , id : Id - , image : Maybe String - , label : String - } - -type alias Author = - { id : Id - , name : String - } diff --git a/src/elm/ArticleForm/Model.elm b/src/elm/ArticleForm/Model.elm deleted file mode 100644 index 69c5b73..0000000 --- a/src/elm/ArticleForm/Model.elm +++ /dev/null @@ -1,35 +0,0 @@ -module ArticleForm.Model exposing (..) - -type PostStatus = Busy | Done | Ready - -type alias ArticleForm = - { label : String - , body : String - , image : Maybe Int - , show : Bool - } - -type UserMessage - = None - | Error String - -type alias Model = - { articleForm : ArticleForm - , postStatus : PostStatus - , userMessage : UserMessage - } - -initialArticleForm : ArticleForm -initialArticleForm = - { label = "" - , body = "" - , image = Nothing - , show = True - } - -initialModel : Model -initialModel = - { articleForm = initialArticleForm - , postStatus = Ready - , userMessage = None - } diff --git a/src/elm/ArticleForm/Update.elm b/src/elm/ArticleForm/Update.elm deleted file mode 100644 index 0dbb685..0000000 --- a/src/elm/ArticleForm/Update.elm +++ /dev/null @@ -1,171 +0,0 @@ -module ArticleForm.Update exposing (..) - -import Article.Decoder exposing (decode) -import Article.Model as Article exposing (Author, Model) -import ArticleForm.Model as ArticleForm exposing (initialArticleForm, initialModel, ArticleForm, Model, UserMessage) - -import Config.Model exposing (BackendConfig) -import Http exposing (post, Error) -import Json.Decode as JD exposing ((:=)) -import Json.Encode as JE exposing (string) -import Task exposing (andThen, Task) -import Utils.Http exposing (getErrorMessageFromHttpResponse) - -init : (ArticleForm.Model, Cmd Msg) -init = - ( initialModel - , Cmd.none - ) - -type Msg - = ResetForm - | SubmitForm - | SetImageId (Maybe Int) - | SetUserMessage UserMessage - | UpdateBody String - | UpdateLabel String - | UpdatePostArticle (Result Http.Error Article.Model) - - -type alias Model = ArticleForm.Model - -type alias Context = - { accessToken : String - , backendConfig : BackendConfig - } - -update : Context -> Msg -> Model -> (Model, Cmd Msg, Maybe Article.Model) -update context action model = - case action of - ResetForm -> - ( { model - | articleForm = initialArticleForm - , postStatus = ArticleForm.Ready - } - , Cmd.none - , Nothing - ) - - SetImageId maybeVal -> - let - articleForm = - model.articleForm - - articleForm' = - { articleForm | image = maybeVal } - in - ( { model | articleForm = articleForm' } - , Cmd.none - , Nothing - ) - - SetUserMessage userMessage -> - ( { model | userMessage = userMessage } - , Cmd.none - , Nothing - ) - - SubmitForm -> - let - backendUrl = - (.backendConfig >> .backendUrl) context - - url = - backendUrl ++ "/api/v1.0/articles" - in - if model.postStatus == ArticleForm.Ready - then - ( { model | postStatus = ArticleForm.Busy } - , postArticle url context.accessToken model.articleForm - , Nothing - ) - - else - ( model - , Cmd.none - , Nothing - ) - - -- @todo: Create a helper function. - UpdateBody val -> - let - articleForm = - model.articleForm - - articleForm' = - { articleForm | body = val } - in - ( { model | articleForm = articleForm' } - , Cmd.none - , Nothing - ) - - UpdateLabel val -> - let - articleForm = - model.articleForm - - articleForm' = - { articleForm | label = val } - in - ( { model | articleForm = articleForm' } - , Cmd.none - , Nothing - ) - - UpdatePostArticle result -> - case result of - Ok article -> - -- Append the new article to the articles list. - ( { model | postStatus = ArticleForm.Done } - -- We can reset the form, as it was posted successfully. - , Task.succeed ResetForm |> Cmd.task - -- Return the article to the parent component. - , Just article - ) - - Err err -> - ( model - , Task.succeed (SetUserMessage <| ArticleForm.Error (getErrorMessageFromHttpResponse err)) |> Cmd.task - , Nothing - ) - - --- EFFECTS - -postArticle : String -> String -> ArticleForm.ArticleForm -> Cmd Msg -postArticle url accessToken data = - let - params = - [ ("access_token", accessToken) ] - - encodedUrl = - Http.url url params - in - Http.post - decodePostArticle - encodedUrl - (Http.string <| dataToJson data ) - |> Task.toResult - |> Task.map UpdatePostArticle - |> Cmd.task - - -dataToJson : ArticleForm.ArticleForm -> String -dataToJson data = - let - intOrNull maybeVal = - case maybeVal of - Just val -> JE.int val - Nothing -> JE.null - in - JE.encode 0 - <| JE.object - [ ("label", JE.string data.label) - , ("body", JE.string data.body) - , ("image", intOrNull data.image) - ] - -decodePostArticle : JD.Decoder Article.Model -decodePostArticle = - JD.at ["data", "0"] <| Article.Decoder.decode diff --git a/src/elm/ArticleForm/View.elm b/src/elm/ArticleForm/View.elm deleted file mode 100644 index 9de8fb2..0000000 --- a/src/elm/ArticleForm/View.elm +++ /dev/null @@ -1,80 +0,0 @@ -module ArticleForm.View exposing (..) - -import ArticleForm.Model exposing (initialModel, Model, UserMessage) -import ArticleForm.Update exposing (Msg) -import Html exposing (i, button, div, label, h2, h3, input, img, li, text, textarea, span, ul, Html) -import Html.Attributes exposing (action, class, id, disabled, name, placeholder, property, required, size, src, style, type', value) -import Html.Events exposing (on, onClick, onSubmit, targetValue) -import String exposing (toInt, toFloat) - -view : Signal.Address Msg -> Model -> Html -view address model = - div - [ class "wrapper -suffix"] - [ viewUserMessage model.userMessage - , viewForm address model - ] - -viewUserMessage : UserMessage -> Html -viewUserMessage userMessage = - case userMessage of - ArticleForm.Model.None -> - div [] [] - ArticleForm.Model.Error message -> - div [ style [("text-align", "center")] ] [ text message ] - -viewForm :Signal.Address Msg -> Model -> Html -viewForm address model = - Html.form - [ onSubmit address ArticleForm.Update.SubmitForm - , action "javascript:void(0);" - ] - [ h3 - [ class "title" ] - [ i [ class "fa fa-pencil" ] [] - , text " Add new article" - ] - -- Label - , div - [ class "input-group" ] - [ label [] [ text "Label" ] - , input - [ type' "text" - , class "form-control" - , value model.articleForm.label - , on "input" targetValue (Signal.message address << ArticleForm.Update.UpdateLabel) - , required True - ] - [] - ] - -- End label - - -- Body - , div - [ class "input-group" ] - [ label [] [ text "Body"] - , textarea - [ class "form-control" - , name "body" - , placeholder "Body" - , value model.articleForm.body - , on "input" targetValue (Signal.message address << ArticleForm.Update.UpdateBody) - ] - [] - ] -- End body - - -- File upload - , div - [ class "input-group " ] - [ label [] [ text "Upload File" ] - , div [ class "dropzone" ] [] - ] - - -- Submit button - , button - [ onClick address ArticleForm.Update.SubmitForm - , class "btn btn-lg btn-primary" - , disabled (String.isEmpty model.articleForm.label) - ] - [ text "Submit" ] -- End submit button - ] diff --git a/src/elm/ArticleList/Model.elm b/src/elm/ArticleList/Model.elm deleted file mode 100644 index c7f61ef..0000000 --- a/src/elm/ArticleList/Model.elm +++ /dev/null @@ -1,25 +0,0 @@ -module ArticleList.Model exposing (..) - -import Article.Model as Article exposing (Model) -import Http exposing (Error) -import Time exposing (Time) - -type alias Id = Int - -type Status = - Init - | Fetching - | Fetched Time.Time - | HttpError Http.Error - - -type alias Model = - { articles : List Article.Model - , status : Status - } - -initialModel : Model -initialModel = - { articles = [] - , status = Init - } diff --git a/src/elm/ArticleList/Update.elm b/src/elm/ArticleList/Update.elm deleted file mode 100644 index 210ed0f..0000000 --- a/src/elm/ArticleList/Update.elm +++ /dev/null @@ -1,135 +0,0 @@ -module ArticleList.Update exposing (..) - -import Article.Decoder exposing (decode) -import Article.Model as Article exposing (Model) -import ArticleList.Model exposing (initialModel, Model) -import Config exposing (cacheTtl) -import Config.Model exposing (BackendConfig) -import Http exposing (post, Error) -import Json.Decode as JD exposing ((:=)) -import Task exposing (andThen, Task) -import Time exposing (Time) - -init : (ArticleList.Model.Model, Cmd Msg) -init = - ( initialModel - , Cmd.none - ) - -type Msg - = AppendArticle Article.Model - | GetData - | GetDataFromServer - | NoOp - | UpdateDataFromServer (Result Http.Error (List Article.Model)) Time.Time - - - -type alias UpdateContext = - { accessToken : String - , backendConfig : BackendConfig - } - -update : UpdateContext -> Msg -> ArticleList.Model.Model -> (ArticleList.Model.Model, Cmd Msg) -update context action model = - case action of - AppendArticle article -> - ( { model | articles = article :: model.articles } - , Cmd.none - ) - - GetData -> - let - effects = - case model.status of - ArticleList.Model.Fetching -> - Cmd.none - - _ -> - getDataFromCache model.status - in - ( model - , effects - ) - - - GetDataFromServer -> - let - backendUrl = - (.backendConfig >> .backendUrl) context - - url = - backendUrl ++ "/api/v1.0/articles" - in - ( { model | status = ArticleList.Model.Fetching } - , getJson url context.accessToken - ) - - - UpdateDataFromServer result timestamp' -> - case result of - Ok articles -> - ( { model - | articles = articles - , status = ArticleList.Model.Fetched timestamp' - } - , Cmd.none - ) - - Err err -> - ( { model | status = ArticleList.Model.HttpError err } - , Cmd.none - ) - - NoOp -> - (model, Cmd.none) - --- EFFECTS - -getDataFromCache : ArticleList.Model.Status -> Cmd Msg -getDataFromCache status = - let - actionTask = - case status of - ArticleList.Model.Fetched fetchTime -> - Task.map (\currentTime -> - if fetchTime + Config.cacheTtl > currentTime - then NoOp - else GetDataFromServer - ) Time.now - - _ -> - Task.succeed GetDataFromServer - - in - Cmd.task actionTask - - -getJson : String -> String -> Cmd Msg -getJson url accessToken = - let - params = - [ ("access_token", accessToken) - , ("sort", "-id") - ] - - encodedUrl = Http.url url params - - httpTask = - Task.toResult <| - Http.get decodeData encodedUrl - - actionTask = - httpTask `andThen` (\result -> - Task.map (\timestamp' -> - UpdateDataFromServer result timestamp' - ) Time.now - ) - - in - Cmd.task actionTask - - -decodeData : JD.Decoder (List Article.Model) -decodeData = - JD.at ["data"] <| JD.list <| Article.Decoder.decode diff --git a/src/elm/ArticleList/View.elm b/src/elm/ArticleList/View.elm deleted file mode 100644 index 9a2aa66..0000000 --- a/src/elm/ArticleList/View.elm +++ /dev/null @@ -1,50 +0,0 @@ -module ArticleList.View exposing (..) - -import Article.Model exposing (Model) - -import ArticleList.Model exposing (initialModel, Model) -import ArticleList.Update exposing (Msg) - -import Html exposing (i, button, div, label, h2, h3, input, img, li, text, textarea, span, ul, Html) -import Html.Attributes exposing (action, class, id, disabled, name, placeholder, property, required, size, src, style, type', value) -import Html.Events exposing (on, onClick, onSubmit, targetValue) -import Json.Encode as JE exposing (string) -import String exposing (toInt, toFloat) - - -type alias Article = Article.Model.Model - -type alias Model = ArticleList.Model.Model - -view : Signal.Address Msg -> Model -> Html -view address model = - viewRecentArticles model.articles - -viewRecentArticles : List Article -> Html -viewRecentArticles articles = - div - [ class "wrapper -suffix" ] - [ h3 - [ class "title" ] - [ i [ class "fa fa-file-o icon" ] [] - , text "Recent articles" - ] - , ul [ class "articles" ] (List.map viewArticles articles) - ] - -viewArticles : Article -> Html -viewArticles article = - let - image = - case article.image of - Just val -> img [ src val ] [] - Nothing -> div [] [] - in - li - [] - [ div [ class "title" ] [ text article.label ] - -- Allow attaching HTML without escaping it. XSS is escaped in the server - -- side. - , div [ property "innerHTML" <| JE.string article.body ] [] - , image - ] diff --git a/src/elm/Company/Model.elm b/src/elm/Company/Model.elm deleted file mode 100644 index c53e81e..0000000 --- a/src/elm/Company/Model.elm +++ /dev/null @@ -1,14 +0,0 @@ -module Company.Model exposing (..) - -type alias CompanyId = Int - -type alias Model = - { id : CompanyId - , label : String - } - -initialModel : Model -initialModel = - { id = 0 - , label = "" - } diff --git a/src/elm/Config.elm b/src/elm/Config.elm deleted file mode 100644 index 691a2b1..0000000 --- a/src/elm/Config.elm +++ /dev/null @@ -1,29 +0,0 @@ -module Config exposing (..) - -import Config.Model as Config exposing (BackendConfig) -import Time exposing (Time) - -localBackend : BackendConfig -localBackend = - { backendUrl = "https://dev-hedley-elm.pantheonsite.io" - , githubClientId = "e5661c832ed931ae176c" - , name = "local" - , hostname = "localhost" - } - -prodBackend : BackendConfig -prodBackend = - { backendUrl = "https://live-hedley-elm.pantheonsite.io" - , githubClientId = "4aef0ced83d72bd48d00" - , name = "gh-pages" - , hostname = "gizra.github.io" - } - -backends : List BackendConfig -backends = - [ localBackend - , prodBackend - ] - -cacheTtl : Time.Time -cacheTtl = (5 * Time.second) diff --git a/src/elm/Config/Model.elm b/src/elm/Config/Model.elm deleted file mode 100644 index cea811e..0000000 --- a/src/elm/Config/Model.elm +++ /dev/null @@ -1,28 +0,0 @@ -module Config.Model exposing (..) - -type alias BackendConfig = - { backendUrl : String - , githubClientId : String - , name : String - -- Url information - , hostname : String - } - -initialBackendConfig : BackendConfig -initialBackendConfig = - { backendUrl = "" - , githubClientId = "" - , name = "" - , hostname = "" - } - -type alias Model = - { backendConfig : BackendConfig - , error : Bool - } - -initialModel : Model -initialModel = - { backendConfig = initialBackendConfig - , error = False - } diff --git a/src/elm/Config/Test.elm b/src/elm/Config/Test.elm deleted file mode 100644 index de4693d..0000000 --- a/src/elm/Config/Test.elm +++ /dev/null @@ -1,24 +0,0 @@ -module Config.Test exposing (..) - -import ElmTest exposing (..) - -import Config.Model exposing (initialBackendConfig, initialModel, Model) -import Config.Update exposing (update, Msg) - -type alias Msg = Config.Update.Msg -type alias Model = Config.Model.Model - -setErrorTest : Test -setErrorTest = - test "set error action" (assertEqual True (.error <| fst(setError))) - -setError : (Model, Cmd Msg) -setError = - Config.Update.update Config.Update.SetError initialModel - - -all : Test -all = - suite "Config tests" - [ setErrorTest - ] diff --git a/src/elm/Config/Update.elm b/src/elm/Config/Update.elm deleted file mode 100644 index 59510f5..0000000 --- a/src/elm/Config/Update.elm +++ /dev/null @@ -1,50 +0,0 @@ -module Config.Update exposing (..) - -import Config exposing (backends) -import Config.Model exposing (initialModel, Model) -import Task exposing (map) -import WebAPI.Location exposing (location) - -init : (Model, Cmd Msg) -init = - ( initialModel - , getConfigFromUrl - ) - -type Msg - = SetConfig Config.Model.BackendConfig - | SetError - -update : Msg -> Model -> (Model, Cmd Msg) -update action model = - case action of - SetConfig backendConfig -> - ( { model | backendConfig = backendConfig } - , Cmd.none - ) - - SetError -> - ( { model | error = True } - , Cmd.none - ) - - --- EFFECTS - -getConfigFromUrl : Cmd Msg -getConfigFromUrl = - let - getAction location = - let - config = - List.filter (\backend -> backend.hostname == location.hostname) backends - |> List.head - in - case config of - Just val -> SetConfig val - Nothing -> SetError - - actionTask = - Task.map getAction WebAPI.Location.location - in - Cmd.task actionTask diff --git a/src/elm/Config/View.elm b/src/elm/Config/View.elm deleted file mode 100644 index 5397298..0000000 --- a/src/elm/Config/View.elm +++ /dev/null @@ -1,13 +0,0 @@ -module Config.View exposing (..) - -import Html exposing (div, h2, text, Html) -import Html.Attributes exposing (class) - --- A plain function that always returns the error message -view : Html -view = - div - [ class "config-error" ] - [ h2 [] [ text "Configuration error" ] - , div [] [ text "Check your Config.elm file and make sure you have defined the enviorement properly" ] - ] diff --git a/src/elm/Event/Decoder.elm b/src/elm/Event/Decoder.elm deleted file mode 100644 index 35a0682..0000000 --- a/src/elm/Event/Decoder.elm +++ /dev/null @@ -1,36 +0,0 @@ -module Event.Decoder exposing (..) - -import Event.Model as Event exposing (Author, Event, Marker) -import Json.Decode as JD exposing ((:=)) -import String exposing (toInt, toFloat) - -decode : JD.Decoder (List Event) -decode = - let - -- Cast String to Int. - number : JD.Decoder Int - number = - JD.oneOf [ JD.int, JD.customDecoder JD.string String.toInt ] - - - numberFloat : JD.Decoder Float - numberFloat = - JD.oneOf [ JD.float, JD.customDecoder JD.string String.toFloat ] - - marker = - JD.object2 Marker - ("lat" := numberFloat) - ("lng" := numberFloat) - - author = - JD.object2 Author - ("id" := number) - ("label" := JD.string) - in - JD.at ["data"] - <| JD.list - <| JD.object4 Event - ("user" := author) - ("id" := number) - ("label" := JD.string) - ("location" := marker) diff --git a/src/elm/Event/Model.elm b/src/elm/Event/Model.elm deleted file mode 100644 index 06a63bd..0000000 --- a/src/elm/Event/Model.elm +++ /dev/null @@ -1,20 +0,0 @@ -module Event.Model exposing (..) - -type alias Id = Int - -type alias Marker = - { lat: Float - , lng : Float - } - -type alias Author = - { id : Id - , name : String - } - -type alias Event = - { author : Author - , id : Id - , label : String - , marker : Marker - } diff --git a/src/elm/EventAuthorFilter/Model.elm b/src/elm/EventAuthorFilter/Model.elm deleted file mode 100644 index 051a6c1..0000000 --- a/src/elm/EventAuthorFilter/Model.elm +++ /dev/null @@ -1,6 +0,0 @@ -module EventAuthorFilter.Model exposing (..) - -type alias Model = Maybe Int - -initialModel : Model -initialModel = Nothing diff --git a/src/elm/EventAuthorFilter/Update.elm b/src/elm/EventAuthorFilter/Update.elm deleted file mode 100644 index f99ce85..0000000 --- a/src/elm/EventAuthorFilter/Update.elm +++ /dev/null @@ -1,19 +0,0 @@ -module EventAuthorFilter.Update exposing (..) - -import EventAuthorFilter.Model as EventAuthorFilter exposing (initialModel, Model) - -init : EventAuthorFilter.Model -init = initialModel - -type Msg - = SelectAuthor Int - | UnSelectAuthor - -update : Msg -> Model -> Model -update action model = - case action of - SelectAuthor id -> - Just id - - UnSelectAuthor -> - Nothing diff --git a/src/elm/EventAuthorFilter/View.elm b/src/elm/EventAuthorFilter/View.elm deleted file mode 100644 index 80ce379..0000000 --- a/src/elm/EventAuthorFilter/View.elm +++ /dev/null @@ -1,80 +0,0 @@ -module EventAuthorFilter.View exposing (..) - -import EventAuthorFilter.Model as EventAuthorFilter exposing (initialModel, Model) -import EventAuthorFilter.Update exposing (Msg) - -import Dict exposing (Dict) -import Event.Model as Event exposing (Author, Event) -import Html exposing (h3, a, i, div, input, text, select, span, li, option, ul, Html) -import Html.Attributes exposing (class, hidden, href, id, placeholder, selected, style, value) -import Html.Events exposing (on, onClick, targetValue) - -type alias Model = EventAuthorFilter.Model - -view : List Event -> Signal.Address Msg -> Model -> Html -view events address eventAuthorFilter = - div - [ class "wrapper -suffix" ] - [ h3 - [ class "title" ] - [ i [ class "glyphicon glyphicon-user" ] [] - , text <| " " ++ "Event Authors" - ] - , ul [ class "authors" ] (viewEventsByAuthors events address eventAuthorFilter) - ] - -viewEventsByAuthors : List Event -> Signal.Address Msg -> Maybe Int -> List Html -viewEventsByAuthors events address eventAuthorFilter = - let - getText : Author -> Int -> Html - getText author count = - let - authorRaw = - text (author.name ++ " (" ++ toString(count) ++ ")") - - authorSelect = - a [ href "javascript:void(0);", onClick address (EventAuthorFilter.Update.SelectAuthor author.id) ] [ authorRaw ] - - authorUnselect = - span [] - [ a - [ class "unselect fa fa-times-circle" - , href "javascript:void(0);" - , onClick address (EventAuthorFilter.Update.UnSelectAuthor) - ] [] - , authorRaw - ] - in - case eventAuthorFilter of - Just id -> - if author.id == id then authorUnselect else authorSelect - - Nothing -> - authorSelect - - viewAuthor (author, count) = - li [] [getText author count] - in - -- Get HTML from the grouped events - groupEventsByAuthors events |> - Dict.values |> - List.map viewAuthor - -groupEventsByAuthors : List Event -> Dict Int (Author, Int) -groupEventsByAuthors events = - let - handleEvent : Event -> Dict Int (Author, Int) -> Dict Int (Author, Int) - handleEvent event dict = - let - currentValue = - Maybe.withDefault (event.author, 0) <| - Dict.get event.author.id dict - - newValue = - case currentValue of - (author, count) -> (author, count + 1) - in - Dict.insert event.author.id newValue dict - - in - List.foldl handleEvent Dict.empty events diff --git a/src/elm/EventCompanyFilter/Model.elm b/src/elm/EventCompanyFilter/Model.elm deleted file mode 100644 index f6cab69..0000000 --- a/src/elm/EventCompanyFilter/Model.elm +++ /dev/null @@ -1,6 +0,0 @@ -module EventCompanyFilter.Model exposing (..) - -type alias Model = Maybe Int - -initialModel : Model -initialModel = Nothing diff --git a/src/elm/EventCompanyFilter/Test.elm b/src/elm/EventCompanyFilter/Test.elm deleted file mode 100644 index 42bdada..0000000 --- a/src/elm/EventCompanyFilter/Test.elm +++ /dev/null @@ -1,34 +0,0 @@ -module EventCompanyFilter.Test exposing (..) - -import ElmTest exposing (..) - -import Company.Model as Company exposing (Model) -import EventCompanyFilter.Model as EventCompanyFilter exposing (initialModel, Model) -import EventCompanyFilter.Update exposing (Msg) - -type alias Model = EventCompanyFilter.Model - -selectCompanySuite : Test -selectCompanySuite = - suite "SelectCompany action" - [ test "no company" (assertEqual Nothing (selectCompany Nothing)) - , test "valid company" (assertEqual (Just 1) (selectCompany <| Just 1)) - , test "invalid company" (assertEqual Nothing (selectCompany <| Just 100)) - ] - -selectCompany : Maybe Int -> Model -selectCompany val = - EventCompanyFilter.Update.update companies (EventCompanyFilter.Update.SelectCompany val) initialModel - -companies : List Company.Model -companies = - [ Company.Model 1 "foo" - , Company.Model 2 "bar" - , Company.Model 3 "baz" - ] - -all : Test -all = - suite "EventCompanyFilter" - [ selectCompanySuite - ] diff --git a/src/elm/EventCompanyFilter/Update.elm b/src/elm/EventCompanyFilter/Update.elm deleted file mode 100644 index 5e21796..0000000 --- a/src/elm/EventCompanyFilter/Update.elm +++ /dev/null @@ -1,37 +0,0 @@ -module EventCompanyFilter.Update exposing (..) - -import EventCompanyFilter.Model as EventCompanyFilter exposing (initialModel, Model) - -import Company.Model as Company exposing (Model) - - -init : Model -init = initialModel - -type Msg - = SelectCompany (Maybe Int) - -type alias Model = EventCompanyFilter.Model - -update : List Company.Model -> Msg -> Model -> Model -update companies action model = - case action of - SelectCompany maybeCompanyId -> - let - isValidCompany val = - companies - |> List.filter (\company -> company.id == val) - |> List.length - - - eventCompanyFilter = - case maybeCompanyId of - Just val -> - -- Make sure the given company ID is a valid one. - if ((isValidCompany val) > 0) - then Just val - else Nothing - Nothing -> - Nothing - in - eventCompanyFilter diff --git a/src/elm/EventCompanyFilter/View.elm b/src/elm/EventCompanyFilter/View.elm deleted file mode 100644 index f462b35..0000000 --- a/src/elm/EventCompanyFilter/View.elm +++ /dev/null @@ -1,66 +0,0 @@ -module EventCompanyFilter.View exposing (..) - -import EventCompanyFilter.Model as EventCompanyFilter exposing (initialModel, Model) -import EventCompanyFilter.Update exposing (Msg) - -import Company.Model as Company exposing (Model) -import Html exposing (h3, a, i, div, input, text, select, span, li, option, ul, Html) -import Html.Attributes exposing (class, hidden, href, id, placeholder, selected, style, value) -import Html.Events exposing (on, onClick, targetValue) -import String exposing (toInt) - -type alias Model = EventCompanyFilter.Model - -view : List Company.Model -> Signal.Address Msg -> Model -> Html -view companies address model = - div - [ class "wrapper -suffix" ] - [ h3 - [ class "title" ] - [ i [ class "fa fa-briefcase" ] [] - , text <| " " ++ "Companies" - ] - , companyListForSelect address companies model - ] - -companyListForSelect : Signal.Address Msg -> List Company.Model -> Model -> Html -companyListForSelect address companies eventCompanyFilter = - let - selectedText = - case eventCompanyFilter of - Just id -> toString id - Nothing -> "" - - textToMaybe string = - if string == "0" - then Nothing - else - -- Converting to int return a result. - case (String.toInt string) of - Ok val -> - Just val - Err _ -> - Nothing - - - -- Add an "All companies" option - companies' = - (Company.Model 0 "-- All companies --") :: companies - - -- The selected company ID. - selectedId = - case eventCompanyFilter of - Just id -> - id - Nothing -> - 0 - - getOption company = - option [value <| toString company.id, selected (company.id == selectedId)] [ text company.label] - in - select - [ class "companies" - , value selectedText - , on "change" targetValue (\str -> Signal.message address <| EventCompanyFilter.Update.SelectCompany <| textToMaybe str) - ] - (List.map getOption companies') diff --git a/src/elm/EventList/Model.elm b/src/elm/EventList/Model.elm deleted file mode 100644 index 1da0fb4..0000000 --- a/src/elm/EventList/Model.elm +++ /dev/null @@ -1,12 +0,0 @@ -module EventList.Model exposing (..) - -type alias Model = - { filterString : String - , selectedEvent : Maybe Int - } - -initialModel : Model -initialModel = - { filterString = "" - , selectedEvent = Nothing - } diff --git a/src/elm/EventList/Update.elm b/src/elm/EventList/Update.elm deleted file mode 100644 index 7537a6d..0000000 --- a/src/elm/EventList/Update.elm +++ /dev/null @@ -1,29 +0,0 @@ -module EventList.Update exposing (..) - -import Event.Model exposing (Event) -import EventList.Model as EventList exposing (initialModel, Model) - -type Msg - = FilterEvents String - -- Select event might get values from JS (i.e. selecting a leaflet marker) - -- so we allow passing a Maybe Int, instead of just Int. - | SelectEvent (Maybe Int) - | UnSelectEvent - -type alias Model = EventList.Model - -init : Model -init = initialModel - - -update : List Event -> Msg -> Model -> Model -update events action model = - case action of - FilterEvents val -> - { model | filterString = val } - - SelectEvent val -> - { model | selectedEvent = val } - - UnSelectEvent -> - { model | selectedEvent = Nothing } diff --git a/src/elm/EventList/Utils.elm b/src/elm/EventList/Utils.elm deleted file mode 100644 index f0ceab3..0000000 --- a/src/elm/EventList/Utils.elm +++ /dev/null @@ -1,19 +0,0 @@ -module EventList.Utils exposing (filterEventsByString) - -import Event.Model exposing (Event) -import String exposing (isEmpty, trim, toLower) - -filterEventsByString : List Event -> String -> List Event -filterEventsByString events filterString = - let - filterString' = - String.trim filterString - in - if String.isEmpty filterString' - then - -- Return all the events. - events - - else - -- Filter out the events that do not contain the string. - List.filter (\event -> String.contains (String.toLower filterString') (String.toLower event.label)) events diff --git a/src/elm/EventList/View.elm b/src/elm/EventList/View.elm deleted file mode 100644 index a30027c..0000000 --- a/src/elm/EventList/View.elm +++ /dev/null @@ -1,82 +0,0 @@ -module EventList.View exposing (view) - -import Event.Model as Event exposing (Event) -import EventList.Model as EventList exposing (initialModel, Model) -import EventList.Update exposing (Msg) -import EventList.Utils exposing (filterEventsByString) - -import Html exposing (h3, a, i, div, input, text, select, span, li, option, ul, Html) -import Html.Attributes exposing (class, hidden, href, id, placeholder, selected, style, value) -import Html.Events exposing (on, onClick, targetValue) - -type alias Model = EventList.Model - -view : List Event -> Signal.Address Msg -> Model -> Html -view events address model = - div - [ id "events" - , class "wrapper -suffix" ] - [ h3 - [ class "title" ] - [ i [ class "fa fa-map-marker" ] [] - , text <| " " ++ "Event List" - ] - , (viewFilterString address model) - , (viewListEvents events address model) - ] - - -viewFilterString : Signal.Address Msg -> Model -> Html -viewFilterString address model = - div [] - [ input - [ class "search form-control" - , placeholder "Filter events" - , value model.filterString - , on "input" targetValue (Signal.message address << EventList.Update.FilterEvents) - ] - [] - ] - - -viewListEvents : List Event -> Signal.Address Msg -> Model -> Html -viewListEvents events address model = - let - filteredEvents = - filterEventsByString events model.filterString - - hrefVoid = - href "javascript:void(0);" - - eventSelect event = - li [] - [ a [ hrefVoid , onClick address (EventList.Update.SelectEvent <| Just event.id) ] [ text event.label ] ] - - eventUnselect event = - li [] - [ span [] - [ a - [ class "unselect fa fa-times-circle" - , href "javascript:void(0);" - , onClick address (EventList.Update.UnSelectEvent) - ] [] - , text event.label - ] - ] - - getListItem : Event -> Html - getListItem event = - case model.selectedEvent of - Just id -> - if event.id == id - then eventUnselect(event) - else eventSelect(event) - - Nothing -> - eventSelect(event) - in - if List.isEmpty filteredEvents - then - div [] [ text "No results found" ] - else - ul [ class "authors" ] (List.map getListItem filteredEvents) diff --git a/src/elm/Leaflet/Model.elm b/src/elm/Leaflet/Model.elm deleted file mode 100644 index b6d1b58..0000000 --- a/src/elm/Leaflet/Model.elm +++ /dev/null @@ -1,20 +0,0 @@ -module Leaflet.Model exposing (..) - -type alias Marker = - { id : Int - , lat : Float - , lng : Float - } - -type alias Model = - { markers : List Marker - , selectedMarker : Maybe Int - , showMap : Bool - } - -initialModel : Model -initialModel = - { markers = [] - , selectedMarker = Nothing - , showMap = False - } diff --git a/src/elm/Leaflet/Update.elm b/src/elm/Leaflet/Update.elm deleted file mode 100644 index 1b74327..0000000 --- a/src/elm/Leaflet/Update.elm +++ /dev/null @@ -1,35 +0,0 @@ -module Leaflet.Update exposing (..) - -import Event.Model exposing (Event) -import Leaflet.Model as Leaflet exposing (initialModel, Marker, Model) - -init : Model -init = - initialModel - -type Msg - = SelectMarker (Maybe Int) - | SetMarkers (List Event) - | ToggleMap - | UnselectMarker - - -update : Msg -> Model -> Model -update action model = - case action of - SelectMarker val -> - { model | selectedMarker = val } - - SetMarkers events -> - { model | markers = eventToMarkers events } - - ToggleMap -> - { model | showMap = (not model.showMap) } - - UnselectMarker -> - { model | selectedMarker = Nothing } - -eventToMarkers : List Event -> List Leaflet.Marker -eventToMarkers events = - events - |> List.map (\event -> Leaflet.Marker event.id event.marker.lat event.marker.lng) diff --git a/src/elm/Leaflet/View.elm b/src/elm/Leaflet/View.elm deleted file mode 100644 index 7c872c9..0000000 --- a/src/elm/Leaflet/View.elm +++ /dev/null @@ -1,20 +0,0 @@ -module Leaflet.View exposing (..) - -import Leaflet.Model exposing (initialModel, Model) -import Leaflet.Update exposing (Msg) - -import Html exposing (div, span, Html) -import Html.Attributes exposing (id, style) - -view : Signal.Address Msg -> Model -> Html -view address model = - if model.showMap - then div [ style myStyle, id "map" ] [] - -- We use span, so the div element will be completely removed. - else span [] [] - -myStyle : List (String, String) -myStyle = - [ ("width", "600px") - , ("height", "400px") - ] diff --git a/src/elm/Main.elm b/src/elm/Main.elm deleted file mode 100644 index 67de012..0000000 --- a/src/elm/Main.elm +++ /dev/null @@ -1,108 +0,0 @@ -import App.Model as App exposing (Model) -import App.Router exposing (delta2update, location2action) -import App.Update exposing (init, update) -import App.View exposing (view) -import ArticleForm.Model exposing (PostStatus) -import ArticleForm.Update exposing (Msg) -import EventList.Update exposing (Msg) -import Pages.Event.Update exposing (Msg) -import Leaflet.Model exposing (Model) -import Pages.Article.Update exposing (Msg) -import RouteHash -import StartApp as StartApp -import Task exposing (Task) - - -inputs = - [ messages.signal - , Signal.map (App.Update.ChildArticleAction << Pages.Article.Update.ChildArticleFormAction << ArticleForm.Update.SetImageId) dropzoneUploadedFile - , Signal.map (App.Update.ChildArticleAction << Pages.Article.Update.ChildArticleFormAction << ArticleForm.Update.UpdateBody) ckeditor - , Signal.map (App.Update.ChildEventAction << Pages.Event.Update.ChildEventListAction << EventList.Update.SelectEvent) selectEvent - ] - -main = - app.html - -messages : Signal.Mailbox App.Update.Msg -messages = - Signal.mailbox App.Update.NoOp - -main = - Html.program - { init = App.Update.init, update = App.Update.update, view = App.View.view, subscriptions = inputs } - -port routeTasks : Signal (Task () ()) -port routeTasks = - RouteHash.start - { prefix = RouteHash.defaultPrefix - , address = messages.address - , models = app.model - , delta2update = App.Router.delta2update - , location2action = App.Router.location2action - } - --- Interactions with Leaflet maps - -type alias LeafletPort = - { leaflet : Leaflet.Model.Model - , events : List Int - } - -port mapManager : Signal LeafletPort -port mapManager = - let - getEvents model = - (.events >> .events) model - - getLeaflet model = - (.events >> .leaflet) model - - getLeafletPort model = - { events = List.map .id <| getEvents model - , leaflet = getLeaflet model - } - - in - Signal.map getLeafletPort app.model - -port selectEvent : Signal (Maybe Int) - --- Dropzone - -type alias ActivePagePort = - { accessToken : String - , activePage : String - , backendUrl : String - , postStatus : String - } - -port activePage : Signal ActivePagePort -port activePage = - let - pageAsString page = - case page of - App.Article -> "Article" - App.Event _ -> "Event" - App.GithubAuth -> "GithubAuth" - App.Login -> "Login" - App.PageNotFound -> "PageNotFound" - App.User -> "User" - - postStatusAsString status = - case status of - ArticleForm.Model.Busy -> "Busy" - ArticleForm.Model.Done -> "Done" - ArticleForm.Model.Ready -> "Ready" - - getPortData model = - { accessToken = model.accessToken - , activePage = pageAsString model.activePage - , backendUrl = (.config >> .backendConfig >> .backendUrl) model - , postStatus = postStatusAsString model.article.articleForm.postStatus - } - in - Signal.map getPortData app.model - -port dropzoneUploadedFile : Signal (Maybe Int) - -port ckeditor : Signal String diff --git a/src/elm/Pages/Article/Model.elm b/src/elm/Pages/Article/Model.elm deleted file mode 100644 index dbcccc3..0000000 --- a/src/elm/Pages/Article/Model.elm +++ /dev/null @@ -1,15 +0,0 @@ -module Pages.Article.Model exposing (..) - -import ArticleForm.Model as ArticleForm exposing (initialModel, Model) -import ArticleList.Model as ArticleList exposing (initialModel, Model) - -type alias Model = - { articleForm : ArticleForm.Model - , articleList : ArticleList.Model - } - -initialModel : Model -initialModel = - { articleForm = ArticleForm.initialModel - , articleList = ArticleList.initialModel - } diff --git a/src/elm/Pages/Article/Update.elm b/src/elm/Pages/Article/Update.elm deleted file mode 100644 index c017e29..0000000 --- a/src/elm/Pages/Article/Update.elm +++ /dev/null @@ -1,61 +0,0 @@ -module Pages.Article.Update exposing (..) - -import ArticleForm.Update exposing (Msg) -import ArticleList.Update exposing (Msg) -import Config.Model exposing (BackendConfig) -import Pages.Article.Model exposing (Model) -import Task exposing (succeed) - -type Msg - = Activate - | ChildArticleFormAction ArticleForm.Update.Msg - | ChildArticleListAction ArticleList.Update.Msg - -type alias UpdateContext = - { accessToken : String - , backendConfig : BackendConfig - } - -init : (Model, Cmd Msg) -init = - ( Pages.Article.Model.initialModel - , Cmd.none - ) - -update : UpdateContext -> Msg -> Pages.Article.Model.Model -> (Pages.Article.Model.Model, Cmd Msg) -update context action model = - case action of - Activate -> - ( model - , Task.succeed (ChildArticleListAction ArticleList.Update.GetData) |> Cmd.task - ) - - ChildArticleFormAction act -> - let - (childModel, childCmd, maybeArticle) = ArticleForm.Update.update context act model.articleForm - - defaultCmd = - [ Cmd.map ChildArticleFormAction childCmd ] - - effects' = - case maybeArticle of - Just article -> - (Task.succeed (ChildArticleListAction <| ArticleList.Update.AppendArticle article) |> Cmd.task) - :: - defaultCmd - Nothing -> - defaultCmd - - in - - ( { model | articleForm = childModel } - , Cmd.batch effects' - ) - - ChildArticleListAction act -> - let - (childModel, childCmd) = ArticleList.Update.update context act model.articleList - in - ( { model | articleList = childModel } - , Cmd.map ChildArticleListAction childCmd - ) diff --git a/src/elm/Pages/Article/View.elm b/src/elm/Pages/Article/View.elm deleted file mode 100644 index 6657a80..0000000 --- a/src/elm/Pages/Article/View.elm +++ /dev/null @@ -1,26 +0,0 @@ -module Pages.Article.View exposing (..) - -import ArticleForm.View as ArticleForm exposing (view) -import ArticleList.View as ArticleList exposing (view) -import Html exposing (i, button, div, label, h2, h3, input, img, li, text, textarea, span, ul, Html) -import Html.Attributes exposing (action, class, id, disabled, name, placeholder, property, required, size, src, style, type', value) -import Pages.Article.Model as Article exposing (Model) -import Pages.Article.Update exposing (Msg) - - -view : Signal.Address Msg -> Article.Model -> Html -view address model = - let - childArticleFormAddress = - Signal.forwardTo address Pages.Article.Update.ChildArticleFormAction - - childArticleListAddress = - Signal.forwardTo address Pages.Article.Update.ChildArticleListAction - in - div - [ id "article-page" - , class "container" - ] - [ ArticleForm.view childArticleFormAddress model.articleForm - , ArticleList.view childArticleListAddress model.articleList - ] diff --git a/src/elm/Pages/Event/Model.elm b/src/elm/Pages/Event/Model.elm deleted file mode 100644 index 00fd557..0000000 --- a/src/elm/Pages/Event/Model.elm +++ /dev/null @@ -1,38 +0,0 @@ -module Pages.Event.Model exposing (..) - -import Event.Model exposing (Event) -import EventAuthorFilter.Model as EventAuthorFilter exposing (initialModel, Model) -import EventCompanyFilter.Model as EventCompanyFilter exposing (initialModel, Model) -import EventList.Model as EventList exposing (initialModel, Model) - -import Http exposing (Error) -import Leaflet.Model exposing (initialModel, Model) -import Time exposing (Time) - -type alias Id = Int -type alias CompanyId = Int - -type Status = - Init - | Fetching (Maybe CompanyId) - | Fetched (Maybe CompanyId) Time.Time - | HttpError Http.Error - -type alias Model = - { events : List Event - , eventList: EventList.Model - , status : Status - , eventCompanyFilter : EventCompanyFilter.Model - , eventAuthorFilter : EventAuthorFilter.Model - , leaflet : Leaflet.Model.Model - } - -initialModel : Model -initialModel = - { events = [] - , eventList = EventList.initialModel - , status = Init - , eventCompanyFilter = EventCompanyFilter.initialModel - , eventAuthorFilter = EventAuthorFilter.initialModel - , leaflet = Leaflet.Model.initialModel - } diff --git a/src/elm/Pages/Event/Router.elm b/src/elm/Pages/Event/Router.elm deleted file mode 100644 index a7d7ad8..0000000 --- a/src/elm/Pages/Event/Router.elm +++ /dev/null @@ -1,28 +0,0 @@ -module Pages.Event.Router exposing (..) - -import Pages.Event.Model as Event exposing (Model) -import RouteHash exposing (HashUpdate) -import String exposing (toInt) - -delta2update : Model -> Model -> Maybe HashUpdate -delta2update previous current = - let - url = - case current.eventCompanyFilter of - Just companyId -> [ toString (companyId) ] - Nothing -> [] - in - Just <| RouteHash.set url - -location2company : List String -> Maybe Int -location2company list = - case List.head list of - Just eventId -> - case String.toInt eventId of - Ok val -> - Just val - Err _ -> - Nothing - - Nothing -> - Nothing diff --git a/src/elm/Pages/Event/Update.elm b/src/elm/Pages/Event/Update.elm deleted file mode 100644 index 3756ac9..0000000 --- a/src/elm/Pages/Event/Update.elm +++ /dev/null @@ -1,260 +0,0 @@ -module Pages.Event.Update exposing (..) - -import Config exposing (cacheTtl) -import Config.Model exposing (BackendConfig) -import Company.Model as Company exposing (Model) -import Event.Decoder exposing (decode) -import Event.Model exposing (Event) -import EventAuthorFilter.Update exposing (Msg) -import EventCompanyFilter.Update exposing (Msg) -import EventList.Update exposing (Msg) -import EventList.Utils exposing (filterEventsByString) -import Http exposing (Error) -import Leaflet.Update exposing (Msg) -import Pages.Event.Model as Event exposing (Model) -import Pages.Event.Utils exposing (filterEventsByAuthor) -import Task exposing (andThen, succeed) -import Time exposing (Time) - -type alias Id = Int -type alias CompanyId = Int -type alias Model = Event.Model - -init : (Model, Cmd Msg) -init = - ( Event.initialModel - , Cmd.none - ) - -type Msg - = NoOp - | GetData (Maybe CompanyId) - | GetDataFromServer (Maybe CompanyId) - | UpdateDataFromServer (Result Http.Error (List Event)) (Maybe CompanyId) Time.Time - - -- Child actions - | ChildEventAuthorFilterAction EventAuthorFilter.Update.Msg - | ChildEventCompanyFilterAction EventCompanyFilter.Update.Msg - | ChildEventListAction EventList.Update.Msg - | ChildLeafletAction Leaflet.Update.Msg - - -- Page - | Activate (Maybe CompanyId) - | Deactivate - - -type alias Context = - { accessToken : String - , backendConfig : BackendConfig - , companies : List Company.Model - } - -update : Context -> Msg -> Model -> (Model, Cmd Msg) -update context action model = - case action of - ChildEventAuthorFilterAction act -> - let - -- The child component doesn't have effects. - childModel = - EventAuthorFilter.Update.update act model.eventAuthorFilter - in - ( { model | eventAuthorFilter = childModel } - -- Filter out the events, before sending the events' markers. - , Task.succeed (ChildLeafletAction <| Leaflet.Update.SetMarkers (filterEventsByAuthor model.events childModel)) |> Cmd.task - ) - - ChildEventCompanyFilterAction act -> - let - childModel = - EventCompanyFilter.Update.update context.companies act model.eventCompanyFilter - - maybeCompanyId = - -- Reach into the selected company, in order to invoke getting the - -- data from server. - case act of - EventCompanyFilter.Update.SelectCompany maybeCompanyId -> - maybeCompanyId - - in - ( { model | eventCompanyFilter = childModel } - , Task.succeed (GetData maybeCompanyId) |> Cmd.task - ) - - ChildEventListAction act -> - let - filteredEventsByAuthor = - filterEventsByAuthor model.events model.eventAuthorFilter - - -- The child component doesn't have effects. - childModel = - EventList.Update.update filteredEventsByAuthor act model.eventList - - childAction = - case act of - EventList.Update.FilterEvents val -> - -- Filter out the events, before sending the events' markers. - Leaflet.Update.SetMarkers (filterEventsByString filteredEventsByAuthor val) - - EventList.Update.SelectEvent val -> - Leaflet.Update.SelectMarker val - - EventList.Update.UnSelectEvent -> - Leaflet.Update.UnselectMarker - in - ( { model | eventList = childModel } - , Task.succeed (ChildLeafletAction <| childAction) |> Cmd.task - ) - - ChildLeafletAction act -> - let - childModel = - Leaflet.Update.update act model.leaflet - in - ( {model | leaflet = childModel } - , Cmd.none - ) - - GetData maybeCompanyId -> - let - noFx = - (model, Cmd.none) - - getFx = - (model, getDataFromCache model.status maybeCompanyId) - in - case model.status of - Event.Fetching id -> - if id == maybeCompanyId - -- We are already fetching this data - then noFx - -- We are fetching data, but for a different company ID, - -- so we need to re-fetch. - else getFx - - _ -> - getFx - - GetDataFromServer maybeCompanyId -> - let - backendUrl = - (.backendConfig >> .backendUrl) context - - url = - backendUrl ++ "/api/v1.0/events" - in - ( { model | status = Event.Fetching maybeCompanyId } - , getJson url maybeCompanyId context.accessToken - ) - - NoOp -> - (model, Cmd.none) - - UpdateDataFromServer result maybeCompanyId timestamp -> - case result of - Ok events -> - let - filteredEventsByAuthor = - filterEventsByAuthor events model.eventAuthorFilter - - filteredEvents = - filterEventsByString filteredEventsByAuthor model.eventList.filterString - in - ( { model - | events = events - , status = Event.Fetched maybeCompanyId timestamp - } - , Cmd.batch - [ Task.succeed (ChildEventAuthorFilterAction EventAuthorFilter.Update.UnSelectAuthor) |> Cmd.task - , Task.succeed (ChildEventListAction EventList.Update.UnSelectEvent) |> Cmd.task - , Task.succeed (ChildEventListAction <| EventList.Update.FilterEvents "") |> Cmd.task - ] - ) - - Err msg -> - ( { model | status = Event.HttpError msg } - , Cmd.none - ) - - Activate maybeCompanyId -> - let - childModel = - Leaflet.Update.update Leaflet.Update.ToggleMap model.leaflet - - in - ( { model | leaflet = childModel } - , Cmd.batch - [ Task.succeed (GetData maybeCompanyId) |> Cmd.task - , Task.succeed (ChildEventCompanyFilterAction <| EventCompanyFilter.Update.SelectCompany maybeCompanyId) |> Cmd.task - ] - ) - - Deactivate -> - let - childModel = - Leaflet.Update.update Leaflet.Update.ToggleMap model.leaflet - in - ( { model | leaflet = childModel } - , Cmd.none - ) - - --- EFFECTS - -getDataFromCache : Event.Status -> Maybe CompanyId -> Cmd Msg -getDataFromCache status maybeCompanyId = - let - getFx = - Task.succeed <| GetDataFromServer maybeCompanyId - - actionTask = - case status of - Event.Fetched id fetchTime -> - if id == maybeCompanyId - then - Task.map (\currentTime -> - if fetchTime + Config.cacheTtl > currentTime - then NoOp - else GetDataFromServer maybeCompanyId - ) Time.now - else - getFx - - _ -> - getFx - - in - Cmd.task actionTask - - -getJson : String -> Maybe CompanyId -> String -> Cmd Msg -getJson url maybeCompanyId accessToken = - let - params = - [ ("access_token", accessToken) ] - - params' = - case maybeCompanyId of - Just id -> - -- Filter by company - ("filter[company]", toString id) :: params - - Nothing -> - params - - - encodedUrl = - Http.url url params' - - httpTask = - Task.toResult <| - Http.get Event.Decoder.decode encodedUrl - - actionTask = - httpTask `andThen` (\result -> - Task.map (\timestamp -> - UpdateDataFromServer result maybeCompanyId timestamp - ) Time.now - ) - - in - Cmd.task actionTask diff --git a/src/elm/Pages/Event/Utils.elm b/src/elm/Pages/Event/Utils.elm deleted file mode 100644 index bc8ebdd..0000000 --- a/src/elm/Pages/Event/Utils.elm +++ /dev/null @@ -1,13 +0,0 @@ -module Pages.Event.Utils exposing (..) - -import EventAuthorFilter.Model as EventAuthorFilter exposing (Model) -import Event.Model exposing (Event) - -filterEventsByAuthor : List Event -> EventAuthorFilter.Model -> List Event -filterEventsByAuthor events authorFilter = - case authorFilter of - Just id -> - List.filter (\event -> event.author.id == id) events - - Nothing -> - events diff --git a/src/elm/Pages/Event/View.elm b/src/elm/Pages/Event/View.elm deleted file mode 100644 index 4710d84..0000000 --- a/src/elm/Pages/Event/View.elm +++ /dev/null @@ -1,63 +0,0 @@ -module Pages.Event.View exposing (..) - -import Company.Model as Company exposing (Model) -import EventAuthorFilter.View exposing (view) -import EventCompanyFilter.View exposing (view) -import EventList.View exposing (view) -import Html exposing (h3, a, i, div, input, text, select, span, li, option, ul, Html) -import Html.Attributes exposing (class, hidden, href, id, placeholder, selected, style, value) -import Pages.Event.Model exposing (initialModel, Model) -import Pages.Event.Update exposing (Msg) -import Pages.Event.Utils exposing (filterEventsByAuthor) - -type alias Msg = Pages.Event.Update.Msg -type alias CompanyId = Int -type alias Model = Pages.Event.Model.Model - -type alias Context = - { companies : List Company.Model } - -view : Context -> Signal.Address Msg -> Model -> Html -view context address model = - let - - childEventAuthorFilterAddress = - Signal.forwardTo address Pages.Event.Update.ChildEventAuthorFilterAction - - childEventCompanyFilterAddress = - Signal.forwardTo address Pages.Event.Update.ChildEventCompanyFilterAction - - childEventListAddress = - Signal.forwardTo address Pages.Event.Update.ChildEventListAction - - filteredEvents = - filterEventsByAuthor model.events model.eventAuthorFilter - - in - div - [ id "events-page" - , class "container" - ] - [ div [class "row"] - [ div [class "col-md-3 first"] - [ (EventCompanyFilter.View.view context.companies childEventCompanyFilterAddress model.eventCompanyFilter) - , (EventAuthorFilter.View.view model.events childEventAuthorFilterAddress model.eventAuthorFilter) - , (EventList.View.view filteredEvents childEventListAddress model.eventList) - ] - - , div - [ class "col-md-9 last"] - [ div - [ class "map-container wrapper -suffix" ] - [ h3 - [ class "title" ] - [ i [ class "fa fa-globe" ] [] - , text <| " " ++ "Map" - ] - , div - [ class "map-wrapper" ] - [ div [ id "map"] [] ] - ] - ] - ] - ] diff --git a/src/elm/Pages/GithubAuth/Model.elm b/src/elm/Pages/GithubAuth/Model.elm deleted file mode 100644 index a289d4f..0000000 --- a/src/elm/Pages/GithubAuth/Model.elm +++ /dev/null @@ -1,25 +0,0 @@ -module Pages.GithubAuth.Model exposing (..) - -import Http exposing (Error) - -type alias AccessToken = String - -type Status = Init - | Error String - | Fetching - | Fetched - | HttpError Http.Error - - -type alias Model = - { accessToken: AccessToken - , status : Status - , code : Maybe String - } - -initialModel : Model -initialModel = - { accessToken = "" - , status = Init - , code = Nothing - } diff --git a/src/elm/Pages/GithubAuth/Update.elm b/src/elm/Pages/GithubAuth/Update.elm deleted file mode 100644 index 1364add..0000000 --- a/src/elm/Pages/GithubAuth/Update.elm +++ /dev/null @@ -1,115 +0,0 @@ -module Pages.GithubAuth.Update exposing (..) - -import Config.Model exposing (BackendConfig) -import Dict exposing (get) -import Http exposing (Error) -import Json.Decode as JD exposing ((:=)) -import Json.Encode as JE exposing (..) -import Pages.GithubAuth.Model as GithubAuth exposing (initialModel, Model) -import Task exposing (map) -import UrlParameterParser exposing (ParseResult, parseSearchString) -import WebAPI.Location exposing (location) - -type alias AccessToken = String - -init : (Model, Cmd Msg) -init = - ( initialModel - , Cmd.none - ) - - -type Msg - = Activate - | AuthorizeUser String - | SetError String - | SetAccessToken AccessToken - | UpdateAccessTokenFromServer (Result Http.Error AccessToken) - -type alias UpdateContext = - { backendConfig : BackendConfig - } - -update : UpdateContext -> Msg -> Model -> (Model, Cmd Msg) -update context action model = - case action of - Activate -> - (model, getCodeFromUrl) - - AuthorizeUser code -> - let - backendUrl = - (.backendConfig >> .backendUrl) context - in - ( model - , getJson backendUrl code - ) - - SetError msg -> - ( { model | status = GithubAuth.Error msg } - , Cmd.none - ) - - SetAccessToken token -> - ( { model | accessToken = token } - , Cmd.none - ) - - UpdateAccessTokenFromServer result -> - case result of - Ok token -> - ( { model | status = GithubAuth.Fetched } - , Task.succeed (SetAccessToken token) |> Cmd.task - ) - Err msg -> - ( { model | status = GithubAuth.HttpError msg } - -- @todo: Improve. - , Task.succeed (SetError "HTTP error") |> Cmd.task - ) - --- EFFECTS - -getCodeFromUrl : Cmd Msg -getCodeFromUrl = - let - errAction = - SetError "code property is missing form URL." - - getAction location = - case (parseSearchString location.search) of - UrlParameterParser.UrlParams dict -> - case (Dict.get "code" dict) of - Just val -> - AuthorizeUser val - Nothing -> - errAction - - UrlParameterParser.Error _ -> - errAction - - actionTask = - Task.map getAction WebAPI.Location.location - in - Cmd.task actionTask - - -getJson : String -> String -> Cmd Msg -getJson backendUrl code = - Http.post - decodeAccessToken - (backendUrl ++ "/auth/github") - (Http.string <| dataToJson code ) - |> Task.toResult - |> Task.map UpdateAccessTokenFromServer - |> Cmd.task - - -dataToJson : String -> String -dataToJson code = - JE.encode 0 - <| JE.object - [ ("code", JE.string code) ] - -decodeAccessToken : JD.Decoder AccessToken -decodeAccessToken = - JD.at ["access_token"] <| JD.string diff --git a/src/elm/Pages/GithubAuth/View.elm b/src/elm/Pages/GithubAuth/View.elm deleted file mode 100644 index 837b77f..0000000 --- a/src/elm/Pages/GithubAuth/View.elm +++ /dev/null @@ -1,35 +0,0 @@ -module Pages.GithubAuth.View exposing (..) - --- import Config.Model exposing (BackendConfig) --- import Dict exposing (get) -import Html exposing (a, div, i, text, Html) -import Html.Attributes exposing (class, href, id) --- import Http exposing (Error) --- import Json.Decode as JD exposing ((:=)) --- import Json.Encode as JE exposing (..) -import Pages.GithubAuth.Model as GithubAuth exposing (initialModel, Model) -import Pages.GithubAuth.Update exposing (Msg) - - -view : Signal.Address Msg -> Model -> Html -view address model = - let - spinner = - i [ class "fa fa-spinner fa-spin" ] [] - - content = - case model.status of - GithubAuth.Error msg -> - div [] - [text <| "Error:" ++ msg - , a [ href "#!/login"] [text "Back to Login"] - ] - - _ -> - spinner - - in - div - [ id "github-auth-page" ] - [ div [ class "container"] [ content ] - ] diff --git a/src/elm/Pages/Login/Model.elm b/src/elm/Pages/Login/Model.elm deleted file mode 100644 index 6030077..0000000 --- a/src/elm/Pages/Login/Model.elm +++ /dev/null @@ -1,39 +0,0 @@ -module Pages.Login.Model exposing (..) - -import Http exposing (Error) - -type alias AccessToken = String - -type alias LoginForm = - { name: String - , pass : String - } - -type UserMessage - = None - | Error String - -type Status - = Init - | Fetching - | Fetched - | HttpError Http.Error - -type alias Model = - { accessToken: AccessToken - , hasAccessTokenInStorage : Bool - , loginForm : LoginForm - , status : Status - , userMessage : UserMessage - } - -initialModel : Model -initialModel = - { accessToken = "" - -- We start by assuming there's already an access token it the localStorage. - -- While this property is set to True, the login form will not appear. - , hasAccessTokenInStorage = True - , loginForm = LoginForm "demo" "1234" - , status = Init - , userMessage = None - } diff --git a/src/elm/Pages/Login/Test.elm b/src/elm/Pages/Login/Test.elm deleted file mode 100644 index 3c85375..0000000 --- a/src/elm/Pages/Login/Test.elm +++ /dev/null @@ -1,82 +0,0 @@ -module Pages.Login.Test exposing (..) - -import ElmTest exposing (..) - -import Config.Model exposing (initialBackendConfig) -import Http exposing (Error) -import Pages.Login.Model exposing (initialModel, Model) -import Pages.Login.Update exposing (Msg) - -type alias Model = Pages.Login.Model.Model - -accessTokenSuite : Test -accessTokenSuite = - let - pass = - .loginForm >> .pass - in - suite "Set access token tests" - [ test "on empty set access token, password is reset" (assertEqual "" (pass <| fst(setAccessToken ""))) - , test "on set access token, password is reset" (assertEqual "" (pass <| fst(setAccessToken "accessToken"))) - ] - -formSuite : Test -formSuite = - let - -- Shorthand, to get to the form's properties. - name = - .loginForm >> .name - - pass = - .loginForm >> .pass - in - suite "Login form tests" - [ test "empty name" (assertEqual "" (name <| fst(updateName ""))) - , test "simple name" (assertEqual "foo" (name <| fst(updateName "foo"))) - -- Password - , test "empty password" (assertEqual "" (pass <| fst(updatePass ""))) - , test "simple password" (assertEqual "bar" (pass <| fst(updatePass "bar"))) - - -- Submit form - , test "first submit, status is Fetching" (assertEqual Pages.Login.Model.Fetching (.status <| fst(submitForm Pages.Login.Model.Init))) - , test "ongoing submit" (assertEqual Pages.Login.Model.Fetching (.status <| fst(submitForm Pages.Login.Model.Fetching))) - , test "submit done without errors" (assertEqual Pages.Login.Model.Fetched (.status <| fst(submitForm Pages.Login.Model.Fetched))) - , test "submit after another submit with errors" (assertEqual Pages.Login.Model.Fetching (.status <| fst(submitForm <| Pages.Login.Model.HttpError Http.NetworkError))) - ] - -updateName : String -> (Model, Cmd Msg) -updateName val = - Pages.Login.Update.update updateContext (Pages.Login.Update.UpdateName val) Pages.Login.Model.initialModel - -updatePass : String -> (Model, Cmd Msg) -updatePass val = - Pages.Login.Update.update updateContext (Pages.Login.Update.UpdatePass val) Pages.Login.Model.initialModel - -submitForm : Pages.Login.Model.Status -> (Model, Cmd Msg) -submitForm status = - let - model = - Pages.Login.Model.initialModel - - model' = - { model | status = status } - - in - Pages.Login.Update.update updateContext Pages.Login.Update.SubmitForm model' - -setAccessToken : String -> (Model, Cmd Msg) -setAccessToken val = - Pages.Login.Update.update updateContext (Pages.Login.Update.SetAccessToken val) Pages.Login.Model.initialModel - - -updateContext : Pages.Login.Update.Context -updateContext = - { backendConfig = initialBackendConfig - } - -all : Test -all = - suite "All Login tests" - [ accessTokenSuite - , formSuite - ] diff --git a/src/elm/Pages/Login/Update.elm b/src/elm/Pages/Login/Update.elm deleted file mode 100644 index c97d560..0000000 --- a/src/elm/Pages/Login/Update.elm +++ /dev/null @@ -1,155 +0,0 @@ -module Pages.Login.Update exposing (..) - -import Pages.Login.Model exposing (initialModel, Model) - -import Base64 exposing (encode) -import Config.Model exposing (BackendConfig) -import Http exposing (Error) -import Json.Decode as JD exposing ((:=)) -import Storage exposing (getItem) -import Task exposing (Task) -import Utils.Http exposing (getErrorMessageFromHttpResponse) - -type alias AccessToken = String - -init : (Model, Cmd Msg) -init = - ( initialModel - -- Try to get an existing access token. - , getInputFromStorage - ) - -type Msg - = UpdateAccessTokenFromServer (Result Http.Error AccessToken) - | UpdateAccessTokenFromStorage (Result String AccessToken) - | UpdateName String - | UpdatePass String - | SetAccessToken AccessToken - | SetUserMessage Pages.Login.Model.UserMessage - | SubmitForm - -type alias Context = - { backendConfig : BackendConfig - } - -update : Context -> Msg -> Model -> (Model, Cmd Msg) -update context action model = - case action of - UpdateName name -> - let - loginForm = model.loginForm - updatedLoginForm = { loginForm | name = name } - in - ( { model | loginForm = updatedLoginForm } - , Cmd.none - ) - - UpdatePass pass -> - let - loginForm = model.loginForm - updatedLoginForm = { loginForm | pass = pass } - in - ( {model | loginForm = updatedLoginForm } - , Cmd.none - ) - - SubmitForm -> - let - backendUrl = - (.backendConfig >> .backendUrl) context - - url = - backendUrl ++ "/api/login-token" - - credentials : String - credentials = encodeCredentials(model.loginForm.name, model.loginForm.pass) - in - if model.status == Pages.Login.Model.Fetching || model.status == Pages.Login.Model.Fetched - then - (model, Cmd.none) - else - ( { model | status = Pages.Login.Model.Fetching } - , Cmd.batch - [ Task.succeed (SetUserMessage Pages.Login.Model.None) |> Cmd.task - , getJson url credentials - ] - ) - - SetAccessToken token -> - ( { model - | accessToken = token - -- This is a good time also to hide the password. - , loginForm = Pages.Login.Model.LoginForm model.loginForm.name "" - } - , Cmd.none - ) - - SetUserMessage userMessage -> - ( { model | userMessage = userMessage } - , Cmd.none - ) - - UpdateAccessTokenFromServer result -> - case result of - Ok token -> - ( { model | status = Pages.Login.Model.Fetched } - , Task.succeed (SetAccessToken token) |> Cmd.task - ) - Err err -> - let - message = - getErrorMessageFromHttpResponse err - in - ( { model | status = Pages.Login.Model.HttpError err } - , Task.succeed (SetUserMessage <| Pages.Login.Model.Error message) |> Cmd.task - ) - - UpdateAccessTokenFromStorage result -> - case result of - Ok token -> - ( model - , Task.succeed (SetAccessToken token) |> Cmd.task - ) - Err err -> - -- There was no access token in the storage, so show the login form - ( { model | hasAccessTokenInStorage = False } - , Cmd.none - ) - - -getInputFromStorage : Cmd Msg -getInputFromStorage = - Storage.getItem "access_token" JD.string - |> Task.toResult - |> Task.map UpdateAccessTokenFromStorage - |> Cmd.task - - --- EFFECTS - -encodeCredentials : (String, String) -> String -encodeCredentials (name, pass) = - let - base64 = Base64.encode(name ++ ":" ++ pass) - in - case base64 of - Ok result -> result - Err err -> "" - -getJson : String -> String -> Cmd Msg -getJson url credentials = - Http.send Http.defaultSettings - { verb = "GET" - , headers = [("Authorization", "Basic " ++ credentials)] - , url = url - , body = Http.empty - } - |> Http.fromJson decodeAccessToken - |> Task.toResult - |> Task.map UpdateAccessTokenFromServer - |> Cmd.task - - -decodeAccessToken : JD.Decoder AccessToken -decodeAccessToken = - JD.at ["access_token"] <| JD.string diff --git a/src/elm/Pages/Login/View.elm b/src/elm/Pages/Login/View.elm deleted file mode 100644 index 73d0819..0000000 --- a/src/elm/Pages/Login/View.elm +++ /dev/null @@ -1,134 +0,0 @@ -module Pages.Login.View exposing (..) - -import Pages.Login.Model exposing (initialModel, Model) -import Pages.Login.Update exposing (Msg) - -import Config.Model exposing (BackendConfig) -import Html exposing (a, button, div, i, input, h2, hr, span, text, Html) -import Html.Attributes exposing (action, class, disabled, id, hidden, href, placeholder, required, size, style, type', value) -import Html.Events exposing (on, onClick, onSubmit, targetValue) -import String exposing (isEmpty) - -type alias ViewContext = - { backendConfig : BackendConfig - } - -view : ViewContext -> Signal.Address Msg -> Model -> Html -view context address model = - let - modelForm = - model.loginForm - - isFormEmpty = - String.isEmpty modelForm.name || String.isEmpty modelForm.pass - - isFetchStatus = - model.status == Pages.Login.Model.Fetching || model.status == Pages.Login.Model.Fetched - - githubClientId = - (.backendConfig >> .githubClientId) context - - githubUrl = - "https://github.com/login/oauth/authorize?client_id=" ++ githubClientId ++ "&scope=user:email" - - - githubLogin = - div - [ class "btn btn-lg btn-primary btn-block"] - [ a - [ href githubUrl] - [ i [ class "fa fa-github", style [("margin-right", "10px")] ] [] - , span [] [ text "Login with GitHub" ] - ] - ] - - loginForm = - Html.form - [ onSubmit address Pages.Login.Update.SubmitForm - , action "javascript:void(0);" - , class "form-signin" - -- Don't show the form while checking for the access token from the - -- storage. - , hidden model.hasAccessTokenInStorage - ] - - -- Form title - [ h2 [] [ text "Please login" ] - -- UserName - , githubLogin - , div - [ style [("margin-bottom", "20px"), ("margin-top", "20px"), ("text-align", "center")] ] - [ text "OR" ] - , div - [ class "input-group" ] - [ span - [ class "input-group-addon" ] - [ i [ class "glyphicon glyphicon-user" ] [] ] - , input - [ type' "text" - , class "form-control" - , placeholder "Name" - , value model.loginForm.name - , on "input" targetValue (Signal.message address << Pages.Login.Update.UpdateName) - , size 40 - , required True - , disabled (isFetchStatus) - ] - [] - ] - -- Password - , div - [ class "input-group"] - [ span - [ class "input-group-addon" ] - [ i [ class "fa fa-lock fa-lg" ] [] ] - , input - [ type' "password" - , class "form-control" - , placeholder "Password" - , value modelForm.pass - , on "input" targetValue (Signal.message address << Pages.Login.Update.UpdatePass) - , size 40 - , required True - , disabled (isFetchStatus) - ] - [] - ] - - -- Submit button - , button - [ onClick address Pages.Login.Update.SubmitForm - , class "btn btn-lg btn-primary btn-block" - , disabled (isFetchStatus || isFormEmpty) - ] - [ span [ hidden <| not isFetchStatus] [ spinner ] - , span [ hidden isFetchStatus ] [ text "Login" ] ] - ] - - spinner = - i [ class "fa fa-spinner fa-spin" ] [] - - userMessage = - case model.userMessage of - Pages.Login.Model.None -> - div [] [] - Pages.Login.Model.Error message -> - div [ style [("text-align", "center")]] [ text message ] - - in - div [ id "login-page" ] [ - hr [] [] - , div - [ class "container" ] - [ userMessage - , div - [ class "wrapper" ] - [ loginForm - , div - [ class "text-center" - , hidden (not (model.status == Pages.Login.Model.Fetching) && not model.hasAccessTokenInStorage) ] - [ text "Loading ..." ] - ] - ] - , hr [] [] - ] diff --git a/src/elm/Pages/PageNotFound/View.elm b/src/elm/Pages/PageNotFound/View.elm deleted file mode 100644 index 587efc7..0000000 --- a/src/elm/Pages/PageNotFound/View.elm +++ /dev/null @@ -1,23 +0,0 @@ -module Pages.PageNotFound.View exposing (..) - -import Html exposing (a, i, div, h2, text, Html) -import Html.Attributes exposing (class, id, href, style) - --- VIEW - -view : Html -view = - div - [ id "page-not-found" - , class "container" - ] - [ div - [ class "wrapper text-center" ] - [ - div - [ class "box" ] - [ h2 [] [ text "This is a 404 page!" ] - , a [ href "#!/" ] [ text "Back to safety" ] - ] - ] - ] diff --git a/src/elm/Pages/User/Decoder.elm b/src/elm/Pages/User/Decoder.elm deleted file mode 100644 index 63b931c..0000000 --- a/src/elm/Pages/User/Decoder.elm +++ /dev/null @@ -1,28 +0,0 @@ -module Pages.User.Decoder exposing (..) - -import Company.Model as Company exposing (Model) -import Http exposing (Error) -import Json.Decode as Json exposing ((:=)) -import String -import Task - -import Pages.User.Model as User exposing (..) - -decode : Json.Decoder (User.Id, String, List Company.Model) -decode = - let - -- Cast String to Int. - number : Json.Decoder Int - number = - Json.oneOf [ Json.int, Json.customDecoder Json.string String.toInt ] - - company = - Json.object2 Company.Model - ("id" := number) - ("label" := Json.string) - in - Json.at ["data", "0"] - <| Json.object3 (,,) - ("id" := number) - ("label" := Json.string) - ("companies" := Json.list company) diff --git a/src/elm/Pages/User/Model.elm b/src/elm/Pages/User/Model.elm deleted file mode 100644 index acc38c7..0000000 --- a/src/elm/Pages/User/Model.elm +++ /dev/null @@ -1,37 +0,0 @@ -module Pages.User.Model exposing (..) - -import Company.Model as Company exposing (initialModel, Model) -import Http exposing (Error) - -type alias Id = Int -type alias AccessToken = String - -type User = Anonymous | LoggedIn String - -type Status = - Init - | Fetching - | Fetched - | HttpError Error - -type alias Model = - { name : User - , id : Id - , status : Status - , accessToken : AccessToken - - -- Child components - , companies : List Company.Model - } - - -initialModel : Model -initialModel = - { name = Anonymous - , id = 0 - , status = Init - , accessToken = "" - - -- Child components - , companies = [Company.initialModel] - } diff --git a/src/elm/Pages/User/Update.elm b/src/elm/Pages/User/Update.elm deleted file mode 100644 index c23e6af..0000000 --- a/src/elm/Pages/User/Update.elm +++ /dev/null @@ -1,100 +0,0 @@ -module Pages.User.Update exposing (..) - -import Config.Model exposing (BackendConfig) -import Company.Model as Company exposing (initialModel, Model) -import Http exposing (Error) -import Pages.User.Model as User exposing (Model) -import Pages.User.Decoder exposing (decode) -import Task exposing (succeed) - -type alias Id = Int -type alias AccessToken = String -type alias Model = User.Model - -type alias UpdateContext = - { accessToken : AccessToken - , backendConfig : BackendConfig - } - -type Msg - = GetDataFromServer - | NoOp (Maybe ()) - | SetAccessToken AccessToken - | UpdateDataFromServer (Result Http.Error (Id, String, List Company.Model)) - -init : (Model, Cmd Msg) -init = - ( User.initialModel - , Cmd.none - ) - -update : UpdateContext -> Msg -> Model -> (Model, Cmd Msg) -update context action model = - case action of - NoOp _ -> - (model, Cmd.none) - - GetDataFromServer -> - let - backendUrl = - (.backendConfig >> .backendUrl) context - - url = - backendUrl ++ "/api/v1.0/me" - in - if model.status == User.Fetching || model.status == User.Fetched - then - (model, Cmd.none) - else - ( { model | status = User.Fetching } - , getJson url context.accessToken - ) - - UpdateDataFromServer result -> - let - model' = - { model | status = User.Fetched} - in - case result of - Ok (id, name, companies) -> - ( {model' - | id = id - , name = User.LoggedIn name - , companies = companies - } - , Cmd.none - ) - Err msg -> - let - effects = - case msg of - Http.BadResponse code _ -> - if (code == 401) - -- Token is wrong, so remove any existing one. - then Task.succeed (SetAccessToken "") |> Cmd.task - else Cmd.none - - _ -> - Cmd.none - - in - ( { model' | status = User.HttpError msg } - , effects - ) - - SetAccessToken accessToken -> - ( {model | accessToken = accessToken} - , Cmd.none - ) - --- Cmd - -getJson : String -> AccessToken -> Cmd Action -getJson url accessToken = - let - encodedUrl = Http.url url [ ("access_token", accessToken) ] - in - Http.get decode encodedUrl - |> Task.toResult - |> Task.map UpdateDataFromServer - |> Cmd.task diff --git a/src/elm/Pages/User/View.elm b/src/elm/Pages/User/View.elm deleted file mode 100644 index 46ab35d..0000000 --- a/src/elm/Pages/User/View.elm +++ /dev/null @@ -1,42 +0,0 @@ -module Pages.User.View exposing (..) - -import Company.Model as Company exposing (Model) -import Html exposing (..) -import Html.Attributes exposing (..) -import Pages.User.Model as User exposing (Model) -import Pages.User.Update exposing (Msg) - - -view : Signal.Address Msg -> User.Model -> Html -view address model = - case model.name of - User.Anonymous -> - div [] [ text "This is wrong - anon user cannot reach this!"] - - User.LoggedIn name -> - let - mainTitle = - h3 - [ class "title" ] - [ i [ class "glyphicon glyphicon-user" ] [] - , text " My account" - ] - in - div - [ - id "my-account" - , class "container" - ] - [ div - [ class "wrapper -suffix"] - [ mainTitle - , h4 [ class "name" ] [ text <| "Welcome " ++ name ] - , h4 [ class "company-title"] [ text "Your companies are:" ] - , ol [ class "companies" ] (List.map viewCompanies model.companies) - ] - ] - - -viewCompanies : Company.Model -> Html -viewCompanies company = - li [] [ text company.label ] diff --git a/src/elm/TestRunner.elm b/src/elm/TestRunner.elm deleted file mode 100644 index 5db5a74..0000000 --- a/src/elm/TestRunner.elm +++ /dev/null @@ -1,22 +0,0 @@ -module Main exposing (..) - -import Graphics.Element exposing (Element) - -import ElmTest exposing (..) - -import Config.Test as Config -import EventCompanyFilter.Test as EventCompanyFilter -import Pages.Login.Test as Login - - -allTests : Test -allTests = - suite "All tests" - [ Config.all - , EventCompanyFilter.all - , Login.all - ] - -main : Element -main = - elementRunner allTests diff --git a/src/elm/Utils/Http.elm b/src/elm/Utils/Http.elm deleted file mode 100644 index e5a648b..0000000 --- a/src/elm/Utils/Http.elm +++ /dev/null @@ -1,23 +0,0 @@ -module Utils.Http exposing (..) - -import Http exposing (Error) - -getErrorMessageFromHttpResponse : Http.Error -> String -getErrorMessageFromHttpResponse err = - case err of - Http.Timeout -> - "Connection has timed out" - - Http.BadResponse code _ -> - if code == 401 then - "Wrong username or password" - else if code == 429 then - "Too many login requests with the wrong username or password. Wait a few hours before trying again" - else - "Some error has occurred on the server" - - Http.NetworkError -> - "A network error has occurred" - - Http.UnexpectedPayload string -> - "Unknown error has occurred: " ++ string diff --git a/src/index.html b/src/index.html deleted file mode 100644 index bdabe60..0000000 --- a/src/index.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - Elm - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/js/elm-interop.js b/src/js/elm-interop.js deleted file mode 100644 index 4d90572..0000000 --- a/src/js/elm-interop.js +++ /dev/null @@ -1,270 +0,0 @@ -"use strict"; - -var initialValues = { - ckeditor : '', - dropzoneUploadedFile : null, - selectEvent: null -}; - -var elmApp = Elm.fullscreen(Elm.Main, initialValues); - -// Maintain the map and marker state. -var mapEl = undefined; -var markersEl = {}; - -var defaultIcon = L.icon({ - iconUrl: 'default@2x.png', - iconRetinaUrl: 'default@2x.png', - iconSize: [35, 46] -}); - -var selectedIcon = L.icon({ - iconUrl: 'selected@2x.png', - iconRetinaUrl: 'selected@2x.png', - iconSize: [35, 46] -}); - -elmApp.ports.mapManager.subscribe(function(model) { - if (!model.leaflet.showMap && !!mapEl) { - // Hide the map. - mapEl.remove(); - mapEl = undefined; - markersEl = {}; - return; - } - - // We use timeout, to let virtual-dom add the div we need to bind to. - waitForElement('#map', mapManager, model); -}); - - -/** - * Wait for selector to appear before invoking related functions. - */ -function waitForElement(selector, fn, model, tryCount) { - - // Repeat the timeout only maximum 5 times, which sohuld be enough for the - // element to appear. - tryCount = tryCount || 5; - --tryCount; - if (tryCount == 0) { - return; - } - - setTimeout(function() { - - var result = fn.call(null, selector, model, tryCount); - if (!result) { - // Element still doesn't exist, so wait some more. - waitForElement(selector, fn, model, tryCount); - } - }, 50); -} - -/** - * Attach or detach the Leaflet map and markers. - * - * @return bool - * Determines if mapManager completed it's operation. True means we don't need - * ro re-call this function. - */ -function mapManager(selector, model) { - if (!model.leaflet.showMap) { - return true; - } - - var element = document.querySelector(selector); - if (!element) { - // Element doesn't exist yet. - return false; - } - - mapEl = mapEl || addMap(); - - // The event Ids holds the array of all the current events - even the one that - // might be filtered out. By unsetting the ones that have visible markers, we - // remain with the ones that should be removed. - // We make sure to clonse the event Ids, so we can always query the original - // events. - var eventIds = JSON.parse(JSON.stringify(model.events)); - - var selectedMarker = undefined; - - model.leaflet.markers.forEach(function(marker) { - var id = marker.id; - if (!markersEl[id]) { - markersEl[id] = L.marker([marker.lat, marker.lng]).addTo(mapEl); - selectMarker(markersEl[id], id); - } - else { - markersEl[id].setLatLng([marker.lat, marker.lng]); - } - - var isSelected = !!model.leaflet.selectedMarker && model.leaflet.selectedMarker === id; - - if (isSelected) { - // Center the map around the selected event. - selectedMarker = markersEl[id]; - } - - // Set the marker's icon. - markersEl[id].setIcon(isSelected ? selectedIcon : defaultIcon); - - // Unset the marker form the event IDs list. - var index = eventIds.indexOf(id); - eventIds.splice(index, 1); - }); - - // When there are markers available, fit the map around them. - if (model.leaflet.markers.length) { - - // Try to see is there are bounds. If there are not, center the map. - try { - mapEl.getBounds(); - } - catch (err) { - mapEl.fitBounds(model.leaflet.markers); - } - - // When a marker is selected, center the map around it. - if (selectedMarker) { - mapEl.panTo(selectedMarker._latlng); - } - else { - mapEl.fitBounds(model.leaflet.markers); - } - } - else { - // Show the entire world when no markers are set. - mapEl.setZoom(1); - } - - // Hide filtered markers. - eventIds.forEach(function(id) { - if (markersEl[id]) { - mapEl.removeLayer(markersEl[id]); - markersEl[id] = undefined; - } - }); - - - // Iterate over all the existing markers, and make sure they part of the - // existing events list. Otherwise, remove them. - for (var id in markersEl) { - if (model.events.indexOf(parseInt(id)) > -1) { - // Marker doesn't exist in the current event list. - continue; - } - - if (!markersEl[id]) { - // Marker is already invisible. - continue; - } - - mapEl.removeLayer(markersEl[id]); - markersEl[id] = undefined; - } - - // Map was binded properly. - return true; -} - -/** - * Send marker click event to Elm. - */ -function selectMarker(markerEl, id) { - markerEl.on('click', function(e) { - elmApp.ports.selectEvent.send(id); - }); -} - -/** - * Initialize a Leaflet map. - */ -function addMap() { - // Leaflet map. - var mapEl = L.map('map'); - - L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpandmbXliNDBjZWd2M2x6bDk3c2ZtOTkifQ._QA7i5Mpkd_m30IGElHziw', { - maxZoom: 10, - id: 'mapbox.streets' - }).addTo(mapEl); - - return mapEl; -} - - - -// Dropzone -// @todo: Move to own file. - -var ck = undefined; -var dropZone = undefined; - -elmApp.ports.activePage.subscribe(function(model) { - if (model.activePage != 'Article') { - // Reset dropzone variable, in case we switch between pages. - ck = undefined; - dropZone = undefined; - return; - } - - waitForElement('.dropzone', attachDropzone, model); -}); - -function attachDropzone(selector, model) { - if (model.activePage != 'Article') { - return false; - } - - var element = document.querySelector(selector); - if (!element) { - // Element doesn't exist yet. - return false; - } - - if (!!dropZone) { - - // Check if we need to remove files. - if (model.postStatus == "Done") { - // Remove all files, even the ones being currently uploaded. - dropZone.removeAllFiles(true); - - // Clear the CKeditor text area. - ck.setData(''); - } - - // Widgets were already attached once. - return true; - } - - - // Set the backend url with the access token. - var url = model.backendUrl + '/api/file-upload?access_token=' + model.accessToken; - - dropZone = new Dropzone(selector, { url: url}); - - dropZone.on('complete', function(file) { - if (!file.accepted) { - // File was not uploaded. - return; - } - - if (file.xhr.status !== 200) { - return; - } - - var data = JSON.parse(file.xhr.response); - - // Get the file ID, and send it to Elm. - var id = parseInt(data.data[0]['id']); - elmApp.ports.dropzoneUploadedFile.send(id); - }); - - ck = CKEDITOR.replace('body'); - - // Send the data to Elm. - ck.on('change', function() { - elmApp.ports.ckeditor.send(ck.getData()); - }); -} diff --git a/src/vendor/elm-param-parsing/.gitignore b/src/vendor/elm-param-parsing/.gitignore deleted file mode 100644 index 61037f8..0000000 --- a/src/vendor/elm-param-parsing/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -elm.js -elm-stuff -Gemfile -Gemfile.lock -_site -node_modules -*.js diff --git a/src/vendor/elm-param-parsing/README.md b/src/vendor/elm-param-parsing/README.md deleted file mode 100644 index 74cf719..0000000 --- a/src/vendor/elm-param-parsing/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# Elm Parameter Parsing - -This is an elm library for parsing parameters on the URL. - -## To use it - -```elm package install jessitron/elm-param-parsing``` - -To use this, you'll need -to create an input port, pass the search string to Elm, and then parse -them with this function, then that can populate your model. - -For instance, in the web page: - - var app = Elm.fullscreen(Elm.YourModule, - { locationSearch: window.location.search }); - -in YourModule.elm, declare the port and then parse what comes into it. This example discards errors: - -```elm -import Dict exposing (Dict) - -port locationSearch : String - -parameters : Dict String String -parameters = - case (parseSearchString locationSearch) of - Error _ -> Dict.empty - UrlParams dict -> dict -``` - -Then use that dict when you call your init function that needs the value -of the parameter. - -```elm -init (Dict.get parameters "customerID") - -init : Maybe String -> Model -init maybeID = ... -``` - -## see it in action - -The example app is built into this repo. -[source](https://github.com/jessitron/elm-param-parsing/tree/ui); -[result](http://jessitron.github.io/elm-param-parsing) diff --git a/src/vendor/elm-param-parsing/build b/src/vendor/elm-param-parsing/build deleted file mode 100755 index 99c2570..0000000 --- a/src/vendor/elm-param-parsing/build +++ /dev/null @@ -1 +0,0 @@ -elm-make src/UrlParameterParser.elm diff --git a/src/vendor/elm-param-parsing/elm-package.json b/src/vendor/elm-param-parsing/elm-package.json deleted file mode 100644 index e8bde90..0000000 --- a/src/vendor/elm-param-parsing/elm-package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "version": "1.0.2", - "summary": "utility method to parse URL parameters", - "repository": "https://github.com/jessitron/elm-param-parsing.git", - "license": "BSD3", - "source-directories": [ - "src" - ], - "exposed-modules": [ - "UrlParameterParser" - ], - "dependencies": { - "elm-lang/core": "3.0.0 <= v < 4.0.0" - }, - "elm-version": "0.16.0 <= v < 0.17.0" -} diff --git a/src/vendor/elm-param-parsing/src/UrlParameterParser.elm b/src/vendor/elm-param-parsing/src/UrlParameterParser.elm deleted file mode 100644 index b4d6990..0000000 --- a/src/vendor/elm-param-parsing/src/UrlParameterParser.elm +++ /dev/null @@ -1,68 +0,0 @@ -module UrlParameterParser(ParseResult(..), parseSearchString) where - -{-| Parse URL parameters. To use this, you'll need to create an input port, pass the search string to Elm, -and then parse them with this function, then that can populate your model. - -For instance, in the web page: -``` - var app = Elm.fullscreen(Elm.YourModule, - { locationSearch: window.location.search }); -``` -in YourModule.elm: -``` -port locationSearch : String -``` - -Then parse the value of the port - this example discards errors: -``` -parameters : Dict String String -parameters = - case (parseSearchString locationSearch) of - Error _ -> Dict.empty - UrlParams dict -> dict -``` - -Then use that dict when you call your init function that needs the value of the parameter. It'll get a Maybe String. -``` -init (Dict.get parameters "customerID") - -init : Maybe String -> Model -init maybeID = ... -``` - -# Method -@docs parseSearchString - -# Return type -@docs ParseResult --} - -import Dict exposing (Dict) -import String -import UrlParseUtil exposing (..) - -{-| If parsing is successful, you get a UrlParams containing a dictionary of keys to values. -Otherwise, an error string. -If there are no parameters, you'll get an error description. --} -type ParseResult - = Error String - | UrlParams (Dict String String) - -{-| Given a search string of the form "?key=value&key2=val2" -parse these into a dictionary of key to value. --} -parseSearchString : String -> ParseResult -parseSearchString startsWithQuestionMarkThenParams = - case (String.uncons startsWithQuestionMarkThenParams) of - Nothing -> Error "No URL params" - Just ('?', rest) -> parseParams rest - _ -> Error "No URL params" - -parseParams : String -> ParseResult -parseParams stringWithAmpersands = - let - eachParam = (String.split "&" stringWithAmpersands) - eachPair = List.map (splitAtFirst '=') eachParam - in - UrlParams (Dict.fromList eachPair) diff --git a/src/vendor/elm-param-parsing/src/UrlParseUtil.elm b/src/vendor/elm-param-parsing/src/UrlParseUtil.elm deleted file mode 100644 index 5083b5e..0000000 --- a/src/vendor/elm-param-parsing/src/UrlParseUtil.elm +++ /dev/null @@ -1,20 +0,0 @@ -module UrlParseUtil where - -import String - -{-| These are broken out only to be testable - without being exposed --} - -splitAtFirst : Char -> String -> (String, String) -splitAtFirst c s = - case (firstOccurrence c s) of - Nothing -> (s, "") - Just i -> ((String.left i s), (String.dropLeft (i + 1) s)) - - -firstOccurrence : Char -> String -> Maybe Int -firstOccurrence c s = - case (String.indexes (String.fromChar c) s) of - [] -> Nothing - head :: _ -> Just head diff --git a/src/vendor/elm-param-parsing/test.sh b/src/vendor/elm-param-parsing/test.sh deleted file mode 100755 index 16be50f..0000000 --- a/src/vendor/elm-param-parsing/test.sh +++ /dev/null @@ -1,4 +0,0 @@ -elm-make src/*.elm -elm-make test/*.elm --output test/raw-test.js -bash test/elm-io.sh test/raw-test.js test/test.js -node test/test.js diff --git a/src/vendor/elm-storage/Example.elm b/src/vendor/elm-storage/Example.elm deleted file mode 100644 index 1ee9b5a..0000000 --- a/src/vendor/elm-storage/Example.elm +++ /dev/null @@ -1,49 +0,0 @@ -import Storage exposing (..) - -import Html exposing (text, div, input, form) -import Html.Attributes exposing (type') -import Html.Events exposing (on, targetValue) -import Json.Encode exposing (string, Value) -import Json.Decode as Decode - -import Signal exposing (Signal, Mailbox, Message, mailbox, message, send) -import Task exposing (Task, succeed, andThen, mapError, onError, fail) - -sendInputMailbox : Mailbox (Task String ()) -sendInputMailbox = mailbox (succeed ()) - -currentValueMailbox : Mailbox String -currentValueMailbox = mailbox "" - -sendInputToStorage : String -> Task String () -sendInputToStorage = - setItem "Test" << string - -getInputFromStorage : Task String String -getInputFromStorage = - getItem "Test" Decode.string - - -sendInput : String -> Task String () -sendInput value = sendInputToStorage value - `andThen` \_ -> getInputFromStorage - `andThen` \val -> send currentValueMailbox.address val - - - -view model = - div [] - [ input - [ on "input" targetValue (message sendInputMailbox.address << sendInput) - ] [] - , text model - ] - - -port sendInputPort : Signal (Task String ()) -port sendInputPort = - sendInputMailbox.signal - - - -main = Signal.map view currentValueMailbox.signal diff --git a/src/vendor/elm-storage/README.md b/src/vendor/elm-storage/README.md deleted file mode 100644 index f0e67db..0000000 --- a/src/vendor/elm-storage/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# elm-storage - -> Local Storage in Elm - -## Example - -```bash -cd example -elm-reactor -``` - diff --git a/src/vendor/elm-storage/elm-package.json b/src/vendor/elm-storage/elm-package.json deleted file mode 100644 index c5c78e3..0000000 --- a/src/vendor/elm-storage/elm-package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "version": "1.0.0", - "summary": "LocalForage Bindings in Elm", - "repository": "https://github.com/USER/PROJECT.git", - "license": "BSD3", - "source-directories": [ - "src" - ], - "exposed-modules": [], - "native-modules" : true, - "dependencies": { - "elm-lang/core": "2.0.0 <= v < 3.0.0", - "evancz/elm-html": "3.0.0 <= v < 4.0.0" - }, - "elm-version": "0.15.0 <= v < 0.16.0" -} diff --git a/src/vendor/elm-storage/example/.gitignore b/src/vendor/elm-storage/example/.gitignore deleted file mode 100644 index 3bd52a1..0000000 --- a/src/vendor/elm-storage/example/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -elm-stuff -elm.js diff --git a/src/vendor/elm-storage/example/App.elm b/src/vendor/elm-storage/example/App.elm deleted file mode 100644 index 4c39c15..0000000 --- a/src/vendor/elm-storage/example/App.elm +++ /dev/null @@ -1,92 +0,0 @@ -module App where - -import Effects exposing (Effects) -import Json.Encode as JE exposing (string, Value) -import Json.Decode as JD -import Html exposing (..) -import Html.Attributes exposing (..) -import Html.Events exposing (on, targetValue) -import Storage exposing (..) -import Task exposing (..) - -import Debug - -type alias Model = Maybe String - -initialModel : Model -initialModel = - Nothing - -init : (Model, Effects Action) -init = - ( initialModel - , getInputFromStorage - ) - --- UPDATE - -type Action - = GetStorage (Result String ()) - | SetStorage String - | UpdateModel (Result String String) - - -update : Action -> Model -> (Model, Effects Action) -update action model = - case action of - GetStorage result -> - case result of - Ok s -> - (model, getInputFromStorage) - Err err -> - (model, Effects.none) - - - SetStorage s -> - -- Don't update the model here, instead after this action is done, the - -- effect should call another action to update the model. - (model, sendInputToStorage s) - - UpdateModel result -> - case result of - Ok s -> - (Just s, Effects.none) - Err err -> - (model, Effects.none) - - -sendInputToStorage : String -> Effects Action -sendInputToStorage s = - Storage.setItem "Test" (JE.string s) - |> Task.toResult - |> Task.map GetStorage - |> Effects.task - -getInputFromStorage : Effects Action -getInputFromStorage = - getItem "Test" JD.string - |> Task.toResult - |> Task.map UpdateModel - |> Effects.task - --- VIEW - -view : Signal.Address Action -> Model -> Html -view address model = - let - existingValue = - case model of - Just s -> - text s - Nothing -> - text "" - in - div [] - [ h2 [] [ text "Storage example"] - , input - [ on "input" targetValue (Signal.message address << SetStorage) - , required True - , placeholder "Add some text" - ] [] - , existingValue - ] diff --git a/src/vendor/elm-storage/example/Main.elm b/src/vendor/elm-storage/example/Main.elm deleted file mode 100644 index 630e9e9..0000000 --- a/src/vendor/elm-storage/example/Main.elm +++ /dev/null @@ -1,24 +0,0 @@ -module Main where - -import Effects exposing (Never) -import App exposing (init, update, view) -import StartApp -import Task - - -app = - StartApp.start - { init = init - , update = update - , view = view - , inputs = [] - } - - -main = - app.html - - -port tasks : Signal (Task.Task Never ()) -port tasks = - app.tasks diff --git a/src/vendor/elm-storage/example/elm-package.json b/src/vendor/elm-storage/example/elm-package.json deleted file mode 100644 index 5ceeaf1..0000000 --- a/src/vendor/elm-storage/example/elm-package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "version": "1.0.0", - "summary": "helpful summary of your project, less than 80 characters", - "repository": "https://github.com/USER/PROJECT.git", - "license": "BSD3", - "source-directories": [ - "../src", - "." - ], - "exposed-modules": [], - "native-modules": true, - "dependencies": { - "elm-lang/core": "2.1.0 <= v < 3.0.0", - "evancz/elm-effects": "2.0.0 <= v < 3.0.0", - "evancz/elm-html": "4.0.1 <= v < 5.0.0", - "evancz/start-app": "2.0.1 <= v < 3.0.0" - }, - "elm-version": "0.15.1 <= v < 0.16.0" -} diff --git a/src/vendor/elm-storage/src/Native/Storage.js b/src/vendor/elm-storage/src/Native/Storage.js deleted file mode 100644 index f96ac2f..0000000 --- a/src/vendor/elm-storage/src/Native/Storage.js +++ /dev/null @@ -1,2595 +0,0 @@ -/*! - localForage -- Offline Storage, Improved - Version 1.2.2 - https://mozilla.github.io/localForage - (c) 2013-2015 Mozilla, Apache License 2.0 -*/ -(function() { -var define, requireModule, require, requirejs; - -(function() { - var registry = {}, seen = {}; - - define = function(name, deps, callback) { - registry[name] = { deps: deps, callback: callback }; - }; - - requirejs = require = requireModule = function(name) { - requirejs._eak_seen = registry; - - if (seen[name]) { return seen[name]; } - seen[name] = {}; - - if (!registry[name]) { - throw new Error("Could not find module " + name); - } - - var mod = registry[name], - deps = mod.deps, - callback = mod.callback, - reified = [], - exports; - - for (var i=0, l=deps.length; i string data storage. - var BASE_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - - var SERIALIZED_MARKER = '__lfsc__:'; - var SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER.length; - - // OMG the serializations! - var TYPE_ARRAYBUFFER = 'arbf'; - var TYPE_BLOB = 'blob'; - var TYPE_INT8ARRAY = 'si08'; - var TYPE_UINT8ARRAY = 'ui08'; - var TYPE_UINT8CLAMPEDARRAY = 'uic8'; - var TYPE_INT16ARRAY = 'si16'; - var TYPE_INT32ARRAY = 'si32'; - var TYPE_UINT16ARRAY = 'ur16'; - var TYPE_UINT32ARRAY = 'ui32'; - var TYPE_FLOAT32ARRAY = 'fl32'; - var TYPE_FLOAT64ARRAY = 'fl64'; - var TYPE_SERIALIZED_MARKER_LENGTH = SERIALIZED_MARKER_LENGTH + - TYPE_ARRAYBUFFER.length; - - // Serialize a value, afterwards executing a callback (which usually - // instructs the `setItem()` callback/promise to be executed). This is how - // we store binary data with localStorage. - function serialize(value, callback) { - var valueString = ''; - if (value) { - valueString = value.toString(); - } - - // Cannot use `value instanceof ArrayBuffer` or such here, as these - // checks fail when running the tests using casper.js... - // - // TODO: See why those tests fail and use a better solution. - if (value && (value.toString() === '[object ArrayBuffer]' || - value.buffer && - value.buffer.toString() === '[object ArrayBuffer]')) { - // Convert binary arrays to a string and prefix the string with - // a special marker. - var buffer; - var marker = SERIALIZED_MARKER; - - if (value instanceof ArrayBuffer) { - buffer = value; - marker += TYPE_ARRAYBUFFER; - } else { - buffer = value.buffer; - - if (valueString === '[object Int8Array]') { - marker += TYPE_INT8ARRAY; - } else if (valueString === '[object Uint8Array]') { - marker += TYPE_UINT8ARRAY; - } else if (valueString === '[object Uint8ClampedArray]') { - marker += TYPE_UINT8CLAMPEDARRAY; - } else if (valueString === '[object Int16Array]') { - marker += TYPE_INT16ARRAY; - } else if (valueString === '[object Uint16Array]') { - marker += TYPE_UINT16ARRAY; - } else if (valueString === '[object Int32Array]') { - marker += TYPE_INT32ARRAY; - } else if (valueString === '[object Uint32Array]') { - marker += TYPE_UINT32ARRAY; - } else if (valueString === '[object Float32Array]') { - marker += TYPE_FLOAT32ARRAY; - } else if (valueString === '[object Float64Array]') { - marker += TYPE_FLOAT64ARRAY; - } else { - callback(new Error('Failed to get type for BinaryArray')); - } - } - - callback(marker + bufferToString(buffer)); - } else if (valueString === '[object Blob]') { - // Conver the blob to a binaryArray and then to a string. - var fileReader = new FileReader(); - - fileReader.onload = function() { - var str = bufferToString(this.result); - - callback(SERIALIZED_MARKER + TYPE_BLOB + str); - }; - - fileReader.readAsArrayBuffer(value); - } else { - try { - callback(JSON.stringify(value)); - } catch (e) { - window.console.error("Couldn't convert value into a JSON " + - 'string: ', value); - - callback(null, e); - } - } - } - - // Deserialize data we've inserted into a value column/field. We place - // special markers into our strings to mark them as encoded; this isn't - // as nice as a meta field, but it's the only sane thing we can do whilst - // keeping localStorage support intact. - // - // Oftentimes this will just deserialize JSON content, but if we have a - // special marker (SERIALIZED_MARKER, defined above), we will extract - // some kind of arraybuffer/binary data/typed array out of the string. - function deserialize(value) { - // If we haven't marked this string as being specially serialized (i.e. - // something other than serialized JSON), we can just return it and be - // done with it. - if (value.substring(0, - SERIALIZED_MARKER_LENGTH) !== SERIALIZED_MARKER) { - return JSON.parse(value); - } - - // The following code deals with deserializing some kind of Blob or - // TypedArray. First we separate out the type of data we're dealing - // with from the data itself. - var serializedString = value.substring(TYPE_SERIALIZED_MARKER_LENGTH); - var type = value.substring(SERIALIZED_MARKER_LENGTH, - TYPE_SERIALIZED_MARKER_LENGTH); - - var buffer = stringToBuffer(serializedString); - - // Return the right type based on the code/type set during - // serialization. - switch (type) { - case TYPE_ARRAYBUFFER: - return buffer; - case TYPE_BLOB: - return new Blob([buffer]); - case TYPE_INT8ARRAY: - return new Int8Array(buffer); - case TYPE_UINT8ARRAY: - return new Uint8Array(buffer); - case TYPE_UINT8CLAMPEDARRAY: - return new Uint8ClampedArray(buffer); - case TYPE_INT16ARRAY: - return new Int16Array(buffer); - case TYPE_UINT16ARRAY: - return new Uint16Array(buffer); - case TYPE_INT32ARRAY: - return new Int32Array(buffer); - case TYPE_UINT32ARRAY: - return new Uint32Array(buffer); - case TYPE_FLOAT32ARRAY: - return new Float32Array(buffer); - case TYPE_FLOAT64ARRAY: - return new Float64Array(buffer); - default: - throw new Error('Unkown type: ' + type); - } - } - - function stringToBuffer(serializedString) { - // Fill the string into a ArrayBuffer. - var bufferLength = serializedString.length * 0.75; - var len = serializedString.length; - var i; - var p = 0; - var encoded1, encoded2, encoded3, encoded4; - - if (serializedString[serializedString.length - 1] === '=') { - bufferLength--; - if (serializedString[serializedString.length - 2] === '=') { - bufferLength--; - } - } - - var buffer = new ArrayBuffer(bufferLength); - var bytes = new Uint8Array(buffer); - - for (i = 0; i < len; i+=4) { - encoded1 = BASE_CHARS.indexOf(serializedString[i]); - encoded2 = BASE_CHARS.indexOf(serializedString[i+1]); - encoded3 = BASE_CHARS.indexOf(serializedString[i+2]); - encoded4 = BASE_CHARS.indexOf(serializedString[i+3]); - - /*jslint bitwise: true */ - bytes[p++] = (encoded1 << 2) | (encoded2 >> 4); - bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2); - bytes[p++] = ((encoded3 & 3) << 6) | (encoded4 & 63); - } - return buffer; - } - - // Converts a buffer to a string to store, serialized, in the backend - // storage library. - function bufferToString(buffer) { - // base64-arraybuffer - var bytes = new Uint8Array(buffer); - var base64String = ''; - var i; - - for (i = 0; i < bytes.length; i += 3) { - /*jslint bitwise: true */ - base64String += BASE_CHARS[bytes[i] >> 2]; - base64String += BASE_CHARS[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)]; - base64String += BASE_CHARS[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)]; - base64String += BASE_CHARS[bytes[i + 2] & 63]; - } - - if ((bytes.length % 3) === 2) { - base64String = base64String.substring(0, base64String.length - 1) + '='; - } else if (bytes.length % 3 === 1) { - base64String = base64String.substring(0, base64String.length - 2) + '=='; - } - - return base64String; - } - - var localforageSerializer = { - serialize: serialize, - deserialize: deserialize, - stringToBuffer: stringToBuffer, - bufferToString: bufferToString - }; - - if (typeof module !== 'undefined' && module.exports) { - module.exports = localforageSerializer; - } else if (typeof define === 'function' && define.amd) { - define('localforageSerializer', function() { - return localforageSerializer; - }); - } else { - this.localforageSerializer = localforageSerializer; - } -}).call(window); -// Some code originally from async_storage.js in -// [Gaia](https://github.com/mozilla-b2g/gaia). -(function() { - 'use strict'; - - // Originally found in https://github.com/mozilla-b2g/gaia/blob/e8f624e4cc9ea945727278039b3bc9bcb9f8667a/shared/js/async_storage.js - - // Promises! - var Promise = (typeof module !== 'undefined' && module.exports) ? - require('promise') : this.Promise; - - // Initialize IndexedDB; fall back to vendor-prefixed versions if needed. - var indexedDB = indexedDB || this.indexedDB || this.webkitIndexedDB || - this.mozIndexedDB || this.OIndexedDB || - this.msIndexedDB; - - // If IndexedDB isn't available, we get outta here! - if (!indexedDB) { - return; - } - - // Open the IndexedDB database (automatically creates one if one didn't - // previously exist), using any options set in the config. - function _initStorage(options) { - var self = this; - var dbInfo = { - db: null - }; - - if (options) { - for (var i in options) { - dbInfo[i] = options[i]; - } - } - - return new Promise(function(resolve, reject) { - var openreq = indexedDB.open(dbInfo.name, dbInfo.version); - openreq.onerror = function() { - reject(openreq.error); - }; - openreq.onupgradeneeded = function() { - // First time setup: create an empty object store - openreq.result.createObjectStore(dbInfo.storeName); - }; - openreq.onsuccess = function() { - dbInfo.db = openreq.result; - self._dbInfo = dbInfo; - resolve(); - }; - }); - } - - function getItem(key, callback) { - var self = this; - - // Cast the key to a string, as that's all we can set as a key. - if (typeof key !== 'string') { - window.console.warn(key + - ' used as a key, but it is not a string.'); - key = String(key); - } - - var promise = new Promise(function(resolve, reject) { - self.ready().then(function() { - var dbInfo = self._dbInfo; - var store = dbInfo.db.transaction(dbInfo.storeName, 'readonly') - .objectStore(dbInfo.storeName); - var req = store.get(key); - - req.onsuccess = function() { - var value = req.result; - if (value === undefined) { - value = null; - } - - resolve(value); - }; - - req.onerror = function() { - reject(req.error); - }; - })["catch"](reject); - }); - - executeDeferedCallback(promise, callback); - return promise; - } - - // Iterate over all items stored in database. - function iterate(iterator, callback) { - var self = this; - - var promise = new Promise(function(resolve, reject) { - self.ready().then(function() { - var dbInfo = self._dbInfo; - var store = dbInfo.db.transaction(dbInfo.storeName, 'readonly') - .objectStore(dbInfo.storeName); - - var req = store.openCursor(); - var iterationNumber = 1; - - req.onsuccess = function() { - var cursor = req.result; - - if (cursor) { - var result = iterator(cursor.value, cursor.key, iterationNumber++); - - if (result !== void(0)) { - resolve(result); - } else { - cursor["continue"](); - } - } else { - resolve(); - } - }; - - req.onerror = function() { - reject(req.error); - }; - })["catch"](reject); - }); - - executeDeferedCallback(promise, callback); - - return promise; - } - - function setItem(key, value, callback) { - var self = this; - - // Cast the key to a string, as that's all we can set as a key. - if (typeof key !== 'string') { - window.console.warn(key + - ' used as a key, but it is not a string.'); - key = String(key); - } - - var promise = new Promise(function(resolve, reject) { - self.ready().then(function() { - var dbInfo = self._dbInfo; - var transaction = dbInfo.db.transaction(dbInfo.storeName, 'readwrite'); - var store = transaction.objectStore(dbInfo.storeName); - - // The reason we don't _save_ null is because IE 10 does - // not support saving the `null` type in IndexedDB. How - // ironic, given the bug below! - // See: https://github.com/mozilla/localForage/issues/161 - if (value === null) { - value = undefined; - } - - var req = store.put(value, key); - transaction.oncomplete = function() { - // Cast to undefined so the value passed to - // callback/promise is the same as what one would get out - // of `getItem()` later. This leads to some weirdness - // (setItem('foo', undefined) will return `null`), but - // it's not my fault localStorage is our baseline and that - // it's weird. - if (value === undefined) { - value = null; - } - - resolve(value); - }; - transaction.onabort = transaction.onerror = function() { - reject(req.error); - }; - })["catch"](reject); - }); - - executeDeferedCallback(promise, callback); - return promise; - } - - function removeItem(key, callback) { - var self = this; - - // Cast the key to a string, as that's all we can set as a key. - if (typeof key !== 'string') { - window.console.warn(key + - ' used as a key, but it is not a string.'); - key = String(key); - } - - var promise = new Promise(function(resolve, reject) { - self.ready().then(function() { - var dbInfo = self._dbInfo; - var transaction = dbInfo.db.transaction(dbInfo.storeName, 'readwrite'); - var store = transaction.objectStore(dbInfo.storeName); - - // We use a Grunt task to make this safe for IE and some - // versions of Android (including those used by Cordova). - // Normally IE won't like `.delete()` and will insist on - // using `['delete']()`, but we have a build step that - // fixes this for us now. - var req = store["delete"](key); - transaction.oncomplete = function() { - resolve(); - }; - - transaction.onerror = function() { - reject(req.error); - }; - - // The request will be aborted if we've exceeded our storage - // space. In this case, we will reject with a specific - // "QuotaExceededError". - transaction.onabort = function(event) { - var error = event.target.error; - if (error === 'QuotaExceededError') { - reject(error); - } - }; - })["catch"](reject); - }); - - executeDeferedCallback(promise, callback); - return promise; - } - - function clear(callback) { - var self = this; - - var promise = new Promise(function(resolve, reject) { - self.ready().then(function() { - var dbInfo = self._dbInfo; - var transaction = dbInfo.db.transaction(dbInfo.storeName, 'readwrite'); - var store = transaction.objectStore(dbInfo.storeName); - var req = store.clear(); - - transaction.oncomplete = function() { - resolve(); - }; - - transaction.onabort = transaction.onerror = function() { - reject(req.error); - }; - })["catch"](reject); - }); - - executeDeferedCallback(promise, callback); - return promise; - } - - function length(callback) { - var self = this; - - var promise = new Promise(function(resolve, reject) { - self.ready().then(function() { - var dbInfo = self._dbInfo; - var store = dbInfo.db.transaction(dbInfo.storeName, 'readonly') - .objectStore(dbInfo.storeName); - var req = store.count(); - - req.onsuccess = function() { - resolve(req.result); - }; - - req.onerror = function() { - reject(req.error); - }; - })["catch"](reject); - }); - - executeCallback(promise, callback); - return promise; - } - - function key(n, callback) { - var self = this; - - var promise = new Promise(function(resolve, reject) { - if (n < 0) { - resolve(null); - - return; - } - - self.ready().then(function() { - var dbInfo = self._dbInfo; - var store = dbInfo.db.transaction(dbInfo.storeName, 'readonly') - .objectStore(dbInfo.storeName); - - var advanced = false; - var req = store.openCursor(); - req.onsuccess = function() { - var cursor = req.result; - if (!cursor) { - // this means there weren't enough keys - resolve(null); - - return; - } - - if (n === 0) { - // We have the first key, return it if that's what they - // wanted. - resolve(cursor.key); - } else { - if (!advanced) { - // Otherwise, ask the cursor to skip ahead n - // records. - advanced = true; - cursor.advance(n); - } else { - // When we get here, we've got the nth key. - resolve(cursor.key); - } - } - }; - - req.onerror = function() { - reject(req.error); - }; - })["catch"](reject); - }); - - executeCallback(promise, callback); - return promise; - } - - function keys(callback) { - var self = this; - - var promise = new Promise(function(resolve, reject) { - self.ready().then(function() { - var dbInfo = self._dbInfo; - var store = dbInfo.db.transaction(dbInfo.storeName, 'readonly') - .objectStore(dbInfo.storeName); - - var req = store.openCursor(); - var keys = []; - - req.onsuccess = function() { - var cursor = req.result; - - if (!cursor) { - resolve(keys); - return; - } - - keys.push(cursor.key); - cursor["continue"](); - }; - - req.onerror = function() { - reject(req.error); - }; - })["catch"](reject); - }); - - executeCallback(promise, callback); - return promise; - } - - function executeCallback(promise, callback) { - if (callback) { - promise.then(function(result) { - callback(null, result); - }, function(error) { - callback(error); - }); - } - } - - function executeDeferedCallback(promise, callback) { - if (callback) { - promise.then(function(result) { - deferCallback(callback, result); - }, function(error) { - callback(error); - }); - } - } - - // Under Chrome the callback is called before the changes (save, clear) - // are actually made. So we use a defer function which wait that the - // call stack to be empty. - // For more info : https://github.com/mozilla/localForage/issues/175 - // Pull request : https://github.com/mozilla/localForage/pull/178 - function deferCallback(callback, result) { - if (callback) { - return setTimeout(function() { - return callback(null, result); - }, 0); - } - } - - var asyncStorage = { - _driver: 'asyncStorage', - _initStorage: _initStorage, - iterate: iterate, - getItem: getItem, - setItem: setItem, - removeItem: removeItem, - clear: clear, - length: length, - key: key, - keys: keys - }; - - if (typeof module !== 'undefined' && module.exports) { - module.exports = asyncStorage; - } else if (typeof define === 'function' && define.amd) { - define('asyncStorage', function() { - return asyncStorage; - }); - } else { - this.asyncStorage = asyncStorage; - } -}).call(window); -// If IndexedDB isn't available, we'll fall back to localStorage. -// Note that this will have considerable performance and storage -// side-effects (all data will be serialized on save and only data that -// can be converted to a string via `JSON.stringify()` will be saved). -(function() { - 'use strict'; - - // Promises! - var Promise = (typeof module !== 'undefined' && module.exports) ? - require('promise') : this.Promise; - - var globalObject = this; - var serializer = null; - var localStorage = null; - - // If the app is running inside a Google Chrome packaged webapp, or some - // other context where localStorage isn't available, we don't use - // localStorage. This feature detection is preferred over the old - // `if (window.chrome && window.chrome.runtime)` code. - // See: https://github.com/mozilla/localForage/issues/68 - try { - // If localStorage isn't available, we get outta here! - // This should be inside a try catch - if (!this.localStorage || !('setItem' in this.localStorage)) { - return; - } - // Initialize localStorage and create a variable to use throughout - // the code. - localStorage = this.localStorage; - } catch (e) { - return; - } - - var ModuleType = { - DEFINE: 1, - EXPORT: 2, - WINDOW: 3 - }; - - // Attaching to window (i.e. no module loader) is the assumed, - // simple default. - var moduleType = ModuleType.WINDOW; - - // Find out what kind of module setup we have; if none, we'll just attach - // localForage to the main window. - if (typeof module !== 'undefined' && module.exports) { - moduleType = ModuleType.EXPORT; - } else if (typeof define === 'function' && define.amd) { - moduleType = ModuleType.DEFINE; - } - - // Config the localStorage backend, using options set in the config. - function _initStorage(options) { - var self = this; - var dbInfo = {}; - if (options) { - for (var i in options) { - dbInfo[i] = options[i]; - } - } - - dbInfo.keyPrefix = dbInfo.name + '/'; - - self._dbInfo = dbInfo; - - var serializerPromise = new Promise(function(resolve/*, reject*/) { - // We allow localForage to be declared as a module or as a - // library available without AMD/require.js. - if (moduleType === ModuleType.DEFINE) { - require(['localforageSerializer'], resolve); - } else if (moduleType === ModuleType.EXPORT) { - // Making it browserify friendly - resolve(require('./../utils/serializer')); - } else { - resolve(globalObject.localforageSerializer); - } - }); - - return serializerPromise.then(function(lib) { - serializer = lib; - return Promise.resolve(); - }); - } - - // Remove all keys from the datastore, effectively destroying all data in - // the app's key/value store! - function clear(callback) { - var self = this; - var promise = self.ready().then(function() { - var keyPrefix = self._dbInfo.keyPrefix; - - for (var i = localStorage.length - 1; i >= 0; i--) { - var key = localStorage.key(i); - - if (key.indexOf(keyPrefix) === 0) { - localStorage.removeItem(key); - } - } - }); - - executeCallback(promise, callback); - return promise; - } - - // Retrieve an item from the store. Unlike the original async_storage - // library in Gaia, we don't modify return values at all. If a key's value - // is `undefined`, we pass that value to the callback function. - function getItem(key, callback) { - var self = this; - - // Cast the key to a string, as that's all we can set as a key. - if (typeof key !== 'string') { - window.console.warn(key + - ' used as a key, but it is not a string.'); - key = String(key); - } - - var promise = self.ready().then(function() { - var dbInfo = self._dbInfo; - var result = localStorage.getItem(dbInfo.keyPrefix + key); - - // If a result was found, parse it from the serialized - // string into a JS object. If result isn't truthy, the key - // is likely undefined and we'll pass it straight to the - // callback. - if (result) { - result = serializer.deserialize(result); - } - - return result; - }); - - executeCallback(promise, callback); - return promise; - } - - // Iterate over all items in the store. - function iterate(iterator, callback) { - var self = this; - - var promise = self.ready().then(function() { - var keyPrefix = self._dbInfo.keyPrefix; - var keyPrefixLength = keyPrefix.length; - var length = localStorage.length; - - for (var i = 0; i < length; i++) { - var key = localStorage.key(i); - var value = localStorage.getItem(key); - - // If a result was found, parse it from the serialized - // string into a JS object. If result isn't truthy, the - // key is likely undefined and we'll pass it straight - // to the iterator. - if (value) { - value = serializer.deserialize(value); - } - - value = iterator(value, key.substring(keyPrefixLength), i + 1); - - if (value !== void(0)) { - return value; - } - } - }); - - executeCallback(promise, callback); - return promise; - } - - // Same as localStorage's key() method, except takes a callback. - function key(n, callback) { - var self = this; - var promise = self.ready().then(function() { - var dbInfo = self._dbInfo; - var result; - try { - result = localStorage.key(n); - } catch (error) { - result = null; - } - - // Remove the prefix from the key, if a key is found. - if (result) { - result = result.substring(dbInfo.keyPrefix.length); - } - - return result; - }); - - executeCallback(promise, callback); - return promise; - } - - function keys(callback) { - var self = this; - var promise = self.ready().then(function() { - var dbInfo = self._dbInfo; - var length = localStorage.length; - var keys = []; - - for (var i = 0; i < length; i++) { - if (localStorage.key(i).indexOf(dbInfo.keyPrefix) === 0) { - keys.push(localStorage.key(i).substring(dbInfo.keyPrefix.length)); - } - } - - return keys; - }); - - executeCallback(promise, callback); - return promise; - } - - // Supply the number of keys in the datastore to the callback function. - function length(callback) { - var self = this; - var promise = self.keys().then(function(keys) { - return keys.length; - }); - - executeCallback(promise, callback); - return promise; - } - - // Remove an item from the store, nice and simple. - function removeItem(key, callback) { - var self = this; - - // Cast the key to a string, as that's all we can set as a key. - if (typeof key !== 'string') { - window.console.warn(key + - ' used as a key, but it is not a string.'); - key = String(key); - } - - var promise = self.ready().then(function() { - var dbInfo = self._dbInfo; - localStorage.removeItem(dbInfo.keyPrefix + key); - }); - - executeCallback(promise, callback); - return promise; - } - - // Set a key's value and run an optional callback once the value is set. - // Unlike Gaia's implementation, the callback function is passed the value, - // in case you want to operate on that value only after you're sure it - // saved, or something like that. - function setItem(key, value, callback) { - var self = this; - - // Cast the key to a string, as that's all we can set as a key. - if (typeof key !== 'string') { - window.console.warn(key + - ' used as a key, but it is not a string.'); - key = String(key); - } - - var promise = self.ready().then(function() { - // Convert undefined values to null. - // https://github.com/mozilla/localForage/pull/42 - if (value === undefined) { - value = null; - } - - // Save the original value to pass to the callback. - var originalValue = value; - - return new Promise(function(resolve, reject) { - serializer.serialize(value, function(value, error) { - if (error) { - reject(error); - } else { - try { - var dbInfo = self._dbInfo; - localStorage.setItem(dbInfo.keyPrefix + key, value); - resolve(originalValue); - } catch (e) { - // localStorage capacity exceeded. - // TODO: Make this a specific error/event. - if (e.name === 'QuotaExceededError' || - e.name === 'NS_ERROR_DOM_QUOTA_REACHED') { - reject(e); - } - reject(e); - } - } - }); - }); - }); - - executeCallback(promise, callback); - return promise; - } - - function executeCallback(promise, callback) { - if (callback) { - promise.then(function(result) { - callback(null, result); - }, function(error) { - callback(error); - }); - } - } - - var localStorageWrapper = { - _driver: 'localStorageWrapper', - _initStorage: _initStorage, - // Default API, from Gaia/localStorage. - iterate: iterate, - getItem: getItem, - setItem: setItem, - removeItem: removeItem, - clear: clear, - length: length, - key: key, - keys: keys - }; - - if (moduleType === ModuleType.EXPORT) { - module.exports = localStorageWrapper; - } else if (moduleType === ModuleType.DEFINE) { - define('localStorageWrapper', function() { - return localStorageWrapper; - }); - } else { - this.localStorageWrapper = localStorageWrapper; - } -}).call(window); -/* - * Includes code from: - * - * base64-arraybuffer - * https://github.com/niklasvh/base64-arraybuffer - * - * Copyright (c) 2012 Niklas von Hertzen - * Licensed under the MIT license. - */ -(function() { - 'use strict'; - - // Promises! - var Promise = (typeof module !== 'undefined' && module.exports) ? - require('promise') : this.Promise; - - var globalObject = this; - var serializer = null; - var openDatabase = this.openDatabase; - - // If WebSQL methods aren't available, we can stop now. - if (!openDatabase) { - return; - } - - var ModuleType = { - DEFINE: 1, - EXPORT: 2, - WINDOW: 3 - }; - - // Attaching to window (i.e. no module loader) is the assumed, - // simple default. - var moduleType = ModuleType.WINDOW; - - // Find out what kind of module setup we have; if none, we'll just attach - // localForage to the main window. - if (typeof module !== 'undefined' && module.exports) { - moduleType = ModuleType.EXPORT; - } else if (typeof define === 'function' && define.amd) { - moduleType = ModuleType.DEFINE; - } - - // Open the WebSQL database (automatically creates one if one didn't - // previously exist), using any options set in the config. - function _initStorage(options) { - var self = this; - var dbInfo = { - db: null - }; - - if (options) { - for (var i in options) { - dbInfo[i] = typeof(options[i]) !== 'string' ? - options[i].toString() : options[i]; - } - } - - var serializerPromise = new Promise(function(resolve/*, reject*/) { - // We allow localForage to be declared as a module or as a - // library available without AMD/require.js. - if (moduleType === ModuleType.DEFINE) { - require(['localforageSerializer'], resolve); - } else if (moduleType === ModuleType.EXPORT) { - // Making it browserify friendly - resolve(require('./../utils/serializer')); - } else { - resolve(globalObject.localforageSerializer); - } - }); - - var dbInfoPromise = new Promise(function(resolve, reject) { - // Open the database; the openDatabase API will automatically - // create it for us if it doesn't exist. - try { - dbInfo.db = openDatabase(dbInfo.name, String(dbInfo.version), - dbInfo.description, dbInfo.size); - } catch (e) { - return self.setDriver(self.LOCALSTORAGE).then(function() { - return self._initStorage(options); -}).then(resolve)["catch"](reject); - } - - // Create our key/value table if it doesn't exist. - dbInfo.db.transaction(function(t) { - t.executeSql('CREATE TABLE IF NOT EXISTS ' + dbInfo.storeName + - ' (id INTEGER PRIMARY KEY, key unique, value)', [], - function() { - self._dbInfo = dbInfo; - resolve(); - }, function(t, error) { - reject(error); - }); - }); - }); - - return serializerPromise.then(function(lib) { - serializer = lib; - return dbInfoPromise; - }); - } - - function getItem(key, callback) { - var self = this; - - // Cast the key to a string, as that's all we can set as a key. - if (typeof key !== 'string') { - window.console.warn(key + - ' used as a key, but it is not a string.'); - key = String(key); - } - - var promise = new Promise(function(resolve, reject) { - self.ready().then(function() { - var dbInfo = self._dbInfo; - dbInfo.db.transaction(function(t) { - t.executeSql('SELECT * FROM ' + dbInfo.storeName + - ' WHERE key = ? LIMIT 1', [key], - function(t, results) { - var result = results.rows.length ? - results.rows.item(0).value : null; - - // Check to see if this is serialized content we need to - // unpack. - if (result) { - result = serializer.deserialize(result); - } - - resolve(result); - }, function(t, error) { - - reject(error); - }); - }); - })["catch"](reject); - }); - - executeCallback(promise, callback); - return promise; - } - - function iterate(iterator, callback) { - var self = this; - - var promise = new Promise(function(resolve, reject) { - self.ready().then(function() { - var dbInfo = self._dbInfo; - - dbInfo.db.transaction(function(t) { - t.executeSql('SELECT * FROM ' + dbInfo.storeName, [], - function(t, results) { - var rows = results.rows; - var length = rows.length; - - for (var i = 0; i < length; i++) { - var item = rows.item(i); - var result = item.value; - - // Check to see if this is serialized content - // we need to unpack. - if (result) { - result = serializer.deserialize(result); - } - - result = iterator(result, item.key, i + 1); - - // void(0) prevents problems with redefinition - // of `undefined`. - if (result !== void(0)) { - resolve(result); - return; - } - } - - resolve(); - }, function(t, error) { - reject(error); - }); - }); - })["catch"](reject); - }); - - executeCallback(promise, callback); - return promise; - } - - function setItem(key, value, callback) { - var self = this; - - // Cast the key to a string, as that's all we can set as a key. - if (typeof key !== 'string') { - window.console.warn(key + - ' used as a key, but it is not a string.'); - key = String(key); - } - - var promise = new Promise(function(resolve, reject) { - self.ready().then(function() { - // The localStorage API doesn't return undefined values in an - // "expected" way, so undefined is always cast to null in all - // drivers. See: https://github.com/mozilla/localForage/pull/42 - if (value === undefined) { - value = null; - } - - // Save the original value to pass to the callback. - var originalValue = value; - - serializer.serialize(value, function(value, error) { - if (error) { - reject(error); - } else { - var dbInfo = self._dbInfo; - dbInfo.db.transaction(function(t) { - t.executeSql('INSERT OR REPLACE INTO ' + - dbInfo.storeName + - ' (key, value) VALUES (?, ?)', - [key, value], function() { - resolve(originalValue); - }, function(t, error) { - reject(error); - }); - }, function(sqlError) { // The transaction failed; check - // to see if it's a quota error. - if (sqlError.code === sqlError.QUOTA_ERR) { - // We reject the callback outright for now, but - // it's worth trying to re-run the transaction. - // Even if the user accepts the prompt to use - // more storage on Safari, this error will - // be called. - // - // TODO: Try to re-run the transaction. - reject(sqlError); - } - }); - } - }); - })["catch"](reject); - }); - - executeCallback(promise, callback); - return promise; - } - - function removeItem(key, callback) { - var self = this; - - // Cast the key to a string, as that's all we can set as a key. - if (typeof key !== 'string') { - window.console.warn(key + - ' used as a key, but it is not a string.'); - key = String(key); - } - - var promise = new Promise(function(resolve, reject) { - self.ready().then(function() { - var dbInfo = self._dbInfo; - dbInfo.db.transaction(function(t) { - t.executeSql('DELETE FROM ' + dbInfo.storeName + - ' WHERE key = ?', [key], function() { - - resolve(); - }, function(t, error) { - - reject(error); - }); - }); - })["catch"](reject); - }); - - executeCallback(promise, callback); - return promise; - } - - // Deletes every item in the table. - // TODO: Find out if this resets the AUTO_INCREMENT number. - function clear(callback) { - var self = this; - - var promise = new Promise(function(resolve, reject) { - self.ready().then(function() { - var dbInfo = self._dbInfo; - dbInfo.db.transaction(function(t) { - t.executeSql('DELETE FROM ' + dbInfo.storeName, [], - function() { - resolve(); - }, function(t, error) { - reject(error); - }); - }); - })["catch"](reject); - }); - - executeCallback(promise, callback); - return promise; - } - - // Does a simple `COUNT(key)` to get the number of items stored in - // localForage. - function length(callback) { - var self = this; - - var promise = new Promise(function(resolve, reject) { - self.ready().then(function() { - var dbInfo = self._dbInfo; - dbInfo.db.transaction(function(t) { - // Ahhh, SQL makes this one soooooo easy. - t.executeSql('SELECT COUNT(key) as c FROM ' + - dbInfo.storeName, [], function(t, results) { - var result = results.rows.item(0).c; - - resolve(result); - }, function(t, error) { - - reject(error); - }); - }); - })["catch"](reject); - }); - - executeCallback(promise, callback); - return promise; - } - - // Return the key located at key index X; essentially gets the key from a - // `WHERE id = ?`. This is the most efficient way I can think to implement - // this rarely-used (in my experience) part of the API, but it can seem - // inconsistent, because we do `INSERT OR REPLACE INTO` on `setItem()`, so - // the ID of each key will change every time it's updated. Perhaps a stored - // procedure for the `setItem()` SQL would solve this problem? - // TODO: Don't change ID on `setItem()`. - function key(n, callback) { - var self = this; - - var promise = new Promise(function(resolve, reject) { - self.ready().then(function() { - var dbInfo = self._dbInfo; - dbInfo.db.transaction(function(t) { - t.executeSql('SELECT key FROM ' + dbInfo.storeName + - ' WHERE id = ? LIMIT 1', [n + 1], - function(t, results) { - var result = results.rows.length ? - results.rows.item(0).key : null; - resolve(result); - }, function(t, error) { - reject(error); - }); - }); - })["catch"](reject); - }); - - executeCallback(promise, callback); - return promise; - } - - function keys(callback) { - var self = this; - - var promise = new Promise(function(resolve, reject) { - self.ready().then(function() { - var dbInfo = self._dbInfo; - dbInfo.db.transaction(function(t) { - t.executeSql('SELECT key FROM ' + dbInfo.storeName, [], - function(t, results) { - var keys = []; - - for (var i = 0; i < results.rows.length; i++) { - keys.push(results.rows.item(i).key); - } - - resolve(keys); - }, function(t, error) { - - reject(error); - }); - }); - })["catch"](reject); - }); - - executeCallback(promise, callback); - return promise; - } - - function executeCallback(promise, callback) { - if (callback) { - promise.then(function(result) { - callback(null, result); - }, function(error) { - callback(error); - }); - } - } - - var webSQLStorage = { - _driver: 'webSQLStorage', - _initStorage: _initStorage, - iterate: iterate, - getItem: getItem, - setItem: setItem, - removeItem: removeItem, - clear: clear, - length: length, - key: key, - keys: keys - }; - - if (moduleType === ModuleType.DEFINE) { - define('webSQLStorage', function() { - return webSQLStorage; - }); - } else if (moduleType === ModuleType.EXPORT) { - module.exports = webSQLStorage; - } else { - this.webSQLStorage = webSQLStorage; - } -}).call(window); -(function() { - 'use strict'; - - // Promises! - var Promise = (typeof module !== 'undefined' && module.exports) ? - require('promise') : this.Promise; - - // Custom drivers are stored here when `defineDriver()` is called. - // They are shared across all instances of localForage. - var CustomDrivers = {}; - - var DriverType = { - INDEXEDDB: 'asyncStorage', - LOCALSTORAGE: 'localStorageWrapper', - WEBSQL: 'webSQLStorage' - }; - - var DefaultDriverOrder = [ - DriverType.INDEXEDDB, - DriverType.WEBSQL, - DriverType.LOCALSTORAGE - ]; - - var LibraryMethods = [ - 'clear', - 'getItem', - 'iterate', - 'key', - 'keys', - 'length', - 'removeItem', - 'setItem' - ]; - - var ModuleType = { - DEFINE: 1, - EXPORT: 2, - WINDOW: 3 - }; - - var DefaultConfig = { - description: '', - driver: DefaultDriverOrder.slice(), - name: 'localforage', - // Default DB size is _JUST UNDER_ 5MB, as it's the highest size - // we can use without a prompt. - size: 4980736, - storeName: 'keyvaluepairs', - version: 1.0 - }; - - // Attaching to window (i.e. no module loader) is the assumed, - // simple default. - var moduleType = ModuleType.WINDOW; - - // Find out what kind of module setup we have; if none, we'll just attach - // localForage to the main window. - if (typeof module !== 'undefined' && module.exports) { - moduleType = ModuleType.EXPORT; - } else if (typeof define === 'function' && define.amd) { - moduleType = ModuleType.DEFINE; - } - - // Check to see if IndexedDB is available and if it is the latest - // implementation; it's our preferred backend library. We use "_spec_test" - // as the name of the database because it's not the one we'll operate on, - // but it's useful to make sure its using the right spec. - // See: https://github.com/mozilla/localForage/issues/128 - var driverSupport = (function(self) { - // Initialize IndexedDB; fall back to vendor-prefixed versions - // if needed. - var indexedDB = indexedDB || self.indexedDB || self.webkitIndexedDB || - self.mozIndexedDB || self.OIndexedDB || - self.msIndexedDB; - - var result = {}; - - result[DriverType.WEBSQL] = !!self.openDatabase; - result[DriverType.INDEXEDDB] = !!(function() { - // We mimic PouchDB here; just UA test for Safari (which, as of - // iOS 8/Yosemite, doesn't properly support IndexedDB). - // IndexedDB support is broken and different from Blink's. - // This is faster than the test case (and it's sync), so we just - // do this. *SIGH* - // http://bl.ocks.org/nolanlawson/raw/c83e9039edf2278047e9/ - // - // We test for openDatabase because IE Mobile identifies itself - // as Safari. Oh the lulz... - if (typeof self.openDatabase !== 'undefined' && self.navigator && - self.navigator.userAgent && - /Safari/.test(self.navigator.userAgent) && - !/Chrome/.test(self.navigator.userAgent)) { - return false; - } - try { - return indexedDB && - typeof indexedDB.open === 'function' && - // Some Samsung/HTC Android 4.0-4.3 devices - // have older IndexedDB specs; if this isn't available - // their IndexedDB is too old for us to use. - // (Replaces the onupgradeneeded test.) - typeof self.IDBKeyRange !== 'undefined'; - } catch (e) { - return false; - } - })(); - - result[DriverType.LOCALSTORAGE] = !!(function() { - try { - return (self.localStorage && - ('setItem' in self.localStorage) && - (self.localStorage.setItem)); - } catch (e) { - return false; - } - })(); - - return result; - })(this); - - var isArray = Array.isArray || function(arg) { - return Object.prototype.toString.call(arg) === '[object Array]'; - }; - - function callWhenReady(localForageInstance, libraryMethod) { - localForageInstance[libraryMethod] = function() { - var _args = arguments; - return localForageInstance.ready().then(function() { - return localForageInstance[libraryMethod].apply(localForageInstance, _args); - }); - }; - } - - function extend() { - for (var i = 1; i < arguments.length; i++) { - var arg = arguments[i]; - - if (arg) { - for (var key in arg) { - if (arg.hasOwnProperty(key)) { - if (isArray(arg[key])) { - arguments[0][key] = arg[key].slice(); - } else { - arguments[0][key] = arg[key]; - } - } - } - } - } - - return arguments[0]; - } - - function isLibraryDriver(driverName) { - for (var driver in DriverType) { - if (DriverType.hasOwnProperty(driver) && - DriverType[driver] === driverName) { - return true; - } - } - - return false; - } - - var globalObject = this; - - function LocalForage(options) { - this._config = extend({}, DefaultConfig, options); - this._driverSet = null; - this._ready = false; - this._dbInfo = null; - - // Add a stub for each driver API method that delays the call to the - // corresponding driver method until localForage is ready. These stubs - // will be replaced by the driver methods as soon as the driver is - // loaded, so there is no performance impact. - for (var i = 0; i < LibraryMethods.length; i++) { - callWhenReady(this, LibraryMethods[i]); - } - - this.setDriver(this._config.driver); - } - - LocalForage.prototype.INDEXEDDB = DriverType.INDEXEDDB; - LocalForage.prototype.LOCALSTORAGE = DriverType.LOCALSTORAGE; - LocalForage.prototype.WEBSQL = DriverType.WEBSQL; - - // Set any config values for localForage; can be called anytime before - // the first API call (e.g. `getItem`, `setItem`). - // We loop through options so we don't overwrite existing config - // values. - LocalForage.prototype.config = function(options) { - // If the options argument is an object, we use it to set values. - // Otherwise, we return either a specified config value or all - // config values. - if (typeof(options) === 'object') { - // If localforage is ready and fully initialized, we can't set - // any new configuration values. Instead, we return an error. - if (this._ready) { - return new Error("Can't call config() after localforage " + - 'has been used.'); - } - - for (var i in options) { - if (i === 'storeName') { - options[i] = options[i].replace(/\W/g, '_'); - } - - this._config[i] = options[i]; - } - - // after all config options are set and - // the driver option is used, try setting it - if ('driver' in options && options.driver) { - this.setDriver(this._config.driver); - } - - return true; - } else if (typeof(options) === 'string') { - return this._config[options]; - } else { - return this._config; - } - }; - - // Used to define a custom driver, shared across all instances of - // localForage. - LocalForage.prototype.defineDriver = function(driverObject, callback, - errorCallback) { - var defineDriver = new Promise(function(resolve, reject) { - try { - var driverName = driverObject._driver; - var complianceError = new Error( - 'Custom driver not compliant; see ' + - 'https://mozilla.github.io/localForage/#definedriver' - ); - var namingError = new Error( - 'Custom driver name already in use: ' + driverObject._driver - ); - - // A driver name should be defined and not overlap with the - // library-defined, default drivers. - if (!driverObject._driver) { - reject(complianceError); - return; - } - if (isLibraryDriver(driverObject._driver)) { - reject(namingError); - return; - } - - var customDriverMethods = LibraryMethods.concat('_initStorage'); - for (var i = 0; i < customDriverMethods.length; i++) { - var customDriverMethod = customDriverMethods[i]; - if (!customDriverMethod || - !driverObject[customDriverMethod] || - typeof driverObject[customDriverMethod] !== 'function') { - reject(complianceError); - return; - } - } - - var supportPromise = Promise.resolve(true); - if ('_support' in driverObject) { - if (driverObject._support && typeof driverObject._support === 'function') { - supportPromise = driverObject._support(); - } else { - supportPromise = Promise.resolve(!!driverObject._support); - } - } - - supportPromise.then(function(supportResult) { - driverSupport[driverName] = supportResult; - CustomDrivers[driverName] = driverObject; - resolve(); - }, reject); - } catch (e) { - reject(e); - } - }); - - defineDriver.then(callback, errorCallback); - return defineDriver; - }; - - LocalForage.prototype.driver = function() { - return this._driver || null; - }; - - LocalForage.prototype.ready = function(callback) { - var self = this; - - var ready = new Promise(function(resolve, reject) { - self._driverSet.then(function() { - if (self._ready === null) { - self._ready = self._initStorage(self._config); - } - - self._ready.then(resolve, reject); - })["catch"](reject); - }); - - ready.then(callback, callback); - return ready; - }; - - LocalForage.prototype.setDriver = function(drivers, callback, - errorCallback) { - var self = this; - - if (typeof drivers === 'string') { - drivers = [drivers]; - } - - this._driverSet = new Promise(function(resolve, reject) { - var driverName = self._getFirstSupportedDriver(drivers); - var error = new Error('No available storage method found.'); - - if (!driverName) { - self._driverSet = Promise.reject(error); - reject(error); - return; - } - - self._dbInfo = null; - self._ready = null; - - if (isLibraryDriver(driverName)) { - // We allow localForage to be declared as a module or as a - // library available without AMD/require.js. - if (moduleType === ModuleType.DEFINE) { - require([driverName], function(lib) { - self._extend(lib); - - resolve(); - }); - - return; - } else if (moduleType === ModuleType.EXPORT) { - // Making it browserify friendly - var driver; - switch (driverName) { - case self.INDEXEDDB: - driver = require('./drivers/indexeddb'); - break; - case self.LOCALSTORAGE: - driver = require('./drivers/localstorage'); - break; - case self.WEBSQL: - driver = require('./drivers/websql'); - } - - self._extend(driver); - } else { - self._extend(globalObject[driverName]); - } - } else if (CustomDrivers[driverName]) { - self._extend(CustomDrivers[driverName]); - } else { - self._driverSet = Promise.reject(error); - reject(error); - return; - } - - resolve(); - }); - - function setDriverToConfig() { - self._config.driver = self.driver(); - } - this._driverSet.then(setDriverToConfig, setDriverToConfig); - - this._driverSet.then(callback, errorCallback); - return this._driverSet; - }; - - LocalForage.prototype.supports = function(driverName) { - return !!driverSupport[driverName]; - }; - - LocalForage.prototype._extend = function(libraryMethodsAndProperties) { - extend(this, libraryMethodsAndProperties); - }; - - // Used to determine which driver we should use as the backend for this - // instance of localForage. - LocalForage.prototype._getFirstSupportedDriver = function(drivers) { - if (drivers && isArray(drivers)) { - for (var i = 0; i < drivers.length; i++) { - var driver = drivers[i]; - - if (this.supports(driver)) { - return driver; - } - } - } - - return null; - }; - - LocalForage.prototype.createInstance = function(options) { - return new LocalForage(options); - }; - - // The actual localForage object that we expose as a module or via a - // global. It's extended by pulling in one of our other libraries. - var localForage = new LocalForage(); - - // We allow localForage to be declared as a module or as a library - // available without AMD/require.js. - if (moduleType === ModuleType.DEFINE) { - define('localforage', function() { - return localForage; - }); - } else if (moduleType === ModuleType.EXPORT) { - module.exports = localForage; - } else { - this.localforage = localForage; - } -}).call(window); - - - - -///////////////////////////////// -/// NATIVE MODULE STARTS HERE /// -///////////////////////////////// - -Elm.Native = Elm.Native || {}; -Elm.Native.Storage = {}; -Elm.Native.Storage.make = function(localRuntime){ - - localRuntime.Native = localRuntime.Native || {}; - localRuntime.Native.Storage = localRuntime.Native.Storage || {}; - - if (localRuntime.Native.Storage.values){ - return localRuntime.Native.Storage.values; - } - - var Task = Elm.Native.Task.make(localRuntime); - var Utils = Elm.Native.Utils.make(localRuntime); - var List = Elm.Native.List.make(localRuntime); - - // getItemAsJson : String -> Task error Value - var getItemAsJson = function(key){ - return Task.asyncFunction(function(callback){ - localforage.getItem(key).then(function(value){ - callback(Task.succeed(value)); - }).catch(function(err){ - console.log("Storage Call: getItemAsJson has failed with key: " + key); - callback(Task.fail("Storage Call: getItemAsJson has failed with key: " + key)); - }); - }); - }; - - // setItem : String -> Value -> Task error () - var setItem = function(key, value){ - return Task.asyncFunction(function(callback){ - localforage.setItem(key, value).then(function(){ - callback(Task.succeed(Utils.Tuple0)); - }).catch(function(){ - console.log("Storage Call: setItem has failed with key: " + key + " and value: " + value); - callback(Task.fail("Storage Call: setItem has failed with key: " + key + " and value: " + value)); - }); - }); - }; - - // removeItem : String -> Task error () - var removeItem = function(key){ - return Task.asyncFunction(function(callback){ - localforage.removeItem(key).then(function(){ - callback(Task.succeed(Utils.Tuple0)); - }).catch(function(){ - callback(Task.fail("Storage Call: removeItem has failed with key: " + key)); - }); - }); - }; - - // clear : Task error () - var clear = Task.asyncFunction(function(callback){ - localforage.clear().then(function(){ - callback(Task.succeed(Utils.Tuple0)); - }).catch(function(){ - callback(Task.fail("Storage Call: clear has failed")); - }); - }); - - - // keys : Task error (List String) - var keys = Task.asyncFunction(function(callback){ - localforage.keys().then(function(keys){ - callback(Task.succeed(List.fromArray(keys))); - }).catch(function(){ - callback(Task.fail("Storage Call: keys has failed")); - }); - }); - - // length : Task error Int - var length = Task.asyncFunction(function(callback){ - localforage.length().then(function(numberOfKeys){ - callback(Task.succeed(numberOfKeys)); - }).catch(function(){ - callback(Task.fail("Storage Call: length has failed")); - }); - }); - - - return { - getItemAsJson : getItemAsJson, - setItem : F2(setItem), - removeItem : removeItem, - clear : clear, - keys : keys, - length : length - }; - - -}; diff --git a/src/vendor/elm-storage/src/Storage.elm b/src/vendor/elm-storage/src/Storage.elm deleted file mode 100644 index 55c9acf..0000000 --- a/src/vendor/elm-storage/src/Storage.elm +++ /dev/null @@ -1,39 +0,0 @@ -module Storage where - -import Json.Encode exposing (Value) -import Json.Decode exposing (Decoder, decodeValue) -import Task exposing (Task, succeed, fail, andThen) -import List -import Native.Storage - - -getItemAsJson : String -> Task String Value -getItemAsJson = Native.Storage.getItemAsJson - --- Do better error detection -getItem : String -> Decoder value -> Task String value -getItem key decoder = - let decode value = case decodeValue decoder value of - Ok v -> succeed v - Err err -> fail "Failed" - in - getItemAsJson key `andThen` decode - -setItem : String -> Value -> Task String () -setItem = Native.Storage.setItem - -removeItem : String -> Task String () -removeItem = Native.Storage.removeItem - -clear : Task String () -clear = Native.Storage.clear - -keys : Task String (List String) -keys = Native.Storage.keys - --- keysArray : Task error (Array String) --- keysArray : Native.Storage.keysArray - - -length : Task String Int -length = Native.Storage.length diff --git a/src/vendor/elm-web-api/.gitignore b/src/vendor/elm-web-api/.gitignore deleted file mode 100644 index 88c4e68..0000000 --- a/src/vendor/elm-web-api/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -**/elm-stuff -**/elm.js -**/index.html -**/elm.html -**/node_modules -.*.swp diff --git a/src/vendor/elm-web-api/.travis.yml b/src/vendor/elm-web-api/.travis.yml deleted file mode 100644 index b710e11..0000000 --- a/src/vendor/elm-web-api/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -language: node_js - -node_js: - - 0.10 - -sudo: false - -install: - - cd test - - npm install - - cd $TEST_DIR - - npm install - - ./node_modules/elm/bin/elm-package install --yes - -script: - - npm run ci - -env: - matrix: - - TEST_DIR=0.15 diff --git a/src/vendor/elm-web-api/README.md b/src/vendor/elm-web-api/README.md deleted file mode 100644 index 099e328..0000000 --- a/src/vendor/elm-web-api/README.md +++ /dev/null @@ -1,1271 +0,0 @@ -[![Build Status](https://travis-ci.org/rgrempel/elm-web-api.svg)](https://travis-ci.org/rgrempel/elm-web-api) - -[![Sauce Test Status](https://saucelabs.com/browser-matrix/elm-web-api.svg)](https://saucelabs.com/u/elm-web-api) - -# elm-web-api - -The purpose of this package is to expose various standard web APIs to Elm, -or document where they are already exposed. - -By "web APIs" I basically mean the kind of things that are listed on -Mozilla's various Web APIs pages, e.g. - -* https://developer.mozilla.org/en-US/docs/Web/API -* https://developer.mozilla.org/en-US/docs/WebAPI -* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference - -Essentially, they are various facilities available in a Javascript web -environment. - -In order for Elm to use such facilities, it is necessary to write "native" -code. So, I'm plugging away at it -- this is a work in progress. - - -## Contents - -* [Supported browsers](#supportedbrowsers) -* [Installation](#installation) -* APIs - * [WebAPI.AnimationFrame](#webapianimationframe) - * [WebAPI.Cookie](#webapicookie) - * [WebAPI.Document](#webapidocument) - * [WebAPI.Date](#webapidate) - * [WebAPI.Location](#webapilocation) - * [WebAPI.Math](#webapimath) - * [WebAPI.Number](#webapinumber) - * [WebAPI.Screen](#webapiscreen) - * [WebAPI.Storage](#webapistorage) - * [WebAPI.Window](#webapiwindow) - - -## Supported browsers - -I have now set up testing via Travis and SauceLabs, and you can see at the top -of this page a graphic that indicates which browsers I'm testing against. -Let me know if you think I should try out some older verions as well. - -For the moment, I'm not thinking too hard about supporting node.js as well. -That's a somewhat larger issue for Elm (it requires some shimming even to get -elm-lang/core to work). Furthermore, it might make sense to have a separate -package to wrap node.js-oriented APIs (and provide appropriate shims), even if -there is some overlap. - - -## Installation - -Because elm-web-api uses "native" modules, it requires approval before it can -be included in the -[Elm package repository](http://package.elm-lang.org/packages). For a variety of -reasons, it's unlikely to get such approval. Thus, you cannot currently install -it using `elm-package`. - -However, you can still install it and use it via the following steps: - -* Download this respository in one way or another. For instance, you might use: - - git clone https://github.com/rgrempel/elm-web-api.git - - Or, you might use git submodules, if you're adept at that. (I wouldn't suggest - trying it if you've never heard of them before). - -* Modify your `elm-package.json` to refer to the `src` folder. - - You can choose where you want to put the downloaded code, but wherever that - is, simply modify your `elm-package.json` file so that it can find the - `src` folder. So, the "source-directories" entry in your - `elm-package.json` file might end up looking like this: - - "source-directories": [ - "src", - "elm-web-api/src" - ], - - But, of course, that depends on where you've actually put it, and where the - rest of your code is. - -* Modify your `elm-package.json` to indicate that you're using 'native' modules. - To do this, add the following entry to `elm-package.json`: - - "native-modules": true, - -Now, doing this would have several implications which you should be aware of. - -* You would, essentially, be trusting me (or looking to verify for yourself) - that the native code in this module is of high quality and will not cause - run-time errors or other problems. - -* You would be relying on me to update that code when the mechanism for using - 'native' modules in Elm changes, or when certain other internal details of Elm's - implementation change. Furthermore, you'd have to check here whenever the Elm - compiler's version changes, or the Elm core library's version changes, to see - whether an update is required. - -* If you're using this as part of a module you'd like to publish yourself, - then you'll now also need approval before becoming available on the Elm - package repository. - -So, you may or may not really want to do this. But I thought it would be nice to -let you know how. - - -## APIs - -### WebAPI.AnimationFrame - -Bindings for -[`window.requestAnimationFrame()`](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame) -and [`window.cancelAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/Window/cancelAnimationFrame). - -Note that -[jwmerrill/elm-animation-frame](http://package.elm-lang.org/packages/jwmerrill/elm-animation-frame/latest) -provides for a `Signal` of animation frames. So, this module merely provides a -`Task`-oriented alternative. - -Other higher-level alternatives include -[evancz/elm-effects](http://package.elm-lang.org/packages/evancz/elm-effects/latest) -and [rgrempel/elm-ticker](https://github.com/rgrempel/elm-ticker.git). - -```elm -module WebAPI.AnimationFrame where - -{-| A task which, when executed, will call `window.requestAnimationFrame()`. -The task will complete when `requestAnimationFrame()` fires its callback, and -will pass along the value provided by the callback. - -So, to do something when the callback fires, just add an `andThen` to the task. --} -task : Task x Time - -{-| A more complex implementation of `window.requestAnimationFrame()` which -allows for cancelling the request. - -Returns a `Task` which, when executed, will call -`window.requestAnimationFrame()`, and then immediately complete with the -identifier returned by `requestAnimationFrame()`. You can supply this -identifier to `cancel` if you want to cancel the request. - -Assuming that you don't cancel the request, the following sequence of events will occur: - -* `window.requestAnimationFrame()` will eventually fire its callback, providing a timestamp -* Your function will be called with that timestamp -* The `Task` returned by your function will be immediately executed --} -request : (Time -> Task x a) -> Task y Request - -{-| Opaque type which represents an animation frame request. -} -type Request - -{-| Returns a task which, when executed, will cancel the supplied request -via `window.cancelAnimationFrame()`. --} -cancel : Request -> Task x () -``` - - ------------------ - -### WebAPI.Cookie - -Wraps the browser's -[`document.cookie`](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie) -object. - -```elm -module WebAPI.Cookie where - -{-| A `Task` which, when executed, will succeed with the cookies. - -In the resulting `Dict`, the keys and values are the key=value pairs parsed from -Javascript's `document.cookie`. The keys and values will have been uriDecoded. --} -get : Task x (Dict String String) - -{-| A task which will set a cookie using the provided key (first parameter) -and value (second parameter). - -The key and value will both be uriEncoded. --} -set : String -> String -> Task x () - -{-| A task which will set a cookie using the provided options, key (second -parameter), and value (third parameter). - -The key and value will be uriEncoded, as well as the path and domain options -(if provided). --} -setWith : Options -> String -> String -> Task x () - -{-| Options which you can provide to setWith. -} -type alias Options = - { path : Maybe String - , domain : Maybe String - , maxAge : Maybe Time - , expires : Maybe Date - , secure : Maybe Bool - } - -{-| The default options, in which all options are set to `Nothing`. - -You can use this as a starting point for `setWith`, where you only want to -specify some options. --} -defaultOptions : Options -``` - ------------------ - -### WebAPI.Date - -Generally speaking, dates are dealt with by the `Date` and `Time` modules in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -See [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date). - -Truly dealing with all the complexity of dates requires something that goes -far beyond the Javascript API -- for instance, one could ideally think in terms -of wrapping (or, even better, porting) the [moment.js](http://momentjs.com) -library (or something even better). - -That isn't in scope for this module. Instead, this is intended merely to be a -thin wrapper over the Javascript `Date` API, such as it is. - -```elm -module WebAPI.Date where - -{- --------------------------------- - Getting the current date and time - --------------------------------- -} - -{-| Get the current date, via the browser's `new Date()` -} -current : Task x Date - -{-| Get the current time, via the browser's `Date.now()` -} -now : Task x Time - -{- --------- - Timezones - --------- -} - -{-| The Javascript API allows you to perform certain operations in terms of -the "local" timezone, or in terms of UTC. So, where we wrap those APIs, we use -this type to let you pick (rather than having separate functions). Of course, -you can use partial application to create separate functions if you like. - -Note that this isn't the kind of support that a more sophisticated library -would have for timezones -- it merely wraps what Javascript provides. --} -type Timezone - = Local - | UTC - -{-| Javascript's `getTimezoneOffset()`. - -This represents what Javascript thinks is the offset between UTC and local time, -for the specified date. It can differ from date to date depending on whether -daylight savings time is in effect on that date. - -Note that this is in units of `Time`, so you can scale via `Time.inMinutes` etc. --} -timezoneOffset : Date -> Time - -{- ------------------- - The parts of a date - ------------------- -} - -{-| The parts of a date. - -Note that (as in the Javascript APIs) the month is 0-based, with January = 0. --} -type alias Parts = - { year : Int - , month : Int - , day : Int - , hour : Int - , minute : Int - , second : Int - , millisecond : Int - } - -{-| Construct a `Date` from the provided parts, using the specified timezone. - -For `Local`, this uses `new Date(...)`. - -For `UTC`, this uses `new Date(Date.UTC(...))`. --} -fromParts : Timezone -> Parts -> Date - -{-| Break a `Date` up into its parts, using the specified timezone. - -For `Local`, this uses `getFullYear()`, `getMonth()`, etc. - -For `UTC`, this uses `getUTCFullYear()`, `getUTCMonth()`, etc. --} -toParts : Timezone -> Date -> Parts - -{-| Get the day of the week corresopnding to a `Date`. - -This is handled separately from `Parts` because it is not symmetrical -- -it makes no sense for there to be a constructor based on this. --} -dayOfWeek : Timezone -> Date -> Date.Day - -{-| Converts from Javascript's 0-based months (where January = 0) to`Date.Month`. -} -toMonth : Int -> Date.Month - -{-| Converts from `Date.Month` to Javascript's 0-based months (where January = 0). -} -fromMonth : Date.Month -> Int - -{-| Converts from Javascript's 0-based days (where Sunday = 0) to`Date.Day`. -} -toDay : Int -> Date.Day - -{-| Converts from `Date.Day` to Javascript's 0-based days (where Sunday = 0). -} -fromDay : Date.Day -> Int - -{- --------------- - Date arithmetic - --------------- -} - -{-| Offset the `Date` by the supplied `Time` (i.e. positive values offset into -the future, and negative values into the past). - -You can use `day`, `week`, `Time.minute`, etc. to scale. However, that won't -always do what you actually want, since the values are treated as durations, -rather than human-oriented intervals. For instance, `offsetTime (365 * day) -date` will advance the date by 365 days. However, if a leap year is involved, -the resulting date might be a different day of the year. If you actually want -the same day in the next year, then use `offsetYear` instead. --} -offsetTime : Time -> Date -> Date - -{-| Offset the `Date` by the specified number of years (forward or backward), -using Javascript's `setFullYear()` and `getFullYear()` (or `getUTCFullYear()` -and `setUTCFullYear`). - -Leap years are handled by the underlying Javascript APIs as follows: - -* If the supplied date is February 29, and the target year has no February 29, - then you'll end up with March 1 in the target year. (Arguably, you might - prefer February 28, but I'm not sure there is a clearly correct answer). - -* If the supplied date is February 29, and the target year also has a February - 29, then you'll end up with February 29. - -* The year is interpreted in terms of either the local timezone or UTC, according - to what you specify. I think the only case in which this could make a - difference is in determining whether it is February 29. - -* If the offset "crosses" a leap day, then you'll end up with the "same" day in - the target year ... for instance, `offsetYear 1` will sometimes move 365 - days and sometimes 366 days, depending on whether a leap year is involved. - -A more sophisticated module might deal with these cases a little differently. --} -offsetYear : Timezone -> Int -> Date -> Date - -{-| Offset the `Date` by the specified number of months (forward or backward), -using Javascript's `setMonth()` and `getMonth()` (or `setUTCMonth()` and -`getUTCMonth()`). - -Here are a few notes about the underlying Javascript implementation: - -* Overflow and underflow basically do the right thing. That is, if you end up - with negative numbers, the year is decremented, and if you end up with - numbers past 11, the year is incremented. (Remember that Javascript months - are 0-based). And, in either case, the month is set to something between - 0 and 11. - -* Dates at the beginning of the month are handled as you might expect. For - instance, adding 1 month to January 1 produces February 1, and adding 1 month - to February 1 produces March 1. Thus, the actual number of days added can vary, - depending on the length of the month. - -* However, dates at the end of the month are handled in a way that could seem - odd. For instance, adding 1 month to August 31 produces October 1 ... were - you expecting September 30? That would probably be more useful, and a more - sophisticated library might arrange for that. - -* Note that the date is interpreted according to either the local timezone or UTC, - as you specify. In some cases, that will affect whether the date is - considered to be the last day of the month, or the first day of the next - month, which will in turn affect whether the "end of month" anomaly is - triggered. --} -offsetMonth : Timezone -> Int -> Date -> Date - -{- --------------------------- - Some additional time scales - --------------------------- -} - -{-| A convenience for arithmetic, analogous to `Time.hour`, `Time.minute`, etc. -} -day : Time - -{-| A convenience for arithmetic, analogous to `Time.inHours`, `Time.inMinutes`, etc. -} -inDays : Time -> Float - -{-| A convenience for arithmetic, analogous to `Time.hour`, `Time.minute`, etc. -} -week : Time - -{-| A convenience for arithmetic, analogous to `Time.inHours`, `Time.inMinutes`, etc. -} -inWeeks : Time -> Float - -{- ------------------ - String conversions - ------------------ -} - -{-| The browser's `toDateString()` -} -dateString : Date -> String - -{-| The browser's `toTimeString()` -} -timeString : Date -> String - -{-| The browser's `toISOString()` -} -isoString : Date -> String - -{-| The browser's `toUTCString()` -} -utcString : Date -> String -``` - -***See also*** - -**`new Date(String)`** - -        -Use `Date.fromString` from -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`new Date(Number)`** - -        -Use `Date.fromTime` from -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`getDate()`** - -        -Use `Date.day` from -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest), -or `toParts Local >> .day` - -**`getDay()`** - -        -Use `Date.dayOfWeek` from -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest), -or `dayOfWeek Local` - -**`getFullYear()`** - -        -Use `Date.year` from -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest), -or `toParts Local >> .year` - -**`getHours()`** - -        -Use `Date.hour` from -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest), -or `toParts Local >> .hour` - -**`getMilliseconds()`** - -        -Use `Date.millisecond` from -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest), -or `toParts Local >> .millisecond` - -**`getMinutes()`** - -        -Use `Date.minute` from -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest), -or `toParts Local >> .minute` - -**`getMonth()`** - -        -Use `Date.month` from -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest), -or `toParts Local >> .month` - -**`getSeconds()`** - -        -Use `Date.second` from -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest), -or `toParts Local >> .second` - -**`getTime()`** - -        -Use `Date.toTime` from -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`getUTCDate()`, `getUTCFullYear()`, `getUTCHours()`, `getUTCMilliseconds()`, -`getUTCMinutes()`, `getUTCMonth()`, `getUTCSeconds()`** - -        -Use `toParts UTC`, and then pick out whichever things you need from the -resulting `Parts`. - -**`getUTCDay()`** - -        -Use `dayOfWeek UTC` - -**`parse()`** - -        -Use `Date.fromString` from -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`setDate()`, `setDay()`, `setFullYear()`, `setHours()`, `setMilliseconds()`, -`setMinutes()`, `setMonth()`, `setSeconds()`** - -        -What I would suggest is - -* Use `toParts Local` -* Update whatever fields you with to update -* Use `fromParts Local` to create a new `Date` - -Alternatively, in some scenarios you could use `offsetYear Local`, `offsetMonth Local` or `offsetTime`. - -**`setUTCDate()`, `setUTCDay()`, `setUTCFullYear()`, `setUTCHours()`, `setUTCMilliseconds()`, -`setUTCMinutes()`, `setUTCMonth()`, `setUTCSeconds()`** - -        -What I would suggest is - -* Use `toParts UTC` -* Update whatever fields you with to update -* Use `fromParts UTC` to create a new `Date` - -Alternatively, in some scenarios you could use `offsetYear UTC`, `offsetMonth UTC` or `offsetTime`. - -**`toLocaleString()`, `toLocaleDateString()`, `toLocaleTimeString()`** - -        -These aren't supported by Safari, so I've left them out for the moment. - - ------------- - -### WebAPI.Document - -See Mozilla documentation for the -[`Document` object](https://developer.mozilla.org/en-US/docs/Web/API/Document). - -Since the browser's `document` object has so many facilities attached, I've split some of -them up into individual modules -- see below for the cross-references. - -TODO: Finish going through the `document` API. - -```elm -module WebAPI.Document where - -{-| Possible values for the browser's `document.readyState` -} -type ReadyState - = Loading - | Interactive - | Complete - -{-| A `Signal` of changes to the browser's `document.readyState` -} -readyState : Signal ReadyState - -{-| A task which, when executed, succeeds with the value of the browser's -`document.readyState`. --} -getReadyState : Task x ReadyState - -{-| A task which, when executed, succeeds with the value of `document.title`. -} -getTitle : Task x String - -{-| A task which, when executed, sets the value of `document.title` to the -supplied `String`. --} -setTitle : String -> Task x () -``` - -***See also*** - -**`cookie`** - -        -See [WebAPI.Cookie](#webapicookie) - - ----------- - -### WebAPI.Intl - -TODO. Note that Safari doesn't support this, so it would need a -[polyfill](https://www.npmjs.com/package/intl). - -See [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl). - - ----------- - -### WebAPI.JSON - -Generally speaking, JSON is handled by the -[`Json.Decode`](http://package.elm-lang.org/packages/elm-lang/core/2.1.0/Json-Decode) and -[`Json.Encode`](http://package.elm-lang.org/packages/elm-lang/core/2.1.0/Json-Encode) -modules in elm-lang/core. - -TODO: Check if anything is missing. - -See [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON). - - ----------- - -### WebAPI.Location - -See the [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/API/Location). - -Note that there is a `Signal`-oriented library for location-related things at -[TheSeamau5/elm-history](http://package.elm-lang.org/packages/TheSeamau5/elm-history/latest). - -```elm -module WebAPI.Location where - -{-| The parts of a location object. Note `port'`, since `port` is a reserved word. -} -type alias Location = - { href: String - , protocol: String - , host: String - , hostname: String - , port': String - , pathname: String - , search: String - , hash: String - , origin: String - } - -{-| The browser's `window.location` object. -} -location : Task x Location - -{-| Reloads the page from the current URL. -} -reload : Source -> Task String () - -{-| Whether to force `reload` to use the server, or allow the cache. -} -type Source - = ForceServer - | AllowCache -``` - -***See also*** - -**`assign`** - -        -Use `setPath` from -[TheSeamau5/elm-history](http://package.elm-lang.org/packages/TheSeamau5/elm-history/latest). - -**`replace`** - -        -Use `replacePath` from -[TheSeamau5/elm-history](http://package.elm-lang.org/packages/TheSeamau5/elm-history/latest). - - ----------- - -### WebAPI.Math - -See the Mozilla documentation for the -[Math object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math). -Note that things marked "experimental" there have been omitted here. - -```elm -module WebAPI.Math where - -{-| Returns E to the power of x, where x is the argument, and E is Euler's -constant (2.718…), the base of the natural logarithm. --} -exp : number -> Float - -{-| Natural logarithm of 2, approximately 0.693. -} -ln2 : Float - -{-| Natural logarithm of 10, approximately 2.303. -} -ln10 : Float - -{-| Returns the natural logarithm (log e, also ln) of a number. -} -log : number -> Float - -{-| Base 2 logarithm of E, approximately 1.443. -} -log2e : Float - -{-| Base 10 logarithm of E, approximately 0.434. -} -log10e : Float - -{-| Returns a pseudo-random number between 0 and 1. - -Note that there is a more sophisticated implementation of `Random` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). -However, this may sometimes be useful if you're in a `Task` context anyway. --} -random : Task x Float - -{-| Square root of 1/2; equivalently, 1 over the square root of 2, -approximately 0.707. --} -sqrt1_2 : Float - -{-| Square root of 2, approximately 1.414. -} -sqrt2 : Float -``` - -***See also*** - -**`abs`** - -        -Use `Basics.abs` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`acos`** - -        -Use `Basics.acos` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`asin`** - -        -Use `Basics.asin` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`atan`** - -        -Use `Basics.atan` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`atan2`** - -        -Use `Basics.atan2` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`ceil`** - -        -Use `Basics.ceiling` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`cos`** - -        -Use `Basics.cos` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`E`** - -        -Use `Basics.e` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`floor`** - -        -Use `Basics.floor` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`max`** - -        -Use `List.maximum` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`min`** - -        -Use `List.minimum` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`PI`** - -        -Use `Basics.pi` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`pow`** - -        -Use `Basics.(^)` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`round`** - -        -Use `Basics.round` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`sin`** - -        -Use `Basics.sin` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`sqrt`** - -        -Use `Basics.sqrt` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`tan`** - -        -Use `Basics.tan` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - - ----------- - -### WebAPI.Number - -See the Mozilla documentation for the -[Number object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number). -Note that things marked "experimental" there have been omitted here. - -```elm -module WebAPI.Number where - -{-| The largest positive representable number. -} -maxValue : Float - -{-| The smallest positive representable number - that is, the positive number -closest to zero (without actually being zero). --} -minValue : Float - -{-| Special "not a number" value. -} -nan : Float - -{-| Special value representing negative infinity; returned on overflow. -} -negativeInfinity : Float - -{-| Special value representing infinity; returned on overflow. -} -positiveInfinity : Float - -{-| A string representing the provided number in exponential notation. -} -toExponential : number -> String - -{-| Either a string representing the second parameter in exponential notation, -with the requested number of digits after the decimal point (first parameter), -or an error. An error should not occur if the requested number of digits is -between 0 and 20. --} -toExponentialDigits : Int -> number -> Result String String - -{-| A string representing the second parameter in exponential notation, -with the requested number of digits after the decimal point (first parameter). -The number of digits will be limited to between 0 and 20. --} -safeExponentialDigits : Int -> number -> String - -{-| A string representing the provided number in fixed-point notation. -} -toFixed : number -> String - -{-| Either a string representing the second parameter in fixed-point notation, -with the requested number of digits after the decimal point (first parameter), -or an error. An error should not occur if the requested number of digits is -between 0 and 20. - -Note that Firefox returns `Ok 0` rather than an `Error` for a negative number -of requested digits. --} -toFixedDigits : Int -> number -> Result String String - -{-| A string representing the second parameter in fixed-point notation, -with the requested number of digits after the decimal point (first parameter). -The number of digits will be limited to between 0 and 20. --} -safeFixedDigits : Int -> number -> String - -{-| Either a string representing the second parameter in fixed-point or -exponential notation, rounded to the requested number of significant digits -(first parameter), or an error. An error should not occur if the requested -number of digits is between 0 and 20. --} -toPrecisionDigits : Int -> number -> Result String String - -{-| A string representing the second parameter in fixed-point or exponential -notation, with the requested number of significant digits (first parameter). -The number of digits will be limited to between 1 and 20. --} -safePrecisionDigits : Int -> number -> String - -{-| Either a string representing the second parameter using the requested base -(first parameter), or an error. An error should not occur if the requested base -is between 2 and 36. --} -toStringUsingBase : Int -> number -> Result String String - -{-| A string representing the second parameter, using the requested base -(first parameter). The requested base will be limited to between 2 and 36. --} -safeStringUsingBase : Int -> number -> String - -``` - -***See also*** - -**`toLocaleString`** - -        -Not implemented for the moment, since localization requires some thought. - - ----------- - -### WebAPI.RegExp - -Generally speaking, regular expressions are handled by the -[`Regex` module](http://package.elm-lang.org/packages/elm-lang/core/2.1.0/Regex) -in elm-lang/core. - -TODO: Check if anything is missing. - -See [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp). - - ----------- - -### WebAPI.Screen - -See [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/API/Screen). - -```elm -module WebAPI.Screen where - -type alias Screen = - { availTop: Int - , availLeft: Int - , availHeight: Int - , availWidth: Int - , colorDepth: Int - , pixelDepth: Int - , height: Int - , width: Int - } - -{-| The browser's `window.screen` object. - -This is a `Task` because, in multi-monitor setups, the result depends on which -screen the browser window is in. So, it is not necessarily a constant. --} -screen : Task x Screen - -{-| A tuple of `(window.screenX, window.screenY)`. - -The first value is the horizontal distance, in CSS pixels, of the left border -of the user's browser from the left side of the screen. - -The second value is the vertical distance, in CSS pixels, of the top border of -the user's browser from the top edge of the screen. --} -screenXY : Task x (Int, Int) -``` - - ----------- - -### WebAPI.Storage - -See [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/API/Storage), -and the [WhatWG documentation](https://html.spec.whatwg.org/multipage/webstorage.html). - -There is a more sophisticated `Storage` module available at -[TheSeamau5/elm-storage](https://github.com/TheSeamau5/elm-storage). - -Note that we're essentially assuming that `window.localStorage` and -`window.sessionStorage` are, in fact, available. We could account for them -possibly not being available by using a `Maybe` type. - -```elm -module WebAPI.Storage where - -{- ----------------- - Roles for Strings - ----------------- -} - -{-| A key. -} -type alias Key = String - -{-| An old value. -} -type alias OldValue = String - -{-| A new value. -} -type alias NewValue = String - -{-| A value. -} -type alias Value = String - -{- ------------- - Storage Areas - ------------- -} - -{-| Represents the `localStorage` and `sessionStorage` areas. -} -type Storage - = Local - | Session - -{-| The browser's `localStorage` area. -} -local : Storage - -{-| The browser's `sessionStorage` area. -} -session : Storage - -{- ----- - Tasks - ----- -} - -{-| A task which, when executed, determines the number of items stored in the -storage area. --} -length : Storage -> Task x Int - -{-| A task which, when executed, determines the name of the key at the given -index (zero-based). --} -key : Storage -> Int -> Task x (Maybe Key) - -{-| A task which, when executed, gets the value at the given key. -} -get : Storage -> Key -> Task x (Maybe Value) - -{-| A task which, when executed, sets the value at the given key, or fails with -an error message. --} -set : Storage -> Key -> NewValue -> Task String () - -{-| A task which, when executed, removes the item with the given key. -} -remove : Storage -> Key -> Task x () - -{-| A task which, when executed, removes all items. -} -clear : Storage -> Task x () - -{- ------ - Events - ------ -} - -{-| A storage event. -} -type alias Event = - { area : Storage - , url : String - , change : Change - } - -{-| A change to a storage area. -} -type Change - = Add Key NewValue - | Remove Key OldValue - | Modify Key OldValue NewValue - | Clear - -{-| A signal of storage events. - -Note that a storage event is not fired within the same document that made a -storage change. Thus, you will only receive events for localStorage changes -that occur in a **separate** tab or window. - -This behaviour reflects how Javascript does things ... let me know if you'd -prefer to have *all* localStorage events go through this `Signal` -- it could -be arranged. - -At least in Safari, sessionStorage is even more restrictive than localStorage --- it is isolated per-tab, so you will only get events on sessionStorage if -using iframes. - -Note that this signal emits `Maybe Event` (rather than `Event`) because Elm -signals must have an initial value -- and there is no natural initial value for -an `Event` unless we wrap it in a `Maybe`. So, you'll often want to use -`Signal.filterMap` when you're integrating this into your own signal of -actions. --} -events : Signal (Maybe Event) -``` - - ----------- - -### WebAPI.String - -Generally speaking, strings are dealt with by the -[`String` module](http://package.elm-lang.org/packages/elm-lang/core/2.1.0/String) -in elm-lang/core. - -TODO: Check if anything is missing. - -See [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String). - - ----------- - -### WebAPI.Window - -See Mozilla documentation for the -[`Window` object](https://developer.mozilla.org/en-US/docs/Web/API/Window), -and for -[function properties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects#Function_properties). - -Since the browser's `window` object has so many facilities attached, I've typically split -them up into individual modules -- see below for the cross-references. - -TODO: Finish going through the `window` API. - -```elm -module WebAPI.Window where - -{-| The browser's `window.alert()` function. -} -alert : String -> Task x () - -{-| The browser's `window.confirm()` function. - -The task will succeed if the user confirms, and fail if the user cancels. --} -confirm : String -> Task () () - -{-| The browser's `window.prompt()` function. - -The first parameter is a message, and the second parameter is a default -response. - -The task will succeed with the user's response, or fail if the user cancels or -enters blank text. --} -prompt : String -> String -> Task () String -``` - -***See also*** - -**`cancelAnimationFrame`** - -        -Use [`WebAPI.AnimationFrame`](#webapianimationframe) - -**`decodeURI`** - -        -Not implemented, since you will generally want `decodeURIComponent` instead. - -**`decodeURIComponent`** - -        -Use `Http.uriDecode` from -[evancz/elm-http](http://package.elm-lang.org/packages/evancz/elm-http/latest). - -**`encodeURI`** - -        -Not implemented, since you will generally want `encodeURIComponent` instead. - -**`encodeURIComponent`** - -        -Use `Http.uriEncode` from -[evancz/elm-http](http://package.elm-lang.org/packages/evancz/elm-http/latest). - -**`eval`** - -        -Not implemented, since it is an abomination. - -**`history`** - -        -See [TheSeamau5/elm-history](http://package.elm-lang.org/packages/TheSeamau5/elm-history/latest) - -**`innerHeight`, `innerWidth`** - -        -See `Window.dimensions` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`isFinite`** - -        -Use `not Basics.isInfinite` from -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest) -(i.e. with the sense reversed). - -**`isNan`** - -        -Use `Basics.isNan` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`localStorage`** - -        -Use [`WebAPI.Storage.localStorage`](#webapistorage) - -**`location`** - -        -For a `Signal`-oriented approach to things you might do with `window.location`, see -[TheSeamau5/elm-history](http://package.elm-lang.org/packages/TheSeamau5/elm-history/latest). -For some additional `Task`-oriented approaches, see -[`WebAPI.Location`](#webapilocation). - -**`parseFloat`** - -        -Use `String.toFloat` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`parseInt`** - -        -Use `String.toInt` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -**`requestAnimationFrame`** - -        -Use [`WebAPI.AnimationFrame`](#webapianimationframe) - -**`setInterval`** - -        -Consider `Time.fps` (or its variants) from -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest), -or `AnimationFrame.frame` (or its variants) from -[jwmerrill/elm-animation-frame](http://package.elm-lang.org/packages/jwmerrill/elm-animation-frame/latest), -or its variants, or `Effects.tick` from -[evancz/elm-effects](http://package.elm-lang.org/packages/evancz/elm-effects/latest). - -**`setTimeout`** - -        -Use `Task.sleep` from -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest), -and then apply an `andThen` to do something after sleeping. - -**`scroll`, `scrollBy`, `scrollTo`, `scrollX`, `scrollY`** - -        -There are a few puzzles about how to best adapt these for Elm, so I'm not sure -a simplistic approach would be best -- a module that thought through scrolling -in an Elm context would probably be better. - -**`screen`** - -        -See [`WebAPI.Screen.screen`](#webapiscreen). - -**`screenX`, `screenY`** - -        -See [`WebAPI.Screen.screenXY`](#webapiscreen). - -**`sessionStorage`** - -        -See [`WebAPI.Storage.sessionStorage`](#webapistorage) - - diff --git a/src/vendor/elm-web-api/elm-package.json b/src/vendor/elm-web-api/elm-package.json deleted file mode 100644 index 5368efb..0000000 --- a/src/vendor/elm-web-api/elm-package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "version": "1.0.0", - "summary": "Expose Web APIs provided by the browser's Javascript runtime", - "repository": "https://github.com/rgrempel/elm-web-api.git", - "license": "BSD3", - "source-directories": [ - "src" - ], - "exposed-modules": [ - "WebAPI.AnimationFrame", - "WebAPI.Cookie", - "WebAPI.Document", - "WebAPI.Date", - "WebAPI.Location", - "WebAPI.Math", - "WebAPI.Number", - "WebAPI.Screen", - "WebAPI.Storage", - "WebAPI.Window" - ], - "native-modules": true, - "dependencies": { - "elm-lang/core": "2.0.0 <= v < 4.0.0" - }, - "elm-version": "0.15.0 <= v < 0.17.0" -} diff --git a/src/vendor/elm-web-api/examples/elm-package.json b/src/vendor/elm-web-api/examples/elm-package.json deleted file mode 100644 index 825c6bc..0000000 --- a/src/vendor/elm-web-api/examples/elm-package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "version": "1.0.0", - "summary": "Examples for the WebAPI module", - "repository": "https://github.com/rgrempel/elm-web-api.git", - "license": "BSD3", - "source-directories": [ - "src", - "../src" - ], - "exposed-modules": [], - "native-modules": true, - "dependencies": { - "elm-lang/core": "2.0.0 <= v < 4.0.0", - "evancz/elm-effects": "2.0.0 <= v < 3.0.0", - "evancz/elm-html": "4.0.1 <= v < 5.0.0", - "evancz/start-app": "2.0.1 <= v < 3.0.0" - }, - "elm-version": "0.15.0 <= v < 0.17.0" -} diff --git a/src/vendor/elm-web-api/examples/package.json b/src/vendor/elm-web-api/examples/package.json deleted file mode 100644 index d499401..0000000 --- a/src/vendor/elm-web-api/examples/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "elm-web-api", - "version": "1.0.0", - "description": "Tests for elm-web-api", - "main": "elm.js", - "dependencies": { - "elm": "^2.0.0" - }, - "devDependencies": {}, - "scripts": { - "test": "elm-make src/WindowExample.elm --output elm.html && open elm.html;", - "package": "elm-package install;" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/rgrempel/elm-web-api.git" - }, - "author": "Ryan Rempel ", - "license": "MIT", - "bugs": { - "url": "https://github.com/rgrempel/elm-web-api/issues" - }, - "homepage": "https://github.com/rgrempel/elm-web-api#readme" -} diff --git a/src/vendor/elm-web-api/examples/src/LocationExample.elm b/src/vendor/elm-web-api/examples/src/LocationExample.elm deleted file mode 100644 index 48aa740..0000000 --- a/src/vendor/elm-web-api/examples/src/LocationExample.elm +++ /dev/null @@ -1,78 +0,0 @@ -module LocationExample where - -import Effects exposing (Effects, Never) -import StartApp exposing (App) -import Task exposing (Task, toResult) -import Html exposing (Html, h4, div, text, button, input) -import Html.Attributes exposing (id) -import Html.Events exposing (onClick) -import Signal exposing (Signal, Address) - -import WebAPI.Location exposing (reload, Source(..)) - - -app : App Model -app = - StartApp.start - { init = init - , update = update - , view = view - , inputs = [] - } - - -main : Signal Html -main = app.html - - -port tasks : Signal (Task.Task Never ()) -port tasks = app.tasks - - -type alias Model = String - - -init : (Model, Effects Action) -init = ("Initial state", Effects.none) - - -type Action - = Reload Source - | HandleReload (Result String ()) - - -update : Action -> Model -> (Model, Effects Action) -update action model = - case action of - HandleReload result -> - ( "Reloaded (but if this stays, then that's an error)" - , Effects.none - ) - - Reload source -> - ( "About to reload" - , reload source |> - toResult |> - Task.map HandleReload |> - Effects.task - ) - - -view : Address Action -> Model -> Html -view address model = - div [] - [ button - [ id "reload-force-button" - , onClick address (Reload ForceServer) - ] - [ text "WebAPI.Location.reload ForceServer" ] - , button - [ id "reload-cache-button" - , onClick address (Reload AllowCache) - ] - [ text "WebAPI.Location.reload AllowCache" ] - , h4 [] [ text "Message" ] - , div [ id "message" ] [ text model ] - , input [ id "input" ] [] - ] - diff --git a/src/vendor/elm-web-api/examples/src/StorageExample.elm b/src/vendor/elm-web-api/examples/src/StorageExample.elm deleted file mode 100644 index 990e2e0..0000000 --- a/src/vendor/elm-web-api/examples/src/StorageExample.elm +++ /dev/null @@ -1,669 +0,0 @@ -module StorageExample where - -import Effects exposing (Effects, Never) -import StartApp exposing (App) -import Task exposing (Task, toResult) -import Html exposing (Html, h4, div, text, button, input, select, option, label, table, tr, td) -import Html.Attributes exposing (id, style, value, type', selected, for, colspan) -import Html.Events exposing (onClick, on, targetValue) -import Signal exposing (Signal, Address) -import String - -import WebAPI.Storage as Storage exposing (Storage) - - -{-| StartApp stuff. -} -app : App Model -app = - StartApp.start - { init = init - , update = update - , view = view - , inputs = [ events ] - } - - -main : Signal Html -main = app.html - - -port tasks : Signal (Task.Task Never ()) -port tasks = app.tasks - - -{-| Our model is: - -* a list of things that have happened (that we want to remember) -* an action which we're currently editing in the UI and might "send" at some point -* the last operation of each type which we've edited, so we can remember parameters - as we switch operation types in the UI --} -type alias Model = - { log : List Log - , action : StorageAction - , lastOperation : LastOperation - } - - -{-| We log: - -* actions that we send to the storage objects -* the responses we get -* events received from other open windows, tabs, etc. --} -type Log - = LogAction StorageAction - | LogResponse StorageResponse - | LogEvent Storage.Event - - - -{-| Our initial model. -} -init : (Model, Effects Action) -init = - ( { log = [] - , action = - { target = Storage.local - , operation = DoLength - } - , lastOperation = - { key = DoKey 0 - , get = DoGet "" - , set = DoSet "" "" - , remove = DoRemove "" - } - } - , Effects.none - ) - - -{-| I've modularized the Action type, even though it's all in one file. -} -type Action - = SetAction SetAction - | DoStorageAction StorageAction - | StorageResponse StorageResponse - | StorageEvent Storage.Event - | NoOp - - -{-| Signal of events from other windows or tabs. -} -events : Signal Action -events = Signal.filterMap (Maybe.map StorageEvent) NoOp Storage.events - - -{-| We dispatch to more specific functions ... often they would be in separate -files, but I've put them all here. --} -update : Action -> Model -> (Model, Effects Action) -update action model = - case action of - SetAction subaction -> - ( updateSetAction subaction model - , Effects.none - ) - - DoStorageAction subaction -> - updateStorageAction subaction model - - StorageResponse subaction -> - updateStorageResponse subaction model - - StorageEvent subaction -> - updateStorageEvent subaction model - - NoOp -> - (model, Effects.none) - - -{-| These are actions from the UI ... thus, the strings. In principle, I could -use Json.Decode in the UI to supply typed data, but this works too. --} -type SetAction - = SetStorage String - | SetOperationType String - | SetKeyIndex String - | SetGetKey String - | SetSetKey String - | SetSetValue String - | SetRemoveKey String - - -{-| An action to send to a storage object. We edit this in the UI, and we -eventually send it in `Task` form. --} -type alias StorageAction = - { target : Storage - , operation : StorageOperation - } - - -{-| An operation to perform on a storage object. -} -type StorageOperation - = DoLength - | DoKey Int - | DoGet Storage.Key - | DoSet Storage.Key Storage.NewValue - | DoRemove Storage.Key - | DoClear - - -{-| Actually perform the StorageAction, and log it. -} -updateStorageAction : StorageAction -> Model -> (Model, Effects Action) -updateStorageAction action model = - ( { model | log = LogAction action :: model.log } - , Effects.task (Task.map StorageResponse (storageAction2task action)) - ) - - -{- When we get a response, we just log it. -} -updateStorageResponse : StorageResponse -> Model -> (Model, Effects Action) -updateStorageResponse action model = - ( { model | log = LogResponse action :: model.log } - , Effects.none - ) - - -{- As with an event. -} -updateStorageEvent : Storage.Event -> Model -> (Model, Effects Action) -updateStorageEvent action model = - ( { model | log = LogEvent action :: model.log } - , Effects.none - ) - - -{-| We want to remember the parameters for the last operation we edited -of a given type, so that as we switch operation types the parameters can -be filled in. --} -type alias LastOperation = - { key : StorageOperation - , get : StorageOperation - , set : StorageOperation - , remove : StorageOperation - } - - -{-| This is for actions coming from the UI. -} -updateSetAction : SetAction -> Model -> Model -updateSetAction action model = - let - currentAction = - model.action - - lastOperation = - model.lastOperation - - in - case action of - SetStorage string -> - let - storage = - if string == phrases.localStorage - then Storage.local - - else if string == phrases.sessionStorage - then Storage.session - - else - currentAction.target - - newAction = - { currentAction | target = storage } - - in - { model | action = newAction } - - SetOperationType string -> - let - operation = - if string == phrases.length - then DoLength - - else if string == phrases.key - then - if doingKey currentAction.operation - then currentAction.operation - else lastOperation.key - - else if string == phrases.get - then - if doingGet currentAction.operation - then currentAction.operation - else lastOperation.get - - else if string == phrases.set - then - if doingSet currentAction.operation - then currentAction.operation - else lastOperation.set - - else if string == phrases.remove - then - if doingRemove currentAction.operation - then currentAction.operation - else lastOperation.remove - - else if string == phrases.clear - then - DoClear - - else - currentAction.operation - - newAction = - { currentAction | operation = operation } - - in - { model | action = newAction } - - SetKeyIndex string -> - let - operation = - case String.toInt string of - Ok int -> - DoKey int - - Err _ -> - lastOperation.key - - newAction = - { currentAction | operation = operation } - - newLastOperation = - { lastOperation | key = operation } - - in - { model - | action = newAction - , lastOperation = newLastOperation - } - - SetGetKey string -> - let - operation = - DoGet string - - newAction = - { currentAction | operation = operation } - - newLastOperation = - { lastOperation | get = operation } - - in - { model - | action = newAction - , lastOperation = newLastOperation - } - - SetRemoveKey string -> - let - operation = - DoRemove string - - newAction = - { currentAction | operation = operation } - - newLastOperation = - { lastOperation | remove = operation } - - in - { model - | action = newAction - , lastOperation = newLastOperation - } - - SetSetKey string -> - let - operation = - case currentAction.operation of - DoSet key value -> - DoSet string value - - _ -> - DoSet string "" - - newAction = - { currentAction | operation = operation } - - newLastOperation = - { lastOperation | set = operation } - - in - { model - | action = newAction - , lastOperation = newLastOperation - } - - SetSetValue string -> - let - operation = - case currentAction.operation of - DoSet key value -> - DoSet key string - - _ -> - DoSet "" string - - newAction = - { currentAction | operation = operation } - - newLastOperation = - { lastOperation | set = operation } - - in - { model - | action = newAction - , lastOperation = newLastOperation - } - - -{-| A bunch of little convenience functions so that I don't have to write out -the pattern matches too often. --} -doingLength : StorageOperation -> Bool -doingLength op = - case op of - DoLength -> True - _ -> False - - -doingKey : StorageOperation -> Bool -doingKey op = - case op of - DoKey _ -> True - _ -> False - - -doingGet : StorageOperation -> Bool -doingGet op = - case op of - DoGet _ -> True - _ -> False - - -doingSet : StorageOperation -> Bool -doingSet op = - case op of - DoSet _ _ -> True - _ -> False - - -doingRemove : StorageOperation -> Bool -doingRemove op = - case op of - DoRemove _ -> True - _ -> False - - -doingClear : StorageOperation -> Bool -doingClear op = - case op of - DoClear -> True - _ -> False - - -{- An Action type that wraps the various responses possible from -the storage tasks. --} -type StorageResponse - = HandleLength Int - | HandleKey (Maybe Storage.Key) - | HandleGet (Maybe Storage.Value) - | HandleSet (Result String ()) - | HandleRemove () - | HandleClear () - - -{-| A convenience function that takes a `StorageAction` and turns it into -a task that provides a `StorageResopnse`. --} -storageAction2task : StorageAction -> Task x StorageResponse -storageAction2task action = - case action.operation of - DoLength -> - Task.map HandleLength <| - Storage.length action.target - - DoKey int -> - Task.map HandleKey <| - Storage.key action.target int - - DoGet key -> - Task.map HandleGet <| - Storage.get action.target key - - DoSet key value -> - Task.map HandleSet <| - Task.toResult <| - Storage.set action.target key value - - DoRemove key -> - Task.map HandleRemove <| - Storage.remove action.target key - - DoClear -> - Task.map HandleClear <| - Storage.clear action.target - - -{-| It's always nice to keep the actual text of the UI in one place. It also -helps for matching the and etc. so that you can edit the -StorageAction. Also, there is a button to actually perform the action. --} -editStorageAction : Address Action -> StorageAction -> Html -editStorageAction address model = - let - notify func = - Signal.message (Signal.forwardTo address SetAction) << func - - makeCell = - td - [ style - [ ("border", "1px dotted black") - , ("padding", "3px") - ] - ] - - makeLabel id string = - td - [ style - [ ("text-align", "right") - , ("border", "1px dotted black") - , ("padding", "3px") - ] - ] - [ label - [ for id ] - [ text string ] - ] - - objectSelector = - tr [] - [ makeLabel "select-area" phrases.localOrSession - , makeCell - [ select - [ id "select-area" - , on "change" targetValue (notify SetStorage) - ] - [ option - [ selected (model.target == Storage.local) ] - [ text phrases.localStorage ] - , option - [ selected (model.target == Storage.session) ] - [ text phrases.sessionStorage ] - ] - ] - ] - - operationSelector = - tr [] - [ makeLabel "select-operation" phrases.operation - , makeCell - [ select - [ id "select-operation" - , on "change" targetValue (notify SetOperationType) - ] - [ option - [ selected (doingLength model.operation) ] - [ text phrases.length ] - , option - [ selected (doingKey model.operation) ] - [ text phrases.key ] - , option - [ selected (doingGet model.operation) ] - [ text phrases.get ] - , option - [ selected (doingSet model.operation) ] - [ text phrases.set ] - , option - [ selected (doingRemove model.operation) ] - [ text phrases.remove ] - , option - [ selected (doingClear model.operation) ] - [ text phrases.clear ] - ] - ] - ] - - parameters = - case model.operation of - -- Nothing needed for DoLength - DoLength -> - [] - - DoKey index -> - [ tr [] - [ makeLabel "select-index" phrases.indexLabel - , makeCell - [ input - [ type' "number" - , id "select-index" - , value (toString index) - , on "input" targetValue (notify SetKeyIndex) - ] [] - ] - ] - ] - - DoGet key -> - [ tr [] - [ makeLabel "select-get-key" phrases.keyLabel - , makeCell - [ input - [ value key - , id "select-get-key" - , on "input" targetValue (notify SetGetKey) - ] [] - ] - ] - ] - - DoSet key val -> - [ tr [] - [ makeLabel "select-set-key" phrases.keyLabel - , makeCell - [ input - [ value key - , id "select-set-key" - , on "input" targetValue (notify SetSetKey) - ] [] - ] - ] - , tr [] - [ makeLabel "select-set-value" phrases.valueLabel - , makeCell - [ input - [ value val - , id "select-set-value" - , on "input" targetValue (notify SetSetValue) - ] [] - ] - ] - ] - - DoRemove key -> - [ tr [] - [ makeLabel "select-remove-key" phrases.keyLabel - , makeCell - [ input - [ value key - , id "select-remove-key" - , on "input" targetValue (notify SetRemoveKey) - ] [] - ] - ] - ] - - DoClear -> - [] - - performAction = - tr [] - [ td - [ colspan 2 - , style - [ ("text-align", "center") - , ("border", "1px dotted black") - , ("padding", "3px") - ] - ] - [ button - [ id "perform-action" - , onClick address (DoStorageAction model) - ] - [ text phrases.performAction ] - ] - ] - - in - table [] <| - [ objectSelector - , operationSelector - ] - ++ - parameters - ++ - [ performAction - ] - - -viewLog : Log -> Html -viewLog log = - div - [ style [( "margin-top", "6pt")] ] - [ text <| toString log ] - - -view : Address Action -> Model -> Html -view address model = - div - [ style [ ("padding", "8px") ] - ] - [ editStorageAction address model.action - - , h4 [] [ text "Log (most recent first)" ] - , div - [ id "log" ] <| - List.map viewLog model.log - ] diff --git a/src/vendor/elm-web-api/examples/src/WindowExample.elm b/src/vendor/elm-web-api/examples/src/WindowExample.elm deleted file mode 100644 index c0dc2cb..0000000 --- a/src/vendor/elm-web-api/examples/src/WindowExample.elm +++ /dev/null @@ -1,123 +0,0 @@ -module WindowExample where - -import Effects exposing (Effects, Never) -import StartApp exposing (App) -import Task exposing (Task, toResult) -import Html exposing (Html, h4, div, text, button) -import Html.Attributes exposing (id) -import Html.Events exposing (onClick) -import Signal exposing (Signal, Address) - -import WebAPI.Window exposing (alert, confirm, prompt) - - -app : App Model -app = - StartApp.start - { init = init - , update = update - , view = view - , inputs = [] - } - - -main : Signal Html -main = app.html - - -port tasks : Signal (Task.Task Never ()) -port tasks = app.tasks - - -type alias Model = String - - -init : (Model, Effects Action) -init = ("", Effects.none) - - -type Action - = ShowAlert String - | HandleAlertResponse - | ShowConfirm String - | HandleConfirmResponse (Result () ()) - | ShowPrompt String String - | HandlePromptResponse (Result () String) - - -update : Action -> Model -> (Model, Effects Action) -update action model = - case action of - ShowAlert message -> - ( model - , alert message |> - Task.map (always HandleAlertResponse) |> - Effects.task - ) - - HandleAlertResponse -> - ( "Got alert response" - , Effects.none - ) - - ShowConfirm message -> - ( model - , confirm message |> - toResult |> - Task.map HandleConfirmResponse |> - Effects.task - ) - - HandleConfirmResponse result -> - ( case result of - Ok _ -> - "Pressed OK" - - Err _ -> - "Pressed cancel" - - , Effects.none - ) - - ShowPrompt message default -> - ( model - , prompt message default |> - toResult |> - Task.map HandlePromptResponse |> - Effects.task - ) - - HandlePromptResponse result -> - ( case result of - Ok response -> - "Got response: " ++ response - - Err _ -> - "User canceled." - - , Effects.none - ) - - -view : Address Action -> Model -> Html -view address model = - div [] - [ button - [ onClick address (ShowAlert "Hello world!") - , id "alert-button" - ] - [ text "WebAPI.Window.alert" ] - , button - [ onClick address (ShowConfirm "Do you agree?") - , id "confirm-button" - ] - [ text "WebAPI.Window.confirm" ] - , button - [ onClick address (ShowPrompt "What is your favourite colour?" "Blue") - , id "prompt-button" - ] - [ text "WebAPI.Window.prompt" ] - , h4 [] [ text "Message" ] - , div [ id "message" ] [ text model ] - ] - diff --git a/src/vendor/elm-web-api/src/Native/WebAPI/AnimationFrame.js b/src/vendor/elm-web-api/src/Native/WebAPI/AnimationFrame.js deleted file mode 100644 index dd6d006..0000000 --- a/src/vendor/elm-web-api/src/Native/WebAPI/AnimationFrame.js +++ /dev/null @@ -1,79 +0,0 @@ -Elm.Native = Elm.Native || {}; -Elm.Native.WebAPI = Elm.Native.WebAPI || {}; -Elm.Native.WebAPI.AnimationFrame = Elm.Native.WebAPI.AnimationFrame || {}; - -// http://paulirish.com/2011/requestanimationframe-for-smart-animating/ -// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating - -// requestAnimationFrame polyfill by Erik Möller -// fixes from Paul Irish and Tino Zijdel -// list-based fallback implementation by Jonas Finnemann Jensen - -var raf = window.requestAnimationFrame; -var caf = window.cancelAnimationFrame; - -if (!raf) { - var tid = null, cbs = [], nb = 0, ts = 0; - - function animate () { - var i, clist = cbs, len = cbs.length; - tid = null; - ts = Date.now(); - cbs = []; - nb += clist.length; - - for (i = 0; i < len; i++) { - if (clist[i]) clist[i](ts); - } - } - - raf = function (cb) { - if (tid == null) { - tid = setTimeout(animate, Math.max(0, 20 + ts - Date.now())); - } - - return cbs.push(cb) + nb; - }; - - caf = function (id) { - delete cbs[id - nb - 1]; - }; -} - -Elm.Native.WebAPI.AnimationFrame.make = function (localRuntime) { - localRuntime.Native = localRuntime.Native || {}; - localRuntime.Native.WebAPI = localRuntime.Native.WebAPI || {}; - localRuntime.Native.WebAPI.AnimationFrame = localRuntime.Native.WebAPI.AnimationFrame || {}; - - if (!localRuntime.Native.WebAPI.AnimationFrame.values) { - var Task = Elm.Native.Task.make(localRuntime); - var Utils = Elm.Native.Utils.make(localRuntime); - - localRuntime.Native.WebAPI.AnimationFrame.values = { - task: Task.asyncFunction(function (callback) { - raf(function (time) { - callback(Task.succeed(time)); - }); - }), - - request: function (taskProducer) { - return Task.asyncFunction(function (callback) { - var request = raf(function (time) { - Task.perform(taskProducer(time)); - }); - - callback(Task.succeed(request)); - }); - }, - - cancel: function (request) { - return Task.asyncFunction(function (callback) { - caf(request); - callback(Task.succeed(Utils.Tuple0)); - }); - } - }; - } - - return localRuntime.Native.WebAPI.AnimationFrame.values; -}; diff --git a/src/vendor/elm-web-api/src/Native/WebAPI/Cookie.js b/src/vendor/elm-web-api/src/Native/WebAPI/Cookie.js deleted file mode 100644 index c7ff078..0000000 --- a/src/vendor/elm-web-api/src/Native/WebAPI/Cookie.js +++ /dev/null @@ -1,41 +0,0 @@ -Elm.Native = Elm.Native || {}; -Elm.Native.WebAPI = Elm.Native.WebAPI || {}; -Elm.Native.WebAPI.Cookie = Elm.Native.WebAPI.Cookie || {}; - -Elm.Native.WebAPI.Cookie.make = function (localRuntime) { - localRuntime.Native = localRuntime.Native || {}; - localRuntime.Native.WebAPI = localRuntime.Native.WebAPI || {}; - localRuntime.Native.WebAPI.Cookie = localRuntime.Native.WebAPI.Cookie || {}; - - if (!localRuntime.Native.WebAPI.Cookie.values) { - var Task = Elm.Native.Task.make(localRuntime); - var Utils = Elm.Native.Utils.make(localRuntime); - - localRuntime.Native.WebAPI.Cookie.values = { - getString: Task.asyncFunction(function (callback) { - callback(Task.succeed(document.cookie)); - }), - - setString: function (cookie) { - return Task.asyncFunction(function (callback) { - document.cookie = cookie; - callback(Task.succeed(Utils.Tuple0)); - }); - }, - - dateToUTCString: function (date) { - return date.toUTCString(); - }, - - uriEncode: function (string) { - return encodeURIComponent(string); - }, - - uriDecode: function (string) { - return decodeURIComponent(string); - } - }; - } - - return localRuntime.Native.WebAPI.Cookie.values; -}; diff --git a/src/vendor/elm-web-api/src/Native/WebAPI/Date.js b/src/vendor/elm-web-api/src/Native/WebAPI/Date.js deleted file mode 100644 index 7196e1f..0000000 --- a/src/vendor/elm-web-api/src/Native/WebAPI/Date.js +++ /dev/null @@ -1,148 +0,0 @@ -Elm.Native = Elm.Native || {}; -Elm.Native.WebAPI = Elm.Native.WebAPI || {}; -Elm.Native.WebAPI.Date = Elm.Native.WebAPI.Date || {}; - -Elm.Native.WebAPI.Date.make = function (localRuntime) { - localRuntime.Native = localRuntime.Native || {}; - localRuntime.Native.WebAPI = localRuntime.Native.WebAPI || {}; - localRuntime.Native.WebAPI.Date = localRuntime.Native.WebAPI.Date || {}; - - if (!localRuntime.Native.WebAPI.Date.values) { - var Task = Elm.Native.Task.make(localRuntime); - var Utils = Elm.Native.Utils.make(localRuntime); - - localRuntime.Native.WebAPI.Date.values = { - current : Task.asyncFunction(function (callback) { - callback( - Task.succeed( - new Date () - ) - ); - }), - - now : Task.asyncFunction(function (callback) { - callback( - Task.succeed( - Date.now() - ) - ); - }), - - fromPartsLocal : function (parts) { - return new Date( - parts.year, - parts.month, - parts.day, - parts.hour, - parts.minute, - parts.second, - parts.millisecond - ); - }, - - fromPartsUtc : function (parts) { - return new Date( - Date.UTC( - parts.year, - parts.month, - parts.day, - parts.hour, - parts.minute, - parts.second, - parts.millisecond - ) - ); - }, - - toPartsLocal : function (date) { - return { - year: date.getFullYear(), - month: date.getMonth(), - day: date.getDate(), - hour: date.getHours(), - minute: date.getMinutes(), - second: date.getSeconds(), - millisecond: date.getMilliseconds() - }; - }, - - toPartsUtc : function (date) { - return { - year: date.getUTCFullYear(), - month: date.getUTCMonth(), - day: date.getUTCDate(), - hour: date.getUTCHours(), - minute: date.getUTCMinutes(), - second: date.getUTCSeconds(), - millisecond: date.getUTCMilliseconds() - }; - }, - - timezoneOffsetInMinutes : function (date) { - return date.getTimezoneOffset(); - }, - - dayOfWeekUTC : function (date) { - return date.getUTCDay(); - }, - - offsetYearLocal : F2(function (offset, date) { - var copy = new Date(date); - copy.setFullYear(date.getFullYear() + offset); - - // For some reason, Firefox loses the milliseconds otherwise - copy.setMilliseconds(date.getMilliseconds()); - - return copy; - }), - - offsetYearUTC : F2(function (offset, date) { - var copy = new Date(date); - copy.setUTCFullYear(date.getUTCFullYear() + offset); - - // For some reason, Firefox loses the milliseconds otherwise - copy.setUTCMilliseconds(date.getUTCMilliseconds()); - - return copy; - }), - - offsetMonthLocal : F2(function (offset, date) { - var copy = new Date(date); - copy.setMonth(date.getMonth() + offset); - - // For some reason, Firefox loses the milliseconds otherwise - copy.setMilliseconds(date.getMilliseconds()); - - return copy; - }), - - offsetMonthUTC : F2(function (offset, date) { - var copy = new Date(date); - copy.setUTCMonth(date.getUTCMonth() + offset); - - // For some reason, Firefox loses the milliseconds otherwise - copy.setUTCMilliseconds(date.getUTCMilliseconds()); - - return copy; - }), - - dateString : function (date) { - return date.toDateString(); - }, - - timeString : function (date) { - return date.toTimeString(); - }, - - isoString : function (date) { - return date.toISOString(); - }, - - utcString : function (date) { - return date.toUTCString(); - } - }; - } - - return localRuntime.Native.WebAPI.Date.values; -}; diff --git a/src/vendor/elm-web-api/src/Native/WebAPI/Document.js b/src/vendor/elm-web-api/src/Native/WebAPI/Document.js deleted file mode 100644 index 8ce0c11..0000000 --- a/src/vendor/elm-web-api/src/Native/WebAPI/Document.js +++ /dev/null @@ -1,58 +0,0 @@ -Elm.Native = Elm.Native || {}; -Elm.Native.WebAPI = Elm.Native.WebAPI || {}; -Elm.Native.WebAPI.Document = Elm.Native.WebAPI.Document || {}; - -Elm.Native.WebAPI.Document.make = function (localRuntime) { - localRuntime.Native = localRuntime.Native || {}; - localRuntime.Native.WebAPI = localRuntime.Native.WebAPI || {}; - localRuntime.Native.WebAPI.Document = localRuntime.Native.WebAPI.Document || {}; - - if (!localRuntime.Native.WebAPI.Document.values) { - var Task = Elm.Native.Task.make(localRuntime); - var NS = Elm.Native.Signal.make(localRuntime); - var Utils = Elm.Native.Utils.make(localRuntime); - - var getState = function () { - switch (document.readyState) { - case "loading": - return {ctor: "Loading"}; - - case "interactive": - return {ctor: "Interactive"}; - - case "complete": - return {ctor: "Complete"}; - - default: - throw "Got unrecognized document.readyState: " + document.readyState; - } - }; - - var readyState = NS.input('WebAPI.Document.readyState', getState()); - - localRuntime.addListener([readyState.id], document, 'readystatechange', function () { - localRuntime.notify(readyState.id, getState()); - }); - - localRuntime.Native.WebAPI.Document.values = { - readyState: readyState, - - getReadyState: Task.asyncFunction(function (callback) { - callback(Task.succeed(getState())); - }), - - getTitle : Task.asyncFunction(function (callback) { - callback(Task.succeed(document.title)); - }), - - setTitle : function (title) { - return Task.asyncFunction(function (cb) { - document.title = title; - cb(Task.succeed(Utils.Tuple0)); - }); - } - }; - } - - return localRuntime.Native.WebAPI.Document.values; -}; diff --git a/src/vendor/elm-web-api/src/Native/WebAPI/Location.js b/src/vendor/elm-web-api/src/Native/WebAPI/Location.js deleted file mode 100644 index ba2f684..0000000 --- a/src/vendor/elm-web-api/src/Native/WebAPI/Location.js +++ /dev/null @@ -1,63 +0,0 @@ -Elm.Native = Elm.Native || {}; -Elm.Native.WebAPI = Elm.Native.WebAPI || {}; -Elm.Native.WebAPI.Location = Elm.Native.WebAPI.Location || {}; - -Elm.Native.WebAPI.Location.make = function (localRuntime) { - localRuntime.Native = localRuntime.Native || {}; - localRuntime.Native.WebAPI = localRuntime.Native.WebAPI || {}; - localRuntime.Native.WebAPI.Location = localRuntime.Native.WebAPI.Location || {}; - - if (!localRuntime.Native.WebAPI.Location.values) { - var Task = Elm.Native.Task.make(localRuntime); - var Utils = Elm.Native.Utils.make(localRuntime); - - // In core before 3.0.0 - var copy = Utils.copy; - - if (!copy) { - // In core from 3.0.0 - copy = function (value) { - return Utils.update(value, {}); - }; - } - - localRuntime.Native.WebAPI.Location.values = { - location: Task.asyncFunction(function (callback) { - var location = copy(window.location); - - // Deal with Elm reserved word - location["port$"] = location.port; - - // Polyfill for IE - if (!location.origin) { - location.origin = - location.protocol + "//" + - location.hostname + - (location.port ? ':' + location.port: ''); - } - - callback(Task.succeed(location)); - }), - - reload: function (forceServer) { - return Task.asyncFunction(function (callback) { - window.location.reload(forceServer); - - // Now, I suppose this won't really accomplish anything, - // but let's do it anyway. - try { - callback( - Task.succeed(Utils.Tuple0) - ); - } catch (ex) { - callback( - Task.fail(ex.message) - ); - } - }); - } - }; - } - - return localRuntime.Native.WebAPI.Location.values; -}; diff --git a/src/vendor/elm-web-api/src/Native/WebAPI/Math.js b/src/vendor/elm-web-api/src/Native/WebAPI/Math.js deleted file mode 100644 index 68c3f64..0000000 --- a/src/vendor/elm-web-api/src/Native/WebAPI/Math.js +++ /dev/null @@ -1,30 +0,0 @@ -Elm.Native = Elm.Native || {}; -Elm.Native.WebAPI = Elm.Native.WebAPI || {}; -Elm.Native.WebAPI.Math = Elm.Native.WebAPI.Math || {}; - -Elm.Native.WebAPI.Math.make = function (localRuntime) { - localRuntime.Native = localRuntime.Native || {}; - localRuntime.Native.WebAPI = localRuntime.Native.WebAPI || {}; - localRuntime.Native.WebAPI.Math = localRuntime.Native.WebAPI.Math || {}; - - if (!localRuntime.Native.WebAPI.Math.values) { - var Task = Elm.Native.Task.make(localRuntime); - - localRuntime.Native.WebAPI.Math.values = { - ln2: Math.LN2, - ln10: Math.LN10, - log2e: Math.LOG2E, - log10e: Math.LOG10E, - sqrt1_2: Math.SQRT1_2, - sqrt2: Math.SQRT2, - exp: Math.exp, - log: Math.log, - - random: Task.asyncFunction(function (callback) { - callback(Task.succeed(Math.random())); - }) - }; - } - - return localRuntime.Native.WebAPI.Math.values; -}; diff --git a/src/vendor/elm-web-api/src/Native/WebAPI/Number.js b/src/vendor/elm-web-api/src/Native/WebAPI/Number.js deleted file mode 100644 index 3b85d98..0000000 --- a/src/vendor/elm-web-api/src/Native/WebAPI/Number.js +++ /dev/null @@ -1,71 +0,0 @@ -Elm.Native = Elm.Native || {}; -Elm.Native.WebAPI = Elm.Native.WebAPI || {}; -Elm.Native.WebAPI.Number = Elm.Native.WebAPI.Number || {}; - -Elm.Native.WebAPI.Number.make = function (localRuntime) { - localRuntime.Native = localRuntime.Native || {}; - localRuntime.Native.WebAPI = localRuntime.Native.WebAPI || {}; - localRuntime.Native.WebAPI.Number = localRuntime.Native.WebAPI.Number || {}; - - if (!localRuntime.Native.WebAPI.Number.values) { - var Result = Elm.Result.make(localRuntime); - - var toExponential = function (number) { - // No try/catch needed because cannot throw exception - return number.toExponential(); - }; - - var toExponentialDigits = function (digits, number) { - try { - return Result.Ok(number.toExponential(digits)); - } catch (ex) { - return Result.Err(ex.message); - } - }; - - var toFixed = function (number) { - // No try/catch needed because cannot throw exception - return number.toFixed(); - }; - - var toFixedDigits = function (digits, number) { - try { - return Result.Ok(number.toFixed(digits)); - } catch (ex) { - return Result.Err(ex.message); - } - }; - - var toPrecisionDigits = function (digits, number) { - try { - return Result.Ok(number.toPrecision(digits)); - } catch (ex) { - return Result.Err(ex.message); - } - }; - - var toStringUsingBase = function (base, number) { - try { - return Result.Ok(number.toString(base)); - } catch (ex) { - return Result.Err(ex.message); - } - }; - - localRuntime.Native.WebAPI.Number.values = { - maxValue: Number.MAX_VALUE, - minValue: Number.MIN_VALUE, - nan: Number.NaN, - negativeInfinity: Number.NEGATIVE_INFINITY, - positiveInfinity: Number.POSITIVE_INFINITY, - toExponential: toExponential, - toExponentialDigits: F2(toExponentialDigits), - toFixed: toFixed, - toFixedDigits: F2(toFixedDigits), - toPrecisionDigits: F2(toPrecisionDigits), - toStringUsingBase: F2(toStringUsingBase) - }; - } - - return localRuntime.Native.WebAPI.Number.values; -}; diff --git a/src/vendor/elm-web-api/src/Native/WebAPI/Screen.js b/src/vendor/elm-web-api/src/Native/WebAPI/Screen.js deleted file mode 100644 index a27562d..0000000 --- a/src/vendor/elm-web-api/src/Native/WebAPI/Screen.js +++ /dev/null @@ -1,51 +0,0 @@ -Elm.Native = Elm.Native || {}; -Elm.Native.WebAPI = Elm.Native.WebAPI || {}; -Elm.Native.WebAPI.Screen = Elm.Native.WebAPI.Screen || {}; - -Elm.Native.WebAPI.Screen.make = function (localRuntime) { - localRuntime.Native = localRuntime.Native || {}; - localRuntime.Native.WebAPI = localRuntime.Native.WebAPI || {}; - localRuntime.Native.WebAPI.Screen = localRuntime.Native.WebAPI.Screen || {}; - - if (!localRuntime.Native.WebAPI.Screen.values) { - var Task = Elm.Native.Task.make(localRuntime); - var Utils = Elm.Native.Utils.make(localRuntime); - - var copy; - if (Utils.copy) { - // In core before 3.0.0 - copy = Utils.copy; - } else { - // In core from 3.0.0 - copy = function (value) { - return Utils.update(value, {}); - }; - } - - localRuntime.Native.WebAPI.Screen.values = { - // Note that this is a Task because in a multi-monitor setup, the - // result depends on which monitor the browser window is being - // displayed on. So, it's not a constant. - // - // That's also why we copy the screen object ... otherwise, it - // would be *live* reference to the screen, and thus, not constant. - screen: Task.asyncFunction(function (callback) { - callback( - Task.succeed( - copy(window.screen) - ) - ); - }), - - screenXY: Task.asyncFunction(function (callback) { - callback( - Task.succeed( - Utils.Tuple2(window.screenX, window.screenY) - ) - ); - }) - }; - } - - return localRuntime.Native.WebAPI.Screen.values; -}; diff --git a/src/vendor/elm-web-api/src/Native/WebAPI/Storage.js b/src/vendor/elm-web-api/src/Native/WebAPI/Storage.js deleted file mode 100644 index f08829b..0000000 --- a/src/vendor/elm-web-api/src/Native/WebAPI/Storage.js +++ /dev/null @@ -1,109 +0,0 @@ -Elm.Native = Elm.Native || {}; -Elm.Native.WebAPI = Elm.Native.WebAPI || {}; -Elm.Native.WebAPI.Storage = Elm.Native.WebAPI.Storage || {}; - -Elm.Native.WebAPI.Storage.make = function (localRuntime) { - localRuntime.Native = localRuntime.Native || {}; - localRuntime.Native.WebAPI = localRuntime.Native.WebAPI || {}; - localRuntime.Native.WebAPI.Storage = localRuntime.Native.WebAPI.Storage || {}; - - if (!localRuntime.Native.WebAPI.Storage.values) { - var Task = Elm.Native.Task.make(localRuntime); - var Maybe = Elm.Maybe.make(localRuntime); - var NS = Elm.Native.Signal.make(localRuntime); - var Utils = Elm.Native.Utils.make(localRuntime); - - var toMaybe = function (obj) { - return obj == null ? Maybe.Nothing : Maybe.Just(obj); - }; - - var length = function (storage) { - return Task.asyncFunction(function (callback) { - callback(Task.succeed(storage.length)); - }); - }; - - var key = function (storage, k) { - return Task.asyncFunction(function (callback) { - var result = null; - - // This check needed to avoid a problem in IE9 - if (k >= 0 && k < storage.length) { - result = storage.key(k); - } - - callback( - Task.succeed( - toMaybe(result) - ) - ); - }); - }; - - var getItem = function (storage, k) { - return Task.asyncFunction(function (callback) { - var result = storage.getItem(k); - callback( - Task.succeed( - toMaybe(result) - ) - ); - }); - }; - - var setItem = function (storage, k, v) { - return Task.asyncFunction(function (callback) { - try { - storage.setItem(k, v); - callback(Task.succeed(Utils.Tuple0)); - } catch (ex) { - callback(Task.fail(ex.message)); - } - }); - }; - - var removeItem = function (storage, k) { - return Task.asyncFunction(function (callback) { - storage.removeItem(k); - callback(Task.succeed(Utils.Tuple0)); - }); - }; - - var clear = function (storage) { - return Task.asyncFunction(function (callback) { - storage.clear(); - callback(Task.succeed(Utils.Tuple0)); - }); - }; - - var events = NS.input('WebAPI.Storage.nativeEvents', Maybe.Nothing); - - localRuntime.addListener([events.id], window, "storage", function (event) { - var e = { - key: toMaybe(event.key), - oldValue: toMaybe(event.oldValue), - newValue: toMaybe(event.newValue), - url : event.url, - storageArea: event.storageArea - }; - - localRuntime.notify(events.id, toMaybe(e)); - }); - - localRuntime.Native.WebAPI.Storage.values = { - localStorage: window.localStorage, - sessionStorage: window.sessionStorage, - - length: length, - key: F2(key), - getItem: F2(getItem), - setItem: F3(setItem), - removeItem: F2(removeItem), - clear: clear, - - nativeEvents: events - }; - } - - return localRuntime.Native.WebAPI.Storage.values; -}; diff --git a/src/vendor/elm-web-api/src/Native/WebAPI/Window.js b/src/vendor/elm-web-api/src/Native/WebAPI/Window.js deleted file mode 100644 index bb52170..0000000 --- a/src/vendor/elm-web-api/src/Native/WebAPI/Window.js +++ /dev/null @@ -1,53 +0,0 @@ -Elm.Native = Elm.Native || {}; -Elm.Native.WebAPI = Elm.Native.WebAPI || {}; -Elm.Native.WebAPI.Window = Elm.Native.WebAPI.Window || {}; - -Elm.Native.WebAPI.Window.make = function (localRuntime) { - localRuntime.Native = localRuntime.Native || {}; - localRuntime.Native.WebAPI = localRuntime.Native.WebAPI || {}; - localRuntime.Native.WebAPI.Window = localRuntime.Native.WebAPI.Window || {}; - - if (!localRuntime.Native.WebAPI.Window.values) { - var Task = Elm.Native.Task.make(localRuntime); - var Utils = Elm.Native.Utils.make(localRuntime); - - var elmAlert = function (message) { - return Task.asyncFunction(function (callback) { - window.alert(message); - callback(Task.succeed(Utils.Tuple0)); - }); - }; - - var elmConfirm = function (message) { - return Task.asyncFunction(function (callback) { - var result = window.confirm(message); - callback( - result - ? Task.succeed(Utils.Tuple0) - : Task.fail(Utils.Tuple0) - ); - }); - }; - - var elmPrompt = function (message, defaultResponse) { - return Task.asyncFunction(function (callback) { - var result = window.prompt(message, defaultResponse); - callback( - // Safari returns "" when you press cancel, so - // we need to check for that. - result == null || result == "" - ? Task.fail(Utils.Tuple0) - : Task.succeed(result) - ); - }); - }; - - localRuntime.Native.WebAPI.Window.values = { - alert: elmAlert, - confirm: elmConfirm, - prompt: F2(elmPrompt) - }; - } - - return localRuntime.Native.WebAPI.Window.values; -}; diff --git a/src/vendor/elm-web-api/src/WebAPI/AnimationFrame.elm b/src/vendor/elm-web-api/src/WebAPI/AnimationFrame.elm deleted file mode 100644 index f7f8f84..0000000 --- a/src/vendor/elm-web-api/src/WebAPI/AnimationFrame.elm +++ /dev/null @@ -1,63 +0,0 @@ -module WebAPI.AnimationFrame - ( task - , Request, request, cancel - ) where - - -{-| Bindings for `window.requestAnimationFrame()` and `window.cancelAnimationFrame`. - -Note that -[jwmerrill/elm-animation-frame](http://package.elm-lang.org/packages/jwmerrill/elm-animation-frame/latest) -provides for a `Signal` of animation frames. So, this module merely provides a -`Task`-oriented alternative. - -Other higher-level alternatives include -[evancz/elm-effects](http://package.elm-lang.org/packages/evancz/elm-effects/latest) -and [rgrempel/elm-ticker](https://github.com/rgrempel/elm-ticker.git). - -@docs task, request, Request, cancel --} - - -import Time exposing (Time) -import Task exposing (Task) -import Native.WebAPI.AnimationFrame - - -{-| A task which, when executed, will call `window.requestAnimationFrame()`. -The task will complete when `requestAnimationFrame()` fires its callback, and -will pass along the value provided by the callback. - -So, to do something when the callback fires, just add an `andThen` to the task. --} -task : Task x Time -task = Native.WebAPI.AnimationFrame.task - - -{-| Opaque type which represents an animation frame request. -} -type Request = Request - - -{-| A more complex implementation of `window.requestAnimationFrame()` which -allows for cancelling the request. - -Returns a `Task` which, when executed, will call -`window.requestAnimationFrame()`, and then immediately complete with the -identifier returned by `requestAnimationFrame()`. You can supply this -identifier to `cancel` if you want to cancel the request. - -Assuming that you don't cancel the request, the following sequence of events will occur: - -* `window.requestAnimationFrame()` will eventually fire its callback, providing a timestamp -* Your function will be called with that timestamp -* The `Task` returned by your function will be immediately executed --} -request : (Time -> Task x a) -> Task y Request -request = Native.WebAPI.AnimationFrame.request - - -{-| Returns a task which, when executed, will cancel the supplied request -via `window.cancelAnimationFrame()`. --} -cancel : Request -> Task x () -cancel = Native.WebAPI.AnimationFrame.cancel diff --git a/src/vendor/elm-web-api/src/WebAPI/Cookie.elm b/src/vendor/elm-web-api/src/WebAPI/Cookie.elm deleted file mode 100644 index 7bee024..0000000 --- a/src/vendor/elm-web-api/src/WebAPI/Cookie.elm +++ /dev/null @@ -1,140 +0,0 @@ -module WebAPI.Cookie - ( get, set - , Options, setWith, defaultOptions - ) where - -{-| Wrap the browser's -[`document.cookie`](https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie) -object. - -# Getting cookies -@docs get - -# Setting cookies -@docs set, setWith, Options, defaultOptions --} - -import Native.WebAPI.Cookie - -import Task exposing (Task) -import String exposing (split, trim, join) -import Dict exposing (Dict, insert) -import Time exposing (inSeconds, Time) -import Date exposing (Date) -import List - - -{-| A `Task` which, when executed, will succeed with the cookies. - -In the resulting `Dict`, the keys and values are the key=value pairs parsed from -Javascript's `document.cookie`. The keys and values will have been uriDecoded. --} -get : Task x (Dict String String) -get = - Task.map cookieString2Dict getString - - -getString : Task x String -getString = Native.WebAPI.Cookie.getString - - -{- We pipeline the various operations inside the foldl so that we don't -iterate over the cookies more then once. Note that the uriDecode needs to -happen after the split on ';' (to divide into key-value pairs) and the split on -'=' (to divide the keys from the values). --} -cookieString2Dict : String -> Dict String String -cookieString2Dict = - let - addCookieToDict = - trim >> split "=" >> List.map uriDecode >> addKeyValueToDict - - addKeyValueToDict keyValueList = - case keyValueList of - key :: value :: _ -> insert key value - _ -> identity - - in - List.foldl addCookieToDict Dict.empty << split ";" - - -{-| A task which will set a cookie using the provided key (first parameter) -and value (second parameter). - -The key and value will both be uriEncoded. --} -set : String -> String -> Task x () -set = setWith defaultOptions - - -{-| Options which you can provide to setWith. -} -type alias Options = - { path : Maybe String - , domain : Maybe String - , maxAge : Maybe Time - , expires : Maybe Date - , secure : Maybe Bool - } - - -{-| The default options, in which all options are set to Nothing. - -You can use this as a starting point for setWith, where you only want to -specify some options. --} -defaultOptions : Options -defaultOptions = - { path = Nothing - , domain = Nothing - , maxAge = Nothing - , expires = Nothing - , secure = Nothing - } - - -{-| A task which will set a cookie using the provided options, key (second -parameter), and value (third parameter). - -The key and value will be uriEncoded, as well as the path and domain options -(if provided). --} -setWith : Options -> String -> String -> Task x () -setWith options key value = - let - andThen = - flip Maybe.andThen - - handlers = - [ always <| Just <| (uriEncode key) ++ "=" ++ (uriEncode value) - , .path >> andThen (\path -> Just <| "path=" ++ uriEncode path) - , .domain >> andThen (\domain -> Just <| "domain=" ++ uriEncode domain) - , .maxAge >> andThen (\age -> Just <| "max-age=" ++ toString (inSeconds age)) - , .expires >> andThen (\expires -> Just <| "expires=" ++ dateToUTCString expires) - , .secure >> andThen (\secure -> if secure then Just "secure" else Nothing) - ] - - cookieStrings = - List.filterMap ((|>) options) handlers - - in - setString <| join ";" cookieStrings - - -setString : String -> Task x () -setString = - Native.WebAPI.Cookie.setString - - -dateToUTCString : Date -> String -dateToUTCString = - Native.WebAPI.Cookie.dateToUTCString - - -uriEncode : String -> String -uriEncode = - Native.WebAPI.Cookie.uriEncode - - -uriDecode : String -> String -uriDecode = - Native.WebAPI.Cookie.uriDecode diff --git a/src/vendor/elm-web-api/src/WebAPI/Date.elm b/src/vendor/elm-web-api/src/WebAPI/Date.elm deleted file mode 100644 index 44d7651..0000000 --- a/src/vendor/elm-web-api/src/WebAPI/Date.elm +++ /dev/null @@ -1,426 +0,0 @@ -module WebAPI.Date - ( current, now - , Timezone(Local, UTC), timezoneOffset - , Parts, fromParts, toParts, dayOfWeek - , toMonth, fromMonth, toDay, fromDay - , offsetTime, offsetYear, offsetMonth - , day, inDays - , week, inWeeks - , dateString, timeString, isoString, utcString - ) where - - -{-| Some additional facilities for the browser's `Date` type, not already -supplied by `Date` and `Time` in -[elm-lang/core](http://package.elm-lang.org/packages/elm-lang/core/latest). - -See the [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date). - -This is intended merely to be a thin wrapper over the Javascript `Date` API. -There is some real complexity in dealing with dates that would benefit from a -more sophisticated library. - -# Getting the current date or time - -@docs current, now - -# Timezones - -@docs Timezone, timezoneOffset - -# The parts of a date - -@docs Parts, fromParts, toParts, dayOfWeek -@docs toMonth, fromMonth, toDay, fromDay - -# Date arithmetic - -@docs offsetTime, offsetYear, offsetMonth - -# Time scales - -In the spirit of `Time.hour`, `Time.inHours`, `Time.second`, `Time.inSeconds`, -`Time.millisecond`, and `Time.inMilliseconds`. - -@docs day, inDays, week, inWeeks - -# String conversions - -@docs dateString, timeString, isoString, utcString --} - - -import Date exposing (Date) -import Time exposing (Time) -import Task exposing (Task) -import Debug - -import Native.WebAPI.Date - - -{- --------------------------------- - Getting the current date and time - --------------------------------- -} - - -{-| Get the current date, via the browser's `new Date()` -} -current : Task x Date -current = Native.WebAPI.Date.current - - -{-| Get the current time, via the browser's `Date.now()` -} -now : Task x Time -now = Native.WebAPI.Date.now - - -{- --------- - Timezones - --------- -} - - -{-| The Javascript API allows you to perform certain operations in terms of -the "local" timezone, or in terms of UTC. So, where we wrap those APIs, we use -this type to let you pick (rather than having separate functions). Of course, -you can use partial application to create separate functions if you like. - -Note that this isn't the kind of support that a more sophisticated library -would have for timezones -- it merely wraps what Javascript provides. --} -type Timezone - = Local - | UTC - - -{-| Javascript's `getTimezoneOffset()`. - -This represents what Javascript thinks is the offset between UTC and local time, -for the specified date. It can differ from date to date depending on whether -daylight savings time is in effect on that date. - -Note that this is in units of `Time`, so you can scale via `Time.inMinutes` etc. --} -timezoneOffset : Date -> Time -timezoneOffset date = - (timezoneOffsetInMinutes date) * Time.minute - - -timezoneOffsetInMinutes : Date -> Float -timezoneOffsetInMinutes = Native.WebAPI.Date.timezoneOffsetInMinutes - - -{- ------------------- - The parts of a date - ------------------- -} - - -{-| The parts of a date. - -Note that (as in the Javascript APIs) the month is 0-based, with January = 0. --} -type alias Parts = - { year : Int - , month : Int - , day : Int - , hour : Int - , minute : Int - , second : Int - , millisecond : Int - } - - -{-| Construct a `Date` from the provided parts, using the specified timezone. - -For `Local`, this uses `new Date(...)`. - -For `UTC`, this uses `new Date(Date.UTC(...))`. --} -fromParts : Timezone -> Parts -> Date -fromParts zone = - case zone of - Local -> fromPartsLocal - UTC -> fromPartsUtc - - -fromPartsLocal : Parts -> Date -fromPartsLocal = Native.WebAPI.Date.fromPartsLocal - - -fromPartsUtc : Parts -> Date -fromPartsUtc = Native.WebAPI.Date.fromPartsUtc - - -{-| Break a `Date` up into its parts, using the specified timezone. - -For `Local`, this uses `getFullYear()`, `getMonth()`, etc. - -For `UTC`, this uses `getUTCFullYear()`, `getUTCMonth()`, etc. --} -toParts : Timezone -> Date -> Parts -toParts zone = - case zone of - Local -> toPartsLocal - UTC -> toPartsUtc - - -toPartsLocal : Date -> Parts -toPartsLocal = Native.WebAPI.Date.toPartsLocal - - -toPartsUtc : Date -> Parts -toPartsUtc = Native.WebAPI.Date.toPartsUtc - - -{-| Get the day of the week corresopnding to a `Date`. - -This is handled separately from `Parts` because it is not symmetrical -- -it makes no sense for there to be a constructor based on this. --} -dayOfWeek : Timezone -> Date -> Date.Day -dayOfWeek timezone date = - case timezone of - Local -> - Date.dayOfWeek date - - UTC -> - toDay (dayOfWeekUTC date) - - -dayOfWeekUTC : Date -> Int -dayOfWeekUTC = Native.WebAPI.Date.dayOfWeekUTC - - -{-| Converts from Javascript's 0-based months (where January = 0) to`Date.Month`. -} -toMonth : Int -> Date.Month -toMonth int = - let - clamped = - int `rem` 12 - - positive = - if clamped < 0 - then clamped + 12 - else clamped - - in - case positive of - 0 -> Date.Jan - 1 -> Date.Feb - 2 -> Date.Mar - 3 -> Date.Apr - 4 -> Date.May - 5 -> Date.Jun - 6 -> Date.Jul - 7 -> Date.Aug - 8 -> Date.Sep - 9 -> Date.Oct - 10 -> Date.Nov - 11 -> Date.Dec - _ -> Debug.crash "This is unreachable." - - -{-| Converts from `Date.Month` to Javascript's 0-based months (where January = 0). -} -fromMonth : Date.Month -> Int -fromMonth month = - case month of - Date.Jan -> 0 - Date.Feb -> 1 - Date.Mar -> 2 - Date.Apr -> 3 - Date.May -> 4 - Date.Jun -> 5 - Date.Jul -> 6 - Date.Aug -> 7 - Date.Sep -> 8 - Date.Oct -> 9 - Date.Nov -> 10 - Date.Dec -> 11 - - -{-| Converts from Javascript's 0-based days (where Sunday = 0) to`Date.Day`. -} -toDay : Int -> Date.Day -toDay int = - let - clamped = - int `rem` 7 - - positive = - if clamped < 0 - then clamped + 7 - else clamped - - in - case positive of - 0 -> Date.Sun - 1 -> Date.Mon - 2 -> Date.Tue - 3 -> Date.Wed - 4 -> Date.Thu - 5 -> Date.Fri - 6 -> Date.Sat - _ -> Debug.crash "This is unreachable." - - -{-| Converts from `Date.Day` to Javascript's 0-based days (where Sunday = 0). -} -fromDay : Date.Day -> Int -fromDay day = - case day of - Date.Sun -> 0 - Date.Mon -> 1 - Date.Tue -> 2 - Date.Wed -> 3 - Date.Thu -> 4 - Date.Fri -> 5 - Date.Sat -> 6 - - -{- --------------- - Date arithmetic - --------------- -} - - -{-| Offset the `Date` by the supplied `Time` (i.e. positive values offset into -the future, and negative values into the past). - -You can use `day`, `week`, `Time.minute`, etc. to scale. However, that won't -always do what you actually want, since the values are treated as durations, -rather than human-oriented intervals. For instance, `offsetTime (365 * day) -date` will advance the date by 365 days. However, if a leap year is involved, -the resulting date might be a different day of the year. If you actually want -the same day in the next year, then use `offsetYear` instead. --} -offsetTime : Time -> Date -> Date -offsetTime time date = - Date.fromTime ((Date.toTime date) + time) - - -{-| Offset the `Date` by the specified number of years (forward or backward), -using Javascript's `setFullYear()` and `getFullYear()` (or `getUTCFullYear()` -and `setUTCFullYear()`). - -Leap years are handled by the underlying Javascript APIs as follows: - -* If the supplied date is February 29, and the target year has no February 29, - then you'll end up with March 1 in the target year. (Arguably, you might - prefer February 28, but I'm not sure there is a clearly correct answer). - -* If the supplied date is February 29, and the target year also has a February - 29, then you'll end up with February 29. - -* The year is interpreted in terms of either the local timezone or UTC, according - to what you specify. I think the only case in which this could make a - difference is in determining whether it is February 29. - -* If the offset "crosses" a leap day, then you'll end up with the "same" day in - the target year ... for instance, `offsetYear 1` will sometimes move 365 - days and sometimes 366 days, depending on whether a leap year is involved. - -A more sophisticated module might deal with these cases a little differently. --} -offsetYear : Timezone -> Int -> Date -> Date -offsetYear zone = - case zone of - Local -> offsetYearLocal - UTC -> offsetYearUTC - - -offsetYearLocal : Int -> Date -> Date -offsetYearLocal = Native.WebAPI.Date.offsetYearLocal - - -offsetYearUTC : Int -> Date -> Date -offsetYearUTC = Native.WebAPI.Date.offsetYearUTC - - -{-| Offset the `Date` by the specified number of months (forward or backward), -using Javascript's `setMonth()` and `getMonth()` (or `setUTCMonth()` and -`getUTCMonth()`). - -Here are a few notes about the underlying Javascript implementation: - -* Overflow and underflow basically do the right thing. That is, if you end up - with negative numbers, the year is decremented, and if you end up with - numbers past 11, the year is incremented. (Remember that Javascript months - are 0-based). And, in either case, the month is set to something between - 0 and 11. - -* Dates at the beginning of the month are handled as you might expect. For - instance, adding 1 month to January 1 produces February 1, and adding 1 month - to February 1 produces March 1. Thus, the actual number of days added can vary, - depending on the length of the month. - -* However, dates at the end of the month are handled in a way that could seem - odd. For instance, adding 1 month to August 31 produces October 1 ... were - you expecting September 30? That would probably be more useful, and a more - sophisticated library might arrange for that. - -* Note that the date is interpreted according to either the local timezone or UTC, - as you specify. In some cases, that will affect whether the date is - considered to be the last day of the month, or the first day of the next - month, which will in turn affect whether the "end of month" anomaly is - triggered. --} -offsetMonth : Timezone -> Int -> Date -> Date -offsetMonth zone = - case zone of - Local -> offsetMonthLocal - UTC -> offsetMonthUTC - - -offsetMonthLocal : Int -> Date -> Date -offsetMonthLocal = Native.WebAPI.Date.offsetMonthLocal - - -offsetMonthUTC : Int -> Date -> Date -offsetMonthUTC = Native.WebAPI.Date.offsetMonthUTC - - -{- --------------------------- - Some additional time scales - --------------------------- -} - - -{-| A convenience for arithmetic, analogous to `Time.hour`, `Time.minute`, etc. -} -day : Time -day = 24 * Time.hour - - -{-| A convenience for arithmetic, analogous to `Time.inHours`, `Time.inMinutes`, etc. -} -inDays : Time -> Float -inDays days = days / day - - -{-| A convenience for arithmetic, analogous to `Time.hour`, `Time.minute`, etc. -} -week : Time -week = 7 * day - - -{-| A convenience for arithmetic, analogous to `Time.inHours`, `Time.inMinutes`, etc. -} -inWeeks : Time -> Float -inWeeks weeks = weeks / week - - -{- ------------------ - String conversions - ------------------ -} - - -{-| The browser's `toDateString()` -} -dateString : Date -> String -dateString = Native.WebAPI.Date.dateString - - -{-| The browser's `toTimeString()` -} -timeString : Date -> String -timeString = Native.WebAPI.Date.timeString - - -{-| The browser's `toISOString()` -} -isoString : Date -> String -isoString = Native.WebAPI.Date.isoString - - -{-| The browser's `toUTCString()` -} -utcString : Date -> String -utcString = Native.WebAPI.Date.utcString - - diff --git a/src/vendor/elm-web-api/src/WebAPI/Document.elm b/src/vendor/elm-web-api/src/WebAPI/Document.elm deleted file mode 100644 index b337d50..0000000 --- a/src/vendor/elm-web-api/src/WebAPI/Document.elm +++ /dev/null @@ -1,62 +0,0 @@ -module WebAPI.Document - ( ReadyState (Loading, Interactive, Complete) - , readyState, getReadyState - , getTitle, setTitle - ) where - -{-| See Mozilla documentation for the -[`Document` object](https://developer.mozilla.org/en-US/docs/Web/API/Document). - -## Loading - -@docs ReadyState, readyState, getReadyState - -## Others - -Since the browser's `document` object has so many facilities attached, I've -broken some of them up into individual modules -- see below for the -cross-references. - -***See also*** - -**`cookie`** - -        -See [WebAPI.Cookie](#webapicookie) --} - - -import Signal exposing (Signal) -import Task exposing (Task) -import Native.WebAPI.Document - - -{-| Possible values for the browser's `document.readyState` -} -type ReadyState - = Loading - | Interactive - | Complete - - -{-| A `Signal` of changes to the browser's `document.readyState` -} -readyState : Signal ReadyState -readyState = Native.WebAPI.Document.readyState - - -{-| A task which, when executed, succeeds with the value of the browser's -`document.readyState`. --} -getReadyState : Task x ReadyState -getReadyState = Native.WebAPI.Document.getReadyState - - -{-| A task which, when executed, succeeds with the value of `document.title`. -} -getTitle : Task x String -getTitle = Native.WebAPI.Document.getTitle - - -{-| A task which, when executed, sets the value of `document.title` to the -supplied `String`. --} -setTitle : String -> Task x () -setTitle = Native.WebAPI.Document.setTitle diff --git a/src/vendor/elm-web-api/src/WebAPI/Location.elm b/src/vendor/elm-web-api/src/WebAPI/Location.elm deleted file mode 100644 index 53e5fd6..0000000 --- a/src/vendor/elm-web-api/src/WebAPI/Location.elm +++ /dev/null @@ -1,63 +0,0 @@ -module WebAPI.Location - ( Location, location - , reload, Source(ForceServer, AllowCache) - ) where - - -{-| Facilities from the browser's `window.location` object. - -See the [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/API/Location) - -For a `Signal`-oriented version of things you might do with `window.location`, see -[TheSeamau5/elm-history](http://package.elm-lang.org/packages/TheSeamau5/elm-history/latest). - -For `assign`, use `setPath` from -[TheSeamau5/elm-history](http://package.elm-lang.org/packages/TheSeamau5/elm-history/latest). - -For `replace`, use `replacePath` from -[TheSeamau5/elm-history](http://package.elm-lang.org/packages/TheSeamau5/elm-history/latest). - -@docs Location, location, reload, Source --} - - -import Task exposing (Task) -import Native.WebAPI.Location - - -{-| The parts of a location object. Note `port'`, since `port` is a reserved word. -} -type alias Location = - { href: String - , protocol: String - , host: String - , hostname: String - , port': String - , pathname: String - , search: String - , hash: String - , origin: String - } - - -{-| The browser's `window.location` object. -} -location : Task x Location -location = Native.WebAPI.Location.location - - -{-| Reloads the page from the current URL.-} -reload : Source -> Task String () -reload source = - nativeReload <| - case source of - ForceServer -> True - AllowCache -> False - - -nativeReload : Bool -> Task String () -nativeReload = Native.WebAPI.Location.reload - - -{-| Whether to force `reload` to use the server, or allow the cache. -} -type Source - = ForceServer - | AllowCache diff --git a/src/vendor/elm-web-api/src/WebAPI/Math.elm b/src/vendor/elm-web-api/src/WebAPI/Math.elm deleted file mode 100644 index 1bd3772..0000000 --- a/src/vendor/elm-web-api/src/WebAPI/Math.elm +++ /dev/null @@ -1,83 +0,0 @@ -module WebAPI.Math - ( ln2, ln10, log2e, log10e, sqrt1_2, sqrt2 - , exp, log - , random - ) where - - -{-| Various facilities from the browser's `Math` object that are not -otherwise available in Elm. - -See the [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math). - -## Constants - -@docs ln2, ln10, log2e, log10e, sqrt1_2, sqrt2 - -## Functions - -@docs exp, log - -## Task - -@docs random --} - - -import Task exposing (Task) -import Native.WebAPI.Math - - -{-| Natural logarithm of 2, approximately 0.693. -} -ln2 : Float -ln2 = Native.WebAPI.Math.ln2 - - -{-| Natural logarithm of 10, approximately 2.303. -} -ln10 : Float -ln10 = Native.WebAPI.Math.ln10 - - -{-| Base 2 logarithm of E, approximately 1.443. -} -log2e : Float -log2e = Native.WebAPI.Math.log2e - - -{-| Base 10 logarithm of E, approximately 0.434 -} -log10e : Float -log10e = Native.WebAPI.Math.log10e - - -{-| Square root of 1/2; equivalently, 1 over the square root of 2, -approximately 0.707. --} -sqrt1_2 : Float -sqrt1_2 = Native.WebAPI.Math.sqrt1_2 - - -{-| Square root of 2, approximately 1.414. -} -sqrt2 : Float -sqrt2 = Native.WebAPI.Math.sqrt2 - - -{-| Returns E to the power of x, where x is the argument, and E is Euler's -constant (2.718…), the base of the natural logarithm. --} -exp : number -> Float -exp = Native.WebAPI.Math.exp - - -{-| Returns the natural logarithm (loge, also ln) of a number. -} -log : number -> Float -log = Native.WebAPI.Math.log - - -{-| Returns a pseudo-random number between 0 and 1. - -Note that there is a more sophisticated implementation of `Random` in -elm-lang/core. However, this may sometimes be useful if you're in a `Task` -context anyway. --} -random : Task x Float -random = Native.WebAPI.Math.random - diff --git a/src/vendor/elm-web-api/src/WebAPI/Number.elm b/src/vendor/elm-web-api/src/WebAPI/Number.elm deleted file mode 100644 index d31465d..0000000 --- a/src/vendor/elm-web-api/src/WebAPI/Number.elm +++ /dev/null @@ -1,160 +0,0 @@ -module WebAPI.Number - ( maxValue, minValue, nan, negativeInfinity, positiveInfinity - , toExponential, toExponentialDigits, safeExponentialDigits - , toFixed, toFixedDigits, safeFixedDigits - , toPrecisionDigits, safePrecisionDigits - , toStringUsingBase, safeStringUsingBase - ) where - - -{-| Various facilities from the browser's `Number` object that are not -otherwise available in Elm. - -See the [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number). - -## Constants - -@docs maxValue, minValue, nan, negativeInfinity, positiveInfinity - -## Functions - -@docs toExponential, toExponentialDigits, safeExponentialDigits -@docs toFixed, toFixedDigits, safeFixedDigits -@docs toPrecisionDigits, safePrecisionDigits -@docs toStringUsingBase, safeStringUsingBase --} - - -import Result exposing (Result) -import Debug -import Native.WebAPI.Number - - -{-| The largest positive representable number. -} -maxValue : Float -maxValue = Native.WebAPI.Number.maxValue - - -{-| The smallest positive representable number - that is, the positive number -closest to zero (without actually being zero). --} -minValue : Float -minValue = Native.WebAPI.Number.minValue - - -{-| Special "not a number" value. -} -nan : Float -nan = Native.WebAPI.Number.nan - - -{-| Special value representing negative infinity; returned on overflow. -} -negativeInfinity : Float -negativeInfinity = Native.WebAPI.Number.negativeInfinity - - -{-| Special value representing infinity; returned on overflow. -} -positiveInfinity : Float -positiveInfinity = Native.WebAPI.Number.positiveInfinity - - -{-| A string representing the provided number in exponential notation. -} -toExponential : number -> String -toExponential = Native.WebAPI.Number.toExponential - - -{-| Either a string representing the second parameter in exponential notation, -with the requested number of digits after the decimal point (first parameter), -or an error. An error should not occur if the requested number of digits is -between 0 and 20. --} -toExponentialDigits : Int -> number -> Result String String -toExponentialDigits = Native.WebAPI.Number.toExponentialDigits - - -{-| A string representing the second parameter in exponential notation, -with the requested number of digits after the decimal point (first parameter). -The number of digits will be limited to between 0 and 20. --} -safeExponentialDigits : Int -> number -> String -safeExponentialDigits digits num = - case toExponentialDigits (clamp 0 20 digits) num of - Ok value -> - value - - Err err -> - Debug.crash "Unexpected error: " ++ err - - -{-| A string representing the provided number in fixed-point notation. -} -toFixed : number -> String -toFixed = Native.WebAPI.Number.toFixed - - -{-| Either a string representing the second parameter in fixed-point notation, -with the requested number of digits after the decimal point (first parameter), -or an error. An error should not occur if the requested number of digits is -between 0 and 20. - -Note that Firefox returns `Ok 0` rather than an `Error` for a negative number -of requested digits. --} -toFixedDigits : Int -> number -> Result String String -toFixedDigits = Native.WebAPI.Number.toFixedDigits - - -{-| A string representing the second parameter in fixed-point notation, -with the requested number of digits after the decimal point (first parameter). -The number of digits will be limited to between 0 and 20. --} -safeFixedDigits : Int -> number -> String -safeFixedDigits digits num = - case toFixedDigits (clamp 0 20 digits) num of - Ok value -> - value - - Err err -> - Debug.crash "Unexpected error: " ++ err - - -{-| Either a string representing the second parameter in fixed-point or -exponential notation, with the requested number of significant digits (first -parameter), or an error. An error should not occur if the requested number of -digits is between 1 and 20. --} -toPrecisionDigits : Int -> number -> Result String String -toPrecisionDigits = Native.WebAPI.Number.toPrecisionDigits - - -{-| A string representing the second parameter in fixed-point or exponential -notation, with the requested number of significant digits (first parameter). -The number of digits will be limited to between 1 and 20. --} -safePrecisionDigits : Int -> number -> String -safePrecisionDigits digits num = - case toPrecisionDigits (clamp 1 20 digits) num of - Ok value -> - value - - Err err -> - Debug.crash "Unexpected error: " ++ err - - -{-| Either a string representing the second parameter, using the requested base -(first parameter), or an error. An error should not occur if the requested base -is between 2 and 36. --} -toStringUsingBase : Int -> number -> Result String String -toStringUsingBase = Native.WebAPI.Number.toStringUsingBase - - -{-| A string representing the second parameter, using the requested base -(first parameter). The requested base will be limited to between 2 and 36. --} -safeStringUsingBase : Int -> number -> String -safeStringUsingBase base num = - case toStringUsingBase (clamp 2 36 base) num of - Ok value -> - value - - Err err -> - Debug.crash "Unexpected error: " ++ err diff --git a/src/vendor/elm-web-api/src/WebAPI/Screen.elm b/src/vendor/elm-web-api/src/WebAPI/Screen.elm deleted file mode 100644 index e3ed9b6..0000000 --- a/src/vendor/elm-web-api/src/WebAPI/Screen.elm +++ /dev/null @@ -1,52 +0,0 @@ -module WebAPI.Screen - ( Screen, screen - , screenXY - ) where - - -{-| The browser's `Screen` type from `window.screen`. - -See the [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/API/Screen). - -@docs Screen, screen - -@docs screenXY --} - -import Task exposing (Task) - -import Native.WebAPI.Screen - - -{-| The browser's `Screen` type. -} -type alias Screen = - { availTop: Int - , availLeft: Int - , availHeight: Int - , availWidth: Int - , colorDepth: Int - , pixelDepth: Int - , height: Int - , width: Int - } - - -{-| The browser's `window.screen` object. - -This is a `Task` because in multi-monitor setups, the result depends on which screen -the browser window is in. So, it is not necessarily a constant. --} -screen : Task x Screen -screen = Native.WebAPI.Screen.screen - - -{-| A tuple of the browser's `(window.screenX, window.screenY)`. - - The first value is the horizontal distance, in CSS pixels, of the left - border of the user's browser from the left side of the screen. - - The second value is the vertical distance, in CSS pixels, of the top border - of the user's browser from the top edge of the screen. --} -screenXY : Task x (Int, Int) -screenXY = Native.WebAPI.Screen.screenXY diff --git a/src/vendor/elm-web-api/src/WebAPI/Storage.elm b/src/vendor/elm-web-api/src/WebAPI/Storage.elm deleted file mode 100644 index 1b7bb73..0000000 --- a/src/vendor/elm-web-api/src/WebAPI/Storage.elm +++ /dev/null @@ -1,271 +0,0 @@ -module WebAPI.Storage - ( Storage(Local, Session), local, session - , length, key, get, set, remove, clear - , events, Event, Change(Add, Remove, Modify, Clear) - , Key, OldValue, NewValue, Value - ) where - - -{-| Facilities from the browser's `Storage` areas (`localStorage` and `sessionStorage`). - -See the [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/API/Storage), -and the [WhatWG documentation](https://html.spec.whatwg.org/multipage/webstorage.html). - -Note that there is a more sophisticated module for `Storage` at -[TheSeamau5/elm-storage](https://github.com/TheSeamau5/elm-storage) - -## Storage Areas - -@docs Storage, local, session - -## Roles for Strings - -@docs Key, OldValue, NewValue, Value - -## Tasks - -@docs length, key, get, set, remove, clear - -## Events - -@docs events, Event, Change - --} - - -import Task exposing (Task) -import Debug -import Native.WebAPI.Storage - - -{- ----------------- - Roles for Strings - ----------------- -} - -{-| A key. -} -type alias Key = String - - -{-| An old value. -} -type alias OldValue = String - - -{-| A new value. -} -type alias NewValue = String - - -{-| A value. -} -type alias Value = String - - -{- ------------- - Storage Areas - ------------- -} - - -{-| Represents the `localStorage` and `sessionStorage` areas. -} -type Storage - = Local - | Session - - -{-| The browser's `localStorage` area. -} -local : Storage -local = Local - - -{-| The browser's `sessionStorage` area. -} -session : Storage -session = Session - - --- We expose a union type (above), rather than the actual native storage objects, --- so that what we expose can be pattern-matched against etc. -type NativeStorage = NativeStorage - - -nativeLocal : NativeStorage -nativeLocal = Native.WebAPI.Storage.localStorage - - -nativeSession : NativeStorage -nativeSession = Native.WebAPI.Storage.sessionStorage - - -toNative : Storage -> NativeStorage -toNative storage = - case storage of - Local -> nativeLocal - Session -> nativeSession - - -fromNative : NativeStorage -> Storage -fromNative native = - if native == nativeLocal - then Local - else if native == nativeSession - then Session - else Debug.crash "There shouldn't be another kind of NativeStorage" - - -{- ----- - Tasks - ----- -} - - -{-| A task which, when executed, determines the number of items stored in the -storage area. --} -length : Storage -> Task x Int -length = nativeLength << toNative - - -nativeLength : NativeStorage -> Task x Int -nativeLength = Native.WebAPI.Storage.length - - -{-| A task which, when executed, determines the name of the key at the given -index (zero-based). --} -key : Storage -> Int -> Task x (Maybe Key) -key storage = nativeKey (toNative storage) - - -nativeKey : NativeStorage -> Int -> Task x (Maybe Key) -nativeKey = Native.WebAPI.Storage.key - - -{-| A task which, when executed, gets the value at the given key. -} -get : Storage -> Key -> Task x (Maybe Value) -get storage = nativeGet (toNative storage) - - -nativeGet : NativeStorage -> Key -> Task x (Maybe Value) -nativeGet = Native.WebAPI.Storage.getItem - - -{-| A task which, when executed, sets the value at the given key, or fails with -an error message. --} -set : Storage -> Key -> NewValue -> Task String () -set storage = nativeSet (toNative storage) - - -nativeSet : NativeStorage -> Key -> NewValue -> Task String () -nativeSet = Native.WebAPI.Storage.setItem - - -{-| A task which, when executed, removes the item with the given key. -} -remove : Storage -> Key -> Task x () -remove storage = nativeRemove (toNative storage) - - -nativeRemove : NativeStorage -> Key -> Task x () -nativeRemove = Native.WebAPI.Storage.removeItem - - -{-| A task which, when executed, removes all items. -} -clear : Storage -> Task x () -clear = nativeClear << toNative - - -nativeClear : NativeStorage -> Task x () -nativeClear = Native.WebAPI.Storage.clear - - -{- ------ - Events - ------ -} - - -{- This is the signal produced by the native code ... this way, we can do -more of the processing in Elm, which is nicer. - -Note that it is a `Maybe` because Elm signals must have initial values, -and there is no natural initial value for the `NativeEvent` itself unless -we wrap it in a `Maybe`. --} -nativeEvents : Signal (Maybe NativeEvent) -nativeEvents = Native.WebAPI.Storage.nativeEvents - - -{- An event as produced by the native code. -} -type alias NativeEvent = - { key : Maybe Key - , oldValue : Maybe OldValue - , newValue : Maybe NewValue - , url : String - , storageArea : NativeStorage - } - - -{-| A storage event. -} -type alias Event = - { area : Storage - , url : String - , change : Change - } - - -{-| A change to a storage area. -} -type Change - = Add Key NewValue - | Remove Key OldValue - | Modify Key OldValue NewValue - | Clear - - -nativeEvent2Change : NativeEvent -> Change -nativeEvent2Change native = - case (native.key, native.oldValue, native.newValue) of - (Nothing, _, _) -> - Clear - - -- Safari does this - (Just "", _, _) -> - Clear - - (Just key, Just oldValue, Nothing) -> - Remove key oldValue - - (Just key, Nothing, Just newValue) -> - Add key newValue - - (Just key, Just oldValue, Just newValue) -> - Modify key oldValue newValue - - (_, Nothing, Nothing) -> - Debug.crash "The browser should never emit this." - - -nativeEvent2Event : NativeEvent -> Event -nativeEvent2Event native = - { area = fromNative native.storageArea - , url = native.url - , change = nativeEvent2Change native - } - - -{-| A signal of storage events. - -Note that a storage event is not fired within the same document that made a -storage change. Thus, you will only receive events for localStorage changes -that occur in a **separate** tab or window. - -This behaviour reflects how Javascript does things ... let me know if you'd -prefer to have *all* localStorage events go through this `Signal` -- it could -be arranged. - -At least in Safari, sessionStorage is even more restrictive than localStorage --- it is isolated per-tab, so you will only get events on sessionStorage if -using iframes. - -Note that this signal emits `Maybe Event` (rather than `Event`) because Elm -signals must have an initial value -- and there is no natural initial value for -an `Event` unless we wrap it in a `Maybe`. So, you'll often want to use -`Signal.filterMap` when you're integrating this into your own signal of -actions. --} -events : Signal (Maybe Event) -events = - Signal.map (Maybe.map nativeEvent2Event) nativeEvents diff --git a/src/vendor/elm-web-api/src/WebAPI/Window.elm b/src/vendor/elm-web-api/src/WebAPI/Window.elm deleted file mode 100644 index 7e46293..0000000 --- a/src/vendor/elm-web-api/src/WebAPI/Window.elm +++ /dev/null @@ -1,57 +0,0 @@ -module WebAPI.Window - ( alert, confirm, prompt - ) where - - -{-| Facilities from the browser's `window` object. - -See the [Mozilla documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window) - -Note that some things on the browser's `window` object are handled through other -modules here. For instance: - -* localStorage, sessionStorage - See `WebAPI.Storage` - -* location - See `WebAPI.Location` - -* screen, screenX, screenY - See `WebAPI.Screen` - -* requestAnimationFrame, cancelAnimationFrame - See `WebAPI.AnimationFrame` - -@docs alert, confirm, prompt --} - - -import Task exposing (Task) -import Native.WebAPI.Window - - -{-| The browser's `window.alert()` function. --} -alert : String -> Task x () -alert = Native.WebAPI.Window.alert - - -{-| The browser's `window.confirm()` function. - -The task will succeed if the user confirms, and fail if the user cancels. --} -confirm : String -> Task () () -confirm = Native.WebAPI.Window.confirm - - -{-| The browser's `window.prompt()` function. - -The first parameter is a message, and the second parameter is a default -response. - -The task will succeed with the user's response, or fail if the user cancels -or enters blank text. --} -prompt : String -> String -> Task () String -prompt = Native.WebAPI.Window.prompt - diff --git a/src/vendor/elm-web-api/test/0.15/elm-package.json b/src/vendor/elm-web-api/test/0.15/elm-package.json deleted file mode 100644 index daab357..0000000 --- a/src/vendor/elm-web-api/test/0.15/elm-package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "version": "1.0.0", - "summary": "Tests for the WebAPI module", - "repository": "https://github.com/rgrempel/elm-web-api.git", - "license": "BSD3", - "source-directories": [ - "../src/elm", - "../../src", - "../../examples/src" - ], - "exposed-modules": [], - "native-modules": true, - "dependencies": { - "Apanatshka/elm-signal-extra": "5.6.0 <= v < 6.0.0", - "deadfoxygrandpa/Elm-Test": "1.0.4 <= v < 2.0.0", - "elm-lang/core": "2.0.0 <= v < 3.0.0", - "evancz/elm-html": "4.0.1 <= v < 5.0.0", - "maxsnew/IO": "1.0.1 <= v < 2.0.0", - "evancz/elm-effects": "2.0.0 <= v < 3.0.0", - "evancz/start-app": "2.0.1 <= v < 3.0.0" - }, - "elm-version": "0.15.0 <= v < 0.16.0" -} diff --git a/src/vendor/elm-web-api/test/0.15/package.json b/src/vendor/elm-web-api/test/0.15/package.json deleted file mode 100644 index 691ec8f..0000000 --- a/src/vendor/elm-web-api/test/0.15/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "elm-web-api", - "version": "1.0.0", - "description": "Tests for elm-web-api", - "main": "elm.js", - "dependencies": { - "mocha": "^2.3.3", - "node-localstorage": "^0.6.0", - "elm": "^2.0.0" - }, - "devDependencies": {}, - "scripts": { - "test": "elm-make ../src/elm/Browser.elm --output elm.html && open elm.html;", - "ci": "sh ../ci.sh", - "console": "elm-make ../src/elm/CommandLine.elm --output elm.js && cat ../src/elm/shim.js >> elm.js && node elm.js;" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/rgrempel/elm-web-api.git" - }, - "author": "Ryan Rempel ", - "license": "MIT", - "bugs": { - "url": "https://github.com/rgrempel/elm-web-api/issues" - }, - "homepage": "https://github.com/rgrempel/elm-web-api#readme" -} diff --git a/src/vendor/elm-web-api/test/0.16/elm-package.json b/src/vendor/elm-web-api/test/0.16/elm-package.json deleted file mode 100644 index 9236117..0000000 --- a/src/vendor/elm-web-api/test/0.16/elm-package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "version": "1.0.0", - "summary": "Tests for the WebAPI module", - "repository": "https://github.com/rgrempel/elm-web-api.git", - "license": "BSD3", - "source-directories": [ - "src", - "../src", - "../../src" - ], - "exposed-modules": [ - ], - "native-modules": true, - "dependencies": { - "elm-lang/core": "3.0.0 <= v < 4.0.0", - "avh4/elm-test": "1.0.0 <= v < 2.0.0", - "laszlopandy/elm-console": "1.0.0 <= v < 2.0.0" - }, - "elm-version": "0.16.0 <= v < 0.17.0" -} diff --git a/src/vendor/elm-web-api/test/0.16/package.json b/src/vendor/elm-web-api/test/0.16/package.json deleted file mode 100644 index 99022e1..0000000 --- a/src/vendor/elm-web-api/test/0.16/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "elm-web-api", - "version": "1.0.0", - "description": "Tests for elm-web-api", - "main": "elm.js", - "dependencies": { - "node-localstorage": "^0.6.0" - }, - "devDependencies": {}, - "scripts": { - "test": "elm-make ../src/Browser.elm --output elm.html && open elm.html;", - "console": "elm-make ../src/CommandLine.elm --output elm.js && cat ../src/shim.js >> elm.js && node elm.js;" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/rgrempel/elm-web-api.git" - }, - "author": "Ryan Rempel ", - "license": "MIT", - "bugs": { - "url": "https://github.com/rgrempel/elm-web-api/issues" - }, - "homepage": "https://github.com/rgrempel/elm-web-api#readme" -} diff --git a/src/vendor/elm-web-api/test/ci.sh b/src/vendor/elm-web-api/test/ci.sh deleted file mode 100644 index 0d7d474..0000000 --- a/src/vendor/elm-web-api/test/ci.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -# Print commands as we go -set -x - -elm-make ../src/elm/CI.elm --output elm.html || exit 1 -elm-make ../../examples/src/WindowExample.elm --output window.html || exit 1 -elm-make ../../examples/src/LocationExample.elm --output location.html || exit 1 -elm-make ../../examples/src/StorageExample.elm --output storage.html || exit 1 - -# Always exit 0 if we get this far ... the SauceLabs matrix takes over -mocha --delay ../src/run.js || exit 0 diff --git a/src/vendor/elm-web-api/test/package.json b/src/vendor/elm-web-api/test/package.json deleted file mode 100644 index e97063a..0000000 --- a/src/vendor/elm-web-api/test/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "elm-web-api", - "version": "1.0.0", - "description": "Tests for elm-web-api", - "main": "elm.js", - "dependencies": { - "chai": "^3.4.0", - "colors": "^1.1.2", - "count-substring": "^1.0.2", - "extend": "^3.0.0", - "git-rev": "^0.2.1", - "html-to-text": "^1.3.2", - "http-server": "^0.8.5", - "q": "^1.4.1", - "sauce-connect-launcher": "^0.13.0", - "saucelabs": "^1.0.1", - "selenium-standalone": "^4.7.1", - "webdriverio": "^3.2.6" - }, - "devDependencies": {}, - "scripts": {}, - "repository": { - "type": "git", - "url": "git+https://github.com/rgrempel/elm-web-api.git" - }, - "author": "Ryan Rempel ", - "license": "MIT", - "bugs": { - "url": "https://github.com/rgrempel/elm-web-api/issues" - }, - "homepage": "https://github.com/rgrempel/elm-web-api#readme" -} diff --git a/src/vendor/elm-web-api/test/src/config.js b/src/vendor/elm-web-api/test/src/config.js deleted file mode 100644 index 4bef20c..0000000 --- a/src/vendor/elm-web-api/test/src/config.js +++ /dev/null @@ -1,33 +0,0 @@ -var sauceUserName = process.env.GEB_SAUCE_LABS_USER; -var sauceAccessKey = process.env.GEB_SAUCE_LABS_ACCESS_PASSWORD; - -module.exports = { - // Configuration options - quiet: false, // Silences the console output - - webdriver: { // Options for Selenium WebDriver (WebdriverIO) - user: sauceUserName, - key: sauceAccessKey - }, - - httpServer: { // Options for local http server (npmjs.org/package/http-server) - disable: false, - port: 8080 // Non-standard option; it is passed into the httpServer.listen() method - }, - - sauceLabs: { // Options for SauceLabs API wrapper (npmjs.org/package/saucelabs) - username: sauceUserName, - password: sauceAccessKey - }, - - sauceConnect: { // Options for SauceLabs Connect (npmjs.org/package/sauce-connect-launcher) - disable: false, - username: sauceUserName, - accessKey: sauceAccessKey - }, - - selenium: { // Options for Selenium Server (npmjs.org/package/selenium-standalone). Only used if you need Selenium running locally. - args: [] // options to pass to `java -jar selenium-server-standalone-X.XX.X.jar` - } -}; - diff --git a/src/vendor/elm-web-api/test/src/elm/Browser.elm b/src/vendor/elm-web-api/test/src/elm/Browser.elm deleted file mode 100644 index 6f66d3a..0000000 --- a/src/vendor/elm-web-api/test/src/elm/Browser.elm +++ /dev/null @@ -1,25 +0,0 @@ -module Main where - -import Signal exposing (Signal, Mailbox, mailbox, constant, send) -import Task exposing (Task, andThen, sequence) -import Graphics.Element exposing (Element, empty, flow, down) -import ElmTest.Runner.Element exposing (runDisplay) -import Tests - - -main : Signal Element -main = - let - update test element = - flow down - [ element - , runDisplay test - ] - - in - Signal.foldp update empty (.signal Tests.tests) - - -port task : Task () () -port task = Tests.task - diff --git a/src/vendor/elm-web-api/test/src/elm/CI.elm b/src/vendor/elm-web-api/test/src/elm/CI.elm deleted file mode 100644 index 37b8f18..0000000 --- a/src/vendor/elm-web-api/test/src/elm/CI.elm +++ /dev/null @@ -1,31 +0,0 @@ -module Main where - -import Signal exposing (Signal, Mailbox, mailbox, constant, send) -import Task exposing (Task, andThen, sequence) -import Graphics.Element exposing (Element, empty, flow, down, show) -import ElmTest.Runner.String exposing (runDisplay) -import Html exposing (Html, pre, text) -import Html.Attributes exposing (id) -import Tests - - -main : Signal Html -main = - let - update test result = - (runDisplay test) :: result - - models = - Signal.foldp update [] (.signal Tests.tests) - - view model = - pre [id "results"] <| - List.map text model - - in - Signal.map view models - - -port task : Task () () -port task = Tests.task - diff --git a/src/vendor/elm-web-api/test/src/elm/CommandLine.elm b/src/vendor/elm-web-api/test/src/elm/CommandLine.elm deleted file mode 100644 index af635ac..0000000 --- a/src/vendor/elm-web-api/test/src/elm/CommandLine.elm +++ /dev/null @@ -1,27 +0,0 @@ -module Main where - -import Task exposing (Task) -import Tests -import ElmTest.Test exposing (Test) -import ElmTest.Runner.String exposing (runDisplay) - - -test : Task () Test -test = Tests.test - - -port task : Task () () -port task = - Task.map runDisplay test - `Task.andThen` Signal.send results.address - - -results : Signal.Mailbox String -results = Signal.mailbox "" - - -port result : Signal String -port result = - results.signal - - diff --git a/src/vendor/elm-web-api/test/src/elm/Native/TestUtil.js b/src/vendor/elm-web-api/test/src/elm/Native/TestUtil.js deleted file mode 100644 index 93cfaed..0000000 --- a/src/vendor/elm-web-api/test/src/elm/Native/TestUtil.js +++ /dev/null @@ -1,40 +0,0 @@ -Elm.Native.TestUtil = {}; -Elm.Native.TestUtil.make = function (localRuntime) { - localRuntime.Native = localRuntime.Native || {}; - localRuntime.Native.TestUtil = localRuntime.Native.TestUtil || {}; - - if (!localRuntime.Native.TestUtil.values) { - var Task = Elm.Native.Task.make(localRuntime); - var Signal = Elm.Native.Signal.make(localRuntime); - - var sample = function (signal) { - // Use closure to track value - var val = signal.value; - - var handler = function (value) { - val = value; - }; - - // We construct a new "output" node, because otherwise the incoming - // signal may be pruned by trimDeadNodes() in Runtime.js - // (if trimDeadNodes() sees that it is not otherwise used). - var output = Signal.output("sample-" + signal.name, handler, signal); - - return Task.asyncFunction(function (callback) { - // Need to return the value inside setTimeout, because - // otherwise we can be called out-of-order ... that is, a - // previous `Task.andThen` which updated a Signal may not have - // actually completed yet unless we do this inside a timeout. - localRuntime.setTimeout(function () { - callback(Task.succeed(val)); - }, 0); - }); - }; - - localRuntime.Native.TestUtil.values = { - sample: sample - }; - } - - return localRuntime.Native.TestUtil.values; -}; diff --git a/src/vendor/elm-web-api/test/src/elm/TestMailbox.elm b/src/vendor/elm-web-api/test/src/elm/TestMailbox.elm deleted file mode 100644 index 5104081..0000000 --- a/src/vendor/elm-web-api/test/src/elm/TestMailbox.elm +++ /dev/null @@ -1,9 +0,0 @@ -module TestMailbox where - -import Signal exposing (Signal, Mailbox, mailbox, constant, send) -import ElmTest.Test exposing (Test, suite) - - -tests : Mailbox Test -tests = - mailbox (suite "Tests have not arrived yet" []) diff --git a/src/vendor/elm-web-api/test/src/elm/TestUtil.elm b/src/vendor/elm-web-api/test/src/elm/TestUtil.elm deleted file mode 100644 index 60fed52..0000000 --- a/src/vendor/elm-web-api/test/src/elm/TestUtil.elm +++ /dev/null @@ -1,17 +0,0 @@ -module TestUtil (sample) where - - -{-| Test utilities. - -@docs sample --} - - -import Task exposing (Task) -import Native.TestUtil - - -{-| Construct a task which, when performed, will return the current value of a Signal. -} -sample : Signal a -> Task x a -sample = - Native.TestUtil.sample diff --git a/src/vendor/elm-web-api/test/src/elm/Tests.elm b/src/vendor/elm-web-api/test/src/elm/Tests.elm deleted file mode 100644 index 383efd3..0000000 --- a/src/vendor/elm-web-api/test/src/elm/Tests.elm +++ /dev/null @@ -1,42 +0,0 @@ -module Tests where - -import Signal exposing (Signal, Mailbox, mailbox, constant, send) -import Task exposing (Task, andThen, sequence) -import ElmTest.Test exposing (Test, suite) - -import TestMailbox - -import WebAPI.MathTest -import WebAPI.NumberTest -import WebAPI.StorageTest -import WebAPI.ScreenTest -import WebAPI.LocationTest -import WebAPI.DateTest -import WebAPI.AnimationFrameTest -import WebAPI.CookieTest -import WebAPI.DocumentTest - - -test : Task () Test -test = - Task.map (suite "WebAPI tests") <| - sequence - [ WebAPI.DocumentTest.tests - , WebAPI.MathTest.tests - , WebAPI.NumberTest.tests - , WebAPI.StorageTest.tests - , WebAPI.ScreenTest.tests - , WebAPI.LocationTest.tests - , WebAPI.DateTest.tests - , WebAPI.AnimationFrameTest.tests - , WebAPI.CookieTest.tests - ] - - -task : Task () () -task = - test `andThen` send tests.address - - -tests : Mailbox Test -tests = TestMailbox.tests diff --git a/src/vendor/elm-web-api/test/src/elm/WebAPI/AnimationFrameTest.elm b/src/vendor/elm-web-api/test/src/elm/WebAPI/AnimationFrameTest.elm deleted file mode 100644 index 9ccec92..0000000 --- a/src/vendor/elm-web-api/test/src/elm/WebAPI/AnimationFrameTest.elm +++ /dev/null @@ -1,111 +0,0 @@ -module WebAPI.AnimationFrameTest where - -import ElmTest.Test exposing (..) -import ElmTest.Assertion exposing (..) -import Task exposing (Task, sequence, succeed, andThen) -import Time exposing (Time) -import Signal exposing (Signal, Mailbox, mailbox) -import String - -import WebAPI.AnimationFrame as AnimationFrame -import WebAPI.Date -import Debug -import TestUtil exposing (sample) - - --- When testing on SauceLabs, this is really slow ... much faster locally ... --- not sure why. So, we allow an absurd amount of time for a frame here ... --- when run locally, the frame rate is about right. So, this is not really --- testing performance at the moment, just that it works at all. -frame : Time -frame = Time.second - - -taskTest : Task () Test -taskTest = - WebAPI.Date.now `andThen` (\startTime -> - AnimationFrame.task `andThen` (\timestamp -> - AnimationFrame.task `andThen` (\timestamp2 -> - WebAPI.Date.now `andThen` (\endTime -> - let - wallTime = - endTime - startTime - - delta = - timestamp2 - timestamp - - in - Task.succeed <| - suite "task" - [ test - ( String.join " " - [ "wall time" - , toString wallTime - , "is less than" - , toString (frame * 2) - ] - ) <| - assert (wallTime < frame * 2) - , test - ( String.join " " - [ "callback time" - , toString delta - , "is less than" - , toString frame - ] - ) <| - assert (delta < frame) - ] - )))) - - -result : Mailbox Time -result = mailbox 0 - - -delay : Time -delay = 0.2 * Time.second - - -requestTest : Task () Test -requestTest = - let - task time = - Signal.send result.address time - - in - Task.map (\time -> - test ("request fired at " ++ (toString time)) <| - assert (time > 0) - ) <| Signal.send result.address 0 - `andThen` always (AnimationFrame.request task) - `andThen` always (Task.sleep delay) - `andThen` always (sample result.signal) - - -cancelTest : Task () Test -cancelTest = - let - task time = - Signal.send result.address time - - in - Task.map (\time -> - test "request should have been canceled" <| - assertEqual 0 time - ) <| Signal.send result.address 0 - `andThen` always (AnimationFrame.request task) - `andThen` AnimationFrame.cancel - `andThen` always (Task.sleep delay) - `andThen` always (sample result.signal) - - -tests : Task () Test -tests = - Task.map (suite "WebAPI.AnimationFrameTest") <| - sequence <| - [ taskTest - , requestTest - , cancelTest - ] - diff --git a/src/vendor/elm-web-api/test/src/elm/WebAPI/CookieTest.elm b/src/vendor/elm-web-api/test/src/elm/WebAPI/CookieTest.elm deleted file mode 100644 index 91dc926..0000000 --- a/src/vendor/elm-web-api/test/src/elm/WebAPI/CookieTest.elm +++ /dev/null @@ -1,158 +0,0 @@ -module WebAPI.CookieTest where - -import String -import ElmTest.Assertion exposing (..) -import ElmTest.Test exposing (..) -import ElmTest.Runner.Element exposing (runDisplay) - -import Task exposing (Task, andThen, sequence, map) -import Date exposing (fromTime) -import Time exposing (second) -import Dict - -import WebAPI.Cookie as Cookies - - -(>>>) = flip Task.map -(>>+) = Task.andThen - - -simpleSetGet : Task x Test -simpleSetGet = - (Cookies.set "bog" "joe" >>+ always Cookies.get) - >>> - (Dict.get "bog" >> assertEqual (Just "joe") >> test "simple set then get") - - --- Make sure we're actually *changing* the cookie -secondSetGet : Task x Test -secondSetGet = - (Cookies.set "bog" "frank" >>+ always Cookies.get) - >>> - (Dict.get "bog" >> assertEqual (Just "frank") >> test "repeated set/get, to make sure we can change the cookie") - - -multipleSetGet : Task x Test -multipleSetGet = - ( - Cookies.set "cookie1" "cookie 1 value" - >>+ - always (Cookies.set "cookie2" "cookie 2 value") - >>+ - always Cookies.get - ) - >>> - (\cookies -> - [Dict.get "cookie1" cookies, Dict.get "cookie2" cookies] |> - assertEqual [Just "cookie 1 value", Just "cookie 2 value"] |> - test "multiple cookies") - - -encodingTest : Task x Test -encodingTest = - (Cookies.set "encoded=" "value needs encoding ;" >>+ always Cookies.get) - >>> - (Dict.get "encoded=" >> assertEqual (Just "value needs encoding ;") >> test "key and value should be encoded") - - -setWithWrongPath : Task x Test -setWithWrongPath = - let - defaults = - Cookies.defaultOptions - - options = - -- { defaults | path = Just "/path" } - Cookies.Options (Just "/path") Nothing Nothing Nothing Nothing - - in - (Cookies.setWith options "wrong path cookie" "path cookie value" >>+ always Cookies.get) - >>> - (Dict.get "wrong path cookie" >> assertEqual Nothing >> test "test with path set to bad value") - - -setWithGoodPath : Task x Test -setWithGoodPath = - let - defaults = - Cookies.defaultOptions - - options = - -- { defaults | path = Just "" } - Cookies.Options (Just "") Nothing Nothing Nothing Nothing - - in - (Cookies.setWith options "good path cookie" "path cookie value" >>+ always Cookies.get) - >>> - (Dict.get "good path cookie" >> assertEqual (Just "path cookie value") >> test "test with path set to good value") - - -maxAgeFuture : Task x Test -maxAgeFuture = - let - defaults = - Cookies.defaultOptions - - options = - -- { defaults | maxAge = Just 1000 } - Cookies.Options Nothing Nothing (Just 1000) Nothing Nothing - - in - (Cookies.setWith options "max age future" "cookie value" >>+ always Cookies.get) - >>> - (Dict.get "max age future" >> assertEqual (Just "cookie value") >> test "test with maxAge in future") - - -expiresInFuture : Task x Test -expiresInFuture = - let - defaults = - Cookies.defaultOptions - - options = - -- Sets the date to September 26, 2028 conveniently - -- { defaults | expires = Just (fromTime (1853609409 * second)) } - Cookies.Options Nothing Nothing Nothing (Just (fromTime (1853609409 * second))) Nothing - - in - (Cookies.setWith options "expires" "cookie value" >>+ always Cookies.get) - >>> - (Dict.get "expires" >> assertEqual (Just "cookie value") >> test "test with expiry in future") - - -expiresInPast : Task x Test -expiresInPast = - let - defaults = - Cookies.defaultOptions - - options = - -- { defaults | expires = Just (fromTime 0) } - Cookies.Options Nothing Nothing Nothing (Just (fromTime 0)) Nothing - - in - (Cookies.setWith options "expires" "cookie value" >>+ always Cookies.get) - >>> - (Dict.get "expires" >> assertEqual (Nothing) >> test "test with expiry in past") - - -tests : Task () Test -tests = - Task.map (suite "WebAPI.CookieTest") <| - sequence - [ simpleSetGet - , secondSetGet - , multipleSetGet - , encodingTest - - -- TODO: setWithWrongPath is "failing" on Chrome, but it's not really a proper - -- test, since I'm just trying to retrieve it locally -- what the path really - -- controls is whether it's sent to the server. So, in principle I ought to - -- do a more sophisticated test of this ... - -- , setWithWrongPath - - , setWithGoodPath - , maxAgeFuture - , expiresInFuture - , expiresInPast - ] diff --git a/src/vendor/elm-web-api/test/src/elm/WebAPI/DateTest.elm b/src/vendor/elm-web-api/test/src/elm/WebAPI/DateTest.elm deleted file mode 100644 index 2658af7..0000000 --- a/src/vendor/elm-web-api/test/src/elm/WebAPI/DateTest.elm +++ /dev/null @@ -1,386 +0,0 @@ -module WebAPI.DateTest where - -import ElmTest.Test exposing (..) -import ElmTest.Assertion exposing (..) -import Task exposing (Task, sequence, succeed, andThen) - -import WebAPI.Date exposing (..) -import Date -import Time -import String - - -testCurrent : Task x Test -testCurrent = - current |> - Task.map (\c -> - test "current" <| - assert <| - (Date.year c) > 2014 - ) - - -testNow : Task x Test -testNow = - now |> - Task.map (\n -> - test "now" <| - assert <| - n > 1445463720748 - ) - - -testTimezoneOffset : Test -testTimezoneOffset = - let - date = - fromParts Local (Parts 2015 1 1 1 1 1 1) - - in - test "timezoneOffset" <| - assert <| - (abs (timezoneOffset date)) < (12 * Time.hour) - - -testFromPartsLocal : Test -testFromPartsLocal = - let - date = - fromParts Local (Parts 2015 1 2 3 4 5 6) - - tuple = - ( Date.year date - , Date.month date - , Date.day date - , Date.hour date - , Date.minute date - , Date.second date - , Date.millisecond date - ) - - in - test "fromParts Local" <| - assertEqual - (2015, Date.Feb, 2, 3, 4, 5, 6) - tuple - - -testFromAndToParts : String -> Timezone -> Test -testFromAndToParts title zone = - let - parts = - Parts 2015 1 2 3 4 5 6 - - date = - fromParts zone parts - - result = - toParts zone date - - back = - fromParts zone result - - in - test title <| - assertEqual - (Date.toTime date) - (Date.toTime back) - - -testDayOfWeek : String -> Timezone -> Test -testDayOfWeek title zone = - let - makeTest (string, expected, parts) = - test string <| - assertEqual expected <| - dayOfWeek zone (fromParts zone parts) - - in - suite title <| - List.map makeTest - [ ("Sunday", Date.Sun, Parts 2015 1 1 0 0 0 0) - , ("Monday", Date.Mon, Parts 2015 1 2 0 0 0 0) - , ("Tuesday", Date.Tue, Parts 2015 1 3 0 0 0 0) - , ("Wednesday", Date.Wed, Parts 2015 1 4 0 0 0 0) - , ("Thursday", Date.Thu, Parts 2015 1 5 0 0 0 0) - , ("Friday", Date.Fri, Parts 2015 1 6 0 0 0 0) - , ("Saturday", Date.Sat, Parts 2015 1 7 0 0 0 0) - ] - - -testToMonth : Test -testToMonth = - let - makeTest (input, expected) = - test (toString input) <| - assertEqual - expected - (toMonth input) - - in - suite "toMonth" <| - List.map makeTest - [ (-8, Date.May) - , (-7, Date.Jun) - , (-6, Date.Jul) - , (-5, Date.Aug) - , (-4, Date.Sep) - , (-3, Date.Oct) - , (-2, Date.Nov) - , (-1, Date.Dec) - , (0, Date.Jan) - , (1, Date.Feb) - , (2, Date.Mar) - , (3, Date.Apr) - , (4, Date.May) - , (5, Date.Jun) - , (6, Date.Jul) - , (7, Date.Aug) - , (8, Date.Sep) - , (9, Date.Oct) - , (10, Date.Nov) - , (11, Date.Dec) - , (12, Date.Jan) - , (13, Date.Feb) - ] - - -testFromMonth : Test -testFromMonth = - let - makeTest (expected, input) = - test (toString input) <| - assertEqual - expected - (fromMonth input) - - in - suite "fromMonth" <| - List.map makeTest - [ (0, Date.Jan) - , (1, Date.Feb) - , (2, Date.Mar) - , (3, Date.Apr) - , (4, Date.May) - , (5, Date.Jun) - , (6, Date.Jul) - , (7, Date.Aug) - , (8, Date.Sep) - , (9, Date.Oct) - , (10, Date.Nov) - , (11, Date.Dec) - ] - - -testToDay : Test -testToDay = - let - makeTest (input, expected) = - test (toString input) <| - assertEqual - expected - (toDay input) - - in - suite "toMonth" <| - List.map makeTest - [ (-8, Date.Sat) - , (-7, Date.Sun) - , (-6, Date.Mon) - , (-5, Date.Tue) - , (-4, Date.Wed) - , (-3, Date.Thu) - , (-2, Date.Fri) - , (-1, Date.Sat) - , (0, Date.Sun) - , (1, Date.Mon) - , (2, Date.Tue) - , (3, Date.Wed) - , (4, Date.Thu) - , (5, Date.Fri) - , (6, Date.Sat) - , (7, Date.Sun) - , (8, Date.Mon) - , (9, Date.Tue) - , (10, Date.Wed) - , (11, Date.Thu) - , (12, Date.Fri) - , (13, Date.Sat) - ] - - -testFromDay : Test -testFromDay = - let - makeTest (expected, input) = - test (toString input) <| - assertEqual - expected - (fromDay input) - - in - suite "fromMonth" <| - List.map makeTest - [ (0, Date.Sun) - , (1, Date.Mon) - , (2, Date.Tue) - , (3, Date.Wed) - , (4, Date.Thu) - , (5, Date.Fri) - , (6, Date.Sat) - ] - - -offsetTimeTest : Test -offsetTimeTest = - let - date = - fromParts Local (Parts 2015 1 2 3 4 5 6) - - forward = - fromParts Local (Parts 2015 1 2 3 5 5 6) - - backward = - fromParts Local (Parts 2015 1 2 3 3 5 6) - - offsetTimePositive = - test "positive" <| - assertEqual - (Date.toTime forward) - (Date.toTime (offsetTime (1 * Time.minute) date)) - - offsetTimeNegative = - test "negative" <| - assertEqual - (Date.toTime backward) - (Date.toTime (offsetTime (-1 * Time.minute) date)) - - in - suite "offsetTime" - [ offsetTimePositive - , offsetTimeNegative - ] - - -offsetYearTest : String -> Timezone -> Test -offsetYearTest title zone = - let - date = - fromParts zone (Parts 2015 1 2 3 4 5 6) - - forward = - fromParts zone (Parts 2016 1 2 3 4 5 6) - - backward = - fromParts zone (Parts 2014 1 2 3 4 5 6) - - offsetYearPositive = - test "positive" <| - assertEqual - (Date.toTime forward) - (Date.toTime (offsetYear zone 1 date)) - - offsetYearNegative = - test "negative" <| - assertEqual - (Date.toTime backward) - (Date.toTime (offsetYear zone -1 date)) - - in - suite title - [ offsetYearPositive - , offsetYearNegative - ] - - -offsetMonthTest : String -> Timezone -> Test -offsetMonthTest title zone = - let - date = - fromParts zone (Parts 2015 0 2 3 4 5 6) - - forward = - fromParts zone (Parts 2015 1 2 3 4 5 6) - - backward = - fromParts zone (Parts 2014 11 2 3 4 5 6) - - offsetPositive = - test "positive" <| - assertEqual - (Date.toTime forward) - (Date.toTime (offsetMonth zone 1 date)) - - offsetNegative = - test "negative" <| - assertEqual - (Date.toTime backward) - (Date.toTime (offsetMonth zone -1 date)) - - in - suite title - [ offsetPositive - , offsetNegative - ] - - -timescale : Test -timescale = - suite "timescale" - [ test "day" <| assertEqual 86400000 day - , test "inDays" <| assertEqual 1 (inDays 86400000) - , test "week" <| assertEqual 604800000 week - , test "inWeeks" <| assertEqual 1 (inWeeks 604800000) - ] - - -strings : Test -strings = - let - date = - fromParts UTC (Parts 2015 0 2 3 4 5 6) - - utc = - utcString date - - in - suite "Strings" - -- For dateString and timeString, we'd have to do some calculation - -- based on timezoneOffset to figure out the real expectation - [ test "dateString" <| assert <| String.length (dateString date) > 6 - , test "timeString" <| assert <| String.length (timeString date) > 6 - , test "isoString" <| assertEqual "2015-01-02T03:04:05.006Z" (isoString date) - , test ("utcString " ++ utc) <| - assert <| - "Fri, 02 Jan 2015 03:04:05 GMT" == utc || - -- This is from IE 10 - "Fri, 2 Jan 2015 03:04:05 UTC" == utc - ] - - -tests : Task () Test -tests = - Task.map (suite "WebAPI.DateTest") <| - sequence <| - [ testCurrent - , testNow - ] - ++ - List.map Task.succeed - [ testTimezoneOffset - , testFromPartsLocal - , testFromAndToParts "fromParts and toParts Local" Local - , testFromAndToParts "fromParts and toParts UTC" UTC - , testDayOfWeek "dayOfWeek Local" Local - , testDayOfWeek "dayOfWeek UTC" UTC - , testToMonth, testFromMonth - , testToDay, testFromDay - , offsetTimeTest - , offsetYearTest "offsetYear Local" Local - , offsetYearTest "offsetYear UTC" UTC - , offsetMonthTest "offsetMonth Local" Local - , offsetMonthTest "offsetMonth UTC" UTC - , timescale - , strings - ] - diff --git a/src/vendor/elm-web-api/test/src/elm/WebAPI/DocumentTest.elm b/src/vendor/elm-web-api/test/src/elm/WebAPI/DocumentTest.elm deleted file mode 100644 index 8061bd3..0000000 --- a/src/vendor/elm-web-api/test/src/elm/WebAPI/DocumentTest.elm +++ /dev/null @@ -1,77 +0,0 @@ -module WebAPI.DocumentTest where - -import String -import ElmTest.Assertion exposing (..) -import ElmTest.Test exposing (..) - -import Task exposing (Task, andThen, sequence, map) -import TestUtil exposing (sample) -import Signal.Extra exposing (foldp') -import Time - -import WebAPI.Document exposing (..) - - -(>>>) = flip Task.map -(>>+) = Task.andThen - - -(>>-) task func = - task `andThen` (always func) - - -getReadyStateTest : Task x Test -getReadyStateTest = - getReadyState >>> (\state -> - test ("getReadyState got " ++ (toString state)) <| - -- Basically, this succeeds if it doesn't throw an error - assert <| - state == Loading || - state == Interactive || - state == Complete - ) - - -readyStateTest : Task x Test -readyStateTest = - let - accumulator = - foldp' (::) (\s -> [s]) readyState - - in - Task.sleep (0.5 * Time.second) >>- - sample accumulator >>> (\list -> - test ("readyState signal: " ++ (toString list)) <| - assert <| - List.length list >= 2 - ) - - -getTitleTest : Task x Test -getTitleTest = - getTitle >>> (\title -> - test "getTitle should be 'Main'" <| - assertEqual "Main" title - ) - - -setTitleTest : Task x Test -setTitleTest = - setTitle "New title" >>+ (\setTitleResponse -> - getTitle >>> (\newTitle -> - test "setTitle should work" <| - assert <| - setTitleResponse == () && - newTitle == "New title" - ) - ) - - -tests : Task () Test -tests = - Task.map (suite "WebAPI.DocumentTest") <| - sequence - [ getReadyStateTest - , readyStateTest - , getTitleTest, setTitleTest - ] diff --git a/src/vendor/elm-web-api/test/src/elm/WebAPI/LocationTest.elm b/src/vendor/elm-web-api/test/src/elm/WebAPI/LocationTest.elm deleted file mode 100644 index 01f35db..0000000 --- a/src/vendor/elm-web-api/test/src/elm/WebAPI/LocationTest.elm +++ /dev/null @@ -1,45 +0,0 @@ -module WebAPI.LocationTest where - -import ElmTest.Test exposing (..) -import ElmTest.Assertion exposing (..) -import Task exposing (Task, sequence, succeed, andThen) -import String - -import WebAPI.Location exposing (..) - - -locationTest : Task () Test -locationTest = - location |> - Task.map (\loc -> - suite "location" - [ test "hash" <| assertEqual "" loc.hash - , test "host" <| assertEqual "localhost:8080" loc.host - , test "hostname" <| assertEqual "localhost" loc.hostname - , test "href" <| - assert <| - List.all identity - [ String.startsWith "http://" loc.href - , String.endsWith "elm.html" loc.href - ] - , test "origin" <| assertEqual "http://localhost:8080" loc.origin - , test "pathname" <| - assert <| - List.all identity - [ String.startsWith "/" loc.pathname - , String.endsWith "elm.html" loc.pathname - ] - , test "port'" <| assertEqual "8080" loc.port' - , test "protocol" <| assertEqual "http:" loc.protocol - , test "search" <| assertEqual "" loc.search - ] - ) - - -tests : Task () Test -tests = - Task.map (suite "WebAPI.LocationTest") <| - sequence <| - [ locationTest - ] - diff --git a/src/vendor/elm-web-api/test/src/elm/WebAPI/MathTest.elm b/src/vendor/elm-web-api/test/src/elm/WebAPI/MathTest.elm deleted file mode 100644 index 89c0500..0000000 --- a/src/vendor/elm-web-api/test/src/elm/WebAPI/MathTest.elm +++ /dev/null @@ -1,46 +0,0 @@ -module WebAPI.MathTest where - -import ElmTest.Test exposing (..) -import ElmTest.Assertion exposing (..) -import Task exposing (Task, sequence, succeed) - -import WebAPI.Math - - -within : Float -> Float -> Float -> Assertion -within tolerance value1 value2 = - assert <| - abs (value1 - value2) < tolerance - - -within001 : Float -> Float -> Assertion -within001 = within 0.001 - - -random : Task x Test -random = - WebAPI.Math.random |> - Task.map (\r -> - test "random" <| - assert <| - (r >= 0 && r <= 1) - ) - - -tests : Task x Test -tests = - Task.map (suite "WebAPI.Math") <| - sequence <| - List.map succeed - [ test "ln2" <| within001 WebAPI.Math.ln2 0.693 - , test "ln10" <| within001 WebAPI.Math.ln10 2.303 - , test "log2e" <| within001 WebAPI.Math.log2e 1.443 - , test "log10e" <| within001 WebAPI.Math.log10e 0.434 - , test "sqrt1_2" <| within001 WebAPI.Math.sqrt1_2 0.707 - , test "sqrt2" <| within001 WebAPI.Math.sqrt2 1.414 - , test "exp" <| within001 (WebAPI.Math.exp 2) (e ^ 2) - , test "log" <| within001 (WebAPI.Math.log 27) (logBase e 27) - ] - ++ - [ random - ] diff --git a/src/vendor/elm-web-api/test/src/elm/WebAPI/NumberTest.elm b/src/vendor/elm-web-api/test/src/elm/WebAPI/NumberTest.elm deleted file mode 100644 index 8dacad9..0000000 --- a/src/vendor/elm-web-api/test/src/elm/WebAPI/NumberTest.elm +++ /dev/null @@ -1,73 +0,0 @@ -module WebAPI.NumberTest where - -import ElmTest.Test exposing (..) -import ElmTest.Assertion exposing (..) -import Task exposing (Task, sequence, succeed) -import Result exposing (Result(..)) - -import WebAPI.Number - - -within : Float -> Float -> Float -> Assertion -within tolerance value1 value2 = - assert <| - abs (value1 - value2) < tolerance - - -within001 : Float -> Float -> Assertion -within001 = within 0.001 - - -isErr : Result a b -> Bool -isErr result = - case result of - Ok _ -> False - Err _ -> True - - -toFixedDigitsFailure : Test -toFixedDigitsFailure = - let - result = - WebAPI.Number.toFixedDigits -10 200 - - in - -- Firefox gives 0 for this, which I suppose is somewhat sensible - test ("toFixedDigits -10 200 should fail, or be 0: " ++ (toString result)) <| - assert <| - (isErr result) || result == (Ok "0") - - -tests : Task x Test -tests = - Task.map (suite "WebAPI.Number") <| - sequence <| - List.map succeed - [ test "maxValue" <| assert <| WebAPI.Number.maxValue > 1000 - , test "minValue" <| within001 WebAPI.Number.minValue 0 - , test "nan" <| assert <| isNaN WebAPI.Number.nan - , test "negativeInfinity" <| assert <| isInfinite WebAPI.Number.negativeInfinity - , test "positiveInfinity" <| assert <| isInfinite WebAPI.Number.positiveInfinity - , test "toExponential" <| assertEqual (WebAPI.Number.toExponential 200) "2e+2" - , test "toExponentialDigits success" <| assertEqual (WebAPI.Number.toExponentialDigits 1 200.0) (Ok "2.0e+2") - , test "toExponentialDigits failure" <| assert <| isErr (WebAPI.Number.toExponentialDigits -10 200) - , test "toExponentialDigits integer" <| assertEqual (WebAPI.Number.toExponentialDigits 1 200) (Ok "2.0e+2") - , test "safeExponentialDigits success" <| assertEqual (WebAPI.Number.safeExponentialDigits 1 200.0) "2.0e+2" - , test "safeExponentialDigits failure" <| assertEqual (WebAPI.Number.safeExponentialDigits -10 200.0) "2e+2" - , test "toFixed" <| assertEqual (WebAPI.Number.toFixed 200.1) "200" - , test "toFixedDigits success" <| assertEqual (WebAPI.Number.toFixedDigits 2 200.1) (Ok "200.10") - , toFixedDigitsFailure - , test "toFixedDigits integer" <| assertEqual (WebAPI.Number.toFixedDigits 2 200) (Ok "200.00") - , test "safeFixedDigits success" <| assertEqual (WebAPI.Number.safeFixedDigits 2 200.1) "200.10" - , test "safeFixedDigits failure" <| assertEqual (WebAPI.Number.safeFixedDigits -10 200.1) "200" - , test "toPrecisionDigits success" <| assertEqual (WebAPI.Number.toPrecisionDigits 5 200.1) (Ok "200.10") - , test "toPrecisionDigits failure" <| assert <| isErr (WebAPI.Number.toPrecisionDigits -10 200) - , test "toPrecisionDigits integer" <| assertEqual (WebAPI.Number.toPrecisionDigits 2 223) (Ok "2.2e+2") - , test "safePrecisionDigits success" <| assertEqual (WebAPI.Number.safePrecisionDigits 5 200.1) "200.10" - , test "safePrecisionDigits failure" <| assertEqual (WebAPI.Number.safePrecisionDigits -10 200.1) "2e+2" - , test "toStringUsingBase success" <| assertEqual (WebAPI.Number.toStringUsingBase 16 32.0) (Ok "20") - , test "toStringUsingBase failure" <| assert <| isErr (WebAPI.Number.toStringUsingBase -10 200) - , test "toStringUsingBase integer" <| assertEqual (WebAPI.Number.toStringUsingBase 16 32) (Ok "20") - , test "safeStringUsingBase success" <| assertEqual (WebAPI.Number.safeStringUsingBase 16 32.0) "20" - , test "safeStringUsingBase failure" <| assertEqual (WebAPI.Number.safeStringUsingBase -10 32) "100000" - ] diff --git a/src/vendor/elm-web-api/test/src/elm/WebAPI/ScreenTest.elm b/src/vendor/elm-web-api/test/src/elm/WebAPI/ScreenTest.elm deleted file mode 100644 index d40f9c2..0000000 --- a/src/vendor/elm-web-api/test/src/elm/WebAPI/ScreenTest.elm +++ /dev/null @@ -1,55 +0,0 @@ -module WebAPI.ScreenTest where - -import ElmTest.Test exposing (..) -import ElmTest.Assertion exposing (..) -import Task exposing (Task, sequence, succeed, andThen) -import String - -import WebAPI.Screen exposing (..) - - -screenTest : Task () Test -screenTest = - screen |> - Task.map (\s -> - test "screen" << - assert <| - List.all ((flip (>=)) 0) <| - List.map ((|>) s) - [ .availTop - , .availLeft - , .availHeight - , .availWidth - , .colorDepth - , .pixelDepth - , .height - , .width - ] - ) - - -screenXYTest : Task () Test -screenXYTest = - screenXY |> - Task.map (\(x, y) -> - test - (String.join "" - [ "screenXY (" - , toString x, ", " - , toString y, ")" - ] - ) <| - -- Note that in IE, you get (-8, -8), which I suppose actually - -- is meaningful. - assert (x >= -32 && y >= -32) - ) - - -tests : Task () Test -tests = - Task.map (suite "WebAPI.ScreenTest") <| - sequence <| - [ screenTest - , screenXYTest - ] - diff --git a/src/vendor/elm-web-api/test/src/elm/WebAPI/StorageTest.elm b/src/vendor/elm-web-api/test/src/elm/WebAPI/StorageTest.elm deleted file mode 100644 index 6a7bc1f..0000000 --- a/src/vendor/elm-web-api/test/src/elm/WebAPI/StorageTest.elm +++ /dev/null @@ -1,104 +0,0 @@ -module WebAPI.StorageTest where - -import ElmTest.Test exposing (..) -import ElmTest.Assertion exposing (..) -import Task exposing (Task, sequence, succeed, andThen) - -import WebAPI.Storage exposing (..) - - -length0Test : Storage -> Task () Test -length0Test storage = - clear storage `andThen` - always (length storage) |> - Task.map (assertEqual 0 >> test "length") - - -length1Test : Storage -> Task () Test -length1Test storage = - clear storage `andThen` - always (set storage "bob" "joe") `andThen` - always (length storage) |> - Task.map (assertEqual 1 >> test "length") |> - Task.mapError (always ()) - - -keyTestSuccess : Storage -> Task () Test -keyTestSuccess storage = - clear storage `andThen` - always (set storage "bob" "joe") `andThen` - always (key storage 0) |> - Task.map (assertEqual (Just "bob") >> test "keySuccess") |> - Task.mapError (always ()) - - -keyTestError : Storage -> Task () Test -keyTestError storage = - clear storage `andThen` - always (set storage "bob" "joe") `andThen` - always (key storage 5) |> - Task.map (assertEqual Nothing >> test "keyError") |> - Task.mapError (always ()) - - -getItemTestSuccess : Storage -> Task () Test -getItemTestSuccess storage = - clear storage `andThen` - always (set storage "bob" "joe") `andThen` - always (get storage "bob") |> - Task.map (assertEqual (Just "joe") >> test "getItemSuccess") |> - Task.mapError (always ()) - - -getItemTestError : Storage -> Task () Test -getItemTestError storage = - clear storage `andThen` - always (set storage "bob" "joe") `andThen` - always (get storage "wrong") |> - Task.map (assertEqual Nothing >> test "getItemError") |> - Task.mapError (always ()) - - -removeItemTest : Storage -> Task () Test -removeItemTest storage = - clear storage `andThen` - always (set storage "bob" "joe") `andThen` - always (remove storage "bob") `andThen` - always (length storage) |> - Task.map (assertEqual 0 >> test "removeItem") |> - Task.mapError (always ()) - - -removeItemTestError : Storage -> Task () Test -removeItemTestError storage = - clear storage `andThen` - always (set storage "bob" "joe") `andThen` - always (remove storage "not there") `andThen` - always (length storage) |> - Task.map (assertEqual 1 >> test "removeItem") |> - Task.mapError (always ()) - - -tests : Task () Test -tests = - Task.map (suite "Storage") <| - sequence <| - List.map makeSuite - [ (local, "localStorage") - , (session, "sessionStorage") - ] - - -makeSuite : (Storage, String) -> Task () Test -makeSuite (storage, label) = - Task.map (suite label) <| - sequence - [ length0Test storage - , length1Test storage - , keyTestSuccess storage - , keyTestError storage - , getItemTestSuccess storage - , getItemTestError storage - , removeItemTest storage - , removeItemTestError storage - ] diff --git a/src/vendor/elm-web-api/test/src/elm/shim.js b/src/vendor/elm-web-api/test/src/elm/shim.js deleted file mode 100644 index 0ffea98..0000000 --- a/src/vendor/elm-web-api/test/src/elm/shim.js +++ /dev/null @@ -1,14 +0,0 @@ -var LocalStorage = require('node-localstorage').LocalStorage; - -var window = { - localStorage: new LocalStorage('./localStorage.store'), - sessionStorage: new LocalStorage('./sessionStorage.store'), - - setTimeout: setTimeout -} - -var app = Elm.worker(Elm.Main); - -app.ports.result.subscribe(function (s) { - console.log(s); -}); diff --git a/src/vendor/elm-web-api/test/src/mocha/browser.js b/src/vendor/elm-web-api/test/src/mocha/browser.js deleted file mode 100644 index 8e397ec..0000000 --- a/src/vendor/elm-web-api/test/src/mocha/browser.js +++ /dev/null @@ -1,41 +0,0 @@ -var windowTest = require('./windowTest'); -var elmTest = require('./elmTest'); -var locationTest = require('./locationTest'); -var storageTest = require('./storageTest'); - -module.exports = function (browser) { - var title = - browser.desiredCapabilities.browserName + "-" + - browser.desiredCapabilities.version + "-" + - browser.desiredCapabilities.platform + " " - browser.desiredCapabilities.build; - - describe(title, function () { - this.timeout(600000); - this.slow(4000); - - var allPassed = true; - - // Before any tests run, initialize the browser. - before(function (done) { - browser.init(function (err) { - if (err) throw err; - done(); - }); - }); - - elmTest(browser); - windowTest(browser); - locationTest(browser); - storageTest(browser); - - afterEach(function() { - allPassed = allPassed && (this.currentTest.state === 'passed'); - }); - - after(function (done) { - console.log(title + (allPassed ? " PASSED" : " FAILED")); - browser.passed(allPassed, done); - }); - }); -}; diff --git a/src/vendor/elm-web-api/test/src/mocha/elmTest.js b/src/vendor/elm-web-api/test/src/mocha/elmTest.js deleted file mode 100644 index 92ba76f..0000000 --- a/src/vendor/elm-web-api/test/src/mocha/elmTest.js +++ /dev/null @@ -1,30 +0,0 @@ -var expect = require('chai').expect; -var count = require('count-substring'); -var Q = require('q'); - -module.exports = function (browser) { - describe("The tests written in Elm", function () { - var falsy = function () { - return Q.when(false); - }; - - it('should pass', function () { - return browser - .url('http://localhost:8080/elm.html') - .waitUntil(function () { - return this.getText("#results").then(function (text) { - return text.indexOf("suites run") > 0; - }, falsy); - }, 30000, 500) - .getText("#results") - .then(function (text) { - // Always log the test results - console.log(text); - - var failedCount = count(text, "FAILED"); - expect(failedCount).to.equal(0); - }); - }); - }); -}; - diff --git a/src/vendor/elm-web-api/test/src/mocha/locationTest.js b/src/vendor/elm-web-api/test/src/mocha/locationTest.js deleted file mode 100644 index d6e1020..0000000 --- a/src/vendor/elm-web-api/test/src/mocha/locationTest.js +++ /dev/null @@ -1,40 +0,0 @@ -var expect = require('chai').expect; -var Q = require('q'); - -module.exports = function (browser) { - describe("The Location example", function () { - beforeEach(function (done) { - browser.url('http://localhost:8080/location.html', done); - }); - - var falsy = function () { - return Q.when(false); - }; - - it("should reload from server", function () { - return browser - .setValue("#input", "This goes away on reload") - .click("#reload-force-button") - - // Wait for it not to have a value again - .waitUntil(function () { - return this.getValue("#input").then(function (value) { - return value === ""; - }, falsy); - }, 6000, 250); - }); - - it("should reload from cache", function () { - return browser - .setValue("#input", "This goes away on reload") - .click("#reload-cache-button") - - // Wait for it not to have a value again - .waitUntil(function () { - return this.getValue("#input").then(function (value) { - return value === ""; - }, falsy); - }, 6000, 250); - }); - }); -}; diff --git a/src/vendor/elm-web-api/test/src/mocha/storageTest.js b/src/vendor/elm-web-api/test/src/mocha/storageTest.js deleted file mode 100644 index 1538bea..0000000 --- a/src/vendor/elm-web-api/test/src/mocha/storageTest.js +++ /dev/null @@ -1,116 +0,0 @@ -var expect = require('chai').expect; -var Q = require('q'); - -module.exports = function (browser) { - var run; - - if ( - browser.desiredCapabilities.browserName == 'chrome' || - browser.desiredCapabilities.browserName == 'internet explorer' || - browser.desiredCapabilities.browserName == 'opera' - ) { - // Can't get the tab switching to work in these - run = describe.skip; - } else { - run = describe; - } - - run("The Storage example", function () { - var url = 'http://localhost:8080/storage.html'; - - before(function () { - return browser - .newWindow(url, "tab1") - .waitForExist("#select-area", 6000) - .selectByIndex("#select-area", 0) - .selectByIndex("#select-operation", 5) - .click("#perform-action") - .newWindow(url, "tab2") - .waitForExist("#select-area", 6000) - .selectByIndex("#select-area", 0) - .selectByIndex("#select-operation", 5) - .click("#perform-action"); - }); - - after(function () { - return browser - .switchTab("tab1") - .close() - .switchTab("tab2") - .close(); - }); - - it("first set should trigger add event", function () { - var expectedText = "LogEvent { area = Local, change = Add \"testKey\" \"testValue\", url = \"" + url + "\" }"; - - return browser - .switchTab("tab1") - .waitForExist("#select-area", 6000) - .selectByIndex("#select-area", 0) - .selectByIndex("#select-operation", 3) - .waitForExist("#select-set-key", 6000) - .setValue("#select-set-key", "testKey") - .setValue("#select-set-value", "testValue") - .click("#perform-action") - .switchTab("tab2") - .waitUntil(function () { - return this.getText("#log").then(function (text) { - return text.indexOf(expectedText) >= 0; - }); - }, 8000, 250); - }); - - it("second set should trigger modify event", function () { - var expectedText = "LogEvent { area = Local, change = Modify \"testKey\" \"testValue\" \"testValue2\", url = \"" + url + "\" }"; - - return browser - .switchTab("tab1") - .setValue("#select-set-key", "testKey") - .setValue("#select-set-value", "testValue2") - .click("#perform-action") - .switchTab("tab2") - .waitUntil(function () { - return this.getText("#log").then(function (text) { - return text.indexOf(expectedText) >= 0; - }); - }, 8000, 250); - }); - - it("remove should trigger remove event", function () { - var expectedText = "LogEvent { area = Local, change = Remove \"testKey\" \"testValue2\", url = \"" + url + "\" }"; - - return browser - .switchTab("tab1") - .selectByIndex("#select-operation", 4) - .waitForExist("#select-remove-key", 6000) - .setValue("#select-remove-key", "testKey") - .click("#perform-action") - .switchTab("tab2") - .waitUntil(function () { - return this.getText("#log").then(function (text) { - return text.indexOf(expectedText) >= 0; - }); - }, 8000, 250); - }); - - it("clear should trigger clear event", function () { - var expectedText = "LogEvent { area = Local, change = Clear, url = \"" + url + "\" }"; - - return browser - .switchTab("tab1") - .selectByIndex("#select-operation", 3) - .waitForExist("#select-set-key", 6000) - .setValue("#select-set-key", "testKey") - .setValue("#select-set-value", "testValue") - .click("#perform-action") - .selectByIndex("#select-operation", 5) - .click("#perform-action") - .switchTab("tab2") - .waitUntil(function () { - return this.getText("#log").then(function (text) { - return text.indexOf(expectedText) >= 0; - }); - }, 8000, 250); - }); - }); -}; diff --git a/src/vendor/elm-web-api/test/src/mocha/windowTest.js b/src/vendor/elm-web-api/test/src/mocha/windowTest.js deleted file mode 100644 index 4376e7f..0000000 --- a/src/vendor/elm-web-api/test/src/mocha/windowTest.js +++ /dev/null @@ -1,166 +0,0 @@ -var expect = require('chai').expect; -var Q = require('q'); - -module.exports = function (browser) { - describe("The Window example", function () { - beforeEach(function (done) { - browser.url('http://localhost:8080/window.html', done); - }); - - // Don't test alerts etc. under Safari, because Selenium can't - // manage alerts with Safari. - var describeAlert = ( - browser.desiredCapabilities.browserName == 'safari' || - browser.desiredCapabilities.browserName == 'opera' - ) ? describe.skip : describe; - - var truthy = function () { - return Q.when(true); - }; - - var falsy = function () { - return Q.when(false); - }; - - describeAlert("alert", function () { - it("should open", function () { - return browser - .click("#alert-button") - - .waitUntil(function () { - return this.alertText().then(truthy, falsy); - }, 30000, 500) - - .alertText().then(function (text) { - expect(text).to.equal("Hello world!"); - }) - - .alertAccept(); - }); - }); - - describeAlert("confirm", function () { - it("should recognize acceptance", function () { - return browser - .click("#confirm-button") - - .waitUntil(function () { - return this.alertText().then(truthy, falsy); - }, 30000, 500) - - .alertText().then(function (text) { - expect(text).to.equal("Do you agree?"); - }) - - .alertAccept() - - .waitUntil(function () { - return this.getText("#message").then(function (text) { - return text.indexOf("Pressed OK") >= 0; - }); - }, 30000, 500); - }); - - it("should recognize rejection", function () { - return browser - .click("#confirm-button") - - .waitUntil(function () { - return this.alertText().then(truthy, falsy); - }, 30000, 500) - - .alertText().then(function (text) { - expect(text).to.equal("Do you agree?"); - }) - - .alertDismiss() - - .waitUntil(function () { - return this.getText("#message").then(function (text) { - return text.indexOf("Pressed cancel") >= 0; - }); - }, 30000, 500); - }); - }); - - describeAlert("prompt", function () { - it("should recognize dismissal", function () { - return browser - .click("#prompt-button") - - .waitUntil(function () { - return this.alertText().then(truthy, falsy); - }, 30000, 500) - - .alertText().then(function (text) { - expect(text).to.equal("What is your favourite colour?"); - }) - - .alertDismiss() - - .waitUntil(function () { - return this.getText("#message").then(function (text) { - return text.indexOf("User canceled.") >= 0; - }); - }, 30000, 500); - }); - - it("should return default when accepted", function () { - return browser - .click("#prompt-button") - - .waitUntil(function () { - return this.alertText().then(truthy, falsy); - }, 30000, 500) - - .alertText().then(function (text) { - expect(text).to.equal("What is your favourite colour?"); - }) - - .alertAccept() - - .waitUntil(function () { - return this.getText("#message").then(function (text) { - return text.indexOf("Got response: Blue") >= 0; - }); - }, 30000, 500); - }); - - it("should interpret empty string as dismissal", function () { - return browser - .click("#prompt-button") - - .waitUntil(function () { - return this.alertText().then(truthy, falsy); - }, 30000, 500) - - .alertText("") - .alertAccept() - - .waitUntil(function () { - return this.getText("#message").then(function (text) { - return text.indexOf("User canceled.") >= 0; - }); - }, 30000, 500); - }); - - it("should return entered text if entered", function () { - return browser - .click("#prompt-button") - - .waitUntil(function () { - return this.alertText().then(truthy, falsy); - }, 30000, 500) - - .alertText("Red") - .alertAccept() - - .waitUntil(function () { - return this.getText("#message").then(function (text) { - return text.indexOf("Got response: Red") >= 0; - }); - }, 30000, 500); - }); - }); - }); -}; diff --git a/src/vendor/elm-web-api/test/src/remote.js b/src/vendor/elm-web-api/test/src/remote.js deleted file mode 100644 index 051aea4..0000000 --- a/src/vendor/elm-web-api/test/src/remote.js +++ /dev/null @@ -1,131 +0,0 @@ -// Definition of browsers to test remotely - -module.exports = function remote (rev) { - return [{ -/* Something about the iPhone setup on SauceLabs isn't working for me - browserName: 'iphone', - platform: 'OS X 10.10', - version: '9.0', - deviceName: 'iPhone 6', - deviceOrientation: 'portrait', - build: rev, - name: 'iphone 6 ' + rev - },{ -*/ browserName: 'safari', - version: '6.0', - platform: 'OS X 10.8', - build: rev, - name: 'Safari Mountain Lion ' + rev - },{ - browserName: 'safari', - version: '7.0', - platform: 'OS X 10.9', - build: rev, - name: 'Safari Mavericks ' + rev - },{ - browserName: 'safari', - version: '8.0', - platform: 'OS X 10.10', - build: rev, - name: 'Safari Yosemite ' + rev - },{ - browserName: 'safari', - version: '9.0', - platform: 'OS X 10.11', - build: rev, - name: 'Safari El Capitan ' + rev - },{ -/* browserName: 'android', - platform: 'Linux', - version: '5.1', - deviceName: 'Android Emulator', - deviceOrientation: 'portrait', - build: rev, - name: 'Android 5.1 ' + rev - },{ -*/ browserName: 'chrome', - version: '46.0', - platform: 'Windows 10', - build: rev, - name: 'Chrome Windows 10 46.0 ' + rev - },{ - browserName: 'chrome', - version: '45.0', - platform: 'Windows 10', - build: rev, - name: 'Chrome Windows 10 45.0 ' + rev - },{ - browserName: 'chrome', - version: '44.0', - platform: 'Windows 10', - build: rev, - name: 'Chrome Windows 10 44.0 ' + rev - },{ - browserName: 'chrome', - version: '43.0', - platform: 'Windows 10', - build: rev, - name: 'Chrome Windows 10 43.0 ' + rev - },{ - browserName: 'firefox', - version: '41.0', - platform: 'Linux', - build: rev, - name: 'Firefox Linux 41.0 ' + rev - },{ - browserName: 'firefox', - version: '40.0', - platform: 'Linux', - build: rev, - name: 'Firefox Linux 40.0 ' + rev - },{ - browserName: 'firefox', - version: '39.0', - platform: 'Linux', - build: rev, - name: 'Firefox Linux 39.0 ' + rev - },{ - browserName: 'firefox', - version: '38.0', - platform: 'Linux', - build: rev, - name: 'Firefox Linux 38.0 ' + rev - },{ -/* browserName: 'internet explorer', - version: '8.0', - platform: 'Windows 7', - build: rev, - name: 'Internet Explorer 8.0 ' + rev, - },{ -*/ browserName: 'internet explorer', - version: '9.0', - platform: 'Windows 7', - build: rev, - name: 'Internet Explorer 9.0 ' + rev, - },{ - browserName: 'opera', - version: '12.15', - platform: 'Linux', - build: rev, - name: 'Opera 12.15 ' + rev, - },{ - browserName: 'internet explorer', - version: '10.0', - platform: 'Windows 8', - build: rev, - name: 'Internet Explorer 10.0 ' + rev - },{ - browserName: 'internet explorer', - version: '11.0', - platform: 'Windows 10', - build: rev, - name: 'Internet Explorer 11.0 ' + rev -/* },{ - Looks like webdriver support for Edge isn't complete yet - browserName: 'microsoftedge', - version: '20.10240', - platform: 'Windows 10', - build: rev, - name: 'MS Edge 20.10240 ' + rev -*/ }]; -}; diff --git a/src/vendor/elm-web-api/test/src/run.js b/src/vendor/elm-web-api/test/src/run.js deleted file mode 100644 index 4293d25..0000000 --- a/src/vendor/elm-web-api/test/src/run.js +++ /dev/null @@ -1,23 +0,0 @@ -var SeSauce = require('./selenium-sauce'); -var git = require('git-rev'); - -var remote = require('./remote'); -var config = require('./config'); -var eachBrowser = require('./mocha/browser'); - -git.short(function (rev) { - // If SauceLabs environment variables are present, set up SauceLabs browsers - if (config.webdriver.user) { - config.webdriver.desiredCapabilities = remote(rev); - } else { - config.webdriver.desiredCapabilities = [{ - browserName: 'firefox' - }]; - }; - - new SeSauce(config, eachBrowser); - - // Need to call mocha with a --delay, since git.short is async - run(); -}); - diff --git a/src/vendor/elm-web-api/test/src/selenium-sauce.js b/src/vendor/elm-web-api/test/src/selenium-sauce.js deleted file mode 100644 index d28eaab..0000000 --- a/src/vendor/elm-web-api/test/src/selenium-sauce.js +++ /dev/null @@ -1,238 +0,0 @@ -var webdriverio = require('webdriverio'), - httpserver = require('http-server'), - selenium = require('selenium-standalone'), - sauceConnectLauncher = require('sauce-connect-launcher'), - extend = require('extend'), - colors = require('colors'), - SauceLabs = require('saucelabs'); - -/** - * Initializes Selenium Sauce using the specified options. - * 'doEachBrowser' is called once for each browser in options.webdriver.desiredCapabilities, passing in the webdriverio instance. - */ -var SeSauce = function(options, doEachBrowser) { - - extend(this, { - browsers: [], // Contains a list of webdriverio instances - _browserActions: [], - - _initialized: false, - _stopped: false, - - options: { - quiet: false, // Silences the console output - webdriver: { // Options for selenium webdriver (webdriverio) - host: 'ondemand.saucelabs.com', - port: 80, - user: null, - key: null, - logLevel: 'silent', - desiredCapabilities: [] // Non-standard option; An array of desired capabilities instead of a single object - }, - httpServer: { // Options for local http server (npmjs.org/package/http-server) - disable: false, // Non-standard option; used to skip launching the http server - port: 8080 // Non-standard option; it is passed into the httpServer.listen() method - }, - sauceLabs: { // Options for SauceLabs API wrapper (npmjs.org/package/saucelabs) - username: null, - password: null - }, - sauceConnect: { // Options for SauceLabs Connect (npmjs.org/package/sauce-connect-launcher) - disable: false, // Non-standard option; used to disable sauce connect - username: null, - accessKey: null - }, - selenium: { // Options for Selenium Server (npmjs.org/package/selenium-standalone). Only used if you need Selenium running locally. - args: [] // options to pass to `java -jar selenium-server-standalone-X.XX.X.jar` - } - } - }); - - - this._doEachBrowser = doEachBrowser; - this.options.quiet = options.quiet; - - extend(this.options.webdriver, options.webdriver || {}); - extend(this.options.httpServer, options.httpServer || {}); - extend(this.options.sauceLabs, options.sauceLabs || {}); - extend(this.options.sauceConnect, options.sauceConnect || {}); - extend(this.options.selenium, options.selenium || {}); - - if (this.options.webdriver.desiredCapabilities && this.options.webdriver.desiredCapabilities.constructor === Object) - this.options.webdriver.desiredCapabilities = [this.options.webdriver.desiredCapabilities]; - - if (!(this.options.webdriver.user && this.options.webdriver.key) && this.options.webdriver.host == 'ondemand.saucelabs.com') { - this.options.webdriver.host = 'localhost'; - this.options.webdriver.port = 4444; - } - - var self = this; - - for (var i = 0, len = this.options.webdriver.desiredCapabilities.length; i < len; i++) { - var wdOptions = extend({}, this.options.webdriver); - wdOptions.desiredCapabilities = this.options.webdriver.desiredCapabilities[i]; - var browser = webdriverio.remote(wdOptions); - this.browsers.push(browser); - - browser._oldInit = browser.init; - browser.init = function (complete) { - self._initOnce(function (err) { - if (err) - return complete(err); - this._oldInit(complete); - }.bind(this)); - }.bind(browser); - - browser._oldEnd = browser.end; - browser.end = function (complete) { - this._oldEnd(function () { - self.browsers.splice(self.browsers.indexOf(this), 1); - if (self.browsers.length == 0) - self._stop(complete); - else - complete(); - }.bind(this)); - }.bind(browser); - - browser.passed = function(success, complete) { - this.updateJob({ passed: success }, function() { - this.end(complete); - }.bind(this)); - }.bind(browser); - - browser.updateJob = function(data, complete) { - if (self.sauceLabs) - self.sauceLabs.updateJob(this.requestHandler.sessionID, data, complete); - else - complete(); - }.bind(browser); - - doEachBrowser.call(this, browser); - } - -}; - -extend(SeSauce.prototype, { - - /** - * Performs one-time initialization. Calls 'complete' when done, passing in an error message if necessary. - * @private - */ - _initOnce: function (complete) { - if (this._initialized) - return complete(); - - var self = this; - this._initialized = true; - - this.webdriver = webdriverio; - - if (!this.options.httpServer.disable) { - this._log("Launching local web server (http://localhost:" + this.options.httpServer.port + "/)..."); - this.httpServer = httpserver.createServer(this.options.httpServer); - this.httpServer.listen(this.options.httpServer.port); - this._log("Web server ready."); - } - - if (this.options.sauceLabs.username && this.options.sauceLabs.password) { - this._log("Initializing SauceLabs API."); - this.sauceLabs = new SauceLabs({ - username: this.options.sauceLabs.username, - password: this.options.sauceLabs.password - }); - } - - if (this.options.sauceConnect.username && this.options.sauceConnect.accessKey) { - if (this.options.sauceConnect.disable) - this._log("Sauce Connect disabled."); - else { - this._log("Launching Sauce Connect..."); - delete this.options.sauceConnect.disable; - sauceConnectLauncher(this.options.sauceConnect, function (errmsg, process) { - if (errmsg) { - if (process) process.close(); - return self._doError('Error launching Sauce Connect:\n' + errmsg, complete); - } - self.sauceConnect = process; - self._log("Sauce Connect ready."); - complete(); - }); - } - } - else { - this._log("No SauceLabs username/accessKey. Launching Selenium locally..."); - - selenium.install({}, function (err) { - if (err) { - self._doError(err, complete); - } else { - selenium.start({ - seleniumArgs: self.options.selenium.args - }, function (err, child) { - if (err) { - self._doError(err, complete); - } else { - self.selenium = child; - complete(); - } - }); - } - }); - } - }, - - /** - * Logs an error message, stops all services, and then calls the 'complete' callback, passing in the error message. - * @private - */ - _doError: function (msg, complete) { - this._err(msg); - this._stop(function () { - complete(msg); - }); - }, - - - /** - * @private - */ - _stop: function (complete) { - if (this._stopped) - return complete && complete(); - - this._stopped = true; - - if (this.httpServer) { - this.httpServer.close(); - this._log("Web server stopped."); - } - - if (this.selenium) { - this.selenium.kill(); - this._log("Local Selenium server stopped."); - } - - if (this.sauceConnect) { - var self = this; - this._log("Closing Sauce Connect..."); - this.sauceConnect.close(function () { - self._log("Sauce Connect closed."); - if (complete) - complete(); - }); - } - else if (complete) - complete(); - }, - - _log: function(str) { - if(!this.options.quiet) - console.log('SelSauce: '.blue + str); - }, - - _err: function(str) { - console.error('SelSauce: '.bgRed + str); - } -}); - -module.exports = SeSauce; From 5bdecdda0392ce6894796afb22bde10b796b1c63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hern=C3=A1ndez?= Date: Wed, 9 Nov 2016 18:11:58 +0100 Subject: [PATCH 05/10] Adds base code generated by generator-elmlang. --- .gitignore | 6 - .travis.yml | 20 ++- README.md | 25 +++ elm-package.json | 21 +++ gulpfile.js | 227 ++++++++++++++++++++++++++++ package.json | 43 ++++++ runTests.js | 18 +++ src/assets/scss/style.scss | 7 + src/elm/App/Model.elm | 34 +++++ src/elm/App/Router.elm | 68 +++++++++ src/elm/App/Test.elm | 50 ++++++ src/elm/App/Update.elm | 103 +++++++++++++ src/elm/App/View.elm | 162 ++++++++++++++++++++ src/elm/Config.elm | 32 ++++ src/elm/Config/Model.elm | 11 ++ src/elm/Config/View.elm | 16 ++ src/elm/Main.elm | 28 ++++ src/elm/Pages/Counter/Model.elm | 12 ++ src/elm/Pages/Counter/Test.elm | 36 +++++ src/elm/Pages/Counter/Update.elm | 27 ++++ src/elm/Pages/Counter/View.elm | 27 ++++ src/elm/Pages/Login/Model.elm | 12 ++ src/elm/Pages/Login/Test.elm | 75 +++++++++ src/elm/Pages/Login/Update.elm | 101 +++++++++++++ src/elm/Pages/Login/View.elm | 58 +++++++ src/elm/Pages/MyAccount/View.elm | 38 +++++ src/elm/Pages/PageNotFound/View.elm | 14 ++ src/elm/TestRunner.elm | 20 +++ src/elm/User/Decoder.elm | 13 ++ src/elm/User/Model.elm | 11 ++ src/index.html | 20 +++ src/js/README.md | 1 + 32 files changed, 1328 insertions(+), 8 deletions(-) create mode 100644 README.md create mode 100644 elm-package.json create mode 100644 gulpfile.js create mode 100644 package.json create mode 100644 runTests.js create mode 100644 src/assets/scss/style.scss create mode 100644 src/elm/App/Model.elm create mode 100644 src/elm/App/Router.elm create mode 100644 src/elm/App/Test.elm create mode 100644 src/elm/App/Update.elm create mode 100644 src/elm/App/View.elm create mode 100644 src/elm/Config.elm create mode 100644 src/elm/Config/Model.elm create mode 100644 src/elm/Config/View.elm create mode 100644 src/elm/Main.elm create mode 100644 src/elm/Pages/Counter/Model.elm create mode 100644 src/elm/Pages/Counter/Test.elm create mode 100644 src/elm/Pages/Counter/Update.elm create mode 100644 src/elm/Pages/Counter/View.elm create mode 100644 src/elm/Pages/Login/Model.elm create mode 100644 src/elm/Pages/Login/Test.elm create mode 100644 src/elm/Pages/Login/Update.elm create mode 100644 src/elm/Pages/Login/View.elm create mode 100644 src/elm/Pages/MyAccount/View.elm create mode 100644 src/elm/Pages/PageNotFound/View.elm create mode 100644 src/elm/TestRunner.elm create mode 100644 src/elm/User/Decoder.elm create mode 100644 src/elm/User/Model.elm create mode 100644 src/index.html create mode 100644 src/js/README.md diff --git a/.gitignore b/.gitignore index 1bd093e..9ffdce2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,4 @@ -bower_components elm-stuff node_modules serve dist -.publish -.idea -# Compiled tests -elm.js -test.html diff --git a/.travis.yml b/.travis.yml index cd8ffbe..f8944a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,11 +2,27 @@ language: node_js node_js: - "4.1" + +cache: + directories: + - sysconfcpus + install: - - npm install -g elm@0.16.0 casperjs http-server + - npm install -g elm@~0.17.0 casperjs http-server - elm-package install -y + # Getting elm-make to run quicker. + # See https://github.com/elm-lang/elm-compiler/issues/1473#issuecomment-245704142 + - | + if [ ! -d sysconfcpus/bin ]; + then + git clone https://github.com/obmarg/libsysconfcpus.git; + cd libsysconfcpus; + ./configure --prefix=$TRAVIS_BUILD_DIR/sysconfcpus; + make && make install; + cd ..; + fi before_script: - - elm-make ./src/elm/TestRunner.elm --output test.html + - $TRAVIS_BUILD_DIR/sysconfcpus/bin/sysconfcpus -n 2 elm-make ./src/elm/TestRunner.elm --output test.html - http-server '.' & # Wait for compilation is done. - until $(curl --output /dev/null --silent --head --fail http://127.0.0.1:8080/test.html); do echo "." && sleep 1; done diff --git a/README.md b/README.md new file mode 100644 index 0000000..f96c9ca --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +[![Build Status](https://travis-ci.org/Gizra/elm-hedley.svg?branch=master)](https://travis-ci.org/Gizra/elm-hedley) + +> elm-hedley + +## Installation + +Make sure the following are installed: + +* NodeJs (and npm) +* Elm (e.g. `npm install -g elm@0.17.0`) +* Compass (for SASS) (`gem update --system && gem install compass`) + +## Usage + +1. Serve locally, and watch file changes: `gulp` +1. Prepare file for publishing (e.g. minify, and rev file names): `gulp publish` +1. Deploy to GitHub's pages (`gh-pages` branch of your repository): `gulp deploy` + +## Unit Tests + +In order to view the tests on the browser Start elm reactor (elm-reactor) and navigate to http://0.0.0.0:8000/src/elm/TestRunner.elm + +## License + +MIT diff --git a/elm-package.json b/elm-package.json new file mode 100644 index 0000000..27bc799 --- /dev/null +++ b/elm-package.json @@ -0,0 +1,21 @@ +{ + "version": "1.0.0", + "summary": "helpful summary of your project, less than 80 characters", + "repository": "https://github.com/Gizra/elm-hedley.git", + "license": "BSD3", + "source-directories": [ + "src/elm" + ], + "exposed-modules": [], + "dependencies": { + "elm-community/elm-test": "1.1.0 <= v < 2.0.0", + "elm-community/json-extra": "1.1.0 <= v < 2.0.0", + "elm-lang/core": "4.0.0 <= v < 5.0.0", + "elm-lang/html": "1.0.0 <= v < 2.0.0", + "elm-lang/navigation": "1.0.0 <= v < 2.0.0", + "evancz/elm-http": "3.0.1 <= v < 4.0.0", + "krisajenkins/remotedata": "2.4.0 <= v < 3.0.0", + "rgrempel/elm-route-url": "2.0.1 <= v < 3.0.0" + }, + "elm-version": "0.17.0 <= v < 0.18.0" +} diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..d7db975 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,227 @@ +// Generated on 2015-05-04 using generator-jekyllized 0.7.3 +"use strict"; + +var gulp = require("gulp"); + +var gulpSequence = require('gulp-sequence'); + +// Loads the plugins without having to list all of them, but you need +// to call them as $.pluginname +var $ = require("gulp-load-plugins")(); +// "del" is used to clean out directories and such +var del = require("del"); +// BrowserSync isn"t a gulp package, and needs to be loaded manually +var browserSync = require("browser-sync"); + +var elm = require('gulp-elm'); + +var fs = require('fs'); + +// merge is used to merge the output from two different streams into the same stream +var merge = require("merge-stream"); +// Need a command for reloading webpages using BrowserSync + +var plumber = require("gulp-plumber"); + +var reload = browserSync.reload; +// And define a variable that BrowserSync uses in its function +var bs; + +var wiredep = require('wiredep').stream; + +// Deletes the directory that is used to serve the site during development +gulp.task("clean:dev", function(cb) { + return del(["serve"], cb); +}); + + +// Deletes the directory that the optimized site is output to +gulp.task("clean:prod", function(cb) { + return del(["dist"], cb); +}); + + +// Compiles the SASS files and moves them into the "assets/stylesheets" directory +gulp.task("styles", function () { + // Looks at the style.scss file for what to include and creates a style.css file + return gulp.src("src/assets/scss/style.scss") + .pipe(plumber()) + .pipe($.sass()) + .on('error', function(err){ + browserSync.notify("SASS error"); + + console.error(err.message); + + // Save the error to index.html, with a simple HTML wrapper + // so browserSync can inject itself in. + fs.writeFileSync('serve/index.html', "
" + err.message + "
"); + + // No need to continue processing. + this.emit('end'); + }) + // AutoPrefix your CSS so it works between browsers + .pipe($.autoprefixer("last 1 version", { cascade: true })) + // Directory your CSS file goes to + .pipe(gulp.dest("serve/assets/stylesheets/")) + // Outputs the size of the CSS file + .pipe($.size({title: "styles"})) + // Injects the CSS changes to your browser since Jekyll doesn"t rebuild the CSS + .pipe(reload({stream: true})); +}); + +// Optimizes the images that exists +gulp.task("images", function () { + return gulp.src("src/assets/images/**") + .pipe($.changed("dist/assets/images")) + .pipe($.imagemin({ + // Lossless conversion to progressive JPGs + progressive: true, + // Interlace GIFs for progressive rendering + interlaced: true + })) + .pipe(gulp.dest("dist/assets/images")) + .pipe($.size({title: "images"})); +}); + +// Copy over fonts to the "dist" directory +gulp.task("fonts", function () { + return gulp.src("src/assets/fonts/**") + .pipe(gulp.dest("dist/assets/fonts")) + .pipe($.size({ title: "fonts" })); +}); + +// Copy index.html and CNAME files to the "serve" directory +gulp.task("copy:dev", ["copy:bower"], function () { + return gulp.src(["src/index.html", "src/CNAME", "src/js/**/*", "src/assets/images/**/*"]) + .pipe(gulp.dest("serve")) + .pipe($.size({ title: "index.html & CNAME" })) +}); + +// Copy bower. +gulp.task("copy:bower", function () { + return gulp.src(["bower_components/**/*"]) + .pipe(gulp.dest("serve/bower_components")) + .pipe($.size({ title: "Bower" })) +}); + +// Copy images. +gulp.task("copy:images", function () { + return gulp.src([]) + .pipe(gulp.dest("serve/assets/images")) + .pipe($.size({ title: "Assets images" })) +}); + + +gulp.task("cname", function () { + return gulp.src(["serve/CNAME"]) + .pipe(gulp.dest("dist")) + .pipe($.size({ title: "CNAME" })) +}); + +gulp.task('bower', function () { + gulp.src("src/index.html") + .pipe(wiredep()) + .pipe(gulp.dest("serve")); +}); + + +// Optimizes all the CSS, HTML and concats the JS etc +gulp.task("minify", ["styles"], function () { + var assets = $.useref.assets({searchPath: "serve"}); + + return gulp.src("serve/**/*.*") + // Concatenate JavaScript files and preserve important comments + .pipe($.if("*.js", $.uglify({preserveComments: "some"}))) + // Minify CSS + .pipe($.if("*.css", $.minifyCss())) + // Start cache busting the files + .pipe($.revAll({ ignore: ["index.html", ".eot", ".svg", ".ttf", ".woff"] })) + .pipe(assets.restore()) + // Replace the asset names with their cache busted names + .pipe($.revReplace()) + // Minify HTML + .pipe($.if("*.html", $.htmlmin({ + removeComments: true, + removeCommentsFromCDATA: true, + removeCDATASectionsFromCDATA: true, + collapseWhitespace: true, + collapseBooleanAttributes: true, + removeAttributeQuotes: true, + removeRedundantAttributes: true + }))) + // Send the output to the correct folder + .pipe(gulp.dest("dist")) + .pipe($.size({title: "optimizations"})); +}); + + +// Task to upload your site to your GH Pages repo +gulp.task("deploy", [], function () { + // Deploys your optimized site, you can change the settings in the html task if you want to + return gulp.src("dist/**/*") + .pipe($.ghPages({branch: "gh-pages"})); +}); + +gulp.task('elm-init', elm.init); +gulp.task('elm', ['elm-init'], function(){ + return gulp.src('src/elm/Main.elm') + .pipe(plumber()) + .pipe(elm()) + .on('error', function(err) { + console.error(err.message); + + browserSync.notify("Elm compile error", 5000); + + // Save the error to index.html, with a simple HTML wrapper + // so browserSync can inject itself in. + fs.writeFileSync('serve/index.html', "
" + err.message + "
"); + }) + .pipe(gulp.dest('serve')); +}); + +// BrowserSync will serve our site on a local server for us and other devices to use +// It will also autoreload across all devices as well as keep the viewport synchronized +// between them. +gulp.task("serve:dev", ["build"], function () { + bs = browserSync({ + notify: true, + // tunnel: "", + server: { + baseDir: "serve" + } + }); +}); + + +// These tasks will look for files that change while serving and will auto-regenerate or +// reload the website accordingly. Update or add other files you need to be watched. +gulp.task("watch", function () { + // We need to copy dev, so index.html may be replaced by error messages. + gulp.watch(["src/index.html", "src/js/**/*.js"], ["copy:dev", reload]); + gulp.watch(["src/elm/**/*.elm"], ["elm", "copy:dev", reload]); + gulp.watch(["src/assets/scss/**/*.scss"], ["styles", "copy:dev", reload]); +}); + +// Serve the site after optimizations to see that everything looks fine +gulp.task("serve:prod", function () { + bs = browserSync({ + notify: false, + // tunnel: true, + server: { + baseDir: "dist" + } + }); +}); + +// Default task, run when just writing "gulp" in the terminal +gulp.task("default", ["serve:dev", "watch"]); + +// Builds the site but doesnt serve it to you +// @todo: Add "bower" here +gulp.task("build", gulpSequence("clean:dev", ["styles", "copy:dev", "elm"])); + +// Builds your site with the "build" command and then runs all the optimizations on +// it and outputs it to "./dist" +gulp.task("publish", ["build", "clean:prod"], function () { + gulp.start("minify", "cname", "images", "fonts"); +}); diff --git a/package.json b/package.json new file mode 100644 index 0000000..69a6f5f --- /dev/null +++ b/package.json @@ -0,0 +1,43 @@ +{ + "name": "generated-elm", + "private": false, + "version": "0.1.0", + "description": "Generated elm", + "dependencies": {}, + "devDependencies": { + "browser-sync": "1.9.2", + "del": "1.2.1", + "gulp": "3.9.1", + "gulp-autoprefixer": "2.3.1", + "gulp-cache": "0.2.10", + "gulp-cached": "1.0.1", + "gulp-changed": "1.0.0", + "gulp-elm": "0.4.1", + "gulp-filter": "2.0.2", + "gulp-gh-pages": "0.4.0", + "gulp-gzip": "0.0.8", + "gulp-htmlmin": "0.2.0", + "gulp-if": "1.2.5", + "gulp-imagemin": "2.3.0", + "gulp-jshint": "1.11.2", + "gulp-load-plugins": "0.8.1", + "gulp-minify-css": "0.3.13", + "gulp-plumber": "1.0.1", + "gulp-rev-all": "0.7.6", + "gulp-rev-replace": "0.3.4", + "gulp-sass": "2.1.0", + "gulp-sequence": "0.4.1", + "gulp-shell": "0.2.11", + "gulp-size": "1.3.0", + "gulp-uglify": "1.4.1", + "gulp-uncss": "0.5.2", + "gulp-useref": "1.3.0", + "jshint-stylish": "1.0.2", + "merge-stream": "0.1.8", + "wiredep": "2.2.2" + }, + "engines": { + "node": ">0.10.0" + }, + "scripts": {} +} diff --git a/runTests.js b/runTests.js new file mode 100644 index 0000000..a57cb6e --- /dev/null +++ b/runTests.js @@ -0,0 +1,18 @@ +var url = 'http://127.0.0.1:8080/test.html'; + +casper.options.waitTimeout = 60000; + +casper.test.begin('Run the Elm tests', function suite(test) { + casper.start(url).then(function() { + // The test runner doesn't provide a class, so we have to do this query + // selector. + casper.waitForSelector('pre', function() { + test.assertSelectorHasText('pre', 'All tests passed'); + }); + + }); + + casper.run(function() { + test.done(); + }); +}); diff --git a/src/assets/scss/style.scss b/src/assets/scss/style.scss new file mode 100644 index 0000000..b27d7e2 --- /dev/null +++ b/src/assets/scss/style.scss @@ -0,0 +1,7 @@ +body { + padding: 20px; + + .container { + padding: 20px; + } +} diff --git a/src/elm/App/Model.elm b/src/elm/App/Model.elm new file mode 100644 index 0000000..c112deb --- /dev/null +++ b/src/elm/App/Model.elm @@ -0,0 +1,34 @@ +module App.Model exposing (emptyModel, Model, Page(..)) + +import Config.Model exposing (Model) +import RemoteData exposing (RemoteData(..), WebData) +import User.Model exposing (..) +import Pages.Counter.Model exposing (emptyModel, Model) +import Pages.Login.Model exposing (emptyModel, Model) + + +type Page + = AccessDenied + | Counter + | Login + | MyAccount + | PageNotFound + + +type alias Model = + { activePage : Page + , config : RemoteData String Config.Model.Model + , pageCounter : Pages.Counter.Model.Model + , pageLogin : Pages.Login.Model.Model + , user : WebData User + } + + +emptyModel : Model +emptyModel = + { activePage = Counter + , config = NotAsked + , pageCounter = Pages.Counter.Model.emptyModel + , pageLogin = Pages.Login.Model.emptyModel + , user = NotAsked + } diff --git a/src/elm/App/Router.elm b/src/elm/App/Router.elm new file mode 100644 index 0000000..f654455 --- /dev/null +++ b/src/elm/App/Router.elm @@ -0,0 +1,68 @@ +module App.Router exposing (delta2url, location2messages) + +import App.Model exposing (..) +import App.Update exposing (..) +import Config exposing (configs) +import Dict exposing (..) +import Navigation exposing (Location) +import RouteUrl exposing (HistoryEntry(..), UrlChange) + + +delta2url : Model -> Model -> Maybe UrlChange +delta2url previous current = + case current.activePage of + AccessDenied -> + Nothing + + Counter -> + Just <| UrlChange NewEntry "/#counter" + + Login -> + Just <| UrlChange NewEntry "/#login" + + MyAccount -> + Just <| UrlChange NewEntry "/#my-account" + + PageNotFound -> + Just <| UrlChange NewEntry "/#404" + + +location2messages : Location -> List Msg +location2messages location = + let + cmd = + case location.hash of + "" -> + [] + + "#counter" -> + [ SetActivePage Counter ] + + "#login" -> + [ SetActivePage Login ] + + "#my-account" -> + [ SetActivePage MyAccount ] + + "#404" -> + [ SetActivePage PageNotFound ] + + _ -> + [ SetActivePage PageNotFound ] + in + getConfigFromLocation location :: cmd + + + +-- @todo: We calcualte the config over and over again. It's not expensive +-- but redundent. + + +getConfigFromLocation : Location -> Msg +getConfigFromLocation location = + case (Dict.get location.hostname configs) of + Just val -> + SetConfig val + + Nothing -> + SetConfigError diff --git a/src/elm/App/Test.elm b/src/elm/App/Test.elm new file mode 100644 index 0000000..b65598b --- /dev/null +++ b/src/elm/App/Test.elm @@ -0,0 +1,50 @@ +module App.Test exposing (all) + +import ElmTest exposing (..) +import RemoteData exposing (RemoteData(..)) +import App.Model exposing (..) +import App.Update exposing (..) + + +setActivePage : Test +setActivePage = + suite "SetActivePage msg" + [ test "set new active page" + (assertEqual PageNotFound (getPageAsAnonymous PageNotFound)) + , test "set Login page for anonymous user" + (assertEqual Login (getPageAsAnonymous Login)) + , test "set My account page for anonymous user" + (assertEqual AccessDenied (getPageAsAnonymous MyAccount)) + , test "set Login page for authenticated user" + (assertEqual AccessDenied (getPageAsAuthenticated Login)) + , test "set My account page for authenticated user" + (assertEqual MyAccount (getPageAsAuthenticated MyAccount)) + ] + + +getPageAsAnonymous : Page -> Page +getPageAsAnonymous page = + update (SetActivePage page) emptyModel + |> fst + |> .activePage + + +getPageAsAuthenticated : Page -> Page +getPageAsAuthenticated page = + let + dummyUser = + { name = Just "Foo", login = "foo", avatarUrl = "https://example.com" } + + model = + { emptyModel | user = Success dummyUser } + in + update (SetActivePage page) model + |> fst + |> .activePage + + +all : Test +all = + suite "App tests" + [ setActivePage + ] diff --git a/src/elm/App/Update.elm b/src/elm/App/Update.elm new file mode 100644 index 0000000..8708569 --- /dev/null +++ b/src/elm/App/Update.elm @@ -0,0 +1,103 @@ +module App.Update exposing (init, update, Msg(..)) + +import App.Model exposing (..) +import Config.Model as Config +import Pages.Counter.Update exposing (Msg) +import Pages.Login.Update exposing (Msg) +import RemoteData exposing (RemoteData(..), WebData) +import User.Model exposing (..) + + +type Msg + = Logout + | PageCounter Pages.Counter.Update.Msg + | PageLogin Pages.Login.Update.Msg + | SetActivePage Page + | SetConfig Config.Model + | SetConfigError + + +init : ( Model, Cmd Msg ) +init = + emptyModel ! [] + + +update : Msg -> Model -> ( Model, Cmd Msg ) +update msg model = + let + backendUrl = + case model.config of + Success config -> + config.backendUrl + + _ -> + "" + in + case msg of + Logout -> + init + + PageCounter msg -> + let + ( val, cmds ) = + Pages.Counter.Update.update msg model.pageCounter + + model' = + { model | pageCounter = val } + in + ( model', Cmd.map PageCounter cmds ) + + PageLogin msg -> + let + ( val, cmds, user ) = + Pages.Login.Update.update backendUrl model.user msg model.pageLogin + + model' = + { model + | pageLogin = val + , user = user + } + + model'' = + case user of + -- If user was successfuly fetched, reditect to my + -- account page. + Success _ -> + update (SetActivePage MyAccount) model' + |> fst + + _ -> + model' + in + ( model'', Cmd.map PageLogin cmds ) + + SetActivePage page -> + { model | activePage = setActivePageAccess model.user page } ! [] + + SetConfig config -> + { model | config = Success config } ! [] + + SetConfigError -> + { model | config = Failure "No config found" } ! [] + + +{-| Determine is a page can be accessed by a user (anonymous or authenticated), +and if not return a access denied page. + +If the user is authenticated, don't allow them to revisit Login page. Do the +opposite for anonumous user - don't allow them to visit the MyAccount page. +-} +setActivePageAccess : WebData User -> Page -> Page +setActivePageAccess user page = + case user of + Success _ -> + if page == Login then + AccessDenied + else + page + + _ -> + if page == MyAccount then + AccessDenied + else + page diff --git a/src/elm/App/View.elm b/src/elm/App/View.elm new file mode 100644 index 0000000..e7f9204 --- /dev/null +++ b/src/elm/App/View.elm @@ -0,0 +1,162 @@ +module App.View exposing (..) + +import Config.View exposing (view) +import Html exposing (..) +import Html.Attributes exposing (class, classList, href, src, style, target) +import Html.App as Html +import Html.Events exposing (onClick) +import App.Model exposing (..) +import App.Update exposing (..) +import User.Model exposing (..) +import Pages.Counter.View exposing (..) +import Pages.Login.View exposing (..) +import Pages.MyAccount.View exposing (..) +import Pages.PageNotFound.View exposing (..) +import RemoteData exposing (RemoteData(..), WebData) + + +view : Model -> Html Msg +view model = + case model.config of + Failure err -> + Config.View.view + + _ -> + div [] + [ div [ class "ui container main" ] + [ viewHeader model + , viewMainContent model + , pre [ class "ui padded secondary segment" ] + [ div [] [ text <| "activePage: " ++ toString model.activePage ] + , div [] [ text <| "pageCounter: " ++ toString model.pageCounter ] + , div [] [ text <| "pageLogin: " ++ toString model.pageLogin ] + , div [] [ text <| "user: " ++ toString model.user ] + , div [] [ text <| "config: " ++ toString model.config ] + ] + ] + , viewFooter + ] + + +viewHeader : Model -> Html Msg +viewHeader model = + let + navbar = + case model.user of + Success _ -> + navbarAuthenticated + + _ -> + navbarAnonymous + in + div [ class "ui secondary pointing menu" ] (navbar model) + + +navbarAnonymous : Model -> List (Html Msg) +navbarAnonymous model = + [ a + [ classByPage Counter model.activePage + , onClick <| SetActivePage Counter + ] + [ text "Counter" ] + , a + [ classByPage Login model.activePage + , onClick <| SetActivePage Login + ] + [ text "Login" ] + , viewPageNotFoundItem model.activePage + ] + + +navbarAuthenticated : Model -> List (Html Msg) +navbarAuthenticated model = + [ a + [ classByPage Counter model.activePage + , onClick <| SetActivePage Counter + ] + [ text "Counter" ] + , a + [ classByPage MyAccount model.activePage + , onClick <| SetActivePage MyAccount + ] + [ text "My Account" ] + , viewPageNotFoundItem model.activePage + , div [ class "right menu" ] + [ viewAvatar model.user + , a + [ class "ui item" + , onClick <| Logout + ] + [ text "Logout" ] + ] + ] + + +viewPageNotFoundItem : Page -> Html Msg +viewPageNotFoundItem activePage = + a + [ classByPage PageNotFound activePage + , onClick <| SetActivePage PageNotFound + ] + [ text "404 page" ] + + +viewAvatar : WebData User -> Html Msg +viewAvatar user = + case user of + Success user' -> + a + [ onClick <| SetActivePage MyAccount + , class "ui item" + ] + [ img + [ class "ui avatar image" + , src user'.avatarUrl + ] + [] + ] + + _ -> + div [] [] + + +viewMainContent : Model -> Html Msg +viewMainContent model = + case model.activePage of + AccessDenied -> + div [] [ text "Access denied" ] + + Counter -> + Html.map PageCounter (Pages.Counter.View.view model.pageCounter) + + Login -> + Html.map PageLogin (Pages.Login.View.view model.user model.pageLogin) + + MyAccount -> + Pages.MyAccount.View.view model.user + + PageNotFound -> + -- We don't need to pass any cmds, so we can call the view directly + Pages.PageNotFound.View.view + + +viewFooter : Html Msg +viewFooter = + div + [ class "ui inverted vertical footer segment form-page" + ] + [ div [ class "ui container" ] + [ div [] [ text "Copyright statement will be here" ] + ] + ] + + +{-| Get menu items classes. This function gets the active page and checks if +it is indeed the page used. +-} +classByPage : Page -> Page -> Attribute a +classByPage page activePage = + classList + [ ( "item", True ) + , ( "active", page == activePage ) + ] diff --git a/src/elm/Config.elm b/src/elm/Config.elm new file mode 100644 index 0000000..a605856 --- /dev/null +++ b/src/elm/Config.elm @@ -0,0 +1,32 @@ +module Config exposing (..) + +import Config.Model as Config exposing (Model) +import Dict exposing (..) +import Time exposing (Time) + + +local : Model +local = + { backendUrl = "https://api.github.com" + , name = "local" + } + + +production : Model +production = + { backendUrl = "https://api.github.com" + , name = "gh-pages" + } + + +configs : Dict String Model +configs = + Dict.fromList + [ ( "localhost", local ) + , ( "example.com", production ) + ] + + +cacheTtl : Time.Time +cacheTtl = + (5 * Time.second) diff --git a/src/elm/Config/Model.elm b/src/elm/Config/Model.elm new file mode 100644 index 0000000..b3af191 --- /dev/null +++ b/src/elm/Config/Model.elm @@ -0,0 +1,11 @@ +module Config.Model exposing (..) + + +type alias BackendUrl = + String + + +type alias Model = + { backendUrl : BackendUrl + , name : String + } diff --git a/src/elm/Config/View.elm b/src/elm/Config/View.elm new file mode 100644 index 0000000..daf759c --- /dev/null +++ b/src/elm/Config/View.elm @@ -0,0 +1,16 @@ +module Config.View exposing (..) + +import Html exposing (div, h2, text, Html) +import Html.Attributes exposing (class) + + +-- A plain function that always returns the error message + + +view : Html msg +view = + div + [ class "config-error" ] + [ h2 [] [ text "Configuration error" ] + , div [] [ text "Check your Config.elm file and make sure you have defined the enviorement properly" ] + ] diff --git a/src/elm/Main.elm b/src/elm/Main.elm new file mode 100644 index 0000000..a193069 --- /dev/null +++ b/src/elm/Main.elm @@ -0,0 +1,28 @@ +module Main exposing (..) + +import App.Model exposing (Model) +import App.Router exposing (..) +import App.Update exposing (init, update, Msg) +import App.View exposing (view) +import RouteUrl + + +main : Program Never +main = + RouteUrl.program + { delta2url = delta2url + , location2messages = location2messages + , init = App.Update.init + , update = App.Update.update + , view = App.View.view + , subscriptions = subscriptions + } + + + +-- SUBSCRIPTIONS + + +subscriptions : Model -> Sub Msg +subscriptions model = + Sub.none diff --git a/src/elm/Pages/Counter/Model.elm b/src/elm/Pages/Counter/Model.elm new file mode 100644 index 0000000..1ae7ca5 --- /dev/null +++ b/src/elm/Pages/Counter/Model.elm @@ -0,0 +1,12 @@ +module Pages.Counter.Model exposing (emptyModel, Model) + +-- MODEL + + +type alias Model = + Int + + +emptyModel : Model +emptyModel = + 0 diff --git a/src/elm/Pages/Counter/Test.elm b/src/elm/Pages/Counter/Test.elm new file mode 100644 index 0000000..7c1ee5b --- /dev/null +++ b/src/elm/Pages/Counter/Test.elm @@ -0,0 +1,36 @@ +module Pages.Counter.Test exposing (..) + +import ElmTest exposing (..) +import Pages.Counter.Model as Counter exposing (emptyModel, Model) +import Pages.Counter.Update as Counter exposing (..) + + +decrementActionSuite : Test +decrementActionSuite = + suite "Decrement action" + [ test "negative count" (assertEqual -2 (updateCounter Counter.Decrement -1)) + , test "zero count" (assertEqual -1 (updateCounter Counter.Decrement 0)) + , test "positive count" (assertEqual 0 (updateCounter Counter.Decrement 1)) + ] + + +incrementActionSuite : Test +incrementActionSuite = + suite "Increment action" + [ test "negative count" (assertEqual 0 (updateCounter Counter.Increment -1)) + , test "zero count" (assertEqual 1 (updateCounter Counter.Increment 0)) + , test "positive count" (assertEqual 2 (updateCounter Counter.Increment 1)) + ] + + +updateCounter : Counter.Msg -> Int -> Counter.Model +updateCounter action initialModel = + fst <| Counter.update action initialModel + + +all : Test +all = + suite "Counter tests" + [ decrementActionSuite + , incrementActionSuite + ] diff --git a/src/elm/Pages/Counter/Update.elm b/src/elm/Pages/Counter/Update.elm new file mode 100644 index 0000000..0fd2395 --- /dev/null +++ b/src/elm/Pages/Counter/Update.elm @@ -0,0 +1,27 @@ +module Pages.Counter.Update exposing (update, Msg(..)) + +import Pages.Counter.Model as Counter exposing (..) + + +init : ( Model, Cmd Msg ) +init = + emptyModel ! [] + + +type Msg + = Decrement + | Increment + + +update : Msg -> Model -> ( Model, Cmd Msg ) +update action model = + case action of + Decrement -> + ( model - 1 + , Cmd.none + ) + + Increment -> + ( model + 1 + , Cmd.none + ) diff --git a/src/elm/Pages/Counter/View.elm b/src/elm/Pages/Counter/View.elm new file mode 100644 index 0000000..0a507a9 --- /dev/null +++ b/src/elm/Pages/Counter/View.elm @@ -0,0 +1,27 @@ +module Pages.Counter.View exposing (view) + +import Html exposing (..) +import Html.Attributes exposing (style) +import Html.Events exposing (onClick) +import Pages.Counter.Model exposing (..) +import Pages.Counter.Update exposing (..) + + +view : Model -> Html Msg +view model = + div [] + [ button [ onClick Decrement ] [ text "-" ] + , div [ countStyle ] [ text (toString model) ] + , button [ onClick Increment ] [ text "+" ] + ] + + +countStyle : Attribute msg +countStyle = + style + [ ( "font-size", "20px" ) + , ( "font-family", "monospace" ) + , ( "display", "inline-block" ) + , ( "width", "50px" ) + , ( "text-align", "center" ) + ] diff --git a/src/elm/Pages/Login/Model.elm b/src/elm/Pages/Login/Model.elm new file mode 100644 index 0000000..456da00 --- /dev/null +++ b/src/elm/Pages/Login/Model.elm @@ -0,0 +1,12 @@ +module Pages.Login.Model exposing (emptyModel, Model) + + +type alias Model = + { login : String + } + + +emptyModel : Model +emptyModel = + { login = "" + } diff --git a/src/elm/Pages/Login/Test.elm b/src/elm/Pages/Login/Test.elm new file mode 100644 index 0000000..3c51e8a --- /dev/null +++ b/src/elm/Pages/Login/Test.elm @@ -0,0 +1,75 @@ +module Pages.Login.Test exposing (all) + +import ElmTest exposing (..) +import RemoteData exposing (RemoteData(..), WebData) +import Pages.Login.Model exposing (..) +import Pages.Login.Update exposing (..) +import User.Model exposing (..) + + +setLogin : Test +setLogin = + suite "SetLogin msg" + [ test "set name without spaces" + (assertEqual "noSpaces" (getLogin "noSpaces")) + , test "set name with space" + (assertEqual "withSpaces" (getLogin "with Spaces")) + , test "set name with multiple spaces" + (assertEqual "withSpaces" (getLogin " with Spaces ")) + , test "set name should result with NotAsked user status if name changed" + (assertEqual NotAsked (getUserStatusAfterSetLogin Loading "someName" emptyModel)) + , test "set name should result with existing user status if name didn't change" + (assertEqual Loading (getUserStatusAfterSetLogin Loading " someName " { login = "someName" })) + ] + + +dummyUser : User +dummyUser = + { name = Just "Foo", login = "foo", avatarUrl = "https://example.com" } + + +getLogin : String -> String +getLogin login = + let + ( model, _, _ ) = + update "https://example.com" NotAsked (SetLogin login) emptyModel + in + model.login + + +getUserStatusAfterSetLogin : WebData User -> String -> Model -> WebData User +getUserStatusAfterSetLogin user login model = + let + ( _, _, user ) = + update "https://example.com" user (SetLogin login) model + in + user + + + +{- Test the returned status after TryLogin msg. -} + + +tryLogin : Test +tryLogin = + suite "TryLogin msg" + [ test "Fetch empty name" + (assertEqual NotAsked (getTryLogin NotAsked { login = "" })) + ] + + +getTryLogin : WebData User -> Model -> WebData User +getTryLogin user model = + let + ( _, _, userStatus ) = + update "https://example.com" user TryLogin model + in + userStatus + + +all : Test +all = + suite "Pages.Login tests" + [ setLogin + , tryLogin + ] diff --git a/src/elm/Pages/Login/Update.elm b/src/elm/Pages/Login/Update.elm new file mode 100644 index 0000000..f04c6b9 --- /dev/null +++ b/src/elm/Pages/Login/Update.elm @@ -0,0 +1,101 @@ +module Pages.Login.Update exposing (update, Msg(..)) + +import Config.Model exposing (BackendUrl) +import Http +import Regex exposing (regex, replace, HowMany(All)) +import String exposing (isEmpty) +import Task +import User.Decoder exposing (..) +import User.Model exposing (..) +import Pages.Login.Model as Login exposing (..) +import RemoteData exposing (RemoteData(..), WebData) + + +type Msg + = FetchFail Http.Error + | FetchSucceed User + | SetLogin String + | TryLogin + + +init : ( Model, Cmd Msg ) +init = + emptyModel ! [] + + +update : BackendUrl -> WebData User -> Msg -> Model -> ( Model, Cmd Msg, WebData User ) +update backendUrl user msg model = + case msg of + FetchSucceed github -> + ( model, Cmd.none, Success github ) + + FetchFail err -> + ( model, Cmd.none, Failure err ) + + SetLogin login -> + let + -- Remove spaces from login. + noSpacesLogin = + replace All (regex " ") (\_ -> "") login + + userStatus = + getUserStatusFromNameChange user model.login noSpacesLogin + in + ( { model | login = noSpacesLogin }, Cmd.none, userStatus ) + + TryLogin -> + let + ( cmd, userStatus ) = + getCmdAndUserStatusForTryLogin backendUrl user model.login + in + ( model, cmd, userStatus ) + + +{-| Try to fetch the user from GitHub only if it was not asked yet. +In case we are still loading, error or a succesful fetch we don't want to repeat +it. +-} +getCmdAndUserStatusForTryLogin : BackendUrl -> WebData User -> String -> ( Cmd Msg, WebData User ) +getCmdAndUserStatusForTryLogin backendUrl user login = + case user of + NotAsked -> + if isEmpty login then + -- login was not asked, however it is empty. + ( Cmd.none, NotAsked ) + else + -- Fetch the login from GitHub, and indicate we are + -- in the middle of "Loading". + ( fetchFromGitHub backendUrl login, Loading ) + + _ -> + -- We are not in "NotAsked" state, so return the existing + -- value + ( Cmd.none, user ) + + +{-| Determine if the user status should change after setting a new name. +When there is a valid name change, status should change to NotAsked. +However if for example a user just tried to add a space to the name, so after +triming it's actually the same. Thus, we avoid changing the user status to +prevent from re-fetching a possibly wrong name. +For example, if the user status would have been Failure, the existing name is +"foo" and user tried to pass "foo " (notice the trailing space), then in fact no +change should happen. +-} +getUserStatusFromNameChange : WebData User -> String -> String -> WebData User +getUserStatusFromNameChange user currentName newName = + if currentName == newName then + user + else + NotAsked + + +{-| Get data from GitHub. +-} +fetchFromGitHub : BackendUrl -> String -> Cmd Msg +fetchFromGitHub backendUrl login = + let + url = + backendUrl ++ "/users/" ++ login + in + Task.perform FetchFail FetchSucceed (Http.get decodeFromGithub url) diff --git a/src/elm/Pages/Login/View.elm b/src/elm/Pages/Login/View.elm new file mode 100644 index 0000000..426cbf5 --- /dev/null +++ b/src/elm/Pages/Login/View.elm @@ -0,0 +1,58 @@ +module Pages.Login.View exposing (view) + +import RemoteData exposing (RemoteData(..), WebData) +import Html exposing (..) +import Html.Attributes exposing (..) +import Html.Events exposing (onClick, onInput, onSubmit) +import User.Model exposing (..) +import Pages.Login.Model exposing (..) +import Pages.Login.Update exposing (..) + + +view : WebData User -> Model -> Html Msg +view user model = + let + spinner = + i [ class "notched circle loading icon" ] [] + + ( isLoading, isError ) = + case user of + Loading -> + ( True, False ) + + Failure _ -> + ( False, True ) + + _ -> + ( False, False ) + + inputClasses = + classList + [ ( "ui action input", True ) + , ( "error", isError ) + ] + in + Html.form + [ onSubmit TryLogin + , action "javascript:void(0);" + , class "ui stacked segment" + ] + [ div [ inputClasses ] + [ input + [ type' "text" + , placeholder "Github name" + , onInput SetLogin + , value model.login + ] + [] + -- Submit button + , button + [ onClick TryLogin + , disabled (isLoading || isError) + , class "ui primary button" + ] + [ span [ hidden <| not isLoading ] [ spinner ] + , span [ hidden isLoading ] [ text "Login" ] + ] + ] + ] diff --git a/src/elm/Pages/MyAccount/View.elm b/src/elm/Pages/MyAccount/View.elm new file mode 100644 index 0000000..472227a --- /dev/null +++ b/src/elm/Pages/MyAccount/View.elm @@ -0,0 +1,38 @@ +module Pages.MyAccount.View exposing (view) + +import RemoteData exposing (RemoteData(..), WebData) +import Html exposing (a, div, h2, i, p, text, img, Html) +import Html.Attributes exposing (class, href, src) +import User.Model exposing (..) + + +-- VIEW + + +view : WebData User -> Html a +view user = + let + ( name, login, avatar ) = + case user of + Success val -> + let + name' = + case val.name of + Just name -> + name + + Nothing -> + val.login + in + ( name', val.login, img [ src val.avatarUrl ] [] ) + + _ -> + ( "", "", div [] [] ) + in + div [ class "ui centered card" ] + [ div [ class "image" ] [ avatar ] + , div [ class "content" ] + [ div [ class "header" ] [ text <| "Welcome " ++ name ] + , div [ class "meta" ] [ text <| "@" ++ login ] + ] + ] diff --git a/src/elm/Pages/PageNotFound/View.elm b/src/elm/Pages/PageNotFound/View.elm new file mode 100644 index 0000000..8576698 --- /dev/null +++ b/src/elm/Pages/PageNotFound/View.elm @@ -0,0 +1,14 @@ +module Pages.PageNotFound.View exposing (view) + +import Html exposing (a, div, h2, text, Html) +import Html.Attributes exposing (class, href) + + +-- VIEW + + +view : Html a +view = + div [ class "ui segment center aligned" ] + [ h2 [] [ text "This is a 404 page!" ] + ] diff --git a/src/elm/TestRunner.elm b/src/elm/TestRunner.elm new file mode 100644 index 0000000..1cb3a4d --- /dev/null +++ b/src/elm/TestRunner.elm @@ -0,0 +1,20 @@ +module Main exposing (..) + +import ElmTest exposing (..) +import App.Test as App exposing (..) +import Pages.Counter.Test as Counter exposing (..) +import Pages.Login.Test as Login exposing (..) + + +allTests : Test +allTests = + suite "All tests" + [ App.all + , Counter.all + , Login.all + ] + + +main : Program Never +main = + runSuiteHtml allTests diff --git a/src/elm/User/Decoder.elm b/src/elm/User/Decoder.elm new file mode 100644 index 0000000..2c3f1c0 --- /dev/null +++ b/src/elm/User/Decoder.elm @@ -0,0 +1,13 @@ +module User.Decoder exposing (decodeFromGithub) + +import Json.Decode exposing ((:=)) +import Json.Decode.Extra exposing ((|:)) +import User.Model exposing (..) + + +decodeFromGithub : Json.Decode.Decoder User +decodeFromGithub = + Json.Decode.succeed User + |: ("avatar_url" := Json.Decode.string) + |: ("login" := Json.Decode.string) + |: ("name" := Json.Decode.maybe Json.Decode.string) diff --git a/src/elm/User/Model.elm b/src/elm/User/Model.elm new file mode 100644 index 0000000..9fdacaf --- /dev/null +++ b/src/elm/User/Model.elm @@ -0,0 +1,11 @@ +module User.Model exposing (..) + + +type alias User = + { avatarUrl : String + , login : + String + -- In GitHub user might not have a name, just the login handler, so this + -- is a "Maybe" value. + , name : Maybe String + } diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..edd08c4 --- /dev/null +++ b/src/index.html @@ -0,0 +1,20 @@ + + + + + + Elm + + + + + + + + + + + + diff --git a/src/js/README.md b/src/js/README.md new file mode 100644 index 0000000..b9dfb1e --- /dev/null +++ b/src/js/README.md @@ -0,0 +1 @@ +Place JS, and JS-inerop files in this folder. From 34b763abd4ae0808650aa2bab1e7d1aa479432d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hern=C3=A1ndez?= Date: Wed, 9 Nov 2016 18:21:22 +0100 Subject: [PATCH 06/10] Updates README.md --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f96c9ca..16e949b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,10 @@ [![Build Status](https://travis-ci.org/Gizra/elm-hedley.svg?branch=master)](https://travis-ci.org/Gizra/elm-hedley) -> elm-hedley +# elm-hedley + +An Elm single page application. The server side code is [here](https://github.com/Gizra/hedley-server). + +[Read more](http://www.gizra.com/content/elm-hedley-overview/) about this project. ## Installation @@ -13,8 +17,6 @@ Make sure the following are installed: ## Usage 1. Serve locally, and watch file changes: `gulp` -1. Prepare file for publishing (e.g. minify, and rev file names): `gulp publish` -1. Deploy to GitHub's pages (`gh-pages` branch of your repository): `gulp deploy` ## Unit Tests @@ -22,4 +24,4 @@ In order to view the tests on the browser Start elm reactor (elm-reactor) and na ## License -MIT +BSD3 From 954272ad55f3223ca4556d68dfe4421c76526ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hern=C3=A1ndez?= Date: Wed, 9 Nov 2016 18:32:05 +0100 Subject: [PATCH 07/10] Removes Counter page. --- src/elm/Pages/Counter/Model.elm | 12 ----------- src/elm/Pages/Counter/Test.elm | 36 -------------------------------- src/elm/Pages/Counter/Update.elm | 27 ------------------------ src/elm/Pages/Counter/View.elm | 27 ------------------------ 4 files changed, 102 deletions(-) delete mode 100644 src/elm/Pages/Counter/Model.elm delete mode 100644 src/elm/Pages/Counter/Test.elm delete mode 100644 src/elm/Pages/Counter/Update.elm delete mode 100644 src/elm/Pages/Counter/View.elm diff --git a/src/elm/Pages/Counter/Model.elm b/src/elm/Pages/Counter/Model.elm deleted file mode 100644 index 1ae7ca5..0000000 --- a/src/elm/Pages/Counter/Model.elm +++ /dev/null @@ -1,12 +0,0 @@ -module Pages.Counter.Model exposing (emptyModel, Model) - --- MODEL - - -type alias Model = - Int - - -emptyModel : Model -emptyModel = - 0 diff --git a/src/elm/Pages/Counter/Test.elm b/src/elm/Pages/Counter/Test.elm deleted file mode 100644 index 7c1ee5b..0000000 --- a/src/elm/Pages/Counter/Test.elm +++ /dev/null @@ -1,36 +0,0 @@ -module Pages.Counter.Test exposing (..) - -import ElmTest exposing (..) -import Pages.Counter.Model as Counter exposing (emptyModel, Model) -import Pages.Counter.Update as Counter exposing (..) - - -decrementActionSuite : Test -decrementActionSuite = - suite "Decrement action" - [ test "negative count" (assertEqual -2 (updateCounter Counter.Decrement -1)) - , test "zero count" (assertEqual -1 (updateCounter Counter.Decrement 0)) - , test "positive count" (assertEqual 0 (updateCounter Counter.Decrement 1)) - ] - - -incrementActionSuite : Test -incrementActionSuite = - suite "Increment action" - [ test "negative count" (assertEqual 0 (updateCounter Counter.Increment -1)) - , test "zero count" (assertEqual 1 (updateCounter Counter.Increment 0)) - , test "positive count" (assertEqual 2 (updateCounter Counter.Increment 1)) - ] - - -updateCounter : Counter.Msg -> Int -> Counter.Model -updateCounter action initialModel = - fst <| Counter.update action initialModel - - -all : Test -all = - suite "Counter tests" - [ decrementActionSuite - , incrementActionSuite - ] diff --git a/src/elm/Pages/Counter/Update.elm b/src/elm/Pages/Counter/Update.elm deleted file mode 100644 index 0fd2395..0000000 --- a/src/elm/Pages/Counter/Update.elm +++ /dev/null @@ -1,27 +0,0 @@ -module Pages.Counter.Update exposing (update, Msg(..)) - -import Pages.Counter.Model as Counter exposing (..) - - -init : ( Model, Cmd Msg ) -init = - emptyModel ! [] - - -type Msg - = Decrement - | Increment - - -update : Msg -> Model -> ( Model, Cmd Msg ) -update action model = - case action of - Decrement -> - ( model - 1 - , Cmd.none - ) - - Increment -> - ( model + 1 - , Cmd.none - ) diff --git a/src/elm/Pages/Counter/View.elm b/src/elm/Pages/Counter/View.elm deleted file mode 100644 index 0a507a9..0000000 --- a/src/elm/Pages/Counter/View.elm +++ /dev/null @@ -1,27 +0,0 @@ -module Pages.Counter.View exposing (view) - -import Html exposing (..) -import Html.Attributes exposing (style) -import Html.Events exposing (onClick) -import Pages.Counter.Model exposing (..) -import Pages.Counter.Update exposing (..) - - -view : Model -> Html Msg -view model = - div [] - [ button [ onClick Decrement ] [ text "-" ] - , div [ countStyle ] [ text (toString model) ] - , button [ onClick Increment ] [ text "+" ] - ] - - -countStyle : Attribute msg -countStyle = - style - [ ( "font-size", "20px" ) - , ( "font-family", "monospace" ) - , ( "display", "inline-block" ) - , ( "width", "50px" ) - , ( "text-align", "center" ) - ] From 8873ca44f9cec32820e803e653f4964a437422cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hern=C3=A1ndez?= Date: Wed, 9 Nov 2016 18:32:18 +0100 Subject: [PATCH 08/10] Adds the model for the Login --- src/elm/Pages/Login/Model.elm | 39 +++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/elm/Pages/Login/Model.elm b/src/elm/Pages/Login/Model.elm index 456da00..a2d5559 100644 --- a/src/elm/Pages/Login/Model.elm +++ b/src/elm/Pages/Login/Model.elm @@ -1,12 +1,47 @@ module Pages.Login.Model exposing (emptyModel, Model) +import Http + + +type alias AccessToken = + String + + +type alias LoginForm = + { name : String + , pass : String + } + + +type UserMessage + = None + | Error String + + +type Status + = Init + | Fetching + | Fetched + | HttpError Http.Error + type alias Model = - { login : String + { accessToken : AccessToken + , hasAccessTokenInStorage : Bool + , loginForm : LoginForm + , status : Status + , userMessage : UserMessage } emptyModel : Model emptyModel = - { login = "" + { accessToken = + "" + -- We start by assuming there's already an access token it the localStorage. + -- While this property is set to True, the login form will not appear. + , hasAccessTokenInStorage = True + , loginForm = LoginForm "demo" "1234" + , status = Init + , userMessage = None } From cf09ffaf3d6a38ca1a0d1240e5e4054cb8b049a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Hern=C3=A1ndez?= Date: Thu, 10 Nov 2016 18:13:52 +0100 Subject: [PATCH 09/10] Removes references from the old counter module from the App files --- src/elm/App/Model.elm | 6 +----- src/elm/App/Router.elm | 6 ------ src/elm/App/Update.elm | 12 ------------ src/elm/App/View.elm | 15 --------------- 4 files changed, 1 insertion(+), 38 deletions(-) diff --git a/src/elm/App/Model.elm b/src/elm/App/Model.elm index c112deb..9dbb1e2 100644 --- a/src/elm/App/Model.elm +++ b/src/elm/App/Model.elm @@ -3,13 +3,11 @@ module App.Model exposing (emptyModel, Model, Page(..)) import Config.Model exposing (Model) import RemoteData exposing (RemoteData(..), WebData) import User.Model exposing (..) -import Pages.Counter.Model exposing (emptyModel, Model) import Pages.Login.Model exposing (emptyModel, Model) type Page = AccessDenied - | Counter | Login | MyAccount | PageNotFound @@ -18,7 +16,6 @@ type Page type alias Model = { activePage : Page , config : RemoteData String Config.Model.Model - , pageCounter : Pages.Counter.Model.Model , pageLogin : Pages.Login.Model.Model , user : WebData User } @@ -26,9 +23,8 @@ type alias Model = emptyModel : Model emptyModel = - { activePage = Counter + { activePage = Login , config = NotAsked - , pageCounter = Pages.Counter.Model.emptyModel , pageLogin = Pages.Login.Model.emptyModel , user = NotAsked } diff --git a/src/elm/App/Router.elm b/src/elm/App/Router.elm index f654455..e0feee2 100644 --- a/src/elm/App/Router.elm +++ b/src/elm/App/Router.elm @@ -14,9 +14,6 @@ delta2url previous current = AccessDenied -> Nothing - Counter -> - Just <| UrlChange NewEntry "/#counter" - Login -> Just <| UrlChange NewEntry "/#login" @@ -35,9 +32,6 @@ location2messages location = "" -> [] - "#counter" -> - [ SetActivePage Counter ] - "#login" -> [ SetActivePage Login ] diff --git a/src/elm/App/Update.elm b/src/elm/App/Update.elm index 8708569..05b7a8f 100644 --- a/src/elm/App/Update.elm +++ b/src/elm/App/Update.elm @@ -2,7 +2,6 @@ module App.Update exposing (init, update, Msg(..)) import App.Model exposing (..) import Config.Model as Config -import Pages.Counter.Update exposing (Msg) import Pages.Login.Update exposing (Msg) import RemoteData exposing (RemoteData(..), WebData) import User.Model exposing (..) @@ -10,7 +9,6 @@ import User.Model exposing (..) type Msg = Logout - | PageCounter Pages.Counter.Update.Msg | PageLogin Pages.Login.Update.Msg | SetActivePage Page | SetConfig Config.Model @@ -37,16 +35,6 @@ update msg model = Logout -> init - PageCounter msg -> - let - ( val, cmds ) = - Pages.Counter.Update.update msg model.pageCounter - - model' = - { model | pageCounter = val } - in - ( model', Cmd.map PageCounter cmds ) - PageLogin msg -> let ( val, cmds, user ) = diff --git a/src/elm/App/View.elm b/src/elm/App/View.elm index e7f9204..f6310c4 100644 --- a/src/elm/App/View.elm +++ b/src/elm/App/View.elm @@ -8,7 +8,6 @@ import Html.Events exposing (onClick) import App.Model exposing (..) import App.Update exposing (..) import User.Model exposing (..) -import Pages.Counter.View exposing (..) import Pages.Login.View exposing (..) import Pages.MyAccount.View exposing (..) import Pages.PageNotFound.View exposing (..) @@ -28,7 +27,6 @@ view model = , viewMainContent model , pre [ class "ui padded secondary segment" ] [ div [] [ text <| "activePage: " ++ toString model.activePage ] - , div [] [ text <| "pageCounter: " ++ toString model.pageCounter ] , div [] [ text <| "pageLogin: " ++ toString model.pageLogin ] , div [] [ text <| "user: " ++ toString model.user ] , div [] [ text <| "config: " ++ toString model.config ] @@ -55,11 +53,6 @@ viewHeader model = navbarAnonymous : Model -> List (Html Msg) navbarAnonymous model = [ a - [ classByPage Counter model.activePage - , onClick <| SetActivePage Counter - ] - [ text "Counter" ] - , a [ classByPage Login model.activePage , onClick <| SetActivePage Login ] @@ -71,11 +64,6 @@ navbarAnonymous model = navbarAuthenticated : Model -> List (Html Msg) navbarAuthenticated model = [ a - [ classByPage Counter model.activePage - , onClick <| SetActivePage Counter - ] - [ text "Counter" ] - , a [ classByPage MyAccount model.activePage , onClick <| SetActivePage MyAccount ] @@ -126,9 +114,6 @@ viewMainContent model = AccessDenied -> div [] [ text "Access denied" ] - Counter -> - Html.map PageCounter (Pages.Counter.View.view model.pageCounter) - Login -> Html.map PageLogin (Pages.Login.View.view model.user model.pageLogin) From 29f603d51093803bd71f0a19f4d0188c38c21176 Mon Sep 17 00:00:00 2001 From: David Hernandez Date: Sun, 27 Nov 2016 09:01:14 +0100 Subject: [PATCH 10/10] Upgrade elm version on elm-package.json and upgrade the vendor libraries. --- elm-package.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/elm-package.json b/elm-package.json index 27bc799..0ef75da 100644 --- a/elm-package.json +++ b/elm-package.json @@ -8,14 +8,14 @@ ], "exposed-modules": [], "dependencies": { - "elm-community/elm-test": "1.1.0 <= v < 2.0.0", - "elm-community/json-extra": "1.1.0 <= v < 2.0.0", - "elm-lang/core": "4.0.0 <= v < 5.0.0", - "elm-lang/html": "1.0.0 <= v < 2.0.0", - "elm-lang/navigation": "1.0.0 <= v < 2.0.0", - "evancz/elm-http": "3.0.1 <= v < 4.0.0", - "krisajenkins/remotedata": "2.4.0 <= v < 3.0.0", + "elm-community/elm-test": "3.1.0 <= v < 4.0.0", + "elm-community/json-extra": "2.0.0 <= v < 3.0.0", + "elm-lang/core": "5.0.0 <= v < 6.0.0", + "elm-lang/html": "2.0.0 <= v < 3.0.0", + "elm-lang/navigation": "2.0.1 <= v < 3.0.0", + "elm-lang/elm-http": "1.0.0 <= v < 2.0.0", + "krisajenkins/remotedata": "4.0.1 <= v < 5.0.0", "rgrempel/elm-route-url": "2.0.1 <= v < 3.0.0" }, - "elm-version": "0.17.0 <= v < 0.18.0" + "elm-version": "0.18.0 <= v < 0.19.0" }