Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
purescript-gargantext
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
137
Issues
137
List
Board
Labels
Milestones
Merge Requests
4
Merge Requests
4
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gargantext
purescript-gargantext
Commits
00098c86
Commit
00098c86
authored
Nov 03, 2021
by
Przemyslaw Kaminski
1
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[GraphQL] user fetched via the user_info endpoint
parent
2dab4e56
Pipeline
#2036
failed with stage
Changes
6
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
449 additions
and
312 deletions
+449
-312
GraphQL.purs
src/Gargantext/Components/GraphQL.purs
+3
-2
User.purs
src/Gargantext/Components/GraphQL/User.purs
+119
-34
Tabs.purs
src/Gargantext/Components/Nodes/Annuaire/Tabs.purs
+14
-14
User.purs
src/Gargantext/Components/Nodes/Annuaire/User.purs
+21
-177
Contact.purs
src/Gargantext/Components/Nodes/Annuaire/User/Contact.purs
+283
-75
Tabs.purs
...gantext/Components/Nodes/Annuaire/User/Contacts/Tabs.purs
+9
-10
No files found.
src/Gargantext/Components/GraphQL.purs
View file @
00098c86
...
...
@@ -6,7 +6,7 @@ import Data.List.Types (NonEmptyList)
import Effect.Aff (Aff)
import Effect.Class (liftEffect)
import Foreign (unsafeToForeign, ForeignError)
import Gargantext.Components.GraphQL.User (User)
import Gargantext.Components.GraphQL.User (User
, UserInfo
)
import Gargantext.Prelude
import Gargantext.Utils.Reactix as R2
import GraphQL.Client.Args (type (==>))
...
...
@@ -53,5 +53,6 @@ queryGql name q = do
-- Schema
type Schema
= { users :: { user_id :: Int } ==> Array User
= { user_infos :: { user_id :: Int } ==> Array UserInfo
, users :: { user_id :: Int } ==> Array User
}
src/Gargantext/Components/GraphQL/User.purs
View file @
00098c86
module Gargantext.Components.GraphQL.User where
import Data.Maybe (Maybe(..), maybe)
import Data.Array as A
import Data.Lens (Lens', lens)
import Data.Maybe (Maybe(..), fromMaybe, maybe)
import Gargantext.Prelude
import Type.Proxy (Proxy(..))
type UserInfo
= { ui_id :: Int
, ui_username :: String
, ui_email :: String
, ui_title :: Maybe String
, ui_source :: Maybe String
, ui_cwFirstName :: Maybe String
, ui_cwLastName :: Maybe String
, ui_cwOrganization :: Array String
, ui_cwLabTeamDepts :: Array String
, ui_cwOffice :: Maybe String
, ui_cwCity :: Maybe String
, ui_cwCountry :: Maybe String
, ui_cwRole :: Maybe String
, ui_cwTouchPhone :: Maybe String
, ui_cwTouchMail :: Maybe String }
_ui_cwFirstName :: Lens' UserInfo String
_ui_cwFirstName = lens getter setter
where
getter ({ ui_cwFirstName: val }) = fromMaybe "" val
setter ui val = ui { ui_cwFirstName = Just val }
_ui_cwLastName :: Lens' UserInfo String
_ui_cwLastName = lens getter setter
where
getter ({ ui_cwLastName: val }) = fromMaybe "" val
setter ui val = ui { ui_cwLastName = Just val }
_ui_cwCity :: Lens' UserInfo String
_ui_cwCity = lens getter setter
where
getter ({ ui_cwCity: val }) = fromMaybe "" val
setter ui val = ui { ui_cwCity = Just val }
_ui_cwCountry :: Lens' UserInfo String
_ui_cwCountry = lens getter setter
where
getter ({ ui_cwCountry: val }) = fromMaybe "" val
setter ui val = ui { ui_cwCountry = Just val }
_ui_cwLabTeamDepts :: Lens' UserInfo (Array String)
_ui_cwLabTeamDepts = lens getter setter
where
getter ({ ui_cwLabTeamDepts: val }) = val
setter ui val = ui { ui_cwLabTeamDepts = val }
_ui_cwLabTeamDeptsFirst :: Lens' UserInfo String
_ui_cwLabTeamDeptsFirst = lens getter setter
where
getter ({ ui_cwLabTeamDepts: val }) = fromMaybe "" $ A.head val
setter ui val = ui { ui_cwLabTeamDepts = fromMaybe [val] $ A.updateAt 0 val ui.ui_cwLabTeamDepts }
_ui_cwOffice :: Lens' UserInfo String
_ui_cwOffice = lens getter setter
where
getter ({ ui_cwOffice: val }) = fromMaybe "" val
setter ui val = ui { ui_cwOffice = Just val }
_ui_cwOrganization :: Lens' UserInfo (Array String)
_ui_cwOrganization = lens getter setter
where
getter ({ ui_cwOrganization: val }) = val
setter ui val = ui { ui_cwOrganization = val }
_ui_cwOrganizationFirst :: Lens' UserInfo String
_ui_cwOrganizationFirst = lens getter setter
where
getter ({ ui_cwOrganization: val }) = fromMaybe "" $ A.head val
setter ui val = ui { ui_cwOrganization = fromMaybe [val] $ A.updateAt 0 val ui.ui_cwOrganization }
_ui_cwRole :: Lens' UserInfo String
_ui_cwRole = lens getter setter
where
getter ({ ui_cwRole: val }) = fromMaybe "" val
setter ui val = ui { ui_cwRole = Just val }
_ui_cwTouchMail :: Lens' UserInfo String
_ui_cwTouchMail = lens getter setter
where
getter ({ ui_cwTouchMail: val }) = fromMaybe "" val
setter ui val = ui { ui_cwTouchMail = Just val }
_ui_cwTouchPhone :: Lens' UserInfo String
_ui_cwTouchPhone = lens getter setter
where
getter ({ ui_cwTouchPhone: val }) = fromMaybe "" val
setter ui val = ui { ui_cwTouchPhone = Just val }
type User
= { u_id :: Int
, u_hyperdata ::
{
_hu_
shared :: Maybe
{
_hc_
title :: Maybe String
,
_hc_
source :: Maybe String
,
_hc_
who :: Maybe
{
_cw_
firstName :: Maybe String
,
_cw_
lastName :: Maybe String
{ shared :: Maybe
{ title :: Maybe String
, source :: Maybe String
, who :: Maybe
{ firstName :: Maybe String
, lastName :: Maybe String
}
,
_hc_where
:: Array
{
_cw_
organization :: Array String }
,
"where"
:: Array
{ organization :: Array String }
}
}
, u_username :: String
...
...
@@ -28,28 +108,33 @@ showUser { u_id
showMUser u = maybe "" showUser u
-- Symbols
u_id :: Proxy "u_id"
u_id = Proxy
u_hyperdata :: Proxy "u_hyperdata"
u_hyperdata = Proxy
u_username :: Proxy "u_username"
u_username = Proxy
u_email :: Proxy "u_email"
u_email = Proxy
_hu_shared :: Proxy "shared"
_hu_shared = Proxy
_hc_source :: Proxy "_hc_source"
_hc_source = Proxy
_hc_title :: Proxy "_hc_title"
_hc_title = Proxy
_hc_who :: Proxy "_hc_who"
_hc_who = Proxy
_hc_where :: Proxy "_cw_where"
_hc_where = Proxy
_cw_firstName :: Proxy "_cw_firstName"
_cw_firstName = Proxy
_cw_lastName :: Proxy "_cw_lastName"
_cw_lastName = Proxy
_cw_organization :: Proxy "_cw_organization"
_cw_organization = Proxy
ui_id :: Proxy "ui_id"
ui_id = Proxy
ui_username :: Proxy "ui_username"
ui_username = Proxy
ui_email :: Proxy "ui_email"
ui_email = Proxy
ui_title :: Proxy "ui_title"
ui_title = Proxy
ui_source :: Proxy "ui_source"
ui_source = Proxy
ui_cwFirstName :: Proxy "ui_cwFirstName"
ui_cwFirstName = Proxy
ui_cwLastName :: Proxy "ui_cwLastName"
ui_cwLastName = Proxy
ui_cwCity :: Proxy "ui_cwCity"
ui_cwCity = Proxy
ui_cwCountry :: Proxy "ui_cwCountry"
ui_cwCountry = Proxy
ui_cwLabTeamDepts :: Proxy "ui_cwLabTeamDepts"
ui_cwLabTeamDepts = Proxy
ui_cwOrganization :: Proxy "ui_cwOrganization"
ui_cwOrganization = Proxy
ui_cwOffice :: Proxy "ui_cwOffice"
ui_cwOffice = Proxy
ui_cwRole :: Proxy "ui_cwRole"
ui_cwRole = Proxy
ui_cwTouchMail :: Proxy "ui_cwTouchMail"
ui_cwTouchMail = Proxy
ui_cwTouchPhone :: Proxy "ui_cwTouchPhone"
ui_cwTouchPhone = Proxy
src/Gargantext/Components/Nodes/Annuaire/Tabs.purs
View file @
00098c86
...
...
@@ -11,6 +11,7 @@ import Effect.Aff (Aff)
import Gargantext.Components.App.Data (Boxes)
import Gargantext.Components.DocsTable as DT
import Gargantext.Components.DocsTable.Types (Year)
import Gargantext.Components.GraphQL.User (UserInfo)
import Gargantext.Components.NgramsTable as NT
import Gargantext.Components.NgramsTable.Core as NTC
import Gargantext.Components.Nodes.Annuaire.User.Contacts.Types (ContactData)
...
...
@@ -52,7 +53,7 @@ modeTabType' Communication = CTabAuthors
type TabsProps =
( boxes :: Boxes
, cacheState :: T.Box LTypes.CacheState
,
contactData :: ContactData
,
defaultListId :: Int
, frontends :: Frontends
, nodeId :: Int
, session :: Session
...
...
@@ -68,21 +69,21 @@ tabsCpt = here.component "tabs" cpt where
yearFilter <- T.useBox (Nothing :: Maybe Year)
pure $ Tab.tabs { activeTab, tabs: tabs' yearFilter props }
tabs' yearFilter props@{ boxes, sidePanel } =
tabs' yearFilter props@{ boxes,
defaultListId,
sidePanel } =
[ "Documents" /\ docs
, "Patents" /\ ngramsView (viewProps Patents)
, "Books" /\ ngramsView (viewProps Books)
, "Communication" /\ ngramsView (viewProps Communication)
, "Trash" /\ docs -- TODO pass-in trash mode
] where
viewProps mode = Record.merge props { defaultListId: props.contactData.defaultListId
, mode }
viewProps mode = Record.merge props { mode }
totalRecords = 4736 -- TODO lol
docs = DT.docViewLayout (Record.merge { boxes, sidePanel } $ Record.merge dtCommon dtExtra)
dtCommon = RX.pick props :: Record DTCommon
dtExtra =
{ chart: mempty
, listId: props.contactData.defaultListId
--, listId: props.contactData.defaultListId
, listId: defaultListId
, mCorpusId: Nothing
, showSearch: true
, tabType: TabPairing TabDocs
...
...
@@ -100,8 +101,7 @@ type DTCommon =
)
type NgramsViewTabsProps =
( defaultListId :: Int
, mode :: Mode
( mode :: Mode
| TabsProps )
ngramsView :: R2.Leaf NgramsViewTabsProps
...
...
src/Gargantext/Components/Nodes/Annuaire/User.purs
View file @
00098c86
...
...
@@ -4,33 +4,29 @@ module Gargantext.Components.Nodes.Annuaire.User
)
where
import Gargantext.Components.GraphQL.User
import Gargantext.Prelude
import Data.Array as A
import Data.Either (Either(..))
import Data.Lens as L
import Data.Either (Either)
import Data.Maybe (Maybe(..), fromMaybe)
import Effect (Effect)
import Effect.Aff (Aff, launchAff_)
import Effect.Class (liftEffect)
import Gargantext.Components.App.Data (Boxes)
import Gargantext.Components.GraphQL (queryGql)
import Gargantext.Components.InputWithEnter (inputWithEnter)
import Gargantext.Components.Nodes.Annuaire.Tabs as Tabs
import Gargantext.Components.Nodes.Annuaire.User.Contact (getUserInfoWithReload, saveUserInfo, contactInfos)
import Gargantext.Components.Nodes.Annuaire.User.Contacts.Types (Contact(..), ContactData, ContactTouch(..), ContactWhere(..), ContactWho(..), HyperdataContact(..), HyperdataUser(..), _city, _country, _firstName, _labTeamDeptsJoinComma, _lastName, _mail, _office, _organizationJoinComma, _ouFirst, _phone, _role, _shared, _touch, _who, defaultContactTouch, defaultContactWhere, defaultContactWho, defaultHyperdataContact, defaultHyperdataUser)
import Gargantext.Components.Nodes.Lists.Types as LT
import Gargantext.Config.REST (RESTError(..), logRESTError)
import Gargantext.Config.REST (RESTError, logRESTError)
import Gargantext.Config.Utils (handleRESTError)
import Gargantext.Ends (Frontends)
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Routes as Routes
import Gargantext.Sessions (WithSession, WithSessionContext, Session, get, put, sessionId)
import Gargantext.Types (NodeType(..))
import Gargantext.Types (
FrontendError,
NodeType(..))
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2
import GraphQL.Client.Args (type (==>), (=>>))
import GraphQL.Client.Query (query_)
import GraphQL.Client.Types (class GqlQuery)
import Reactix as R
import Reactix.DOM.HTML as H
import Record as Record
...
...
@@ -59,98 +55,10 @@ displayCpt = here.component "display" cpt
[ H.div { className: "col-md-2" } [ H.img { src: "/images/Gargantextuel-212x300.jpg"} ]
, H.div { className: "col-md-1"} []
, H.div { className: "col-md-8"} children
]]]]
-- | TODO format data in better design (UI) shape
contactInfos :: HyperdataUser -> (HyperdataUser -> Effect Unit) -> Array R.Element
contactInfos h onUpdateHyperdata = item <$> contactInfoItems
where
item {label, defaultVal, lens} =
contactInfoItem { hyperdata: h
, label
, lens
, onUpdateHyperdata
, placeholder: defaultVal }
contactInfoItems :: Array {label:: String, defaultVal:: String, lens:: HyperdataUserLens}
contactInfoItems =
[ {label: "Last Name" , defaultVal: "Empty Last Name" , lens: _shared <<< _who <<< _lastName }
, {label: "First Name" , defaultVal: "Empty First Name" , lens: _shared <<< _who <<< _firstName }
, {label: "Organisation" , defaultVal: "Empty Organisation" , lens: _shared <<< _ouFirst <<< _organizationJoinComma}
, {label: "Lab/Team/Dept", defaultVal: "Empty Lab/Team/Dept", lens: _shared <<< _ouFirst <<< _labTeamDeptsJoinComma}
, {label: "Office" , defaultVal: "Empty Office" , lens: _shared <<< _ouFirst <<< _office }
, {label: "City" , defaultVal: "Empty City" , lens: _shared <<< _ouFirst <<< _city }
, {label: "Country" , defaultVal: "Empty Country" , lens: _shared <<< _ouFirst <<< _country }
, {label: "Role" , defaultVal: "Empty Role" , lens: _shared <<< _ouFirst <<< _role }
, {label: "Phone" , defaultVal: "Empty Phone" , lens: _shared <<< _ouFirst <<< _touch <<< _phone }
, {label: "Mail" , defaultVal: "Empty Mail" , lens: _shared <<< _ouFirst <<< _touch <<< _mail }
]
type HyperdataUserLens = L.ALens' HyperdataUser String
type ContactInfoItemProps =
( hyperdata :: HyperdataUser
, label :: String
, lens :: HyperdataUserLens
, onUpdateHyperdata :: HyperdataUser -> Effect Unit
, placeholder :: String
)
contactInfoItem :: Record ContactInfoItemProps -> R.Element
contactInfoItem props = R.createElement contactInfoItemCpt props []
contactInfoItemCpt :: R.Component ContactInfoItemProps
contactInfoItemCpt = here.component "contactInfoItem" cpt
where
cpt {hyperdata, label, lens, onUpdateHyperdata, placeholder} _ = do
isEditing <- T.useBox false
isEditing' <- T.useLive T.unequal isEditing
let value = (L.view cLens hyperdata) :: String
valueRef <- R.useRef value
pure $ H.div { className: "form-group row" }
[ H.span { className: "col-sm-2 col-form-label" } [ H.text label ]
, item isEditing' isEditing valueRef
]
where
cLens = L.cloneLens lens
item false isEditing valueRef =
H.div { className: "input-group col-sm-6" }
[ H.input { className: "form-control"
, defaultValue: placeholder'
, disabled: 1
, type: "text" }
, H.div { className: "btn input-group-append"
, on: { click: onClick } } [
H.div { className: "input-group-text fa fa-pencil" } []
]
]
where
placeholder' = R.readRef valueRef
onClick _ = T.write_ true isEditing
item true isEditing valueRef =
H.div { className: "input-group col-sm-6" }
[ inputWithEnter {
autoFocus: true
, className: "form-control"
, defaultValue: R.readRef valueRef
, onBlur: R.setRef valueRef
, onEnter: onClick
, onValueChanged: R.setRef valueRef
, placeholder
, type: "text"
}
, H.div { className: "btn input-group-append"
, on: { click: onClick } }
[ H.div { className: "input-group-text fa fa-floppy-o" } []
]
]
where
onClick _ = do
T.write_ true isEditing
let newHyperdata = (L.over cLens (\_ -> R.readRef valueRef) hyperdata) :: HyperdataUser
onUpdateHyperdata newHyperdata
{-
listElement :: Array R.Element -> R.Element
...
...
@@ -197,16 +105,16 @@ userLayoutWithKeyCpt = here.component "userLayoutWithKey" cpt where
cacheState <- T.useBox LT.CacheOn
useLoader { errorHandler
, loader: getUserWithReload
, loader: getUser
Info
WithReload
, path: { nodeId, reload: reload', session }
, render: \
contactData@{contactNode: Contact {name, hyperdata}
} ->
, render: \
userInfo@{ ui_username
} ->
H.ul { className: "col-md-12 list-group" } [
display { title: fromMaybe "no name"
name
}
(contactInfos
hyperdata (onUpdateHyperdata
reload))
display { title: fromMaybe "no name"
(Just ui_username)
}
(contactInfos
userInfo (onUpdateUserInfo boxes.errors
reload))
, Tabs.tabs {
boxes
, cacheState
,
contactData
,
defaultListId: 424242
, frontends
, nodeId
, session
...
...
@@ -216,12 +124,16 @@ userLayoutWithKeyCpt = here.component "userLayoutWithKey" cpt where
}
where
errorHandler = logRESTError here "[userLayoutWithKey]"
onUpdate
Hyperdata :: T2.ReloadS -> HyperdataUser
-> Effect Unit
onUpdate
Hyperdata reload hd
= do
onUpdate
UserInfo :: T.Box (Array FrontendError) -> T2.ReloadS -> UserInfo
-> Effect Unit
onUpdate
UserInfo errors reload ui
= do
launchAff_ $ do
_ <- saveContactHyperdata session nodeId hd
res <- saveUserInfo session nodeId ui
handleRESTError errors res $ \_ ->
liftEffect $ T2.reload reload
saveContactHyperdata :: Session -> Int -> HyperdataUser -> Aff (Either RESTError Int)
saveContactHyperdata session id = put session (Routes.NodeAPI Node (Just id) "")
-- | toUrl to get data XXX
getContact :: Session -> Int -> Aff (Either RESTError ContactData)
getContact session id = do
...
...
@@ -234,71 +146,3 @@ getContact session id = do
-- Nothing ->
-- throwError $ error "Missing default list"
pure $ (\contactNode -> { contactNode, defaultListId: 424242 }) <$> eContactNode
getUserWithReload :: { nodeId :: Int
, reload :: T2.Reload
, session :: Session} -> Aff (Either RESTError ContactData)
getUserWithReload {nodeId, session} = getUser session nodeId -- getContact session nodeId
getUser :: Session -> Int -> Aff (Either RESTError ContactData)
getUser session id = do
{ users } <- queryGql "get user"
{ users: { user_id: id } =>>
{ u_id
, u_hyperdata:
{ _hu_shared:
{ _hc_title
, _hc_source
, _hc_who:
{ _cw_firstName
, _cw_lastName }
, _hc_where:
{ _cw_organization }
}
}
, u_username
, u_email } }
liftEffect $ here.log2 "[getUser] users" users
pure $ case A.head users of
Nothing -> Left (CustomError $ "user with id " <> show id <> " not found")
-- NOTE Contact is at G.C.N.A.U.C.Types
Just u -> Right $ { contactNode: Contact
{ id: u.u_id
, date: Nothing
, hyperdata: HyperdataUser
{ shared: (\shared -> HyperdataContact
{ bdd: Nothing
, who: (\who -> ContactWho
{ idWho: Nothing
, firstName: who._cw_firstName
, lastName: who._cw_lastName
, keywords: []
, freetags: []
}) <$> shared._hc_who
, ou: (\ou -> ContactWhere
{ organization: ou._cw_organization
, labTeamDepts: []
, role: Nothing
, office: Nothing
, country: Nothing
, city: Nothing
, touch: Nothing
, entry: Nothing
, exit: Nothing }) <$> shared._hc_where
, source: shared._hc_source
, title: shared._hc_title
, lastValidation: Nothing
, uniqId: Nothing
, uniqIdBdd: Nothing
}) <$> u.u_hyperdata._hu_shared
}
, name: Just u.u_username
, parentId: Nothing
, typename: Nothing
, userId: Just u.u_id }
, defaultListId: 424242 }
saveContactHyperdata :: Session -> Int -> HyperdataUser -> Aff (Either RESTError Int)
saveContactHyperdata session id h = do
put session (Routes.NodeAPI Node (Just id) "") h
src/Gargantext/Components/Nodes/Annuaire/User/Contact.purs
View file @
00098c86
module Gargantext.Components.Nodes.Annuaire.User.Contact
( module Gargantext.Components.Nodes.Annuaire.User.Contacts.Types
, contactInfos
, contactLayout
, getUserInfo
, getUserInfoWithReload
, saveContactHyperdata
, saveUserInfo
) where
import Data.Either (Either)
import Gargantext.Components.GraphQL.User
import Gargantext.Prelude
import Affjax.RequestBody (RequestBody(..))
import Data.Array as A
import Data.Either (Either(..))
import Data.Lens as L
import Data.Maybe (Maybe(..), fromMaybe)
import Effect (Effect)
import Effect.Aff (Aff, launchAff_)
import Effect.Class (liftEffect)
import Gargantext.Components.App.Data (Boxes)
import Gargantext.Components.GraphQL (queryGql)
import Gargantext.Components.InputWithEnter (inputWithEnter)
import Gargantext.Components.Nodes.Annuaire.User.Contacts.Tabs as Tabs
import Gargantext.Components.Nodes.Annuaire.User.Contacts.Types (Contact'(..), ContactData', ContactTouch(..), ContactWhere(..), ContactWho(..), HyperdataContact(..), HyperdataUser(..), _city, _country, _firstName, _labTeamDeptsJoinComma, _lastName, _mail, _office, _organizationJoinComma, _ouFirst, _phone, _role, _shared, _touch, _who, defaultContactTouch, defaultContactWhere, defaultContactWho, defaultHyperdataContact, defaultHyperdataUser)
import Gargantext.Components.Nodes.Lists.Types as LT
import Gargantext.Config.REST (RESTError, logRESTError)
import Gargantext.Config.REST (RESTError
(..)
, logRESTError)
import Gargantext.Ends (Frontends)
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Prelude
import Gargantext.Routes as Routes
import Gargantext.Sessions (Session, get, put, sessionId)
import Gargantext.Types (NodeType(..))
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2
import GraphQL.Client.Args (type (==>), (=>>))
import Reactix as R
import Reactix.DOM.HTML as H
import Record as Record
...
...
@@ -51,36 +62,60 @@ displayCpt = here.component "display" cpt
[ H.div { className: "col-md-2" } [ H.img { src: "/images/Gargantextuel-212x300.jpg"} ]
, H.div { className: "col-md-1"} []
, H.div { className: "col-md-8"} children
]]]]
]
]
]
]
-- | TODO format data in better design (UI) shape
contactInfos ::
HyperdataContact -> (HyperdataContact
-> Effect Unit) -> Array R.Element
contactInfos
h onUpdateHyperdata
= item <$> contactInfoItems where
item { label, lens, defaultVal
: placeholder
} =
contactInfoItem {
label, lens, onUpdateHyperdata, placeholder, hyperdata: h
}
contactInfos ::
UserInfo -> (UserInfo
-> Effect Unit) -> Array R.Element
contactInfos
userInfo onUpdateUserInfo
= item <$> contactInfoItems where
item { label, lens, defaultVal } =
contactInfoItem {
defaultVal, label, lens, onUpdateUserInfo, userInfo
}
contactInfoItems :: Array {label:: String, defaultVal:: String, lens::
HyperdataContact
Lens}
contactInfoItems :: Array {label:: String, defaultVal:: String, lens::
UserInfo
Lens}
contactInfoItems =
[ {
label: "Last Name" , defaultVal: "Empty Last Name" , lens: _who <<< _lastName
}
, {
label: "First Name" , defaultVal: "Empty First Name" , lens: _who <<< _firstName
}
, {
label: "Organisation" , defaultVal: "Empty Organisation" , lens: _ouFirst <<< _organizationJoinComma
}
, {
label: "Lab/Team/Dept", defaultVal: "Empty Lab/Team/Dept", lens: _ouFirst <<< _labTeamDeptsJoinComma
}
, {
label: "Office" , defaultVal: "Empty Office" , lens: _ouFirst <<< _office
}
, {
label: "City" , defaultVal: "Empty City" , lens: _ouFirst <<< _city
}
, {
label: "Country" , defaultVal: "Empty Country" , lens: _ouFirst <<< _country
}
, {
label: "Role" , defaultVal: "Empty Role" , lens: _ouFirst <<< _role
}
, {
label: "Phone" , defaultVal: "Empty Phone" , lens: _ouFirst <<< _touch <<< _phone
}
, {
label: "Mail" , defaultVal: "Empty Mail" , lens: _ouFirst <<< _touch <<< _mail
}
[ {
label: "Last Name" , defaultVal: "Empty Last Name" , lens: _ui_cwLastName
}
, {
label: "First Name" , defaultVal: "Empty First Name" , lens: _ui_cwFirstName
}
, {
label: "Organisation" , defaultVal: "Empty Organisation" , lens: _ui_cwOrganizationFirst
}
, {
label: "Lab/Team/Dept", defaultVal: "Empty Lab/Team/Dept", lens: _ui_cwLabTeamDeptsFirst
}
, {
label: "Office" , defaultVal: "Empty Office" , lens: _ui_cwOffice
}
, {
label: "City" , defaultVal: "Empty City" , lens: _ui_cwCity
}
, {
label: "Country" , defaultVal: "Empty Country" , lens: _ui_cwCountry
}
, {
label: "Role" , defaultVal: "Empty Role" , lens: _ui_cwRole
}
, {
label: "Phone" , defaultVal: "Empty Phone" , lens: _ui_cwTouchPhone
}
, {
label: "Mail" , defaultVal: "Empty Mail" , lens: _ui_cwTouchMail
}
]
type HyperdataContactLens = L.ALens' HyperdataContact String
type UserInfoLens = L.ALens' UserInfo String
--
-- contactInfos' :: HyperdataContact -> (HyperdataContact -> Effect Unit) -> Array R.Element
-- contactInfos' h onUpdateHyperdata = item <$> contactInfoItems where
-- item { label, lens, defaultVal: placeholder } =
-- contactInfoItem { label, lens, onUpdateHyperdata, placeholder, hyperdata: h }
--
-- contactInfoItems' :: Array {label:: String, defaultVal:: String, lens:: HyperdataContactLens}
-- contactInfoItems' =
-- [ {label: "Last Name" , defaultVal: "Empty Last Name" , lens: _who <<< _lastName }
-- , {label: "First Name" , defaultVal: "Empty First Name" , lens: _who <<< _firstName }
-- , {label: "Organisation" , defaultVal: "Empty Organisation" , lens: _ouFirst <<< _organizationJoinComma}
-- , {label: "Lab/Team/Dept", defaultVal: "Empty Lab/Team/Dept", lens: _ouFirst <<< _labTeamDeptsJoinComma}
-- , {label: "Office" , defaultVal: "Empty Office" , lens: _ouFirst <<< _office }
-- , {label: "City" , defaultVal: "Empty City" , lens: _ouFirst <<< _city }
-- , {label: "Country" , defaultVal: "Empty Country" , lens: _ouFirst <<< _country }
-- , {label: "Role" , defaultVal: "Empty Role" , lens: _ouFirst <<< _role }
-- , {label: "Phone" , defaultVal: "Empty Phone" , lens: _ouFirst <<< _touch <<< _phone }
-- , {label: "Mail" , defaultVal: "Empty Mail" , lens: _ouFirst <<< _touch <<< _mail }
-- ]
--
-- type HyperdataContactLens = L.ALens' HyperdataContact String
type ContactInfoItemProps =
(
hyperdata :: HyperdataContact
(
defaultVal :: String
, label :: String
, lens
:: HyperdataContact
Lens
, onUpdate
Hyperdata :: HyperdataContact
-> Effect Unit
,
placeholder :: String
, lens
:: UserInfo
Lens
, onUpdate
UserInfo :: UserInfo
-> Effect Unit
,
userInfo :: UserInfo
)
contactInfoItem :: R2.Leaf ContactInfoItemProps
...
...
@@ -88,47 +123,84 @@ contactInfoItem props = R.createElement contactInfoItemCpt props []
contactInfoItemCpt :: R.Component ContactInfoItemProps
contactInfoItemCpt = here.component "contactInfoItem" cpt
where
cpt {
hyperdata, label, lens, onUpdateHyperdata, placeholder
} _ = do
cpt {
defaultVal, label, lens, onUpdateUserInfo, userInfo
} _ = do
isEditing <- T.useBox false
isEditing' <- T.useLive T.unequal isEditing
let value = (L.view cLens
hyperdata
) :: String
let value = (L.view cLens
userInfo
) :: String
value
Ref <- R.useRef
value
value
Box <- T.useBox
value
pure $
H.div { className: "form-group row" }
[ H.span { className: "col-sm-2 col-form-label" } [ H.text label ]
, item isEditing' isEditing valueRef ]
, if isEditing' then
itemEditing { defaultVal, isEditing, lens, onUpdateUserInfo, userInfo, valueBox }
else
itemNotEditing { defaultVal, isEditing, lens, onUpdateUserInfo, userInfo, valueBox }
]
where
cLens = L.cloneLens lens
item false isEditing valueRef =
H.div { className: "input-group col-sm-6" }
type ItemProps =
( defaultVal :: String
, isEditing :: T.Box Boolean
, lens :: UserInfoLens
, onUpdateUserInfo :: UserInfo -> Effect Unit
, userInfo :: UserInfo
, valueBox :: T.Box String
)
itemNotEditing :: R2.Leaf ItemProps
itemNotEditing props = R.createElement itemNotEditingCpt props []
itemNotEditingCpt :: R.Component ItemProps
itemNotEditingCpt = here.component "itemEditing" cpt where
cpt { isEditing, valueBox } _ = do
valueBox' <- T.useLive T.unequal valueBox
pure $ H.div { className: "input-group col-sm-6" }
[ H.input
{ className: "form-control", type: "text"
, defaultValue: placeholder
', disabled: true }
, defaultValue: valueBox
', disabled: true }
, H.div { className: "btn input-group-append", on: { click } }
[ H.div { className: "input-group-text fa fa-pencil" } [] ]]
[ H.div { className: "input-group-text fa fa-pencil" } [] ]
]
where
placeholder' = R.readRef valueRef
click _ = T.write_ true isEditing
item true isEditing valueRef =
H.div { className: "input-group col-sm-6" }
itemEditing :: R2.Leaf ItemProps
itemEditing props = R.createElement itemEditingCpt props []
itemEditingCpt :: R.Component ItemProps
itemEditingCpt = here.component "itemNotEditing" cpt where
cpt { defaultVal, isEditing, lens, onUpdateUserInfo, userInfo, valueBox } _ = do
valueBox' <- T.useLive T.unequal valueBox
pure $ H.div { className: "input-group col-sm-6" }
[ inputWithEnter
{ autoFocus: true
, className: "form-control"
, defaultValue: R.readRef valueRef
, onBlur: R.setRef valueRef
, defaultValue: valueBox'
--, defaultValue: R.readRef valueRef
, onBlur: \v -> T.write_ v valueBox
--, onBlur: R.setRef valueRef
, onEnter: click
, onValueChanged: R.setRef valueRef
, placeholder
, onValueChanged: \v -> do
here.log2 "[itemEditingCpt] value Changed: " v
T.write_ v valueBox
--, onValueChanged: R.setRef valueRef
, placeholder: defaultVal
, type: "text" }
, H.div { className: "btn input-group-append", on: { click } }
[ H.div { className: "input-group-text fa fa-floppy-o" } [] ]]
[ H.div { className: "input-group-text fa fa-floppy-o" } [] ]
]
where
cLens = L.cloneLens lens
click _ = do
T.write_ false isEditing
let newHyperdata = (L.over cLens (\_ -> R.readRef valueRef) hyperdata) :: HyperdataContact
onUpdateHyperdata newHyperdata
--let newUserInfo = (L.over cLens (\_ -> R.readRef valueRef) userInfo) :: UserInfo
value <- T.read valueBox
here.log2 "[itemEditing] value" value
let newUserInfo = (L.set cLens value userInfo) :: UserInfo
onUpdateUserInfo newUserInfo
type ReloadProps =
( boxes :: Boxes
...
...
@@ -148,6 +220,11 @@ type KeyLayoutProps =
saveContactHyperdata :: Session -> Int -> HyperdataContact -> Aff (Either RESTError Int)
saveContactHyperdata session id = put session (Routes.NodeAPI Node (Just id) "")
saveUserInfo :: Session -> Int -> UserInfo -> Aff (Either RESTError Int)
saveUserInfo session id ui = do
-- TODO GraphQL
pure $ Left $ CustomError "TODO implement graphql for saveUserInfo"
type AnnuaireLayoutProps = ( annuaireId :: Int, session :: Session | ReloadProps )
type AnnuaireKeyLayoutProps = ( annuaireId :: Int | KeyLayoutProps )
...
...
@@ -175,27 +252,31 @@ contactLayoutWithKeyCpt = here.component "contactLayoutWithKey" cpt where
_ <- T.useLive T.unequal reload
cacheState <- T.useBox LT.CacheOn
useLoader { errorHandler
, loader: getAnnuaireContact session annuaireId
--, loader: getAnnuaireContact session annuaireId
, loader: getUserInfo session
, path: nodeId
, render: \
contactData@{contactNode: Contact' {name, hyperdata}
} ->
, render: \
userInfo@{ ui_username
} ->
H.ul { className: "col-md-12 list-group" }
[ display { title: fromMaybe "no name" name
}
(contactInfos hyperdata (onUpdateHyperdata
reload))
[ display { title: fromMaybe "no name" (Just ui_username)
}
(contactInfos userInfo (onUpdateUserInfo
reload))
, Tabs.tabs
{ boxes
, cacheState
, contactData
, defaultListId: 424242 -- TODO
, frontends
, nodeId
, session
, sidePanel: sidePanelTexts
} ] }
}
]
}
where
errorHandler = logRESTError here "[contactLayoutWithKey]"
onUpdateHyperdata :: T2.ReloadS -> HyperdataContact -> Effect Unit
onUpdateHyperdata reload hd =
launchAff_ $
saveContactHyperdata session nodeId hd *> liftEffect (T2.reload reload)
onUpdateUserInfo :: T2.ReloadS -> UserInfo -> Effect Unit
onUpdateUserInfo reload ui = do
launchAff_ $ do
_ <- saveUserInfo session nodeId ui
liftEffect (T2.reload reload)
getAnnuaireContact :: Session -> Int -> Int -> Aff (Either RESTError ContactData')
getAnnuaireContact session annuaireId id = do
...
...
@@ -208,3 +289,130 @@ getAnnuaireContact session annuaireId id = do
-- Nothing ->
-- throwError $ error "Missing default list"
pure $ (\contactNode -> { contactNode, defaultListId: 424242 }) <$> eContactNode
getUserInfoWithReload :: { nodeId :: Int
, reload :: T2.Reload
, session :: Session} -> Aff (Either RESTError UserInfo)
getUserInfoWithReload {nodeId, session} = getUserInfo session nodeId -- getContact session nodeId
getUserInfo :: Session -> Int -> Aff (Either RESTError UserInfo)
getUserInfo session id = do
{ user_infos } <- queryGql "get user infos"
{ user_infos: { user_id: id } =>>
{ ui_id
, ui_username
, ui_email
, ui_title
, ui_source
, ui_cwFirstName
, ui_cwLastName
, ui_cwCity
, ui_cwCountry
, ui_cwLabTeamDepts
, ui_cwOrganization
, ui_cwOffice
, ui_cwRole
, ui_cwTouchMail
, ui_cwTouchPhone }
}
liftEffect $ here.log2 "[getUserInfo] user infos" user_infos
pure $ case A.head user_infos of
Nothing -> Left (CustomError $ "user with id " <> show id <> " not found")
-- NOTE Contact is at G.C.N.A.U.C.Types
Just ui -> Right ui
-- Just ui -> Right $ { contactNode: Contact
-- { id: ui.ui_id
-- , date: Nothing
-- , hyperdata: HyperdataUser
-- { shared: Just $ HyperdataContact
-- { bdd: Nothing
-- , who: Just $ ContactWho
-- { idWho: Nothing
-- , firstName: ui.ui_cwFirstName
-- , lastName: ui.ui_cwLastName
-- , keywords: []
-- , freetags: []
-- }
-- , ou:
-- [ ContactWhere
-- { organization: ui.ui_cwOrganization
-- , labTeamDepts: ui.ui_cwLabTeamDepts
-- , role: ui.ui_cwRole
-- , office: ui.ui_cwOffice
-- , country: ui.ui_cwCountry
-- , city: ui.ui_cwCity
-- , touch: Nothing -- TODO
-- , entry: Nothing
-- , exit: Nothing }
-- ]
-- , source: ui.ui_source
-- , title: ui.ui_title
-- , lastValidation: Nothing
-- , uniqId: Nothing
-- , uniqIdBdd: Nothing
-- }
-- }
-- , name: Just ui.ui_username
-- , parentId: Nothing
-- , typename: Nothing
-- , userId: Just ui.ui_id }
-- , defaultListId: 424242 }
--
--getUser' :: Session -> Int -> Aff (Either RESTError ContactData)
--getUser' session id = do
-- { users } <- queryGql "get user"
-- { users: { user_id: id } =>>
-- { u_id
-- , u_hyperdata:
-- { shared:
-- { title
-- , source
-- , who:
-- { firstName
-- , lastName }
-- , "where":
-- { organization }
-- }
-- }
-- , u_username
-- , u_email } }
-- liftEffect $ here.log2 "[getUser] users" users
-- pure $ case A.head users of
-- Nothing -> Left (CustomError $ "user with id " <> show id <> " not found")
-- -- NOTE Contact is at G.C.N.A.U.C.Types
-- Just u -> Right $ { contactNode: Contact
-- { id: u.u_id
-- , date: Nothing
-- , hyperdata: HyperdataUser
-- { shared: (\shared -> HyperdataContact
-- { bdd: Nothing
-- , who: (\who -> ContactWho
-- { idWho: Nothing
-- , firstName: who.firstName
-- , lastName: who.lastName
-- , keywords: []
-- , freetags: []
-- }) <$> shared.who
-- , ou: (\ou -> ContactWhere
-- { organization: ou.organization
-- , labTeamDepts: []
-- , role: Nothing
-- , office: Nothing
-- , country: Nothing
-- , city: Nothing
-- , touch: Nothing
-- , entry: Nothing
-- , exit: Nothing }) <$> shared.where
-- , source: shared.source
-- , title: shared.title
-- , lastValidation: Nothing
-- , uniqId: Nothing
-- , uniqIdBdd: Nothing
-- }) <$> u.u_hyperdata.shared
-- }
-- , name: Just u.u_username
-- , parentId: Nothing
-- , typename: Nothing
-- , userId: Just u.u_id }
-- , defaultListId: 424242 }
src/Gargantext/Components/Nodes/Annuaire/User/Contacts/Tabs.purs
View file @
00098c86
...
...
@@ -47,10 +47,10 @@ modeTabType' Patents = CTabAuthors
modeTabType' Books = CTabAuthors
modeTabType' Communication = CTabAuthors
type TabsProps =
(
boxes
:: Boxes
type TabsProps =
( boxes
:: Boxes
, cacheState :: T.Box LTypes.CacheState
,
contactData :: ContactData'
,
defaultListId :: Int
, frontends :: Frontends
, nodeId :: Int
, session :: Session
...
...
@@ -64,7 +64,7 @@ tabsCpt = here.component "tabs" cpt
where
cpt { boxes
, cacheState
,
contactData: {defaultListId}
,
defaultListId
, frontends
, nodeId
, session
...
...
@@ -134,7 +134,6 @@ type NgramsViewTabsProps = (
ngramsView :: R2.Component NgramsViewTabsProps
ngramsView = R.createElement ngramsViewCpt
ngramsViewCpt :: R.Component NgramsViewTabsProps
ngramsViewCpt = here.component "ngramsView" cpt
where
...
...
arturo
@pdominique
mentioned in issue
#376
·
Mar 22, 2022
mentioned in issue
#376
mentioned in issue #376
Toggle commit list
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment