Commit 5c5b4641 authored by Przemyslaw Kaminski's avatar Przemyslaw Kaminski

Merge branch 'dev' into dev-doc-table-optimization

parents 756153d5 2ee876fb
......@@ -2675,6 +2675,15 @@
"repo": "https://github.com/reactormonk/purescript-simple-timestamp.git",
"version": "v1.3.0"
},
"simplecrypto": {
"dependencies": [
"prelude",
"maybe",
"node-buffer"
],
"repo": "https://github.com/alpacaaa/purescript-simplecrypto",
"version": "v1.0.1"
},
"sized-vectors": {
"dependencies": [
"arrays",
......
......@@ -838,6 +838,15 @@
sha256 = "10fkkmmb7qh4p5gmgb6xpxh9g8hy06ddy8cyfrs3py8a5b8h46hw";
};
};
"simplecrypto" = {
name = "simplecrypto";
version = "v1.0.1";
src = pkgs.fetchgit {
url = "https://github.com/alpacaaa/purescript-simplecrypto";
rev = "v1.0.1";
sha256 = "0rzjzwn4s7pb8f9hm9wkl1gza9y2y9qn1116s6x5lizv81q48cyw";
};
};
"smolder" = {
name = "smolder";
version = "v12.0.0";
......
{
"name": "Gargantext",
"version": "0.0.1.6.6",
"version": "0.0.1.7.1",
"scripts": {
"rebase-set": "spago package-set-upgrade && spago psc-package-insdhall",
"rebuild-set": "spago psc-package-insdhall",
......@@ -13,10 +13,12 @@
"clean": "rm -Rf output node_modules",
"clean-js": "rm -Rf node_modules",
"clean-ps": "rm -Rf output",
"test": "pulp test",
"test": "pulp test --no-check-main",
"server": "serve dist"
},
"dependencies": {
"aes-js": "^3.1.1",
"base-x": "^3.0.2",
"create-react-class": "^15.6.3",
"echarts": "^4.1.0",
"echarts-for-react": "^2.0.14",
......@@ -25,6 +27,7 @@
"react": "^16.10",
"react-awesome-popover": "^6.1.1",
"react-dom": "^16.10",
"secp256k1": "^3.3.0",
"sigma": "git://github.com/poorscript/sigma.js#garg"
},
"devDependencies": {
......
......@@ -140,6 +140,11 @@ let additions =
[ "prelude" ]
"https://github.com/hdgarrood/purescript-versions.git"
"v5.0.1"
, simplecrypto =
mkPackage
[ "prelude", "maybe", "node-buffer"]
"https://github.com/alpacaaa/purescript-simplecrypto"
"v1.0.1"
}
in upstream ⫽ overrides ⫽ additions
......@@ -3,8 +3,8 @@
"set": "local",
"source": ".psc-package/local/.set/packages.json",
"depends": [
"affjax",
"aff-promise",
"affjax",
"argonaut",
"console",
"css",
......@@ -12,8 +12,8 @@
"dom-filereader",
"dom-simple",
"effect",
"foreign-object",
"foreign-generic",
"foreign-object",
"generics-rep",
"globals",
"integers",
......@@ -32,6 +32,7 @@
"record-extra",
"routing",
"sequences",
"simplecrypto",
"smolder",
"spec-discovery",
"spec-quickcheck",
......
module Gargantext.Components.App where
import Prelude
import Data.Array (fromFoldable)
import Data.Foldable (intercalate)
import Data.Maybe (Maybe(..), maybe')
import Data.Tuple (fst, snd)
import Data.Tuple.Nested ((/\))
import Effect.Aff (launchAff_)
import Effect.Class (liftEffect)
import Reactix as R
import Reactix.DOM.HTML as H
import Gargantext.License (license)
import Gargantext.Components.Lang (LandingLang(..))
import Gargantext.Components.Forest (forest)
import Gargantext.Components.GraphExplorer (explorerLayout)
import Gargantext.Components.Lang (LandingLang(..))
import Gargantext.Components.Login (login)
import Gargantext.Components.Nodes.Annuaire (annuaireLayout)
import Gargantext.Components.Nodes.Annuaire.User.Contacts (annuaireUserLayout, userLayout)
import Gargantext.Components.Nodes.Corpus (corpusLayout)
import Gargantext.Components.Nodes.Frame (frameLayout)
import Gargantext.Components.Nodes.Corpus.Dashboard (dashboardLayout)
import Gargantext.Components.Nodes.Corpus.Document (documentLayout)
import Gargantext.Components.Nodes.Frame (frameLayout)
import Gargantext.Components.Nodes.Home (homeLayout)
import Gargantext.Components.Nodes.Lists (listsLayout)
import Gargantext.Components.Nodes.Texts (textsLayout)
import Gargantext.Config (defaultFrontends, defaultBackends)
import Gargantext.Ends (Frontends)
import Gargantext.Hooks.Router (useHashRouter)
import Gargantext.License (license)
import Gargantext.Router (router)
import Gargantext.Routes (AppRoute(..))
import Gargantext.Sessions (Sessions, useSessions)
import Gargantext.Sessions as Sessions
import Gargantext.Utils.Reactix as R2
import Gargantext.Version as GV
import Prelude
import Reactix as R
import Reactix.DOM.HTML as H
-- TODO (what does this mean?)
-- tree changes endConfig state => trigger endConfig change in outerLayout, layoutFooter etc
......@@ -251,59 +245,21 @@ liNav (LiNav { title : title'
]
---------------------------------------------------------------------------
-- | TODO put Version in the Tree/Root node
type VersionProps =
type FooterProps =
(
session :: Sessions.Session
)
version :: Record VersionProps -> R.Element
version props = R.createElement versionCpt props []
versionCpt :: R.Component VersionProps
versionCpt = R.hooksComponent "G.C.A.version" cpt
where
cpt { session } _ = do
(ver /\ setVer) <- R.useState' "No Backend Version"
R.useEffect' $ do
launchAff_ $ do
v <- GV.getBackendVersion session
liftEffect $ setVer $ const v
pure $ H.div { className: "row" }
[ H.div { className: versionCheck GV.version ver}
[ H.h4 {} [H.text $ versionMessage GV.version ver]
, H.div { className: "container" } [showVersions GV.version ver]
]
]
where
versionCheck v1 v2 = case v1 == v2 of
false -> "col alert alert-danger"
true -> "col alert alert-success"
versionMessage v1 v2 = case v1 == v2 of
false -> "Versions do not match"
true -> "Versions are up to date"
showVersions frontendVer backendVer =
H.div { className: "row" }
[ H.h5 {} [ H.text $ "Frontend version: " <> frontendVer ]
, H.h5 {} [ H.text $ "Backend version: " <> backendVer ]
]
footer :: Record VersionProps -> R.Element
footer :: Record FooterProps -> R.Element
footer props = R.createElement footerCpt props []
footerCpt :: R.Component VersionProps
footerCpt :: R.Component FooterProps
footerCpt = R.hooksComponent "G.C.A.footer" cpt
where
cpt { session } _ = do
pure $ H.div
{ className: "container" }
[ H.hr {}
, H.footer {} [ version { session }
, license
]
, H.footer {} [ license ]
]
......@@ -363,18 +363,18 @@ loadPage session { corpusId, listId, nodeId, query, tabType } = do
--liftEffect $ log3 "loading documents page: loadPage with Offset and limit" offset limit
-- res <- get $ toUrl endConfigStateful Back (Tab tabType offset limit (convOrderBy <$> orderBy)) (Just nodeId)
let p = NodeAPI Node (Just nodeId) $ "table" <> "?tabType=" <> (showTabType' tabType)
HashedResponse { md5, value: res } <- (get session p) :: Aff (HashedResponse (TableResult Response))
HashedResponse { hash, value: res } <- (get session p) :: Aff (HashedResponse (TableResult Response))
let docs = res2corpus <$> res.docs
let ret = if mock then
--Tuple 0 (take limit $ drop offset sampleData)
Tuple 0 sampleData
else
Tuple res.count docs
pure $ HashedResponse { md5, value: ret }
pure $ HashedResponse { hash, value: ret }
getPageMD5 :: Session -> PageParams -> Aff String
getPageMD5 session { corpusId, listId, nodeId, query, tabType } = do
let p = NodeAPI Node (Just nodeId) $ "table/md5" <> "?tabType=" <> (showTabType' tabType)
getPageHash :: Session -> PageParams -> Aff String
getPageHash session { corpusId, listId, nodeId, query, tabType } = do
let p = NodeAPI Node (Just nodeId) $ "table/hash" <> "?tabType=" <> (showTabType' tabType)
(get session p) :: Aff String
......@@ -404,9 +404,9 @@ pageLayoutCpt :: R.Component PageLayoutProps
pageLayoutCpt = R.hooksComponent "G.C.DocsTable.pageLayout" cpt where
cpt props@{frontends, session, nodeId, listId, corpusId, tabType, query, params} _ =
-- useLoader path (loadPage session) paint
--useLoaderWithCache path keyFunc (getPageMD5 session) (loadPage session) paint
-- useLoaderWithCache path keyFunc (getPageHash session) (loadPage session) paint
useLoaderWithCacheAPI {
cacheEndpoint: getPageMD5 session
cacheEndpoint: getPageHash session
, handleResponse
, mkRequest
, path
......@@ -424,7 +424,7 @@ pageLayoutCpt = R.hooksComponent "G.C.DocsTable.pageLayout" cpt where
mkRequest p@{ listId, nodeId, tabType } =
GUC.makeGetRequest session $ NodeAPI Node (Just nodeId) $ "table" <> "?tabType=" <> (showTabType' tabType) <> "&list=" <> (show listId)
handleResponse :: HashedResponse (TableResult Response) -> Tuple Int (Array DocumentsView)
handleResponse (HashedResponse { md5, value: res }) = ret
handleResponse (HashedResponse { hash, value: res }) = ret
where
docs = res2corpus <$> res.docs
ret = if mock then
......
......@@ -63,7 +63,7 @@ forestCpt = R.hooksComponent "G.C.Forest.forest" cpt where
plus :: R2.Setter Boolean -> R.Element
plus showLogin =
H.button { on: {click}
, className: "btn btn-primary"
, className: "btn btn-default"
}
[ H.div { "type": ""
, className: "fa fa-universal-access fa-lg"
......
......@@ -18,12 +18,12 @@ import Gargantext.Components.Forest.Tree.Node (nodeMainSpan)
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree.Types (SubTreeOut(..))
import Gargantext.Components.Forest.Tree.Node.Action (Action(..))
import Gargantext.Components.Forest.Tree.Node.Action.Add (AddNodeValue(..), addNode)
import Gargantext.Components.Forest.Tree.Node.Action.Delete (deleteNode)
import Gargantext.Components.Forest.Tree.Node.Action.Delete (deleteNode, unpublishNode)
import Gargantext.Components.Forest.Tree.Node.Action.Move (moveNodeReq)
import Gargantext.Components.Forest.Tree.Node.Action.Merge (mergeNodeReq)
import Gargantext.Components.Forest.Tree.Node.Action.Link (linkNodeReq)
import Gargantext.Components.Forest.Tree.Node.Action.Rename (RenameValue(..), rename)
import Gargantext.Components.Forest.Tree.Node.Action.Share (ShareValue(..), share)
import Gargantext.Components.Forest.Tree.Node.Action.Share as Share
import Gargantext.Components.Forest.Tree.Node.Action.Update (updateRequest)
import Gargantext.Components.Forest.Tree.Node.Action.Upload (uploadFile)
import Gargantext.Components.Forest.Tree.Node.Tools.FTree (FTree, LNode(..), NTree(..))
......@@ -33,7 +33,7 @@ import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Prelude (Unit, bind, discard, map, pure, void, ($), (+), (<>))
import Gargantext.Routes (AppRoute)
import Gargantext.Sessions (OpenNodes, Session, mkNodeId, get)
import Gargantext.Types (ID, Reload)
import Gargantext.Types (ID, Reload, isPublic, publicize)
import Gargantext.Types as GT
import Gargantext.Routes as GR
......@@ -192,7 +192,11 @@ toHtml p@{ asyncTasks
} ]
<> childNodes ( Record.merge commonProps
{ asyncTasks
, children: ary
, children: if isPublic nodeType
then map (\t -> map (\(LNode n@{ nodeType:nt } )
-> (LNode (n { nodeType= publicize nt }))
) t) ary
else ary
, folderOpen
}
)
......@@ -232,13 +236,17 @@ type PerformActionProps =
performAction :: Action
-> Record PerformActionProps
-> Aff Unit
performAction DeleteNode p@{ openNodes: (_ /\ setOpenNodes)
performAction (DeleteNode nt) p@{ openNodes: (_ /\ setOpenNodes)
, reload: (_ /\ setReload)
, session
, tree: (NTree (LNode {id}) _)
, tree: (NTree (LNode {id, parent_id}) _)
} =
do
void $ deleteNode session id
case nt of
GT.NodePublic GT.FolderPublic -> void $ deleteNode session nt id
GT.NodePublic _ -> void $ unpublishNode session parent_id id
_ -> void $ deleteNode session nt id
liftEffect $ setOpenNodes (Set.delete (mkNodeId session id))
performAction RefreshTree p
......@@ -274,12 +282,22 @@ performAction (RenameNode name) p@{ reload: (_ /\ setReload)
performAction RefreshTree p
-------
performAction (ShareNode username) p@{ reload: (_ /\ setReload)
performAction (ShareTeam username) p@{ reload: (_ /\ setReload)
, session
, tree: (NTree (LNode {id}) _)
} =
do
void $ share session id $ ShareValue {text:username}
void $ Share.shareReq session id $ Share.ShareTeamParams {username}
performAction (SharePublic {params}) p@{ session
, openNodes: (_ /\ setOpenNodes)
} =
case params of
Nothing -> performAction NoAction p
Just (SubTreeOut {in:inId,out}) -> do
void $ Share.shareReq session inId $ Share.SharePublicParams {node_id:out}
liftEffect $ setOpenNodes (Set.insert (mkNodeId session out))
performAction RefreshTree p
-------
performAction (AddNode name nodeType) p@{ openNodes: (_ /\ setOpenNodes)
......
......@@ -22,6 +22,7 @@ import Gargantext.Ends (Frontends, url)
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Prelude (Unit, bind, const, discard, map, pure, show, unit, void, ($), (<>), (==))
import Gargantext.Routes as Routes
import Gargantext.Version as GV
import Gargantext.Sessions (Session, sessionId)
import Gargantext.Types (Name, ID)
import Gargantext.Types as GT
......@@ -88,6 +89,9 @@ nodeMainSpan p@{ dispatch, folderOpen, frontends, session } = R.createElement el
}
) tasks
)
, if nodeType == GT.NodeUser
then GV.versionView {session}
else H.div {} []
]
where
SettingsBox {show: showBox} = settingsBox nodeType
......@@ -96,6 +100,7 @@ nodeMainSpan p@{ dispatch, folderOpen, frontends, session } = R.createElement el
name' {name, nodeType} = if nodeType == GT.NodeUser
then show session
else name
chevronIcon nodeType folderOpen'@(open /\ _) =
H.a { className: "chevron-icon"
, onClick: R2.effToggler folderOpen'
......@@ -230,6 +235,8 @@ mAppRouteId (Just (Routes.Texts _ id)) = Just id
mAppRouteId (Just (Routes.Lists _ id)) = Just id
mAppRouteId (Just (Routes.Annuaire _ id)) = Just id
mAppRouteId (Just (Routes.UserPage _ id)) = Just id
mAppRouteId (Just (Routes.RouteFrameWrite _ id)) = Just id
mAppRouteId (Just (Routes.RouteFrameCalc _ id)) = Just id
mAppRouteId (Just (Routes.Document _ id _ )) = Just id
mAppRouteId (Just (Routes.ContactPage _ id _ )) = Just id
mAppRouteId (Just (Routes.CorpusDocument _ id _ _)) = Just id
......
......@@ -20,41 +20,45 @@ type Props =
data Action = AddNode String GT.NodeType
| DeleteNode
| DeleteNode GT.NodeType
| RenameNode String
| UpdateNode UpdateNodeParams
| ShareNode String
| DoSearch GT.AsyncTaskWithType
| UploadFile GT.NodeType FileType (Maybe String) UploadFileContents
| DownloadNode
| RefreshTree
| MoveNode {params :: Maybe SubTreeOut}
| MergeNode {params :: Maybe SubTreeOut}
| LinkNode {params :: Maybe SubTreeOut}
| ShareTeam String
| SharePublic {params :: Maybe SubTreeOut}
| MoveNode {params :: Maybe SubTreeOut}
| MergeNode {params :: Maybe SubTreeOut}
| LinkNode {params :: Maybe SubTreeOut}
| NoAction
subTreeOut :: Action -> Maybe SubTreeOut
subTreeOut (MoveNode {params}) = params
subTreeOut (MergeNode {params}) = params
subTreeOut (LinkNode {params}) = params
subTreeOut (MoveNode {params}) = params
subTreeOut (MergeNode {params}) = params
subTreeOut (LinkNode {params}) = params
subTreeOut (SharePublic {params}) = params
subTreeOut _ = Nothing
setTreeOut :: Action -> Maybe SubTreeOut -> Action
setTreeOut (MoveNode {params:_}) p = MoveNode {params: p}
setTreeOut (MergeNode {params:_}) p = MergeNode {params: p}
setTreeOut (LinkNode {params:_}) p = LinkNode {params: p}
setTreeOut (SharePublic {params:_}) p = SharePublic {params: p}
setTreeOut a _ = a
instance showShow :: Show Action where
show (AddNode _ _ )= "AddNode"
show DeleteNode = "DeleteNode"
show (DeleteNode _ )= "DeleteNode"
show (RenameNode _ )= "RenameNode"
show (UpdateNode _ )= "UpdateNode"
show (ShareNode _ )= "ShareNode"
show (ShareTeam _ )= "ShareTeam"
show (SharePublic _ )= "SharePublic"
show (DoSearch _ )= "SearchQuery"
show (UploadFile _ _ _ _)= "UploadFile"
show RefreshTree = "RefreshTree"
......@@ -67,10 +71,11 @@ instance showShow :: Show Action where
-----------------------------------------------------------------------
icon :: Action -> String
icon (AddNode _ _) = glyphiconNodeAction (Add [])
icon DeleteNode = glyphiconNodeAction Delete
icon (DeleteNode _) = glyphiconNodeAction Delete
icon (RenameNode _) = glyphiconNodeAction Config
icon (UpdateNode _) = glyphiconNodeAction Refresh
icon (ShareNode _) = glyphiconNodeAction Share
icon (ShareTeam _) = glyphiconNodeAction Share
icon (SharePublic _ ) = glyphiconNodeAction (Publish { subTreeParams : SubTreeParams {showtypes:[], valitypes:[] }})
icon (DoSearch _) = glyphiconNodeAction SearchBox
icon (UploadFile _ _ _ _) = glyphiconNodeAction Upload
icon RefreshTree = glyphiconNodeAction Refresh
......@@ -85,16 +90,17 @@ icon NoAction = "hand-o-right"
text :: Action -> String
text (AddNode _ _ )= "Add !"
text DeleteNode = "Delete !"
text (DeleteNode _ )= "Delete !"
text (RenameNode _ )= "Rename !"
text (UpdateNode _ )= "Update !"
text (ShareNode _ )= "Share !"
text (ShareTeam _ )= "Share with team !"
text (SharePublic _ )= "Publish !"
text (DoSearch _ )= "Launch search !"
text (UploadFile _ _ _ _)= "Upload File !"
text RefreshTree = "Refresh Tree !"
text DownloadNode = "Download !"
text (MoveNode _ ) = "Move !"
text (MergeNode _ ) = "Merge !"
text (LinkNode _ ) = "Link !"
text (MoveNode _ ) = "Move !"
text (MergeNode _ ) = "Merge !"
text (LinkNode _ ) = "Link !"
text NoAction = "No Action"
-----------------------------------------------------------------------
module Gargantext.Components.Forest.Tree.Node.Action.Add where
import Data.Argonaut (class EncodeJson, jsonEmptyObject, (:=), (~>))
import Data.Array (head)
import Data.Array (head, length)
import Data.Maybe (Maybe(..), fromMaybe)
import Data.Tuple.Nested ((/\))
import Effect.Aff (Aff)
import Gargantext.Components.Forest.Tree.Node.Settings (SettingsBox(..), settingsBox)
import Gargantext.Components.Forest.Tree.Node.Action (Action(..))
import Gargantext.Components.Forest.Tree.Node.Tools (submitButton, formEdit, formChoiceSafe, panel)
import Gargantext.Prelude (Unit, bind, pure, show, ($), (<>))
import Gargantext.Prelude (Unit, bind, pure, show, ($), (<>), (>))
import Gargantext.Routes as GR
import Gargantext.Sessions (Session, post)
import Gargantext.Types as GT
......@@ -61,17 +61,26 @@ addNodeView p@{ dispatch, nodeType, nodeTypes } = R.createElement el p []
el = R.hooksComponent "AddNodeView" cpt
cpt {id, name} _ = do
nodeName@(name' /\ setNodeName) <- R.useState' "Name"
nodeType'@(nt /\ setNodeType) <- R.useState' $ fromMaybe NodeUser $ head nodeTypes
nodeType'@(nt /\ setNodeType) <- R.useState' $ fromMaybe Folder $ head nodeTypes
let
SettingsBox {edit} = settingsBox nt
maybeChoose = [ formChoiceSafe nodeTypes Error setNodeType ]
(maybeChoose /\ nt') = if length nodeTypes > 1
then ([ formChoiceSafe nodeTypes Error setNodeType ] /\ nt)
else ([H.div {} [H.text $ "Creating a node of type "
<> show defaultNt
<> " with name:"
]
] /\ defaultNt
)
where
defaultNt = (fromMaybe Error $ head nodeTypes)
maybeEdit = [ if edit
then formEdit "Node Name" setNodeName
else H.div {} []
]
pure $ panel (maybeChoose <> maybeEdit) (submitButton (AddNode name' nt) dispatch)
pure $ panel (maybeChoose <> maybeEdit) (submitButton (AddNode name' nt') dispatch)
-- END Create Node
......
......@@ -5,7 +5,7 @@ import Data.Maybe (Maybe(..))
import Gargantext.Prelude
import Effect.Aff (Aff)
import Gargantext.Types as GT
import Gargantext.Sessions (Session, delete)
import Gargantext.Sessions (Session, delete, put_)
import Gargantext.Routes (SessionRoute(..))
import Gargantext.Types (NodeType(..))
import Gargantext.Components.Forest.Tree.Node.Action (Action(..))
......@@ -14,8 +14,20 @@ import Gargantext.Components.Forest.Tree.Node.Tools (submitButton, panel)
import Reactix.DOM.HTML as H
-- TODO Delete with asyncTaskWithType
deleteNode :: Session -> GT.ID -> Aff GT.ID
deleteNode session nodeId = delete session $ NodeAPI GT.Node (Just nodeId) ""
deleteNode :: Session -> NodeType -> GT.ID -> Aff GT.ID
deleteNode session nt nodeId = delete session $ NodeAPI GT.Node (Just nodeId) ""
{-
case nt of
NodePublic FolderPublic -> delete session $ NodeAPI GT.Node (Just nodeId) ""
NodePublic _ -> put_ session $ NodeAPI GT.Node (Just nodeId) "unpublish"
_ -> delete session $ NodeAPI GT.Node (Just nodeId) ""
-}
type ParentID = GT.ID
unpublishNode :: Session -> Maybe ParentID -> GT.ID -> Aff GT.ID
unpublishNode s p n = put_ s $ NodeAPI GT.Node p ("unpublish/" <> show n)
-- | Action : Delete
actionDelete :: NodeType -> (Action -> Aff Unit) -> R.Hooks R.Element
......@@ -29,7 +41,7 @@ actionDelete NodeUser _ = do
]
(H.div {} [])
actionDelete _ dispatch = do
actionDelete nt dispatch = do
pure $ panel [ H.div {style: {margin: "10px"}}
(map (\t -> H.p {} [H.text t])
[ "Are your sure you want to delete it ?"
......@@ -37,7 +49,7 @@ actionDelete _ dispatch = do
]
)
]
(submitButton DeleteNode dispatch)
(submitButton (DeleteNode nt) dispatch)
......
......@@ -5,31 +5,87 @@ import Data.Maybe (Maybe(..))
import Effect.Aff (Aff)
import Prelude (($))
import Reactix as R
import Gargantext.Components.Forest.Tree.Node.Action
import Gargantext.Components.Forest.Tree.Node.Action (Action)
import Gargantext.Components.Forest.Tree.Node.Action as Action
import Gargantext.Types as GT
import Gargantext.Types (ID)
import Gargantext.Routes as GR
import Gargantext.Sessions (Session, post)
import Gargantext.Components.Forest.Tree.Node.Tools as Tools
import Data.Maybe (Maybe(..))
import Data.Tuple.Nested ((/\))
import Effect.Aff (Aff)
import Gargantext.Components.Forest.Tree.Node.Action (Action)
import Gargantext.Components.Forest.Tree.Node.Action as Action
import Gargantext.Components.Forest.Tree.Node.Tools (submitButton, panel)
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree (subTreeView, SubTreeParamsIn)
import Gargantext.Prelude
import Gargantext.Routes (SessionRoute(..))
import Gargantext.Sessions (Session, put_)
import Gargantext.Types as GT
import Reactix as R
import Reactix.DOM.HTML as H
import Data.Argonaut as Argonaut
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Gargantext.Utils.Argonaut (genericSumDecodeJson, genericSumEncodeJson, genericEnumDecodeJson, genericEnumEncodeJson)
import Data.Maybe (Maybe(..))
import Gargantext.Prelude (class Eq, class Read, class Show)
------------------------------------------------------------------------
share :: Session -> ID -> ShareValue -> Aff (Array ID)
share session nodeId =
shareReq :: Session -> ID -> ShareNodeParams -> Aff ID
shareReq session nodeId =
post session $ GR.NodeAPI GT.Node (Just nodeId) "share"
shareAction :: String -> Action
shareAction username = ShareNode username
shareAction username = Action.ShareTeam username
------------------------------------------------------------------------
textInputBox :: Record Tools.TextInputBoxProps -> R.Element
textInputBox = Tools.textInputBox
------------------------------------------------------------------------
newtype ShareValue = ShareValue
{ text :: String }
data ShareNodeParams = ShareTeamParams { username :: String }
| SharePublicParams { node_id :: Int }
derive instance eqShareNodeParams :: Eq ShareNodeParams
derive instance genericShareNodeParams :: Generic ShareNodeParams _
instance showShareNodeParams :: Show ShareNodeParams where
show = genericShow
instance decodeJsonShareNodeParams :: Argonaut.DecodeJson ShareNodeParams where
decodeJson = genericSumDecodeJson
instance encodeJsonShareNodeParams :: Argonaut.EncodeJson ShareNodeParams where
encodeJson = genericSumEncodeJson
instance encodeJsonShareValue :: EncodeJson ShareValue where
encodeJson (ShareValue {text})
= "username" := text
~> jsonEmptyObject
------------------------------------------------------------------------
textInputBox :: Record Tools.TextInputBoxProps -> R.Element
textInputBox = Tools.textInputBox
shareNode :: Record SubTreeParamsIn -> R.Element
shareNode p = R.createElement shareNodeCpt p []
shareNodeCpt :: R.Component SubTreeParamsIn
shareNodeCpt = R.hooksComponent "G.C.F.T.N.A.M.shareNode" cpt
where
cpt p@{dispatch, subTreeParams, id, nodeType, session} _ = do
action@(valAction /\ setAction) :: R.State Action <- R.useState' (Action.SharePublic {params: Nothing})
let button = case valAction of
Action.SharePublic {params} -> case params of
Just val -> submitButton (Action.SharePublic {params: Just val}) dispatch
Nothing -> H.div {} []
_ -> H.div {} []
pure $ panel [ subTreeView { action
, dispatch
, id
, nodeType
, session
, subTreeParams
}
] button
......@@ -215,12 +215,12 @@ buttonClickCpt = R.hooksComponent "G.C.F.T.N.B.buttonClick" cpt
[]
]
where
{- -- This shows the Help of this button
undo = setNodePopup
$ const (node { action = Nothing })
-}
doToDo = setNodePopup $ const $ node { action = Just todo }
-- | Open the help indications if selected already
doToDo = setNodePopup $ const $ node { action = todo' }
where
todo' = case action == Just todo of
true -> Nothing
false -> Just todo
iconAStyle :: GT.NodeType -> NodeAction -> {
color :: String
......@@ -295,8 +295,13 @@ panelActionCpt = R.hooksComponent "G.C.F.T.N.B.panelAction" cpt
, id
, text: "username"
, isOpen
}
}
]
cpt {action : Publish {subTreeParams}, dispatch, id, nodeType, session } _ = do
pure $ Share.shareNode {dispatch, id, nodeType, session, subTreeParams}
cpt props@{action: SearchBox, id, session, dispatch, nodePopup} _ =
actionSearch session (Just id) dispatch nodePopup
......
......@@ -20,6 +20,7 @@ data NodeAction = Documentation NodeType
| Download | Upload | Refresh | Config
| Delete
| Share
| Publish { subTreeParams :: SubTreeParams }
| Add (Array NodeType)
| Merge { subTreeParams :: SubTreeParams }
| Move { subTreeParams :: SubTreeParams }
......@@ -41,6 +42,7 @@ instance eqNodeAction :: Eq NodeAction where
eq (Add x) (Add y) = x == y
eq (Merge x) (Merge y) = x == y
eq Config Config = true
eq (Publish x) (Publish y) = x == y
eq _ _ = false
instance showNodeAction :: Show NodeAction where
......@@ -57,7 +59,7 @@ instance showNodeAction :: Show NodeAction where
show (Link x) = "Link to " <> show x
show (Add xs) = foldl (\a b -> a <> show b) "Add " xs
show (Merge t) = "Merge with subtree" <> show t
show (Publish x) = "Publish" <> show x
glyphiconNodeAction :: NodeAction -> String
glyphiconNodeAction (Documentation _) = "question-circle"
......@@ -72,9 +74,9 @@ glyphiconNodeAction Refresh = "refresh"
glyphiconNodeAction Config = "wrench"
glyphiconNodeAction Share = "user-plus"
glyphiconNodeAction (Move _) = "share-square-o"
glyphiconNodeAction (Publish _) = fldr FolderPublic true