Commit 729b0a4b authored by Karen Konou's avatar Karen Konou

Merge branch 'dev' into 548-dev-node-url-share

parents d9358b74 c13a7aff
Pipeline #5473 failed with stage
in 0 seconds
{ {
"name": "Gargantext", "name": "Gargantext",
"version": "0.0.6.9.9.9.3.2", "version": "0.0.6.9.9.9.4.4",
"scripts": { "scripts": {
"generate-purs-packages-nix": "./nix/generate-purs-packages.nix", "generate-purs-packages-nix": "./nix/generate-purs-packages.nix",
"generate-psc-packages-nix": "./nix/generate-packages-json.bash", "generate-psc-packages-nix": "./nix/generate-packages-json.bash",
......
...@@ -6,6 +6,7 @@ import Control.Monad.Trans.Class ...@@ -6,6 +6,7 @@ import Control.Monad.Trans.Class
import Data.String (Pattern(..), split) import Data.String (Pattern(..), split)
import Data.Array as A import Data.Array as A
import Data.Int (fromString) import Data.Int (fromString)
import Data.List (head)
import Data.Map (Map) import Data.Map (Map)
import Data.Map as Map import Data.Map as Map
import Data.Maybe (Maybe(..), fromMaybe) import Data.Maybe (Maybe(..), fromMaybe)
...@@ -254,6 +255,8 @@ breadcrumbItemCpt = here.component "breadcrumbItemCpt" cpt where ...@@ -254,6 +255,8 @@ breadcrumbItemCpt = here.component "breadcrumbItemCpt" cpt where
, disabled , disabled
} _ = do } _ = do
url <- R.unsafeHooksEffect GU.href
let sid = sessionId session let sid = sessionId session
let rootId = treeId session let rootId = treeId session
...@@ -275,7 +278,21 @@ breadcrumbItemCpt = here.component "breadcrumbItemCpt" cpt where ...@@ -275,7 +278,21 @@ breadcrumbItemCpt = here.component "breadcrumbItemCpt" cpt where
} }
] ]
, ,
H.text props.text if show nodeType == "NodeUser"
then
H.text $ getUserText url
else
H.text props.text
, H.span { className: "text-small" }
[
if show nodeType == "NodeUser"
then
H.text $ " (" <> getInstanceText url <> ")"
else
H.text ""
]
] ]
else else
...@@ -311,6 +328,16 @@ treeId (Session {treeId: tId}) = tId ...@@ -311,6 +328,16 @@ treeId (Session {treeId: tId}) = tId
getLastUrlElement :: String -> String getLastUrlElement :: String -> String
getLastUrlElement str = fromMaybe "" $ A.last $ split (Pattern "/") str getLastUrlElement str = fromMaybe "" $ A.last $ split (Pattern "/") str
getFirstUrlElement :: String -> String
getFirstUrlElement str = fromMaybe "" $ A.head $ split (Pattern "/") str
getInstanceText :: String -> String
getInstanceText str = getFirstUrlElement $ fromMaybe "" $ A.last $ split (Pattern "@") str
getUserText :: String -> String
getUserText str = getLastUrlElement $ fromMaybe "" $ A.head $ split (Pattern "@") str
type LoadProps = type LoadProps =
( (
session :: Session session :: Session
...@@ -320,65 +347,3 @@ type LoadProps = ...@@ -320,65 +347,3 @@ type LoadProps =
loadBreadcrumbData :: Record LoadProps -> AffRESTError BreadcrumbInfo loadBreadcrumbData :: Record LoadProps -> AffRESTError BreadcrumbInfo
loadBreadcrumbData {nodeId, session} = getBreadcrumb session nodeId loadBreadcrumbData {nodeId, session} = getBreadcrumb session nodeId
-- type BreadcrumbProps = ( nodeId :: NodeID )
-- breadcrumbLayout :: R2.Leaf BreadcrumbProps
-- breadcrumbLayout = R2.leaf breadcrumbLayoutCpt
-- breadcrumbLayoutCpt :: R.Component BreadcrumbProps
-- breadcrumbLayoutCpt = here.component "breadcrumbLayout" cpt where
-- cpt props@{ nodeId } _ = do
-- session <- useSession
-- let
-- breadcrumbData = getBreadcrumb session nodeId
-- pure $
-- -- breadcrumb layout
-- H.div {}
-- [
-- H.nav
-- { className: "breadcrumb-wrapper bg-light"
-- , "aria-label": "breadcrumb" }
-- [
-- H.ol { className: "breadcrumb text-small" }
-- [
-- H.li { className: "breadcrumb-item" }
-- [
-- H.a { href: "/" }
-- [ H.span { className: "" }
-- [
-- B.icon { name: "home" }
-- ]
-- , H.text "Home"
-- ]
-- ]
-- ,
-- H.li { className: "breadcrumb-item" }
-- [
-- H.a { href: "/" }
-- [ H.span { className: "" }
-- [
-- B.icon { name: "folder-open-o" }
-- ]
-- , H.text "parent folder"
-- ]
-- ]
-- ,
-- H.li { className: "breadcrumb-item" }
-- [ H.span { className: "active-page" }
-- [ H.span { className: "" }
-- [
-- B.icon { name: "book" }
-- ]
-- , H.text "current node"
-- ]
-- ]
-- ]
-- ]
-- ]
...@@ -42,6 +42,8 @@ defaultSearch :: Search ...@@ -42,6 +42,8 @@ defaultSearch :: Search
defaultSearch = { databases : Empty defaultSearch = { databases : Empty
, datafield : Just (External Empty) , datafield : Just (External Empty)
, node_id : Nothing , node_id : Nothing
, epoApiUser : Nothing
, epoApiToken : Nothing
, pubmedApiKey : Nothing , pubmedApiKey : Nothing
, lang : Nothing , lang : Nothing
, term : "" , term : ""
...@@ -226,6 +228,12 @@ isPubmed ( Just ...@@ -226,6 +228,12 @@ isPubmed ( Just
) = true ) = true
isPubmed _ = false isPubmed _ = false
isEPO :: Maybe DataField -> Boolean
isEPO ( Just
( External EPO )
) = true
isEPO _ = false
needsLang :: Maybe DataField -> Boolean needsLang :: Maybe DataField -> Boolean
needsLang (Just Gargantext) = true needsLang (Just Gargantext) = true
needsLang (Just Web) = true needsLang (Just Web) = true
...@@ -394,7 +402,7 @@ pubmedInputCpt = here.component "pubmedInput" cpt where ...@@ -394,7 +402,7 @@ pubmedInputCpt = here.component "pubmedInput" cpt where
, render: \user -> pubmedInputLoaded { pubmedAPIKey: user.u_hyperdata.pubmed_api_key , render: \user -> pubmedInputLoaded { pubmedAPIKey: user.u_hyperdata.pubmed_api_key
, search } [] } , search } [] }
where where
errorHandler = logRESTError here "[componentIMT]" errorHandler = logRESTError here "[pubmedInput]"
type PubmedInputLoadedProps = ( type PubmedInputLoadedProps = (
...@@ -431,6 +439,74 @@ pubmedInputLoadedCpt = here.component "pubmedInputLoaded" cpt where ...@@ -431,6 +439,74 @@ pubmedInputLoadedCpt = here.component "pubmedInputLoaded" cpt where
s { pubmedApiKey = mVal }) search s { pubmedApiKey = mVal }) search
type EPOInputProps = (
search :: T.Box Search
, session :: Session
)
epoInput :: R2.Component EPOInputProps
epoInput = R.createElement epoInputCpt
epoInputCpt :: R.Component EPOInputProps
epoInputCpt = here.component "epoInput" cpt where
cpt { search, session: session@(Session { treeId }) } _ = do
useLoader { errorHandler
, loader: \_ -> getUser session treeId
, path: unit
, render: \user -> epoInputLoaded { epoAPIUser: user.u_hyperdata.epo_api_user
, epoAPIToken: user.u_hyperdata.epo_api_token
, search } [] }
where
errorHandler = logRESTError here "[epoInput]"
type EPOInputLoadedProps = (
epoAPIUser :: Maybe String
, epoAPIToken :: Maybe String
, search :: T.Box Search
)
epoInputLoaded :: R2.Component EPOInputLoadedProps
epoInputLoaded = R.createElement epoInputLoadedCpt
epoInputLoadedCpt :: R.Component EPOInputLoadedProps
epoInputLoadedCpt = here.component "epoInputLoaded" cpt where
cpt { epoAPIUser, epoAPIToken, search } _ = do
search' <- T.useLive T.unequal search
R.useEffectOnce' $ do
when (search'.epoApiUser /= epoAPIUser || search'.epoApiToken /= epoAPIToken) $ do
T.write_ (search' { epoApiUser = epoAPIUser
, epoApiToken = epoAPIToken }) search
pure $
H.div { className: "form-group p-1 m-0" }
[ H.div { className: "text-primary center" } [ H.text "EPO API User" ]
, H.input { className: "form-control"
, defaultValue: fromMaybe "" search'.epoApiUser
, on: { blur: modifyEPOAPIUser search
, change: modifyEPOAPIUser search
, input: modifyEPOAPIUser search } }
, H.div { className: "text-primary center" } [ H.text "EPO API Token" ]
, H.input { className: "form-control"
, defaultValue: fromMaybe "" search'.epoApiToken
, on: { blur: modifyEPOAPIToken search
, change: modifyEPOAPIToken search
, input: modifyEPOAPIToken search } } ]
where
modifyEPOAPIUser search e = do
let val = R.unsafeEventValue e
let mVal = case val of
"" -> Nothing
s -> Just s
T.modify_ (\s -> s { epoApiUser = mVal }) search
modifyEPOAPIToken search e = do
let val = R.unsafeEventValue e
let mVal = case val of
"" -> Nothing
s -> Just s
T.modify_ (\s -> s { epoApiToken = mVal }) search
type OrgInputProps = type OrgInputProps =
( orgs :: Array Org ( orgs :: Array Org
| ComponentProps) | ComponentProps)
...@@ -499,6 +575,10 @@ datafieldInputCpt = here.component "datafieldInput" cpt where ...@@ -499,6 +575,10 @@ datafieldInputCpt = here.component "datafieldInput" cpt where
then pubmedInput { search, session } [] then pubmedInput { search, session } []
else H.div {} [] else H.div {} []
, if isEPO search'.datafield
then epoInput { search, session } []
else H.div {} []
, if isHAL search'.datafield , if isHAL search'.datafield
then orgInput { orgs: allOrgs, search } [] then orgInput { orgs: allOrgs, search } []
else H.div {} [] else H.div {} []
...@@ -673,6 +753,23 @@ searchQuery selection { databases ...@@ -673,6 +753,23 @@ searchQuery selection { databases
, query = queryHAL term (Just imtOrgs) lang years , query = queryHAL term (Just imtOrgs) lang years
, selection = selection , selection = selection
}) defaultSearchQuery }) defaultSearchQuery
searchQuery selection { databases
, datafield: datafield@(Just (External EPO))
, lang
, epoApiUser
, epoApiToken
, node_id
, term
, years } =
over SearchQuery (_ { databases = databases
, datafield = datafield
, lang = lang
, node_id = node_id
, epoAPIUser = epoApiUser
, epoAPIToken = epoApiToken
, query = term
, selection = selection
}) defaultSearchQuery
searchQuery selection { databases searchQuery selection { databases
, datafield: datafield@(Just (External PubMed)) , datafield: datafield@(Just (External PubMed))
, lang , lang
......
...@@ -29,6 +29,8 @@ type Search = { databases :: Database ...@@ -29,6 +29,8 @@ type Search = { databases :: Database
, url :: String , url :: String
, lang :: Maybe Lang , lang :: Maybe Lang
, node_id :: Maybe Int , node_id :: Maybe Int
, epoApiUser :: Maybe String
, epoApiToken :: Maybe String
, pubmedApiKey :: Maybe String , pubmedApiKey :: Maybe String
, term :: String , term :: String
, years :: Array String , years :: Array String
...@@ -110,6 +112,7 @@ data Database = All_Databases ...@@ -110,6 +112,7 @@ data Database = All_Databases
| IsTex | IsTex
| IsTex_Advanced | IsTex_Advanced
| Isidore | Isidore
| EPO
-- | News -- | News
-- | SocialNetworks -- | SocialNetworks
derive instance Generic Database _ derive instance Generic Database _
...@@ -125,6 +128,7 @@ instance Show Database where ...@@ -125,6 +128,7 @@ instance Show Database where
show IsTex = "IsTex" show IsTex = "IsTex"
show IsTex_Advanced = "IsTex_Advanced" show IsTex_Advanced = "IsTex_Advanced"
show Isidore = "Isidore" show Isidore = "Isidore"
show EPO = "EPO"
show Empty = "Empty" show Empty = "Empty"
-- show News = "News" -- show News = "News"
-- show SocialNetworks = "Social Networks" -- show SocialNetworks = "Social Networks"
...@@ -138,6 +142,7 @@ instance Doc Database where ...@@ -138,6 +142,7 @@ instance Doc Database where
doc IsTex = "All Elsevier enriched by CNRS/INIST" doc IsTex = "All Elsevier enriched by CNRS/INIST"
doc IsTex_Advanced = "IsTex advanced search" doc IsTex_Advanced = "IsTex advanced search"
doc Isidore = "All (French) Social Sciences" doc Isidore = "All (French) Social Sciences"
doc EPO = "European Patent Office"
doc Empty = "Empty" doc Empty = "Empty"
-- doc News = "Web filtered by News" -- doc News = "Web filtered by News"
-- doc SocialNetworks = "Web filtered by MicroBlogs" -- doc SocialNetworks = "Web filtered by MicroBlogs"
...@@ -167,6 +172,7 @@ allDatabases = [ Empty ...@@ -167,6 +172,7 @@ allDatabases = [ Empty
, Arxiv , Arxiv
, OpenAlex , OpenAlex
, IsTex , IsTex
-- , EPO
--, IsTex_Advanced --, IsTex_Advanced
--, Isidore --, Isidore
--, Web --, Web
...@@ -183,6 +189,7 @@ dbToInputValue (HAL _) = "hal" ...@@ -183,6 +189,7 @@ dbToInputValue (HAL _) = "hal"
dbToInputValue IsTex = "istex" dbToInputValue IsTex = "istex"
dbToInputValue IsTex_Advanced = "istex_advanced" dbToInputValue IsTex_Advanced = "istex_advanced"
dbToInputValue Isidore = "isidore" dbToInputValue Isidore = "isidore"
dbToInputValue EPO = "epo"
dbToInputValue Empty = "empty" dbToInputValue Empty = "empty"
dbFromInputValue :: String -> Maybe Database dbFromInputValue :: String -> Maybe Database
...@@ -194,6 +201,7 @@ dbFromInputValue "hal" = Just (HAL Nothing) ...@@ -194,6 +201,7 @@ dbFromInputValue "hal" = Just (HAL Nothing)
dbFromInputValue "istex" = Just IsTex dbFromInputValue "istex" = Just IsTex
dbFromInputValue "istex_advanced" = Just IsTex_Advanced dbFromInputValue "istex_advanced" = Just IsTex_Advanced
dbFromInputValue "isidore" = Just Isidore dbFromInputValue "isidore" = Just Isidore
dbFromInputValue "epo" = Just EPO
dbFromInputValue "empty" = Just Empty dbFromInputValue "empty" = Just Empty
dbFromInputValue _ = Nothing dbFromInputValue _ = Nothing
...@@ -274,6 +282,8 @@ newtype SearchQuery = SearchQuery ...@@ -274,6 +282,8 @@ newtype SearchQuery = SearchQuery
, node_id :: Maybe Int , node_id :: Maybe Int
, offset :: Maybe Int , offset :: Maybe Int
, order :: Maybe SearchOrder , order :: Maybe SearchOrder
, epoAPIUser :: Maybe String
, epoAPIToken :: Maybe String
, pubmedAPIKey :: Maybe String , pubmedAPIKey :: Maybe String
, selection :: ListSelection.Selection , selection :: ListSelection.Selection
} }
...@@ -292,13 +302,23 @@ instance GT.ToQuery SearchQuery where ...@@ -292,13 +302,23 @@ instance GT.ToQuery SearchQuery where
pair k = maybe [] $ \v -> pair k = maybe [] $ \v ->
[ QP.keyFromString k /\ Just (QP.valueFromString $ show v) ] [ QP.keyFromString k /\ Just (QP.valueFromString $ show v) ]
instance JSON.WriteForeign SearchQuery where instance JSON.WriteForeign SearchQuery where
writeImpl (SearchQuery { databases, datafield, lang, node_id, pubmedAPIKey, query, selection }) = writeImpl (SearchQuery { databases
, datafield
, lang
, node_id
, epoAPIUser
, epoAPIToken
, pubmedAPIKey
, query
, selection }) =
JSON.writeImpl { query: query -- String.replace (String.Pattern "\"") (String.Replacement "\\\"") query JSON.writeImpl { query: query -- String.replace (String.Pattern "\"") (String.Replacement "\\\"") query
, databases , databases
, datafield , datafield
, lang: maybe "EN" show lang , lang: maybe "EN" show lang
, node_id: fromMaybe 0 node_id , node_id: fromMaybe 0 node_id
, flowListWith: selection , flowListWith: selection
, epoAPIUser
, epoAPIToken
, pubmedAPIKey , pubmedAPIKey
} }
...@@ -313,6 +333,8 @@ defaultSearchQuery = SearchQuery ...@@ -313,6 +333,8 @@ defaultSearchQuery = SearchQuery
, node_id : Nothing , node_id : Nothing
, offset : Nothing , offset : Nothing
, order : Nothing , order : Nothing
, epoAPIUser : Nothing
, epoAPIToken : Nothing
, pubmedAPIKey : Nothing , pubmedAPIKey : Nothing
, selection : ListSelection.NoList -- MyListsFirst , selection : ListSelection.NoList -- MyListsFirst
} }
......
...@@ -6,7 +6,7 @@ import Data.Array (filter, nub) ...@@ -6,7 +6,7 @@ import Data.Array (filter, nub)
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Show.Generic (genericShow) import Data.Show.Generic (genericShow)
import Data.String (Pattern(..), contains) import Data.String (Pattern(..), contains, trim)
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
import Effect.Aff (Aff) import Effect.Aff (Aff)
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action) import Gargantext.Components.Forest.Tree.Node.Action.Types (Action)
...@@ -41,7 +41,7 @@ getCompletionsReq { session } = ...@@ -41,7 +41,7 @@ getCompletionsReq { session } =
get session GR.Members get session GR.Members
shareAction :: String -> Action shareAction :: String -> Action
shareAction username = Action.ShareTeam username shareAction username = Action.ShareTeam (trim username)
------------------------------------------------------------------------ ------------------------------------------------------------------------
...@@ -100,6 +100,8 @@ shareNodeInnerCpt = here.component "shareNodeInner" cpt ...@@ -100,6 +100,8 @@ shareNodeInnerCpt = here.component "shareNodeInner" cpt
, autocompleteSearch , autocompleteSearch
, onAutocompleteClick , onAutocompleteClick
, text , text
, pattern: "^\\S+$" -- pattern doesn't allow space characters
, title: "Enter a username or an email address (space characters are not allowed)"
, placeholder: "username or email"} , placeholder: "username or email"}
] (H.div {} [H.text text']) ] (H.div {} [H.text text'])
where where
......
...@@ -66,6 +66,8 @@ nodeSearchControlCpt = here.component "nodeSearchControl" cpt ...@@ -66,6 +66,8 @@ nodeSearchControlCpt = here.component "nodeSearchControl" cpt
, 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"
, state: search , state: search
, pattern: ".*"
, title: ""
, placeholder: "find and select a term here..." , placeholder: "find and select a term here..."
} }
, ,
......
...@@ -16,7 +16,7 @@ import Gargantext.Components.GraphQL.IMT as GQLIMT ...@@ -16,7 +16,7 @@ import Gargantext.Components.GraphQL.IMT as GQLIMT
import Gargantext.Components.GraphQL.NLP as GQLNLP import Gargantext.Components.GraphQL.NLP as GQLNLP
import Gargantext.Components.GraphQL.Node as GQLNode import Gargantext.Components.GraphQL.Node as GQLNode
import Gargantext.Components.GraphQL.Tree (TreeFirstLevel, BreadcrumbInfo) import Gargantext.Components.GraphQL.Tree (TreeFirstLevel, BreadcrumbInfo)
import Gargantext.Components.GraphQL.User (User, UserInfo, UserInfoM, UserPubmedAPIKeyM) import Gargantext.Components.GraphQL.User (User, UserInfo, UserInfoM, UserPubmedAPIKeyM, UserEPOAPIUserM, UserEPOAPITokenM)
import Gargantext.Components.GraphQL.Team (Team, TeamDeleteM) import Gargantext.Components.GraphQL.Team (Team, TeamDeleteM)
import Gargantext.Ends (Backend(..)) import Gargantext.Ends (Backend(..))
import Gargantext.Sessions (Session(..)) import Gargantext.Sessions (Session(..))
...@@ -92,5 +92,7 @@ type Schema ...@@ -92,5 +92,7 @@ type Schema
type Mutation type Mutation
= { update_user_info :: UserInfoM ==> Int = { update_user_info :: UserInfoM ==> Int
, update_user_pubmed_api_key :: UserPubmedAPIKeyM ==> Int , update_user_pubmed_api_key :: UserPubmedAPIKeyM ==> Int
, update_user_epo_api_user :: UserEPOAPIUserM ==> Int
, update_user_epo_api_token :: UserEPOAPITokenM ==> Int
, delete_team_membership :: TeamDeleteM ==> Array Int , delete_team_membership :: TeamDeleteM ==> Array Int
, update_node_context_category :: GQLCTX.NodeContextCategoryM ==> Array Int } , update_node_context_category :: GQLCTX.NodeContextCategoryM ==> Array Int }
...@@ -81,6 +81,26 @@ updateUserPubmedAPIKey session user_id api_key = do ...@@ -81,6 +81,26 @@ updateUserPubmedAPIKey session user_id api_key = do
{ update_user_pubmed_api_key: onlyArgs { user_id { update_user_pubmed_api_key: onlyArgs { user_id
, api_key } } , api_key } }
pure $ Right unit pure $ Right unit
updateUserEPOAPIUser :: Session -> Int -> String -> AffRESTError Unit
updateUserEPOAPIUser session user_id api_user = do
client <- liftEffect $ getClient session
{ update_user_epo_api_user } <- mutation
client
"update_user_epo_api_user"
{ update_user_epo_api_user: onlyArgs { user_id
, api_user } }
pure $ Right unit
updateUserEPOAPIToken :: Session -> Int -> String -> AffRESTError Unit
updateUserEPOAPIToken session user_id api_token = do
client <- liftEffect $ getClient session
{ update_user_epo_api_token } <- mutation
client
"update_user_epo_api_token"
{ update_user_epo_api_token: onlyArgs { user_id
, api_token } }
pure $ Right unit
getUserInfo :: Session -> Int -> AffRESTError UserInfo getUserInfo :: Session -> Int -> AffRESTError UserInfo
getUserInfo session id = do getUserInfo session id = do
......
...@@ -148,6 +148,8 @@ type User ...@@ -148,6 +148,8 @@ type User
{ organization :: Array String } { organization :: Array String }
} }
, pubmed_api_key :: Maybe String , pubmed_api_key :: Maybe String
, epo_api_user :: Maybe String
, epo_api_token :: Maybe String
} }
, u_username :: String , u_username :: String
, u_email :: String , u_email :: String
...@@ -172,6 +174,8 @@ userQuery = { users: { user_id: Var :: _ "id" Int } =>> ...@@ -172,6 +174,8 @@ userQuery = { users: { user_id: Var :: _ "id" Int } =>>
, "where": { organization: unit } , "where": { organization: unit }
} }
, pubmed_api_key: unit , pubmed_api_key: unit
, epo_api_user: unit
, epo_api_token: unit
} }
, u_username: unit , u_username: unit
, u_email: unit , u_email: unit
...@@ -182,3 +186,11 @@ userQuery = { users: { user_id: Var :: _ "id" Int } =>> ...@@ -182,3 +186,11 @@ userQuery = { users: { user_id: Var :: _ "id" Int } =>>
type UserPubmedAPIKeyM = type UserPubmedAPIKeyM =
{ user_id :: Int { user_id :: Int
, api_key :: String } , api_key :: String }
type UserEPOAPIUserM =
{ user_id :: Int
, api_user :: String }
type UserEPOAPITokenM =
{ user_id :: Int
, api_token :: String }
...@@ -7,6 +7,7 @@ import DOM.Simple as DOM ...@@ -7,6 +7,7 @@ import DOM.Simple as DOM
import DOM.Simple.Event as DE import DOM.Simple.Event as DE
import Data.Maybe (Maybe(..), maybe) import Data.Maybe (Maybe(..), maybe)
import Data.Nullable (Nullable, null, toMaybe) import Data.Nullable (Nullable, null, toMaybe)
import Data.String as S
import Effect (Effect) import Effect (Effect)
import Effect.Aff (Aff, launchAff_) import Effect.Aff (Aff, launchAff_)
import FFI.Simple ((..)) import FFI.Simple ((..))
...@@ -31,6 +32,8 @@ type Props = ...@@ -31,6 +32,8 @@ type Props =
, onAutocompleteClick :: String -> Effect Unit , onAutocompleteClick :: String -> Effect Unit
, onEnterPress :: String -> Effect Unit , onEnterPress :: String -> Effect Unit
, placeholder :: String , placeholder :: String
, pattern :: String
, title :: String
, state :: T.Box String , state :: T.Box String
) )
...@@ -44,6 +47,8 @@ inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt ...@@ -44,6 +47,8 @@ inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt
, onAutocompleteClick , onAutocompleteClick
, onEnterPress , onEnterPress
, placeholder , placeholder
, pattern
, title
, state } _ = do , state } _ = do
-- States -- States
state' <- T.useLive T.unequal state state' <- T.useLive T.unequal state
...@@ -68,6 +73,8 @@ inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt ...@@ -68,6 +73,8 @@ inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt
, ref: inputRef , ref: inputRef
, className: "form-control" , className: "form-control"
, value: state' , value: state'
, pattern: pattern
, title: title
, placeholder , placeholder
, on: { focus: onFocus completions state' , on: { focus: onFocus completions state'
, input: onInput completions , input: onInput completions
...@@ -114,7 +121,7 @@ inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt ...@@ -114,7 +121,7 @@ inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt
onInput :: forall event. T.Box Completions -> event -> Effect Unit onInput :: forall event. T.Box Completions -> event -> Effect Unit
onInput completions e = do onInput completions e = do
let val = R.unsafeEventValue e let val = S.trim $ R.unsafeEventValue e
T.write_ val state T.write_ val state
cs <- autocompleteSearch val cs <- autocompleteSearch val
T.write_ cs completions T.write_ cs completions
...@@ -145,6 +152,8 @@ type Props' = ...@@ -145,6 +152,8 @@ type Props' =
, boxAction :: String -> Action , boxAction :: String -> Action
, state :: T.Box String , state :: T.Box String
, text :: T.Box String , text :: T.Box String
, pattern :: String
, title :: String
, placeholder :: String , placeholder :: String
) )
...@@ -160,6 +169,8 @@ inputWithAutocompleteCpt' = here.component "inputWithAutocomplete" cpt ...@@ -160,6 +169,8 @@ inputWithAutocompleteCpt' = here.component "inputWithAutocomplete" cpt
, boxAction , boxAction
, state , state
, text , text
, pattern
, title
, placeholder } _ = do , placeholder } _ = do
-- States -- States
state' <- T.useLive T.unequal state state' <- T.useLive T.unequal state
...@@ -184,6 +195,8 @@ inputWithAutocompleteCpt' = here.component "inputWithAutocomplete" cpt ...@@ -184,6 +195,8 @@ inputWithAutocompleteCpt' = here.component "inputWithAutocomplete" cpt
, ref: inputRef , ref: inputRef
, className: "form-control" , className: "form-control"
, value: state' , value: state'
, pattern: pattern
, title: title
, placeholder , placeholder
, on: { focus: onFocus completions state' , on: { focus: onFocus completions state'
, input: onInput completions , input: onInput completions
...@@ -246,7 +259,7 @@ inputWithAutocompleteCpt' = here.component "inputWithAutocomplete" cpt ...@@ -246,7 +259,7 @@ inputWithAutocompleteCpt' = here.component "inputWithAutocomplete" cpt
if DE.key e == "Enter" then do if DE.key e == "Enter" then do
R2.preventDefault e R2.preventDefault e
R2.stopPropagation e R2.stopPropagation e
let val = R.unsafeEventValue e let val = S.trim $ R.unsafeEventValue e
let mInput = toMaybe $ R.readRef inputRef let mInput = toMaybe $ R.readRef inputRef
T.write_ val state T.write_ val state
launchAff_ $ dispatch (boxAction val) launchAff_ $ dispatch (boxAction val)
...@@ -260,7 +273,7 @@ inputWithAutocompleteCpt' = here.component "inputWithAutocomplete" cpt ...@@ -260,7 +273,7 @@ inputWithAutocompleteCpt' = here.component "inputWithAutocomplete" cpt
pure $ false pure $ false
submit val _ = do submit val _ = do
T.write_ ("Invited " <> val <> " to the team") text T.write_ ("Invited " <> S.trim val <> " to the team") text
launchAff_ $ dispatch (boxAction val) launchAff_ $ dispatch (boxAction val)
--------------------------------------------------------- ---------------------------------------------------------
......
...@@ -15,7 +15,7 @@ import Effect.Aff (launchAff_) ...@@ -15,7 +15,7 @@ import Effect.Aff (launchAff_)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Gargantext.Components.App.Store (Boxes) import Gargantext.Components.App.Store (Boxes)
import Gargantext.Components.GraphQL (getClient) import Gargantext.Components.GraphQL (getClient)
import Gargantext.Components.GraphQL.Endpoints (getUserInfo, getUser, updateUserPubmedAPIKey) import Gargantext.Components.GraphQL.Endpoints (getUserInfo, getUser, updateUserPubmedAPIKey, updateUserEPOAPIUser, updateUserEPOAPIToken)
import Gargantext.Components.GraphQL.User (UserInfo, _ui_cwCity, _ui_cwCountry, _ui_cwFirstName, _ui_cwLabTeamDeptsFirst, _ui_cwLastName, _ui_cwOffice, _ui_cwOrganizationFirst, _ui_cwRole, _ui_cwTouchMail, _ui_cwTouchPhone, _ui_cwDescription) import Gargantext.Components.GraphQL.User (UserInfo, _ui_cwCity, _ui_cwCountry, _ui_cwFirstName, _ui_cwLabTeamDeptsFirst, _ui_cwLastName, _ui_cwOffice, _ui_cwOrganizationFirst, _ui_cwRole, _ui_cwTouchMail, _ui_cwTouchPhone, _ui_cwDescription)
import Gargantext.Components.InputWithEnter (inputWithEnter) import Gargantext.Components.InputWithEnter (inputWithEnter)
import Gargantext.Components.Nodes.Annuaire.Tabs as Tabs import Gargantext.Components.Nodes.Annuaire.Tabs as Tabs
...@@ -114,6 +114,7 @@ userLayoutWithKeyCpt = here.component "userLayoutWithKey" cpt where ...@@ -114,6 +114,7 @@ userLayoutWithKeyCpt = here.component "userLayoutWithKey" cpt where
display { title: fromMaybe "no name" (Just ui_username) } display { title: fromMaybe "no name" (Just ui_username) }
(contactInfos userInfo (onUpdateUserInfo boxes.errors reload)) (contactInfos userInfo (onUpdateUserInfo boxes.errors reload))
, pubmedSettings { boxes, nodeId, session } , pubmedSettings { boxes, nodeId, session }
, epoSettings { boxes, nodeId, session }
-- , Tabs.tabs { -- , Tabs.tabs {
-- boxes -- boxes
-- , cacheState -- , cacheState
...@@ -185,7 +186,7 @@ pubmedSettingsLoaded :: R2.Leaf PubmedSettingsLoadedProps ...@@ -185,7 +186,7 @@ pubmedSettingsLoaded :: R2.Leaf PubmedSettingsLoadedProps
pubmedSettingsLoaded = R2.leaf pubmedSettingsLoadedCpt pubmedSettingsLoaded = R2.leaf pubmedSettingsLoadedCpt
pubmedSettingsLoadedCpt :: R.Component PubmedSettingsLoadedProps pubmedSettingsLoadedCpt :: R.Component PubmedSettingsLoadedProps
pubmedSettingsLoadedCpt = here.component "pubmedSettingsLoaded" cpt where pubmedSettingsLoadedCpt = here.component "pubmedSettingsLoaded" cpt where
cpt { boxes: { errors } cpt { boxes
, nodeId , nodeId
, mPubmedAPIKey , mPubmedAPIKey
, session } _ = do , session } _ = do
...@@ -197,26 +198,110 @@ pubmedSettingsLoadedCpt = here.component "pubmedSettingsLoaded" cpt where ...@@ -197,26 +198,110 @@ pubmedSettingsLoadedCpt = here.component "pubmedSettingsLoaded" cpt where
[ R2.col 12 [ R2.col 12
[ R2.row [ R2.row
[ H.h2 {} [ H.text "PubMed settings" ] ] [ H.h2 {} [ H.text "PubMed settings" ] ]
, H.div { className: "form-group row"} , editableUserField { boxes
[ H.span { className: "col-sm-2 col-form-label" } [ H.text "API Key" ] , callback: updateUserPubmedAPIKey session nodeId
, H.div { className: "input-group col-sm-6"} , description: "API Key"
[ itemEditable { defaultVal: "" , mValue: mPubmedAPIKey }
, isEditing
, onUpdate: \s -> do
here.log2 "[pubmedSettingsLoaded] new api key" s
case s of
"" -> pure unit
_ -> do
launchAff_ $ do
res <- updateUserPubmedAPIKey session nodeId s
handleRESTError here errors res $ \_result ->
liftEffect $ here.log "[pubmedSettingsLoaded] api key updated"
, valueBox: box }]
]
] ]
] ]
] ]
------------------------------------------------------------
type EPOSettingsProps =
( boxes :: Boxes
, nodeId :: CorpusId
, session :: Session )
epoSettings :: R2.Leaf EPOSettingsProps
epoSettings = R2.leaf epoSettingsCpt
epoSettingsCpt :: R.Component EPOSettingsProps
epoSettingsCpt = here.component "epoSettings" cpt where
cpt { boxes
, nodeId
, session } _ = do
useLoader { errorHandler
, loader: \_ -> getUser session nodeId
, path: unit
, render: \user -> epoSettingsLoaded { boxes
, nodeId
, mEPOAPIUser: user.u_hyperdata.epo_api_user
, mEPOAPIToken: user.u_hyperdata.epo_api_token
, session } }
where
errorHandler = logRESTError here "[epoSettings]"
type EPOSettingsLoadedProps =
( mEPOAPIUser :: Maybe String
, mEPOAPIToken :: Maybe String
| EPOSettingsProps )
epoSettingsLoaded :: R2.Leaf EPOSettingsLoadedProps
epoSettingsLoaded = R2.leaf epoSettingsLoadedCpt
epoSettingsLoadedCpt :: R.Component EPOSettingsLoadedProps
epoSettingsLoadedCpt = here.component "epoSettingsLoaded" cpt where
cpt { boxes
, nodeId
, mEPOAPIUser
, mEPOAPIToken
, session } _ = do
pure $ R2.row
[ R2.col 12
[ R2.col 12
[ R2.row
[ H.h2 {} [ H.text "EPO settings" ] ]
, editableUserField { boxes
, callback: updateUserEPOAPIUser session nodeId
, description: "API User"
, mValue: mEPOAPIUser }
, editableUserField { boxes
, callback: updateUserEPOAPIToken session nodeId
, description: "API Token"
, mValue: mEPOAPIToken }
]
]
]
------------------------------------------------------------
type EditableUserField =
( boxes :: Boxes
, callback :: String -> AffRESTError Unit
, description :: String
, mValue :: Maybe String )
editableUserField :: R2.Leaf EditableUserField
editableUserField = R2.leaf editableUserFieldCpt
editableUserFieldCpt :: R.Component EditableUserField
editableUserFieldCpt = here.component "editableUserField" cpt where
cpt { boxes: { errors }
, callback
, description
, mValue } _ = do
box <- T.useBox $ fromMaybe "" mValue
isEditing <- T.useBox false
pure $ H.div { className: "form-group row"}
[ H.span { className: "col-sm-2 col-form-label" } [ H.text description ]
, H.div { className: "input-group col-sm-6"}
[ itemEditable { defaultVal: ""
, isEditing
, onUpdate: \s -> do
here.log2 ("[editableUserField] " <> description) s
case s of
"" -> pure unit
_ -> do
launchAff_ $ do
res <- callback s
handleRESTError here errors res $ \_result ->
liftEffect $ here.log ("[editableUserField] " <> description <> " updated")
, valueBox: box }]
]
------------------------------------------------------------
-- | TODO format data in better design (UI) shape -- | TODO format data in better design (UI) shape
contactInfos :: UserInfo -> (UserInfo -> Effect Unit) -> Array R.Element contactInfos :: UserInfo -> (UserInfo -> Effect Unit) -> Array R.Element
contactInfos userInfo onUpdateUserInfo = item <$> contactInfoItems where contactInfos userInfo onUpdateUserInfo = item <$> contactInfoItems where
......
...@@ -147,6 +147,8 @@ component = here.component "main" cpt where ...@@ -147,6 +147,8 @@ component = here.component "main" cpt where
Nothing -> pure unit Nothing -> pure unit
Just h -> autocompleteClickCallback h Just h -> autocompleteClickCallback h
, classes: "filter-results-completions rounded-circle-2 text-small py-0" , classes: "filter-results-completions rounded-circle-2 text-small py-0"
, pattern: ".*"
, title: ""
, placeholder: "find and select a term here..." , placeholder: "find and select a term here..."
, state: searchState , state: searchState
} }
......
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