Commit 52ac326e authored by Alexandre Delanoë's avatar Alexandre Delanoë

Merge branch '318-dev-corpus-fields-editeable' of...

Merge branch '318-dev-corpus-fields-editeable' of ssh://gitlab.iscpif.fr:20022/gargantext/purescript-gargantext into dev-merge
parents a7b8a5a0 00901a4b
......@@ -12,6 +12,7 @@ import Effect.Class (liftEffect)
import Foreign (unsafeToForeign, ForeignError)
import Gargantext.Components.GraphQL.Node (Node)
import Gargantext.Components.GraphQL.User (User, UserInfo, UserInfoM)
import Gargantext.Ends (Backend(..))
import Gargantext.Sessions (Session(..))
import Gargantext.Utils.Reactix as R2
import GraphQL.Client.Args (type (==>))
......@@ -45,7 +46,7 @@ toJsonError :: NonEmptyList ForeignError -> JsonDecodeError
toJsonError = unsafeCoerce -- map ForeignErrors to JsonDecodeError as you wish
getClient :: Session -> Effect (Client UrqlClient Schema Mutation Void)
getClient (Session { token }) = createClient { headers, url: "http://localhost:8008/gql" }
getClient (Session { token, backend: Backend b }) = createClient { headers, url: b.baseUrl <> "/gql" }
where
headers = [ ARH.RequestHeader "Authorization" $ "Bearer " <> token ]
......
......@@ -56,3 +56,23 @@ getCorpusInfo (FTFieldList as) = case List.head (List.filter isJSON as) of
, authors:""
, totalRecords: 0
}
saveCorpusInfo :: CorpusInfo -> FTFieldList -> FTFieldList
saveCorpusInfo (CorpusInfo i) (FTFieldList fields) =
FTFieldList $ List.snoc (List.filter (not isJSON) fields) (Field {name: oName, typ: JSON { authors: i.authors
, desc: i.desc
, query: i.query
, title: i.title
, tag: oTag
}})
where
oName = case o of
Just (Field {name}) -> name
_ -> ""
oTag = case o of
Just (Field {typ: JSON {tag}}) -> tag
_ -> ""
o = List.head (List.filter isJSON fields)
......@@ -8,7 +8,6 @@ import Gargantext.Components.App.Data (Boxes)
import Gargantext.Components.NgramsTable.Loader (clearCache)
import Gargantext.Components.Node (NodePoly(..))
import Gargantext.Components.Nodes.Corpus (loadCorpusWithChild)
import Gargantext.Components.Nodes.Corpus.Types (getCorpusInfo, CorpusInfo(..), Hyperdata(..))
import Gargantext.Components.Nodes.Lists.Tabs as Tabs
import Gargantext.Components.Nodes.Lists.Types (CacheState(..))
import Gargantext.Components.Table as Table
......@@ -73,18 +72,18 @@ listsLayoutWithKeyCpt = here.component "listsLayoutWithKey" cpt where
, path
, loader: loadCorpusWithChild
, render: \corpusData@{ corpusId, corpusNode: NodePoly poly } ->
let { date, hyperdata : Hyperdata h, name } = poly
CorpusInfo { authors, desc, query } = getCorpusInfo h.fields
let { name, date, hyperdata } = poly
in
R.fragment [
Table.tableHeaderLayout {
Table.tableHeaderWithRenameLayout {
cacheState
, name
, date
, desc
, hyperdata
, nodeId: corpusId
, session
, key: "listsLayoutWithKey-header-" <> (show cacheState')
, query
, title: "Corpus " <> name
, user: authors } []
} []
, Tabs.tabs {
activeTab
, boxes
......
......@@ -17,7 +17,7 @@ import Gargantext.Components.Node (NodePoly(..))
import Gargantext.Components.Nodes.Corpus (loadCorpusWithChild)
import Gargantext.Components.Nodes.Corpus.Chart.Histo (histo)
import Gargantext.Components.Nodes.Corpus.Document as D
import Gargantext.Components.Nodes.Corpus.Types (CorpusData, CorpusInfo(..), Hyperdata(..), getCorpusInfo)
import Gargantext.Components.Nodes.Corpus.Types (CorpusData)
import Gargantext.Components.Nodes.Lists.Types as LT
import Gargantext.Components.Nodes.Texts.Types as TT
import Gargantext.Components.Reload (textsReloadContext)
......@@ -105,17 +105,16 @@ textsLayoutWithKeyCpt = here.component "textsLayoutWithKey" cpt
, loader: loadCorpusWithChild
, path: { nodeId, session }
, render: \corpusData@{ corpusId, corpusNode } -> do
let NodePoly { date, hyperdata: Hyperdata h, name } = corpusNode
CorpusInfo { authors, desc, query } = getCorpusInfo h.fields
title = "Corpus " <> name
let NodePoly { name, date, hyperdata } = corpusNode
R.fragment
[ Table.tableHeaderLayout { cacheState
[ Table.tableHeaderWithRenameLayout {
cacheState
, name
, date
, desc
, query
, title
, user: authors
, hyperdata
, nodeId: corpusId
, session
, key: "textsLayoutWithKey-" <> (show cacheState') } []
, tabs { boxes
, cacheState
......
module Gargantext.Components.Renameable where
import Effect (Effect)
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
import Gargantext.Prelude
import Effect (Effect)
import Gargantext.Components.InputWithEnter (inputWithEnter)
import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
here :: R2.Here
......@@ -18,6 +17,7 @@ type RenameableProps =
(
onRename :: String -> Effect Unit
, text :: String
, icon :: String
)
renameable :: R2.Component RenameableProps
......@@ -25,7 +25,7 @@ renameable = R.createElement renameableCpt
renameableCpt :: R.Component RenameableProps
renameableCpt = here.component "renameableCpt" cpt
where
cpt { onRename, text } _ = do
cpt { onRename, text, icon } _ = do
isEditing <- T.useBox false
state <- T.useBox text
textRef <- R.useRef text
......@@ -39,7 +39,7 @@ renameableCpt = here.component "renameableCpt" cpt
T.write_ text state
pure $ H.div { className: "renameable" } [
renameableText { isEditing, onRename, state } []
renameableText { isEditing, onRename, state, icon } []
]
type RenameableTextProps =
......@@ -47,6 +47,7 @@ type RenameableTextProps =
isEditing :: T.Box Boolean
, onRename :: String -> Effect Unit
, state :: T.Box String
, icon :: String
)
renameableText :: R2.Component RenameableTextProps
......@@ -58,9 +59,9 @@ renameableTextCpt = here.component "renameableText" cpt
isEditing' <- T.useLive T.unequal isEditing
pure $ if isEditing' then
notEditing props []
else
editing props []
else
notEditing props []
notEditing :: R2.Component RenameableTextProps
......@@ -68,15 +69,13 @@ notEditing = R.createElement notEditingCpt
notEditingCpt :: R.Component RenameableTextProps
notEditingCpt = here.component "notEditing" cpt
where
cpt { isEditing, state } _ = do
cpt { isEditing, state, icon} _ = do
state' <- T.useLive T.unequal state
pure $ H.div { className: "input-group" }
[ H.input { className: "form-control"
, defaultValue: state'
, disabled: 1
, type: "text" }
, H.div { className: "btn input-group-append"
[ H.span {className: icon} []
, H.text state'
, H.button { className: "btn input-group-append"
, on: { click: \_ -> T.write_ true isEditing } }
[ H.span { className: "fa fa-pencil" } []
]
......@@ -88,11 +87,12 @@ editing = R.createElement editingCpt
editingCpt :: R.Component RenameableTextProps
editingCpt = here.component "editing" cpt
where
cpt { isEditing, onRename, state } _ = do
cpt { isEditing, onRename, state, icon } _ = do
state' <- T.useLive T.unequal state
pure $ H.div { className: "input-group" }
[ inputWithEnter {
[ H.span {className: icon} []
, inputWithEnter {
autoFocus: false
, className: "form-control text"
, defaultValue: state'
......@@ -102,8 +102,8 @@ editingCpt = here.component "editing" cpt
, placeholder: ""
, type: "text"
}
, H.div { className: "btn input-group-append"
, on: { click: submit } }
, H.button { className: "btn input-group-append"
, on: { click: submit state' } }
[ H.span { className: "fa fa-floppy-o" } []
]
]
......
module Gargantext.Components.Table where
import Gargantext.Prelude
import Data.Array as A
import Data.Either (Either(..))
import Data.Maybe (Maybe(..))
import Data.Sequence as Seq
import Effect (Effect)
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
import Gargantext.Prelude
import Effect.Aff (launchAff_)
import Effect.Class (liftEffect)
import Gargantext.Components.FolderView as FV
import Gargantext.Components.Table.Types (ColumnName, OrderBy, OrderByDirection(..), Params, Props, TableContainerProps, columnName)
import Gargantext.Components.Forest.Tree.Node.Action.Rename (RenameValue(..), rename)
import Gargantext.Components.Nodes.Corpus (saveCorpus)
import Gargantext.Components.Nodes.Corpus.Types (CorpusInfo(..), Hyperdata(..), getCorpusInfo, saveCorpusInfo)
import Gargantext.Components.Nodes.Lists.Types as NT
import Gargantext.Components.Nodes.Types (FTFieldList)
import Gargantext.Components.Renameable (renameable)
import Gargantext.Components.Search (SearchType(..))
import Gargantext.Utils.Reactix as R2
import Gargantext.Components.Table.Types (ColumnName, OrderBy, OrderByDirection(..), Params, Props, TableContainerProps, columnName)
import Gargantext.Sessions.Types (Session)
import Gargantext.Types (NodeID)
import Gargantext.Utils.Reactix (effectLink)
import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
here :: R2.Here
here = R2.here "Gargantext.Components.Table"
......@@ -51,10 +60,155 @@ type TableHeaderLayoutProps = (
, user :: String
)
type TableHeaderWithRenameLayoutProps = (
cacheState :: T.Box NT.CacheState
, session :: Session
, hyperdata :: Hyperdata
, nodeId :: NodeID
, name :: String
, date :: String
, key :: String
)
type TableHeaderWithRenameBoxedLayoutProps = (
cacheState :: T.Box NT.CacheState
, session :: Session
, hyperdata :: Hyperdata
, nodeId :: NodeID
, name :: String
, date :: String
, key :: String
, corpusInfoS :: T.Box CorpusInfo
)
initialParams :: Params
initialParams = stateParams {page: 1, pageSize: PS10, orderBy: Nothing, searchType: SearchDoc}
-- TODO: Not sure this is the right place for this
tableHeaderWithRenameLayout :: R2.Component TableHeaderWithRenameLayoutProps
tableHeaderWithRenameLayout = R.createElement tableHeaderWithRenameLayoutCpt
tableHeaderWithRenameLayoutCpt :: R.Component TableHeaderWithRenameLayoutProps
tableHeaderWithRenameLayoutCpt = here.component "tableHeaderWithRenameLayoutCpt" cpt
where
cpt { hyperdata: Hyperdata h, nodeId, session, cacheState, name, date, key } _ = do
let corpusInfo = getCorpusInfo h.fields
corpusInfoS <- T.useBox corpusInfo
pure $ tableHeaderWithRenameBoxedLayout {hyperdata: Hyperdata h, nodeId, session, cacheState, name, date, corpusInfoS, key} []
tableHeaderWithRenameBoxedLayout :: R2.Component TableHeaderWithRenameBoxedLayoutProps
tableHeaderWithRenameBoxedLayout = R.createElement tableHeaderWithRenameBoxedLayoutCpt
tableHeaderWithRenameBoxedLayoutCpt :: R.Component TableHeaderWithRenameBoxedLayoutProps
tableHeaderWithRenameBoxedLayoutCpt = here.component "tableHeaderWithRenameBoxedLayoutCpt" cpt
where
cpt { hyperdata: Hyperdata h, nodeId, session, cacheState, name, date, corpusInfoS} _ = do
cacheState' <- T.useLive T.unequal cacheState
CorpusInfo {title, desc, query, authors} <- T.read corpusInfoS
pure $ R.fragment
[ R2.row [FV.backButton {} []]
,
R2.row
[ H.div {className: "col-md-3"} [ H.h3 {} [renameable {icon: "", text: name, onRename: onRenameCorpus} []] ]
, H.div {className: "col-md-9"}
[ H.hr {style: {height: "2px", backgroundColor: "black"}} ]
]
, R2.row
[ H.div {className: "col-md-8 content"}
[ H.p {}
[
renameable {icon: "fa fa-info", text: title, onRename: onRenameTitle} []
]
, H.p {}
[
renameable {icon: "fa fa-globe", text: desc, onRename: onRenameDesc} []
]
, H.p {}
[
renameable {icon: "fa fa-search-plus", text: query, onRename: onRenameQuery} []
]
, H.p { className: "cache-toggle"
, on: { click: cacheClick cacheState } }
[ H.span { className: "fa " <> (cacheToggle cacheState') } []
, H.text $ cacheText cacheState'
]
]
, H.div {className: "col-md-4 content"}
[ H.p {}
[
renameable {icon: "fa fa-user", text: authors, onRename: onRenameAuthors} []
]
, H.p {}
[ H.span {className: "fa fa-calendar"} []
, H.text $ " " <> date
]
]
]
]
where
onRenameCorpus newName = do
saveCorpusName {name: newName, session, nodeId}
onRenameTitle newTitle = do
_ <- T.modify (\(CorpusInfo c) -> CorpusInfo $ c {title = newTitle}) corpusInfoS
corpusInfo <- T.read corpusInfoS
let newFields = saveCorpusInfo corpusInfo h.fields
save {fields: newFields, session, nodeId}
onRenameDesc newDesc = do
_ <- T.modify (\(CorpusInfo c) -> CorpusInfo $ c {desc = newDesc}) corpusInfoS
corpusInfo <- T.read corpusInfoS
let newFields = saveCorpusInfo corpusInfo h.fields
save {fields: newFields, session, nodeId}
onRenameQuery newQuery = do
_ <- T.modify (\(CorpusInfo c) -> CorpusInfo $ c {query = newQuery}) corpusInfoS
corpusInfo <- T.read corpusInfoS
let newFields = saveCorpusInfo corpusInfo h.fields
save {fields: newFields, session, nodeId}
onRenameAuthors newAuthors = do
_ <- T.modify (\(CorpusInfo c) -> CorpusInfo $ c {authors = newAuthors}) corpusInfoS
corpusInfo <- T.read corpusInfoS
let newFields = saveCorpusInfo corpusInfo h.fields
save {fields: newFields, session, nodeId}
cacheToggle NT.CacheOn = "fa-toggle-on"
cacheToggle NT.CacheOff = "fa-toggle-off"
cacheText NT.CacheOn = "Cache On"
cacheText NT.CacheOff = "Cache Off"
cacheClick cacheState _ = do
T.modify cacheStateToggle cacheState
cacheStateToggle NT.CacheOn = NT.CacheOff
cacheStateToggle NT.CacheOff = NT.CacheOn
save :: {fields :: FTFieldList, session :: Session, nodeId :: Int} -> Effect Unit
save {fields, session, nodeId} = do
launchAff_ do
res <- saveCorpus $ {hyperdata: Hyperdata {fields}, session, nodeId}
liftEffect $ do
_ <- case res of
Left err -> here.log2 "[corpusLayoutView] onClickSave RESTError" err
_ -> pure unit
pure unit
saveCorpusName :: {name :: String, session :: Session, nodeId :: Int} -> Effect Unit
saveCorpusName {name, session, nodeId} = do
launchAff_ do
res <- rename session nodeId $ RenameValue {text: name}
liftEffect $ do
_ <- case res of
Left err -> here.log2 "[corpusLayoutView] onClickSave RESTError" err
_ -> pure unit
pure unit
tableHeaderLayout :: R2.Component TableHeaderLayoutProps
tableHeaderLayout = R.createElement tableHeaderLayoutCpt
tableHeaderLayoutCpt :: R.Component TableHeaderLayoutProps
......@@ -89,13 +243,13 @@ tableHeaderLayoutCpt = here.component "tableHeaderLayout" cpt
]
, H.div {className: "col-md-4 content"}
[ H.p {}
[ H.span {className: "fa fa-calendar"} []
, H.text $ " " <> date
]
, H.p {}
[ H.span {className: "fa fa-user"} []
, H.text $ " " <> user
]
, H.p {}
[ H.span {className: "fa fa-calendar"} []
, H.text $ " " <> date
]
]
]
]
......
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