Commit fe4d4ab2 authored by Alexandre Delanoë's avatar Alexandre Delanoë

Merge branch 'dev-public' into dev

parents f0d9255c c81552e7
...@@ -76,6 +76,7 @@ import System.IO (FilePath) ...@@ -76,6 +76,7 @@ import System.IO (FilePath)
import qualified Data.ByteString.Lazy.Char8 as BL8 import qualified Data.ByteString.Lazy.Char8 as BL8
import qualified Data.Text.IO as T import qualified Data.Text.IO as T
import qualified Paths_gargantext as PG -- cabal magic build module import qualified Paths_gargantext as PG -- cabal magic build module
import qualified Gargantext.API.Public as Public
data Mode = Dev | Mock | Prod data Mode = Dev | Mock | Prod
...@@ -219,7 +220,7 @@ server :: forall env. EnvC env => env -> IO (Server API) ...@@ -219,7 +220,7 @@ server :: forall env. EnvC env => env -> IO (Server API)
server env = do server env = do
-- orchestrator <- scrapyOrchestrator env -- orchestrator <- scrapyOrchestrator env
pure $ schemaUiServer swaggerDoc pure $ schemaUiServer swaggerDoc
:<|> hoistServerWithContext :<|> hoistServerWithContext
(Proxy :: Proxy GargAPI) (Proxy :: Proxy GargAPI)
(Proxy :: Proxy AuthContext) (Proxy :: Proxy AuthContext)
transform transform
...@@ -240,6 +241,8 @@ serverGargAPI -- orchestrator ...@@ -240,6 +241,8 @@ serverGargAPI -- orchestrator
= auth = auth
:<|> gargVersion :<|> gargVersion
:<|> serverPrivateGargAPI :<|> serverPrivateGargAPI
:<|> Public.api
-- :<|> orchestrator -- :<|> orchestrator
where where
......
...@@ -201,8 +201,7 @@ withAccessM uId (PathNodeNode cId docId) m = do ...@@ -201,8 +201,7 @@ withAccessM uId (PathNodeNode cId docId) m = do
withAccess :: forall env err m api. withAccess :: forall env err m api.
(GargServerC env err m, HasServer api '[]) => (GargServerC env err m, HasServer api '[]) =>
Proxy api -> Proxy m -> Proxy api -> Proxy m -> UserId -> PathId ->
UserId -> PathId ->
ServerT api m -> ServerT api m ServerT api m -> ServerT api m
withAccess p _ uId id = hoistServer p f withAccess p _ uId id = hoistServer p f
where where
......
...@@ -46,7 +46,6 @@ import Gargantext.Core.Types (NodeTableResult) ...@@ -46,7 +46,6 @@ import Gargantext.Core.Types (NodeTableResult)
import Gargantext.Core.Types.Individu (User(..)) import Gargantext.Core.Types.Individu (User(..))
import Gargantext.Core.Types.Main (Tree, NodeTree) import Gargantext.Core.Types.Main (Tree, NodeTree)
import Gargantext.Database.Action.Flow.Pairing (pairing) import Gargantext.Database.Action.Flow.Pairing (pairing)
import Gargantext.Database.Action.Share (unPublish)
import Gargantext.Database.Admin.Types.Node import Gargantext.Database.Admin.Types.Node
import Gargantext.Database.Prelude -- (Cmd, CmdM) import Gargantext.Database.Prelude -- (Cmd, CmdM)
import Gargantext.Database.Query.Facet (FacetDoc, OrderBy(..)) import Gargantext.Database.Query.Facet (FacetDoc, OrderBy(..))
...@@ -145,7 +144,7 @@ type NodeAPI a = Get '[JSON] (Node a) ...@@ -145,7 +144,7 @@ type NodeAPI a = Get '[JSON] (Node a)
:<|> "phylo" :> PhyloAPI :<|> "phylo" :> PhyloAPI
-- :<|> "add" :> NodeAddAPI -- :<|> "add" :> NodeAddAPI
:<|> "move" :> MoveAPI :<|> "move" :> MoveAPI
:<|> "unpublish" :> Put '[JSON] Int :<|> "unpublish" :> Share.Unpublish
-- TODO-ACCESS: check userId CanRenameNode nodeId -- TODO-ACCESS: check userId CanRenameNode nodeId
-- TODO-EVENTS: NodeRenamed RenameNode or re-use some more general NodeEdited... -- TODO-EVENTS: NodeRenamed RenameNode or re-use some more general NodeEdited...
...@@ -221,7 +220,7 @@ nodeAPI p uId id' = withAccess (Proxy :: Proxy (NodeAPI a)) Proxy uId (PathNode ...@@ -221,7 +220,7 @@ nodeAPI p uId id' = withAccess (Proxy :: Proxy (NodeAPI a)) Proxy uId (PathNode
:<|> moveNode (RootId $ NodeId uId) id' :<|> moveNode (RootId $ NodeId uId) id'
-- :<|> nodeAddAPI id' -- :<|> nodeAddAPI id'
-- :<|> postUpload id' -- :<|> postUpload id'
:<|> unPublish (RootId $ NodeId uId) id' :<|> Share.unPublish id'
------------------------------------------------------------------------ ------------------------------------------------------------------------
......
...@@ -20,8 +20,10 @@ import Data.Aeson ...@@ -20,8 +20,10 @@ import Data.Aeson
import Data.Swagger import Data.Swagger
import Data.Text (Text) import Data.Text (Text)
import GHC.Generics (Generic) import GHC.Generics (Generic)
import Gargantext.API.Prelude
import Gargantext.Core.Types.Individu (User(..)) import Gargantext.Core.Types.Individu (User(..))
import Gargantext.Database.Action.Share (shareNodeWith) import Gargantext.Database.Action.Share (ShareNodeWith(..))
import Gargantext.Database.Action.Share as DB (shareNodeWith, unPublish)
import Gargantext.Database.Admin.Types.Node import Gargantext.Database.Admin.Types.Node
import Gargantext.Database.Prelude import Gargantext.Database.Prelude
import Gargantext.Database.Query.Table.Node.Error (HasNodeError(..)) import Gargantext.Database.Query.Table.Node.Error (HasNodeError(..))
...@@ -31,37 +33,40 @@ import Test.QuickCheck (elements) ...@@ -31,37 +33,40 @@ import Test.QuickCheck (elements)
import Test.QuickCheck.Arbitrary import Test.QuickCheck.Arbitrary
------------------------------------------------------------------------ ------------------------------------------------------------------------
data ShareNode = ShareTeam { username :: Text } data ShareNodeParams = ShareTeamParams { username :: Text }
| SharePublic { rights :: Text} | SharePublicParams { node_id :: NodeId}
deriving (Generic) deriving (Generic)
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- TODO unPrefix "pn_" FromJSON, ToJSON, ToSchema, adapt frontend. -- TODO unPrefix "pn_" FromJSON, ToJSON, ToSchema, adapt frontend.
instance FromJSON ShareNode where instance FromJSON ShareNodeParams where
parseJSON = genericParseJSON (defaultOptions { sumEncoding = ObjectWithSingleField }) parseJSON = genericParseJSON (defaultOptions { sumEncoding = ObjectWithSingleField })
instance ToJSON ShareNode where instance ToJSON ShareNodeParams where
toJSON = genericToJSON (defaultOptions { sumEncoding = ObjectWithSingleField }) toJSON = genericToJSON (defaultOptions { sumEncoding = ObjectWithSingleField })
instance ToSchema ShareNode instance ToSchema ShareNodeParams
instance Arbitrary ShareNode where instance Arbitrary ShareNodeParams where
arbitrary = elements [ ShareTeam "user1" arbitrary = elements [ ShareTeamParams "user1"
, SharePublic "public" , SharePublicParams (NodeId 1)
] ]
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- TODO permission -- TODO permission
api :: HasNodeError err api :: HasNodeError err
=> NodeId => NodeId
-> ShareNode -> ShareNodeParams
-> Cmd err Int -> Cmd err Int
api nId (ShareTeam user) = api nId (ShareTeamParams user) =
fromIntegral <$> shareNodeWith nId NodeFolderShared (UserName user) fromIntegral <$> DB.shareNodeWith (ShareNodeWith_User NodeFolderShared (UserName user)) nId
api nId (SharePublic _rights) = api nId2 (SharePublicParams nId1) =
fromIntegral <$> shareNodeWith nId NodeFolderPublic UserPublic fromIntegral <$> DB.shareNodeWith (ShareNodeWith_Node NodeFolderPublic nId1) nId2
------------------------------------------------------------------------ ------------------------------------------------------------------------
type API = Summary " Share Node with username" type API = Summary " Share Node with username"
:> ReqBody '[JSON] ShareNode :> ReqBody '[JSON] ShareNodeParams
:> Post '[JSON] Int :> Post '[JSON] Int
------------------------------------------------------------------------
type Unpublish = Summary " Unpublish Node"
:> Capture "node_id" NodeId
:> Put '[JSON] Int
unPublish :: NodeId -> GargServer Unpublish
unPublish n = DB.unPublish n
{-|
Module : Gargantext.API.Public
Description :
Copyright : (c) CNRS, 2017-Present
License : AGPL + CECILL v3
Maintainer : team@gargantext.org
Stability : experimental
Portability : POSIX
-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Gargantext.API.Public
where
import Control.Lens ((^?), (^.), _Just)
import Data.Maybe (maybe, catMaybes)
import Data.Tuple (snd)
import Data.Text (Text)
import Data.List (replicate, null)
import Data.Aeson
import Data.Swagger
import GHC.Generics (Generic)
import Gargantext.Database.Query.Table.Node.Error (HasNodeError(..))
import Gargantext.Database.Prelude
import Gargantext.Database.Admin.Types.Node
import Gargantext.Database.Query.Table.NodeNode (selectPublicNodes)
import Gargantext.Core.Utils.DateUtils (utc2year)
import Gargantext.Database.Admin.Types.Hyperdata
import Gargantext.Database.Schema.Node -- (NodePoly(..))
import Gargantext.Prelude
import Servant
import Test.QuickCheck (elements)
import Test.QuickCheck.Arbitrary
import qualified Data.Map as Map
------------------------------------------------------------------------
type API = Summary " Public API"
:> Get '[JSON] [PublicData]
api :: HasNodeError err
=> Cmd err [PublicData]
api = catMaybes <$> map toPublicData <$> filterPublicDatas <$> selectPublic
selectPublic :: HasNodeError err
=> Cmd err [( Node HyperdataFolder, Maybe Int)]
selectPublic = selectPublicNodes
-- | For tests only
-- pure $ replicate 6 defaultPublicData
filterPublicDatas :: [( Node HyperdataFolder, Maybe Int)] -> [(Node HyperdataFolder, [NodeId])]
filterPublicDatas datas = map (\(n,mi) -> let mi' = NodeId <$> mi in
( _node_id n, (n, maybe [] (:[]) mi' ))
) datas
& Map.fromListWith (\(n1,i1) (_n2,i2) -> (n1, i1 <> i2))
& Map.filter (not . null . snd)
& Map.elems
toPublicData :: (Node HyperdataFolder, [NodeId]) -> Maybe PublicData
toPublicData (n , _mn) = PublicData <$> (hd ^? (_Just . hf_data . cf_title))
<*> (hd ^? (_Just . hf_data . cf_desc))
<*> Just "images/Gargantextuel-212x300.jpg"
<*> Just "https://.."
<*> Just (cs $ show $ utc2year (n^.node_date))
<*> (hd ^? (_Just . hf_data . cf_query))
<*> (hd ^? (_Just . hf_data . cf_authors))
where
hd = head
$ filter (\(HyperdataField cd _ _) -> cd == JSON)
$ n^. (node_hyperdata . hc_fields)
data PublicData = PublicData
{ title :: Text
, abstract :: Text
, img :: Text
, url :: Text
, date :: Text
, database :: Text
, author :: Text
} | NoData { nodata:: Text}
deriving (Generic)
instance FromJSON PublicData where
parseJSON = genericParseJSON (defaultOptions { sumEncoding = ObjectWithSingleField })
instance ToJSON PublicData where
toJSON = genericToJSON (defaultOptions { sumEncoding = ObjectWithSingleField })
instance ToSchema PublicData
instance Arbitrary PublicData where
arbitrary = elements
$ replicate 6 defaultPublicData
defaultPublicData :: PublicData
defaultPublicData =
PublicData "Title"
(foldl (<>) "" $ replicate 100 "abstract ")
"images/Gargantextuel-212x300.jpg"
"https://.."
"YY/MM/DD"
"database"
"Author"
...@@ -24,34 +24,34 @@ Portability : POSIX ...@@ -24,34 +24,34 @@ Portability : POSIX
module Gargantext.API.Routes module Gargantext.API.Routes
where where
--------------------------------------------------------------------- ---------------------------------------------------------------------
import Control.Concurrent (threadDelay) import Control.Concurrent (threadDelay)
import Data.Text (Text) import Data.Text (Text)
import Data.Validity import Data.Validity
import Servant
import Servant.Auth as SA
import Servant.Auth.Swagger ()
import Servant.Job.Async
import Servant.Swagger.UI
import Gargantext.API.Admin.Auth (AuthRequest, AuthResponse, AuthenticatedUser(..), withAccess, PathId(..)) import Gargantext.API.Admin.Auth (AuthRequest, AuthResponse, AuthenticatedUser(..), withAccess, PathId(..))
import Gargantext.API.Admin.FrontEnd (FrontEndAPI) import Gargantext.API.Admin.FrontEnd (FrontEndAPI)
import Gargantext.API.Prelude
import Gargantext.API.Count (CountAPI, count, Query) import Gargantext.API.Count (CountAPI, count, Query)
import Gargantext.API.Ngrams (TableNgramsApi, apiNgramsTableDoc) import Gargantext.API.Ngrams (TableNgramsApi, apiNgramsTableDoc)
import Gargantext.API.Node import Gargantext.API.Node
import Gargantext.API.Prelude
import Gargantext.API.Search (SearchPairsAPI, searchPairs) import Gargantext.API.Search (SearchPairsAPI, searchPairs)
import Gargantext.Core.Types.Individu (User(..)) import Gargantext.Core.Types.Individu (User(..))
import Gargantext.Database.Query.Table.Node.Contact (HyperdataContact)
import Gargantext.Database.Admin.Types.Hyperdata import Gargantext.Database.Admin.Types.Hyperdata
import Gargantext.Database.Admin.Types.Node import Gargantext.Database.Admin.Types.Node
import Gargantext.Database.Admin.Types.Node (NodeId, CorpusId, AnnuaireId) import Gargantext.Database.Admin.Types.Node (NodeId, CorpusId, AnnuaireId)
import Gargantext.Database.Query.Table.Node.Contact (HyperdataContact)
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Viz.Graph.API import Gargantext.Viz.Graph.API
import Servant
import Servant.Auth as SA
import Servant.Auth.Swagger ()
import Servant.Job.Async
import Servant.Swagger.UI
import qualified Gargantext.API.Ngrams.List as List
import qualified Gargantext.API.Node.Corpus.Annuaire as Annuaire import qualified Gargantext.API.Node.Corpus.Annuaire as Annuaire
import qualified Gargantext.API.Node.Corpus.Export as Export import qualified Gargantext.API.Node.Corpus.Export as Export
import qualified Gargantext.API.Node.Corpus.New as New import qualified Gargantext.API.Node.Corpus.New as New
import qualified Gargantext.API.Ngrams.List as List import qualified Gargantext.API.Public as Public
type GargAPI = "api" :> Summary "API " :> GargAPIVersion type GargAPI = "api" :> Summary "API " :> GargAPIVersion
...@@ -75,6 +75,7 @@ type GargAPI' = ...@@ -75,6 +75,7 @@ type GargAPI' =
-- TODO-ACCESS here we want to request a particular header for -- TODO-ACCESS here we want to request a particular header for
-- auth and capabilities. -- auth and capabilities.
:<|> GargPrivateAPI :<|> GargPrivateAPI
:<|> "public" :> Public.API
type GargPrivateAPI = SA.Auth '[SA.JWT, SA.Cookie] AuthenticatedUser type GargPrivateAPI = SA.Auth '[SA.JWT, SA.Cookie] AuthenticatedUser
......
...@@ -101,7 +101,10 @@ mkNodeWithParent NodeFrameWrite i u n = ...@@ -101,7 +101,10 @@ mkNodeWithParent NodeFrameWrite i u n =
mkNodeWithParent NodeFrameCalc i u n = mkNodeWithParent NodeFrameCalc i u n =
mkNodeWithParent_ConfigureHyperdata NodeFrameCalc i u n mkNodeWithParent_ConfigureHyperdata NodeFrameCalc i u n
mkNodeWithParent _ _ _ _ = nodeError NotImplYet mkNodeWithParent n (Just i) uId name =
insertNodesWithParentR (Just i) [node NodeDashboard name (hasDefaultData n) Nothing uId]
-- mkNodeWithParent _ _ _ _ = nodeError NotImplYet
-- | Sugar to create a node, get his NodeId and update his Hyperdata after -- | Sugar to create a node, get his NodeId and update his Hyperdata after
......
...@@ -9,72 +9,87 @@ Portability : POSIX ...@@ -9,72 +9,87 @@ Portability : POSIX
-} -}
module Gargantext.Database.Action.Share module Gargantext.Database.Action.Share
where where
import Control.Lens (view) import Control.Lens (view)
import Gargantext.Core.Types.Individu (User(..)) import Gargantext.Core.Types.Individu (User(..))
import Gargantext.Database.Action.Flow.Utils (getUserId) import Gargantext.Database.Action.Flow.Utils (getUserId)
import Gargantext.Database.Admin.Config (hasNodeType) import Gargantext.Database.Admin.Config (hasNodeType, isInNodeTypes)
import Gargantext.Database.Admin.Types.Hyperdata (HyperdataAny(..)) import Gargantext.Database.Admin.Types.Hyperdata (HyperdataAny(..))
import Gargantext.Database.Admin.Types.Node (NodeId) import Gargantext.Database.Admin.Types.Node (NodeId)
import Gargantext.Database.Admin.Types.Node -- (NodeType(..)) import Gargantext.Database.Admin.Types.Node -- (NodeType(..))
import Gargantext.Database.Prelude (Cmd) import Gargantext.Database.Prelude (Cmd)
import Gargantext.Database.Query.Table.Node (getNode, getNodesWith) import Gargantext.Database.Query.Table.Node (getNode, getNodesWith)
import Gargantext.Database.Query.Table.Node.Error (HasNodeError) import Gargantext.Database.Query.Table.Node.Error (HasNodeError, msg)
import Gargantext.Database.Query.Table.NodeNode (insertNodeNode, deleteNodeNode) import Gargantext.Database.Query.Table.NodeNode (insertNodeNode, deleteNodeNode)
import Gargantext.Database.Query.Tree.Root (getRootId) import Gargantext.Database.Query.Tree.Root (getRootId)
import Gargantext.Database.Schema.Node import Gargantext.Database.Schema.Node
import Gargantext.Database.Schema.NodeNode (NodeNodePoly(..)) import Gargantext.Database.Schema.NodeNode (NodeNodePoly(..))
import Gargantext.Prelude import Gargantext.Prelude
-- | TODO move in Config of Gargantext
publicNodeTypes :: [NodeType]
publicNodeTypes = [NodeDashboard, NodeGraph, NodePhylo]
------------------------------------------------------------------------
data ShareNodeWith = ShareNodeWith_User { snwu_nodetype :: NodeType
, snwu_user :: User }
| ShareNodeWith_Node { snwn_nodetype :: NodeType
, snwn_node_id :: NodeId
}
------------------------------------------------------------------------ ------------------------------------------------------------------------
shareNodeWith :: HasNodeError err shareNodeWith :: HasNodeError err
=> NodeId => ShareNodeWith
-> NodeType -> NodeId
-> User
-> Cmd err Int64 -> Cmd err Int64
shareNodeWith n nt u = do shareNodeWith (ShareNodeWith_User NodeFolderShared u) n = do
nodeToCheck <- getNode n nodeToCheck <- getNode n
case nt of userIdCheck <- getUserId u
NodeFolderShared -> do if not (hasNodeType nodeToCheck NodeTeam)
userIdCheck <- getUserId u then msg "Can share node Team only"
if not (hasNodeType nodeToCheck NodeTeam) else
then panic "Can share node Team only" if (view node_userId nodeToCheck == userIdCheck)
else then msg "Can share to others only"
if (view node_userId nodeToCheck == userIdCheck) else do
then panic "Can share to others only" folderSharedId <- getFolderId u NodeFolderShared
else do insertNodeNode [NodeNode folderSharedId n Nothing Nothing]
folderSharedId <- getFolderId u NodeFolderShared
insertNodeNode [NodeNode folderSharedId n Nothing Nothing] shareNodeWith (ShareNodeWith_Node NodeFolderPublic nId) n = do
nodeToCheck <- getNode n
NodeFolderPublic -> if not (hasNodeType nodeToCheck NodeGraph) if not (isInNodeTypes nodeToCheck publicNodeTypes)
then panic "Can share node graph only" then msg $ "Can share this nodesTypes only: " <> (cs $ show publicNodeTypes)
else do else do
folderId <- getFolderId (UserDBId $ view node_userId nodeToCheck) NodeFolderPublic folderToCheck <- getNode nId
insertNodeNode [NodeNode folderId n Nothing Nothing] if hasNodeType folderToCheck NodeFolderPublic
then insertNodeNode [NodeNode nId n Nothing Nothing]
_ -> panic "shareNodeWith not implemented with this NodeType" else msg "Can share NodeWith NodeFolderPublic only"
shareNodeWith _ _ = msg "shareNodeWith not implemented for this NodeType"
------------------------------------------------------------------------ ------------------------------------------------------------------------
getFolderId :: User -> NodeType -> Cmd err NodeId getFolderId :: HasNodeError err => User -> NodeType -> Cmd err NodeId
getFolderId u nt = do getFolderId u nt = do
rootId <- getRootId u rootId <- getRootId u
s <- getNodesWith rootId HyperdataAny (Just nt) Nothing Nothing s <- getNodesWith rootId HyperdataAny (Just nt) Nothing Nothing
case head s of case head s of
Nothing -> panic "No folder shared found" Nothing -> msg "No folder shared found"
Just f -> pure (_node_id f) Just f -> pure (_node_id f)
------------------------------------------------------------------------ ------------------------------------------------------------------------
type TeamId = NodeId type TeamId = NodeId
delFolderTeam :: User -> TeamId -> Cmd err Int delFolderTeam :: HasNodeError err => User -> TeamId -> Cmd err Int
delFolderTeam u nId = do delFolderTeam u nId = do
folderSharedId <- getFolderId u NodeFolderShared folderSharedId <- getFolderId u NodeFolderShared
deleteNodeNode folderSharedId nId deleteNodeNode folderSharedId nId
unPublish :: User -> NodeId -> Cmd err Int
unPublish u nId = do unPublish :: HasNodeError err
folderId <- getFolderId u NodeFolderPublic => ParentId -> NodeId
deleteNodeNode folderId nId -> Cmd err Int
unPublish p n = deleteNodeNode p n
...@@ -87,6 +87,8 @@ nodeTypeId n = ...@@ -87,6 +87,8 @@ nodeTypeId n =
hasNodeType :: forall a. Node a -> NodeType -> Bool hasNodeType :: forall a. Node a -> NodeType -> Bool
hasNodeType n nt = (view node_typename n) == (nodeTypeId nt) hasNodeType n nt = (view node_typename n) == (nodeTypeId nt)
isInNodeTypes :: forall a. Node a -> [NodeType] -> Bool
isInNodeTypes n ts = elem (view node_typename n) (map nodeTypeId ts)
-- | Nodes are typed in the database according to a specific ID -- | Nodes are typed in the database according to a specific ID
-- --
......
...@@ -35,7 +35,7 @@ import Gargantext.Viz.Types (Histo(..)) ...@@ -35,7 +35,7 @@ import Gargantext.Viz.Types (Histo(..))
data CodeType = JSON | Markdown | Haskell data CodeType = JSON | Markdown | Haskell
deriving (Generic) deriving (Generic, Eq)
instance ToJSON CodeType instance ToJSON CodeType
instance FromJSON CodeType instance FromJSON CodeType
instance ToSchema CodeType instance ToSchema CodeType
...@@ -57,6 +57,12 @@ data CorpusField = MarkdownField { _cf_text :: !Text } ...@@ -57,6 +57,12 @@ data CorpusField = MarkdownField { _cf_text :: !Text }
| HaskellField { _cf_haskell :: !Text } | HaskellField { _cf_haskell :: !Text }
deriving (Generic) deriving (Generic)
isField :: CodeType -> CorpusField -> Bool
isField Markdown (MarkdownField _) = True
isField JSON (JsonField _ _ _ _) = True
isField Haskell (HaskellField _) = True
isField _ _ = False
$(deriveJSON (unPrefix "_cf_") ''CorpusField) $(deriveJSON (unPrefix "_cf_") ''CorpusField)
$(makeLenses ''CorpusField) $(makeLenses ''CorpusField)
...@@ -194,6 +200,7 @@ $(makeLenses ''HyperdataCorpus) ...@@ -194,6 +200,7 @@ $(makeLenses ''HyperdataCorpus)
instance Hyperdata HyperdataCorpus instance Hyperdata HyperdataCorpus
type HyperdataFolder = HyperdataCorpus
------------------------------------------------------------------------ ------------------------------------------------------------------------
data HyperdataFrame = data HyperdataFrame =
HyperdataFrame { base :: !Text HyperdataFrame { base :: !Text
...@@ -296,38 +303,25 @@ $(deriveJSON (unPrefix "hyperdataResource_") ''HyperdataResource) ...@@ -296,38 +303,25 @@ $(deriveJSON (unPrefix "hyperdataResource_") ''HyperdataResource)
instance Hyperdata HyperdataResource instance Hyperdata HyperdataResource
------------------------------------------------------------------------ ------------------------------------------------------------------------
data HyperdataDashboard = HyperdataDashboard { hyperdataDashboard_preferences :: !(Maybe Text)
, hyperdataDashboard_charts :: ![Chart]
} deriving (Show, Generic)
$(deriveJSON (unPrefix "hyperdataDashboard_") ''HyperdataDashboard)
instance Hyperdata HyperdataDashboard
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- TODO add the Graph Structure here -- TODO add the Graph Structure here
data HyperdataPhylo = HyperdataPhylo { hyperdataPhylo_preferences :: !(Maybe Text)
, hyperdataPhylo_data :: !(Maybe Phylo)
} deriving (Show, Generic)
$(deriveJSON (unPrefix "hyperdataPhylo_") ''HyperdataPhylo)
instance Hyperdata HyperdataPhylo
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | TODO FEATURE: Notebook saved in the node
data HyperdataNotebook = HyperdataNotebook { hyperdataNotebook_preferences :: !(Maybe Text)
} deriving (Show, Generic)
$(deriveJSON (unPrefix "hyperdataNotebook_") ''HyperdataNotebook)
instance Hyperdata HyperdataNotebook
-- | TODO CLEAN -- | TODO CLEAN
-- | TODO FEATURE: Notebook saved in the node
data HyperData = HyperdataTexts { hd_preferences :: !(Maybe Text)} data HyperData = HyperdataTexts { hd_preferences :: !(Maybe Text)}
| HyperdataList' { hd_preferences :: !(Maybe Text)} | HyperdataList' { hd_preferences :: !(Maybe Text)}
| HyperdataDashboard { hd_preferences :: !(Maybe Text)
, hd_charts :: ![Chart]
}
| HyperdataNotebook { hd_preferences :: !(Maybe Text)}
| HyperdataPhylo { hd_preferences :: !(Maybe Text)
, hd_data :: !(Maybe Phylo)
}
deriving (Show, Generic) deriving (Show, Generic)
$(deriveJSON (unPrefix "hd_") ''HyperData) $(deriveJSON (unPrefix "hd_") ''HyperData)
instance Hyperdata HyperData instance Hyperdata HyperData
------------------------------------------------------------------------ ------------------------------------------------------------------------
...@@ -395,10 +389,6 @@ instance FromField HyperdataListModel ...@@ -395,10 +389,6 @@ instance FromField HyperdataListModel
where where
fromField = fromField' fromField = fromField'
instance FromField HyperdataPhylo
where
fromField = fromField'
instance FromField HyperdataAnnuaire instance FromField HyperdataAnnuaire
where where
fromField = fromField' fromField = fromField'
...@@ -437,10 +427,6 @@ instance QueryRunnerColumnDefault PGJsonb HyperdataListModel ...@@ -437,10 +427,6 @@ instance QueryRunnerColumnDefault PGJsonb HyperdataListModel
where where
queryRunnerColumnDefault = fieldQueryRunnerColumn queryRunnerColumnDefault = fieldQueryRunnerColumn
instance QueryRunnerColumnDefault PGJsonb HyperdataPhylo
where
queryRunnerColumnDefault = fieldQueryRunnerColumn
instance QueryRunnerColumnDefault PGJsonb HyperdataAnnuaire instance QueryRunnerColumnDefault PGJsonb HyperdataAnnuaire
where where
queryRunnerColumnDefault = fieldQueryRunnerColumn queryRunnerColumnDefault = fieldQueryRunnerColumn
...@@ -233,10 +233,6 @@ instance Arbitrary Resource where ...@@ -233,10 +233,6 @@ instance Arbitrary Resource where
instance ToSchema Resource where instance ToSchema Resource where
declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "resource_") declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "resource_")
------------------------------------------------------------------------
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | Then a Node can be either a Folder or a Corpus or a Document -- | Then a Node can be either a Folder or a Corpus or a Document
data NodeType = NodeUser data NodeType = NodeUser
...@@ -280,6 +276,8 @@ instance ToSchema NodeType ...@@ -280,6 +276,8 @@ instance ToSchema NodeType
instance Arbitrary NodeType where instance Arbitrary NodeType where
arbitrary = elements allNodeTypes arbitrary = elements allNodeTypes
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- Instances -- Instances
------------------------------------------------------------------------ ------------------------------------------------------------------------
...@@ -311,5 +309,3 @@ instance QueryRunnerColumnDefault (Nullable PGInt4) NodeId ...@@ -311,5 +309,3 @@ instance QueryRunnerColumnDefault (Nullable PGInt4) NodeId
queryRunnerColumnDefault = fieldQueryRunnerColumn queryRunnerColumnDefault = fieldQueryRunnerColumn
...@@ -228,17 +228,20 @@ class HasDefault a where ...@@ -228,17 +228,20 @@ class HasDefault a where
instance HasDefault NodeType where instance HasDefault NodeType where
hasDefaultData nt = case nt of hasDefaultData nt = case nt of
NodeTexts -> HyperdataTexts (Just "Preferences") NodeTexts -> HyperdataTexts (Just "Preferences")
NodeList -> HyperdataList' (Just "Preferences") NodeList -> HyperdataList' (Just "Preferences")
NodeListCooc -> HyperdataList' (Just "Preferences") NodeListCooc -> HyperdataList' (Just "Preferences")
_ -> undefined -- NodeFolder -> defaultFolder
NodeDashboard -> arbitraryDashboard
_ -> panic "HasDefaultData undefined"
--NodeAnnuaire -> HyperdataAnnuaire (Just "Title") (Just "Description") --NodeAnnuaire -> HyperdataAnnuaire (Just "Title") (Just "Description")
hasDefaultName nt = case nt of hasDefaultName nt = case nt of
NodeTexts -> "Texts" NodeTexts -> "Texts"
NodeList -> "Lists" NodeList -> "Lists"
NodeListCooc -> "Cooc" NodeListCooc -> "Cooc"
_ -> undefined NodePhylo -> "Phylo"
_ -> panic "HasDefaultName undefined"
------------------------------------------------------------------------ ------------------------------------------------------------------------
nodeDefault :: NodeType -> ParentId -> UserId -> NodeWrite nodeDefault :: NodeType -> ParentId -> UserId -> NodeWrite
...@@ -277,17 +280,7 @@ insertGraph :: ParentId -> UserId -> HyperdataGraph -> Cmd err [GraphId] ...@@ -277,17 +280,7 @@ insertGraph :: ParentId -> UserId -> HyperdataGraph -> Cmd err [GraphId]
insertGraph p u h = insertNodesR [nodeGraphW Nothing (Just h) p u] insertGraph p u h = insertNodesR [nodeGraphW Nothing (Just h) p u]
------------------------------------------------------------------------ ------------------------------------------------------------------------
arbitraryPhylo :: HyperdataPhylo arbitraryDashboard :: HyperData
arbitraryPhylo = HyperdataPhylo Nothing Nothing
nodePhyloW :: Maybe Name -> Maybe HyperdataPhylo -> ParentId -> UserId -> NodeWrite
nodePhyloW maybeName maybePhylo pId = node NodePhylo name graph (Just pId)
where
name = maybe "Phylo" identity maybeName
graph = maybe arbitraryPhylo identity maybePhylo
------------------------------------------------------------------------
arbitraryDashboard :: HyperdataDashboard
arbitraryDashboard = HyperdataDashboard (Just "Preferences") [] arbitraryDashboard = HyperdataDashboard (Just "Preferences") []
------------------------------------------------------------------------ ------------------------------------------------------------------------
...@@ -446,16 +439,12 @@ mkNode nt p u = insertNodesR [nodeDefault nt p u] ...@@ -446,16 +439,12 @@ mkNode nt p u = insertNodesR [nodeDefault nt p u]
mkDashboard :: ParentId -> UserId -> Cmd err [NodeId] mkDashboard :: ParentId -> UserId -> Cmd err [NodeId]
mkDashboard p u = insertNodesR [nodeDashboardW Nothing Nothing p u] mkDashboard p u = insertNodesR [nodeDashboardW Nothing Nothing p u]
where where
nodeDashboardW :: Maybe Name -> Maybe HyperdataDashboard -> ParentId -> UserId -> NodeWrite nodeDashboardW :: Maybe Name -> Maybe HyperData -> ParentId -> UserId -> NodeWrite
nodeDashboardW maybeName maybeDashboard pId = node NodeDashboard name dashboard (Just pId) nodeDashboardW maybeName maybeDashboard pId = node NodeDashboard name dashboard (Just pId)
where where
name = maybe "Board" identity maybeName name = maybe "Board" identity maybeName
dashboard = maybe arbitraryDashboard identity maybeDashboard dashboard = maybe arbitraryDashboard identity maybeDashboard
mkPhylo :: ParentId -> UserId -> Cmd err [NodeId]
mkPhylo p u = insertNodesR [nodePhyloW Nothing Nothing p u]
getListsWithParentId :: NodeId -> Cmd err [Node HyperdataList] getListsWithParentId :: NodeId -> Cmd err [Node HyperdataList]
getListsWithParentId n = runOpaQuery $ selectNodesWith' n (Just NodeList) getListsWithParentId n = runOpaQuery $ selectNodesWith' n (Just NodeList)
......
...@@ -19,6 +19,7 @@ Portability : POSIX ...@@ -19,6 +19,7 @@ Portability : POSIX
module Gargantext.Database.Query.Table.Node.Error where module Gargantext.Database.Query.Table.Node.Error where
import Data.Text (Text)
import Gargantext.Database.Admin.Types.Node (NodeId) import Gargantext.Database.Admin.Types.Node (NodeId)
import Control.Lens (Prism', (#), (^?)) import Control.Lens (Prism', (#), (^?))
import Control.Monad.Error.Class (MonadError(..)) import Control.Monad.Error.Class (MonadError(..))
...@@ -39,6 +40,7 @@ data NodeError = NoListFound ...@@ -39,6 +40,7 @@ data NodeError = NoListFound
| ManyNodeUsers | ManyNodeUsers
| DoesNotExist NodeId | DoesNotExist NodeId
| NeedsConfiguration | NeedsConfiguration
| NodeError Text
instance Show NodeError instance Show NodeError
where where
...@@ -56,10 +58,16 @@ instance Show NodeError ...@@ -56,10 +58,16 @@ instance Show NodeError
show ManyNodeUsers = "Many userNode/user" show ManyNodeUsers = "Many userNode/user"
show (DoesNotExist n) = "Node does not exist" <> show n show (DoesNotExist n) = "Node does not exist" <> show n
show NeedsConfiguration = "Needs configuration" show NeedsConfiguration = "Needs configuration"
show (NodeError e) = "NodeError: " <> cs e
class HasNodeError e where class HasNodeError e where
_NodeError :: Prism' e NodeError _NodeError :: Prism' e NodeError
msg :: ( MonadError e m
, HasNodeError e)
=> Text -> m a
msg x = nodeError (NodeError x)
nodeError :: ( MonadError e m nodeError :: ( MonadError e m
, HasNodeError e) , HasNodeError e)
=> NodeError -> m a => NodeError -> m a
......
...@@ -28,6 +28,7 @@ module Gargantext.Database.Query.Table.NodeNode ...@@ -28,6 +28,7 @@ module Gargantext.Database.Query.Table.NodeNode
, getNodeNode , getNodeNode
, insertNodeNode , insertNodeNode
, deleteNodeNode , deleteNodeNode
, selectPublicNodes
) )
where where
...@@ -153,3 +154,21 @@ joinInCorpus = leftJoin queryNodeTable queryNodeNodeTable cond ...@@ -153,3 +154,21 @@ joinInCorpus = leftJoin queryNodeTable queryNodeNodeTable cond
cond :: (NodeRead, NodeNodeRead) -> Column PGBool cond :: (NodeRead, NodeNodeRead) -> Column PGBool
cond (n, nn) = nn^.nn_node2_id .== (view node_id n) cond (n, nn) = nn^.nn_node2_id .== (view node_id n)
joinOn1 :: O.Query (NodeRead, NodeNodeReadNull)
joinOn1 = leftJoin queryNodeTable queryNodeNodeTable cond
where
cond :: (NodeRead, NodeNodeRead) -> Column PGBool
cond (n, nn) = nn^.nn_node1_id .== n^.node_id
------------------------------------------------------------------------
selectPublicNodes :: (Hyperdata a, QueryRunnerColumnDefault PGJsonb a)
=> Cmd err [(Node a, Maybe Int)]
selectPublicNodes = runOpaQuery (queryWithType NodeFolderPublic)
queryWithType :: NodeType -> O.Query (NodeRead, Column (Nullable PGInt4))
queryWithType nt = proc () -> do
(n, nn) <- joinOn1 -< ()
restrict -< n^.node_typename .== (pgInt4 $ nodeTypeId nt)
returnA -< (n, nn^.nn_node2_id)
...@@ -40,7 +40,7 @@ import Data.Text (Text) ...@@ -40,7 +40,7 @@ import Data.Text (Text)
import Database.PostgreSQL.Simple import Database.PostgreSQL.Simple
import Database.PostgreSQL.Simple.SqlQQ import Database.PostgreSQL.Simple.SqlQQ
import Gargantext.Core.Types.Main (NodeTree(..), Tree(..)) import Gargantext.Core.Types.Main (NodeTree(..), Tree(..))
import Gargantext.Database.Admin.Config (fromNodeTypeId, nodeTypeId) import Gargantext.Database.Admin.Config (fromNodeTypeId, nodeTypeId, fromNodeTypeId)
import Gargantext.Database.Admin.Types.Node (NodeId, NodeType, DocId, allNodeTypes) import Gargantext.Database.Admin.Types.Node (NodeId, NodeType, DocId, allNodeTypes)
import Gargantext.Database.Admin.Types.Node -- (pgNodeId, NodeType(..)) import Gargantext.Database.Admin.Types.Node -- (pgNodeId, NodeType(..))
import Gargantext.Database.Prelude (Cmd, runPGSQuery) import Gargantext.Database.Prelude (Cmd, runPGSQuery)
...@@ -89,28 +89,48 @@ tree_advanced :: HasTreeError err ...@@ -89,28 +89,48 @@ tree_advanced :: HasTreeError err
-> Cmd err (Tree NodeTree) -> Cmd err (Tree NodeTree)
tree_advanced r nodeTypes = do tree_advanced r nodeTypes = do
mainRoot <- dbTree r nodeTypes mainRoot <- dbTree r nodeTypes
sharedRoots <- findShared r NodeFolderShared nodeTypes sharedRoots <- findShared r NodeFolderShared nodeTypes sharedTreeUpdate
publicRoots <- findShared r NodeFolderPublic nodeTypes publicRoots <- findShared r NodeFolderPublic nodeTypes publicTreeUpdate
toTree $ toTreeParent (mainRoot <> sharedRoots <> publicRoots) toTree $ toTreeParent (mainRoot <> sharedRoots <> publicRoots)
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | Collaborative Nodes in the Tree -- | Collaborative Nodes in the Tree
findShared :: RootId -> NodeType -> [NodeType] -> Cmd err [DbTreeNode] findShared :: HasTreeError err
findShared r nt nts = do => RootId -> NodeType -> [NodeType] -> UpdateTree err
folderSharedId <- maybe (panic "no folder found") identity -> Cmd err [DbTreeNode]
<$> head findShared r nt nts fun = do
<$> findNodesId r [nt] foldersSharedId <- findNodesId r [nt]
folders <- getNodeNode folderSharedId trees <- mapM (updateTree nts fun) foldersSharedId
nodesSharedId <- mapM (\child -> sharedTree folderSharedId child nts) pure $ concat trees
updateTree :: HasTreeError err
=> [NodeType] -> UpdateTree err -> RootId
-> Cmd err [DbTreeNode]
updateTree nts fun r = do
folders <- getNodeNode r
nodesSharedId <- mapM (fun r nts)
$ map _nn_node2_id folders $ map _nn_node2_id folders
pure $ concat nodesSharedId pure $ concat nodesSharedId
sharedTree :: ParentId -> NodeId -> [NodeType] -> Cmd err [DbTreeNode]
sharedTree p n nt = dbTree n nt type UpdateTree err = ParentId -> [NodeType] -> NodeId -> Cmd err [DbTreeNode]
<&> map (\n' -> if _dt_nodeId n' == n
sharedTreeUpdate :: HasTreeError err => UpdateTree err
sharedTreeUpdate p nt n = dbTree n nt
<&> map (\n' -> if _dt_nodeId n' == n
then set dt_parentId (Just p) n'
else n')
publicTreeUpdate :: HasTreeError err => UpdateTree err
publicTreeUpdate p nt n = dbTree n nt
<&> map (\n' -> if _dt_nodeId n' == n
-- && (fromNodeTypeId $ _dt_typeId n') /= NodeFolderPublic
then set dt_parentId (Just p) n' then set dt_parentId (Just p) n'
else n') else n')
-- | findNodesId returns all nodes matching nodeType but the root (Nodeuser) -- | findNodesId returns all nodes matching nodeType but the root (Nodeuser)
findNodesId :: RootId -> [NodeType] -> Cmd err [NodeId] findNodesId :: RootId -> [NodeType] -> Cmd err [NodeId]
findNodesId r nt = tail findNodesId r nt = tail
......
...@@ -32,7 +32,7 @@ import Web.HttpApiData (parseUrlPiece, readTextData) ...@@ -32,7 +32,7 @@ import Web.HttpApiData (parseUrlPiece, readTextData)
import Gargantext.API.Prelude import Gargantext.API.Prelude
import Gargantext.Database.Admin.Types.Hyperdata import Gargantext.Database.Admin.Types.Hyperdata
import Gargantext.Database.Admin.Types.Node -- (PhyloId, ListId, CorpusId, UserId, NodeId(..)) import Gargantext.Database.Admin.Types.Node -- (PhyloId, ListId, CorpusId, UserId, NodeId(..))
import Gargantext.Database.Query.Table.Node (insertNodes, nodePhyloW, getNodeWith) import Gargantext.Database.Query.Table.Node (insertNodes, node, getNodeWith)
import Gargantext.Database.Schema.Node (_node_hyperdata) import Gargantext.Database.Schema.Node (_node_hyperdata)
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Viz.Phylo import Gargantext.Viz.Phylo
...@@ -95,15 +95,16 @@ type GetPhylo = QueryParam "listId" ListId ...@@ -95,15 +95,16 @@ type GetPhylo = QueryParam "listId" ListId
-- Add real text processing -- Add real text processing
-- Fix Filter parameters -- Fix Filter parameters
getPhylo :: PhyloId -> GargServer GetPhylo getPhylo :: PhyloId -> GargServer GetPhylo
--getPhylo phId _lId l msb _f _b _l' _ms _x _y _z _ts _s _o _e _d _b' = do
getPhylo phId _lId l msb = do getPhylo phId _lId l msb = do
phNode <- getNodeWith phId (Proxy :: Proxy HyperdataPhylo) phNode <- getNodeWith phId (Proxy :: Proxy HyperData)
let let
level = maybe 2 identity l level = maybe 2 identity l
branc = maybe 2 identity msb branc = maybe 2 identity msb
maybePhylo = hyperdataPhylo_data $ _node_hyperdata phNode maybePhylo = hd_data $ _node_hyperdata phNode
p <- liftBase $ viewPhylo2Svg $ viewPhylo level branc $ maybe phyloFromQuery identity maybePhylo p <- liftBase $ viewPhylo2Svg
$ viewPhylo level branc
$ maybe phyloFromQuery identity maybePhylo
pure (SVG p) pure (SVG p)
------------------------------------------------------------------------ ------------------------------------------------------------------------
type PostPhylo = QueryParam "listId" ListId type PostPhylo = QueryParam "listId" ListId
...@@ -119,7 +120,7 @@ postPhylo n userId _lId = do ...@@ -119,7 +120,7 @@ postPhylo n userId _lId = do
-- _sft = Just (Software "Gargantext" "4") -- _sft = Just (Software "Gargantext" "4")
-- _prm = initPhyloParam vrs sft (Just q) -- _prm = initPhyloParam vrs sft (Just q)
phy <- flowPhylo n phy <- flowPhylo n
pId <- insertNodes [nodePhyloW (Just "Phylo") (Just $ HyperdataPhylo Nothing (Just phy)) n userId] pId <- insertNodes [node NodePhylo "Phylo" (HyperdataPhylo Nothing (Just phy)) (Just n) userId]
pure $ NodeId (fromIntegral pId) pure $ NodeId (fromIntegral pId)
------------------------------------------------------------------------ ------------------------------------------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment