Split Login component into its own module.
[?]
Jan 22, 2016, 4:37 AM
EA5BFM5GMM7KNMDLTVOSUKVKMSIDD72TAFVHDVGEOUY5VELECU3QCDependencies
- [2]
HO2PFRABClient login now handles response correctly. - [3]
ARX7SHY5Begin work on login UI. - [4]
RB2ETNIFAdd skeletal PureScript client project.
Change contents
- file addition: Aftok[3.393]
- file addition: Login.purs[0.1]
module Aftok.Login whereimport Preludeimport Control.Monad.Aff (Aff())import Data.Maybe (Maybe(..))import Data.Functor (($>))import Halogenimport Halogen.HTML.Core (className)import qualified Halogen.HTML.Indexed as Himport qualified Halogen.HTML.Events.Indexed as Eimport qualified Halogen.HTML.Properties.Indexed as Pimport Network.HTTP.Affjax (AJAX(), affjax)import Network.HTTP.Methodimport Network.HTTP.StatusCodetype LoginState = { username :: String, password :: String }initialState :: LoginStateinitialState = { username: "", password: "" }-- | The component query algebra.data LoginAction a= SetUsername String a| SetPassword String a| Login String String a-- | The effects used in the login component.type LoginEffects eff = HalogenEffects (ajax :: AJAX | eff)-- | The definition for the app's main UI component.ui :: forall eff. Component LoginState LoginAction (Aff (LoginEffects eff))ui = component render evalwhererender :: LoginState -> ComponentHTML LoginActionrender st =H.div[ P.classes (className <$> ["panel", "panel-primary"]) ][ H.div[ P.classes [ className "panel-heading" ] ][ H.h3 [ P.classes [ className "panel-title" ]] [ H.text "Aftok Login" ] ], H.div[ P.classes [ className "panel-body" ] ][H.h2_[ H.text "username:" ], H.p_[ H.input[ P.value st.username, P.inputType P.InputText, E.onValueInput (E.input SetUsername)]], H.h2_[ H.text "password:" ], H.p_[ H.input[ P.value st.password, P.inputType P.InputPassword, E.onValueInput (E.input SetPassword)]], H.p_[ H.button[ P.classes (className <$> ["btn", "btn-primary"]), E.onClick (E.input_ (Login st.username st.password))][ H.text "Login" ]]]]eval :: Natural LoginAction (ComponentDSL LoginState LoginAction (Aff (LoginEffects eff)))eval (SetUsername user next) = modify (_ { username = user }) $> nexteval (SetPassword pass next) = modify (_ { password = pass }) $> nexteval (Login user pass next) = doresult <- liftAff' (login user pass)pure nextdata LoginResponse= OK| Forbidden| Error { status :: StatusCode, message :: String }-- | Post credentials to the login service and interpret the responselogin :: forall eff. String -> String -> Aff (ajax :: AJAX | eff) LoginResponselogin user pass = doresult <- affjax $ { method: POST, url: "/login", headers: [], content: Nothing :: Maybe String, username: Just user, password: Just pass}pure $ case result.status ofStatusCode 403 -> ForbiddenStatusCode 200 -> OKother -> Error { status: other , message: result.response } - edit in client/src/Main.purs at line 5
--import Control.Alt ((<|>))import Control.Monad.Aff (Aff(), runAff) - replacement in client/src/Main.purs at line 7
import Control.Monad.Eff.Console (CONSOLE(), log)import Control.Monad.Eff.Console (CONSOLE())import Control.Monad.Aff (runAff) - edit in client/src/Main.purs at line 10[3.647]→[2.914:978](∅→∅),[2.978]→[3.679:712](∅→∅),[3.679]→[3.679:712](∅→∅),[3.712]→[2.979:1018](∅→∅),[2.1018]→[3.749:776](∅→∅),[3.749]→[3.749:776](∅→∅),[3.776]→[2.1019:1053](∅→∅),[2.1053]→[3.776:809](∅→∅),[3.776]→[3.776:809](∅→∅)
import Data.Maybe (Maybe(..))--import Data.Either (Either(..))--import Data.Foldable (foldMap)--import Data.Foreign.Class (readProp)import Data.Functor (($>))import Data.Functor.Eff (liftEff)--import Data.Maybe (Maybe(..)) - replacement in client/src/Main.purs at line 12
import Halogen.HTML.Core (className)import qualified Halogen.HTML.Indexed as Himport qualified Halogen.HTML.Events.Indexed as Eimport qualified Halogen.HTML.Properties.Indexed as Pimport Network.HTTP.Affjax (AJAX(), affjax)import Network.HTTP.Methodimport Network.HTTP.StatusCodeimport Halogen.Util (appendToBody, onLoad)import qualified Aftok.Login as L - replacement in client/src/Main.purs at line 15
-- | The state of the component.type LoginState = { username :: String, password :: String }import Network.HTTP.Affjax (AJAX()) - edit in client/src/Main.purs at line 17
initialState :: LoginStateinitialState = { username: "", password: "" }-- | The component query algebra.data LoginAction a= SetUsername String a| SetPassword String a| Login String String a-- | The effects used in the app. - edit in client/src/Main.purs at line 19[3.1487]→[3.1487:1649](∅→∅),[3.1649]→[3.429:430](∅→∅),[3.429]→[3.429:430](∅→∅),[3.430]→[3.1650:3061](∅→∅),[3.3061]→[2.1238:1423](∅→∅),[2.1423]→[3.3099:3113](∅→∅),[3.3099]→[3.3099:3113](∅→∅),[3.3113]→[2.1424:1522](∅→∅),[2.1522]→[3.3113:3195](∅→∅),[3.3113]→[3.3113:3195](∅→∅),[3.3195]→[2.1523:2050](∅→∅),[2.2050]→[3.463:464](∅→∅),[3.3496]→[3.463:464](∅→∅),[3.463]→[3.463:464](∅→∅),[3.464]→[3.3497:3515](∅→∅)
-- | The definition for the app's main UI component.ui :: forall eff. Component LoginState LoginAction (Aff (AppEffects eff))ui = component render evalwhererender :: LoginState -> ComponentHTML LoginActionrender st =H.div[ P.classes (className <$> ["panel", "panel-primary"]) ][ H.div[ P.classes [ className "panel-heading" ] ][ H.h3 [ P.classes [ className "panel-title" ]] [ H.text "Aftok Login" ] ], H.div[ P.classes [ className "panel-body" ] ][H.h2_[ H.text "username:" ], H.p_[ H.input[ P.value st.username, P.inputType P.InputText, E.onValueInput (E.input SetUsername)]], H.h2_[ H.text "password:" ], H.p_[ H.input[ P.value st.password, P.inputType P.InputPassword, E.onValueInput (E.input SetPassword)]], H.p_[ H.button[ P.classes (className <$> ["btn", "btn-primary"]), E.onClick (E.input_ (Login st.username st.password))][ H.text "Login" ]]]]eval :: Natural LoginAction (ComponentDSL LoginState LoginAction (Aff (AppEffects eff)))eval (SetUsername user next) = modify (_ { username = user }) $> nexteval (SetPassword pass next) = modify (_ { password = pass }) $> nexteval (Login user pass next) = doresult <- liftAff' (login user pass)_ <- liftEff case result ofOK -> log "Login succeeded"Forbidden -> log "Password incorrect"Error m -> log m.messagepure nextdata LoginResponse= OK| Forbidden| Error { status :: StatusCode, message :: String }-- | Post some PureScript code to the trypurescript API and fetch the JS result.login :: forall eff. String -> String -> Aff (ajax :: AJAX | eff) LoginResponselogin user pass = doresult <- affjax $ { method: POST, url: "/login", headers: [], content: Nothing :: Maybe String, username: Just user, password: Just pass}pure $ case result.status ofStatusCode 403 -> ForbiddenStatusCode 200 -> OKother -> Error { status: other , message: result.response }-- | Run the app. - replacement in client/src/Main.purs at line 21
app <- runUI ui initialStateapp <- runUI L.ui L.initialState