[team share] autofocus on username, fixes to errors

parent 3ce1b08e
...@@ -325,7 +325,7 @@ renameNode name p@{ boxes: { errors }, session, tree: (NTree (LNode {id}) _) } = ...@@ -325,7 +325,7 @@ renameNode name p@{ boxes: { errors }, session, tree: (NTree (LNode {id}) _) } =
handleRESTError here errors eTask $ \_task -> pure unit handleRESTError here errors eTask $ \_task -> pure unit
refreshTree p refreshTree p
shareTeam username { boxes: { errors }, session, tree: (NTree (LNode {id}) _)} = do shareTeam username { boxes: { errors }, session, tree: (NTree (LNode {id}) _) } = do
eTask <- Share.shareReq session id $ Share.ShareTeamParams { username } eTask <- Share.shareReq session id $ Share.ShareTeamParams { username }
handleRESTError here errors eTask $ \_task -> pure unit handleRESTError here errors eTask $ \_task -> pure unit
......
...@@ -73,7 +73,7 @@ shareNodeCpt = here.component "shareNode" cpt ...@@ -73,7 +73,7 @@ shareNodeCpt = here.component "shareNode" cpt
useLoader { useLoader {
loader: getCompletionsReq loader: getCompletionsReq
, path: { session } , path: { session }
, render: \completions -> shareNodeInner {completions, dispatch} [] , render: \completions -> shareNodeInner { completions, dispatch } []
, errorHandler , errorHandler
} }
where where
...@@ -94,15 +94,16 @@ shareNodeInnerCpt = here.component "shareNodeInner" cpt ...@@ -94,15 +94,16 @@ shareNodeInnerCpt = here.component "shareNodeInner" cpt
text' /\ text <- R2.useBox' "" text' /\ text <- R2.useBox' ""
pure $ Tools.panel pure $ Tools.panel
[ inputWithAutocomplete { autocompleteSearch [ inputWithAutocomplete { autoFocus: true
, autocompleteSearch
, classes: "share-users-completions d-flex align-items-center" , classes: "share-users-completions d-flex align-items-center"
, onAutocompleteClick , onAutocompleteClick
, onEnterPress: onEnterPress text , onEnterPress: onEnterPress text
, placeholder: "username or email" , placeholder: "username or email"
, pattern: "^\\S+$" -- pattern doesn't allow space characters , pattern: "^\\S+$" -- pattern doesn't allow space characters
, title: "Enter a username or an email address (space characters are not allowed)" , title
, state } , state }
[ B.iconButton { callback: submit state' text [ B.iconButton { callback: \_ -> onEnterPress text state'
, elevation: Level1 , elevation: Level1
, name: "send" , name: "send"
, title: "Submit" } ] , title: "Submit" } ]
...@@ -110,10 +111,10 @@ shareNodeInnerCpt = here.component "shareNodeInner" cpt ...@@ -110,10 +111,10 @@ shareNodeInnerCpt = here.component "shareNodeInner" cpt
where where
autocompleteSearch input = pure $ nub $ filter (contains (Pattern input)) completions autocompleteSearch input = pure $ nub $ filter (contains (Pattern input)) completions
onAutocompleteClick _ = pure unit onAutocompleteClick _ = pure unit
onEnterPress text val = T.write_ ("Invited " <> val <> " to the team") text onEnterPress text val = do
submit val text _ = do
onEnterPress text val
launchAff_ $ dispatch (shareAction val) launchAff_ $ dispatch (shareAction val)
T.write_ ("Invited " <> val <> " to the team") text
title = "Enter a username or an email address (space characters are not allowed)"
------------------------------------------------------------------------ ------------------------------------------------------------------------
publishNode :: R2.Component SubTreeParamsIn publishNode :: R2.Component SubTreeParamsIn
publishNode = R.createElement publishNodeCpt publishNode = R.createElement publishNodeCpt
......
...@@ -61,7 +61,8 @@ nodeSearchControlCpt = here.component "nodeSearchControl" cpt ...@@ -61,7 +61,8 @@ nodeSearchControlCpt = here.component "nodeSearchControl" cpt
} }
[ [
inputWithAutocomplete inputWithAutocomplete
{ autocompleteSearch: autocompleteSearch graph { autoFocus: true
, autocompleteSearch: autocompleteSearch graph
, onAutocompleteClick: doSearch , onAutocompleteClick: doSearch
, onEnterPress: doSearch , onEnterPress: doSearch
, classes: "filter-results-completions rounded-circle-2 text-small py-0" , classes: "filter-results-completions rounded-circle-2 text-small py-0"
......
...@@ -27,7 +27,8 @@ type Completions = Array String ...@@ -27,7 +27,8 @@ type Completions = Array String
type Props = type Props =
( (
autocompleteSearch :: String -> Effect Completions autoFocus :: Boolean
, autocompleteSearch :: String -> Effect Completions
, classes :: String , classes :: String
, onAutocompleteClick :: String -> Effect Unit , onAutocompleteClick :: String -> Effect Unit
, onEnterPress :: String -> Effect Unit , onEnterPress :: String -> Effect Unit
...@@ -42,7 +43,8 @@ inputWithAutocomplete = R2.component inputWithAutocompleteCpt ...@@ -42,7 +43,8 @@ inputWithAutocomplete = R2.component inputWithAutocompleteCpt
inputWithAutocompleteCpt :: R.Component Props inputWithAutocompleteCpt :: R.Component Props
inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt
where where
cpt { autocompleteSearch cpt { autoFocus
, autocompleteSearch
, classes , classes
, onAutocompleteClick , onAutocompleteClick
, onEnterPress , onEnterPress
...@@ -71,10 +73,11 @@ inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt ...@@ -71,10 +73,11 @@ inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt
completionsCpt { completions, onAutocompleteClick, state } [] completionsCpt { completions, onAutocompleteClick, state } []
, H.input { type: "text" , H.input { type: "text"
, ref: inputRef , ref: inputRef
, autoFocus
, className: "form-control" , className: "form-control"
, value: state' , value: state'
, pattern: pattern , pattern
, title: title , title
, placeholder , placeholder
, on: { focus: onFocus completions state' , on: { focus: onFocus completions state'
, input: onInput completions , input: onInput completions
......
...@@ -139,7 +139,8 @@ component = here.component "main" cpt where ...@@ -139,7 +139,8 @@ component = here.component "main" cpt where
} }
[ [
inputWithAutocomplete inputWithAutocomplete
{ autocompleteSearch: searchCallback { autoFocus: true
, autocompleteSearch: searchCallback
, onAutocompleteClick: autocompleteClickCallback , onAutocompleteClick: autocompleteClickCallback
, onEnterPress: \s -> do , onEnterPress: \s -> do
cs <- searchCallback s cs <- searchCallback s
......
...@@ -5,6 +5,7 @@ import Affjax as Affjax ...@@ -5,6 +5,7 @@ import Affjax as Affjax
import Affjax.RequestBody (formData, formURLEncoded, string) import Affjax.RequestBody (formData, formURLEncoded, string)
import Affjax.RequestHeader as ARH import Affjax.RequestHeader as ARH
import Affjax.ResponseFormat as ResponseFormat import Affjax.ResponseFormat as ResponseFormat
import Affjax.StatusCode (StatusCode(..))
import Data.Argonaut.Core as AC import Data.Argonaut.Core as AC
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.Foldable (foldMap) import Data.Foldable (foldMap)
...@@ -23,29 +24,36 @@ import Gargantext.Utils.Reactix as R2 ...@@ -23,29 +24,36 @@ import Gargantext.Utils.Reactix as R2
import Simple.JSON as JSON import Simple.JSON as JSON
import Web.XHR.FormData as XHRFormData import Web.XHR.FormData as XHRFormData
here :: R2.Here
here = R2.here "Gargantext.Config.REST"
type Token = String type Token = String
data RESTError = data RESTError =
SendResponseError Affjax.Error CustomError String
| ReadJSONError Foreign.MultipleErrors | ReadJSONError Foreign.MultipleErrors
| CustomError String | SendResponseError Affjax.Error
| ServerError String
| UnknownServerError String
derive instance Generic RESTError _ derive instance Generic RESTError _
instance Show RESTError where instance Show RESTError where
show (CustomError s) = "CustomError " <> s
show (ReadJSONError e) = "ReadJSONError " <> show e
show (SendResponseError e) = "SendResponseError " <> showError e show (SendResponseError e) = "SendResponseError " <> showError e
where where
showError (RequestContentError e') = "(RequestContentError " <> show e' <> ")"
showError (ResponseBodyError fe _) = "(ResponseBodyError " <> show fe <> " (rf)" -- <> show rf <> ")" showError (ResponseBodyError fe _) = "(ResponseBodyError " <> show fe <> " (rf)" -- <> show rf <> ")"
showError (TimeoutError) = "(TimeoutError)" showError (RequestContentError e') = "(RequestContentError " <> show e' <> ")"
showError (RequestFailedError) = "(RequestFailedError)" showError (RequestFailedError) = "(RequestFailedError)"
showError (XHROtherError e') = "(XHROtherError " <> show e' <> ")" showError (TimeoutError) = "(TimeoutError)"
show (ReadJSONError e) = "ReadJSONError " <> show e showError (XHROtherError e') = "(XHROtherError " <> show e' <> ")"
show (CustomError s) = "CustomError " <> s show (ServerError e) = "ServerError: " <> e
show (UnknownServerError e) = "UnknownServerError: " <> e
instance Eq RESTError where instance Eq RESTError where
-- this is crude but we need it only because of useLoader -- this is crude but we need it only because of useLoader
eq _ _ = false eq _ _ = false
logRESTError :: R2.Here -> String -> RESTError -> Effect Unit logRESTError :: R2.Here -> String -> RESTError -> Effect Unit
logRESTError here prefix e = here.warn2 (prefix <> " " <> show e) e logRESTError here' prefix e = here'.warn2 (prefix <> " " <> show e) e
-- logRESTError here prefix (SendResponseError e) = here.warn2 (prefix <> " SendResponseError ") e -- TODO: No show -- logRESTError here prefix (SendResponseError e) = here.warn2 (prefix <> " SendResponseError ") e -- TODO: No show
-- logRESTError here prefix (ReadJSONError e) = here.warn2 (prefix <> " ReadJSONError ") $ show e -- logRESTError here prefix (ReadJSONError e) = here.warn2 (prefix <> " ReadJSONError ") $ show e
-- logRESTError here prefix (CustomError e) = here.warn2 (prefix <> " CustomError ") $ e -- logRESTError here prefix (CustomError e) = here.warn2 (prefix <> " CustomError ") $ e
...@@ -53,11 +61,9 @@ logRESTError here prefix e = here.warn2 (prefix <> " " <> show e) e ...@@ -53,11 +61,9 @@ logRESTError here prefix e = here.warn2 (prefix <> " " <> show e) e
type AffRESTError a = Aff (Either RESTError a) type AffRESTError a = Aff (Either RESTError a)
readJSON :: forall a b. JSON.ReadForeign a => readJSON :: forall a. JSON.ReadForeign a =>
Either Affjax.Error Either Affjax.Error (Affjax.Response AC.Json)
{ body :: AC.Json -> Either RESTError a
| b
} -> Either RESTError a
readJSON affResp = readJSON affResp =
case affResp of case affResp of
Left err -> do Left err -> do
...@@ -68,9 +74,15 @@ readJSON affResp = ...@@ -68,9 +74,15 @@ readJSON affResp =
--_ <- liftEffect $ log json.status --_ <- liftEffect $ log json.status
--_ <- liftEffect $ log json.headers --_ <- liftEffect $ log json.headers
--_ <- liftEffect $ log json.body --_ <- liftEffect $ log json.body
case (JSON.readJSON $ AC.stringify resp.body) of case resp.status of
Left err -> Left $ ReadJSONError err StatusCode 500 ->
Right r -> Right r case (JSON.readJSON $ AC.stringify resp.body :: JSON.E { error :: String }) of
Right ({ error }) -> Left $ ServerError error
Left _ -> Left $ UnknownServerError $ AC.stringify resp.body
_ ->
case (JSON.readJSON $ AC.stringify resp.body) of
Left err -> Left $ ReadJSONError err
Right r -> Right r
-- TODO too much duplicate code in `postWwwUrlencoded` -- TODO too much duplicate code in `postWwwUrlencoded`
send :: forall body res. JSON.WriteForeign body => JSON.ReadForeign res => send :: forall body res. JSON.WriteForeign body => JSON.ReadForeign res =>
...@@ -94,6 +106,7 @@ send m mtoken url reqbody = do ...@@ -94,6 +106,7 @@ send m mtoken url reqbody = do
let cookie = "JWT-Cookie=" <> token <> "; Path=/;" --" HttpOnly; Secure; SameSite=Lax" let cookie = "JWT-Cookie=" <> token <> "; Path=/;" --" HttpOnly; Secure; SameSite=Lax"
R2.setCookie cookie R2.setCookie cookie
affResp <- request req affResp <- request req
liftEffect $ here.log2 "[send] affResp" affResp
pure $ readJSON affResp pure $ readJSON affResp
noReqBody :: Maybe String noReqBody :: Maybe String
......
...@@ -147,7 +147,7 @@ newtype Point = Point { x :: Number, y :: Number } ...@@ -147,7 +147,7 @@ newtype Point = Point { x :: Number, y :: Number }
-- a reducer function living in effector, for useReductor -- a reducer function living in effector, for useReductor
type Actor s a = (a -> s -> Effect s) type Actor s a = (a -> s -> Effect s)
-- | Turns a ReactElement into aReactix Element -- | Turns a ReactElement into a Reactix Element
-- | buff (v.) to polish -- | buff (v.) to polish
buff :: ReactElement -> R.Element buff :: ReactElement -> R.Element
buff = unsafeCoerce buff = unsafeCoerce
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment