[GraphQL] refactoring of endpoints

Mostly, it's about reducing their number and making things cleaner.

E.g. tree is not a different request, but a combination of various
"nodes" requests to get children/parent.
parent 931051af
Pipeline #7589 failed with stages
in 18 minutes and 45 seconds
<!--
* Copyright (c) 2021 GraphQL Contributors
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE file in the root directory of this source tree.
This is a copy-paste from
https://github.com/graphql/graphiql/tree/main/examples/graphiql-cdn
adjusted to get the GGTX bearer token.
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>GraphiQL 4 with React 19 and GraphiQL Explorer</title>
<style>
body {
margin: 0;
overflow: hidden; /* in Firefox */
}
#graphiql {
height: 100dvh;
}
.loading {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
font-size: 4rem;
}
</style>
<link
rel="stylesheet"
href="https://esm.sh/graphiql@4.0.0/dist/style.css"
/>
<link
rel="stylesheet"
href="https://esm.sh/@graphiql/plugin-explorer@4.0.0/dist/style.css"
/>
<!-- Note: the ?standalone flag bundles the module along with all of its `dependencies`, excluding `peerDependencies`, into a single JavaScript file. -->
<script type="importmap">
{
"imports": {
"react": "https://esm.sh/react@19.1.0",
"react/jsx-runtime": "https://esm.sh/react@19.1.0/jsx-runtime",
"react-dom": "https://esm.sh/react-dom@19.1.0",
"react-dom/client": "https://esm.sh/react-dom@19.1.0/client",
"graphiql": "https://esm.sh/graphiql@4.0.0?standalone&external=react,react/jsx-runtime,react-dom,@graphiql/react",
"@graphiql/plugin-explorer": "https://esm.sh/@graphiql/plugin-explorer@4.0.0?standalone&external=react,react/jsx-runtime,react-dom,@graphiql/react,graphql",
"@graphiql/react": "https://esm.sh/@graphiql/react@0.30.0?standalone&external=react,react/jsx-runtime,react-dom,graphql,@graphiql/toolkit",
"@graphiql/toolkit": "https://esm.sh/@graphiql/toolkit@0.11.2?standalone&external=graphql",
"graphql": "https://esm.sh/graphql@16.11.0"
}
}
</script>
<script type="module">
// Import React and ReactDOM
import React from 'react';
import ReactDOM from 'react-dom/client';
// Import GraphiQL and the Explorer plugin
import { GraphiQL } from 'graphiql';
import { createGraphiQLFetcher } from '@graphiql/toolkit';
import { explorerPlugin } from '@graphiql/plugin-explorer';
// find gargantext local storage session cookie
const sessions = JSON.parse(localStorage.getItem('garg-sessions')) || [];
const token = (sessions.filter((s) => s.backend.baseUrl == window.location.origin)[0] || {}).token;
console.log('found token', token);
const fetcher = createGraphiQLFetcher({
// url: 'https://countries.trevorblades.com',
url: 'http://localhost:8008/gql',
headers: {
'Authorization': `Bearer ${token}`,
},
});
const explorer = explorerPlugin();
function App() {
return React.createElement(GraphiQL, {
fetcher,
plugins: [explorer],
});
}
const container = document.getElementById('graphiql');
const root = ReactDOM.createRoot(container);
root.render(React.createElement(App));
</script>
</head>
<body>
<div id="graphiql">
<div class="loading">Loading…</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="SwaggerUI" />
<title>SwaggerUI</title>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5.11.0/swagger-ui.css" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://unpkg.com/swagger-ui-dist@5.11.0/swagger-ui-bundle.js" crossorigin></script>
<script>
window.onload = () => {
window.ui = SwaggerUIBundle({
url: `${window.location.origin}/swagger.json`,
dom_id: '#swagger-ui',
});
};
</script>
</body>
</html>
...@@ -1020,7 +1020,7 @@ ...@@ -1020,7 +1020,7 @@
"debouncing": "0.1.2", "debouncing": "0.1.2",
"graphql-client": { "graphql-client": {
"git": "https://github.com/OxfordAbstracts/purescript-graphql-client", "git": "https://github.com/OxfordAbstracts/purescript-graphql-client",
"ref": "v10.0.3", "ref": "694551e8baa992310eedf0a9d90f6e23b2e8d964",
"dependencies": [ "dependencies": [
"aff", "aff",
"affjax", "affjax",
...@@ -1780,7 +1780,7 @@ ...@@ -1780,7 +1780,7 @@
"graphql-client": { "graphql-client": {
"type": "git", "type": "git",
"url": "https://github.com/OxfordAbstracts/purescript-graphql-client", "url": "https://github.com/OxfordAbstracts/purescript-graphql-client",
"rev": "7f85c4d64ab4b767ecc999429c1c37f7a6ad4816", "rev": "694551e8baa992310eedf0a9d90f6e23b2e8d964",
"dependencies": [ "dependencies": [
"aff", "aff",
"affjax", "affjax",
......
...@@ -20,7 +20,8 @@ workspace: ...@@ -20,7 +20,8 @@ workspace:
# https://github.com/OxfordAbstracts/purescript-graphql-client/issues/138 # https://github.com/OxfordAbstracts/purescript-graphql-client/issues/138
graphql-client: graphql-client:
git: https://github.com/OxfordAbstracts/purescript-graphql-client git: https://github.com/OxfordAbstracts/purescript-graphql-client
ref: v10.0.3 ref: 694551e8baa992310eedf0a9d90f6e23b2e8d964
#ref: v10.0.3
dependencies: dependencies:
- aff - aff
- affjax - affjax
......
...@@ -17,7 +17,7 @@ import Gargantext.Components.Bootstrap as B ...@@ -17,7 +17,7 @@ import Gargantext.Components.Bootstrap as B
import Gargantext.Components.Bootstrap.Types (ComponentStatus(..), SpinnerTheme(..)) import Gargantext.Components.Bootstrap.Types (ComponentStatus(..), SpinnerTheme(..))
import Gargantext.Components.Category (ratingSimpleLoader) import Gargantext.Components.Category (ratingSimpleLoader)
import Gargantext.Components.Document.Types (DocPath, Document(..), LoadedData, initialState) import Gargantext.Components.Document.Types (DocPath, Document(..), LoadedData, initialState)
import Gargantext.Components.GraphQL.Endpoints (getContextNgrams) import Gargantext.Components.GraphQL.Endpoints (getNgramsForContextAndList)
import Gargantext.Components.NgramsTable.AutoSync (useAutoSync) import Gargantext.Components.NgramsTable.AutoSync (useAutoSync)
import Gargantext.Components.Node (NodePoly(..)) import Gargantext.Components.Node (NodePoly(..))
import Gargantext.Core.NgramsTable.Functions (addNewNgramA, applyNgramsPatches, coreDispatch, findNgramRoot, setTermListA, computeCache) import Gargantext.Core.NgramsTable.Functions (addNewNgramA, applyNgramsPatches, coreDispatch, findNgramRoot, setTermListA, computeCache)
...@@ -76,7 +76,7 @@ layoutCpt = R2.hereComponent here "layout" hCpt ...@@ -76,7 +76,7 @@ layoutCpt = R2.hereComponent here "layout" hCpt
useLoader useLoader
{ errorHandler: Nothing { errorHandler: Nothing
, herePrefix: hp , herePrefix: hp
, loader: \p -> getContextNgrams session p.contextId p.listId , loader: \p -> getNgramsForContextAndList session p.contextId p.listId
, path: { contextId: nodeId, listId } , path: { contextId: nodeId, listId }
, render: \contextNgrams -> , render: \contextNgrams ->
layoutWithContextNgrams $ Record.merge props { contextNgrams } layoutWithContextNgrams $ Record.merge props { contextNgrams }
......
...@@ -6,6 +6,7 @@ import DOM.Simple (window) ...@@ -6,6 +6,7 @@ import DOM.Simple (window)
import Data.Array as A import Data.Array as A
import Data.Maybe (Maybe(..), fromMaybe) import Data.Maybe (Maybe(..), fromMaybe)
import Data.Traversable (traverse_) import Data.Traversable (traverse_)
import Effect (Effect)
import Effect.Aff (Aff) import Effect.Aff (Aff)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Gargantext.AsyncTasks as GAT import Gargantext.AsyncTasks as GAT
...@@ -27,12 +28,12 @@ import Gargantext.Components.Forest.Tree.Node.Action.Update (updateRequest) ...@@ -27,12 +28,12 @@ import Gargantext.Components.Forest.Tree.Node.Action.Update (updateRequest)
import Gargantext.Components.Forest.Tree.Node.Action.Upload (uploadArbitraryFile, uploadFile) import Gargantext.Components.Forest.Tree.Node.Action.Upload (uploadArbitraryFile, uploadFile)
import Gargantext.Components.Forest.Tree.Node.Box (nodePopupView) import Gargantext.Components.Forest.Tree.Node.Box (nodePopupView)
import Gargantext.Components.Forest.Tree.Node.Tools.SubTree.Types (SubTreeOut(..)) import Gargantext.Components.Forest.Tree.Node.Tools.SubTree.Types (SubTreeOut(..))
import Gargantext.Components.GraphQL.Endpoints (getNode, getTreeFirstLevel) import Gargantext.Components.GraphQL.Endpoints (getNodeById, getTreeFirstLevel)
import Gargantext.Components.GraphQL.Node (Node) import Gargantext.Components.GraphQL.Node (Node)
import Gargantext.Components.GraphQL.Tree (TreeFirstLevel, TreeNode) import Gargantext.Components.GraphQL.Tree (TreeFirstLevel)
import Gargantext.Config.REST (AffRESTError) import Gargantext.Config.REST (AffRESTError)
import Gargantext.Config.Utils (handleRESTError) import Gargantext.Config.Utils (handleRESTError)
import Gargantext.Hooks.LinkHandler (useLinkHandler) import Gargantext.Hooks.LinkHandler (useLinkHandler, Methods)
import Gargantext.Hooks.Loader (useLoader) import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Routes (AppRoute(Home), appPath, nodeTypeAppRoute) import Gargantext.Routes (AppRoute(Home), appPath, nodeTypeAppRoute)
import Gargantext.Sessions (Session(..), sessionId) import Gargantext.Sessions (Session(..), sessionId)
...@@ -101,10 +102,10 @@ folderViewMainCpt = here.component "folderViewMainCpt" cpt ...@@ -101,10 +102,10 @@ folderViewMainCpt = here.component "folderViewMainCpt" cpt
$ parent $ parent
<> childrenEl <> childrenEl
makeFolderElements :: Array TreeNode -> Record FolderViewProps -> Array R.Element makeFolderElements :: Array Node -> Record FolderViewProps -> Array R.Element
makeFolderElements folders' props = makeFolderElementsMap <$> folders' makeFolderElements folders' props = makeFolderElementsMap <$> folders'
where where
makeFolderElementsMap :: TreeNode -> R.Element makeFolderElementsMap :: Node -> R.Element
makeFolderElementsMap node = folder makeFolderElementsMap node = folder
{ nodeId: node.id { nodeId: node.id
, linkId: node.id , linkId: node.id
...@@ -117,7 +118,7 @@ folderViewMainCpt = here.component "folderViewMainCpt" cpt ...@@ -117,7 +118,7 @@ folderViewMainCpt = here.component "folderViewMainCpt" cpt
, text: node.name , text: node.name
} }
makeParentFolder :: TreeNode -> Maybe TreeNode -> Record FolderViewProps -> Array R.Element makeParentFolder :: Node -> Maybe Node -> Record FolderViewProps -> Array R.Element
makeParentFolder root (Just parent) props = makeParentFolder root (Just parent) props =
[ folder [ folder
{ linkId: parent.id { linkId: parent.id
...@@ -133,7 +134,7 @@ folderViewMainCpt = here.component "folderViewMainCpt" cpt ...@@ -133,7 +134,7 @@ folderViewMainCpt = here.component "folderViewMainCpt" cpt
] ]
makeParentFolder _ Nothing _ = [] makeParentFolder _ Nothing _ = []
sortFolders :: TreeNode -> TreeNode -> Ordering sortFolders :: Node -> Node -> Ordering
sortFolders a b = compare a.id b.id sortFolders a b = compare a.id b.id
type FolderProps = type FolderProps =
...@@ -298,7 +299,9 @@ backButtonSmartMainCpt = here.component "backButtonSmartMain" cpt ...@@ -298,7 +299,9 @@ backButtonSmartMainCpt = here.component "backButtonSmartMain" cpt
[ H.i { className: "fa fa-arrow-left", title: "Previous view" } [] [ H.i { className: "fa fa-arrow-left", title: "Previous view" } []
] ]
where where
action rootId pId handlers action :: Int -> Maybe Int -> Record Methods -> Effect Unit
action _rootId Nothing _handlers = pure unit
action rootId (Just pId) handlers
| rootId == pId = handlers.goToRoute Home | rootId == pId = handlers.goToRoute Home
| otherwise = handlers.goToPreviousPage unit | otherwise = handlers.goToPreviousPage unit
...@@ -315,7 +318,7 @@ loadFolders :: Record LoadProps -> AffRESTError TreeFirstLevel ...@@ -315,7 +318,7 @@ loadFolders :: Record LoadProps -> AffRESTError TreeFirstLevel
loadFolders { nodeId, session } = getTreeFirstLevel session nodeId loadFolders { nodeId, session } = getTreeFirstLevel session nodeId
loadNode :: Record LoadProps -> AffRESTError Node loadNode :: Record LoadProps -> AffRESTError Node
loadNode { nodeId, session } = getNode session nodeId loadNode { nodeId, session } = getNodeById session nodeId
type PerformActionProps = type PerformActionProps =
( boxes :: Boxes ( boxes :: Boxes
......
...@@ -11,7 +11,8 @@ import Data.String (Pattern(..), split) ...@@ -11,7 +11,8 @@ import Data.String (Pattern(..), split)
import Gargantext.Components.App.Store as Store import Gargantext.Components.App.Store as Store
import Gargantext.Components.Bootstrap as B import Gargantext.Components.Bootstrap as B
import Gargantext.Components.GraphQL.Endpoints (getBreadcrumb, getNodeChildren, getNodeParent) import Gargantext.Components.GraphQL.Endpoints (getBreadcrumb, getNodeChildren, getNodeParent)
import Gargantext.Components.GraphQL.Tree (BreadcrumbInfo, TreeNode) import Gargantext.Components.GraphQL.Node (Node)
import Gargantext.Components.GraphQL.Tree (BreadcrumbInfo)
import Gargantext.Config.REST (AffRESTError) import Gargantext.Config.REST (AffRESTError)
import Gargantext.Ends (Backend(..)) import Gargantext.Ends (Backend(..))
import Gargantext.Hooks.Loader (useLoader) import Gargantext.Hooks.Loader (useLoader)
...@@ -195,10 +196,10 @@ breadcrumbViewMainCpt = here.component "breadcrumbViewMainCpt" cpt ...@@ -195,10 +196,10 @@ breadcrumbViewMainCpt = here.component "breadcrumbViewMainCpt" cpt
pure $ pure $
R.fragment items R.fragment items
makeBreadcrumbElements :: Array TreeNode -> Session -> String -> Boolean -> Array R.Element makeBreadcrumbElements :: Array Node -> Session -> String -> Boolean -> Array R.Element
makeBreadcrumbElements items' session format openTreeNodes = makeBreadcrumbElementsMap <$> items' makeBreadcrumbElements items' session format openTreeNodes = makeBreadcrumbElementsMap <$> items'
where where
makeBreadcrumbElementsMap :: TreeNode -> R.Element makeBreadcrumbElementsMap :: Node -> R.Element
makeBreadcrumbElementsMap node = breadcrumbItem makeBreadcrumbElementsMap node = breadcrumbItem
{ linkId: node.id { linkId: node.id
, linkNodeType: node.node_type , linkNodeType: node.node_type
...@@ -353,8 +354,8 @@ loadBreadcrumbData { route: CorpusDocument _s corpusId listId documentId, sessio ...@@ -353,8 +354,8 @@ loadBreadcrumbData { route: CorpusDocument _s corpusId listId documentId, sessio
loadBreadcrumbData { route: Dashboard _s nodeId, session } = do loadBreadcrumbData { route: Dashboard _s nodeId, session } = do
loadBreadcrumbDataRaw { nodeId, session } loadBreadcrumbDataRaw { nodeId, session }
loadBreadcrumbData { route: Document _s listId documentId, session } = do loadBreadcrumbData { route: Document _s listId documentId, session } = do
corpora <- getNodeParent session listId GT.Corpus corpus <- getNodeParent session listId GT.Corpus
let nodeId = maybe listId _.id $ either (const Nothing) A.head corpora let nodeId = either (const listId) _.id corpus
loadBreadcrumbDataRaw { nodeId, session } loadBreadcrumbDataRaw { nodeId, session }
loadBreadcrumbData { route: Folder _s nodeId, session } = do loadBreadcrumbData { route: Folder _s nodeId, session } = do
loadBreadcrumbDataRaw { nodeId, session } loadBreadcrumbDataRaw { nodeId, session }
......
...@@ -260,16 +260,17 @@ nodeSpanCpt = here.component "nodeSpan" cpt ...@@ -260,16 +260,17 @@ nodeSpanCpt = here.component "nodeSpan" cpt
NT.NUpdateWorkerProgress ji atl -> do NT.NUpdateWorkerProgress ji atl -> do
-- TODO Fire this only once! -- TODO Fire this only once!
here.log3 "[nodeSpan] update job progress" ji atl here.log3 "[nodeSpan] update job progress" ji atl
let wtl = GT.WorkerTaskWithLog { task: ji, lastLog: Just atl }
if GT.asyncTaskLogIsFinished atl then do if GT.asyncTaskLogIsFinished atl then do
-- Handle error but only when the task is not already in the storage -- Handle error but only when the task is not already in the storage
-- (we want to avoid reporting the error multiple times, from different places). -- (we want to avoid reporting the error multiple times, from different places).
-- See e.g. https://gitlab.iscpif.fr/gargantext/purescript-gargantext/issues/728 -- See e.g. https://gitlab.iscpif.fr/gargantext/purescript-gargantext/issues/728
-- (error is thrown before the task marks any progress) -- (error is thrown before the task marks any progress)
hasTask <- GAT.hasTask props.id ji boxes.tasks hasTask <- GAT.hasTask props.id wtl boxes.tasks
unless hasTask $ do unless hasTask $ do
handleErrorInAsyncTaskLog boxes.errors atl handleErrorInAsyncTaskLog boxes.errors atl
else do else do
GAT.insert props.id ji boxes.tasks GAT.insert props.id wtl boxes.tasks
_ -> pure unit _ -> pure unit
ws <- T.read boxes.wsNotification ws <- T.read boxes.wsNotification
let action = NT.InsertCallback (NT.UpdateTree props.id) ("node-span-" <> show props.id) cb let action = NT.InsertCallback (NT.UpdateTree props.id) ("node-span-" <> show props.id) cb
......
...@@ -25,6 +25,8 @@ import Gargantext.Routes (AppRoute) ...@@ -25,6 +25,8 @@ import Gargantext.Routes (AppRoute)
import Gargantext.Sessions (Session(..)) import Gargantext.Sessions (Session(..))
import Gargantext.Types (NodeType) import Gargantext.Types (NodeType)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import GraphQL.Client.Args (OrArg, IgnoreArg, AndArg)
import GraphQL.Client.AsGql (AsGql)
import GraphQL.Client.BaseClients.Urql (UrqlClient, createClient) import GraphQL.Client.BaseClients.Urql (UrqlClient, createClient)
import GraphQL.Client.Operation (OpMutation, OpQuery) import GraphQL.Client.Operation (OpMutation, OpQuery)
import GraphQL.Client.Query (decodeGqlRes) --, mutationJson) import GraphQL.Client.Query (decodeGqlRes) --, mutationJson)
...@@ -32,6 +34,7 @@ import GraphQL.Client.SafeQueryName (safeQueryName) ...@@ -32,6 +34,7 @@ import GraphQL.Client.SafeQueryName (safeQueryName)
import GraphQL.Client.ToGqlString (toGqlQueryString) import GraphQL.Client.ToGqlString (toGqlQueryString)
import GraphQL.Client.Types (class GqlQuery, Client(..), class QueryClient, clientQuery, defQueryOpts, clientMutation, defMutationOpts) import GraphQL.Client.Types (class GqlQuery, Client(..), class QueryClient, clientQuery, defQueryOpts, clientMutation, defMutationOpts)
import GraphQL.Client.Variables (class VarsTypeChecked, getVarsJson, getVarsTypeNames) import GraphQL.Client.Variables (class VarsTypeChecked, getVarsJson, getVarsTypeNames)
import Prim.Row as Row
import Simple.JSON as JSON import Simple.JSON as JSON
import Type.Data.List (Nil') import Type.Data.List (Nil')
import Type.Proxy (Proxy(..)) import Type.Proxy (Proxy(..))
...@@ -122,6 +125,7 @@ getClient (Session { token, backend: Backend b }) = createClient { headers, url: ...@@ -122,6 +125,7 @@ getClient (Session { token, backend: Backend b }) = createClient { headers, url:
queryGql queryGql
:: forall query returns :: forall query returns
. GqlQuery Nil' OpQuery Schema query returns . GqlQuery Nil' OpQuery Schema query returns
-- => Row.Union Schema sr schema
=> JSON.ReadForeign returns => JSON.ReadForeign returns
=> Session => Session
-> String -> String
...@@ -147,21 +151,24 @@ mutationGql session name q = do ...@@ -147,21 +151,24 @@ mutationGql session name q = do
-- Schema -- Schema
type Schema = type Schema =
{ annuaire_contacts :: { contact_id :: Int } -> Array AnnuaireContact { annuaireContact :: { contactId :: Int } -> AnnuaireContact
, context_ngrams :: { context_id :: Int, list_id :: Int } -> Array String , context :: { contextId :: Int, nodeId :: Int } -> GQLCTX.NodeContext
, contexts :: { context_id :: Int, node_id :: Int } -> Array GQLCTX.NodeContext , contextsForNgrams :: { corpus_id :: Int, ngrams_terms :: GQLCTX.NgramsTerms, and_logic :: String } -> Array GQLCTX.Context
, contexts_for_ngrams :: { corpus_id :: Int, ngrams_terms :: GQLCTX.NgramsTerms, and_logic :: String } -> Array GQLCTX.Context , corpus :: { id :: Int } -> GQLNode.Corpus
, imt_schools :: {} -> Array GQLIMT.School
, languages :: {} -> Array GQLNLP.Language , languages :: {} -> Array GQLNLP.Language
, node_children :: { node_id :: Int, child_type :: NodeType } -> Array GQLNode.Node , ngramsForContextAndListId :: { contextId :: Int, listId :: Int } -> Array String
, node_parent :: { node_id :: Int, parent_type :: NodeType } -> Array GQLNode.Node , node :: { id :: Int } -> GQLNode.Node
, nodes :: { node_id :: Int } -> Array GQLNode.Node , nodes ::
, nodes_corpus :: { corpus_id :: Int } -> Array GQLNode.Corpus { parentId :: AsGql "Int" Int
, user_infos :: { user_id :: Int } -> Array UserInfo , containsChildId :: AsGql "Int" Int
, users :: { user_id :: Int } -> Array User , deepChildId :: AsGql "Int" Int
, nodeType :: AsGql "NodeType" NodeType
}
-> Array GQLNode.Node
, schools :: {} -> Array GQLIMT.School
, team :: { team_node_id :: Int } -> Team , team :: { team_node_id :: Int } -> Team
, tree :: { root_id :: Int } -> TreeFirstLevel , user :: { id :: Int } -> User
, tree_branch :: { node_id :: Int } -> BreadcrumbInfo , userInfo :: { userId :: Int } -> UserInfo
} }
type Mutation = type Mutation =
......
...@@ -48,9 +48,9 @@ type AnnuaireContact = ...@@ -48,9 +48,9 @@ type AnnuaireContact =
} }
type AnnuaireContactQuery = type AnnuaireContactQuery =
{ annuaire_contacts :: { annuaireContact ::
Args Args
{ contact_id :: Var "id" Int } { contactId :: Var "id" Int }
{ ac_title :: Unit { ac_title :: Unit
, ac_source :: Unit , ac_source :: Unit
, ac_id :: Unit , ac_id :: Unit
...@@ -70,8 +70,8 @@ type AnnuaireContactQuery = ...@@ -70,8 +70,8 @@ type AnnuaireContactQuery =
annuaireContactQuery :: AnnuaireContactQuery annuaireContactQuery :: AnnuaireContactQuery
annuaireContactQuery = annuaireContactQuery =
{ annuaire_contacts: { annuaireContact:
{ contact_id: Var :: _ "id" Int } =>> { contactId: Var :: _ "id" Int } =>>
GGQL.getFieldsStandard (Proxy :: _ AnnuaireContact) GGQL.getFieldsStandard (Proxy :: _ AnnuaireContact)
} }
......
...@@ -5,10 +5,11 @@ module Gargantext.Components.GraphQL.Context ...@@ -5,10 +5,11 @@ module Gargantext.Components.GraphQL.Context
, Hyperdata , Hyperdata
, NodeContext , NodeContext
, NodeContext_ , NodeContext_
, nodeContextQuery , ContextByIdAndNodeQuery
, getContextByIdAndNodeQuery
, NodeContextCategoryM , NodeContextCategoryM
, contextsForNgramsQuery , getContextsForNgramsQuery
, contextNgramsQuery , getNgramsForContextAndListQuery
, NgramsTerms(..) , NgramsTerms(..)
) where ) where
...@@ -70,11 +71,11 @@ type NodeContext_ = ...@@ -70,11 +71,11 @@ type NodeContext_ =
type NodeContext = Record NodeContext_ type NodeContext = Record NodeContext_
type NodeContextQuery = type ContextByIdAndNodeQuery =
{ contexts :: { context ::
Args Args
{ context_id :: Var "context_id" Int { contextId :: Var "contextId" Int
, node_id :: Var "node_id" Int , nodeId :: Var "nodeId" Int
} }
{ nc_id :: Unit { nc_id :: Unit
, nc_node_id :: Unit , nc_node_id :: Unit
...@@ -84,17 +85,17 @@ type NodeContextQuery = ...@@ -84,17 +85,17 @@ type NodeContextQuery =
} }
} }
nodeContextQuery :: NodeContextQuery getContextByIdAndNodeQuery :: ContextByIdAndNodeQuery
nodeContextQuery = getContextByIdAndNodeQuery =
{ contexts: { context:
{ context_id: Var :: _ "context_id" Int { contextId: Var :: _ "contextId" Int
, node_id: Var :: _ "node_id" Int , nodeId: Var :: _ "nodeId" Int
} =>> } =>>
GGQL.getFieldsStandard (Proxy :: _ NodeContext) GGQL.getFieldsStandard (Proxy :: _ NodeContext)
} }
type ContextsForNgramsQuery = type ContextsForNgramsQuery =
{ contexts_for_ngrams :: { contextsForNgrams ::
Args Args
{ corpus_id :: Var "corpus_id" Int { corpus_id :: Var "corpus_id" Int
, ngrams_terms :: Var "ngrams_terms" NgramsTerms , ngrams_terms :: Var "ngrams_terms" NgramsTerms
...@@ -131,9 +132,9 @@ type ContextsForNgramsQuery = ...@@ -131,9 +132,9 @@ type ContextsForNgramsQuery =
} }
} }
contextsForNgramsQuery :: ContextsForNgramsQuery getContextsForNgramsQuery :: ContextsForNgramsQuery
contextsForNgramsQuery = getContextsForNgramsQuery =
{ contexts_for_ngrams: { contextsForNgrams:
{ corpus_id: Var :: _ "corpus_id" Int { corpus_id: Var :: _ "corpus_id" Int
, ngrams_terms: Var :: _ "ngrams_terms" NgramsTerms , ngrams_terms: Var :: _ "ngrams_terms" NgramsTerms
, and_logic: Var :: _ "and_logic" String , and_logic: Var :: _ "and_logic" String
...@@ -141,20 +142,20 @@ contextsForNgramsQuery = ...@@ -141,20 +142,20 @@ contextsForNgramsQuery =
GGQL.getFieldsStandard (Proxy :: _ Context) GGQL.getFieldsStandard (Proxy :: _ Context)
} }
type ContextNgramsQuery = type NgramsForContextAndListQuery =
{ context_ngrams :: { ngramsForContextAndListId ::
Args Args
{ context_id :: Var "context_id" Int { contextId :: Var "contextId" Int
, list_id :: Var "list_id" Int , listId :: Var "listId" Int
} }
Unit Unit
} }
contextNgramsQuery :: ContextNgramsQuery getNgramsForContextAndListQuery :: NgramsForContextAndListQuery
contextNgramsQuery = getNgramsForContextAndListQuery =
{ context_ngrams: { ngramsForContextAndListId:
{ context_id: Var :: _ "context_id" Int { contextId: Var :: _ "contextId" Int
, list_id: Var :: _ "list_id" Int , listId: Var :: _ "listId" Int
} =>> unit } =>> unit
} }
......
...@@ -2,7 +2,7 @@ module Gargantext.Components.GraphQL.Endpoints where ...@@ -2,7 +2,7 @@ module Gargantext.Components.GraphQL.Endpoints where
import Data.Array as A import Data.Array as A
import Data.Bifunctor (rmap) import Data.Bifunctor (rmap)
import Data.Either (Either(..)) import Data.Either (Either(..), note)
import Data.Map as Map import Data.Map as Map
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Data.Tuple (Tuple(..)) import Data.Tuple (Tuple(..))
...@@ -12,10 +12,10 @@ import Gargantext.Components.GraphQL.Contact (AnnuaireContact, annuaireContactQu ...@@ -12,10 +12,10 @@ import Gargantext.Components.GraphQL.Contact (AnnuaireContact, annuaireContactQu
import Gargantext.Components.GraphQL.Context as GQLCTX import Gargantext.Components.GraphQL.Context as GQLCTX
import Gargantext.Components.GraphQL.IMT as GQLIMT import Gargantext.Components.GraphQL.IMT as GQLIMT
import Gargantext.Components.GraphQL.NLP as GQLNLP import Gargantext.Components.GraphQL.NLP as GQLNLP
import Gargantext.Components.GraphQL.Node (Corpus, Node, nodeChildrenQuery, nodeParentQuery, nodesQuery, nodesCorpusQuery) import Gargantext.Components.GraphQL.Node (Corpus, Node, getNodeChildrenQuery, getNodeParentQuery, getNodeByIdQuery, getCorpusByIdQuery, getNodesQuery)
import Gargantext.Components.GraphQL.Team (Team, teamQuery) import Gargantext.Components.GraphQL.Team (Team, teamQuery)
import Gargantext.Components.GraphQL.Tree (TreeFirstLevel, treeFirstLevelQuery, BreadcrumbInfo, breadcrumbQuery) import Gargantext.Components.GraphQL.Tree (TreeFirstLevel, getTreeByRootIdQuery, BreadcrumbInfo, breadcrumbQuery)
import Gargantext.Components.GraphQL.User (UserInfo, userInfoQuery, User, userQuery) import Gargantext.Components.GraphQL.User (UserInfo, getUserInfoQuery, User, getUserByIdQuery)
import Gargantext.Components.Lang (Lang) import Gargantext.Components.Lang (Lang)
import Gargantext.Config.REST (RESTError(..), AffRESTError) import Gargantext.Config.REST (RESTError(..), AffRESTError)
import Gargantext.Core.NgramsTable.Types (NgramsTerm(..)) import Gargantext.Core.NgramsTable.Types (NgramsTerm(..))
...@@ -23,8 +23,9 @@ import Gargantext.Prelude ...@@ -23,8 +23,9 @@ import Gargantext.Prelude
import Gargantext.Routes (AppRoute(..)) import Gargantext.Routes (AppRoute(..))
import Gargantext.Sessions (Session(..)) import Gargantext.Sessions (Session(..))
import Gargantext.Types (CorpusId, NodeType) import Gargantext.Types (CorpusId, NodeType)
import Gargantext.Utils.GraphQL (unwrapGraphQLResult)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import GraphQL.Client.Args (onlyArgs) import GraphQL.Client.Args (onlyArgs, OrArg(..), IgnoreArg(..))
import GraphQL.Client.Variables (withVars) import GraphQL.Client.Variables (withVars)
here :: R2.Here here :: R2.Here
...@@ -32,67 +33,50 @@ here = R2.here "Gargantext.Components.GraphQL.Endpoints" ...@@ -32,67 +33,50 @@ here = R2.here "Gargantext.Components.GraphQL.Endpoints"
getIMTSchools :: Session -> AffRESTError (Array GQLIMT.School) getIMTSchools :: Session -> AffRESTError (Array GQLIMT.School)
getIMTSchools session = do getIMTSchools session = do
eRes <- queryGql session "get imt schools" $ GQLIMT.schoolsQuery eRes <- queryGql session "get imt schools" $ GQLIMT.getSchoolsQuery
pure $ rmap _.imt_schools eRes pure $ rmap _.schools eRes
-- liftEffect $ here.log2 "[getIMTSchools] imt_schools" imt_schools -- liftEffect $ here.log2 "[getIMTSchools] imt_schools" imt_schools
-- pure $ Right imt_schools -- pure $ Right imt_schools
getNode :: Session -> Int -> AffRESTError Node getNodeById :: Session -> Int -> AffRESTError Node
getNode session nodeId = do getNodeById session nodeId = do
eRes <- queryGql session "get nodes" $ nodesQuery `withVars` { id: nodeId } let params = { id: nodeId }
case eRes of eRes <- queryGql session "get node" $ getNodeByIdQuery `withVars` params
Left err -> pure $ Left err pure $ _.node <$> eRes
Right { nodes } -> do
-- liftEffect $ here.log2 "[getNode] node" nodes
pure $ case A.head nodes of
Nothing -> Left (CustomError $ "node with id" <> show nodeId <> " not found")
Just node -> Right node
getNodeCorpus :: Session -> Int -> AffRESTError Corpus getCorpusById :: Session -> Int -> AffRESTError Corpus
getNodeCorpus session corpusId = do getCorpusById session corpusId = do
eRes <- queryGql session "get nodes corpus" $ let params = { id: corpusId }
nodesCorpusQuery `withVars` { id: corpusId } eRes <- queryGql session "get corpus by id" $
case eRes of getCorpusByIdQuery `withVars` params
Left err -> pure $ Left err pure $ _.corpus <$> eRes
Right { nodes_corpus } -> do
liftEffect $ here.log2 "[getNodesCorpus] nodes_corpus" nodes_corpus
pure $ case A.head nodes_corpus of
Nothing -> Left (CustomError $ "corpus with id" <> show corpusId <> " not found")
Just corpus -> Right corpus
getNodeParent :: Session -> Int -> NodeType -> AffRESTError (Array Node) getNodeParent :: Session -> Int -> NodeType -> AffRESTError Node
getNodeParent session nodeId parentType = do getNodeParent session nodeId parentType = do
let params = { nodeId, parentType }
eRes <- queryGql session "get node parent" $ eRes <- queryGql session "get node parent" $
nodeParentQuery `withVars` getNodeParentQuery nodeId parentType
{ id: nodeId pure $ unwrapGraphQLResult (Tuple "node parent" params) (_.parent <$> eRes)
, parent_type: parentType
}
-- liftEffect $ here.log2 "[getNodeParent] node_parent" node_parent
--pure node_parent
pure $ rmap _.node_parent eRes
getNodeChildren :: Session -> Int -> NodeType -> AffRESTError (Array Node) getNodeChildren :: Session -> Int -> NodeType -> AffRESTError (Array Node)
getNodeChildren session nodeId childType = do getNodeChildren session nodeId childType = do
eRes <- queryGql session "get node child" $ let
nodeChildrenQuery `withVars` params =
{ id: nodeId { id: nodeId
, child_type: childType , nodeType: childType
} }
eRes <- queryGql session "get node child" $
getNodeChildrenQuery `withVars` params
-- liftEffect $ here.log2 "[getNodeParent] node_parent" node_parent -- liftEffect $ here.log2 "[getNodeParent] node_parent" node_parent
--pure node_parent --pure node_parent
pure $ rmap _.node_children eRes pure $ rmap _.nodes eRes
getUser :: Session -> Int -> AffRESTError User getUser :: Session -> Int -> AffRESTError User
getUser session id = do getUser session id = do
eRes <- queryGql session "get user" $ userQuery `withVars` { id } let params = { id }
case eRes of eRes <- queryGql session "get user by id" $ getUserByIdQuery `withVars` params
Left err -> pure $ Left err pure $ _.user <$> eRes
Right { users } -> do
liftEffect $ here.log2 "[getUser] users" users
pure $ case A.head users of
Nothing -> Left (CustomError $ "user with id " <> show id <> " not found")
Just u -> Right u
updateUserPubmedAPIKey :: Session -> Int -> String -> AffRESTError Unit updateUserPubmedAPIKey :: Session -> Int -> String -> AffRESTError Unit
updateUserPubmedAPIKey session user_id api_key = do updateUserPubmedAPIKey session user_id api_key = do
...@@ -130,45 +114,31 @@ updateUserEPOAPIToken session user_id api_token = do ...@@ -130,45 +114,31 @@ updateUserEPOAPIToken session user_id api_token = do
getUserInfo :: Session -> Int -> AffRESTError UserInfo getUserInfo :: Session -> Int -> AffRESTError UserInfo
getUserInfo session id = do getUserInfo session id = do
eRes <- queryGql session "get user infos" $ userInfoQuery `withVars` { id } eRes <- queryGql session "get user info" $ getUserInfoQuery `withVars` { id }
case eRes of pure $ _.userInfo <$> eRes
Left err -> pure $ Left err
Right { user_infos } -> do
liftEffect $ here.log2 "[getUserInfo] user infos" user_infos
pure $ case A.head user_infos of
Nothing -> Left (CustomError $ "user with id " <> show id <> " not found")
-- NOTE Contact is at G.C.N.A.U.C.Types
Just ui -> Right ui
getAnnuaireContact :: Session -> Int -> AffRESTError AnnuaireContact getAnnuaireContact :: Session -> Int -> AffRESTError AnnuaireContact
getAnnuaireContact session id = do getAnnuaireContact session id = do
let params = { id }
eRes <- queryGql session "get annuaire contact" $ eRes <- queryGql session "get annuaire contact" $
annuaireContactQuery `withVars` { id } annuaireContactQuery `withVars` params
case eRes of pure $ _.annuaireContact <$> eRes
Left err -> pure $ Left err
Right { annuaire_contacts } -> do
liftEffect $ here.log2 "[getAnnuaireContact] data" annuaire_contacts
pure $ case A.head annuaire_contacts of
Nothing -> Left (CustomError $ "contact id=" <> show id <> " not found")
Just r -> Right r
getTreeFirstLevel :: Session -> Int -> AffRESTError TreeFirstLevel getTreeFirstLevel :: Session -> Int -> AffRESTError TreeFirstLevel
getTreeFirstLevel session id = do getTreeFirstLevel session id = do
eRes <- queryGql session "get tree first level" $ treeFirstLevelQuery `withVars` { id } let params = { id }
case eRes of eRes <- queryGql session "get tree first level" $
Left err -> pure $ Left err getTreeByRootIdQuery id
Right { tree } -> do -- getTreeByRootIdQuery `withVars` params
-- liftEffect $ here.log2 "[getTreeFirstLevel] tree first level" tree pure $ (\{ root, children, parents } -> { root, children, parent: A.head parents }) <$> eRes
pure $ Right tree -- TODO: error handling
-- pure $ (\{ root } -> { root, children: [], parent: Nothing }) <$> eRes
getTeam :: Session -> Int -> AffRESTError Team getTeam :: Session -> Int -> AffRESTError Team
getTeam session id = do getTeam session id = do
eRes <- queryGql session "get team" $ teamQuery `withVars` { id } let params = { id }
case eRes of eRes <- queryGql session "get team" $ teamQuery `withVars` params
Left err -> pure $ Left err pure $ _.team <$> eRes
Right { team } -> do
liftEffect $ here.log2 "[getTree] data" team
pure $ Right team
type SharedFolderId = Int type SharedFolderId = Int
type TeamNodeId = Int type TeamNodeId = Int
...@@ -194,29 +164,25 @@ deleteTeamMembership session sharedFolderId teamNodeId = do ...@@ -194,29 +164,25 @@ deleteTeamMembership session sharedFolderId teamNodeId = do
getToken (Session { token }) = token getToken (Session { token }) = token
getNodeContext :: Session -> Int -> Int -> AffRESTError GQLCTX.NodeContext getNodeContext :: Session -> Int -> Int -> AffRESTError GQLCTX.NodeContext
getNodeContext session context_id node_id = do getNodeContext session contextId nodeId = do
let query = GQLCTX.nodeContextQuery `withVars` { context_id, node_id } let params = { contextId, nodeId }
eRes <- queryGql session "get node context" query eRes <- queryGql session "get context by id and node" $
case eRes of GQLCTX.getContextByIdAndNodeQuery `withVars` params
Left err -> pure $ Left err pure $ _.context <$> eRes
Right { contexts } -> do
--liftEffect $ here.log2 "[getNodeContext] node context" contexts
case A.head contexts of
Nothing -> pure $ Left $ CustomError "no node context found"
Just context -> pure $ Right context -- TODO: error handling
type ContextsForNgramsGQL = { contexts_for_ngrams :: Array GQLCTX.Context } type ContextsForNgramsGQL = { contextsForNgrams :: Array GQLCTX.Context }
getContextsForNgrams :: Session -> CorpusId -> Array String -> Boolean -> AffRESTError (Array GQLCTX.Context) getContextsForNgrams :: Session -> CorpusId -> Array String -> Boolean -> AffRESTError (Array GQLCTX.Context)
getContextsForNgrams session corpus_id ngrams_terms logic = do getContextsForNgrams session corpus_id ngrams_terms logic = do
let let
query = GQLCTX.contextsForNgramsQuery `withVars` params =
{ corpus_id { corpus_id
, ngrams_terms: GQLCTX.NgramsTerms ngrams_terms , ngrams_terms: GQLCTX.NgramsTerms ngrams_terms
, and_logic: show logic , and_logic: show logic
} }
query = GQLCTX.getContextsForNgramsQuery `withVars` params
eRes <- queryGql session "get contexts for ngrams" query eRes <- queryGql session "get contexts for ngrams" query
pure $ rmap _.contexts_for_ngrams eRes pure $ rmap _.contextsForNgrams eRes
updateNodeContextCategory :: Session -> Int -> Int -> Int -> AffRESTError Int updateNodeContextCategory :: Session -> Int -> Int -> Int -> AffRESTError Int
updateNodeContextCategory session context_id node_id category = do updateNodeContextCategory session context_id node_id category = do
...@@ -238,21 +204,16 @@ getLanguages :: Session -> AffRESTError (Map.Map Lang GQLNLP.LanguageProperties) ...@@ -238,21 +204,16 @@ getLanguages :: Session -> AffRESTError (Map.Map Lang GQLNLP.LanguageProperties)
getLanguages session = do getLanguages session = do
let query = GQLNLP.nlpQuery let query = GQLNLP.nlpQuery
eRes <- queryGql session "get languages" query eRes <- queryGql session "get languages" query
case eRes of pure $ (\res -> Map.fromFoldable $ (\{ lt_lang, lt_server } -> Tuple lt_lang lt_server) <$> res.languages) <$> eRes
Left err -> pure $ Left err
Right { languages } -> do
liftEffect $ here.log2 "[getLanguages] languages" languages
pure $ Right $ Map.fromFoldable $ (\{ lt_lang, lt_server } -> Tuple lt_lang lt_server) <$> languages
getContextNgrams :: Session -> Int -> Int -> AffRESTError (Array NgramsTerm) getNgramsForContextAndList :: Session -> Int -> Int -> AffRESTError (Array NgramsTerm)
getContextNgrams session context_id list_id = do getNgramsForContextAndList session contextId listId = do
let query = GQLCTX.contextNgramsQuery `withVars` { context_id, list_id } let query = GQLCTX.getNgramsForContextAndListQuery `withVars` { contextId, listId }
eRes <- queryGql session "get context ngrams" query eRes <- queryGql session "get ngrams for context and list" query
pure $ rmap (\{ context_ngrams } -> NormNgramsTerm <$> context_ngrams) eRes pure $ rmap (\{ ngramsForContextAndListId } -> NormNgramsTerm <$> ngramsForContextAndListId) eRes
getBreadcrumb :: Session -> Int -> AffRESTError BreadcrumbInfo getBreadcrumb :: Session -> Int -> AffRESTError BreadcrumbInfo
getBreadcrumb session node_id = do getBreadcrumb session nodeId = do
eRes <- queryGql session "get breadcrumb branch" $ breadcrumbQuery `withVars` { node_id } eRes <- queryGql session "get breadcrumb branch" $ breadcrumbQuery nodeId
-- liftEffect $ here.log2 "[getBreadcrumb] breadcrumb" tree_branch -- liftEffect $ here.log2 "[getBreadcrumb] breadcrumb" tree_branch
pure $ rmap _.tree_branch eRes pure $ eRes
...@@ -11,15 +11,15 @@ type School = ...@@ -11,15 +11,15 @@ type School =
} }
type SchoolsQuery = type SchoolsQuery =
{ imt_schools :: { schools ::
{ school_id :: Unit { school_id :: Unit
, school_longName :: Unit , school_longName :: Unit
, school_shortName :: Unit , school_shortName :: Unit
} }
} }
schoolsQuery :: SchoolsQuery getSchoolsQuery :: SchoolsQuery
schoolsQuery = getSchoolsQuery =
{ imt_schools: { schools:
GGQL.getFieldsStandard (Proxy :: _ School) GGQL.getFieldsStandard (Proxy :: _ School)
} }
module Gargantext.Components.GraphQL.Node where module Gargantext.Components.GraphQL.Node where
import Data.Maybe (Maybe(..))
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Types (NodeType) import Gargantext.Types (NodeType)
import Gargantext.Utils.GraphQL as GGQL import Gargantext.Utils.GraphQL as GGQL
import Gargantext.Types (NodeType) import Gargantext.Types (NodeType)
import GraphQL.Client.Args (Args, (=>>)) import GraphQL.Client.Alias ((:))
import GraphQL.Client.Args (Args, (=>>), OrArg(..), IgnoreArg(..))
import GraphQL.Client.Variable (Var(..)) import GraphQL.Client.Variable (Var(..))
import Type.Proxy (Proxy(..)) import Type.Proxy (Proxy(..))
type Corpus = type Corpus =
{ id :: Int { id :: Int
, name :: String , name :: String
, parent_id :: Int , parent_id :: Maybe Int
, type_id :: Int , type_id :: Int
, node_type :: NodeType , node_type :: NodeType
} }
...@@ -19,59 +21,88 @@ type Corpus = ...@@ -19,59 +21,88 @@ type Corpus =
type Node = type Node =
{ id :: Int { id :: Int
, name :: String , name :: String
, parent_id :: Int , parent_id :: Maybe Int
, type_id :: Int , type_id :: Int
, node_type :: NodeType , node_type :: NodeType
} }
type NodesCorpusQuery = type NodeQ =
{ nodes_corpus ::
Args
{ corpus_id :: Var "id" Int }
{ id :: Unit { id :: Unit
, name :: Unit , name :: Unit
, parent_id :: Unit , parent_id :: Unit
, type_id :: Unit , type_id :: Unit
, node_type :: Unit , node_type :: Unit
} }
nodeQ :: NodeQ
nodeQ = GGQL.getFieldsStandard (Proxy :: _ Node)
type CorpusByIdQuery =
{ corpus ::
Args
{ id :: Var "id" Int }
NodeQ
} }
type NodesQuery = type NodeByIdQuery =
{ nodes :: { node ::
Args Args
{ node_id :: Var "id" Int } { id :: Var "id" Int }
{ id :: Unit NodeQ
, name :: Unit
, parent_id :: Unit
, type_id :: Unit
, node_type :: Unit
} }
getNodeByIdQuery :: NodeByIdQuery
getNodeByIdQuery =
{ node: { id: Var :: _ "id" Int } =>> nodeQ
} }
nodesQuery :: NodesQuery type NodesQueryArgs =
nodesQuery = { parentId :: OrArg IgnoreArg Int
{ nodes: { node_id: Var :: _ "id" Int } =>> , containsChildId :: OrArg IgnoreArg Int
GGQL.getFieldsStandard (Proxy :: _ Node) , nodeType :: OrArg IgnoreArg NodeType
} }
nodesCorpusQuery :: NodesCorpusQuery type NodesQuery =
nodesCorpusQuery = { nodes :: Args NodesQueryArgs NodeQ }
{ nodes_corpus: { corpus_id: Var :: _ "id" Int } =>>
getNodesQuery :: NodesQueryArgs -> NodesQuery
getNodesQuery args =
{ nodes: args =>> nodeQ }
-- getNodesQuery :: Maybe Int -> Maybe Int -> NodesQuery
-- getNodesQuery mParentId mChildId =
-- { nodes: { parentId: mVar mParentId
-- , containsChildId: mVar mChildId } =>>
-- -- , nodeType: Var :: _ "nodeType" (Maybe NodeType) } =>>
-- nodeQ
-- }
-- where
-- mVar Nothing = ArgL IgnoreArg
-- mVar (Just x) = ArgR x
getCorpusByIdQuery :: CorpusByIdQuery
getCorpusByIdQuery =
{ corpus: { id: Var :: _ "id" Int } =>>
GGQL.getFieldsStandard (Proxy :: _ Corpus) GGQL.getFieldsStandard (Proxy :: _ Corpus)
} }
nodeParentQuery = getNodeParentQuery id nodeType =
{ node_parent: { parent:
{ node_id: Var :: _ "id" Int nodes
, parent_type: Var :: _ "parent_type" NodeType :
} =>> { containsChildId: id
GGQL.getFieldsStandard (Proxy :: _ Node) , nodeType: nodeType
}
=>>
nodeQ
} }
where
nodes = Proxy :: Proxy "nodes"
nodeChildrenQuery = getNodeChildrenQuery =
{ node_children: { nodes:
{ node_id: Var :: _ "id" Int { parentId: Var :: _ "id" Int
, child_type: Var :: _ "child_type" NodeType , nodeType: Var :: _ "nodeType" NodeType
} =>> } =>>
GGQL.getFieldsStandard (Proxy :: _ Node) nodeQ
} }
module Gargantext.Components.GraphQL.Tree where module Gargantext.Components.GraphQL.Tree where
import Data.Maybe (Maybe(..))
import Gargantext.Components.GraphQL.Node (Node, NodeQ, nodeQ, getNodeByIdQuery, getNodesQuery)
import Gargantext.Prelude import Gargantext.Prelude
import Data.Maybe (Maybe)
import Gargantext.Routes (AppRoute) import Gargantext.Routes (AppRoute)
import Gargantext.Types (NodeType) import Gargantext.Types (NodeType)
import GraphQL.Client.Args ((=>>)) import Gargantext.Utils.GraphQL as GGQL
import GraphQL.Client.Alias ((:), Alias)
import GraphQL.Client.Args ((=>>), Args, OrArg(ArgR), IgnoreArg)
import GraphQL.Client.Variable (Var(..)) import GraphQL.Client.Variable (Var(..))
import Type.Proxy (Proxy(..))
type TreeNode =
{ name :: String
, id :: Int
, node_type :: NodeType
, parent_id :: Maybe Int
}
type TreeFirstLevel = type TreeFirstLevel =
{ root :: TreeNode { root :: Node
, children :: Array TreeNode , children :: Array Node
, parent :: Maybe TreeNode , parent :: Maybe Node
} }
type BreadcrumbInfo = type BreadcrumbInfo =
{ parents :: Array TreeNode } { parents :: Array Node }
treeFirstLevelQuery = -- | This is a composite query that is composed of calling "node" and
{ tree: { root_id: Var :: _ "id" Int } =>> -- | "nodes" with appropriate arguments.
{ root: getTreeByRootIdQuery
{ name: unit :: Int
, node_type: unit -> { root ::
, id: unit Alias (Proxy "node")
, parent_id: unit ( Args
{ id :: Int }
NodeQ
)
, children ::
Alias (Proxy "nodes")
( Args
{ parentId :: Int }
NodeQ
)
, parents ::
Alias (Proxy "nodes")
( Args
{ containsChildId :: Int }
NodeQ
)
} }
getTreeByRootIdQuery id =
{ root:
node : { id: id } =>> nodeQ
, children: , children:
{ name: unit nodes : { parentId: id } =>> nodeQ
, node_type: unit , parents:
, id: unit nodes : { containsChildId: id } =>> nodeQ
, parent_id: unit
}
, parent:
{ name: unit
, node_type: unit
, id: unit
, parent_id: unit
}
}
} }
where
node = Proxy :: Proxy "node"
nodes = Proxy :: Proxy "nodes"
breadcrumbQuery = breadcrumbQuery
{ tree_branch: { node_id: Var :: _ "node_id" Int } =>> :: Int
{ parents: -> { parents ::
{ name: unit Alias (Proxy "nodes")
, node_type: unit ( Args
, id: unit { deepChildId :: Int }
, parent_id: unit NodeQ
} )
} }
breadcrumbQuery id =
{ parents:
nodes : { deepChildId: id } =>>
nodeQ
} }
where
nodes = Proxy :: Proxy "nodes"
...@@ -47,8 +47,8 @@ type UserInfoM = ...@@ -47,8 +47,8 @@ type UserInfoM =
, ui_cwDescription :: String , ui_cwDescription :: String
} }
userInfoQuery = getUserInfoQuery =
{ user_infos: { user_id: Var :: _ "id" Int } =>> { userInfo: { userId: Var :: _ "id" Int } =>>
{ ui_id: unit { ui_id: unit
, ui_username: unit , ui_username: unit
, ui_email: unit , ui_email: unit
...@@ -178,8 +178,8 @@ showUser ...@@ -178,8 +178,8 @@ showUser
showMUser u = maybe "" showUser u showMUser u = maybe "" showUser u
userQuery = getUserByIdQuery =
{ users: { user_id: Var :: _ "id" Int } =>> { user: { id: Var :: _ "id" Int } =>>
{ u_id: unit { u_id: unit
, u_hyperdata: , u_hyperdata:
{ shared: { shared:
......
...@@ -6,7 +6,7 @@ import Data.Maybe (Maybe(..), isJust) ...@@ -6,7 +6,7 @@ import Data.Maybe (Maybe(..), isJust)
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
import Gargantext.Components.Bootstrap as B import Gargantext.Components.Bootstrap as B
import Gargantext.Components.Corpus.Layout (layout) import Gargantext.Components.Corpus.Layout (layout)
import Gargantext.Components.GraphQL.Endpoints (getNode) import Gargantext.Components.GraphQL.Endpoints (getNodeById)
import Gargantext.Config.REST (logRESTError) import Gargantext.Config.REST (logRESTError)
import Gargantext.Hooks.Loader (useLoaderEffect) import Gargantext.Hooks.Loader (useLoaderEffect)
import Gargantext.Hooks.Session (useSession) import Gargantext.Hooks.Session (useSession)
...@@ -39,7 +39,7 @@ nodeCpt = here.component "node" cpt ...@@ -39,7 +39,7 @@ nodeCpt = here.component "node" cpt
let let
errorHandler = logRESTError (R2.herePrefix here "[corpusLayout]") errorHandler = logRESTError (R2.herePrefix here "[corpusLayout]")
loader { nodeId: nodeId_, session: session_ } = getNode session_ nodeId_ loader { nodeId: nodeId_, session: session_ } = getNodeById session_ nodeId_
-- | Hooks -- | Hooks
-- | -- |
......
...@@ -21,6 +21,7 @@ import Gargantext.Utils.Glyphicon (classNamePrefix, glyphiconToCharCode) ...@@ -21,6 +21,7 @@ import Gargantext.Utils.Glyphicon (classNamePrefix, glyphiconToCharCode)
import Gargantext.Utils.SimpleJSON (encodeJsonArgonaut) import Gargantext.Utils.SimpleJSON (encodeJsonArgonaut)
import GraphQL.Client.Args (class ArgGql) import GraphQL.Client.Args (class ArgGql)
import GraphQL.Client.GqlType (class GqlType) import GraphQL.Client.GqlType (class GqlType)
import GraphQL.Client.ToGqlString (class GqlArgString)
import Prim.Row (class Union) import Prim.Row (class Union)
import Reactix as R import Reactix as R
import Simple.JSON as JSON import Simple.JSON as JSON
...@@ -198,6 +199,8 @@ instance Argonaut.EncodeJson NodeType where ...@@ -198,6 +199,8 @@ instance Argonaut.EncodeJson NodeType where
-- instance ArgGql String NodeType -- instance ArgGql String NodeType
-- instance ArgGql NodeType NodeType -- instance ArgGql NodeType NodeType
instance GqlType NodeType "NodeType!" instance GqlType NodeType "NodeType!"
instance GqlArgString NodeType where
toGqlArgStringImpl = show
instance Show NodeType where instance Show NodeType where
show NodeUser = "NodeUser" show NodeUser = "NodeUser"
......
...@@ -5,12 +5,18 @@ module Gargantext.Utils.GraphQL ...@@ -5,12 +5,18 @@ module Gargantext.Utils.GraphQL
( class GetFieldsStandard ( class GetFieldsStandard
, PropGetFieldsStandard , PropGetFieldsStandard
, getFieldsStandard , getFieldsStandard
, unwrapGraphQLResult
) where ) where
import Prelude import Prelude
import Data.Array as A
import Data.Bifunctor (rmap)
import Data.Either (Either(..), note)
import Data.HeytingAlgebra (class HeytingAlgebraRecord, tt) import Data.HeytingAlgebra (class HeytingAlgebraRecord, tt)
import Data.Maybe (Maybe) import Data.Maybe (Maybe)
import Data.Tuple (Tuple(..))
import Gargantext.Config.REST (RESTError(CustomError))
import Heterogeneous.Mapping (class HMap, class Mapping, hmap) import Heterogeneous.Mapping (class HMap, class Mapping, hmap)
import Prim.RowList (class RowToList) import Prim.RowList (class RowToList)
import Type.Proxy (Proxy(..)) import Type.Proxy (Proxy(..))
...@@ -54,3 +60,15 @@ instance propGetFieldsStandard :: ...@@ -54,3 +60,15 @@ instance propGetFieldsStandard ::
) => ) =>
Mapping PropGetFieldsStandard t fields where Mapping PropGetFieldsStandard t fields where
mapping PropGetFieldsStandard _ = getFieldsStandard (Proxy :: _ t) mapping PropGetFieldsStandard _ = getFieldsStandard (Proxy :: _ t)
-- | GraphQL returns an Either Error a result type and one usually has to get the head of a
unwrapGraphQLResult
:: forall a params
. (Show params)
=> Tuple String params
-> Either RESTError (Array a)
-> Either RESTError a
unwrapGraphQLResult _ (Left err) = Left err
unwrapGraphQLResult (Tuple name params) (Right res) =
note (CustomError $ "[unwrapGraphQLResult] " <> name <> " with params " <> show params <> " not found")
(A.head res)
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