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
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
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
Grégoire Locqueville
purescript-gargantext
Commits
65e9cf3e
Commit
65e9cf3e
authored
Jan 15, 2024
by
Alexandre Delanoë
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/600-dev-team-invite-fixes' into dev
parents
16762559
81ad30d2
Changes
27
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
1047 additions
and
984 deletions
+1047
-984
packages.dhall
packages.dhall
+39
-33
spago.dhall
spago.dhall
+1
-0
FolderView.purs
src/Gargantext/Components/FolderView.purs
+0
-5
Tree.purs
src/Gargantext/Components/Forest/Tree.purs
+2
-6
Add.purs
src/Gargantext/Components/Forest/Tree/Node/Action/Add.purs
+37
-34
Contact.purs
...argantext/Components/Forest/Tree/Node/Action/Contact.purs
+61
-50
Delete.purs
...Gargantext/Components/Forest/Tree/Node/Action/Delete.purs
+18
-13
Documentation.purs
...ext/Components/Forest/Tree/Node/Action/Documentation.purs
+8
-9
Download.purs
...rgantext/Components/Forest/Tree/Node/Action/Download.purs
+26
-17
Link.purs
src/Gargantext/Components/Forest/Tree/Node/Action/Link.purs
+19
-16
ManageTeam.purs
...antext/Components/Forest/Tree/Node/Action/ManageTeam.purs
+33
-30
Merge.purs
src/Gargantext/Components/Forest/Tree/Node/Action/Merge.purs
+27
-25
Move.purs
src/Gargantext/Components/Forest/Tree/Node/Action/Move.purs
+11
-8
Share.purs
src/Gargantext/Components/Forest/Tree/Node/Action/Share.purs
+50
-30
Update.purs
...Gargantext/Components/Forest/Tree/Node/Action/Update.purs
+49
-39
Upload.purs
...Gargantext/Components/Forest/Tree/Node/Action/Upload.purs
+27
-27
WriteNodesDocuments.purs
...mponents/Forest/Tree/Node/Action/WriteNodesDocuments.purs
+78
-73
Box.purs
src/Gargantext/Components/Forest/Tree/Node/Box.purs
+21
-13
Settings.purs
src/Gargantext/Components/Forest/Tree/Node/Settings.purs
+244
-340
Tools.purs
src/Gargantext/Components/Forest/Tree/Node/Tools.purs
+122
-36
Search.purs
src/Gargantext/Components/GraphExplorer/Topbar/Search.purs
+3
-2
InputWithAutocomplete.purs
src/Gargantext/Components/InputWithAutocomplete.purs
+12
-142
TopBar.purs
src/Gargantext/Components/PhyloExplorer/Topbar/TopBar.purs
+3
-2
TreeSearch.purs
src/Gargantext/Components/TreeSearch.purs
+9
-9
REST.purs
src/Gargantext/Config/REST.purs
+143
-18
Sessions.purs
src/Gargantext/Sessions.purs
+3
-6
Reactix.purs
src/Gargantext/Utils/Reactix.purs
+1
-1
No files found.
packages.dhall
View file @
65e9cf3e
...
@@ -104,7 +104,23 @@ let overrides =
...
@@ -104,7 +104,23 @@ let overrides =
}
}
let additions =
let additions =
{ sequences =
{ convertable-options =
{ dependencies = [ "console", "effect", "maybe", "record" ]
, repo = "https://github.com/natefaubion/purescript-convertable-options"
, version = "v1.0.0"
}
, data-default =
{ dependencies =
[ "assert", "lists", "maybe", "record", "effect", "prelude" ]
, repo = "https://github.com/thought2/purescript-data-default"
, version = "350e600a5a022c9599865a2dd14196b442f59bcc"
}
, dom-filereader =
{ dependencies = [ "aff", "arraybuffer-types", "web-file", "web-html" ]
, repo = "https://github.com/nwolverson/purescript-dom-filereader"
, version = "v5.0.0"
}
, sequences =
{ dependencies =
{ dependencies =
[ "arrays"
[ "arrays"
, "assert"
, "assert"
...
@@ -126,6 +142,28 @@ let additions =
...
@@ -126,6 +142,28 @@ let additions =
, repo = "https://github.com/garganscript/purescript-sequences.git"
, repo = "https://github.com/garganscript/purescript-sequences.git"
, version = "recursion-fix"
, version = "recursion-fix"
}
}
, read =
{ dependencies = [ "prelude", "maybe", "strings" ]
, repo = "https://github.com/truqu/purescript-read"
, version = "v1.0.1"
}
, simple-json-generics =
{ dependencies =
[ "assert"
, "control"
, "effect"
, "either"
, "foreign"
, "partial"
, "prelude"
, "simple-json"
, "transformers"
, "typelevel-prelude"
]
, repo =
"https://github.com/garganscript/purescript-simple-json-generics"
, version = "master"
}
, spec-discovery =
, spec-discovery =
{ dependencies = [ "prelude", "effect", "arrays", "spec", "node-fs" ]
{ dependencies = [ "prelude", "effect", "arrays", "spec", "node-fs" ]
, repo = "https://github.com/purescript-spec/purescript-spec-discovery"
, repo = "https://github.com/purescript-spec/purescript-spec-discovery"
...
@@ -156,28 +194,6 @@ let additions =
...
@@ -156,28 +194,6 @@ let additions =
"https://gitlab.iscpif.fr/gargantext/purescript-string-search.git"
"https://gitlab.iscpif.fr/gargantext/purescript-string-search.git"
, version = "v0.1.6"
, version = "v0.1.6"
}
}
, dom-filereader =
{ dependencies = [ "aff", "arraybuffer-types", "web-file", "web-html" ]
, repo = "https://github.com/nwolverson/purescript-dom-filereader"
, version = "v5.0.0"
}
, simple-json-generics =
{ dependencies =
[ "assert"
, "control"
, "effect"
, "either"
, "foreign"
, "partial"
, "prelude"
, "simple-json"
, "transformers"
, "typelevel-prelude"
]
, repo =
"https://github.com/garganscript/purescript-simple-json-generics"
, version = "master"
}
, tuples-native =
, tuples-native =
{ dependencies =
{ dependencies =
[ "console"
[ "console"
...
@@ -191,11 +207,6 @@ let additions =
...
@@ -191,11 +207,6 @@ let additions =
, repo = "https://github.com/garganscript/purescript-tuples-native"
, repo = "https://github.com/garganscript/purescript-tuples-native"
, version = "v2.3.0"
, version = "v2.3.0"
}
}
, read =
{ dependencies = [ "prelude", "maybe", "strings" ]
, repo = "https://github.com/truqu/purescript-read"
, version = "v1.0.1"
}
, versions =
, versions =
{ dependencies = [ "prelude" ]
{ dependencies = [ "prelude" ]
, repo = "https://github.com/hdgarrood/purescript-versions.git"
, repo = "https://github.com/hdgarrood/purescript-versions.git"
...
@@ -206,11 +217,6 @@ let additions =
...
@@ -206,11 +217,6 @@ let additions =
, repo = "https://github.com/mjepronk/purescript-web-url"
, repo = "https://github.com/mjepronk/purescript-web-url"
, version = "v2.0.0"
, version = "v2.0.0"
}
}
, convertable-options =
{ dependencies = [ "console", "effect", "maybe", "record" ]
, repo = "https://github.com/natefaubion/purescript-convertable-options"
, version = "v1.0.0"
}
}
}
in upstream // overrides // additions
in upstream // overrides // additions
spago.dhall
View file @
65e9cf3e
...
@@ -28,6 +28,7 @@ to generate this file without the comments in this block.
...
@@ -28,6 +28,7 @@ to generate this file without the comments in this block.
, "convertable-options"
, "convertable-options"
, "css"
, "css"
, "d3"
, "d3"
, "data-default"
, "datetime"
, "datetime"
, "debug"
, "debug"
, "dom-filereader"
, "dom-filereader"
...
...
src/Gargantext/Components/FolderView.purs
View file @
65e9cf3e
...
@@ -330,7 +330,6 @@ performAction = performAction' where
...
@@ -330,7 +330,6 @@ performAction = performAction' where
performAction' (DoSearch task) p = doSearch task p
performAction' (DoSearch task) p = doSearch task p
performAction' (UpdateNode params) p = updateNode params p
performAction' (UpdateNode params) p = updateNode params p
performAction' (RenameNode name) p = renameNode name p
performAction' (RenameNode name) p = renameNode name p
performAction' (ShareTeam username) p = shareTeam username p
performAction' (SharePublic { params }) p = sharePublic params p
performAction' (SharePublic { params }) p = sharePublic params p
performAction' (AddContact params) p = addContact params p
performAction' (AddContact params) p = addContact params p
performAction' (AddNode name nodeType) p = addNode' name nodeType p
performAction' (AddNode name nodeType) p = addNode' name nodeType p
...
@@ -385,10 +384,6 @@ performAction = performAction' where
...
@@ -385,10 +384,6 @@ performAction = performAction' where
GAT.insert id task tasks
GAT.insert id task tasks
here.log2 "[performAction] UpdateNode task:" task
here.log2 "[performAction] UpdateNode task:" task
shareTeam username { boxes: { errors }, nodeId: id, session } = do
eTask <- Share.shareReq session id $ Share.ShareTeamParams { username }
handleRESTError here errors eTask $ \_task -> pure unit
sharePublic params p@{ boxes: { errors }, session } = traverse_ f params where
sharePublic params p@{ boxes: { errors }, session } = traverse_ f params where
f (SubTreeOut { in: inId, out }) = do
f (SubTreeOut { in: inId, out }) = do
eTask <- Share.shareReq session inId $ Share.SharePublicParams { node_id: out }
eTask <- Share.shareReq session inId $ Share.SharePublicParams { node_id: out }
...
...
src/Gargantext/Components/Forest/Tree.purs
View file @
65e9cf3e
...
@@ -325,10 +325,6 @@ renameNode name p@{ boxes: { errors }, session, tree: (NTree (LNode {id}) _) } =
...
@@ -325,10 +325,6 @@ 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
eTask <- Share.shareReq session id $ Share.ShareTeamParams { username }
handleRESTError here errors eTask $ \_task -> pure unit
sharePublic params p@{ boxes: { errors, forestOpen }, session } = traverse_ f params where
sharePublic params p@{ boxes: { errors, forestOpen }, session } = traverse_ f params where
f (SubTreeOut { in: inId, out }) = do
f (SubTreeOut { in: inId, out }) = do
eTask <- Share.shareReq session inId $ Share.SharePublicParams { node_id: out }
eTask <- Share.shareReq session inId $ Share.SharePublicParams { node_id: out }
...
@@ -398,7 +394,6 @@ performAction (DeleteNode nt) p = deleteNode' nt p
...
@@ -398,7 +394,6 @@ performAction (DeleteNode nt) p = deleteNode' nt p
performAction (DoSearch task) p = doSearch task p
performAction (DoSearch task) p = doSearch task p
performAction (UpdateNode params) p = updateNode params p
performAction (UpdateNode params) p = updateNode params p
performAction (RenameNode name) p = renameNode name p
performAction (RenameNode name) p = renameNode name p
performAction (ShareTeam username) p = shareTeam username p
performAction (SharePublic { params }) p = sharePublic params p
performAction (SharePublic { params }) p = sharePublic params p
performAction (AddContact params) p = addContact params p
performAction (AddContact params) p = addContact params p
performAction (AddNode name nodeType) p = addNode' name nodeType p
performAction (AddNode name nodeType) p = addNode' name nodeType p
...
@@ -407,7 +402,6 @@ performAction (UploadFile nodeType fileType fileFormat lang mName contents selec
...
@@ -407,7 +402,6 @@ performAction (UploadFile nodeType fileType fileFormat lang mName contents selec
uploadFile' nodeType fileType fileFormat lang mName contents p selection
uploadFile' nodeType fileType fileFormat lang mName contents p selection
performAction (UploadArbitraryFile fileFormat mName blob selection) p =
performAction (UploadArbitraryFile fileFormat mName blob selection) p =
uploadArbitraryFile' fileFormat mName blob p selection
uploadArbitraryFile' fileFormat mName blob p selection
performAction DownloadNode _ = liftEffect $ here.log "[performAction] DownloadNode"
performAction (MoveNode {params}) p = moveNode params p
performAction (MoveNode {params}) p = moveNode params p
performAction (MergeNode {params}) p = mergeNode params p
performAction (MergeNode {params}) p = mergeNode params p
performAction (LinkNode { nodeType, params }) p = linkNode nodeType params p
performAction (LinkNode { nodeType, params }) p = linkNode nodeType params p
...
@@ -415,3 +409,5 @@ performAction RefreshTree p = refreshTree p
...
@@ -415,3 +409,5 @@ performAction RefreshTree p = refreshTree p
performAction CloseBox p = closeBox p
performAction CloseBox p = closeBox p
performAction (DocumentsFromWriteNodes params) p = documentsFromWriteNodes params p
performAction (DocumentsFromWriteNodes params) p = documentsFromWriteNodes params p
performAction NoAction _ = liftEffect $ here.log "[performAction] NoAction"
performAction NoAction _ = liftEffect $ here.log "[performAction] NoAction"
performAction DownloadNode _ = liftEffect $ here.log "[performAction] DownloadNode"
performAction (ShareTeam _) _ = liftEffect $ here.log "[performAction] ShareTeam not used as action, see Node/Action/Share instead"
src/Gargantext/Components/Forest/Tree/Node/Action/Add.purs
View file @
65e9cf3e
...
@@ -13,7 +13,7 @@ import Effect (Effect)
...
@@ -13,7 +13,7 @@ import Effect (Effect)
import Effect.Aff (Aff, launchAff_)
import Effect.Aff (Aff, launchAff_)
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Settings (SettingsBox(..), settingsBox)
import Gargantext.Components.Forest.Tree.Node.Settings (SettingsBox(..), settingsBox)
import Gargantext.Components.Forest.Tree.Node.Tools
(formChoice, panel, submitButton)
import Gargantext.Components.Forest.Tree.Node.Tools
as Tools
import Gargantext.Components.InputWithEnter (inputWithEnterWithKey)
import Gargantext.Components.InputWithEnter (inputWithEnterWithKey)
import Gargantext.Components.Lang (Lang(..), translate)
import Gargantext.Components.Lang (Lang(..), translate)
import Gargantext.Config.REST (RESTError, AffRESTError)
import Gargantext.Config.REST (RESTError, AffRESTError)
...
@@ -43,9 +43,7 @@ addNodeAsync :: Session
...
@@ -43,9 +43,7 @@ addNodeAsync :: Session
-> AffRESTError GT.AsyncTaskWithType
-> AffRESTError GT.AsyncTaskWithType
addNodeAsync session parentId q = do
addNodeAsync session parentId q = do
eTask :: Either RESTError GT.AsyncTask <- post session p q
eTask :: Either RESTError GT.AsyncTask <- post session p q
case eTask of
pure $ (\task -> GT.AsyncTaskWithType { task, typ: GT.AddNode }) <$> eTask
Left err -> pure $ Left err
Right task -> pure $ Right $ GT.AsyncTaskWithType { task, typ: GT.AddNode }
where
where
p = GR.NodeAPI GT.Node (Just parentId) (GT.asyncTaskTypePath GT.AddNode)
p = GR.NodeAPI GT.Node (Just parentId) (GT.asyncTaskTypePath GT.AddNode)
...
@@ -91,36 +89,41 @@ addNodeViewCpt = here.component "addNodeView" cpt where
...
@@ -91,36 +89,41 @@ addNodeViewCpt = here.component "addNodeView" cpt where
setNodeType' nt = do
setNodeType' nt = do
T.write_ (GT.prettyNodeType nt) nodeName
T.write_ (GT.prettyNodeType nt) nodeName
T.write_ nt nodeType
T.write_ nt nodeType
(maybeChoose /\ nt') = if length nodeTypes > 1
(maybeChoose /\ nt') =
then ([ formChoice { items: nodeTypes
if length nodeTypes > 1 then
, default: nodeType'
[ Tools.formChoice { items: nodeTypes
, callback: setNodeType'
, default: nodeType'
, print: print hasChromeAgent' } [] ] /\ nodeType')
, callback: setNodeType'
else ([H.div {} [H.text $ "Creating a node of type "
, print: print hasChromeAgent' } []
<> show defaultNt
] /\ nodeType'
<> " with name:"
else
]
[ H.div {}
] /\ defaultNt
[H.text $ "Creating a node of type "
)
<> show defaultNt
where
<> " with name:"
defaultNt = (fromMaybe Error $ head nodeTypes)
]
maybeEdit = [ if edit
] /\ defaultNt
then inputWithEnterWithKey {
where
onBlur: \val -> T.write_ val nodeName
defaultNt = fromMaybe Error $ head nodeTypes
, onEnter: \_ -> launchAff_ $ dispatch (AddNode nodeName' nt')
maybeEdit =
, onValueChanged: \val -> T.write_ val nodeName
if edit then
, autoFocus: true
[ inputWithEnterWithKey {
, className: "form-control"
onBlur: \val -> T.write_ val nodeName
, defaultValue: nodeName' -- (prettyNodeType nt')
, onEnter: \_ -> launchAff_ $ dispatch (AddNode nodeName' nt')
, placeholder: nodeName' -- (prettyNodeType nt')
, onValueChanged: \val -> T.write_ val nodeName
, type: "text"
, autoFocus: true
, key: show nodeType'
, className: "form-control"
, required: false
, defaultValue: nodeName' -- (prettyNodeType nt')
}
, placeholder: nodeName' -- (prettyNodeType nt')
else H.div {} []
, type: "text"
]
, key: show nodeType'
, required: false
pure $ panel (maybeChoose <> maybeEdit) (submitButton (AddNode nodeName' nt') dispatch)
} ]
else []
pure $ Tools.panelWithSubmitButton { action: AddNode nodeName' nt'
, dispatch
, mError: Nothing } (maybeChoose <> maybeEdit)
-- END Create Node
-- END Create Node
...
...
src/Gargantext/Components/Forest/Tree/Node/Action/Contact.purs
View file @
65e9cf3e
...
@@ -3,20 +3,21 @@ module Gargantext.Components.Forest.Tree.Node.Action.Contact where
...
@@ -3,20 +3,21 @@ module Gargantext.Components.Forest.Tree.Node.Action.Contact where
import Prelude
import Prelude
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..))
import Effect.Aff (Aff, launchAff)
import Effect.Aff (Aff, launchAff
_
)
import Formula as F
import Formula as F
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Action.Contact.Types (AddContactParams(..))
import Gargantext.Components.Forest.Tree.Node.Action.Contact.Types (AddContactParams(..))
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Tools as Tools
import Gargantext.Components.InputWithEnter (inputWithEnter)
import Gargantext.Config.REST (AffRESTError)
import Gargantext.Config.REST (AffRESTError)
import Gargantext.Routes as GR
import Gargantext.Routes as GR
import Gargantext.Sessions (Session, post)
import Gargantext.Sessions (Session, post)
import Gargantext.Types (ID)
import Gargantext.Types (ID)
import Gargantext.Types as GT
import Gargantext.Types as GT
import Gargantext.Utils.Reactix as R2
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
here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Contact"
here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Contact"
...
@@ -34,21 +35,19 @@ actionAddContact = R.createElement actionAddContactCpt
...
@@ -34,21 +35,19 @@ actionAddContact = R.createElement actionAddContactCpt
actionAddContactCpt :: R.Component ActionAddContact
actionAddContactCpt :: R.Component ActionAddContact
actionAddContactCpt = here.component "actionAddContact" cpt where
actionAddContactCpt = here.component "actionAddContact" cpt where
cpt { dispatch, id } _ = do
cpt { dispatch, id } _ = do
isOpen <- T.useBox true
pure $
pure $ textInputBox
Tools.panelNoFooter { mError: Nothing }
{ boxAction: \p -> AddContact p
[ textInputBox
, boxName:"addContact"
{ boxAction: \p -> AddContact p
, dispatch
, dispatch
, id
, id
, isOpen
, params: { firstname: "", lastname: "" } }
, params: {firstname:"First Name", lastname: "Last Name"} }
]
type TextInputBoxProps =
type TextInputBoxProps =
( boxAction :: AddContactParams -> Action
( boxAction :: AddContactParams -> Action
, boxName :: String
, dispatch :: Action -> Aff Unit
, dispatch :: Action -> Aff Unit
, id :: ID
, id :: ID
, isOpen :: T.Box Boolean
, params :: Record AddContactProps )
, params :: Record AddContactProps )
type AddContactProps = ( firstname :: String, lastname :: String )
type AddContactProps = ( firstname :: String, lastname :: String )
...
@@ -57,38 +56,50 @@ textInputBox :: R2.Leaf TextInputBoxProps
...
@@ -57,38 +56,50 @@ textInputBox :: R2.Leaf TextInputBoxProps
textInputBox = R2.leaf textInputBoxCpt
textInputBox = R2.leaf textInputBoxCpt
textInputBoxCpt :: R.Component TextInputBoxProps
textInputBoxCpt :: R.Component TextInputBoxProps
textInputBoxCpt = here.component "textInputBox" cpt where
textInputBoxCpt = here.component "textInputBox" cpt where
cpt { boxName, boxAction, dispatch, isOpen
cpt { boxAction, dispatch
, params: { firstname, lastname } } _ =
, params: { firstname, lastname } } _ = do
content <$> T.useLive T.unequal isOpen
<*> T.useBox firstname <*> T.useBox lastname
firstName <- T.useBox firstname
lastName <- T.useBox lastname
let submitF unit = do
f <- T.read firstName
l <- T.read lastName
launchAff_ $
dispatch (boxAction $ AddContactParams { firstname: f, lastname: l })
pure $ H.div { className: "from-group" }
[ textInput "First name" firstName firstname submitF true
, textInput "Last name" lastName lastname submitF false
, R2.row [
submitBtn submitF
]
]
where
where
content false _ _ = H.div {} []
textInput placeholder value defaultValue submitF autoFocus =
content true firstName lastName =
R2.row
H.div { className: "from-group row" }
[ R2.col 8
[ textInput firstName
[ inputWithEnter { onBlur: \s -> T.write_ s value
, textInput lastName
, onEnter: submitF
, submitBtn firstName lastName
, onValueChanged: \s -> T.write_ s value
, cancelBtn
, autoFocus
] where
, className: "form-control"
textInput value =
, defaultValue
H.div {className: "col-md-8"}
, placeholder
[ F.bindInput
, type: "value"
{ value, className: "form-control", type: "text"
, required: true }
, placeholder: (boxName <> " Node") } ]
]
submitBtn first last =
-- [ F.bindInput
H.a
-- { value
{ className: "btn glyphitem fa fa-ok col-md-2 pull-left"
-- , className: "form-control"
, type: "button", on: { click }, title:"Submit"
-- , type: "text"
} [] where
-- , placeholder: boxName <> " Node" }
click _ = do
-- ]
f <- T.read first
]
l <- T.read last
submitBtn submitF =
T.write_ false isOpen
H.a { className: "btn glyphitem fa fa-send col-md-2 pull-left"
launchAff $
, type: "button"
dispatch (boxAction $ AddContactParams { firstname: f, lastname: l })
, on: { click: \_ -> submitF unit }
cancelBtn =
, title:"Submit"
H.a
} []
{ className: "btn text-danger glyphitem fa fa-remove col-md-2 pull-left"
, on: { click }, title: "Cancel", type: "button"
} [] where
click _ = T.write_ false isOpen
src/Gargantext/Components/Forest/Tree/Node/Action/Delete.purs
View file @
65e9cf3e
...
@@ -6,7 +6,7 @@ import Gargantext.Prelude
...
@@ -6,7 +6,7 @@ import Gargantext.Prelude
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..))
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(..))
import Gargantext.Components.Forest.Tree.Node.Tools
(submitButton, panel)
import Gargantext.Components.Forest.Tree.Node.Tools
as Tools
import Gargantext.Config.REST (AffRESTError)
import Gargantext.Config.REST (AffRESTError)
import Gargantext.Routes (SessionRoute(..))
import Gargantext.Routes (SessionRoute(..))
import Gargantext.Sessions (Session, delete, put_)
import Gargantext.Sessions (Session, delete, put_)
...
@@ -53,21 +53,26 @@ actionDeleteUser = R.createElement actionDeleteUserCpt
...
@@ -53,21 +53,26 @@ actionDeleteUser = R.createElement actionDeleteUserCpt
actionDeleteUserCpt :: R.Component Delete
actionDeleteUserCpt :: R.Component Delete
actionDeleteUserCpt = here.component "actionDeleteUser" cpt where
actionDeleteUserCpt = here.component "actionDeleteUser" cpt where
cpt _ _ = do
cpt _ _ = do
pure $ panel [ H.div { style: {margin: "10px"}}
pure $
[ H.text $ "Yes, we are RGPD compliant!"
Tools.panelNoFooter { mError: Nothing }
<> " But you can not delete User Node yet."
[ H.div { style: {margin: "10px"}}
<> " We are still on development."
[ H.text $ "Yes, we are RGPD compliant!"
<> " Thanks for your comprehensin."
<> " But you can not delete User Node yet."
]
<> " We are still on development."
] (H.div {} [])
<> " Thanks for your comprehensin."
]
]
actionDeleteOther :: R2.Component Delete
actionDeleteOther :: R2.Component Delete
actionDeleteOther = R.createElement actionDeleteOtherCpt
actionDeleteOther = R.createElement actionDeleteOtherCpt
actionDeleteOtherCpt :: R.Component Delete
actionDeleteOtherCpt :: R.Component Delete
actionDeleteOtherCpt = here.component "actionDeleteOther" cpt where
actionDeleteOtherCpt = here.component "actionDeleteOther" cpt where
cpt { dispatch, nodeType } _ = do
cpt { dispatch, nodeType } _ = do
pure $ panel (map (\t -> H.p {} [H.text t])
pure $
[ "Are your sure you want to delete it ?"
Tools.panelWithSubmitButton { action: DeleteNode nodeType
, "If yes, click again below."
, dispatch
]
, mError: Nothing }
) (submitButton (DeleteNode nodeType) dispatch)
(map (\t -> H.p {} [H.text t])
[ "Are your sure you want to delete it ?"
, "If yes, click again below."
])
src/Gargantext/Components/Forest/Tree/Node/Action/Documentation.purs
View file @
65e9cf3e
module Gargantext.Components.Forest.Tree.Node.Action.Documentation where
module Gargantext.Components.Forest.Tree.Node.Action.Documentation where
import Reactix as R
import Data.Maybe (Maybe(..))
import Reactix.DOM.HTML as H
import Gargantext.Components.Forest.Tree.Node.Tools as Tools
import Gargantext.Prelude (map, pure, show, ($), (<>))
import Gargantext.Prelude (map, pure, show, ($), (<>))
import Gargantext.Components.Forest.Tree.Node.Tools (panel)
import Gargantext.Types (NodeType)
import Gargantext.Types (NodeType)
import Gargantext.Types as GT
import Gargantext.Types as GT
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
here :: R2.Here
here :: R2.Here
here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Documentation"
here = R2.here "Gargantext.Components.Forest.Tree.Node.Action.Documentation"
...
@@ -22,10 +21,10 @@ actionDoc = R.createElement actionDocCpt
...
@@ -22,10 +21,10 @@ actionDoc = R.createElement actionDocCpt
actionDocCpt :: R.Component ActionDoc
actionDocCpt :: R.Component ActionDoc
actionDocCpt = here.component "actionDoc" cpt where
actionDocCpt = here.component "actionDoc" cpt where
cpt { nodeType } _ = do
cpt { nodeType } _ = do
pure $
panel ([ infoTitle nodeType ]
pure $
<> (map (\info -> H.p {} [H.text info]) $ docOf nodeType)
Tools.panelNoFooter { mError: Nothing }
)
([ infoTitle nodeType ]
(H.div {} []
)
<> (map (\info -> H.p {} [ H.text info ]) $ docOf nodeType)
)
where
where
infoTitle :: NodeType -> R.Element
infoTitle :: NodeType -> R.Element
infoTitle nt = H.div { style: {margin: "10px"}}
infoTitle nt = H.div { style: {margin: "10px"}}
...
...
src/Gargantext/Components/Forest/Tree/Node/Action/Download.purs
View file @
65e9cf3e
...
@@ -5,7 +5,7 @@ import Data.Maybe (Maybe(..))
...
@@ -5,7 +5,7 @@ import Data.Maybe (Maybe(..))
import Data.Show.Generic (genericShow)
import Data.Show.Generic (genericShow)
import Data.String.Common (toLower)
import Data.String.Common (toLower)
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(DownloadNode))
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(DownloadNode))
import Gargantext.Components.Forest.Tree.Node.Tools
(fragmentPT, panel, submitButtonHref)
import Gargantext.Components.Forest.Tree.Node.Tools
as Tools
import Gargantext.Ends (url)
import Gargantext.Ends (url)
import Gargantext.Prelude
import Gargantext.Prelude
import Gargantext.Routes as Routes
import Gargantext.Routes as Routes
...
@@ -41,8 +41,11 @@ actionDownloadCorpus = R.createElement actionDownloadCorpusCpt
...
@@ -41,8 +41,11 @@ actionDownloadCorpus = R.createElement actionDownloadCorpusCpt
actionDownloadCorpusCpt :: R.Component ActionDownload
actionDownloadCorpusCpt :: R.Component ActionDownload
actionDownloadCorpusCpt = here.component "actionDownloadCorpus" cpt where
actionDownloadCorpusCpt = here.component "actionDownloadCorpus" cpt where
cpt { id, session } _ = do
cpt { id, session } _ = do
pure $ panel [H.div {} [H.text info]]
pure $
(submitButtonHref DownloadNode href)
Tools.panelWithSubmitButtonHref { action: DownloadNode
, href
, mError: Nothing }
[ H.div {} [H.text info] ]
where
where
href = url session $ Routes.NodeAPI GT.Corpus (Just id) "export"
href = url session $ Routes.NodeAPI GT.Corpus (Just id) "export"
info = "Download as JSON"
info = "Download as JSON"
...
@@ -52,8 +55,11 @@ actionDownloadGraph = R.createElement actionDownloadGraphCpt
...
@@ -52,8 +55,11 @@ actionDownloadGraph = R.createElement actionDownloadGraphCpt
actionDownloadGraphCpt :: R.Component ActionDownload
actionDownloadGraphCpt :: R.Component ActionDownload
actionDownloadGraphCpt = here.component "actionDownloadGraph" cpt where
actionDownloadGraphCpt = here.component "actionDownloadGraph" cpt where
cpt { id, session } _ = do
cpt { id, session } _ = do
pure $ panel [H.div {} [H.text info]]
pure $
(submitButtonHref DownloadNode href)
Tools.panelWithSubmitButtonHref { action: DownloadNode
, href
, mError: Nothing }
[ H.div {} [H.text info] ]
where
where
href = url session $ Routes.NodeAPI GT.Graph (Just id) "gexf"
href = url session $ Routes.NodeAPI GT.Graph (Just id) "gexf"
info = "Info about the Graph as GEXF format"
info = "Info about the Graph as GEXF format"
...
@@ -79,15 +85,17 @@ actionDownloadNodeListCpt = here.component "actionDownloadNodeList" cpt where
...
@@ -79,15 +85,17 @@ actionDownloadNodeListCpt = here.component "actionDownloadNodeList" cpt where
downloadFormat <- T.useBox NL_JSON
downloadFormat <- T.useBox NL_JSON
downloadFormat' <- T.useLive T.unequal downloadFormat
downloadFormat' <- T.useLive T.unequal downloadFormat
pure $ panel
pure $
[ R2.select { className: "form-control"
Tools.panelWithSubmitButtonHref { action: DownloadNode
, defaultValue: show downloadFormat'
, href: href downloadFormat'
, on: { change: onChange downloadFormat } }
, mError: Nothing }
[ opt NL_CSV downloadFormat
[ R2.select { className: "form-control"
, opt NL_JSON downloadFormat ]
, defaultValue: show downloadFormat'
, H.div {} [ H.text $ info downloadFormat' ]
, on: { change: onChange downloadFormat } }
]
[ opt NL_CSV downloadFormat
(submitButtonHref DownloadNode $ href downloadFormat')
, opt NL_JSON downloadFormat ]
, H.div {} [ H.text $ info downloadFormat' ]
]
where
where
opt t downloadFormat = H.option { value: show t } [ H.text $ show t ]
opt t downloadFormat = H.option { value: show t } [ H.text $ show t ]
where
where
...
@@ -122,7 +130,9 @@ actionDownloadNodeTextsCpt = here.component "actionDownloadNodeTexts" cpt where
...
@@ -122,7 +130,9 @@ actionDownloadNodeTextsCpt = here.component "actionDownloadNodeTexts" cpt where
downloadFormat <- T.useBox NT_JSON
downloadFormat <- T.useBox NT_JSON
downloadFormat' <- T.useLive T.unequal downloadFormat
downloadFormat' <- T.useLive T.unequal downloadFormat
pure $ panel
pure $ Tools.panelWithSubmitButtonHref { action: DownloadNode
, href: href downloadFormat'
, mError: Nothing }
[ R2.select { className: "form-control"
[ R2.select { className: "form-control"
, defaultValue: show downloadFormat'
, defaultValue: show downloadFormat'
, on: { change: onChange downloadFormat } }
, on: { change: onChange downloadFormat } }
...
@@ -130,7 +140,6 @@ actionDownloadNodeTextsCpt = here.component "actionDownloadNodeTexts" cpt where
...
@@ -130,7 +140,6 @@ actionDownloadNodeTextsCpt = here.component "actionDownloadNodeTexts" cpt where
, opt NT_JSON downloadFormat ]
, opt NT_JSON downloadFormat ]
, H.div {} [ H.text $ info downloadFormat' ]
, H.div {} [ H.text $ info downloadFormat' ]
]
]
(submitButtonHref DownloadNode $ href downloadFormat')
where
where
opt t downloadFormat = H.option { value: show t } [ H.text $ show t ]
opt t downloadFormat = H.option { value: show t } [ H.text $ show t ]
where
where
...
@@ -154,4 +163,4 @@ actionDownloadOther = R.createElement actionDownloadOtherCpt
...
@@ -154,4 +163,4 @@ actionDownloadOther = R.createElement actionDownloadOtherCpt
actionDownloadOtherCpt :: R.Component ActionDownload
actionDownloadOtherCpt :: R.Component ActionDownload
actionDownloadOtherCpt = here.component "actionDownloadOther" cpt where
actionDownloadOtherCpt = here.component "actionDownloadOther" cpt where
cpt _ _ = do
cpt _ _ = do
pure $ fragmentPT $ "Soon, you will be able to download your file here "
pure $
Tools.
fragmentPT $ "Soon, you will be able to download your file here "
src/Gargantext/Components/Forest/Tree/Node/Action/Link.purs
View file @
65e9cf3e
...
@@ -6,7 +6,7 @@ import Data.Either (Either)
...
@@ -6,7 +6,7 @@ import Data.Either (Either)
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..))
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Action.Update.Types (LinkNodeReq(..), UpdateNodeParams(..))
import Gargantext.Components.Forest.Tree.Node.Action.Update.Types (LinkNodeReq(..), UpdateNodeParams(..))
import Gargantext.Components.Forest.Tree.Node.Tools
(submitButton, panel)
import Gargantext.Components.Forest.Tree.Node.Tools
as Tools
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree (subTreeView, SubTreeParamsIn)
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree (subTreeView, SubTreeParamsIn)
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree.Types (SubTreeOut(..))
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree.Types (SubTreeOut(..))
import Gargantext.Config.REST (AffRESTError, RESTError)
import Gargantext.Config.REST (AffRESTError, RESTError)
...
@@ -69,23 +69,26 @@ linkNodeCpt' = here.component "__clone__" cpt
...
@@ -69,23 +69,26 @@ linkNodeCpt' = here.component "__clone__" cpt
let
let
button = case action' of
button = case action' of
LinkNode { params } ->
case params of
LinkNode { params } ->
Just (SubTreeOut { in: inId }) -> submitButton
R2.fromMaybe params $
(toParams nodeType inId)
\(SubTreeOut { in: inId }) ->
dispatch
Tools.submitButton { action: toParams nodeType inId
Nothing -> mempty
, dispatch }
_ -> mempty
_ -> mempty
pure $ panel [
pure $
subTreeView { action
Tools.panel { mError: Nothing }
, boxes
[ subTreeView { action
, dispatch
, boxes
, id
, dispatch
, nodeType
, id
, session
, nodeType
, subTreeParams
, session
} []
, subTreeParams
] button
} []
-- footer
, button ]
toParams :: GT.NodeType -> GT.ID -> Action
toParams :: GT.NodeType -> GT.ID -> Action
toParams nodeType id
toParams nodeType id
...
...
src/Gargantext/Components/Forest/Tree/Node/Action/ManageTeam.purs
View file @
65e9cf3e
...
@@ -4,6 +4,7 @@ import Gargantext.Prelude
...
@@ -4,6 +4,7 @@ import Gargantext.Prelude
import Data.Array (filter, null, (:))
import Data.Array (filter, null, (:))
import Data.Either (Either(..))
import Data.Either (Either(..))
import Data.Maybe (Maybe(..))
import Effect.Aff (runAff_)
import Effect.Aff (runAff_)
import Effect.Class (liftEffect)
import Effect.Class (liftEffect)
import Gargantext.Components.Forest.Tree.Node.Tools as Tools
import Gargantext.Components.Forest.Tree.Node.Tools as Tools
...
@@ -52,52 +53,53 @@ type TeamProps =
...
@@ -52,52 +53,53 @@ type TeamProps =
teamLayoutWrapper :: R2.Component TeamProps
teamLayoutWrapper :: R2.Component TeamProps
teamLayoutWrapper = R.createElement teamLayoutWrapperCpt
teamLayoutWrapper = R.createElement teamLayoutWrapperCpt
teamLayoutWrapperCpt :: R.Component TeamProps
teamLayoutWrapperCpt :: R.Component TeamProps
teamLayoutWrapperCpt = here.component "teamLayoutWrapper" cpt where
teamLayoutWrapperCpt = here.component "teamLayoutWrapper" cpt where
cpt {nodeId, session, team: {team_owner_username, team_members}} _ = do
cpt {nodeId, session, team: {team_owner_username, team_members}} _ = do
teamS <- T.useBox team_members
team_members <- T.useBox team_members
team' <- T.useLive T.unequal teamS
error <- T.useBox Nothing
error <- T.useBox ""
error' <- T.useLive T.unequal error
pure $ teamLayoutRows {nodeId, session, team
: teamS, team', error, error'
, team_owner_username}
pure $ teamLayoutRows {nodeId, session, team
_members, error
, team_owner_username}
type TeamRowProps =
type TeamRowProps =
( nodeId :: ID
( nodeId :: ID
, session :: Session
, session :: Session
, team :: T.Box (Array TeamMember)
, team_members :: T.Box (Array TeamMember)
, error :: T.Box String
, error :: T.Box (Maybe String)
, team' :: Array TeamMember
, error' :: String
, team_owner_username :: String
, team_owner_username :: String
)
)
teamLayoutRows :: R2.Leaf TeamRowProps
teamLayoutRows :: R2.Leaf TeamRowProps
teamLayoutRows = R2.leaf teamLayoutRowsCpt
teamLayoutRows = R2.leaf teamLayoutRowsCpt
teamLayoutRowsCpt :: R.Component TeamRowProps
teamLayoutRowsCpt :: R.Component TeamRowProps
teamLayoutRowsCpt = here.component "teamLayoutRows" cpt where
teamLayoutRowsCpt = here.component "teamLayoutRows" cpt where
cpt { team, nodeId, session, error, team', error', team_owner_username} _ = do
cpt { team_members, nodeId, session, error, team_owner_username } _ = do
team_members' <- T.useLive T.unequal team_members
case null team' of
error' <- T.useLive T.unequal error
true -> pure $ H.div { style: {margin: "10px"}}
[ H.h4 {} [H.text "Your team is empty, you can send some invitations."]]
pure $
false -> pure $ Tools.panel (makeLeader team_owner_username : (map makeTeam team')) (H.div {} [H.text error'])
if null team_members' then
H.div { style: {margin: "10px"}}
[ H.h4 {} [H.text "Your team is empty, you can send some invitations."]]
else
Tools.panelNoFooter { mError: error' }
(makeLeader team_owner_username : (map makeTeam team_members'))
where
where
makeTeam :: TeamMember -> R.Element
makeTeam :: TeamMember -> R.Element
makeTeam { username, shared_folder_id } = H.div {className: "from-group row"} [ H.div { className: "col-8" } [ H.text username ]
makeTeam { username, shared_folder_id } =
, H.a { className: "text-danger col-2 fa fa-times"
H.div {className: "from-group row"} [ H.div { className: "col-8" } [ H.text username ]
, title: "Remove user from team"
, H.a { className: "text-danger col-2 fa fa-times"
, type: "button"
, title: "Remove user from team"
, on: {click: submit shared_folder_id }
, type: "button"
} []
, on: {click: submit shared_folder_id }
]
} []
]
makeLeader username = H.div {className: "from-group row"} [ H.div { className: "col-8"} [ H.text username ]
, H.p { className: "col-2"} [ H.text "owner"]
makeLeader username =
]
H.div {className: "from-group row"} [ H.div { className: "col-8"} [ H.text username ]
, H.p { className: "col-2"} [ H.text "owner"]
]
submit sharedFolderId _ = do
submit sharedFolderId _ = do
runAff_ callback $ saveDeleteTeam { session, nodeId, sharedFolderId }
runAff_ callback $ saveDeleteTeam { session, nodeId, sharedFolderId }
...
@@ -105,14 +107,15 @@ teamLayoutRowsCpt = here.component "teamLayoutRows" cpt where
...
@@ -105,14 +107,15 @@ teamLayoutRowsCpt = here.component "teamLayoutRows" cpt where
callback res =
callback res =
case res of
case res of
Left _ -> do
Left _ -> do
_ <- liftEffect $ T.write
"Only the Team owner can remove users"
error
_ <- liftEffect $ T.write
(Just "Only the Team owner can remove users")
error
pure unit
pure unit
Right val ->
Right val ->
case val of
case val of
Left _ -> do
Left _ -> do
pure unit
pure unit
Right r -> do
Right r -> do
T.write_ (filter (\tm -> tm.shared_folder_id /= r) team') team
T.modify_ (filter (\tm -> tm.shared_folder_id /= r)) team_members
T.write_ Nothing error
-------------------------------------------------------------
-------------------------------------------------------------
...
...
src/Gargantext/Components/Forest/Tree/Node/Action/Merge.purs
View file @
65e9cf3e
...
@@ -5,7 +5,7 @@ import Gargantext.Prelude
...
@@ -5,7 +5,7 @@ import Gargantext.Prelude
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..))
import Data.Set as Set
import Data.Set as Set
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Tools
(submitButton, panel, checkbox, checkboxesListGroup)
import Gargantext.Components.Forest.Tree.Node.Tools
as Tools
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree (subTreeView, SubTreeParamsIn)
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree (subTreeView, SubTreeParamsIn)
import Gargantext.Config.REST (AffRESTError)
import Gargantext.Config.REST (AffRESTError)
import Gargantext.Routes (SessionRoute(..))
import Gargantext.Routes (SessionRoute(..))
...
@@ -36,12 +36,13 @@ mergeNodeCpt = here.component "mergeNode" cpt
...
@@ -36,12 +36,13 @@ mergeNodeCpt = here.component "mergeNode" cpt
options <- T.useBox (Set.singleton GT.MapTerm)
options <- T.useBox (Set.singleton GT.MapTerm)
let button = case action' of
let button = case action' of
MergeNode {params} -> case params of
MergeNode { params } ->
Just val -> submitButton (MergeNode {params: Just val}) dispatch
R2.fromMaybe params $
Nothing -> H.div {} []
\val -> Tools.submitButton { action: MergeNode {params: Just val }
, dispatch }
_ -> H.div {} []
_ -> H.div {} []
pure $
panel
pure $
Tools.panel { mError: Nothing }
[ subTreeView { action
[ subTreeView { action
, boxes
, boxes
, dispatch
, dispatch
...
@@ -50,23 +51,24 @@ mergeNodeCpt = here.component "mergeNode" cpt
...
@@ -50,23 +51,24 @@ mergeNodeCpt = here.component "mergeNode" cpt
, session
, session
, subTreeParams
, subTreeParams
} []
} []
, H.ul { className:"merge mx-auto list-group"}
, H.ul { className:"merge mx-auto list-group"}
([ H.li { className: "list-group-item" }
[ H.li { className: "list-group-item" }
[ H.h5 { className: "mb-1" } [ H.text "Merge which list?" ]
[ H.h5 { className: "mb-1" } [ H.text "Merge which list?" ]
, checkboxesListGroup { groups: [ GT.MapTerm, GT.CandidateTerm, GT.StopTerm ]
, Tools.checkboxesListGroup { groups: [ GT.MapTerm, GT.CandidateTerm, GT.StopTerm ]
, options } []
, options } []
]
]
])
]
, H.ul { className:"merge mx-auto list-group"}
, H.ul { className:"merge mx-auto list-group"}
[ H.li { className: "list-group-item" }
[ H.li { className: "list-group-item" }
[ H.h5 { className: "mb-1" } [ H.text "Title" ]
[ H.h5 { className: "mb-1" } [ H.text "Title" ]
]
]
, H.li { className: "list-group-item" }
, H.li { className: "list-group-item" }
[ H.div { className: " form-check" }
[ H.div { className: " form-check" }
[ checkbox { value: merge }
[ Tools.checkbox { value: merge }
, H.label { className: "form-check-label" } [ H.text "Merge data?" ]
, H.label { className: "form-check-label" } [ H.text "Merge data?" ]
]
]
]
]
]
]
]
button
-- footer
, button ]
src/Gargantext/Components/Forest/Tree/Node/Action/Move.purs
View file @
65e9cf3e
...
@@ -7,7 +7,7 @@ import Gargantext.Prelude
...
@@ -7,7 +7,7 @@ import Gargantext.Prelude
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..))
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Tools
(submitButton, panel)
import Gargantext.Components.Forest.Tree.Node.Tools
as Tools
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree (SubTreeParamsIn, subTreeView)
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree (SubTreeParamsIn, subTreeView)
import Gargantext.Config.REST (AffRESTError)
import Gargantext.Config.REST (AffRESTError)
import Gargantext.Routes (SessionRoute(..))
import Gargantext.Routes (SessionRoute(..))
...
@@ -59,15 +59,16 @@ moveNodeCpt' = here.component "__clone__" cpt where
...
@@ -59,15 +59,16 @@ moveNodeCpt' = here.component "__clone__" cpt where
action' <- T.useLive T.unequal action
action' <- T.useLive T.unequal action
let button = case action' of
let button = case action' of
MoveNode { params } -> case params of
MoveNode { params } ->
Just val -> submitButton (MoveNode {params: Just val}) dispatch
R2.fromMaybe params $
Nothing -> H.div {} []
\val -> Tools.submitButton { action: MoveNode {params: Just val}
_ -> H.div {} []
, dispatch }
_ -> H.div {} []
pure $
pure $
panel
Tools.panel { mError: Nothing }
[ subTreeView { action
[ subTreeView { action
, boxes
, boxes
, dispatch
, dispatch
, id
, id
...
@@ -75,4 +76,6 @@ moveNodeCpt' = here.component "__clone__" cpt where
...
@@ -75,4 +76,6 @@ moveNodeCpt' = here.component "__clone__" cpt where
, session
, session
, subTreeParams
, subTreeParams
} []
} []
] button
-- footer
, button ]
src/Gargantext/Components/Forest/Tree/Node/Action/Share.purs
View file @
65e9cf3e
...
@@ -4,16 +4,20 @@ import Gargantext.Prelude
...
@@ -4,16 +4,20 @@ import Gargantext.Prelude
import Data.Array (filter, nub)
import Data.Array (filter, nub)
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep (class Generic)
import Data.Either (Either(..))
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..))
import Data.Show.Generic (genericShow)
import Data.Show.Generic (genericShow)
import Data.String (Pattern(..), contains, trim)
import Data.String (Pattern(..), contains, trim)
import Data.Tuple.Nested ((/\))
import Data.Tuple.Nested ((/\))
import Effect.Aff (Aff)
import Effect.Aff (Aff, launchAff_)
import Effect.Class (liftEffect)
import Gargantext.Components.Bootstrap as B
import Gargantext.Components.Bootstrap.Types (Elevation(Level1))
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action)
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action)
import Gargantext.Components.Forest.Tree.Node.Action.Types as Action
import Gargantext.Components.Forest.Tree.Node.Action.Types as Action
import Gargantext.Components.Forest.Tree.Node.Tools as Tools
import Gargantext.Components.Forest.Tree.Node.Tools as Tools
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree (subTreeView, SubTreeParamsIn)
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree (subTreeView, SubTreeParamsIn)
import Gargantext.Components.InputWithAutocomplete (inputWithAutocomplete
'
)
import Gargantext.Components.InputWithAutocomplete (inputWithAutocomplete)
import Gargantext.Config.REST (AffRESTError, logRESTError)
import Gargantext.Config.REST (AffRESTError, logRESTError)
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Routes as GR
import Gargantext.Routes as GR
...
@@ -39,9 +43,6 @@ getCompletionsReq :: { session :: Session } -> AffRESTError (Array String)
...
@@ -39,9 +43,6 @@ getCompletionsReq :: { session :: Session } -> AffRESTError (Array String)
getCompletionsReq { session } =
getCompletionsReq { session } =
get session GR.Members
get session GR.Members
shareAction :: String -> Action
shareAction username = Action.ShareTeam (trim username)
------------------------------------------------------------------------
------------------------------------------------------------------------
data ShareNodeParams = ShareTeamParams { username :: String }
data ShareNodeParams = ShareTeamParams { username :: String }
...
@@ -59,27 +60,26 @@ instance Show ShareNodeParams where show = genericShow
...
@@ -59,27 +60,26 @@ instance Show ShareNodeParams where show = genericShow
------------------------------------------------------------------------
------------------------------------------------------------------------
type ShareNode =
type ShareNode =
( id :: ID
( id :: ID
, dispatch :: Action -> Aff Unit
, session :: Session )
, session :: Session)
shareNode :: R2.Component ShareNode
shareNode :: R2.Component ShareNode
shareNode = R.createElement shareNodeCpt
shareNode = R.createElement shareNodeCpt
shareNodeCpt :: R.Component ShareNode
shareNodeCpt :: R.Component ShareNode
shareNodeCpt = here.component "shareNode" cpt
shareNodeCpt = here.component "shareNode" cpt
where
where
cpt {
session, dispatch
} _ = do
cpt {
id, session
} _ = do
useLoader {
useLoader {
loader: getCompletionsReq
loader: getCompletionsReq
, path: { session }
, path: { session }
, render: \completions -> shareNodeInner {
completions, dispatch
} []
, render: \completions -> shareNodeInner {
completions, id, session
} []
, errorHandler
, errorHandler
}
}
where
where
errorHandler = logRESTError here "[shareNode]"
errorHandler = logRESTError here "[shareNode]"
type ShareNodeInner =
type ShareNodeInner =
(
dispatch :: Action -> Aff Unit
(
completions :: Array String
, completions :: Array String
| ShareNode
)
)
shareNodeInner :: R2.Component ShareNodeInner
shareNodeInner :: R2.Component ShareNodeInner
...
@@ -87,25 +87,42 @@ shareNodeInner = R.createElement shareNodeInnerCpt
...
@@ -87,25 +87,42 @@ shareNodeInner = R.createElement shareNodeInnerCpt
shareNodeInnerCpt :: R.Component ShareNodeInner
shareNodeInnerCpt :: R.Component ShareNodeInner
shareNodeInnerCpt = here.component "shareNodeInner" cpt
shareNodeInnerCpt = here.component "shareNodeInner" cpt
where
where
cpt {
dispatch, completions
} _ = do
cpt {
completions, id, session
} _ = do
state
<- T.useBox
""
state
' /\ state <- R2.useBox'
""
text' /\ text <- R2.useBox' ""
text' /\ text <- R2.useBox' ""
mError' /\ mError <- R2.useBox' Nothing
pure $ Tools.panel { mError: mError' }
[ inputWithAutocomplete { autoFocus: true
, autocompleteSearch
, classes: "share-users-completions d-flex align-items-center"
, onAutocompleteClick
, onEnterPress: onEnterPress text mError
, pattern: "^\\S+$" -- pattern doesn't allow space characters
, placeholder: "username or email"
, state
, title }
[ B.iconButton { callback: \_ -> onEnterPress text mError state'
, elevation: Level1
, name: "send"
, title: "Submit" } ]
pure $ Tools.panel
-- footer
[ inputWithAutocomplete' { boxAction: shareAction
, H.div {} [ H.text text' ] ]
, dispatch
, state
, classes: "share-users-completions d-flex align-items-center"
, autocompleteSearch
, onAutocompleteClick
, 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"}
] (H.div {} [H.text text'])
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 mError val = do
T.write_ Nothing mError
launchAff_ do
eRes <- shareReq session id $ ShareTeamParams { username: val }
liftEffect $ case eRes of
Left err -> do
T.write_ (Just $ show err) mError
Right _ -> do
T.write_ ("Invited " <> val <> " to the team") text
T.write_ Nothing mError
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
...
@@ -117,12 +134,13 @@ publishNodeCpt = here.component "publishNode" cpt
...
@@ -117,12 +134,13 @@ publishNodeCpt = here.component "publishNode" cpt
action' <- T.useLive T.unequal action
action' <- T.useLive T.unequal action
let button = case action' of
let button = case action' of
Action.SharePublic { params } -> case params of
Action.SharePublic { params } ->
Just val -> Tools.submitButton (Action.SharePublic {params: Just val}) dispatch
R2.fromMaybe params $
Nothing -> H.div {} []
\val -> Tools.submitButton { action: Action.SharePublic {params: Just val}
, dispatch }
_ -> H.div {} []
_ -> H.div {} []
pure $ Tools.panel
pure $ Tools.panel
{ mError: Nothing }
[ subTreeView { action
[ subTreeView { action
, boxes
, boxes
, dispatch
, dispatch
...
@@ -131,4 +149,6 @@ publishNodeCpt = here.component "publishNode" cpt
...
@@ -131,4 +149,6 @@ publishNodeCpt = here.component "publishNode" cpt
, session
, session
, subTreeParams
, subTreeParams
} []
} []
] button
-- footer
, button ]
src/Gargantext/Components/Forest/Tree/Node/Action/Update.purs
View file @
65e9cf3e
...
@@ -11,7 +11,7 @@ import Effect (Effect)
...
@@ -11,7 +11,7 @@ import Effect (Effect)
import Effect.Aff (Aff, launchAff_)
import Effect.Aff (Aff, launchAff_)
import Gargantext.Components.Bootstrap.Types (ComponentStatus(..))
import Gargantext.Components.Bootstrap.Types (ComponentStatus(..))
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Tools
(formChoiceSafe, submitButton, panel)
import Gargantext.Components.Forest.Tree.Node.Tools
as Tools
import Gargantext.Components.PhyloExplorer.API as Phylo
import Gargantext.Components.PhyloExplorer.API as Phylo
import Gargantext.Components.PhyloExplorer.Config.ConfigForm as PhyloForm
import Gargantext.Components.PhyloExplorer.Config.ConfigForm as PhyloForm
import Gargantext.Components.PhyloExplorer.ConfigFormParser as PhyloHook
import Gargantext.Components.PhyloExplorer.ConfigFormParser as PhyloHook
...
@@ -62,13 +62,16 @@ updateDashboardCpt = here.component "updateDashboard" cpt where
...
@@ -62,13 +62,16 @@ updateDashboardCpt = here.component "updateDashboard" cpt where
methodBoard <- T.useBox All
methodBoard <- T.useBox All
methodBoard' <- T.useLive T.unequal methodBoard
methodBoard' <- T.useLive T.unequal methodBoard
pure $ panel [ -- H.text "Update with"
pure $
formChoiceSafe { items: [All, Sources, Authors, Institutes, Ngrams]
Tools.panelWithSubmitButton { action: UpdateNode $ UpdateNodeParamsBoard { methodBoard: methodBoard' }
, default: methodBoard'
, dispatch
, callback: \val -> T.write_ val methodBoard
, mError: Nothing }
, print: show } []
[ -- H.text "Update with"
]
Tools.formChoiceSafe { items: [All, Sources, Authors, Institutes, Ngrams]
(submitButton (UpdateNode $ UpdateNodeParamsBoard { methodBoard: methodBoard' }) dispatch)
, default: methodBoard'
, callback: \val -> T.write_ val methodBoard
, print: show } []
]
updateGraph :: R2.Component UpdateProps
updateGraph :: R2.Component UpdateProps
updateGraph = R.createElement updateGraphCpt
updateGraph = R.createElement updateGraphCpt
...
@@ -97,12 +100,24 @@ updateGraphCpt = here.component "updateGraph" cpt where
...
@@ -97,12 +100,24 @@ updateGraphCpt = here.component "updateGraph" cpt where
callback :: Action -> Aff Unit
callback :: Action -> Aff Unit
callback = dispatch >=> \_ -> dispatch CloseBox
callback = dispatch >=> \_ -> dispatch CloseBox
pure $ panel [ H.text "Show subjects with Order1 or concepts with Order2 ?"
let action = UpdateNode $ UpdateNodeParamsGraph { methodGraphMetric: methodGraphMetric'
, formChoiceSafe { items: [Order1, Order2_A, Order2_B]
, methodGraphClustering: methodGraphClustering'
, default: methodGraphMetric'
, methodGraphBridgeness: methodGraphBridgeness'
, callback: \val -> T.write_ val methodGraphMetric
, methodGraphEdgesStrength : methodGraphEdgesStrength'
, print: show } []
, methodGraphNodeType1 : methodGraphNodeType1'
, methodGraphNodeType2 : methodGraphNodeType2'
}
pure $
Tools.panelWithSubmitButton { action
, dispatch: callback
, mError: Nothing }
[ H.text "Show subjects with Order1 or concepts with Order2 ?"
, Tools.formChoiceSafe { items: [Order1, Order2_A, Order2_B]
, default: methodGraphMetric'
, callback: \val -> T.write_ val methodGraphMetric
, print: show } []
]
{-
{-
...
@@ -138,16 +153,6 @@ updateGraphCpt = here.component "updateGraph" cpt where
...
@@ -138,16 +153,6 @@ updateGraphCpt = here.component "updateGraph" cpt where
, callback: \val -> T.write_ val methodGraphClustering
, callback: \val -> T.write_ val methodGraphClustering
, print: show } []
, print: show } []
-}
-}
]
(submitButton (UpdateNode $ UpdateNodeParamsGraph { methodGraphMetric: methodGraphMetric'
, methodGraphClustering: methodGraphClustering'
, methodGraphBridgeness: methodGraphBridgeness'
, methodGraphEdgesStrength : methodGraphEdgesStrength'
, methodGraphNodeType1 : methodGraphNodeType1'
, methodGraphNodeType2 : methodGraphNodeType2'
}
) callback
)
...
@@ -214,13 +219,16 @@ updateNodeListCpt = here.component "updateNodeList" cpt where
...
@@ -214,13 +219,16 @@ updateNodeListCpt = here.component "updateNodeList" cpt where
methodList <- T.useBox Basic
methodList <- T.useBox Basic
methodList' <- T.useLive T.unequal methodList
methodList' <- T.useLive T.unequal methodList
pure $ panel [ -- H.text "Update with"
pure $
formChoiceSafe { items: [Basic, Advanced, WithModel]
Tools.panelWithSubmitButton { action: UpdateNode $ UpdateNodeParamsList { methodList: methodList' }
, default: methodList'
, dispatch
, callback: \val -> T.write_ val methodList
, mError: Nothing }
, print: show } []
[ -- H.text "Update with"
]
Tools.formChoiceSafe { items: [Basic, Advanced, WithModel]
(submitButton (UpdateNode $ UpdateNodeParamsList { methodList: methodList' }) dispatch)
, default: methodList'
, callback: \val -> T.write_ val methodList
, print: show } []
]
updateTexts :: R2.Component UpdateProps
updateTexts :: R2.Component UpdateProps
updateTexts = R.createElement updateTextsCpt
updateTexts = R.createElement updateTextsCpt
...
@@ -230,14 +238,16 @@ updateTextsCpt = here.component "updateTexts" cpt where
...
@@ -230,14 +238,16 @@ updateTextsCpt = here.component "updateTexts" cpt where
-- methodTexts <- T.useBox NewNgrams
-- methodTexts <- T.useBox NewNgrams
-- methodTexts' <- T.useLive T.unequal methodTexts
-- methodTexts' <- T.useLive T.unequal methodTexts
pure $ panel [ -- H.text "Update with"
pure $
-- formChoiceSafe { items: [NewNgrams, NewTexts, Both]
Tools.panelWithSubmitButton { action: UpdateNode $ UpdateNodeParamsTexts { methodTexts: Both }
-- , default: methodTexts'
, dispatch
-- , callback: \val -> T.write_ val methodTexts
, mError: Nothing }
-- , print: show } []
[] -- H.text "Update with"
]
-- formChoiceSafe { items: [NewNgrams, NewTexts, Both]
-- (submitButton (UpdateNode $ UpdateNodeParamsTexts { methodTexts: methodTexts' }) dispatch)
-- , default: methodTexts'
(submitButton (UpdateNode $ UpdateNodeParamsTexts { methodTexts: Both }) dispatch)
-- , callback: \val -> T.write_ val methodTexts
-- , print: show } []
-- (submitButton (UpdateNode $ UpdateNodeParamsTexts { methodTexts: methodTexts' }) dispatch)
updateOther :: R2.Component UpdateProps
updateOther :: R2.Component UpdateProps
...
...
src/Gargantext/Components/Forest/Tree/Node/Action/Upload.purs
View file @
65e9cf3e
...
@@ -23,7 +23,7 @@ import Gargantext.Components.Forest.Tree.Node.Action (Props)
...
@@ -23,7 +23,7 @@ import Gargantext.Components.Forest.Tree.Node.Action (Props)
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Action.Upload.Types (FileFormat(..), FileType(..), UploadFileBlob(..), readUFBAsBase64, readUFBAsText)
import Gargantext.Components.Forest.Tree.Node.Action.Upload.Types (FileFormat(..), FileType(..), UploadFileBlob(..), readUFBAsBase64, readUFBAsText)
import Gargantext.Components.Forest.Tree.Node.Action.Utils (loadLanguages)
import Gargantext.Components.Forest.Tree.Node.Action.Utils (loadLanguages)
import Gargantext.Components.Forest.Tree.Node.Tools
(fragmentPT, formChoiceSafe, panel)
import Gargantext.Components.Forest.Tree.Node.Tools
as Tools
import Gargantext.Components.Lang (Lang(..), langReader)
import Gargantext.Components.Lang (Lang(..), langReader)
import Gargantext.Components.ListSelection as ListSelection
import Gargantext.Components.ListSelection as ListSelection
import Gargantext.Components.ListSelection.Types (Selection(..))
import Gargantext.Components.ListSelection.Types (Selection(..))
...
@@ -83,7 +83,7 @@ actionUploadOther = R.createElement actionUploadOtherCpt
...
@@ -83,7 +83,7 @@ actionUploadOther = R.createElement actionUploadOtherCpt
actionUploadOtherCpt :: R.Component ActionUpload
actionUploadOtherCpt :: R.Component ActionUpload
actionUploadOtherCpt = here.component "actionUploadOther" cpt where
actionUploadOtherCpt = here.component "actionUploadOther" cpt where
cpt _ _ = do
cpt _ _ = do
pure $ fragmentPT $ "Soon, upload for this NodeType."
pure $
Tools.
fragmentPT $ "Soon, upload for this NodeType."
-- file upload types
-- file upload types
...
@@ -153,30 +153,30 @@ uploadFileViewWithLangsCpt = here.component "uploadFileViewWithLangs" cpt
...
@@ -153,30 +153,30 @@ uploadFileViewWithLangsCpt = here.component "uploadFileViewWithLangs" cpt
]
]
, R2.row
, R2.row
[ H.div {className:"col-6 flex-space-around"}
[ H.div {className:"col-6 flex-space-around"}
[ formChoiceSafe { items: [ CSV
[
Tools.
formChoiceSafe { items: [ CSV
, CSV_HAL
, CSV_HAL
, Istex
, Istex
, WOS
, WOS
, JSON
, JSON
-- , Iramuteq
-- , Iramuteq
]
]
, default: CSV
, default: CSV
, callback: setFileType'
, callback: setFileType'
, print: show } []
, print: show } []
, formChoiceSafe { items: [ Plain
,
Tools.
formChoiceSafe { items: [ Plain
, ZIP ]
, ZIP ]
, default: Plain
, default: Plain
, callback: setFileFormat'
, callback: setFileFormat'
, print: show } []
, print: show } []
]
]
]
]
, R2.row
, R2.row
[ H.div {className:"col-6 flex-space-around"}
[ H.div {className:"col-6 flex-space-around"}
[ formChoiceSafe { items: langs <> [No_extraction]
[
Tools.
formChoiceSafe { items: langs <> [No_extraction]
, default: EN
, default: EN
, callback: setLang'
, callback: setLang'
, print: show
, print: show
} []
} []
]
]
]
]
, R2.row
, R2.row
...
@@ -194,7 +194,7 @@ uploadFileViewWithLangsCpt = here.component "uploadFileViewWithLangs" cpt
...
@@ -194,7 +194,7 @@ uploadFileViewWithLangsCpt = here.component "uploadFileViewWithLangs" cpt
, selection
, selection
} []
} []
]
]
pure $
panel bodies footer
pure $
Tools.panel { mError: Nothing } (bodies <> [ footer ])
onChangeContents :: forall e. T.Box (Maybe UploadFile) -> E.SyntheticEvent_ e -> Effect Unit
onChangeContents :: forall e. T.Box (Maybe UploadFile) -> E.SyntheticEvent_ e -> Effect Unit
...
@@ -318,7 +318,7 @@ uploadListViewCpt = here.component "uploadListView" cpt where
...
@@ -318,7 +318,7 @@ uploadListViewCpt = here.component "uploadListView" cpt where
-- Render
-- Render
pure $
pure $
panel
Tools.panel { mError: Nothing }
-- Body
-- Body
[
[
-- Upload
-- Upload
...
@@ -423,9 +423,9 @@ uploadListViewCpt = here.component "uploadListView" cpt where
...
@@ -423,9 +423,9 @@ uploadListViewCpt = here.component "uploadListView" cpt where
} []
} []
]
]
]
]
]
-- Footer
-- Footer
(
,
H.div
H.div
{}
{}
[
[
...
@@ -439,7 +439,7 @@ uploadListViewCpt = here.component "uploadListView" cpt where
...
@@ -439,7 +439,7 @@ uploadListViewCpt = here.component "uploadListView" cpt where
, nodeType: GT.Annuaire
, nodeType: GT.Annuaire
} []
} []
]
]
)
]
-- START File Type View
-- START File Type View
type FileTypeProps =
type FileTypeProps =
...
@@ -663,12 +663,12 @@ uploadTermListViewCpt = here.component "uploadTermListView" cpt
...
@@ -663,12 +663,12 @@ uploadTermListViewCpt = here.component "uploadTermListView" cpt
}
}
]
]
pure $
panel
pure $
Tools.panel { mError: Nothing }
[ H.form {}
[ H.form {}
[ R2.row [ R2.col 12 [ input ] ]
[ R2.row [ R2.col 12 [ input ] ]
, R2.row [ R2.col 12 [ uploadTypeHtml ] ]
, R2.row [ R2.col 12 [ uploadTypeHtml ] ]
]
]
] footer
, footer ]
onChangeContents :: forall e. T.Box (Maybe UploadFile)
onChangeContents :: forall e. T.Box (Maybe UploadFile)
-> E.SyntheticEvent_ e
-> E.SyntheticEvent_ e
...
@@ -815,7 +815,7 @@ uploadFrameCalcViewWithLangsCpt = here.component "uploadFrameCalcViewWithLangs"
...
@@ -815,7 +815,7 @@ uploadFrameCalcViewWithLangsCpt = here.component "uploadFrameCalcViewWithLangs"
[ H.text "Upload!" ]
[ H.text "Upload!" ]
]
]
pure $
panel bodies footer
pure $
Tools.panel { mError: Nothing } (bodies <> [ footer ])
where
where
onClick lang' selection' _ = do
onClick lang' selection' _ = do
...
...
src/Gargantext/Components/Forest/Tree/Node/Action/WriteNodesDocuments.purs
View file @
65e9cf3e
...
@@ -11,7 +11,7 @@ import Gargantext.Components.App.Store (Boxes)
...
@@ -11,7 +11,7 @@ import Gargantext.Components.App.Store (Boxes)
import Gargantext.Components.Bootstrap as B
import Gargantext.Components.Bootstrap as B
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Action.Utils (loadLanguages)
import Gargantext.Components.Forest.Tree.Node.Action.Utils (loadLanguages)
import Gargantext.Components.Forest.Tree.Node.Tools
(panel, submitButton)
import Gargantext.Components.Forest.Tree.Node.Tools
as Tools
import Gargantext.Components.Lang (Lang(..))
import Gargantext.Components.Lang (Lang(..))
import Gargantext.Components.ListSelection as ListSelection
import Gargantext.Components.ListSelection as ListSelection
import Gargantext.Components.ListSelection.Types as ListSelection
import Gargantext.Components.ListSelection.Types as ListSelection
...
@@ -71,80 +71,85 @@ actionWriteNodesDocumentsWithLangsCpt = here.component "actionWriteNodesDocument
...
@@ -71,80 +71,85 @@ actionWriteNodesDocumentsWithLangsCpt = here.component "actionWriteNodesDocument
paragraphs' /\ paragraphBox
paragraphs' /\ paragraphBox
<- R2.useBox' "7"
<- R2.useBox' "7"
let bodies = [
pure $
H.div
Tools.panelWithSubmitButton { action: DocumentsFromWriteNodes { id
{ className: "col-12 flex-space-around" }
, lang: lang'
[ H.h4 {}
, selection: selection'
[ H.text "Will traverse all Write Nodes and insert them as documents into current corpus." ]
, paragraphs: paragraphs' }
]
, dispatch
,
, mError: Nothing }
-- lang
H.div
{ className: "form-group" }
[
H.div
{ className: "form-group__label" }
[
[
B.label_ $
H.div
"File lang"
{ className: "col-12 flex-space-around" }
[ H.h4 {}
[ H.text "Will traverse all Write Nodes and insert them as documents into current corpus." ]
]
,
-- lang
H.div
{ className: "form-group" }
[
H.div
{ className: "form-group__label" }
[
B.label_ $
"File lang"
]
,
H.div
{ className: "form-group__field" }
[
B.formSelect'
{ callback: flip T.write_ langBox
, value: lang'
, list: langs <> [ No_extraction ]
}
[]
]
]
,
-- paragraph
H.div
{ className: "form-group "}
[
H.div
{ className: "form-group__label" }
[
B.label_ $
"Paragraph size (sentences)"
]
,
H.div
{ className: "form-group__field" }
[
B.formInput
{ callback: flip T.write_ paragraphBox
, value: paragraphs'
}
]
]
,
--selection
H.div
{ className: "form-group" }
[
H.div
{ className: "form-group__label" }
[
B.label_ $
"List selection"
]
,
H.div
{ className: "form-group__field" }
[
ListSelection.selection
{ selection: selectionBox
, session
} []
]
]
]
]
,
H.div
{ className: "form-group__field" }
[
B.formSelect'
{ callback: flip T.write_ langBox
, value: lang'
, list: langs <> [ No_extraction ]
}
[]
]
]
,
-- paragraph
H.div
{ className: "form-group "}
[
H.div
{ className: "form-group__label" }
[
B.label_ $
"Paragraph size (sentences)"
]
,
H.div
{ className: "form-group__field" }
[
B.formInput
{ callback: flip T.write_ paragraphBox
, value: paragraphs'
}
]
]
,
--selection
H.div
{ className: "form-group" }
[
H.div
{ className: "form-group__label" }
[
B.label_ $
"List selection"
]
,
H.div
{ className: "form-group__field" }
[
ListSelection.selection
{ selection: selectionBox
, session
} []
]
]
]
pure $ panel bodies (submitButton (DocumentsFromWriteNodes { id, lang: lang', selection: selection', paragraphs: paragraphs' }) dispatch)
type Params =
type Params =
...
...
src/Gargantext/Components/Forest/Tree/Node/Box.purs
View file @
65e9cf3e
...
@@ -332,31 +332,39 @@ panelAction = R2.leaf panelActionCpt
...
@@ -332,31 +332,39 @@ panelAction = R2.leaf panelActionCpt
panelActionCpt :: R.Component PanelActionProps
panelActionCpt :: R.Component PanelActionProps
panelActionCpt = here.component "panelAction" cpt
panelActionCpt = here.component "panelAction" cpt
where
where
cpt { action: Documentation nodeType} _ = pure $ actionDoc { nodeType } []
cpt { action: Download, id, nodeType, session} _ = pure $ actionDownload { id, nodeType, session } []
cpt { action: Upload, dispatch, id, nodeType, session} _ = pure $ actionUpload { dispatch, id, nodeType, session } []
cpt { action: Delete, nodeType, dispatch} _ = pure $ actionDelete { dispatch, nodeType } []
cpt { action: ManageTeam, nodeType, id, session} _ = pure $ actionManageTeam { id, nodeType, session } []
cpt { action: Add xs, dispatch, id, name, nodeType} _ =
cpt { action: Add xs, dispatch, id, name, nodeType} _ =
pure $ addNodeView {dispatch, id, name, nodeType, nodeTypes: xs} []
pure $ addNodeView {dispatch, id, name, nodeType, nodeTypes: xs} []
cpt { action
: Refresh , dispatch, nodeType } _ = pure $ update { dispatch, nodeType } []
cpt { action
: AddingContact, dispatch, id } _ =
cpt { action: ReloadWithSettings , dispatch, nodeType } _ = pure $ update { dispatch, nodeType
} []
pure $ Contact.actionAddContact { dispatch, id
} []
cpt { action: Config, nodeType } _ =
cpt { action: Config, nodeType } _ =
pure $ fragmentPT $ "Config " <> show nodeType
pure $ fragmentPT $ "Config " <> show nodeType
-- Functions using SubTree
cpt { action: Delete, nodeType, dispatch} _ =
cpt { action: Reconstruct , dispatch, nodeType } _ = pure $ update { dispatch, nodeType } []
pure $ actionDelete { dispatch, nodeType } []
cpt { action: Documentation nodeType} _ =
pure $ actionDoc { nodeType } []
cpt { action: Download, id, nodeType, session} _ =
pure $ actionDownload { id, nodeType, session } []
cpt { action: Link {subTreeParams}, boxes, dispatch, id, nodeType, session } _ =
pure $ linkNode { boxes, dispatch, id, nodeType, session, subTreeParams } []
cpt { action: ManageTeam, nodeType, id, session} _ =
pure $ actionManageTeam { id, nodeType, session } []
cpt { action: Merge {subTreeParams}, boxes, dispatch, id, nodeType, session } _ =
cpt { action: Merge {subTreeParams}, boxes, dispatch, id, nodeType, session } _ =
pure $ mergeNode { boxes, dispatch, id, nodeType, session, subTreeParams } []
pure $ mergeNode { boxes, dispatch, id, nodeType, session, subTreeParams } []
cpt { action: Move {subTreeParams}, boxes, dispatch, id, nodeType, session } _ =
cpt { action: Move {subTreeParams}, boxes, dispatch, id, nodeType, session } _ =
pure $ moveNode { boxes, dispatch, id, nodeType, session, subTreeParams } []
pure $ moveNode { boxes, dispatch, id, nodeType, session, subTreeParams } []
cpt { action: Link {subTreeParams}, boxes, dispatch, id, nodeType, session } _ =
pure $ linkNode { boxes, dispatch, id, nodeType, session, subTreeParams } []
cpt { action : Share, dispatch, id, session } _ = pure $ Share.shareNode { dispatch, id, session } []
cpt { action : AddingContact, dispatch, id } _ = pure $ Contact.actionAddContact { dispatch, id } []
cpt { action : Publish {subTreeParams}, boxes, dispatch, id, nodeType, session } _ =
cpt { action : Publish {subTreeParams}, boxes, dispatch, id, nodeType, session } _ =
pure $ Share.publishNode { boxes, dispatch, id, nodeType, session, subTreeParams } []
pure $ Share.publishNode { boxes, dispatch, id, nodeType, session, subTreeParams } []
cpt { action: Reconstruct , dispatch, nodeType } _ =
pure $ update { dispatch, nodeType } []
cpt { action: Refresh , dispatch, nodeType } _ =
pure $ update { dispatch, nodeType } []
cpt { action: ReloadWithSettings , dispatch, nodeType } _ =
pure $ update { dispatch, nodeType } []
cpt { action: SearchBox, boxes, dispatch, id, session } _ =
cpt { action: SearchBox, boxes, dispatch, id, session } _ =
pure $ actionSearch { boxes, dispatch, id: Just id, session } []
pure $ actionSearch { boxes, dispatch, id: Just id, session } []
cpt { action : Share, id, session } _ = pure $ Share.shareNode { id, session } []
cpt { action: Upload, dispatch, id, nodeType, session} _ =
pure $ actionUpload { dispatch, id, nodeType, session } []
cpt { action: WriteNodesDocuments, boxes, dispatch, id, session } _ =
cpt { action: WriteNodesDocuments, boxes, dispatch, id, session } _ =
pure $ actionWriteNodesDocuments { boxes, dispatch, id, session } []
pure $ actionWriteNodesDocuments { boxes, dispatch, id, session } []
cpt _ _ = pure $ H.div {} []
cpt _ _ = pure $ H.div {} []
src/Gargantext/Components/Forest/Tree/Node/Settings.purs
View file @
65e9cf3e
module Gargantext.Components.Forest.Tree.Node.Settings where
module Gargantext.Components.Forest.Tree.Node.Settings where
import Gargantext.Prelude (class Eq, class Show, show, (&&), (<>), (==))
import Data.Default (class Default, def)
import Data.Lens (Lens', lens, (.~))
import Data.Lens.Record (prop)
import Gargantext.Prelude (class Eq, class Show, show, (&&), (<>), (==), ($), (<<<))
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree.Types (SubTreeParams(..))
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree.Types (SubTreeParams(..))
import Gargantext.Types
import Gargantext.Types
import Type.Proxy (Proxy(..))
------------------------------------------------------------------------
------------------------------------------------------------------------
------------------------------------------------------------------------
------------------------------------------------------------------------
...
@@ -11,92 +15,89 @@ import Gargantext.Types
...
@@ -11,92 +15,89 @@ import Gargantext.Types
if user has access to node then he can do all his related actions
if user has access to node then he can do all his related actions
-}
-}
------------------------------------------------------------------------
------------------------------------------------------------------------
data NodeAction = Documentation NodeType
data NodeAction = Add (Array NodeType)
| SearchBox
| AddingContact
| Download
| CloseNodePopover
| Upload
| Refresh
| ReloadWithSettings
| Config
| Config
| Reconstruct
| Delete
| Delete
| Share
| Documentation NodeType
| Download
| Link { subTreeParams :: SubTreeParams }
| ManageTeam
| ManageTeam
| Publish { subTreeParams :: SubTreeParams }
| Add (Array NodeType)
| Merge { subTreeParams :: SubTreeParams }
| Merge { subTreeParams :: SubTreeParams }
| Move { subTreeParams :: SubTreeParams }
| Move { subTreeParams :: SubTreeParams }
| Link { subTreeParams :: SubTreeParams }
| Publish { subTreeParams :: SubTreeParams }
| Clone
| Refresh
| AddingContact
| ReloadWithSettings
| CloseNodePopover
| Reconstruct
| SearchBox
| Share
| Upload
| WriteNodesDocuments -- https://gitlab.iscpif.fr/gargantext/purescript-gargantext/issues/331
| WriteNodesDocuments -- https://gitlab.iscpif.fr/gargantext/purescript-gargantext/issues/331
------------------------------------------------------------------------
------------------------------------------------------------------------
instance Eq NodeAction where
instance Eq NodeAction where
eq (Add x) (Add y) = x == y
eq AddingContact AddingContact = true
eq CloseNodePopover CloseNodePopover = true
eq Config Config = true
eq Delete Delete = true
eq (Documentation x) (Documentation y) = true && (x == y)
eq (Documentation x) (Documentation y) = true && (x == y)
eq SearchBox SearchBox = true
eq Download Download = true
eq Download Download = true
eq Upload Upload = true
eq Refresh Refresh = true
eq ReloadWithSettings ReloadWithSettings = true
eq (Move x) (Move y) = x == y
eq Clone Clone = true
eq Delete Delete = true
eq Share Share = true
eq ManageTeam ManageTeam = true
eq (Link x) (Link y) = x == y
eq (Link x) (Link y) = x == y
eq
(Add x) (Add y) = x == y
eq
ManageTeam ManageTeam = true
eq (Merge x) (Merge y) = x == y
eq (Merge x) (Merge y) = x == y
eq Config Config = true
eq (Move x) (Move y) = x == y
eq Reconstruct Reconstruct = true
eq (Publish x) (Publish y) = x == y
eq (Publish x) (Publish y) = x == y
eq AddingContact AddingContact = true
eq Reconstruct Reconstruct = true
eq CloseNodePopover CloseNodePopover = true
eq Refresh Refresh = true
eq ReloadWithSettings ReloadWithSettings = true
eq SearchBox SearchBox = true
eq Share Share = true
eq Upload Upload = true
eq WriteNodesDocuments WriteNodesDocuments = true
eq WriteNodesDocuments WriteNodesDocuments = true
eq _ _ = false
eq _ _ = false
instance Show NodeAction where
instance Show NodeAction where
show (Add _) = "Add Child" -- foldl (\a b -> a <> show b) "Add " xs
show AddingContact = "AddingContact"
show CloseNodePopover = "CloseNodePopover"
show Config = "Config"
show Delete = "Delete"
show (Documentation x) = "Documentation of " <> show x
show (Documentation x) = "Documentation of " <> show x
show SearchBox = "SearchBox"
show Download = "Download"
show Download = "Download"
show Upload = "Upload"
show Refresh = "Refresh"
show ReloadWithSettings = "Reload (with settings)"
show (Move _) = "Move with subtree params" -- <> show t
show Clone = "Clone"
show Delete = "Delete"
show Share = "Share"
show ManageTeam = "Team"
show Config = "Config"
show Reconstruct = "Reconstruct"
show (Link _) = "Link to " -- <> show x
show (Link _) = "Link to " -- <> show x
show
(Add _) = "Add Child" -- foldl (\a b -> a <> show b) "Add " xs
show
ManageTeam = "Team"
show (Merge _) = "Merge with subtree" -- <> show t
show (Merge _) = "Merge with subtree" -- <> show t
show (Move _) = "Move with subtree params" -- <> show t
show (Publish _) = "Publish" -- <> show x
show (Publish _) = "Publish" -- <> show x
show AddingContact = "AddingContact"
show Reconstruct = "Reconstruct"
show CloseNodePopover = "CloseNodePopover"
show Refresh = "Refresh"
show ReloadWithSettings = "Reload (with settings)"
show SearchBox = "SearchBox"
show Share = "Share"
show Upload = "Upload"
show WriteNodesDocuments = "WriteNodesDocuments"
show WriteNodesDocuments = "WriteNodesDocuments"
glyphiconNodeAction :: NodeAction -> String
glyphiconNodeAction :: NodeAction -> String
glyphiconNodeAction (Documentation _) = "question-circle"
glyphiconNodeAction Delete = "trash"
glyphiconNodeAction (Add _) = "plus"
glyphiconNodeAction (Add _) = "plus"
glyphiconNodeAction SearchBox = "search"
glyphiconNodeAction AddingContact = "user-plus"
glyphiconNodeAction Upload = "upload"
glyphiconNodeAction CloseNodePopover = "close"
glyphiconNodeAction (Link _) = "arrows-h"
glyphiconNodeAction Config = "wrench"
glyphiconNodeAction Delete = "trash"
glyphiconNodeAction (Documentation _) = "question-circle"
glyphiconNodeAction Download = "download"
glyphiconNodeAction Download = "download"
glyphiconNodeAction (Link _) = "arrows-h"
glyphiconNodeAction ManageTeam = "users"
glyphiconNodeAction (Merge _) = "random"
glyphiconNodeAction (Merge _) = "random"
glyphiconNodeAction (Move _) = "share-square-o"
glyphiconNodeAction (Publish _) = fldr FolderPublic true
glyphiconNodeAction Reconstruct = "cogs"
glyphiconNodeAction Refresh = "refresh"
glyphiconNodeAction Refresh = "refresh"
glyphiconNodeAction ReloadWithSettings = "reload-with-settings"
glyphiconNodeAction ReloadWithSettings = "reload-with-settings"
glyphiconNodeAction Config = "wrench"
glyphiconNodeAction SearchBox = "search"
glyphiconNodeAction Reconstruct = "cogs"
glyphiconNodeAction Share = "user-plus"
glyphiconNodeAction Share = "user-plus"
glyphiconNodeAction ManageTeam = "users"
glyphiconNodeAction Upload = "upload"
glyphiconNodeAction AddingContact = "user-plus"
glyphiconNodeAction (Move _) = "share-square-o"
glyphiconNodeAction (Publish _) = fldr FolderPublic true
glyphiconNodeAction CloseNodePopover = "close"
glyphiconNodeAction WriteNodesDocuments = "bars"
glyphiconNodeAction WriteNodesDocuments = "bars"
glyphiconNodeAction _ = ""
glyphiconNodeAction _ = ""
...
@@ -107,294 +108,197 @@ data SettingsBox =
...
@@ -107,294 +108,197 @@ data SettingsBox =
, doc :: NodeAction
, doc :: NodeAction
, buttons :: Array NodeAction
, buttons :: Array NodeAction
}
}
instance Default SettingsBox where
def = SettingsBox { show: true
, edit: true
, doc: Documentation Annuaire
, buttons: []
}
defNt :: NodeType -> SettingsBox
defNt nt = (_doc .~ Documentation nt) def
_show :: Lens' SettingsBox Boolean
_show = lens (\(SettingsBox { show }) -> show) (\(SettingsBox sb) val -> SettingsBox (sb { show = val }))
_edit :: Lens' SettingsBox Boolean
_edit = lens (\(SettingsBox { edit }) -> edit) (\(SettingsBox sb) val -> SettingsBox (sb { edit = val }))
_doc :: Lens' SettingsBox NodeAction
_doc = lens (\(SettingsBox { doc }) -> doc) (\(SettingsBox sb) val -> SettingsBox (sb { doc = val }))
_buttons :: Lens' SettingsBox (Array NodeAction)
_buttons = lens (\(SettingsBox { buttons }) -> buttons)
(\(SettingsBox sb) val -> SettingsBox (sb { buttons = val }))
------------------------------------------------------------------------
------------------------------------------------------------------------
settingsBox :: NodeType -> SettingsBox
settingsBox :: NodeType -> SettingsBox
settingsBox NodeUser =
settingsBox p = (settingsBoxLens p) $ defNt p
SettingsBox { show : true
, edit : false
settingsBoxLens :: NodeType -> (SettingsBox -> SettingsBox)
, doc : Documentation NodeUser
settingsBoxLens Annuaire =
, buttons : [ Delete
_buttons .~ [ Upload
]
, AddingContact
}
, Move moveParameters
, Link (linkParams Corpus)
settingsBox FolderPrivate =
, Delete ]
SettingsBox { show : true
settingsBoxLens Calc =
, edit : false
_buttons .~ [ Upload
, doc : Documentation FolderPrivate
, Add [ Calc
, buttons : [ Add [ Notes
, Notes ]
, Corpus
, Move moveFrameParameters
, Calc
, Delete ]
, Folder
settingsBoxLens Corpus =
, Annuaire
_buttons .~ [ Add [ Graph
-- , NodeFrameNotebook
, Notes
]
, Calc
]
, NodeTexts
}
, NodeList
, Graph
settingsBox Team =
-- , Dashboard
SettingsBox { show : true
, Phylo
, edit : true
-- , NodeFrameNotebook
, doc : Documentation Team
]
, buttons : [ Add [ Notes
, Move moveParameters
, Corpus
, Upload
, Calc
, SearchBox
, Folder
, WriteNodesDocuments
, Team
-- , Download
, Annuaire
, Link (linkParams Annuaire)
-- , NodeFrameNotebook
, Delete
-- , FolderShared
]
, NodeFrameVisio
settingsBoxLens Dashboard =
]
(_edit .~ false) <<<
, Share
(_buttons .~ [ ReloadWithSettings
, ManageTeam
, Publish publishParams
, Delete
, Delete
]
])
}
settingsBoxLens Folder =
_buttons .~ [ Add [ Notes
settingsBox FolderShared =
, Corpus
SettingsBox { show : true
, Calc
, edit : true
, Folder
, doc : Documentation FolderShared
, Annuaire
, buttons : [ Add [Team, FolderShared]
-- , NodeFrameNotebook
]
]
}
, Move moveParameters
, Delete
settingsBox FolderPublic =
]
SettingsBox { show : true
settingsBoxLens FolderPrivate =
, edit : true
(_edit .~ false) <<<
, doc : Documentation FolderPublic
(_buttons .~ [ Add [ Notes
, buttons : [ Add [ FolderPublic ]
, Corpus
]
, Calc
}
, Folder
, Annuaire
settingsBox Folder =
-- , NodeFrameNotebook
SettingsBox { show : true
]
, edit : true
])
, doc : Documentation Folder
settingsBoxLens FolderPublic =
, buttons : [ Add [ Notes
_buttons .~ [ Add [ FolderPublic ]
, Corpus
]
, Calc
settingsBoxLens FolderShared =
, Folder
_buttons .~ [ Add [Team, FolderShared]
, Annuaire
]
-- , NodeFrameNotebook
settingsBoxLens Graph =
]
_buttons .~ [ ReloadWithSettings
, Move moveParameters
, Config
, Delete
, Download -- TODO as GEXF or JSON
]
-- , Publish publishParams
}
, Delete
]
settingsBox Corpus =
settingsBoxLens NodeFile =
SettingsBox { show : true
_buttons .~ [ Publish publishParams
, edit : true
, Delete ]
, doc : Documentation Corpus
settingsBoxLens NodeFrameNotebook =
, buttons : [ Add [ Graph
_buttons .~ [ Add [ Calc
, Notes
, Notes
, Calc
-- , NodeFrameNotebook
, NodeTexts
]
, NodeList
, Move moveFrameParameters
, Graph
, Delete
-- , Dashboard
]
, Phylo
settingsBoxLens NodeFrameVisio =
-- , NodeFrameNotebook
_buttons .~ [ Add [ NodeFrameVisio
]
, Notes
, Move moveParameters
, Calc
, Upload
]
, SearchBox
, Delete
, WriteNodesDocuments
]
-- , Download
settingsBoxLens NodeList =
, Link (linkParams Annuaire)
_buttons .~ [ ReloadWithSettings
, Delete
, Config
]
, Upload
}
, Download
, Merge {subTreeParams : SubTreeParams { showtypes: [ FolderPrivate
settingsBox NodeTexts =
, FolderShared
SettingsBox { show : true
, Team
, edit : true
, FolderPublic
, doc : Documentation NodeTexts
, Folder
, buttons : [ ReloadWithSettings
, Corpus
, Upload
, NodeList
, Download
]
, Delete
, valitypes: [ NodeList ]
]
}
}
}
, Delete
settingsBox Graph =
]
SettingsBox { show : true
settingsBoxLens (NodePublic Dashboard) =
, edit : true
_buttons .~ [ Delete
, doc : Documentation Graph
]
, buttons : [ ReloadWithSettings
settingsBoxLens (NodePublic FolderPublic) =
, Config
_buttons .~ [ Add [FolderPublic]
, Download -- TODO as GEXF or JSON
, Delete
-- , Publish publishParams
]
, Delete
settingsBoxLens (NodePublic Graph) =
]
_buttons .~ [ Download -- TODO as GEXF or JSON
}
, Delete
]
settingsBox Phylo =
settingsBoxLens (NodePublic NodeFile) =
SettingsBox { show : true
_buttons .~ [ Delete
, edit : true
]
, doc : Documentation Phylo
settingsBoxLens NodeTexts =
, buttons : [ Reconstruct
_buttons .~ [ ReloadWithSettings
, Delete
, Upload
]
, Download
}
, Delete
]
settingsBoxLens NodeUser =
(_edit .~ false) <<<
settingsBox (NodePublic Graph) =
(_buttons .~ [ Delete
SettingsBox { show : true
])
, edit : true
settingsBoxLens Notes =
, doc : Documentation Graph
_buttons .~ [ Add [ Notes
, buttons : [ Download -- TODO as GEXF or JSON
, Calc
, Delete
, Folder
]
, Corpus
}
]
, Move moveFrameParameters
settingsBox (NodePublic Dashboard) =
, Delete
SettingsBox { show : true
]
, edit : true
settingsBoxLens Phylo =
, doc : Documentation Dashboard
_buttons .~ [ Reconstruct
, buttons : [ Delete
, Delete
]
]
}
settingsBoxLens Team =
_buttons .~ [ Add [ Notes
settingsBox (NodePublic NodeFile) =
, Corpus
SettingsBox { show : true
, Calc
, edit : true
, Folder
, doc : Documentation NodeFile
, Team
, buttons : [ Delete
, Annuaire
]
-- , NodeFrameNotebook
}
-- , FolderShared
, NodeFrameVisio
]
, Share
settingsBox (NodePublic FolderPublic) =
, ManageTeam
SettingsBox { show : true
, Delete
, edit : true
]
, doc : Documentation FolderPublic
settingsBoxLens _ =
, buttons : [ Add [FolderPublic]
(_show .~ false) <<<
, Delete
(_edit .~ false)
]
}
settingsBox NodeList =
SettingsBox { show : true
, edit : true
, doc : Documentation NodeList
, buttons : [ ReloadWithSettings
, Config
, Upload
, Download
, Merge {subTreeParams : SubTreeParams { showtypes: [ FolderPrivate
, FolderShared
, Team
, FolderPublic
, Folder
, Corpus
, NodeList
]
, valitypes: [ NodeList ]
}
}
, Delete
]
}
settingsBox Dashboard =
SettingsBox { show : true
, edit : false
, doc : Documentation Dashboard
, buttons : [ ReloadWithSettings
, Publish publishParams
, Delete
]
}
settingsBox Annuaire =
SettingsBox { show : true
, edit : true
, doc : Documentation Annuaire
, buttons : [ Upload
, AddingContact
, Move moveParameters
, Link (linkParams Corpus)
, Delete
]
}
settingsBox Notes =
SettingsBox { show : true
, edit : true
, doc : Documentation Notes
, buttons : [ Add [ Notes
, Calc
, Folder
, Corpus
]
, Move moveFrameParameters
, Delete
]
}
settingsBox Calc =
SettingsBox { show : true
, edit : true
, doc : Documentation Calc
, buttons : [ Upload
, Add [ Calc
, Notes
]
, Move moveFrameParameters
, Delete
]
}
settingsBox NodeFrameNotebook =
SettingsBox { show : true
, edit : true
, doc : Documentation NodeFrameNotebook
, buttons : [ Add [ Calc
, Notes
-- , NodeFrameNotebook
]
, Move moveFrameParameters
, Delete
]
}
settingsBox NodeFrameVisio =
SettingsBox { show : true
, edit : true
, doc : Documentation NodeFrameVisio
, buttons : [ Add [ NodeFrameVisio
, Notes
, Calc
]
, Delete
]
}
settingsBox NodeFile =
SettingsBox { show: true
, edit: true
, doc: Documentation NodeFile
, buttons: [ Publish publishParams
, Delete ]
}
settingsBox _ =
SettingsBox { show : false
, edit : false
, doc : Documentation NodeUser
, buttons : []
}
-- | SubTree Parameters
-- | SubTree Parameters
...
...
src/Gargantext/Components/Forest/Tree/Node/Tools.purs
View file @
65e9cf3e
...
@@ -2,10 +2,12 @@ module Gargantext.Components.Forest.Tree.Node.Tools where
...
@@ -2,10 +2,12 @@ module Gargantext.Components.Forest.Tree.Node.Tools where
import Gargantext.Prelude
import Gargantext.Prelude
import Data.Maybe (fromMaybe)
import Data.Array as A
import Data.Maybe (fromMaybe, Maybe(..))
import Data.Set (Set)
import Data.Set (Set)
import Data.Set as Set
import Data.Set as Set
import Data.String as S
import Data.String as S
import Data.Tuple.Nested ((/\))
import Effect (Effect)
import Effect (Effect)
import Effect.Aff (Aff, launchAff, launchAff_)
import Effect.Aff (Aff, launchAff, launchAff_)
import Gargantext.Components.Bootstrap as B
import Gargantext.Components.Bootstrap as B
...
@@ -19,6 +21,7 @@ import Gargantext.Utils.Reactix as R2
...
@@ -19,6 +21,7 @@ import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Show as GUS
import Gargantext.Utils.Show as GUS
import Reactix as R
import Reactix as R
import Reactix.DOM.HTML as H
import Reactix.DOM.HTML as H
import Record.Extra as RX
import Toestand as T
import Toestand as T
here :: R2.Here
here :: R2.Here
...
@@ -27,20 +30,86 @@ here = R2.here "Gargantext.Components.Forest.Tree.Node.Tools"
...
@@ -27,20 +30,86 @@ here = R2.here "Gargantext.Components.Forest.Tree.Node.Tools"
fragmentPT :: String -> R.Element
fragmentPT :: String -> R.Element
fragmentPT text = H.div { style: { margin: "10px" }} [ H.text text ]
fragmentPT text = H.div { style: { margin: "10px" }} [ H.text text ]
type Body = Array R.Element
type Footer = R.Element
type PanelProps =
( mError :: Maybe String )
-- | Last element of panel's children goes to footer, all others go to body
panel :: R2.Component PanelProps
panel = R.createElement panelCpt
panelCpt :: R.Component PanelProps
panelCpt = here.component "panel" cpt where
cpt { mError } children = do
let errorCpt =
R2.fromMaybe mError $
\err ->
R2.row
[ R2.col 12
[ H.div { className: "alert alert-danger" } [ H.text err ]
]
]
pure $ R.fragment
[ H.div { className: "card-body" }
[ H.div { className: "card-text" }
[ R2.row
-- TODO add type for text or form here [ H.form {className: "form-horizontal"} bodies ]
[ R2.col 12 bodies ]
, errorCpt
]
]
, H.div {className: "card-footer"}
[ R2.row
[ H.div { className: "mx-auto"} [ footer ] ]
]
]
where
bodies /\ footer =
case A.unsnoc children of
Nothing -> [] /\ (H.div {} [])
Just { init, last } -> init /\ last
-- | A panel without a footer
panelNoFooter :: R2.Component PanelProps
panelNoFooter = R.createElement panelNoFooterCpt
panelNoFooterCpt :: R.Component PanelProps
panelNoFooterCpt = here.component "panelNoFooter" cpt where
cpt props children =
pure $ panel props (children <> [ H.div {} [] ])
type PanelWithSubmitButtonProps =
( action :: Action
, dispatch :: Action -> Aff Unit
| PanelProps )
-- | A panel with 'submitButton { action, dispatch }'
panelWithSubmitButton :: R2.Component PanelWithSubmitButtonProps
panelWithSubmitButton = R.createElement panelWithSubmitButtonCpt
panelWithSubmitButtonCpt :: R.Component PanelWithSubmitButtonProps
panelWithSubmitButtonCpt = here.component "panelWithSubmitButton" cpt where
cpt props@{ action, dispatch } children = do
let pProps = (RX.pick props :: Record PanelProps)
pure $ panel pProps (children
-- footer
<> [ submitButton { action, dispatch } ])
type PanelWithSubmitButtonHrefProps =
( action :: Action
, href :: String
| PanelProps )
-- | A panel with 'submitButtonHref { action, href }'
panelWithSubmitButtonHref :: R2.Component PanelWithSubmitButtonHrefProps
panelWithSubmitButtonHref = R.createElement panelWithSubmitButtonHrefCpt
panelWithSubmitButtonHrefCpt :: R.Component PanelWithSubmitButtonHrefProps
panelWithSubmitButtonHrefCpt = here.component "panelWithSubmitButtonHref" cpt where
cpt props@{ action, href } children = do
let pProps = (RX.pick props :: Record PanelProps)
pure $ panel pProps (children
-- footer
<> [ submitButtonHref { action, href } ])
panel :: Body -> Footer -> R.Element
panel bodies submit =
R.fragment
[ H.div { className: "card-body" }
[ H.div { className: "row" }
-- TODO add type for text or form here [ H.form {className: "form-horizontal"} bodies ]
[ H.div { className: "col-12" } bodies ]]
, H.div {className: "card-footer"}
[ H.div { className: "row" }
[ H.div { className: "mx-auto"} [ submit ] ]]]
type TextInputBoxProps =
type TextInputBoxProps =
( id :: GT.ID
( id :: GT.ID
...
@@ -163,15 +232,15 @@ inviteInputBoxCpt = here.component "textInputBox" cpt where
...
@@ -163,15 +232,15 @@ inviteInputBoxCpt = here.component "textInputBox" cpt where
T.write_ ("Invited " <> R.readRef ref <> " to the team") username
T.write_ ("Invited " <> R.readRef ref <> " to the team") username
launchAff_ $ dispatch (boxAction $ R.readRef ref)
launchAff_ $ dispatch (boxAction $ R.readRef ref)
type DefaultText = String
--
type DefaultText = String
formEdit :: forall prev next
--
formEdit :: forall prev next
. DefaultText -> ((prev -> String) -> Effect next) -> R.Element
--
. DefaultText -> ((prev -> String) -> Effect next) -> R.Element
formEdit defaultValue setter =
--
formEdit defaultValue setter =
H.div { className: "form-group" }
--
H.div { className: "form-group" }
[ H.input { defaultValue, type: "text", on: { input }
--
[ H.input { defaultValue, type: "text", on: { input }
, placeholder: defaultValue, className: "form-control" }
--
, placeholder: defaultValue, className: "form-control" }
] where input = setter <<< const <<< R.unsafeEventValue
--
] where input = setter <<< const <<< R.unsafeEventValue
type FormChoiceSafeProps item m =
type FormChoiceSafeProps item m =
( items :: Array item
( items :: Array item
...
@@ -252,24 +321,41 @@ formButtonCpt = here.component "formButton" cpt where
...
@@ -252,24 +321,41 @@ formButtonCpt = here.component "formButton" cpt where
------------------------------------------------------------------------
------------------------------------------------------------------------
------------------------------------------------------------------------
------------------------------------------------------------------------
submitButton :: Action -> (Action -> Aff Unit) -> R.Element
type SubmitButtonProps =
submitButton action dispatch =
( action :: Action
H.button { className : "btn btn-primary fa fa-" <> icon action
, dispatch :: Action -> Aff Unit )
, type: "button"
, id: S.toLower $ show action
submitButton :: R2.Leaf SubmitButtonProps
, title: show action
submitButton = R2.leaf submitButtonCpt
, on: {click: \_ -> launchAff $ dispatch action}
submitButtonCpt :: R.Component SubmitButtonProps
}
submitButtonCpt = here.component "submitButton" cpt where
[ H.span {className: "font-family-theme mx-1"} [ H.text $ " " <> text action] ]
cpt { action
, dispatch } _ = do
pure $ H.button { className : "btn btn-primary fa fa-" <> icon action
, type: "button"
, id: S.toLower $ show action
, title: show action
, on: {click: \_ -> launchAff $ dispatch action}
}
[ H.span {className: "font-family-theme mx-1"} [ H.text $ " " <> text action] ]
type Href = String
type Href = String
submitButtonHref :: Action -> Href -> R.Element
type SubmitButtonHrefProps =
submitButtonHref action href =
( action :: Action
H.a { className, href, target: "_blank" }
, href :: Href )
[ H.span {className: "font-family-theme mx-1"} [ H.text $ " " <> text action ] ]
where
submitButtonHref :: R2.Leaf SubmitButtonHrefProps
className = "btn btn-primary fa fa-" <> icon action
submitButtonHref = R2.leaf submitButtonHrefCpt
submitButtonHrefCpt :: R.Component SubmitButtonHrefProps
submitButtonHrefCpt = here.component "submitButtonHref" cpt where
cpt { action, href } _ = do
pure $
H.a { className, href, target: "_blank" }
[ H.span {className: "font-family-theme mx-1"} [ H.text $ " " <> text action ] ]
where
className = "btn btn-primary fa fa-" <> icon action
------------------------------------------------------------------------
------------------------------------------------------------------------
-- | CheckBox tools
-- | CheckBox tools
...
...
src/Gargantext/Components/GraphExplorer/Topbar/Search.purs
View file @
65e9cf3e
...
@@ -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"
...
@@ -69,7 +70,7 @@ nodeSearchControlCpt = here.component "nodeSearchControl" cpt
...
@@ -69,7 +70,7 @@ nodeSearchControlCpt = here.component "nodeSearchControl" cpt
, pattern: ".*"
, pattern: ".*"
, title: ""
, title: ""
, placeholder: "find and select a term here..."
, placeholder: "find and select a term here..."
}
}
[]
,
,
B.button
B.button
{ callback: \_ -> doSearch search'
{ callback: \_ -> doSearch search'
...
...
src/Gargantext/Components/InputWithAutocomplete.purs
View file @
65e9cf3e
...
@@ -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
...
@@ -37,19 +38,20 @@ type Props =
...
@@ -37,19 +38,20 @@ type Props =
, state :: T.Box String
, state :: T.Box String
)
)
inputWithAutocomplete :: R2.
Leaf
Props
inputWithAutocomplete :: R2.
Component
Props
inputWithAutocomplete = R2.
leaf
inputWithAutocompleteCpt
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
, placeholder
, placeholder
, pattern
, pattern
, title
, title
, state }
_
= do
, state }
children
= do
-- States
-- States
state' <- T.useLive T.unequal state
state' <- T.useLive T.unequal state
containerRef <- R.useRef null
containerRef <- R.useRef null
...
@@ -67,14 +69,15 @@ inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt
...
@@ -67,14 +69,15 @@ inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt
{ className: "input-with-autocomplete " <> classes
{ className: "input-with-autocomplete " <> classes
, ref: containerRef
, ref: containerRef
}
}
[
(
[
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
...
@@ -83,7 +86,7 @@ inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt
...
@@ -83,7 +86,7 @@ inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt
, blur: onBlur completions containerRef
, blur: onBlur completions containerRef
}
}
}
}
]
]
<> children)
-- Helpers
-- Helpers
where
where
...
@@ -143,139 +146,6 @@ inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt
...
@@ -143,139 +146,6 @@ inputWithAutocompleteCpt = here.component "inputWithAutocomplete" cpt
else
else
pure $ false
pure $ false
type Props' =
(
autocompleteSearch :: String -> Effect Completions
, classes :: String
, onAutocompleteClick :: String -> Effect Unit
, dispatch :: Action -> Aff Unit
, boxAction :: String -> Action
, state :: T.Box String
, text :: T.Box String
, pattern :: String
, title :: String
, placeholder :: String
)
inputWithAutocomplete' :: R2.Leaf Props'
inputWithAutocomplete' = R2.leaf inputWithAutocompleteCpt'
inputWithAutocompleteCpt' :: R.Component Props'
inputWithAutocompleteCpt' = here.component "inputWithAutocomplete" cpt
where
cpt { autocompleteSearch
, classes
, onAutocompleteClick
, dispatch
, boxAction
, state
, text
, pattern
, title
, placeholder } _ = do
-- States
state' <- T.useLive T.unequal state
containerRef <- R.useRef null
inputRef <- R.useRef null
completions <- T.useBox []
R.useEffectOnce' $ do
cs <- autocompleteSearch state'
T.write_ cs completions
-- Render
pure $
H.div
{ className: "input-with-autocomplete " <> classes
, ref: containerRef
}
[
completionsCpt { completions, onAutocompleteClick, state } []
, H.input { type: "text"
, ref: inputRef
, className: "form-control"
, value: state'
, pattern: pattern
, title: title
, placeholder
, on: { focus: onFocus completions state'
, input: onInput completions
, change: onInput completions
, keyUp: onInputKeyUp inputRef
, blur: onBlur completions containerRef
}
}
, B.iconButton
{ callback: submit state'
, title: "Submit"
, name: "send"
, elevation: Level1
}
]
-- Helpers
where
-- (!) `onBlur` DOM.Event is triggered before any `onClick` DOM.Event
-- So when a completion is being clicked, the UX will be broken
--
-- ↳ As a solution we chose to check if the click is made from
-- the autocompletion list
onBlur :: forall event.
T.Box Completions
-> R.Ref (Nullable DOM.Element)
-> event
-> Effect Unit
onBlur completions containerRef event =
if isInnerEvent
then
pure $ (event .. "preventDefault")
else
T.write_ [] completions
where
mContains = do
a <- toMaybe $ R.readRef containerRef
b <- toMaybe (event .. "relatedTarget")
Just (contains a b)
isInnerEvent = maybe false identity mContains
onFocus :: forall event. T.Box Completions -> String -> event -> Effect Unit
onFocus completions st _ = do
cs <- autocompleteSearch st
T.write_ cs completions
onInput :: forall event. T.Box Completions -> event -> Effect Unit
onInput completions e = do
let val = R.unsafeEventValue e
T.write_ val state
cs <- autocompleteSearch val
T.write_ cs completions
onInputKeyUp :: R.Ref (Nullable DOM.Element) -> DE.KeyboardEvent -> Effect Boolean
onInputKeyUp inputRef e = do
if DE.key e == "Enter" then do
R2.preventDefault e
R2.stopPropagation e
let val = S.trim $ R.unsafeEventValue e
let mInput = toMaybe $ R.readRef inputRef
T.write_ val state
launchAff_ $ dispatch (boxAction val)
T.write_ ("Invited " <> val <> " to the team") text
case mInput of
Nothing -> pure false
Just input -> do
R2.blur input
pure false
else
pure $ false
submit val _ = do
T.write_ ("Invited " <> S.trim val <> " to the team") text
launchAff_ $ dispatch (boxAction val)
---------------------------------------------------------
---------------------------------------------------------
type CompletionsProps =
type CompletionsProps =
...
...
src/Gargantext/Components/PhyloExplorer/Topbar/TopBar.purs
View file @
65e9cf3e
...
@@ -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
...
@@ -151,7 +152,7 @@ component = here.component "main" cpt where
...
@@ -151,7 +152,7 @@ component = here.component "main" cpt where
, title: ""
, title: ""
, placeholder: "find and select a term here..."
, placeholder: "find and select a term here..."
, state: searchState
, state: searchState
}
}
[]
]
]
]
]
...
...
src/Gargantext/Components/TreeSearch.purs
View file @
65e9cf3e
...
@@ -78,15 +78,15 @@ treeSearchCpt = here.component "treeSearch" cpt where
...
@@ -78,15 +78,15 @@ treeSearchCpt = here.component "treeSearch" cpt where
{ className: "input-group p-1" }
{ className: "input-group p-1" }
[
[
inputWithEnter { className: "form-control"
inputWithEnter { className: "form-control"
, autoFocus: true
, autoFocus: true
, onEnter: submit inputRef query
, onEnter: submit inputRef query
, onValueChanged: R.setRef inputRef
, onValueChanged: R.setRef inputRef
, onBlur: R.setRef inputRef
, onBlur: R.setRef inputRef
, type: "value"
, type: "value"
, defaultValue: ""
, defaultValue: ""
, required: true
, required: true
, placeholder: "Search keys..."
, placeholder: "Search keys..."
}
}
,
,
H.div { className: "input-group-append"}
H.div { className: "input-group-append"}
[
[
...
...
src/Gargantext/Config/REST.purs
View file @
65e9cf3e
...
@@ -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)
...
@@ -13,6 +14,7 @@ import Data.Generic.Rep (class Generic)
...
@@ -13,6 +14,7 @@ import Data.Generic.Rep (class Generic)
import Data.HTTP.Method (Method(..))
import Data.HTTP.Method (Method(..))
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..))
import Data.MediaType.Common (applicationFormURLEncoded, applicationJSON, multipartFormData)
import Data.MediaType.Common (applicationFormURLEncoded, applicationJSON, multipartFormData)
import Data.Show.Generic (genericShow)
import Data.Tuple (Tuple)
import Data.Tuple (Tuple)
import Effect (Effect)
import Effect (Effect)
import Effect.Aff (Aff)
import Effect.Aff (Aff)
...
@@ -23,29 +25,145 @@ import Gargantext.Utils.Reactix as R2
...
@@ -23,29 +25,145 @@ 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
| FE FrontendError
| CustomError String
| ReadJSONError Foreign.MultipleErrors
| 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 (FE e) = show e
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
data FrontendError =
EC_400__node_creation_failed_insert_node { user_id :: Int
, parent_id :: Int }
| EC_400__node_creation_failed_no_parent { user_id :: Int }
| EC_400__node_creation_failed_parent_exists { parent_id :: Int
, user_id :: Int }
| EC_400__node_creation_failed_user_negative_id { user_id :: Int }
| EC_400__node_lookup_failed_user_too_many_roots { user_id :: Int
, roots :: Array Int }
| EC_400__node_needs_configuration
| EC_403__login_failed_error { node_id :: Int
, user_id :: Int }
| EC_403__login_failed_invalid_username_or_password
| EC_404__node_context_not_found { context_id :: Int }
| EC_404__node_lookup_failed_not_found { node_id :: Int }
| EC_404__node_lookup_failed_parent_not_found { node_id :: Int }
| EC_404__node_lookup_failed_username_not_found { username :: String }
| EC_404__node_list_not_found { list_id :: Int }
| EC_404__node_root_not_found
| EC_500__node_generic_exception { error :: String }
| EC_500__node_not_implemented_yet
derive instance Generic FrontendError _
instance Show FrontendError where
show (EC_400__node_creation_failed_insert_node { user_id, parent_id }) =
"Failed to insert node for user " <> show user_id <> ", parent " <> show parent_id
show (EC_400__node_creation_failed_no_parent { user_id }) =
"Failed to insert node for user " <> show user_id <> ": no parent"
show (EC_400__node_creation_failed_parent_exists { user_id, parent_id }) =
"Failed to insert node for user " <> show user_id <> ", parent " <> show parent_id <> " exists"
show (EC_400__node_creation_failed_user_negative_id { user_id }) =
"Failed to insert node for use " <> show user_id <> " (negative user_id)"
show (EC_400__node_lookup_failed_user_too_many_roots { user_id, roots }) =
"Failed to lookup node for user " <> show user_id <> ": too many roots (" <> show roots <> ")"
show EC_400__node_needs_configuration = "Node needs configuration"
show (EC_403__login_failed_error { node_id, user_id }) =
"Login failed for node_id " <> show node_id <> ", user id " <> show user_id
show EC_403__login_failed_invalid_username_or_password =
"Invalid username or password"
show (EC_404__node_context_not_found { context_id }) =
"Context not found with id " <> show context_id
show (EC_404__node_lookup_failed_not_found { node_id }) =
"Node not found with id " <> show node_id
show (EC_404__node_lookup_failed_parent_not_found { node_id }) =
"Node parent not found for id " <> show node_id
show (EC_404__node_lookup_failed_username_not_found { username }) =
"User '" <> username <> "' not found"
show (EC_404__node_list_not_found { list_id }) =
"Node list not found for id " <> show list_id
show EC_404__node_root_not_found = "Node root not found"
show (EC_500__node_generic_exception { error }) =
"Node exception: " <> error
show EC_500__node_not_implemented_yet = "Node not implemented yet"
instance JSON.ReadForeign FrontendError where
readImpl f = do
{ type: type_ } <- JSON.readImpl f :: Foreign.F { type :: String }
case type_ of
"EC_400__node_creation_failed_insert_node" -> do
{ data: { parent_id, user_id } } <- JSON.readImpl f :: Foreign.F { data :: { parent_id :: Int
, user_id :: Int } }
pure $ EC_400__node_creation_failed_insert_node { parent_id, user_id }
"EC_400__node_creation_failed_no_parent" -> do
{ data: { user_id } } <- JSON.readImpl f :: Foreign.F { data :: { user_id :: Int } }
pure $ EC_400__node_creation_failed_no_parent { user_id }
"EC_400__node_creation_failed_parent_exists" -> do
{ data: { parent_id, user_id } } <- JSON.readImpl f :: Foreign.F { data :: { parent_id :: Int
, user_id :: Int } }
pure $ EC_400__node_creation_failed_parent_exists { parent_id, user_id }
"EC_400__node_creation_failed_user_negative_id" -> do
{ data: { user_id } } <- JSON.readImpl f :: Foreign.F { data :: { user_id :: Int } }
pure $ EC_400__node_creation_failed_user_negative_id { user_id }
"EC_400__node_lookup_failed_user_too_many_roots" -> do
{ data: { user_id, roots } } <- JSON.readImpl f :: Foreign.F { data :: { user_id :: Int
, roots :: Array Int } }
pure $ EC_400__node_lookup_failed_user_too_many_roots { user_id, roots }
"EC_400__node_needs_configuration" -> do
pure $ EC_400__node_needs_configuration
"EC_403__login_failed_error" -> do
{ data: { node_id, user_id } } <- JSON.readImpl f :: Foreign.F { data :: { node_id :: Int
, user_id :: Int } }
pure $ EC_403__login_failed_error { node_id, user_id }
"EC_403__login_failed_invalid_username_or_password" -> do
pure $ EC_403__login_failed_invalid_username_or_password
"EC_404__node_context_not_found" -> do
{ data: { context_id } } <- JSON.readImpl f :: Foreign.F { data :: { context_id :: Int } }
pure $ EC_404__node_context_not_found { context_id }
"EC_404__node_lookup_failed_not_found" -> do
{ data: { node_id } } <- JSON.readImpl f :: Foreign.F { data :: { node_id :: Int } }
pure $ EC_404__node_lookup_failed_not_found { node_id }
"EC_404__node_lookup_failed_parent_not_found" -> do
{ data: { node_id } } <- JSON.readImpl f :: Foreign.F { data :: { node_id :: Int } }
pure $ EC_404__node_lookup_failed_parent_not_found { node_id }
"EC_404__node_lookup_failed_username_not_found" -> do
{ data: { username } } <- JSON.readImpl f :: Foreign.F { data :: { username :: String } }
pure $ EC_404__node_lookup_failed_username_not_found { username }
"EC_404__node_list_not_found" -> do
{ data: { list_id } } <- JSON.readImpl f :: Foreign.F { data :: { list_id :: Int } }
pure $ EC_404__node_list_not_found { list_id }
"EC_404__node_root_not_found" -> do
pure $ EC_404__node_root_not_found
"EC_500__node_generic_exception" -> do
{ data: { error } } <- JSON.readImpl f :: Foreign.F { data :: { error :: String } }
pure $ EC_500__node_generic_exception { error }
"EC_500__node_not_implemented_yet" -> do
pure $ EC_500__node_not_implemented_yet
_ -> Foreign.fail $ Foreign.ForeignError $ "deserialization for '" <> type_ <> "' not implemented"
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 +171,9 @@ logRESTError here prefix e = here.warn2 (prefix <> " " <> show e) e
...
@@ -53,11 +171,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 +184,16 @@ readJSON affResp =
...
@@ -68,9 +184,16 @@ 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
Left err -> Left $ ReadJSONError err
case resp.status of
Right r -> Right r
StatusCode 200 ->
case (JSON.readJSON $ AC.stringify resp.body) of
Left err -> Left $ ReadJSONError err
Right r -> Right r
_ -> case (JSON.readJSON $ AC.stringify resp.body :: JSON.E FrontendError) of
Right err -> Left $ FE err
Left _ -> Left $ UnknownServerError $ AC.stringify resp.body
-- 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 =>
...
@@ -82,6 +205,7 @@ send m mtoken url reqbody = do
...
@@ -82,6 +205,7 @@ send m mtoken url reqbody = do
, method = Left m
, method = Left m
, headers = [ ARH.ContentType applicationJSON
, headers = [ ARH.ContentType applicationJSON
, ARH.Accept applicationJSON
, ARH.Accept applicationJSON
, ARH.RequestHeader "X-Garg-Error-Scheme" $ "new"
] <>
] <>
foldMap (\token ->
foldMap (\token ->
[ARH.RequestHeader "Authorization" $ "Bearer " <> token]
[ARH.RequestHeader "Authorization" $ "Bearer " <> token]
...
@@ -94,6 +218,7 @@ send m mtoken url reqbody = do
...
@@ -94,6 +218,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
...
...
src/Gargantext/Sessions.purs
View file @
65e9cf3e
...
@@ -115,12 +115,9 @@ postAuthRequest :: Backend -> AuthRequest -> Aff (Either String Session)
...
@@ -115,12 +115,9 @@ postAuthRequest :: Backend -> AuthRequest -> Aff (Either String Session)
postAuthRequest backend ar@(AuthRequest {username}) =
postAuthRequest backend ar@(AuthRequest {username}) =
decode <$> REST.post Nothing (toUrl backend "auth") ar
decode <$> REST.post Nothing (toUrl backend "auth") ar
where
where
decode (Left err) = Left $ "Error when sending REST.post: " <> show err
decode (Left err) = Left $ show err
decode (Right (AuthResponse ar2))
decode (Right (AuthData { token, tree_id, user_id })) =
| {inval: Just (AuthInvalid {message})} <- ar2 = Left message
Right $ Session { backend, caches: Map.empty, token, treeId: tree_id, username, userId: user_id }
| {valid: Just (AuthData {token, tree_id, user_id})} <- ar2 =
Right $ Session { backend, caches: Map.empty, token, treeId: tree_id, username, userId: user_id }
| otherwise = Left "Invalid response from server"
postForgotPasswordRequest :: Backend -> String -> Aff (Either String { status :: String })
postForgotPasswordRequest :: Backend -> String -> Aff (Either String { status :: String })
postForgotPasswordRequest backend email =
postForgotPasswordRequest backend email =
...
...
src/Gargantext/Utils/Reactix.purs
View file @
65e9cf3e
...
@@ -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
...
...
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