Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
haskell-gargantext
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
160
Issues
160
List
Board
Labels
Milestones
Merge Requests
14
Merge Requests
14
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gargantext
haskell-gargantext
Commits
842b3d36
Commit
842b3d36
authored
Jan 06, 2025
by
Alfredo Di Napoli
1
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support exporting docs and ngrams (but not importing them yet)
parent
98708c2e
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
96 additions
and
30 deletions
+96
-30
Types.hs
src/Gargantext/API/Ngrams/Types.hs
+1
-0
Export.hs
src/Gargantext/API/Node/Document/Export.hs
+24
-13
Types.hs
src/Gargantext/API/Node/Document/Export/Types.hs
+7
-1
Remote.hs
src/Gargantext/API/Server/Named/Remote.hs
+50
-10
Ngrams.hs
src/Gargantext/Core/Text/Ngrams.hs
+1
-0
Document.hs
src/Gargantext/Database/Admin/Types/Hyperdata/Document.hs
+2
-0
Node.hs
src/Gargantext/Database/Schema/Node.hs
+11
-6
No files found.
src/Gargantext/API/Ngrams/Types.hs
View file @
842b3d36
...
...
@@ -698,6 +698,7 @@ makeLenses ''Versioned
instance
(
Typeable
a
,
ToSchema
a
)
=>
ToSchema
(
Versioned
a
)
where
declareNamedSchema
=
wellNamedSchema
"_v_"
instance
NFData
a
=>
NFData
(
Versioned
a
)
where
instance
Serialise
a
=>
Serialise
(
Versioned
a
)
where
------------------------------------------------------------------------
type
Count
=
Int
...
...
src/Gargantext/API/Node/Document/Export.hs
View file @
842b3d36
...
...
@@ -9,6 +9,10 @@ Portability : POSIX
-}
module
Gargantext.API.Node.Document.Export
(
documentExportAPI
-- * Internals
,
get_document_json
)
where
import
Control.Lens
(
view
)
...
...
@@ -20,7 +24,7 @@ import Data.Time.Clock.System (getSystemTime, systemSeconds)
import
Data.Time.LocalTime
(
getCurrentTimeZone
,
TimeZone
(
timeZoneMinutes
))
import
Data.Version
(
showVersion
)
import
Gargantext.API.Node.Document.Export.Types
import
Gargantext.API.Prelude
(
GargNoServer
,
IsGargServer
)
import
Gargantext.API.Prelude
(
IsGargServer
)
import
Gargantext.API.Routes.Named.Document
qualified
as
Named
import
Gargantext.Core
(
toDBid
)
import
Gargantext.Database.Admin.Types.Node
(
DocId
,
NodeId
,
NodeType
(
..
))
...
...
@@ -46,21 +50,26 @@ documentExportAPI userNodeId dId = Named.DocumentExportAPI $ Named.DocumentExpor
--------------------------------------------------
-- | Hashes are ordered by Set
getDocumentsJSON
::
NodeId
getDocumentsJSON
::
IsGargServer
env
err
m
=>
NodeId
-- ^ The ID of the target user
->
DocId
->
GargNoServer
(
Headers
'[
H
eader
"Content-Disposition"
T
.
Text
]
DocumentExport
)
->
m
(
Headers
'[
H
eader
"Content-Disposition"
T
.
Text
]
DocumentExport
)
getDocumentsJSON
nodeUserId
pId
=
do
dexp
<-
get_document_json
nodeUserId
pId
pure
$
addHeader
(
T
.
concat
[
"attachment; filename="
,
"GarganText_DocsList-"
,
T
.
pack
(
show
pId
)
,
".json"
])
dexp
get_document_json
::
IsGargServer
err
env
m
=>
NodeId
->
DocId
->
m
DocumentExport
get_document_json
nodeUserId
pId
=
do
uId
<-
view
node_user_id
<$>
getNodeUser
nodeUserId
mcId
<-
getClosestParentIdByType
pId
NodeCorpus
let
cId
=
maybe
(
panicTrace
"[G.A.N.D.Export] Node has no parent"
)
identity
mcId
docs
<-
runViewDocuments
cId
False
Nothing
Nothing
Nothing
Nothing
Nothing
let
dexp
=
DocumentExport
{
_de_documents
=
mapFacetDoc
uId
<$>
docs
pure
DocumentExport
{
_de_documents
=
mapFacetDoc
uId
<$>
docs
,
_de_garg_version
=
T
.
pack
$
showVersion
PG
.
version
}
pure
$
addHeader
(
T
.
concat
[
"attachment; filename="
,
"GarganText_DocsList-"
,
T
.
pack
(
show
pId
)
,
".json"
])
dexp
where
mapFacetDoc
uId
(
FacetDoc
{
..
})
=
Document
{
_d_document
=
...
...
@@ -80,10 +89,11 @@ getDocumentsJSON nodeUserId pId = do
,
_ng_hash
=
""
}
,
_d_hash
=
""
}
getDocumentsJSONZip
::
NodeId
getDocumentsJSONZip
::
IsGargServer
env
err
m
=>
NodeId
-- ^ The Node ID of the target user
->
DocId
->
GargNoServer
(
Headers
'[
H
eader
"Content-Disposition"
T
.
Text
]
DocumentExportZIP
)
-- [Document]
->
m
(
Headers
'[
H
eader
"Content-Disposition"
T
.
Text
]
DocumentExportZIP
)
-- [Document]
getDocumentsJSONZip
userNodeId
pId
=
do
dJSON
<-
getDocumentsJSON
userNodeId
pId
systime
<-
liftBase
getSystemTime
...
...
@@ -98,10 +108,11 @@ getDocumentsJSONZip userNodeId pId = do
,
dezFileName
dexpz
,
".zip"
])
dexpz
getDocumentsTSV
::
NodeId
getDocumentsTSV
::
IsGargServer
err
env
m
=>
NodeId
-- ^ The Node ID of the target user
->
DocId
->
GargNoServer
(
Headers
'[
H
eader
"Content-Disposition"
T
.
Text
]
T
.
Text
)
-- [Document]
->
m
(
Headers
'[
H
eader
"Content-Disposition"
T
.
Text
]
T
.
Text
)
-- [Document]
getDocumentsTSV
userNodeId
pId
=
do
dJSON
<-
getDocumentsJSON
userNodeId
pId
let
DocumentExport
{
_de_documents
}
=
getResponse
dJSON
...
...
src/Gargantext/API/Node/Document/Export/Types.hs
View file @
842b3d36
...
...
@@ -13,12 +13,13 @@ Portability : POSIX
module
Gargantext.API.Node.Document.Export.Types
where
import
Codec.Serialise.Class
hiding
(
encode
)
import
Data.Aeson
(
encode
)
import
Data.Aeson.TH
(
deriveJSON
)
import
Data.Csv
(
DefaultOrdered
(
..
),
ToNamedRecord
(
..
),
(
.=
),
header
,
namedRecord
)
import
Data.Swagger
(
genericDeclareNamedSchema
,
ToParamSchema
(
..
),
ToSchema
(
..
)
)
import
Data.Text
qualified
as
T
import
Data.Text.Encoding
qualified
as
TE
import
Data.Text
qualified
as
T
import
Gargantext.Core.Types
(
Node
,
TODO
)
import
Gargantext.Core.Utils.Prefix
(
unPrefix
,
unPrefixSwagger
)
import
Gargantext.Database.Admin.Types.Hyperdata.Document
(
HyperdataDocument
(
..
)
)
...
...
@@ -36,6 +37,8 @@ data DocumentExport =
,
_de_garg_version
::
Text
}
deriving
(
Generic
)
instance
Serialise
DocumentExport
where
-- | This is to represent a zipped document export. We want to have doc_id in zipped file name.
data
DocumentExportZIP
=
DocumentExportZIP
{
_dez_dexp
::
DocumentExport
...
...
@@ -49,6 +52,7 @@ data Document =
,
_d_hash
::
Hash
}
deriving
(
Generic
)
instance
Serialise
Document
where
--instance Read Document where
-- read "" = panic "not implemented"
instance
DefaultOrdered
Document
where
...
...
@@ -102,6 +106,8 @@ instance ToParamSchema Document where
instance
ToParamSchema
Ngrams
where
toParamSchema
_
=
toParamSchema
(
Proxy
::
Proxy
TODO
)
instance
Serialise
Ngrams
where
$
(
deriveJSON
(
unPrefix
"_ng_"
)
''
N
grams
)
$
(
deriveJSON
(
unPrefix
"_d_"
)
''
D
ocument
)
$
(
deriveJSON
(
unPrefix
"_de_"
)
''
D
ocumentExport
)
...
...
src/Gargantext/API/Server/Named/Remote.hs
View file @
842b3d36
...
...
@@ -26,21 +26,39 @@ import Gargantext.API.Admin.Auth
import
Gargantext.API.Admin.Auth.Types
(
AuthenticatedUser
(
..
))
import
Gargantext.API.Auth.PolicyCheck
(
remoteExportChecks
)
import
Gargantext.API.Errors.Types
import
Gargantext.API.Ngrams.Prelude
(
getNgramsList
)
import
Gargantext.API.Ngrams.Types
(
NgramsList
)
import
Gargantext.API.Node.Document.Export.Types
(
DocumentExport
)
import
Gargantext.API.Prelude
(
IsGargServer
)
import
Gargantext.API.Routes.Client
(
remoteImportClient
)
import
Gargantext.API.Routes.Named.Remote
qualified
as
Named
import
Gargantext.Core.Config
import
Gargantext.Core
(
lookupDBid
)
import
Gargantext.Core.Types.Main
import
Gargantext.Database.Admin.Types.Node
import
Gargantext.Database.Prelude
(
IsDBCmd
)
import
Gargantext.Database.Query.Table.Node.Error
(
HasNodeError
,
nodeError
,
NodeError
(
..
))
import
Gargantext.Database.Query.Table.Node
(
insertNodeWithHyperdata
,
getNodes
,
getUserRootPrivateNode
)
import
Gargantext.Database.Schema.Node
(
NodePoly
(
..
))
import
Gargantext.Orphans
()
import
GHC.Generics
(
Generic
)
import
Prelude
import
Servant.Client.Streaming
(
mkClientEnv
,
withClientM
,
ClientError
)
import
Servant.Server.Generic
(
AsServerT
)
import
Gargantext.Core.Types.Main
import
Gargantext.API.Node.Document.Export
(
get_document_json
)
data
ExportableNode
=
ExportableNode
{
_en_node
::
Node
JSON
.
Value
-- | If this node is a \"docs\" node, remotely export also
-- all the associated documents.
,
_en_associated_docs
::
Maybe
DocumentExport
-- | If this node is a \"terms\" node, remotely export also
-- all the associated ngrams
,
_en_associated_ngrams
::
Maybe
NgramsList
}
deriving
Generic
instance
Serialise
ExportableNode
where
remoteAPI
::
(
MonadIO
m
,
IsGargServer
env
BackendInternalError
m
)
=>
AuthenticatedUser
...
...
@@ -48,11 +66,11 @@ remoteAPI :: (MonadIO m, IsGargServer env BackendInternalError m)
remoteAPI
authenticatedUser
=
Named
.
RemoteAPI
$
Named
.
RemoteAPI'
{
remoteExportEp
=
\
payload
@
Named
.
RemoteExportRequest
{
..
}
mgr
->
withPolicy
authenticatedUser
(
remoteExportChecks
_rer_node_id
)
(
remoteExportHandler
payload
)
mgr
withPolicy
authenticatedUser
(
remoteExportChecks
_rer_node_id
)
(
remoteExportHandler
authenticatedUser
payload
)
mgr
,
remoteImportEp
=
remoteImportHandler
authenticatedUser
}
type
ExpectedPayload
=
Tree
(
Node
JSON
.
Value
)
type
ExpectedPayload
=
Tree
ExportableNode
remoteImportHandler
::
forall
err
env
m
.
(
HasNodeError
err
,
HasBackendInternalError
err
,
IsDBCmd
env
err
m
,
MonadIO
m
)
...
...
@@ -74,14 +92,14 @@ remoteImportHandler loggedInUser c = do
foldlM
(
insertTrees
(
Just
rootNode
))
[
rootNode
]
xs
where
insertNode
::
Maybe
NodeId
->
Node
JSON
.
Valu
e
->
m
NodeId
insertNode
mb_parent
x
=
case
lookupDBid
$
_node_typename
x
of
insertNode
::
Maybe
NodeId
->
ExportableNod
e
->
m
NodeId
insertNode
mb_parent
(
ExportableNode
x
_mb_docs
_mb_terms
)
=
case
lookupDBid
$
_node_typename
x
of
Nothing
->
throwError
$
_BackendInternalError
#
InternalUnexpectedError
(
toException
$
userError
$
"remoteImportHandler: impossible, node with invalid type."
)
Just
ty
->
do
new_node
<-
insertNodeWithHyperdata
ty
(
_node_name
x
)
(
_node_hyperdata
x
)
mb_parent
(
_auth_user_id
loggedInUser
)
pure
new_node
insertTrees
::
Maybe
NodeId
->
[
NodeId
]
->
Tree
(
Node
JSON
.
Value
)
->
m
[
NodeId
]
insertTrees
::
Maybe
NodeId
->
[
NodeId
]
->
Tree
ExportableNode
->
m
[
NodeId
]
insertTrees
currentParent
!
acc
(
TreeN
x
xs
)
=
do
childrenRoot
<-
insertNode
currentParent
x
(`
mappend
`
acc
)
<$>
foldlM
(
insertTrees
(
Just
childrenRoot
))
[
childrenRoot
]
xs
...
...
@@ -91,15 +109,37 @@ remoteImportHandler loggedInUser c = do
remoteExportHandler
::
(
MonadIO
m
,
Safe
.
MonadCatch
m
,
IsGargServer
err
env
m
)
=>
Named
.
RemoteExportRequest
=>
AuthenticatedUser
->
Named
.
RemoteExportRequest
->
m
[
NodeId
]
remoteExportHandler
Named
.
RemoteExportRequest
{
..
}
=
do
remoteExportHandler
loggedInUser
Named
.
RemoteExportRequest
{
..
}
=
do
mgr
<-
view
gargHttpManager
nodes
<-
getNodes
_rer_node_id
checkNodesTypeAllowed
nodes
liftIO
(
withClientM
(
remoteImportClient
_rer_instance_auth
(
streamEncoder
nodes
))
(
mkClientEnv
mgr
_rer_instance_url
)
streamDecode
)
exportable
<-
makeExportable
(
_auth_node_id
loggedInUser
)
nodes
liftIO
(
withClientM
(
remoteImportClient
_rer_instance_auth
(
streamEncoder
exportable
))
(
mkClientEnv
mgr
_rer_instance_url
)
streamDecode
)
`
Safe
.
catch
`
\
(
e
::
BackendInternalError
)
->
throwError
$
_BackendInternalError
#
e
makeExportable
::
IsGargServer
err
env
m
=>
NodeId
->
Tree
(
Node
JSON
.
Value
)
->
m
(
Tree
ExportableNode
)
makeExportable
userNodeId
(
TreeN
x
xs
)
|
Just
nty
<-
lookupDBid
(
_node_typename
x
)
=
do
mb_docs
<-
case
nty
of
NodeDocument
->
Just
<$>
get_document_json
userNodeId
(
_node_id
x
)
_
->
pure
Nothing
mb_ngrams
<-
case
nty
of
NodeList
->
Just
<$>
getNgramsList
(
_node_id
x
)
_
->
pure
Nothing
let
exportableRoot
=
ExportableNode
x
mb_docs
mb_ngrams
children
<-
mapM
(
makeExportable
userNodeId
)
xs
pure
$
TreeN
exportableRoot
children
|
otherwise
=
throwError
$
_BackendInternalError
#
InternalUnexpectedError
(
toException
$
userError
$
"remoteImportHandler: impossible, node with invalid type."
)
checkNodesTypeAllowed
::
(
MonadError
e
m
,
HasNodeError
e
)
=>
Tree
(
Node
a
)
->
m
()
checkNodesTypeAllowed
(
TreeN
r
xs
)
=
do
checkNodeTypeAllowed
r
...
...
@@ -118,7 +158,7 @@ checkNodeTypeAllowed n
exportableNodeTypes
::
[
NodeType
]
exportableNodeTypes
=
[
NodeCorpus
,
NodeCorpusV3
,
NodeTexts
,
NodeGraph
,
NodeList
,
NodePhylo
]
streamEncoder
::
(
MonadIO
m
,
Serialise
a
)
=>
a
->
ConduitT
()
Named
.
RemoteBinaryData
m
()
streamEncoder
::
MonadIO
m
=>
ExpectedPayload
->
ConduitT
()
Named
.
RemoteBinaryData
m
()
streamEncoder
=
CL
.
sourceList
.
map
Named
.
RemoteBinaryData
.
BL
.
toChunks
.
serialise
-- | Returns a conduit which can be used to decode
...
...
src/Gargantext/Core/Text/Ngrams.hs
View file @
842b3d36
...
...
@@ -88,6 +88,7 @@ data Ngrams = UnsafeNgrams { _ngramsTerms :: Text
deriving
(
Generic
,
Show
,
Eq
,
Ord
)
instance
Hashable
Ngrams
instance
Serialise
Ngrams
where
makeLenses
''
N
grams
instance
PGS
.
ToRow
Ngrams
where
...
...
src/Gargantext/Database/Admin/Types/Hyperdata/Document.hs
View file @
842b3d36
...
...
@@ -17,6 +17,7 @@ import Gargantext.Prelude hiding (ByteString)
import
Gargantext.Core.Text
(
HasText
(
..
))
import
Gargantext.Core.Utils.Prefix
(
unCapitalize
,
dropPrefix
)
import
Gargantext.Database.Admin.Types.Hyperdata.Prelude
import
Codec.Serialise.Class
hiding
(
decode
)
------------------------------------------------------------------------
data
HyperdataDocument
=
HyperdataDocument
{
_hd_bdd
::
!
(
Maybe
Text
)
...
...
@@ -41,6 +42,7 @@ data HyperdataDocument = HyperdataDocument { _hd_bdd :: !(Maybe T
deriving
(
Show
,
Generic
)
instance
NFData
HyperdataDocument
instance
Serialise
HyperdataDocument
instance
HasText
HyperdataDocument
where
...
...
src/Gargantext/Database/Schema/Node.hs
View file @
842b3d36
...
...
@@ -16,13 +16,14 @@ Portability : POSIX
module
Gargantext.Database.Schema.Node
where
import
Codec.Serialise
import
Codec.CBOR.JSON
qualified
as
CBOR
import
Codec.Serialise
import
Control.Lens
hiding
(
elements
,
(
&
))
import
Data.Aeson
qualified
as
JSON
import
Data.Aeson
(
ToJSON
,
toJSON
,
parseJSON
,
FromJSON
)
import
Gargantext.Database.Schema.Prelude
import
Gargantext.Prelude
(
NFData
(
..
))
import
Prelude
hiding
(
null
,
id
,
map
,
sum
)
import
Data.Aeson.Types
(
parseEither
)
------------------------------------------------------------------------
-- Main polymorphic Node definition
...
...
@@ -57,7 +58,9 @@ instance ( Serialise i
,
Serialise
p
,
Serialise
n
,
Serialise
d
)
=>
Serialise
(
NodePoly
i
h
t
u
p
n
d
JSON
.
Value
)
where
,
ToJSON
json
,
FromJSON
json
)
=>
Serialise
(
NodePoly
i
h
t
u
p
n
d
json
)
where
encode
Node
{
..
}
=
encode
_node_id
<>
encode
_node_hash_id
<>
...
...
@@ -66,7 +69,7 @@ instance ( Serialise i
encode
_node_parent_id
<>
encode
_node_name
<>
encode
_node_date
<>
CBOR
.
encodeValue
_node_hyperdata
CBOR
.
encodeValue
(
toJSON
_node_hyperdata
)
decode
=
do
_node_id
<-
decode
_node_hash_id
<-
decode
...
...
@@ -75,8 +78,10 @@ instance ( Serialise i
_node_parent_id
<-
decode
_node_name
<-
decode
_node_date
<-
decode
_node_hyperdata
<-
CBOR
.
decodeValue
False
pure
Node
{
..
}
mb_node_hyperdata
<-
parseEither
parseJSON
<$>
CBOR
.
decodeValue
False
case
mb_node_hyperdata
of
Left
err
->
fail
err
Right
_node_hyperdata
->
pure
Node
{
..
}
------------------------------------------------------------------------
-- Automatic instances derivation
...
...
Przemyslaw Kaminski
@cgenie
mentioned in commit
942e663f
·
Jan 29, 2025
mentioned in commit
942e663f
mentioned in commit 942e663f539b287b4cc0469fe2bcf735813b4ff2
Toggle commit list
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment