Commit a8ea25ac authored by Przemyslaw Kaminski's avatar Przemyslaw Kaminski

Merge branch 'dev-search-removal' into feature/sigmax-graph-explorer

parents 80479a93 a00f9694
...@@ -8,11 +8,15 @@ ...@@ -8,11 +8,15 @@
/.purs* /.purs*
/.psa* /.psa*
/.spago /.spago
bundle.js
# webpack splays purescript modules in dist. we don't want these to be
# added, but we do want static assets to be added
/dist/* /dist/*
!/dist/styles/ !/dist/styles/
/dist/styles/*map
!/dist/examples/ !/dist/examples/
!/dist/fonts/ !/dist/fonts/
!/dist/images/ !/dist/images/
!/dist/js/ !/dist/js/
/dist/styles/*map # css source maps
\ No newline at end of file /dist/styles/*map
...@@ -37,8 +37,25 @@ curl -sL https://deb.nodesource.com/setup_11.x | sudo bash - ...@@ -37,8 +37,25 @@ curl -sL https://deb.nodesource.com/setup_11.x | sudo bash -
sudo apt update && sudo apt install nodejs sudo apt update && sudo apt install nodejs
``` ```
On Mac OS (with Homebrew): (For Ubuntu)
```shell
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt update && sudo apt install yarn
```
To upgrade to latest version (and not current stable) version, you can use
(Use n module from npm in order to upgrade node)
```shell
sudo npm cache clean -f
sudo npm install -g n
sudo n stable
sudo n latest
```
### OSX
```shell ```shell
brew install node brew install node
``` ```
...@@ -88,7 +105,43 @@ Or run a repl: ...@@ -88,7 +105,43 @@ Or run a repl:
yarn repl yarn repl
``` ```
To test in the browser, you need to build a browser bundle: ```shell
yarn install && yarn ps-deps
```
### Running a dev server
```shell
yarn dev
```
This will launch a hot-reloading development server with
webpack-dev-server. Visit [localhost:9000](http://localhost:9000/) to
see the result when the output shows a line like this:
```
ℹ 「wdm」: Compiled successfully.
```
#### Purescript IDE integration
A `purs ide` connection will be available on port 9002 while the
development server is running.
A guide to getting set up with the IDE integration is beyond the scope
of this document.
#### Source maps
Currently broken. Someone please fix them.
### Getting a purescript repl
```shell
yarn repl
```
### Building for production
```shell ```shell
yarn build yarn build
...@@ -108,6 +161,24 @@ Examples: ...@@ -108,6 +161,24 @@ Examples:
<!-- yarn live --> <!-- yarn live -->
<!-- ``` --> <!-- ``` -->
Note that a production build takes a little while.
### How do I?
#### Change which backend to connect to?
Edit `Config.purs`. Find the function `endConfig'` just after the
imports and edit `back`. The definitions are not far below, just after
the definitions of the various `front` options.
Example (using `demo.gargantext.org` as backend):
```
endConfig' :: ApiVersion -> EndConfig
endConfig' v = { front : frontRelative
, back : backDemo v }
```
## Note to the contributors ## Note to the contributors
Please follow CONTRIBUTING.md Please follow CONTRIBUTING.md
......
{
"name": "purescript-gargantext",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"output"
],
"dependencies": {
"purescript-console": "^4.1.0",
"purescript-thermite": "https://github.com/np/purescript-thermite.git#cf194360c8ee440978a2b342382fc3fddc65b39e",
"purescript-affjax": "^7.0.0",
"purescript-routing": "^8.0.0",
"purescript-argonaut": "^4.0.1",
"purescript-random": "^4.0.0",
"purescript-css": "^4.0.0"
},
"devDependencies": {
"purescript-psci-support": "^4.0.0"
},
"resolutions": {
"purescript-react": "exports",
"purescript-profunctor-lenses": "^4.0.0"
}
}
#!/bin/bash
yarn install && yarn rebuild-set && yarn install-ps && yarn pulp --psc-package build && yarn pulp --psc-package browserify --to dist/bundle.js
...@@ -4,13 +4,12 @@ ...@@ -4,13 +4,12 @@
<meta charset="utf-8"/> <meta charset="utf-8"/>
<title>CNRS GarganText</title> <title>CNRS GarganText</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://use.fontawesome.com/releases/v5.0.8/css/all.css" rel="stylesheet"> <link href="https://use.fontawesome.com/releases/v5.0.8/styles/all.css" rel="stylesheet">
<link href="styles/login.min.css" rel="stylesheet"> <link href="styles/login.min.css" rel="stylesheet">
<link href="styles/bootstrap.min.css" rel="stylesheet"> <link href="styles/bootstrap.min.css" rel="stylesheet">
<!-- <link href="css/lavish-bootstrap.css" rel="stylesheet"> --> <!-- <link href="styles/lavish-bootstrap.css" rel="stylesheet"> -->
<link rel="stylesheet" type="text/css" href="styles/menu.css"/>
<link rel="stylesheet" type="text/css" href="styles/context-menu.css"/> <link rel="stylesheet" type="text/css" href="styles/context-menu.css"/>
<link rel="stylesheet" type="text/css" href="styles/annotation.css"/> <link rel="stylesheet" type="text/css" href="styles/menu.css"/>
<link href="styles/Login.css" rel="stylesheet"> <link href="styles/Login.css" rel="stylesheet">
<style> <style>
* {margin: 0; padding: 0; list-style: none;} * {margin: 0; padding: 0; list-style: none;}
...@@ -54,7 +53,7 @@ ...@@ -54,7 +53,7 @@
background-color: "#000"; background-color: "#000";
top: 12px; top: 12px;
} }
</style> </style>
</head> </head>
<body> <body>
<div id="app" class ="container-fluid"></div> <div id="app" class ="container-fluid"></div>
......
// This file is just a wrapper so that webpack will call our main function
require('./Main.purs').main();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- lib CSS -->
<link rel="stylesheet" type="text/css" href="./lib/css/qlobbe.css">
<!-- lib JS -->
<script type="text/javascript" src="./lib/js/jquery-3.4.1.min.js"></script>
<script type="text/javascript" src="./lib/js/bootstrap.min.js"></script>
<script type="text/javascript" src="./lib/js/d3.min.js"></script>
<title>Mèmiescape</title>
</head>
<body>
<div id="main">
<div id="viz"></div>
</div>
<script type="text/javascript">
/*
* Draw functions
*/
function draw(phyloData) {
// set up margin
var margin = {t:0, r:30, b:15, l:0};
var w = document.getElementById("viz").offsetWidth - margin.l - margin.r,
h = $(window).height() - margin.t - margin.b;
// draw svg view
var svg = d3.select("#viz").append("svg")
.attr("width",w)
.attr("height",h);
var g = svg.append("g").attr("id","svg-view");
// draw phylomemy from an url
d3.xml(phyloData).then(data => {
var newNodes = document.importNode(data.documentElement,true);
svg.attr("viewBox", newNodes.getAttribute("viewBox"));
g.each(function(){
this.appendChild(newNodes);
})
svg.call(zoom)
d3.select("#viz")
.append('button')
.attr("type","button")
.attr("id","btn_reset")
.attr("class","btn btn-light")
.text("reset");
d3.select("#btn_reset").on("click", reset);
})
// set up d3 zoom
var transform = d3.zoomIdentity;
zoom = d3.zoom()
.scaleExtent([1, 50])
.on("zoom", zoomed);
function zoomed() {
g.attr("transform", d3.event.transform);
}
function reset() {
svg.transition().call(zoom.transform, d3.zoomIdentity);
}
}
/*
* Control functions
*/
window.onload = function() {
clean()
var url = window.location.href;
// console.log(url);
readUrl(url)
};
/* Get a Phylo file from an URL */
function readUrl(url) {
var node = url.match(/nodeId=(.*)/);
if (node != null) {
fetch("http://localhost:8008" + "/api/v1.0/node/" + node[1] + "/phylo")
//fetch("https://dev.gargantext.org" + "/api/v1.0/node/" + node[1] + "/phylo")
//fetch(window.location.origin + "/api/v1.0/node/" + node[1] + "/phylo")
.then(res => res.blob())
.then(blob => {
var reader = new FileReader();
reader.onload = (function(phyloFile) {
return function(e) {
draw(e.target.result)
};
})(blob);
reader.readAsDataURL(blob);
});
} else {
try {
throw new Error("Unable to find a nodeId");
} catch (e) {
console.log(e.name + ": " + e.message);
}
}
}
/* Clean the view each time you load a new phylomemy */
function clean() {
d3.select("svg").remove();
d3.select("#btn_reset").remove();
}
</script>
</body>
</html>
html,body {
height: 100%;
}
hr {
border-color: #555555;
}
.alert-label {
margin-bottom: 0px;
}
.custom-file-label {
overflow: hidden;
border-color: rgb(101, 101, 127);
}
.drop-down-menu, .drop-down-menu:hover, .drop-down-menu:active, .drop-down-menu:focus {
color: #0d1824;
outline: 0;
}
.rotate {
-moz-transition: all .15s linear;
-webkit-transition: all .15s linear;
transition: all .15s linear;
}
.rotate.down {
-moz-transform:rotate(90deg);
-webkit-transform:rotate(90deg);
transform:rotate(90deg);
}
.title {
color: #0d1824;
font-family: 'Montserrat', sans-serif;
text-rendering: optimizeLegibility;
font-weight: 600;
font-style: normal;
}
#btn_draw {
background-color: #63c4e2;
border-color: rgb(101, 101, 127);
}
#btn_reset {
position: absolute;
left: 15px;
top: 15px;
border-color: #555555;
}
#layer-radio {
display: none;
list-style-type: none;
padding-left: 5px;
padding-top: 10px;
}
#left_view {
padding-top: 15px;
background-color: rgb(240, 240, 243);
border-right: 1px solid #555555;
color: #0d1824;
font-family: 'Open Sans', sans-serif;
text-rendering: optimizeLegibility;
}
#options {
display: none;
}
#processing {
color: #0d1824;
background-color: rgb(240, 240, 243);
border-color: rgb(101, 101, 127);
display: none;
}
#right_view {
padding-top: 15px;
background-color: #FFF;
position: relative;
}
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
...@@ -219,3 +219,7 @@ text-align: center; ...@@ -219,3 +219,7 @@ text-align: center;
padding-left: 0 !important; padding-left: 0 !important;
padding-right: 0 !important; padding-right: 0 !important;
} }
.tab-pane .reload-btn {
padding-right: 6px;
}
#!/bin/bash
echo "Upgrading nodeJS"
sudo npm cache clean -f
sudo npm install -g n
sudo n stable
sudo n latest
echo "Installing yarn"
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt update
sudo apt install yarn
./build
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
"install-ps": "psc-package install", "install-ps": "psc-package install",
"compile": "pulp --psc-package build", "compile": "pulp --psc-package build",
"build": "pulp --psc-package browserify -t dist/bundle.js", "build": "pulp --psc-package browserify -t dist/bundle.js",
"dev": "webpack-dev-server --env dev --mode development",
"repl": "pulp --psc-package repl", "repl": "pulp --psc-package repl",
"clean": "rm -Rf output" "clean": "rm -Rf output"
}, },
...@@ -20,6 +21,9 @@ ...@@ -20,6 +21,9 @@
"react-dom": "^16.8.6", "react-dom": "^16.8.6",
"sigma": "git://github.com/jjl/sigma.js#garg" "sigma": "git://github.com/jjl/sigma.js#garg"
}, },
"eslintConfig": {
"extends": "react-app"
},
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.1.5", "@babel/cli": "^7.1.5",
"@babel/core": "^7.1.6", "@babel/core": "^7.1.6",
...@@ -27,13 +31,30 @@ ...@@ -27,13 +31,30 @@
"@babel/preset-react": "^7.0.0", "@babel/preset-react": "^7.0.0",
"@babel/preset-stage-2": "^7.0.0", "@babel/preset-stage-2": "^7.0.0",
"babel-core": "^7.0.0-bridge", "babel-core": "^7.0.0-bridge",
"babel-loader": "^8.0.4",
"clean-webpack-plugin": "^1.0.0",
"css-loader": "^2.1.0",
"envify": "^4.1.0", "envify": "^4.1.0",
"executive": "^1.6.3",
"file-loader": "^3.0.1",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^4.0.0-beta.5",
"http-server": "^0.11.1", "http-server": "^0.11.1",
"mini-css-extract-plugin": "^0.5.0",
"psc-package": "^3.0.1", "psc-package": "^3.0.1",
"pulp": "^12.4.0", "pulp": "^12.4.0",
"purescript": "^0.12.4", "purescript": "^0.12.4",
"purs-loader": "^3.3.0",
"react-testing-library": "^6.1.2", "react-testing-library": "^6.1.2",
"spago": "^0.7.5" "source-map-loader": "^0.2.4",
}, "spago": "^0.7.5",
"version": "0.0.0" "style-loader": "^0.23.1",
"uglify-js": "^3.4.9",
"uglifyify": "^5.0.1",
"webpack": "^4.26.0",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.10",
"webpack-node-externals": "^1.7.2",
"xhr2": "^0.1.4"
}
} }
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
"argonaut", "argonaut",
"console", "console",
"css", "css",
"debug",
"dom-filereader", "dom-filereader",
"dom-simple", "dom-simple",
"effect", "effect",
......
#!/bin/bash
rm -rf .psc-package output bower_components node_modules
./build
#!/bin/bash
yarn repl
...@@ -15,6 +15,7 @@ import Prelude ...@@ -15,6 +15,7 @@ import Prelude
import Data.Lens ((^?), _Just) import Data.Lens ((^?), _Just)
import Data.Lens.At (at) import Data.Lens.At (at)
import Data.Maybe ( Maybe(..), maybe, maybe' ) import Data.Maybe ( Maybe(..), maybe, maybe' )
import Data.String.Regex as R
import Data.String as S import Data.String as S
import Data.Tuple ( Tuple(..) ) import Data.Tuple ( Tuple(..) )
import Data.Tuple.Nested ( (/\) ) import Data.Tuple.Nested ( (/\) )
...@@ -25,9 +26,10 @@ import Reactix as R ...@@ -25,9 +26,10 @@ import Reactix as R
import Reactix.DOM.HTML as HTML import Reactix.DOM.HTML as HTML
import Reactix.SyntheticEvent as E import Reactix.SyntheticEvent as E
import Gargantext.Config (CTabNgramType(..))
import Gargantext.Types ( TermList ) import Gargantext.Types ( TermList )
import Gargantext.Components.Annotation.Utils ( termBootstrapClass ) import Gargantext.Components.Annotation.Utils ( termBootstrapClass )
import Gargantext.Components.NgramsTable.Core ( NgramsTerm, NgramsTable(..), _NgramsElement, _list, highlightNgrams ) import Gargantext.Components.NgramsTable.Core ( NgramsTerm, NgramsTable(..), _NgramsElement, _list, highlightNgrams, findNgramTermList )
import Gargantext.Components.Annotation.Menu ( AnnotationMenu, annotationMenu, MenuType(..) ) import Gargantext.Components.Annotation.Menu ( AnnotationMenu, annotationMenu, MenuType(..) )
import Gargantext.Utils.Selection as Sel import Gargantext.Utils.Selection as Sel
...@@ -58,7 +60,7 @@ annotatedFieldComponent = R.hooksComponent "AnnotatedField" cpt ...@@ -58,7 +60,7 @@ annotatedFieldComponent = R.hooksComponent "AnnotatedField" cpt
let x = E.clientX event let x = E.clientX event
y = E.clientY event y = E.clientY event
setList t = do setList t = do
setTermList (S.toLower text') (Just list) t setTermList text' (Just list) t
setMenu (const Nothing) setMenu (const Nothing)
setMenu (const $ Just {x, y, list: Just list, menuType: SetTermListItem, setList} ) setMenu (const $ Just {x, y, list: Just list, menuType: SetTermListItem, setList} )
...@@ -79,7 +81,7 @@ maybeShowMenu setMenu setTermList ngrams event = do ...@@ -79,7 +81,7 @@ maybeShowMenu setMenu setTermList ngrams event = do
sel' -> do sel' -> do
let x = E.clientX event let x = E.clientX event
y = E.clientY event y = E.clientY event
list = findNgram ngrams sel' list = findNgramTermList CTabTerms ngrams sel'
setList t = do setList t = do
setTermList sel' list t setTermList sel' list t
setMenu (const Nothing) setMenu (const Nothing)
...@@ -96,10 +98,7 @@ maybeAddMenu setMenu e (Just props) = annotationMenu setMenu props <> e ...@@ -96,10 +98,7 @@ maybeAddMenu setMenu e (Just props) = annotationMenu setMenu props <> e
maybeAddMenu _ e _ = e maybeAddMenu _ e _ = e
compile :: NgramsTable -> Maybe String -> Array (Tuple String (Maybe TermList)) compile :: NgramsTable -> Maybe String -> Array (Tuple String (Maybe TermList))
compile ngrams = maybe [] (highlightNgrams ngrams) compile ngrams = maybe [] (highlightNgrams CTabTerms ngrams)
findNgram :: NgramsTable -> String -> Maybe TermList
findNgram (NgramsTable m) s = m ^? at s <<< _Just <<< _NgramsElement <<< _list
-- Runs -- Runs
......
...@@ -49,6 +49,6 @@ addToList {menuType, setList} t = Just $ CM.contextMenuItem [ link ] ...@@ -49,6 +49,6 @@ addToList {menuType, setList} t = Just $ CM.contextMenuItem [ link ]
where where
link = HTML.a { onClick: click, className: className } [ HTML.text (label menuType) ] link = HTML.a { onClick: click, className: className } [ HTML.text (label menuType) ]
label NewNgram = "Add to " <> termListName t label NewNgram = "Add to " <> termListName t
label SetTermListItem = "Change to" <> termListName t label SetTermListItem = "Change to " <> termListName t
className = "list-group-item list-group-item-" <> (termBootstrapClass t) className = "list-group-item list-group-item-" <> (termBootstrapClass t)
click = mkEffectFn1 $ \_ -> setList t click = mkEffectFn1 $ \_ -> setList t
...@@ -19,7 +19,7 @@ import DOM.Simple.Document as Document ...@@ -19,7 +19,7 @@ import DOM.Simple.Document as Document
import DOM.Simple.Types ( DOMRect ) import DOM.Simple.Types ( DOMRect )
import Effect (Effect) import Effect (Effect)
import Effect.Uncurried ( mkEffectFn1 ) import Effect.Uncurried ( mkEffectFn1 )
import FFI.Simple ( (...), (..), (.=), delay ) import FFI.Simple ( (...), (..), delay )
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as HTML import Reactix.DOM.HTML as HTML
import Reactix.SyntheticEvent as E import Reactix.SyntheticEvent as E
...@@ -56,8 +56,17 @@ contextMenuCpt = R.hooksComponent "ContextMenu" cpt ...@@ -56,8 +56,17 @@ contextMenuCpt = R.hooksComponent "ContextMenu" cpt
] ]
] ]
pure $ R.createPortal [ elems root menu rect $ cs ] host pure $ R.createPortal [ elems root menu rect $ cs ] host
elems ref menu (Just rect) = HTML.div (({ ref , className: "context-menu", style: position menu rect} .= "data-toggle" $ "popover") .= "data-placement" $ "right") elems ref menu (Just rect) = HTML.div
elems ref _ _ = HTML.div (({ ref, className: "context-menu" } .= "data-toggle" $ "popover") .= "data-placement" $ "right") { ref
, className: "context-menu"
, style: position menu rect
, data: {toggle: "popover", placement: "right"}
}
elems ref _ _ = HTML.div
{ ref
, className: "context-menu"
, data: {toggle: "popover", placement: "right"}
}
contextMenuEffect contextMenuEffect
:: forall t :: forall t
......
This diff is collapsed.
...@@ -26,10 +26,12 @@ import React as React ...@@ -26,10 +26,12 @@ import React as React
import React (ReactClass, ReactElement, Children) import React (ReactClass, ReactElement, Children)
------------------------------------------------------------------------ ------------------------------------------------------------------------
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Config (End(..), NodeType(..), OrderBy(..), Path(..), TabType, toUrl) import Gargantext.Config (End(..), NodeType(..), OrderBy(..), Path(..), TabType, toUrl, toLink)
import Gargantext.Config.REST (put, post, deleteWithBody) import Gargantext.Config.REST (put, post, deleteWithBody)
import Gargantext.Components.Loader as Loader import Gargantext.Components.Loader as Loader
import Gargantext.Components.Search.Types (Category(..), CategoryQuery(..), favCategory, trashCategory, decodeCategory, putCategories)
import Gargantext.Components.Table as T import Gargantext.Components.Table as T
import Gargantext.Router as Router
import Gargantext.Utils (toggleSet) import Gargantext.Utils (toggleSet)
import Gargantext.Utils.DecodeMaybe ((.|)) import Gargantext.Utils.DecodeMaybe ((.|))
import React.DOM (a, br', button, div, i, input, p, text, span) import React.DOM (a, br', button, div, i, input, p, text, span)
...@@ -83,9 +85,9 @@ initialState = ...@@ -83,9 +85,9 @@ initialState =
} }
data Action data Action
= MarkFavorites (Array Int) = MarkCategory Category (Array Int)
| ToggleDocumentToDelete Int | ToggleDocumentToDelete Int
| Trash | TrashDocuments
newtype Pair = Pair newtype Pair = Pair
{ id :: Int { id :: Int
...@@ -106,9 +108,9 @@ newtype DocumentsView ...@@ -106,9 +108,9 @@ newtype DocumentsView
, score :: Int , score :: Int
, pairs :: Array Pair , pairs :: Array Pair
, delete :: Boolean , delete :: Boolean
, category :: Category
} }
derive instance genericDocumentsView :: Generic DocumentsView _ derive instance genericDocumentsView :: Generic DocumentsView _
instance showDocumentsView :: Show DocumentsView where instance showDocumentsView :: Show DocumentsView where
...@@ -118,7 +120,7 @@ newtype Response = Response ...@@ -118,7 +120,7 @@ newtype Response = Response
{ id :: Int { id :: Int
, created :: String , created :: String
, hyperdata :: Hyperdata , hyperdata :: Hyperdata
, favorite :: Boolean , category :: Category
, ngramCount :: Int , ngramCount :: Int
-- , date :: String -- , date :: String
-- , score :: Int -- , score :: Int
...@@ -174,7 +176,7 @@ instance decodeResponse :: DecodeJson Response where ...@@ -174,7 +176,7 @@ instance decodeResponse :: DecodeJson Response where
hyperdata <- obj .? "hyperdata" hyperdata <- obj .? "hyperdata"
favorite <- obj .? "favorite" favorite <- obj .? "favorite"
ngramCount <- obj .? "ngramCount" ngramCount <- obj .? "ngramCount"
pure $ Response { id, created, hyperdata, favorite, ngramCount } pure $ Response { id, created, hyperdata, category: decodeCategory favorite, ngramCount }
-- | Filter -- | Filter
-- TODO: unused -- TODO: unused
...@@ -194,12 +196,12 @@ layoutDocview :: Spec State Props Action ...@@ -194,12 +196,12 @@ layoutDocview :: Spec State Props Action
layoutDocview = simpleSpec performAction render layoutDocview = simpleSpec performAction render
where where
performAction :: PerformAction State Props Action performAction :: PerformAction State Props Action
performAction (MarkFavorites nids) {nodeId} _ = performAction (MarkCategory category nids) {nodeId} _ =
void $ lift $ putFavorites nodeId (FavoriteQuery {favorites: nids}) void $ lift $ putCategories nodeId $ CategoryQuery {nodeIds: nids, category: favCategory category}
--TODO add array of delete rows here --TODO add array of delete rows here
performAction (ToggleDocumentToDelete nid) _ _ = performAction (ToggleDocumentToDelete nid) _ _ =
modifyState_ \state -> state {documentIdsToDelete = toggleSet nid state.documentIdsToDelete} modifyState_ \state -> state {documentIdsToDelete = toggleSet nid state.documentIdsToDelete}
performAction Trash {nodeId} {documentIdsToDelete} = do performAction TrashDocuments {nodeId} {documentIdsToDelete} = do
void $ lift $ deleteDocuments nodeId (DeleteDocumentQuery {documents: Set.toUnfoldable documentIdsToDelete}) void $ lift $ deleteDocuments nodeId (DeleteDocumentQuery {documents: Set.toUnfoldable documentIdsToDelete})
modifyState_ \{documentIdsToDelete, documentIdsDeleted} -> modifyState_ \{documentIdsToDelete, documentIdsDeleted} ->
{ documentIdsToDelete: mempty { documentIdsToDelete: mempty
...@@ -229,7 +231,7 @@ layoutDocview = simpleSpec performAction render ...@@ -229,7 +231,7 @@ layoutDocview = simpleSpec performAction render
] ]
, div [className "col-md-12"] , div [className "col-md-12"]
[ button [ style {backgroundColor: "peru", padding : "9px", color : "white", border : "white", float: "right"} [ button [ style {backgroundColor: "peru", padding : "9px", color : "white", border : "white", float: "right"}
, onClick $ (\_ -> dispatch Trash) , onClick $ (\_ -> dispatch TrashDocuments)
] ]
[ i [className "glyphitem glyphicon glyphicon-trash", style {marginRight : "9px"}] [] [ i [className "glyphitem glyphicon glyphicon-trash", style {marginRight : "9px"}] []
, text "Trash it !" , text "Trash it !"
...@@ -245,12 +247,12 @@ layoutDocviewGraph :: Spec State Props Action ...@@ -245,12 +247,12 @@ layoutDocviewGraph :: Spec State Props Action
layoutDocviewGraph = simpleSpec performAction render layoutDocviewGraph = simpleSpec performAction render
where where
performAction :: PerformAction State Props Action performAction :: PerformAction State Props Action
performAction (MarkFavorites nids) {nodeId} _ = performAction (MarkCategory category nids) {nodeId} _ =
void $ lift $ putFavorites nodeId (FavoriteQuery {favorites: nids}) void $ lift $ putCategories nodeId $ CategoryQuery {nodeIds: nids, category: favCategory category}
--TODO add array of delete rows here --TODO add array of delete rows here
performAction (ToggleDocumentToDelete nid) _ _ = performAction (ToggleDocumentToDelete nid) _ _ =
modifyState_ \state -> state {documentIdsToDelete = toggleSet nid state.documentIdsToDelete} modifyState_ \state -> state {documentIdsToDelete = toggleSet nid state.documentIdsToDelete}
performAction Trash {nodeId} {documentIdsToDelete} = do performAction TrashDocuments {nodeId} {documentIdsToDelete} = do
void $ lift $ deleteDocuments nodeId (DeleteDocumentQuery {documents: Set.toUnfoldable documentIdsToDelete}) void $ lift $ deleteDocuments nodeId (DeleteDocumentQuery {documents: Set.toUnfoldable documentIdsToDelete})
modifyState_ \{documentIdsToDelete, documentIdsDeleted} -> modifyState_ \{documentIdsToDelete, documentIdsDeleted} ->
{ documentIdsToDelete: mempty { documentIdsToDelete: mempty
...@@ -275,7 +277,7 @@ layoutDocviewGraph = simpleSpec performAction render ...@@ -275,7 +277,7 @@ layoutDocviewGraph = simpleSpec performAction render
, container , container
} }
, button [ style {backgroundColor: "peru", padding : "9px", color : "white", border : "white", float: "right"} , button [ style {backgroundColor: "peru", padding : "9px", color : "white", border : "white", float: "right"}
, onClick $ (\_ -> dispatch Trash) , onClick $ (\_ -> dispatch TrashDocuments)
] ]
[ i [className "glyphitem glyphicon glyphicon-trash", style {marginRight : "9px"}] [] [ i [className "glyphitem glyphicon glyphicon-trash", style {marginRight : "9px"}] []
, text "Trash it !" , text "Trash it !"
...@@ -303,7 +305,7 @@ loadPage {nodeId, listId, query, params: {limit, offset, orderBy}} = do ...@@ -303,7 +305,7 @@ loadPage {nodeId, listId, query, params: {limit, offset, orderBy}} = do
res2corpus :: Response -> DocumentsView res2corpus :: Response -> DocumentsView
res2corpus (Response { id, created: date, ngramCount: score res2corpus (Response { id, created: date, ngramCount: score
, hyperdata: Hyperdata {title, source} , hyperdata: Hyperdata {title, source}
-- favorite TODO , category
}) = }) =
DocumentsView DocumentsView
{ id { id
...@@ -313,6 +315,7 @@ loadPage {nodeId, listId, query, params: {limit, offset, orderBy}} = do ...@@ -313,6 +315,7 @@ loadPage {nodeId, listId, query, params: {limit, offset, orderBy}} = do
, score , score
, pairs: [] , pairs: []
, delete: false , delete: false
, category
} }
convOrderBy (T.ASC (T.ColumnName "Date")) = DateAsc convOrderBy (T.ASC (T.ColumnName "Date")) = DateAsc
convOrderBy (T.DESC (T.ColumnName "Date")) = DateDesc convOrderBy (T.DESC (T.ColumnName "Date")) = DateDesc
...@@ -363,7 +366,7 @@ renderPage loaderDispatch { totalRecords, dispatch, container ...@@ -363,7 +366,7 @@ renderPage loaderDispatch { totalRecords, dispatch, container
] ]
where where
-- TODO: how to interprete other scores? -- TODO: how to interprete other scores?
gi 0 = "glyphicon glyphicon-star-empty" gi Favorite = "glyphicon glyphicon-star-empty"
gi _ = "glyphicon glyphicon-star" gi _ = "glyphicon glyphicon-star"
isChecked id = Set.member id documentIdsToDelete isChecked id = Set.member id documentIdsToDelete
isDeleted (DocumentsView {id}) = Set.member id documentIdsDeleted isDeleted (DocumentsView {id}) = Set.member id documentIdsDeleted
...@@ -371,7 +374,7 @@ renderPage loaderDispatch { totalRecords, dispatch, container ...@@ -371,7 +374,7 @@ renderPage loaderDispatch { totalRecords, dispatch, container
| id > 1 = [a [href (toUrl Front NodeContact (Just id)), target "blank"] [text label]] | id > 1 = [a [href (toUrl Front NodeContact (Just id)), target "blank"] [text label]]
| otherwise = [text label] | otherwise = [text label]
comma = span [] [text ", "] comma = span [] [text ", "]
rows = (\(DocumentsView {id,score,title,source,date,pairs,delete}) -> rows = (\(DocumentsView {id,score,title,source,date,pairs,delete,category}) ->
let let
strikeIfDeleted strikeIfDeleted
| delete = [style {textDecoration : "line-through"}] | delete = [style {textDecoration : "line-through"}]
...@@ -379,13 +382,13 @@ renderPage loaderDispatch { totalRecords, dispatch, container ...@@ -379,13 +382,13 @@ renderPage loaderDispatch { totalRecords, dispatch, container
in in
{ row: { row:
[ div [] [ div []
[ a [ className $ gi score [ a [ className $ gi category
, onClick $ const $ dispatch $ MarkFavorites [id] , onClick $ const $ dispatch $ MarkCategory category [id]
] [] ] []
] ]
-- TODO show date: Year-Month-Day only -- TODO show date: Year-Month-Day only
, div strikeIfDeleted [text date] , div strikeIfDeleted [text date]
, a (strikeIfDeleted <> [ href (toUrl Front (ListDocument (Just listId)) (Just id)) , a (strikeIfDeleted <> [ href $ toLink $ Router.Document listId id
, target "blank"]) , target "blank"])
[ text title ] [ text title ]
, div strikeIfDeleted [text source] , div strikeIfDeleted [text source]
...@@ -405,15 +408,6 @@ pageLoader props = React.createElement pageLoaderClass props [] ...@@ -405,15 +408,6 @@ pageLoader props = React.createElement pageLoaderClass props []
--------------------------------------------------------- ---------------------------------------------------------
newtype FavoriteQuery = FavoriteQuery
{ favorites :: Array Int
}
instance encodeJsonFQuery :: EncodeJson FavoriteQuery where
encodeJson (FavoriteQuery post)
= "favorites" := post.favorites
~> jsonEmptyObject
newtype DeleteDocumentQuery = DeleteDocumentQuery newtype DeleteDocumentQuery = DeleteDocumentQuery
{ {
documents :: Array Int documents :: Array Int
...@@ -425,11 +419,5 @@ instance encodeJsonDDQuery :: EncodeJson DeleteDocumentQuery where ...@@ -425,11 +419,5 @@ instance encodeJsonDDQuery :: EncodeJson DeleteDocumentQuery where
= "documents" := post.documents = "documents" := post.documents
~> jsonEmptyObject ~> jsonEmptyObject
putFavorites :: Int -> FavoriteQuery -> Aff (Array Int)
putFavorites nodeId = put (toUrl Back Node (Just nodeId) <> "/favorites")
deleteFavorites :: Int -> FavoriteQuery -> Aff (Array Int)
deleteFavorites nodeId = deleteWithBody (toUrl Back Node (Just nodeId) <> "/favorites")
deleteDocuments :: Int -> DeleteDocumentQuery -> Aff (Array Int) deleteDocuments :: Int -> DeleteDocumentQuery -> Aff (Array Int)
deleteDocuments nodeId = deleteWithBody (toUrl Back Node (Just nodeId) <> "/documents") deleteDocuments nodeId = deleteWithBody (toUrl Back Node (Just nodeId) <> "/documents")
...@@ -40,6 +40,7 @@ import Gargantext.Types (class Optional) ...@@ -40,6 +40,7 @@ import Gargantext.Types (class Optional)
import Gargantext.Utils (toggleSet) import Gargantext.Utils (toggleSet)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Partial.Unsafe (unsafePartial) import Partial.Unsafe (unsafePartial)
import Thermite (Spec)
import Unsafe.Coerce (unsafeCoerce) import Unsafe.Coerce (unsafeCoerce)
import Web.HTML (window) import Web.HTML (window)
import Web.HTML.Window (localStorage) import Web.HTML.Window (localStorage)
...@@ -49,13 +50,14 @@ import Reactix.DOM.HTML as RH ...@@ -49,13 +50,14 @@ import Reactix.DOM.HTML as RH
type Props s fa2 = () type Props s fa2 = ()
spec = R2.scuff $ explorer {} spec :: forall s fa2. Spec {} (Record (Props s fa2)) Void
spec = R2.elSpec $ explorerCpt
explorer :: forall s fa2. Record (Props s fa2) -> R.Element explorer :: forall s fa2. Record (Props s fa2) -> R.Element
explorer props = R.createElement explorerCpt props [] explorer props = R.createElement explorerCpt props []
explorerCpt :: forall s fa2. R.Component (Props s fa2) explorerCpt :: forall s fa2. R.Component (Props s fa2)
explorerCpt = R.hooksComponent "Explorer" cpt explorerCpt = R.hooksComponent "GraphExplorer" cpt
where where
cpt props _ = do cpt props _ = do
controls <- Controls.useGraphControls controls <- Controls.useGraphControls
......
module Gargantext.Components.Loader2 where
import Data.Maybe (Maybe(..), isNothing)
import Data.Tuple.Nested ((/\))
import Gargantext.Prelude
import Effect.Aff (Aff, launchAff, launchAff_, killFiber)
import Effect.Class (liftEffect)
import Effect.Exception (error)
import Reactix as R
type Props path loaded = { path :: path, loaded :: loaded }
type State path loaded = { currentPath :: path, loaded :: Maybe loaded }
useLoader
:: forall path loaded
. Eq path
=> Show path
=> path
-> (path -> Aff loaded)
-> (Props path loaded -> R.Element)
-> R.Hooks R.Element
useLoader newPath loader render = do
{currentPath, loaded} /\ setState <- R.useState' { currentPath: newPath, loaded: Nothing }
R.useEffect $
if (isNothing loaded || newPath /= currentPath) then do
logs $ "useLoader " <> show {newPath, currentPath, loadedIsNothing: isNothing loaded}
fiber <- launchAff do
freshlyLoaded <- loader newPath
liftEffect $ setState $ const { currentPath: newPath, loaded: Just freshlyLoaded }
pure $ launchAff_ $ killFiber (error "useLoader") fiber
else do
pure $ pure $ unit
pure case loaded of
Nothing ->
-- TODO load spinner
R.fragment []
Just loadedData ->
render {path: currentPath, loaded: loadedData}
This diff is collapsed.
module Gargantext.Components.Login.Types where module Gargantext.Components.Login.Types where
import Prelude import Prelude
import Data.Lens (Iso', iso)
import Data.Argonaut ( class DecodeJson, class EncodeJson, decodeJson, jsonEmptyObject import Data.Argonaut ( class DecodeJson, class EncodeJson, decodeJson, jsonEmptyObject
, (.?), (.??), (:=), (~>) , (.?), (.??), (:=), (~>)
) )
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Eq (genericEq)
import Data.Lens (Iso', iso)
import Data.Maybe (Maybe) import Data.Maybe (Maybe)
type Username = String type Username = String
...@@ -30,6 +32,12 @@ newtype AuthData = AuthData ...@@ -30,6 +32,12 @@ newtype AuthData = AuthData
, tree_id :: TreeId , tree_id :: TreeId
} }
derive instance genericAuthData :: Generic AuthData _
instance eqAuthData :: Eq AuthData where
eq = genericEq
_AuthData :: Iso' AuthData { token :: Token, tree_id :: TreeId } _AuthData :: Iso' AuthData { token :: Token, tree_id :: TreeId }
_AuthData = iso (\(AuthData v) -> v) AuthData _AuthData = iso (\(AuthData v) -> v) AuthData
......
...@@ -34,12 +34,13 @@ import Thermite (PerformAction, Render, Spec, defaultPerformAction, modifyState_ ...@@ -34,12 +34,13 @@ import Thermite (PerformAction, Render, Spec, defaultPerformAction, modifyState_
import Unsafe.Coerce (unsafeCoerce) import Unsafe.Coerce (unsafeCoerce)
import Gargantext.Types (TermList(..), readTermList, readTermSize, termLists, termSizes) import Gargantext.Types (TermList(..), readTermList, readTermSize, termLists, termSizes)
import Gargantext.Config (OrderBy(..), TabType) import Gargantext.Config (OrderBy(..), TabType, CTabNgramType(..))
import Gargantext.Components.AutoUpdate (autoUpdateElt) import Gargantext.Components.AutoUpdate (autoUpdateElt)
import Gargantext.Components.Table as T import Gargantext.Components.Table as T
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Components.Loader as Loader import Gargantext.Components.Loader as Loader
import Gargantext.Components.NgramsTable.Core import Gargantext.Components.NgramsTable.Core
import Gargantext.Utils.Reactix as R2
type State = type State =
CoreState CoreState
...@@ -119,7 +120,7 @@ tableContainer { pageParams ...@@ -119,7 +120,7 @@ tableContainer { pageParams
, name "search", placeholder "Search" , name "search", placeholder "Search"
, _type "value" , _type "value"
, value pageParams.searchQuery , value pageParams.searchQuery
, onInput \e -> setSearchQuery (unsafeEventValue e) , onInput \e -> setSearchQuery (R2.unsafeEventValue e)
] ]
, div [] ( , div [] (
if A.null props.tableBody && pageParams.searchQuery /= "" then [ if A.null props.tableBody && pageParams.searchQuery /= "" then [
...@@ -134,7 +135,7 @@ tableContainer { pageParams ...@@ -134,7 +135,7 @@ tableContainer { pageParams
[ select [ _id "picklistmenu" [ select [ _id "picklistmenu"
, className "form-control custom-select" , className "form-control custom-select"
, value (maybe "" show pageParams.termListFilter) , value (maybe "" show pageParams.termListFilter)
, onChange (\e -> setTermListFilter $ readTermList $ unsafeEventValue e) , onChange (\e -> setTermListFilter $ readTermList $ R2.unsafeEventValue e)
] $ map optps1 termLists ] $ map optps1 termLists
] ]
] ]
...@@ -143,7 +144,7 @@ tableContainer { pageParams ...@@ -143,7 +144,7 @@ tableContainer { pageParams
[ select [ _id "picktermtype" [ select [ _id "picktermtype"
, className "form-control custom-select" , className "form-control custom-select"
, value (maybe "" show pageParams.termSizeFilter) , value (maybe "" show pageParams.termSizeFilter)
, onChange (\e -> setTermSizeFilter $ readTermSize $ unsafeEventValue e) , onChange (\e -> setTermSizeFilter $ readTermSize $ R2.unsafeEventValue e)
] $ map optps1 termSizes ] $ map optps1 termSizes
] ]
] ]
...@@ -197,8 +198,8 @@ toggleMap :: forall a. a -> Maybe a -> Maybe a ...@@ -197,8 +198,8 @@ toggleMap :: forall a. a -> Maybe a -> Maybe a
toggleMap _ (Just _) = Nothing toggleMap _ (Just _) = Nothing
toggleMap b Nothing = Just b toggleMap b Nothing = Just b
ngramsTableSpec :: Spec State LoadedNgramsTableProps Action ngramsTableSpec :: CTabNgramType -> Spec State LoadedNgramsTableProps Action
ngramsTableSpec = simpleSpec performAction render ngramsTableSpec ntype = simpleSpec performAction render
where where
setParentResetChildren :: Maybe NgramsTerm -> State -> State setParentResetChildren :: Maybe NgramsTerm -> State -> State
setParentResetChildren p = _ { ngramsParent = p, ngramsChildren = mempty } setParentResetChildren p = _ { ngramsParent = p, ngramsChildren = mempty }
...@@ -213,9 +214,8 @@ ngramsTableSpec = simpleSpec performAction render ...@@ -213,9 +214,8 @@ ngramsTableSpec = simpleSpec performAction render
performAction (SetTermListItem n pl) {path: {nodeId, listIds, tabType}} {ngramsVersion} = performAction (SetTermListItem n pl) {path: {nodeId, listIds, tabType}} {ngramsVersion} =
commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: pt}) commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: pt})
where where
listId = Just 10 -- List.head listIds
pe = NgramsPatch { patch_list: pl, patch_children: mempty } pe = NgramsPatch { patch_list: pl, patch_children: mempty }
pt = PatchMap $ Map.singleton n pe pt = singletonNgramsTablePatch ntype n pe
performAction AddTermChildren _ {ngramsParent: Nothing} = performAction AddTermChildren _ {ngramsParent: Nothing} =
-- impossible but harmless -- impossible but harmless
pure unit pure unit
...@@ -227,14 +227,13 @@ ngramsTableSpec = simpleSpec performAction render ...@@ -227,14 +227,13 @@ ngramsTableSpec = simpleSpec performAction render
modifyState_ $ setParentResetChildren Nothing modifyState_ $ setParentResetChildren Nothing
commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: pt}) commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: pt})
where where
listId = Just 10 -- List.head listIds
pc = patchSetFromMap ngramsChildren pc = patchSetFromMap ngramsChildren
pe = NgramsPatch { patch_list: mempty, patch_children: pc } pe = NgramsPatch { patch_list: mempty, patch_children: pc }
pt = PatchMap $ Map.fromFoldable [Tuple parent pe] pt = singletonNgramsTablePatch ntype parent pe
-- TODO ROOT-UPDATE performAction (AddNewNgram ngram) {path: {listIds, nodeId, tabType}} {ngramsVersion} =
-- patch the root of the child to be equal to the root of the parent. commitPatch {listIds, nodeId, tabType} (Versioned {version: ngramsVersion, data: pt})
performAction (AddNewNgram ngram) {path: params} _ = where
lift $ addNewNgram ngram Nothing params pt = addNewNgram ntype ngram CandidateTerm
render :: Render State LoadedNgramsTableProps Action render :: Render State LoadedNgramsTableProps Action
render dispatch { path: pageParams render dispatch { path: pageParams
...@@ -251,7 +250,7 @@ ngramsTableSpec = simpleSpec performAction render ...@@ -251,7 +250,7 @@ ngramsTableSpec = simpleSpec performAction render
, container: tableContainer {pageParams, loaderDispatch, dispatch, ngramsParent, ngramsChildren, ngramsTable} , container: tableContainer {pageParams, loaderDispatch, dispatch, ngramsParent, ngramsChildren, ngramsTable}
, colNames: , colNames:
T.ColumnName <$> T.ColumnName <$>
[ "Graph" [ "Map"
, "Stop" , "Stop"
, "Terms" , "Terms"
, "Score (Occurrences)" -- see convOrderBy , "Score (Occurrences)" -- see convOrderBy
...@@ -294,21 +293,24 @@ ngramsTableSpec = simpleSpec performAction render ...@@ -294,21 +293,24 @@ ngramsTableSpec = simpleSpec performAction render
, delete: false , delete: false
} }
ngramsTableClass :: Loader.InnerClass PageParams VersionedNgramsTable ngramsTableClass :: CTabNgramType -> Loader.InnerClass PageParams VersionedNgramsTable
ngramsTableClass = createClass "NgramsTable" ngramsTableSpec initialState ngramsTableClass ct = createClass "NgramsTable" (ngramsTableSpec ct) initialState
type MainNgramsTableProps = type MainNgramsTableProps =
Loader.InnerProps Int { defaultListId :: Int } { nodeId :: Int
( tabType :: TabType ) -- ^ This node can be a corpus or contact.
, defaultListId :: Int
, tabType :: TabType
}
mainNgramsTableSpec :: Spec {} MainNgramsTableProps Void mainNgramsTableSpec :: CTabNgramType -> Spec {} MainNgramsTableProps Void
mainNgramsTableSpec = simpleSpec defaultPerformAction render mainNgramsTableSpec nt = simpleSpec defaultPerformAction render
where where
render :: Render {} MainNgramsTableProps Void render :: Render {} MainNgramsTableProps Void
render _ {path: nodeId, loaded: {defaultListId}, tabType} _ _ = render _ {nodeId, defaultListId, tabType} _ _ =
[ ngramsLoader [ ngramsLoader
{ path: initialPageParams nodeId [defaultListId] tabType { path: initialPageParams nodeId [defaultListId] tabType
, component: ngramsTableClass , component: (ngramsTableClass nt)
} ] } ]
type NgramsDepth = {ngrams :: NgramsTerm, depth :: Int} type NgramsDepth = {ngrams :: NgramsTerm, depth :: Int}
...@@ -419,6 +421,3 @@ optps1 :: forall a. Show a => { desc :: String, mval :: Maybe a } -> ReactElemen ...@@ -419,6 +421,3 @@ optps1 :: forall a. Show a => { desc :: String, mval :: Maybe a } -> ReactElemen
optps1 { desc, mval } = option [value val] [text desc] optps1 { desc, mval } = option [value val] [text desc]
where where
val = maybe "" show mval val = maybe "" show mval
unsafeEventValue :: forall event. event -> String
unsafeEventValue e = (unsafeCoerce e).target.value
...@@ -25,10 +25,10 @@ instance decodeNodePoly :: (DecodeJson a) ...@@ -25,10 +25,10 @@ instance decodeNodePoly :: (DecodeJson a)
parentId <- obj .? "parentId" parentId <- obj .? "parentId"
name <- obj .? "name" name <- obj .? "name"
date <- obj .? "date" date <- obj .? "date"
hyperdata <- obj .? "hyperdata" hyperdata <- obj .? "hyperdata"
hyperdata' <- decodeJson hyperdata hyperdata' <- decodeJson hyperdata
pure $ NodePoly { id : id pure $ NodePoly { id : id
, typename : typename , typename : typename
, userId : userId , userId : userId
......
...@@ -14,7 +14,7 @@ import DOM.Simple.Element as Element ...@@ -14,7 +14,7 @@ import DOM.Simple.Element as Element
import DOM.Simple.Event as DE import DOM.Simple.Event as DE
import Effect ( Effect ) import Effect ( Effect )
import Effect.Uncurried (mkEffectFn1) import Effect.Uncurried (mkEffectFn1)
import FFI.Simple ((..), (.=)) import FFI.Simple ((..))
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as HTML import Reactix.DOM.HTML as HTML
import Reactix.DOM.HTML (text, button, div, input, option, form, span, ul, li, a) import Reactix.DOM.HTML (text, button, div, input, option, form, span, ul, li, a)
...@@ -47,7 +47,7 @@ searchFieldComponent = R.memo (R.hooksComponent "SearchField" cpt) hasChanged ...@@ -47,7 +47,7 @@ searchFieldComponent = R.memo (R.hooksComponent "SearchField" cpt) hasChanged
cpt props _ = do cpt props _ = do
let search = maybe defaultSearch identity (fst props.search) let search = maybe defaultSearch identity (fst props.search)
term <- R.useState' search.term term <- R.useState' search.term
db <- R.useState' Nothing db <- R.useState' (Nothing :: Maybe Database)
pure $ pure $
div { className: "search-field input-group" } div { className: "search-field input-group" }
[ databaseInput db props.databases [ databaseInput db props.databases
...@@ -60,18 +60,18 @@ searchFieldComponent = R.memo (R.hooksComponent "SearchField" cpt) hasChanged ...@@ -60,18 +60,18 @@ searchFieldComponent = R.memo (R.hooksComponent "SearchField" cpt) hasChanged
databaseInput :: R.State (Maybe Database) -> Array Database -> R.Element databaseInput :: R.State (Maybe Database) -> Array Database -> R.Element
databaseInput (db /\ setDB) dbs = databaseInput (db /\ setDB) dbs =
div { className: "input-group-btn search-panel dropdown" } div { className: "input-group-btn search-panel dropdown" }
[ [ dropdownBtn db
dropdownBtn db , ul {className: "dropdown-menu", role: "menu"} (liItem <$> dbs)
, ul {className: "dropdown-menu", role: "menu"} (liItem <$> dbs)
] ]
where where
liItem db = li { onClick } liItem db = li { onClick } [ a {href: "#"} [text (show db) ] ]
[ a {href: "#"} [text (show db) ] ] where
where onClick = mkEffectFn1 $ \_ -> setDB $ const $ Just db
onClick = mkEffectFn1 $ \_ -> setDB (const $ Just db)
dropdownBtnProps = { id: "search-dropdown" dropdownBtnProps = { id: "search-dropdown"
, className: "btn btn-default dropdown-toggle" , className: "btn btn-default dropdown-toggle"
, type: "button"} .= "data-toggle" $ "dropdown" , type: "button"
, data: {toggle: "dropdown"}
}
dropdownBtn (Just db) = button dropdownBtnProps [ span {} [ text (show db) ] ] dropdownBtn (Just db) = button dropdownBtnProps [ span {} [ text (show db) ] ]
dropdownBtn (Nothing) = button dropdownBtnProps [ span {} [ text "-" ] ] dropdownBtn (Nothing) = button dropdownBtnProps [ span {} [ text "-" ] ]
...@@ -82,7 +82,7 @@ searchInput (term /\ setTerm) = ...@@ -82,7 +82,7 @@ searchInput (term /\ setTerm) =
, type: "text" , type: "text"
, onChange , onChange
, placeholder } , placeholder }
where onChange = mkEffectFn1 $ \e -> setTerm (const $ e .. "target" .. "value") where onChange = mkEffectFn1 $ \e -> setTerm $ const $ e .. "target" .. "value"
submitButton :: R.State (Maybe Database) -> R.State String -> R.State (Maybe Search) -> R.Element submitButton :: R.State (Maybe Database) -> R.State String -> R.State (Maybe Search) -> R.Element
...@@ -91,5 +91,5 @@ submitButton (database /\ _) (term /\ _) (_ /\ setSearch) = ...@@ -91,5 +91,5 @@ submitButton (database /\ _) (term /\ _) (_ /\ setSearch) =
where where
click = mkEffectFn1 $ \_ -> do click = mkEffectFn1 $ \_ -> do
case term of case term of
"" -> setSearch (const Nothing) "" -> setSearch $ const Nothing
_ -> setSearch (const $ Just { database, term }) _ -> setSearch $ const $ Just { database, term }
module Gargantext.Components.Search.Types where module Gargantext.Components.Search.Types where
import Control.Monad.Cont.Trans (lift) import Control.Monad.Cont.Trans (lift)
import Data.Argonaut (class EncodeJson, jsonEmptyObject, (:=), (~>)) import Data.Argonaut (class EncodeJson, jsonEmptyObject, (:=), (~>), encodeJson)
import Data.Array (head)
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Eq (genericEq)
import Data.Generic.Rep.Show (genericShow)
import Data.Maybe (Maybe(..), fromMaybe, maybe) import Data.Maybe (Maybe(..), fromMaybe, maybe)
import Data.Newtype (class Newtype) import Data.Newtype (class Newtype)
import Data.Tuple (Tuple) import Data.Tuple (Tuple)
...@@ -13,19 +17,19 @@ import Thermite (PerformAction, modifyState) ...@@ -13,19 +17,19 @@ import Thermite (PerformAction, modifyState)
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Types (class ToQuery) import Gargantext.Types (class ToQuery)
import Gargantext.Config.REST (post) import Gargantext.Config (End(..), NodeType(..), Path(..), toUrl)
import Gargantext.Config.REST (post, put)
import Gargantext.Components.Modals.Modal (modalHide) import Gargantext.Components.Modals.Modal (modalHide)
import Gargantext.Pages.Layout.Specs.AddCorpus.States (Response, State)
import Gargantext.Utils (id) import Gargantext.Utils (id)
import URI.Extra.QueryPairs as QP import URI.Extra.QueryPairs as QP
data Database = All | PubMed | HAL | IsTex data Database = All | PubMed | HAL | IsTex
instance showDatabase :: Show Database where instance showDatabase :: Show Database where
show All = "All" show All = "All"
show PubMed = "PubMed" show PubMed = "PubMed"
show HAL = "HAL" show HAL = "HAL"
show IsTex = "IsTex" show IsTex = "IsTex"
readDatabase :: String -> Maybe Database readDatabase :: String -> Maybe Database
readDatabase "All" = Just All readDatabase "All" = Just All
...@@ -36,6 +40,10 @@ readDatabase _ = Nothing ...@@ -36,6 +40,10 @@ readDatabase _ = Nothing
derive instance eqDatabase :: Eq Database derive instance eqDatabase :: Eq Database
instance encodeJsonDatabase :: EncodeJson Database where
encodeJson a = encodeJson (show a)
allDatabases :: Array Database allDatabases :: Array Database
allDatabases = [All, HAL, IsTex, PubMed] allDatabases = [All, HAL, IsTex, PubMed]
...@@ -85,8 +93,57 @@ instance searchQueryToQuery :: ToQuery SearchQuery where ...@@ -85,8 +93,57 @@ instance searchQueryToQuery :: ToQuery SearchQuery where
[ QP.keyFromString k /\ Just (QP.valueFromString $ show v) ] [ QP.keyFromString k /\ Just (QP.valueFromString $ show v) ]
instance encodeJsonSearchQuery :: EncodeJson SearchQuery where instance encodeJsonSearchQuery :: EncodeJson SearchQuery where
encodeJson (SearchQuery {query, corpus_id, files_id}) encodeJson (SearchQuery {query, databases, corpus_id, files_id})
= "query" := query = "query" := query
~> "corpus_id" := fromMaybe 0 corpus_id ~> "databases" := databases
~> "files_id" := files_id ~> "corpus_id" := fromMaybe 0 corpus_id
~> "files_id" := files_id
~> jsonEmptyObject ~> jsonEmptyObject
data Category = Trash | Normal | Favorite
derive instance genericFavorite :: Generic Category _
instance showCategory :: Show Category where
show = genericShow
instance eqCategory :: Eq Category where
eq = genericEq
instance encodeJsonCategory :: EncodeJson Category where
encodeJson Trash = encodeJson 0
encodeJson Normal = encodeJson 1
encodeJson Favorite = encodeJson 2
favCategory :: Category -> Category
favCategory Normal = Favorite
favCategory Trash = Favorite
favCategory Favorite = Normal
trashCategory :: Category -> Category
trashCategory Normal = Trash
trashCategory Trash = Normal
trashCategory Favorite = Trash
decodeCategory :: Int -> Category
decodeCategory 0 = Trash
decodeCategory 1 = Normal
decodeCategory 2 = Favorite
decodeCategory _ = Normal
newtype CategoryQuery = CategoryQuery {
nodeIds :: Array Int
, category :: Category
}
instance encodeJsonCategoryQuery :: EncodeJson CategoryQuery where
encodeJson (CategoryQuery post) =
"ntc_nodesId" := post.nodeIds
~> "ntc_category" := encodeJson post.category
~> jsonEmptyObject
categoryUrl :: Int -> String
categoryUrl nodeId = toUrl Back Node (Just nodeId) <> "/category"
putCategories :: Int -> CategoryQuery -> Aff (Array Int)
putCategories nodeId = put $ categoryUrl nodeId
...@@ -9,11 +9,12 @@ import Effect (Effect) ...@@ -9,11 +9,12 @@ import Effect (Effect)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import React (ReactElement, ReactClass, Children, createElement) import React (ReactElement, ReactClass, Children, createElement)
import React.DOM (a, b, b', p, i, h3, hr, div, option, select, span, table, tbody, td, text, th, thead, tr) import React.DOM (a, b, b', p, i, h3, hr, div, option, select, span, table, tbody, td, text, th, thead, tr)
import React.DOM.Props (className, href, onChange, onClick, scope, selected, value, style) import React.DOM.Props (className, href, onChange, onClick, scope, selected, value, defaultValue, style)
import Thermite (PerformAction, Render, Spec, modifyState_, simpleSpec, StateCoTransformer, createClass) import Thermite (PerformAction, Render, Spec, modifyState_, simpleSpec, StateCoTransformer, createClass)
import Unsafe.Coerce (unsafeCoerce) import Unsafe.Coerce (unsafeCoerce)
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Utils.Reactix as R2
type TableContainerProps = type TableContainerProps =
{ pageSizeControl :: ReactElement { pageSizeControl :: ReactElement
...@@ -218,7 +219,8 @@ sizeDD :: PageSizes -> (Action -> Effect Unit) -> ReactElement ...@@ -218,7 +219,8 @@ sizeDD :: PageSizes -> (Action -> Effect Unit) -> ReactElement
sizeDD ps d sizeDD ps d
= span [] = span []
[ select [ className "form-control" [ select [ className "form-control"
, onChange (\e -> d (ChangePageSize $ string2PageSize $ (unsafeCoerce e).target.value)) , defaultValue $ show ps
, onChange $ \e -> d (ChangePageSize $ string2PageSize $ R2.unsafeEventValue e)
] $ map (optps ps) aryPS ] $ map (optps ps) aryPS
] ]
...@@ -316,4 +318,4 @@ string2PageSize "200" = PS200 ...@@ -316,4 +318,4 @@ string2PageSize "200" = PS200
string2PageSize _ = PS10 string2PageSize _ = PS10
optps :: PageSizes -> PageSizes -> ReactElement optps :: PageSizes -> PageSizes -> ReactElement
optps cv val = option [ selected (cv == val), value $ show val ] [text $ show val] optps cv val = option [ value $ show val ] [text $ show val]
This diff is collapsed.
...@@ -10,17 +10,14 @@ toUrl Front Corpus 1 == "http://localhost:2015/#/corpus/1" ...@@ -10,17 +10,14 @@ toUrl Front Corpus 1 == "http://localhost:2015/#/corpus/1"
module Gargantext.Config where module Gargantext.Config where
import Prelude import Prelude
import Data.Argonaut (class DecodeJson, decodeJson, class EncodeJson, encodeJson) import Data.Argonaut (class DecodeJson, decodeJson, class EncodeJson, encodeJson, (:=), (~>), jsonEmptyObject)
import Data.Foldable (foldMap) import Data.Foldable (foldMap)
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow) import Data.Generic.Rep.Show (genericShow)
import Data.Map (Map)
import Data.Map as DM
import Data.Maybe (Maybe(..), maybe) import Data.Maybe (Maybe(..), maybe)
import Data.Tuple (Tuple(..))
import Gargantext.Router as R import Gargantext.Router as R
import Gargantext.Types import Gargantext.Types (TermList, TermSize(..))
urlPlease :: End -> String -> String urlPlease :: End -> String -> String
urlPlease end path = theEnd.baseUrl <> theEnd.prePath <> path urlPlease end path = theEnd.baseUrl <> theEnd.prePath <> path
...@@ -31,7 +28,8 @@ endConfig = endConfig' V10 ...@@ -31,7 +28,8 @@ endConfig = endConfig' V10
endConfig' :: ApiVersion -> EndConfig endConfig' :: ApiVersion -> EndConfig
endConfig' v = { front : frontRelative endConfig' v = { front : frontRelative
, back : backDev v --, back : backLocal v
, back: backDev v
, static : staticRelative , static : staticRelative
} }
-- , back : backDemo v } -- , back : backDemo v }
...@@ -62,6 +60,11 @@ frontDev = { baseUrl: "https://dev.gargantext.org" ...@@ -62,6 +60,11 @@ frontDev = { baseUrl: "https://dev.gargantext.org"
, prePath: "/#/" , prePath: "/#/"
} }
frontDemo :: Config
frontDemo = { baseUrl: "https://demo.gargantext.org"
, prePath: "/#/"
}
frontProd :: Config frontProd :: Config
frontProd = { baseUrl: "https://gargantext.org" frontProd = { baseUrl: "https://gargantext.org"
, prePath: "/#/" , prePath: "/#/"
...@@ -119,11 +122,6 @@ endBaseUrl end c = (endOf end c).baseUrl ...@@ -119,11 +122,6 @@ endBaseUrl end c = (endOf end c).baseUrl
endPathUrl :: End -> EndConfig -> Path -> Maybe Id -> UrlPath endPathUrl :: End -> EndConfig -> Path -> Maybe Id -> UrlPath
endPathUrl end = pathUrl <<< endOf end endPathUrl end = pathUrl <<< endOf end
tabTypeDocs :: TabType -> UrlPath
tabTypeDocs (TabCorpus t) = "table?view=" <> show t
tabTypeDocs (TabDocument t)= "table?view=" <> show t
tabTypeDocs (TabPairing t) = "pairing?view=" <> show t
limitUrl :: Limit -> UrlPath limitUrl :: Limit -> UrlPath
limitUrl l = "&limit=" <> show l limitUrl l = "&limit=" <> show l
...@@ -141,10 +139,26 @@ showTabType' (TabCorpus t) = show t ...@@ -141,10 +139,26 @@ showTabType' (TabCorpus t) = show t
showTabType' (TabDocument t) = show t showTabType' (TabDocument t) = show t
showTabType' (TabPairing t) = show t showTabType' (TabPairing t) = show t
data TabPostQuery = TabPostQuery {
offset :: Int
, limit :: Int
, orderBy :: OrderBy
, tabType :: TabType
, query :: String
}
instance encodeJsonTabPostQuery :: EncodeJson TabPostQuery where
encodeJson (TabPostQuery post) =
"view" := showTabType' post.tabType
~> "offset" := post.offset
~> "limit" := post.limit
~> "orderBy" := show post.orderBy
~> "query" := post.query
~> jsonEmptyObject
pathUrl :: Config -> Path -> Maybe Id -> UrlPath pathUrl :: Config -> Path -> Maybe Id -> UrlPath
pathUrl c (Tab t o l s) i = pathUrl c (Tab t) i =
pathUrl c (NodeAPI Node) i <> pathUrl c (NodeAPI Node) i <> "/" <> showTabType' t
"/" <> tabTypeDocs t <> offsetUrl o <> limitUrl l <> orderUrl s
pathUrl c (Children n o l s) i = pathUrl c (Children n o l s) i =
pathUrl c (NodeAPI Node) i <> pathUrl c (NodeAPI Node) i <>
"/" <> "children?type=" <> show n <> offsetUrl o <> limitUrl l <> orderUrl s "/" <> "children?type=" <> show n <> offsetUrl o <> limitUrl l <> orderUrl s
...@@ -204,14 +218,16 @@ pathUrl c (Chart {chartType, tabType}) i = ...@@ -204,14 +218,16 @@ pathUrl c (Chart {chartType, tabType}) i =
------------------------------------------------------------ ------------------------------------------------------------
routesPath :: R.Routes -> String
routesPath R.Home = "" routesPath R.Home = ""
routesPath R.Login = "login" routesPath R.Login = "login"
routesPath R.SearchView = "search"
routesPath (R.Folder i) = "folder/" <> show i routesPath (R.Folder i) = "folder/" <> show i
routesPath (R.Corpus i) = "corpus/" <> show i routesPath (R.Corpus i) = "corpus/" <> show i
routesPath R.AddCorpus = "addCorpus" routesPath (R.CorpusDocument c l i) = "corpus/" <> show c <> "/list/" <> show l <> "/document/" <> show i
routesPath (R.Document l i) = "list/" <> show l <> "/document/" <> show i routesPath (R.Document l i) = "list/" <> show l <> "/document/" <> show i
routesPath (R.PGraphExplorer i) = "#/" routesPath (R.PGraphExplorer i) = "#/"
routesPath (R.Texts i) = "texts/" <> show i
routesPath (R.Lists i) = "lists/" <> show i
routesPath R.Dashboard = "dashboard" routesPath R.Dashboard = "dashboard"
routesPath (R.Annuaire i) = "annuaire/" <> show i routesPath (R.Annuaire i) = "annuaire/" <> show i
routesPath (R.UserPage i) = "user/" <> show i routesPath (R.UserPage i) = "user/" <> show i
...@@ -253,6 +269,7 @@ data NodeType = NodeUser ...@@ -253,6 +269,7 @@ data NodeType = NodeUser
| Nodes | Nodes
| Tree | Tree
| NodeList | NodeList
| Texts
derive instance eqNodeType :: Eq NodeType derive instance eqNodeType :: Eq NodeType
...@@ -273,6 +290,7 @@ instance showNodeType :: Show NodeType where ...@@ -273,6 +290,7 @@ instance showNodeType :: Show NodeType where
show Nodes = "Nodes" show Nodes = "Nodes"
show Tree = "NodeTree" show Tree = "NodeTree"
show NodeList = "NodeList" show NodeList = "NodeList"
show Texts = "NodeTexts"
readNodeType :: String -> NodeType readNodeType :: String -> NodeType
readNodeType "NodeAnnuaire" = Annuaire readNodeType "NodeAnnuaire" = Annuaire
...@@ -290,6 +308,7 @@ readNodeType "NodeUser" = NodeUser ...@@ -290,6 +308,7 @@ readNodeType "NodeUser" = NodeUser
readNodeType "NodeContact" = NodeContact readNodeType "NodeContact" = NodeContact
readNodeType "Tree" = Tree readNodeType "Tree" = Tree
readNodeType "NodeList" = NodeList readNodeType "NodeList" = NodeList
readNodeType "NodeTexts" = Texts
readNodeType _ = Error readNodeType _ = Error
{- {-
------------------------------------------------------------ ------------------------------------------------------------
...@@ -320,18 +339,19 @@ nodeTypeUrl Graph = "graph" ...@@ -320,18 +339,19 @@ nodeTypeUrl Graph = "graph"
nodeTypeUrl Phylo = "phylo" nodeTypeUrl Phylo = "phylo"
nodeTypeUrl Individu = "individu" nodeTypeUrl Individu = "individu"
nodeTypeUrl Node = "node" nodeTypeUrl Node = "node"
nodeTypeUrl Nodes = "nodes" nodeTypeUrl Nodes = "nodes"
nodeTypeUrl NodeUser = "user" nodeTypeUrl NodeUser = "user"
nodeTypeUrl NodeContact = "contact" nodeTypeUrl NodeContact = "contact"
nodeTypeUrl Tree = "tree" nodeTypeUrl Tree = "tree"
nodeTypeUrl NodeList = "list" nodeTypeUrl NodeList = "lists"
nodeTypeUrl Texts = "texts"
------------------------------------------------------------ ------------------------------------------------------------
type ListId = Int type ListId = Int
data Path data Path
= Auth = Auth
| Tab TabType Offset Limit (Maybe OrderBy) | Tab TabType
| Children NodeType Offset Limit (Maybe OrderBy) | Children NodeType Offset Limit (Maybe OrderBy)
| GetNgrams | GetNgrams
{ tabType :: TabType { tabType :: TabType
...@@ -416,7 +436,7 @@ instance showPTabNgramType :: Show PTabNgramType where ...@@ -416,7 +436,7 @@ instance showPTabNgramType :: Show PTabNgramType where
show PTabBooks = "Books" show PTabBooks = "Books"
show PTabCommunication = "Communication" show PTabCommunication = "Communication"
data TabSubType a = TabDocs | TabNgramType a | TabTrash data TabSubType a = TabDocs | TabNgramType a | TabTrash | TabMoreLikeFav | TabMoreLikeTrash
derive instance eqTabSubType :: Eq a => Eq (TabSubType a) derive instance eqTabSubType :: Eq a => Eq (TabSubType a)
...@@ -424,6 +444,8 @@ instance showTabSubType :: Show a => Show (TabSubType a) where ...@@ -424,6 +444,8 @@ instance showTabSubType :: Show a => Show (TabSubType a) where
show TabDocs = "Docs" show TabDocs = "Docs"
show (TabNgramType a) = show a show (TabNgramType a) = show a
show TabTrash = "Trash" show TabTrash = "Trash"
show TabMoreLikeFav = "MoreFav"
show TabMoreLikeTrash = "MoreTrash"
data TabType data TabType
= TabCorpus (TabSubType CTabNgramType) = TabCorpus (TabSubType CTabNgramType)
......
...@@ -4,4 +4,4 @@ module Gargantext.Pages.Annuaire.User.Contacts ...@@ -4,4 +4,4 @@ module Gargantext.Pages.Annuaire.User.Contacts
where where
import Gargantext.Pages.Annuaire.User.Contacts.Types import Gargantext.Pages.Annuaire.User.Contacts.Types
import Gargantext.Pages.Annuaire.User.Contacts.Specs import Gargantext.Pages.Annuaire.User.Contacts.Specs (layoutUser)
...@@ -16,20 +16,20 @@ import Data.Newtype (unwrap) ...@@ -16,20 +16,20 @@ import Data.Newtype (unwrap)
import Data.String (joinWith) import Data.String (joinWith)
import Effect.Aff (Aff, throwError) import Effect.Aff (Aff, throwError)
import Effect.Exception (error) import Effect.Exception (error)
import Thermite (Render, Spec, defaultPerformAction, simpleSpec, createClass) import Thermite (Render, Spec, defaultPerformAction, simpleSpec)
import React as React import React as React
import React (ReactClass, ReactElement) import React (ReactClass, ReactElement)
import React.DOM (div, h3, img, li, span, text, ul, text) import React.DOM (div, h3, img, li, span, text, ul, text)
import React.DOM.Props (_id, className, src) import React.DOM.Props (_id, className, src)
import Reactix as R
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Config (toUrl, End(..), NodeType(..), Path(..)) import Gargantext.Config (toUrl, End(..), NodeType(..), Path(..))
import Gargantext.Config.REST (get) import Gargantext.Config.REST (get)
import Gargantext.Components.Node (NodePoly(..), HyperdataList(..)) import Gargantext.Components.Node (NodePoly(..), HyperdataList(..))
import Gargantext.Components.Loader as Loader import Gargantext.Components.Loader2 (useLoader)
import Gargantext.Pages.Annuaire.User.Contacts.Types import Gargantext.Pages.Annuaire.User.Contacts.Types
import Gargantext.Pages.Annuaire.User.Contacts.Tabs.Specs as Tabs import Gargantext.Pages.Annuaire.User.Contacts.Tabs.Specs as Tabs
import Gargantext.Utils.Reactix as R2
--type Props = Loader.InnerProps Int Contact
display :: String -> Array ReactElement -> Array ReactElement display :: String -> Array ReactElement -> Array ReactElement
display title elems = display title elems =
...@@ -153,30 +153,16 @@ infoRender (Tuple title content) = ...@@ -153,30 +153,16 @@ infoRender (Tuple title content) =
-- | Below an example of a loader, use all code below and adapt it -- | Below an example of a loader, use all code below and adapt it
-- to your code -- to your code
-- layoutUser is exported by the module -- layoutUser is exported by the module
-- only one subnode: contactLoader which as 2 parameters
-- - path (nodeId)
-- - components (which has to be drawn when loaded
layoutUser :: Spec {} {nodeId :: Int} Void layoutUser :: Spec {} {nodeId :: Int} Void
layoutUser = simpleSpec defaultPerformAction render layoutUser =
where R2.elSpec $ R.hooksComponent "LayoutUser" \{nodeId} _ ->
render :: Render {} {nodeId :: Int} Void useLoader nodeId getContact $ \{loaded: contactData} ->
render _ {nodeId} _ _ = let {contactNode: Contact {name, hyperdata}} = contactData in
[ contactLoader { path: nodeId R2.toElement
, component: createClass "LayoutUser" layoutUser' (const {}) [ ul [className "col-md-12 list-group"] $
} ] display (fromMaybe "no name" name) (contactInfos hyperdata)
, Tabs.elt {nodeId, contactData}
-- | Take the spec and transform it in React Class ]
-- put here how to draw the Composant
-- props loaded: what has been loaded by the component loader
layoutUser' :: Spec {} Props Void
layoutUser' = simpleSpec defaultPerformAction render
<> Tabs.pureTabs
where
render :: Render {} Props Void
render dispatch {loaded: {contactNode: Contact {name, hyperdata}}} _ _ =
[ ul [className "col-md-12 list-group"] $
display (fromMaybe "no name" name) (contactInfos hyperdata)
]
-- | toUrl to get data -- | toUrl to get data
getContact :: Int -> Aff ContactData getContact :: Int -> Aff ContactData
...@@ -190,11 +176,3 @@ getContact id = do ...@@ -190,11 +176,3 @@ getContact id = do
-- Nothing -> -- Nothing ->
-- throwError $ error "Missing default list" -- throwError $ error "Missing default list"
pure {contactNode, defaultListId: 424242} pure {contactNode, defaultListId: 424242}
-- | Change name for you
contactLoaderClass :: ReactClass (Loader.Props Int ContactData)
contactLoaderClass = Loader.createLoaderClass "ContactLoader" getContact
-- | Change type according to what has been loaded
contactLoader :: Loader.Props' Int ContactData -> ReactElement
contactLoader props = React.createElement contactLoaderClass props []
...@@ -6,14 +6,20 @@ import Prelude hiding (div) ...@@ -6,14 +6,20 @@ import Prelude hiding (div)
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow) import Data.Generic.Rep.Show (genericShow)
import Data.List (fromFoldable) import Data.List (fromFoldable)
import Data.Maybe (Maybe(..))
import Data.Tuple (Tuple(..)) import Data.Tuple (Tuple(..))
import Gargantext.Config (TabType(..), TabSubType(..), PTabNgramType(..)) import Gargantext.Config (TabType(..), TabSubType(..), PTabNgramType(..), CTabNgramType(..))
import Gargantext.Components.DocsTable as DT import Gargantext.Components.DocsTable as DT
import Gargantext.Components.NgramsTable as NT import Gargantext.Components.NgramsTable as NT
import Gargantext.Components.Tab as Tab import Gargantext.Components.Tab as Tab
import Gargantext.Pages.Annuaire.User.Contacts.Types (Props) import Gargantext.Pages.Annuaire.User.Contacts.Types (ContactData)
import Thermite (Spec, focus, hideState, noState, cmapProps) import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
import React (Children, ReactElement, ReactClass, createElement)
import Thermite (Spec, focus, hideState, noState, cmapProps, createClass)
data Mode = Patents | Books | Communication data Mode = Patents | Books | Communication
...@@ -29,6 +35,27 @@ modeTabType Patents = PTabPatents ...@@ -29,6 +35,27 @@ modeTabType Patents = PTabPatents
modeTabType Books = PTabBooks modeTabType Books = PTabBooks
modeTabType Communication = PTabCommunication modeTabType Communication = PTabCommunication
-- TODO fix this type
modeTabType' :: Mode -> CTabNgramType
modeTabType' Patents = CTabAuthors
modeTabType' Books = CTabAuthors
modeTabType' Communication = CTabAuthors
type PropsRow =
( nodeId :: Int
, contactData :: ContactData
)
type Props = Record PropsRow
elt :: Props -> ReactElement
elt props = createElement tabsClass props []
tabsClass :: ReactClass { children :: Children | PropsRow }
tabsClass = createClass "ContactsTabs" pureTabs (const {})
pureTabs :: Spec {} Props Void pureTabs :: Spec {} Props Void
pureTabs = hideState (const {activeTab: 0}) statefulTabs pureTabs = hideState (const {activeTab: 0}) statefulTabs
...@@ -44,17 +71,21 @@ statefulTabs = ...@@ -44,17 +71,21 @@ statefulTabs =
where where
chart = mempty chart = mempty
-- TODO totalRecords -- TODO totalRecords
docs = cmapProps (\{path: nodeId, loaded} -> docs = noState $ R2.elSpec $ R.hooksComponent "DocViewSpecWithCorpus" $ \{nodeId, contactData: {defaultListId}} _ -> do
{ nodeId, chart pure $ DT.docViewSpec
, tabType: TabPairing TabDocs { nodeId
, totalRecords: 4736 , chart
, listId: loaded.defaultListId}) $ , tabType: TabPairing TabDocs
noState DT.docViewSpec , totalRecords: 4736
, listId: defaultListId
, corpusId: Nothing
, showSearch: true
}
ngramsViewSpec :: {mode :: Mode} -> Spec Tab.State Props Tab.Action ngramsViewSpec :: {mode :: Mode} -> Spec Tab.State Props Tab.Action
ngramsViewSpec {mode} = ngramsViewSpec {mode} =
cmapProps (\{loaded: {defaultListId}, path, dispatch} -> cmapProps (\{contactData: {defaultListId}, nodeId} ->
{loaded: {defaultListId}, path, dispatch, tabType}) {defaultListId, nodeId, tabType})
(noState NT.mainNgramsTableSpec) (noState (NT.mainNgramsTableSpec (modeTabType' mode)))
where where
tabType = TabPairing $ TabNgramType $ modeTabType mode tabType = TabPairing $ TabNgramType $ modeTabType mode
...@@ -162,13 +162,9 @@ instance decodeUser :: DecodeJson Contact where ...@@ -162,13 +162,9 @@ instance decodeUser :: DecodeJson Contact where
name <- obj .?? "name" name <- obj .?? "name"
date <- obj .?| "date" date <- obj .?| "date"
hyperdata <- obj .? "hyperdata" hyperdata <- obj .? "hyperdata"
pure $ Contact { id, typename, userId pure $ Contact { id, typename, userId
, parentId, name, date , parentId, name, date
, hyperdata , hyperdata
} }
type ContactData = {contactNode :: Contact, defaultListId :: Int} type ContactData = {contactNode :: Contact, defaultListId :: Int}
type PropsRow = Loader.InnerPropsRow Int ContactData ()
type Props = Record PropsRow
module Gargantext.Pages.Corpus where module Gargantext.Pages.Corpus where
import Data.Array (head) import Data.Array (head)
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
import Effect.Aff (Aff, throwError) import Effect.Aff (Aff, throwError)
import Effect.Exception (error) import Effect.Exception (error)
import React as React import Reactix as R
import React (ReactClass, ReactElement) import Reactix.DOM.HTML as H
import Thermite (Spec, Render, simpleSpec, createClass, defaultPerformAction) import Thermite (Spec)
-------------------------------------------------------- --------------------------------------------------------
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Components.Node (NodePoly(..), HyperdataList(..)) import Gargantext.Components.Node (NodePoly(..), HyperdataList)
import Gargantext.Components.Loader as Loader import Gargantext.Components.Loader2 (useLoader)
import Gargantext.Components.Loader (createLoaderClass)
import Gargantext.Components.Table as Table import Gargantext.Components.Table as Table
import Gargantext.Config (toUrl, Path(..), NodeType(..), End(..)) import Gargantext.Config (toUrl, Path(..), NodeType(..), End(..))
import Gargantext.Config.REST (get) import Gargantext.Config.REST (get)
import Gargantext.Pages.Corpus.Tabs.Types (CorpusData, CorpusInfo(..)) import Gargantext.Pages.Texts.Tabs.Types (CorpusData, CorpusInfo(..))
import Gargantext.Pages.Corpus.Tabs.Types (Props) as Tabs import Gargantext.Pages.Texts.Tabs.Specs (elt) as Tabs
import Gargantext.Pages.Corpus.Tabs.Specs (pureTabs) as Tabs import Gargantext.Utils.Reactix as R2
-------------------------------------------------------------------
type Props = Tabs.Props
------------------------------------------------------------------------ ------------------------------------------------------------------------
layout :: Spec {} {nodeId :: Int} Void layout :: Spec {} {nodeId :: Int} Void
layout = simpleSpec defaultPerformAction render layout = R2.elSpec $ R.hooksComponent "CorpusLoader" cpt
where where
render :: Render {} {nodeId :: Int} Void cpt {nodeId} _children = do
render _ {nodeId} _ _ = pure $ H.div {} [H.text "Empty page"]
[ corpusLoader { path: nodeId
, component: createClass "Layout" layout' (const {})
} ]
layout' :: Spec {} Props Void
layout' = corpusHeaderSpec <> Tabs.pureTabs
corpusHeaderSpec :: Spec {} Props Void
corpusHeaderSpec = simpleSpec defaultPerformAction render
where
render :: Render {} Props Void
render dispatch {loaded: {corpusNode}} _ _ =
Table.renderTableHeaderLayout
{ title: "Corpus " <> title
, desc: corpus.desc
, query: corpus.query
, date: date'
, user: corpus.authors
}
where
NodePoly { name: title
, date: date'
, hyperdata : CorpusInfo corpus
}
= corpusNode
------------------------------------------------------------------------
getCorpus :: Int -> Aff CorpusData
getCorpus corpusId = do
corpusNode <- get $ toUrl Back Corpus $ Just corpusId
defaultListIds <- get $ toUrl Back (Children NodeList 0 1 Nothing) $ Just corpusId
case (head defaultListIds :: Maybe (NodePoly HyperdataList)) of
Just (NodePoly { id: defaultListId }) ->
pure {corpusNode, defaultListId}
Nothing ->
throwError $ error "Missing default list"
corpusLoaderClass :: ReactClass (Loader.Props Int CorpusData)
corpusLoaderClass = createLoaderClass "CorpusLoader" getCorpus
corpusLoader :: Loader.Props' Int CorpusData -> ReactElement
corpusLoader props = React.createElement corpusLoaderClass props []
module Gargantext.Pages.Corpus.Chart.Histo where module Gargantext.Pages.Corpus.Chart.Histo where
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
import Data.Array (foldl) import Data.Array (foldl)
import Data.Tuple (Tuple(..))
import Data.Map as Map
import Data.Int (toNumber) import Data.Int (toNumber)
import Data.Map as Map
import Data.Map (Map) import Data.Map (Map)
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
import Data.Maybe (Maybe(..), maybe) import Data.Maybe (Maybe(..), maybe)
import Data.Tuple (Tuple(..))
import Effect.Aff (Aff) import Effect.Aff (Aff)
import Gargantext.Config -- (End(..), Path(..), TabType, toUrl) import Gargantext.Config -- (End(..), Path(..), TabType, toUrl)
import Gargantext.Config.REST (get) import Gargantext.Config.REST (get)
import React (ReactClass, ReactElement, createElement) import React (ReactClass, ReactElement, createElement)
import Thermite (Spec, Render, defaultPerformAction, simpleSpec, createClass) import Reactix as R
import Reactix.DOM.HTML as H
import Thermite (Spec)
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Types (TermList(..)) import Gargantext.Types (TermList(..))
import Gargantext.Components.Loader as Loader import Gargantext.Components.Loader as Loader
import Gargantext.Components.Loader2 (useLoader)
import Gargantext.Components.Charts.Options.ECharts import Gargantext.Components.Charts.Options.ECharts
import Gargantext.Components.Charts.Options.Type import Gargantext.Components.Charts.Options.Type
import Gargantext.Components.Charts.Options.Series import Gargantext.Components.Charts.Options.Series
import Gargantext.Components.Charts.Options.Color import Gargantext.Components.Charts.Options.Color
import Gargantext.Components.Charts.Options.Font import Gargantext.Components.Charts.Options.Font
import Gargantext.Components.Charts.Options.Data import Gargantext.Components.Charts.Options.Data
import Gargantext.Utils.Reactix as R2
import Gargantext.Pages.Corpus.Chart.Utils as U
type Path = type Path =
{ corpusId :: Int { corpusId :: Int
...@@ -51,12 +57,6 @@ instance decodeHistoMetrics :: DecodeJson HistoMetrics where ...@@ -51,12 +57,6 @@ instance decodeHistoMetrics :: DecodeJson HistoMetrics where
type Loaded = HistoMetrics type Loaded = HistoMetrics
loadedMetricsSpec :: Spec {} (Loader.InnerProps Path Loaded ()) Void
loadedMetricsSpec = simpleSpec defaultPerformAction render
where
render :: Render {} (Loader.InnerProps Path Loaded ()) Void
render dispatch {loaded:histoMetrics} {} _ = [chart (chartOptions histoMetrics)]
chartOptions :: HistoMetrics -> Options chartOptions :: HistoMetrics -> Options
chartOptions (HistoMetrics { dates: dates', count: count'}) = Options chartOptions (HistoMetrics { dates: dates', count: count'}) = Options
{ mainTitle : "Histogram" { mainTitle : "Histogram"
...@@ -68,23 +68,27 @@ chartOptions (HistoMetrics { dates: dates', count: count'}) = Options ...@@ -68,23 +68,27 @@ chartOptions (HistoMetrics { dates: dates', count: count'}) = Options
, tooltip : mkTooltip { formatter: templateFormatter "{b0}" } , tooltip : mkTooltip { formatter: templateFormatter "{b0}" }
} }
metricsLoader :: Loader.Props' Path HistoMetrics -> ReactElement
metricsLoader props = createElement metricsLoaderClass props []
where
metricsLoaderClass :: ReactClass (Loader.Props Path HistoMetrics)
metricsLoaderClass = Loader.createLoaderClass "MetricsLoader" getMetrics
getMetrics :: Path -> Aff HistoMetrics getMetrics :: Path -> Aff HistoMetrics
getMetrics {corpusId, tabType} = do getMetrics {corpusId, tabType} = do
ChartMetrics ms <- get $ toUrl Back (Chart {chartType: Histo, tabType: tabType}) $ Just corpusId ChartMetrics ms <- get $ toUrl Back (Chart {chartType: Histo, tabType: tabType}) $ Just corpusId
pure ms."data" pure ms."data"
histoSpec :: Spec {} Path Void histoSpec :: Spec {} Path Void
histoSpec = simpleSpec defaultPerformAction render histoSpec = R2.elSpec $ R.hooksComponent "LoadedMetricsHisto" cpt
where where
render :: Render {} Path Void cpt p _ = do
render dispatch path {} _ = setReload <- R.useState' 0
[ metricsLoader
{ path pure $ metricsLoadView setReload p
, component: createClass "LoadedMetrics" loadedMetricsSpec (const {})
} ] metricsLoadView :: R.State Int -> Path -> R.Element
metricsLoadView setReload p = R.createElement el p []
where
el = R.hooksComponent "MetricsLoadedHistoView" cpt
cpt p _ = do
useLoader p getMetrics $ \{loaded} ->
loadedMetricsView setReload loaded
loadedMetricsView :: R.State Int -> HistoMetrics -> R.Element
loadedMetricsView setReload loaded = U.reloadButtonWrap setReload $ R2.buff $ chart $ chartOptions loaded
module Gargantext.Pages.Corpus.Chart.Metrics where module Gargantext.Pages.Corpus.Chart.Metrics where
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
import Data.Array (foldl) import Data.Array (foldl)
import Data.Tuple (Tuple(..))
import Data.Map as Map import Data.Map as Map
import Data.Map (Map) import Data.Map (Map)
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
import Data.Maybe (Maybe(..), maybe) import Data.Maybe (Maybe(..), maybe)
import Data.Tuple (Tuple(..))
import Effect.Aff (Aff) import Effect.Aff (Aff)
import Gargantext.Config -- (End(..), Path(..), TabType, toUrl) import Gargantext.Config -- (End(..), Path(..), TabType, toUrl)
import Gargantext.Config.REST (get) import Gargantext.Config.REST (get)
import React (ReactClass, ReactElement, createElement) import React (ReactClass, ReactElement, createElement)
import Thermite (Spec, Render, defaultPerformAction, simpleSpec, createClass) import Reactix as R
import Reactix.DOM.HTML as H
import Thermite (Spec)
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Types (TermList(..)) import Gargantext.Types (TermList(..))
import Gargantext.Components.Loader2 (useLoader)
import Gargantext.Components.Loader as Loader import Gargantext.Components.Loader as Loader
import Gargantext.Components.Charts.Options.ECharts import Gargantext.Components.Charts.Options.ECharts
import Gargantext.Components.Charts.Options.Type import Gargantext.Components.Charts.Options.Type
...@@ -20,6 +24,8 @@ import Gargantext.Components.Charts.Options.Series ...@@ -20,6 +24,8 @@ import Gargantext.Components.Charts.Options.Series
import Gargantext.Components.Charts.Options.Color import Gargantext.Components.Charts.Options.Color
import Gargantext.Components.Charts.Options.Font import Gargantext.Components.Charts.Options.Font
import Gargantext.Components.Charts.Options.Data import Gargantext.Components.Charts.Options.Data
import Gargantext.Utils.Reactix as R2
import Gargantext.Pages.Corpus.Chart.Utils as U
type Path = type Path =
{ corpusId :: Int { corpusId :: Int
...@@ -56,12 +62,6 @@ instance decodeMetrics :: DecodeJson Metrics where ...@@ -56,12 +62,6 @@ instance decodeMetrics :: DecodeJson Metrics where
type Loaded = Array Metric type Loaded = Array Metric
loadedMetricsSpec :: Spec {} (Loader.InnerProps Path Loaded ()) Void
loadedMetricsSpec = simpleSpec defaultPerformAction render
where
render :: Render {} (Loader.InnerProps Path Loaded ()) Void
render dispatch {loaded} {} _ = [chart (scatterOptions loaded)]
scatterOptions :: Array Metric -> Options scatterOptions :: Array Metric -> Options
scatterOptions metrics = Options scatterOptions metrics = Options
{ mainTitle : "Ngrams Selection Metrics" { mainTitle : "Ngrams Selection Metrics"
...@@ -101,18 +101,21 @@ getMetrics {corpusId, listId, limit, tabType} = do ...@@ -101,18 +101,21 @@ getMetrics {corpusId, listId, limit, tabType} = do
Metrics ms <- get $ toUrl Back (CorpusMetrics {listId, tabType, limit}) $ Just corpusId Metrics ms <- get $ toUrl Back (CorpusMetrics {listId, tabType, limit}) $ Just corpusId
pure ms."data" pure ms."data"
metricsLoaderClass :: ReactClass (Loader.Props Path Loaded)
metricsLoaderClass = Loader.createLoaderClass "MetricsLoader" getMetrics
metricsLoader :: Loader.Props' Path Loaded -> ReactElement metricsSpec = R2.elSpec $ R.hooksComponent "LoadedMetrics" cpt
metricsLoader props = createElement metricsLoaderClass props [] where
cpt p _ = do
setReload <- R.useState' 0
metricsSpec :: Spec {} Path Void pure $ metricsLoadView setReload p
metricsSpec = simpleSpec defaultPerformAction render
metricsLoadView :: R.State Int -> Path -> R.Element
metricsLoadView setReload p = R.createElement el p []
where where
render :: Render {} Path Void el = R.hooksComponent "MetricsLoadedView" cpt
render dispatch path {} _ = cpt p _ = do
[ metricsLoader useLoader p getMetrics $ \{loaded} ->
{ path loadedMetricsView setReload loaded
, component: createClass "LoadedMetrics" loadedMetricsSpec (const {})
} ] loadedMetricsView :: R.State Int -> Loaded -> R.Element
loadedMetricsView setReload loaded = U.reloadButtonWrap setReload $ R2.buff $ chart $ scatterOptions loaded
module Gargantext.Pages.Corpus.Chart.Pie where module Gargantext.Pages.Corpus.Chart.Pie where
import Data.String (take, joinWith, Pattern(..), split, length) import Data.Argonaut (class DecodeJson, decodeJson, (.?))
import Data.Array (foldl, zip, filter) import Data.Array (foldl, zip, filter)
import Data.Array as A import Data.Array as A
import Data.Tuple (Tuple(..))
import Data.Map as Map
import Data.Int (toNumber) import Data.Int (toNumber)
import Data.Map (Map)
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
import Data.Maybe (Maybe(..), maybe) import Data.Maybe (Maybe(..), maybe)
import Data.String (take, joinWith, Pattern(..), split, length)
import Data.Tuple (Tuple(..))
import Effect.Aff (Aff) import Effect.Aff (Aff)
import Gargantext.Config -- (End(..), Path(..), TabType, toUrl) import Gargantext.Config -- (End(..), Path(..), TabType, toUrl)
import Gargantext.Config.REST (get) import Gargantext.Config.REST (get)
import React (ReactClass, ReactElement, createElement) import React (ReactClass, ReactElement, createElement)
import Thermite (Spec, Render, defaultPerformAction, simpleSpec, createClass) import Reactix as R
import Reactix.DOM.HTML as H
import Thermite (Spec)
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Types (TermList(..)) import Gargantext.Types (TermList(..))
import Gargantext.Components.Loader as Loader import Gargantext.Components.Loader2 (useLoader)
import Gargantext.Components.Charts.Options.ECharts import Gargantext.Components.Charts.Options.ECharts
import Gargantext.Components.Charts.Options.Type import Gargantext.Components.Charts.Options.Type
import Gargantext.Components.Charts.Options.Series import Gargantext.Components.Charts.Options.Series
import Gargantext.Components.Charts.Options.Color import Gargantext.Components.Charts.Options.Color
import Gargantext.Components.Charts.Options.Font import Gargantext.Components.Charts.Options.Font
import Gargantext.Components.Charts.Options.Data import Gargantext.Components.Charts.Options.Data
import Gargantext.Utils.Reactix as R2
import Gargantext.Pages.Corpus.Chart.Utils as U
type Path = type Path =
{ corpusId :: Int { corpusId :: Int
...@@ -53,14 +56,8 @@ instance decodeHistoMetrics :: DecodeJson HistoMetrics where ...@@ -53,14 +56,8 @@ instance decodeHistoMetrics :: DecodeJson HistoMetrics where
type Loaded = HistoMetrics type Loaded = HistoMetrics
loadedMetricsSpec :: Spec {} (Loader.InnerProps Path Loaded ()) Void chartOptionsBar :: HistoMetrics -> Options
loadedMetricsSpec = simpleSpec defaultPerformAction render chartOptionsBar (HistoMetrics { dates: dates', count: count'}) = Options
where
render :: Render {} (Loader.InnerProps Path Loaded ()) Void
render dispatch {loaded : metricsData} {} _ = [chart (chartOptions metricsData)]
chartOptions :: HistoMetrics -> Options
chartOptions (HistoMetrics { dates: dates', count: count'}) = Options
{ mainTitle : "Bar" { mainTitle : "Bar"
, subTitle : "Count of GraphTerm" , subTitle : "Count of GraphTerm"
, xAxis : xAxis' $ map (\t -> joinWith " " $ map (take 3) $ A.take 3 $ filter (\s -> length s > 3) $ split (Pattern " ") t) dates' , xAxis : xAxis' $ map (\t -> joinWith " " $ map (take 3) $ A.take 3 $ filter (\s -> length s > 3) $ split (Pattern " ") t) dates'
...@@ -70,12 +67,6 @@ chartOptions (HistoMetrics { dates: dates', count: count'}) = Options ...@@ -70,12 +67,6 @@ chartOptions (HistoMetrics { dates: dates', count: count'}) = Options
, tooltip : mkTooltip { formatter: templateFormatter "{b0}" } , tooltip : mkTooltip { formatter: templateFormatter "{b0}" }
} }
loadedMetricsSpecPie :: Spec {} (Loader.InnerProps Path Loaded ()) Void
loadedMetricsSpecPie = simpleSpec defaultPerformAction render
where
render :: Render {} (Loader.InnerProps Path Loaded ()) Void
render dispatch {loaded : metricsData} {} _ = [chart (chartOptionsPie metricsData)]
chartOptionsPie :: HistoMetrics -> Options chartOptionsPie :: HistoMetrics -> Options
chartOptionsPie (HistoMetrics { dates: dates', count: count'}) = Options chartOptionsPie (HistoMetrics { dates: dates', count: count'}) = Options
{ mainTitle : "Pie" { mainTitle : "Pie"
...@@ -89,34 +80,50 @@ chartOptionsPie (HistoMetrics { dates: dates', count: count'}) = Options ...@@ -89,34 +80,50 @@ chartOptionsPie (HistoMetrics { dates: dates', count: count'}) = Options
} }
metricsLoader :: Loader.Props' Path HistoMetrics -> ReactElement getMetrics :: Path -> Aff HistoMetrics
metricsLoader props = createElement metricsLoaderClass props [] getMetrics {corpusId, tabType:tabType} = do
where ChartMetrics ms <- get $ toUrl Back (Chart {chartType: ChartPie, tabType: tabType}) $ Just corpusId
metricsLoaderClass :: ReactClass (Loader.Props Path HistoMetrics) pure ms."data"
metricsLoaderClass = Loader.createLoaderClass "MetricsLoader" getMetrics
getMetrics :: Path -> Aff HistoMetrics
getMetrics {corpusId, tabType:tabType} = do
ChartMetrics ms <- get $ toUrl Back (Chart {chartType: ChartPie, tabType: tabType}) $ Just corpusId
pure ms."data"
pieSpec :: Spec {} Path Void pieSpec :: Spec {} Path Void
pieSpec = simpleSpec defaultPerformAction render pieSpec = R2.elSpec $ R.hooksComponent "LoadedMetricsPie" cpt
where
cpt p _ = do
setReload <- R.useState' 0
pure $ metricsLoadPieView setReload p
metricsLoadPieView :: R.State Int -> Path -> R.Element
metricsLoadPieView setReload p = R.createElement el p []
where where
render :: Render {} Path Void el = R.hooksComponent "MetricsLoadedPieView" cpt
render dispatch path {} _ = cpt p _ = do
[ metricsLoader useLoader p getMetrics $ \{loaded} ->
{ path loadedMetricsPieView setReload loaded
, component: createClass "LoadedMetrics" loadedMetricsSpecPie (const {})
} ] loadedMetricsPieView :: R.State Int -> HistoMetrics -> R.Element
loadedMetricsPieView setReload loaded = U.reloadButtonWrap setReload $ R2.buff $ chart $ chartOptionsPie loaded
barSpec :: Spec {} Path Void barSpec :: Spec {} Path Void
barSpec = simpleSpec defaultPerformAction render barSpec = R2.elSpec $ R.hooksComponent "LoadedMetricsBar" cpt
where
cpt p _ = do
setReload <- R.useState' 0
pure $ metricsLoadBarView setReload p
metricsLoadBarView :: R.State Int -> Path -> R.Element
metricsLoadBarView setReload p = R.createElement el p []
where where
render :: Render {} Path Void el = R.hooksComponent "MetricsLoadedBarView" cpt
render dispatch path {} _ = cpt p _ = do
[ metricsLoader useLoader p getMetrics $ \{loaded} ->
{ path loadedMetricsBarView setReload loaded
, component: createClass "LoadedMetrics" loadedMetricsSpec (const {})
} ]
loadedMetricsBarView :: R.State Int -> Loaded -> R.Element
loadedMetricsBarView setReload loaded = U.reloadButtonWrap setReload $ R2.buff $ chart $ chartOptionsBar loaded
module Gargantext.Pages.Corpus.Chart.Tree where module Gargantext.Pages.Corpus.Chart.Tree where
import Data.Array (foldl) import Data.Array (foldl)
import Data.Tuple (Tuple(..))
import Data.Map as Map import Data.Map as Map
import Data.Map (Map) import Data.Map (Map)
import Data.Argonaut (class DecodeJson, decodeJson, (.?)) import Data.Argonaut (class DecodeJson, decodeJson, (.?))
import Data.Maybe (Maybe(..), maybe) import Data.Maybe (Maybe(..), maybe)
import Data.Tuple (Tuple(..))
import Effect.Aff (Aff) import Effect.Aff (Aff)
import Gargantext.Config -- (End(..), Path(..), TabType, toUrl) import Gargantext.Config -- (End(..), Path(..), TabType, toUrl)
import Gargantext.Config.REST (get) import Gargantext.Config.REST (get)
import React (ReactClass, ReactElement, createElement) import React (ReactClass, ReactElement, createElement)
import Thermite (Spec, Render, defaultPerformAction, simpleSpec, createClass) import Reactix as R
import Reactix.DOM.HTML as H
import Thermite (Spec)
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Types (TermList(..)) import Gargantext.Types (TermList(..))
import Gargantext.Components.Loader as Loader import Gargantext.Components.Loader2 (useLoader)
import Gargantext.Components.Charts.Options.ECharts import Gargantext.Components.Charts.Options.ECharts
import Gargantext.Components.Charts.Options.Type import Gargantext.Components.Charts.Options.Type
import Gargantext.Components.Charts.Options.Series import Gargantext.Components.Charts.Options.Series
import Gargantext.Components.Charts.Options.Color import Gargantext.Components.Charts.Options.Color
import Gargantext.Components.Charts.Options.Font import Gargantext.Components.Charts.Options.Font
import Gargantext.Components.Charts.Options.Data import Gargantext.Components.Charts.Options.Data
import Gargantext.Utils.Reactix as R2
import Gargantext.Pages.Corpus.Dashboard (treeMapEx) import Gargantext.Pages.Corpus.Chart.Utils as U
type Path = type Path =
...@@ -44,12 +47,6 @@ instance decodeMetrics :: DecodeJson Metrics where ...@@ -44,12 +47,6 @@ instance decodeMetrics :: DecodeJson Metrics where
type Loaded = Array TreeNode type Loaded = Array TreeNode
loadedMetricsSpec :: Spec {} (Loader.InnerProps Path Loaded ()) Void
loadedMetricsSpec = simpleSpec defaultPerformAction render
where
render :: Render {} (Loader.InnerProps Path Loaded ()) Void
render dispatch {loaded} {} _ = [chart (scatterOptions loaded)]
scatterOptions :: Array TreeNode -> Options scatterOptions :: Array TreeNode -> Options
scatterOptions nodes = Options scatterOptions nodes = Options
{ mainTitle : "Tree" { mainTitle : "Tree"
...@@ -69,18 +66,24 @@ getMetrics {corpusId, listId, limit, tabType} = do ...@@ -69,18 +66,24 @@ getMetrics {corpusId, listId, limit, tabType} = do
Metrics ms <- get $ toUrl Back (Chart {chartType : ChartTree, tabType: tabType}) $ Just corpusId Metrics ms <- get $ toUrl Back (Chart {chartType : ChartTree, tabType: tabType}) $ Just corpusId
pure ms."data" pure ms."data"
metricsLoaderClass :: ReactClass (Loader.Props Path Loaded) treeSpec :: Spec {} Path Void
metricsLoaderClass = Loader.createLoaderClass "MetricsLoader" getMetrics treeSpec = R2.elSpec $ R.hooksComponent "LoadedMetrics" cpt
where
cpt p _ = do
setReload <- R.useState' 0
metricsLoader :: Loader.Props' Path Loaded -> ReactElement pure $ metricsLoadView setReload p
metricsLoader props = createElement metricsLoaderClass props []
treeSpec :: Spec {} Path Void metricsLoadView :: R.State Int -> Path -> R.Element
treeSpec = simpleSpec defaultPerformAction render metricsLoadView setReload p = R.createElement el p []
where where
render :: Render {} Path Void el = R.hooksComponent "MetricsLoadView" cpt
render dispatch path {} _ = cpt p _ = do
[ metricsLoader useLoader p getMetrics $ \{loaded} ->
{ path loadedMetricsView setReload loaded
, component: createClass "LoadedMetrics" loadedMetricsSpec (const {})
} ] loadedMetricsView :: R.State Int -> Loaded -> R.Element
loadedMetricsView setReload loaded = H.div {} [
U.reloadButton setReload
, R2.buff $ chart (scatterOptions loaded)
]
module Gargantext.Pages.Corpus.Chart.Utils where
import Data.Tuple.Nested ((/\))
import Effect.Uncurried (mkEffectFn1)
import Reactix as R
import Reactix.DOM.HTML as H
import Gargantext.Prelude
reloadButtonWrap :: R.State Int -> R.Element -> R.Element
reloadButtonWrap setReload el = H.div {} [
reloadButton setReload
, el
]
reloadButton :: R.State Int -> R.Element
reloadButton (_ /\ setReload) = H.a {className, onClick, title: "Reload"} []
where
className = "reload-btn glyphicon glyphicon-refresh"
onClick = mkEffectFn1 $ \_ -> setReload $ \r -> r + 1
...@@ -3,28 +3,26 @@ module Gargantext.Pages.Corpus.Document where ...@@ -3,28 +3,26 @@ module Gargantext.Pages.Corpus.Document where
import Data.Argonaut (class DecodeJson, decodeJson, (.:), (.:?)) import Data.Argonaut (class DecodeJson, decodeJson, (.:), (.:?))
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow) import Data.Generic.Rep.Show (genericShow)
import Data.Map as Map
import Data.Maybe (Maybe(..), maybe) import Data.Maybe (Maybe(..), maybe)
import Effect.Aff (Aff) import Effect.Aff (Aff)
import React (ReactElement, ReactClass) import React (ReactClass, Children)
import React as React
import React.DOM (div, h4, li, p, span, text, ul) import React.DOM (div, h4, li, p, span, text, ul)
import React.DOM.Props (className) import React.DOM.Props (className)
import Thermite (PerformAction, Render, Spec, simpleSpec, cmapProps, defaultPerformAction, createClass) import Reactix as R
import Control.Monad.Trans.Class (lift) import Thermite (PerformAction, Render, Spec, simpleSpec, cmapProps, createClass)
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Config (toUrl, NodeType(..), End(..), TabSubType(..), TabType(..), CTabNgramType(..)) import Gargantext.Config (toUrl, NodeType(..), End(..), TabSubType(..), TabType(..), CTabNgramType(..), CTabNgramType(..))
import Gargantext.Config.REST (get) import Gargantext.Config.REST (get)
import Gargantext.Components.AutoUpdate (autoUpdateElt) import Gargantext.Components.AutoUpdate (autoUpdateElt)
import Gargantext.Components.Loader as Loader import Gargantext.Components.Loader2 (useLoader)
import Gargantext.Components.Node (NodePoly(..)) import Gargantext.Components.Node (NodePoly(..))
import Gargantext.Components.NgramsTable.Core import Gargantext.Components.NgramsTable.Core
import Gargantext.Components.Annotation.AnnotatedField as AnnotatedField import Gargantext.Components.Annotation.AnnotatedField as AnnotatedField
import Gargantext.Types (TermList) import Gargantext.Types (TermList)
import Gargantext.Utils.Reactix ( scuff ) import Gargantext.Utils.Reactix as R2
type DocPath = { nodeId :: Int, listIds :: Array Int, tabType :: TabType } type DocPath = { nodeId :: Int, listIds :: Array Int, corpusId :: Maybe Int, tabType :: TabType }
type NodeDocument = NodePoly Document type NodeDocument = NodePoly Document
...@@ -32,7 +30,10 @@ type LoadedData = ...@@ -32,7 +30,10 @@ type LoadedData =
{ document :: NodeDocument { document :: NodeDocument
, ngramsTable :: VersionedNgramsTable } , ngramsTable :: VersionedNgramsTable }
type LoadedDataProps = Loader.InnerProps DocPath LoadedData () type Props =
{ loaded :: LoadedData
, path :: DocPath
}
-- This is a subpart of NgramsTable.State. -- This is a subpart of NgramsTable.State.
type State = CoreState () type State = CoreState ()
...@@ -273,24 +274,24 @@ instance decodeDocument :: DecodeJson Document ...@@ -273,24 +274,24 @@ instance decodeDocument :: DecodeJson Document
--, text --, text
} }
docViewSpec :: Spec State LoadedDataProps Action docViewSpec :: Spec State Props Action
docViewSpec = simpleSpec performAction render docViewSpec = simpleSpec performAction render
where where
performAction :: PerformAction State LoadedDataProps Action performAction :: PerformAction State Props Action
performAction Refresh {path: {nodeId, listIds, tabType}} {ngramsVersion} = do performAction Refresh {path: {nodeId, listIds, tabType}} {ngramsVersion} = do
commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: mempty}) commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: mempty})
performAction (SetTermListItem n pl) {path: {nodeId, listIds, tabType}} {ngramsVersion} = performAction (SetTermListItem n pl) {path: {nodeId, listIds, tabType}} {ngramsVersion} =
commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: pt}) commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: pt})
where where
pe = NgramsPatch { patch_list: pl, patch_children: mempty } pe = NgramsPatch { patch_list: pl, patch_children: mempty }
pt = PatchMap $ Map.singleton n pe pt = singletonNgramsTablePatch CTabTerms n pe
performAction (AddNewNgram ngram termList) {path: params} _ = performAction (AddNewNgram ngram termList) {path: {nodeId, listIds, tabType}} {ngramsVersion} =
lift $ addNewNgram ngram (Just termList) params commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: pt})
where
pt = addNewNgram CTabTerms ngram termList
render :: Render State LoadedDataProps Action render :: Render State Props Action
render dispatch { path: pageParams render dispatch { loaded: { ngramsTable: Versioned { data: initTable }, document } }
, loaded: { ngramsTable: Versioned { data: initTable }, document }
, dispatch: loaderDispatch }
{ ngramsTablePatch } { ngramsTablePatch }
_reactChildren = _reactChildren =
[ autoUpdateElt { duration: 3000 [ autoUpdateElt { duration: 3000
...@@ -327,23 +328,27 @@ docViewSpec = simpleSpec performAction render ...@@ -327,23 +328,27 @@ docViewSpec = simpleSpec performAction render
ngramsTable = applyNgramsTablePatch ngramsTablePatch initTable ngramsTable = applyNgramsTablePatch ngramsTablePatch initTable
setTermList ngram Nothing newList = dispatch $ AddNewNgram ngram newList setTermList ngram Nothing newList = dispatch $ AddNewNgram ngram newList
setTermList ngram (Just oldList) newList = dispatch $ SetTermListItem ngram (replace oldList newList) setTermList ngram (Just oldList) newList = dispatch $ SetTermListItem ngram (replace oldList newList)
annotate text = scuff $ AnnotatedField.annotatedField { ngrams: ngramsTable, setTermList, text } annotate text = R2.scuff $ AnnotatedField.annotatedField { ngrams: ngramsTable, setTermList, text }
li' = li [className "list-group-item justify-content-between"] li' = li [className "list-group-item justify-content-between"]
text' x = text $ maybe "Nothing" identity x text' x = text $ maybe "Nothing" identity x
badge s = span [className "badge badge-default badge-pill"] [text s] badge s = span [className "badge badge-default badge-pill"] [text s]
NodePoly {hyperdata : Document doc} = document NodePoly {hyperdata : Document doc} = document
layout :: Spec {} {nodeId :: Int, listId :: Int} Void docViewClass :: ReactClass
layout = cmapProps (\{nodeId, listId} -> {nodeId, listIds: [listId], tabType}) { children :: Children
$ simpleSpec defaultPerformAction render , loaded :: LoadedData
, path :: DocPath
}
docViewClass = createClass "DocumentView" docViewSpec initialState
layout :: Spec {} {nodeId :: Int, listId :: Int, corpusId :: Maybe Int} Void
layout =
cmapProps (\{nodeId, listId, corpusId} -> {nodeId, listIds: [listId], corpusId, tabType}) $
R2.elSpec $ R.hooksComponent "DocumentLoader" \path _ ->
useLoader path loadData $ \props ->
R2.createElement' docViewClass props []
where where
tabType = TabDocument (TabNgramType CTabTerms) tabType = TabDocument (TabNgramType CTabTerms)
render :: Render {} DocPath Void
render _ path _ _ =
[ documentLoader
{ path
, component: createClass "DocumentView" docViewSpec initialState
} ]
------------------------------------------------------------------------ ------------------------------------------------------------------------
...@@ -363,9 +368,3 @@ loadData {nodeId, listIds, tabType} = do ...@@ -363,9 +368,3 @@ loadData {nodeId, listIds, tabType} = do
, termSizeFilter : Nothing , termSizeFilter : Nothing
} }
pure {document, ngramsTable} pure {document, ngramsTable}
documentLoaderClass :: ReactClass (Loader.Props DocPath LoadedData)
documentLoaderClass = Loader.createLoaderClass "DocumentLoader" loadData
documentLoader :: Loader.Props' DocPath LoadedData -> ReactElement
documentLoader props = React.createElement documentLoaderClass props []
...@@ -244,29 +244,17 @@ render d p (State {sigmaGraphData, settings, legendData}) c = ...@@ -244,29 +244,17 @@ render d p (State {sigmaGraphData, settings, legendData}) c =
-- where -- where
-- treespec = over _render \frender d p (State s) c -> -- treespec = over _render \frender d p (State s) c ->
-- [ div [ className "col-md-2", _id "graph-tree", style {marginTop: "65px"}] $ -- graphspec = over _render \frender d p s c -> [
-- [ -- div [ className "col-md-9"] (frender d p s c)
-- button [className "btn btn-primary" , onClick \_ -> d ToggleTree] -- ]
-- [text $ if s.showTree then "Hide Tree" else "Show Tree"] -- treeSpec :: Spec State {} Action
-- ] -- treeSpec = withState \(State st) ->
-- <> -- case st.treeId of
-- if s.showTree then (frender d p (State s) c) else [] -- Nothing ->
-- ] -- simpleSpec defaultPerformAction defaultRender
-- Just treeId ->
-- cmapProps (const {root: treeId, mCurrentRoute: Nothing}) $ noState $ Tree.treeview
-- graphspec = over _render \frender d p s c -> [
-- div [ className "col-md-9"] (frender d p s c)
-- ]
-- treeSpec :: Spec State {} Action
-- treeSpec = withState \(State st) ->
-- case st.treeId of
-- Nothing ->
-- simpleSpec defaultPerformAction defaultRender
-- Just treeId ->
-- (cmapProps (const {root: treeId}) (noState Tree.treeview))
-- render' :: Render State {} Action -- render' :: Render State {} Action
-- render' d _ (State st@{sigmaSettings, graphData: GraphData {sides,metaData }}) _ = -- render' d _ (State st@{sigmaSettings, graphData: GraphData {sides,metaData }}) _ =
-- [ div [className "container-fluid", style {paddingTop : "90px" }] -- [ div [className "container-fluid", style {paddingTop : "90px" }]
......
...@@ -4,7 +4,6 @@ import Prelude hiding (div) ...@@ -4,7 +4,6 @@ import Prelude hiding (div)
import Data.Lens (view) import Data.Lens (view)
import Data.List (fromFoldable) import Data.List (fromFoldable)
import Data.Tuple (Tuple(..)) import Data.Tuple (Tuple(..))
import Gargantext.Config (TabType(..), TabSubType(..))
import Gargantext.Components.GraphExplorer.Types (GraphSideCorpus(..)) import Gargantext.Components.GraphExplorer.Types (GraphSideCorpus(..))
import Gargantext.Components.FacetsTable (TextQuery, docViewSpec) import Gargantext.Components.FacetsTable (TextQuery, docViewSpec)
import Gargantext.Components.Table as T import Gargantext.Components.Table as T
......
module Gargantext.Pages.Corpus.Tabs
( module Gargantext.Pages.Corpus.Tabs.Specs
) where
import Gargantext.Pages.Corpus.Tabs.Specs
...@@ -10,14 +10,15 @@ import Gargantext.Components.Lang.Landing.EnUS as En ...@@ -10,14 +10,15 @@ import Gargantext.Components.Lang.Landing.EnUS as En
import Gargantext.Components.Lang.Landing.FrFR as Fr import Gargantext.Components.Lang.Landing.FrFR as Fr
import Gargantext.Components.Data.Landing (BlockText(..), BlockTexts(..), Button(..), LandingData(..)) import Gargantext.Components.Data.Landing (BlockText(..), BlockTexts(..), Button(..), LandingData(..))
import Gargantext.Components.Data.Lang (Lang(..)) import Gargantext.Components.Data.Lang (Lang(..))
import Gargantext.Pages.Home.States (State, initialState)
import Gargantext.Pages.Home.Actions (Action, performAction) import Gargantext.Pages.Home.Actions (Action, performAction)
import Reactix as R
import Reactix.DOM.HTML as H
import React (ReactElement) import React (ReactElement)
import React.DOM (a, div, h3, i, img, p, span, text) import React.DOM.Props (Props)
import React.DOM.Props (Props, _id, aria, className, href, src, target, title, height, width) import Thermite (Spec, hideState, focusState, Render, simpleSpec)
import Thermite (Render, Spec, simpleSpec, hideState, focusState)
import Gargantext.Utils.Reactix as R2
-- Layout | -- Layout |
...@@ -26,80 +27,82 @@ landingData FR = Fr.landingData ...@@ -26,80 +27,82 @@ landingData FR = Fr.landingData
landingData EN = En.landingData landingData EN = En.landingData
layoutLanding :: Lang -> Spec {} {} Void layoutLanding :: Lang -> Spec {} {} Void
layoutLanding = hideState (const $ unwrap initialState) layoutLanding = layoutLanding' <<< landingData
<<< focusState (re _Newtype)
<<< layoutLanding' <<< landingData
------------------------------------------------------------------------ ------------------------------------------------------------------------
layoutLanding' :: LandingData -> Spec State {} Action layoutLanding' :: LandingData -> Spec {} {} Void
layoutLanding' hd = simpleSpec performAction render layoutLanding' hd = R2.elSpec $ R.hooksComponent "LayoutLanding" cpt
where where
render :: Render State {} Action cpt {} _children = do
render dispatch _ state _ = pure $ H.span {} [
[ div [ className "container1" ] [ jumboTitle hd false ] H.div { className: "container1" }
, div [ className "container1" ] [] -- TODO put research form [ jumboTitle hd false ]
, div [ className "container1" ] [ blocksRandomText' hd ] , H.div { className: "container1" } [] -- TODO put research form
] , H.div { className: "container1" } [ blocksRandomText' hd ]
]
------------------------------------------------------------------------ ------------------------------------------------------------------------
blocksRandomText' :: LandingData -> ReactElement blocksRandomText' :: LandingData -> R.Element
blocksRandomText' (LandingData hd) = blocksRandomText hd.blockTexts blocksRandomText' (LandingData hd) = blocksRandomText hd.blockTexts
blocksRandomText :: BlockTexts -> ReactElement blocksRandomText :: BlockTexts -> R.Element
blocksRandomText (BlockTexts bt) = blocksRandomText (BlockTexts bt) =
div [ className "row" ] ( map showBlock bt.blocks ) H.div { className: "row" } ( map showBlock bt.blocks )
where where
showBlock :: BlockText -> ReactElement showBlock :: BlockText -> R.Element
showBlock (BlockText b) = showBlock (BlockText b) =
div [ className "col-md-4 content" ] H.div { className: "col-md-4 content" }
[ h3 [] [ a [ href b.href, title b.title] [ H.h3 {} [ H.a { href: b.href, title: b.title}
[ i [className b.icon] [] [ H.i {className: b.icon} []
, text (" " <> b.titleText) , H.text (" " <> b.titleText)
] ]
] ]
, p [] [ text b.text ] , H.p {} [ H.text b.text ]
, p [] [ docButton b.docButton ] , H.p {} [ docButton b.docButton ]
] ]
docButton :: Button -> ReactElement docButton :: Button -> R.Element
docButton (Button b) = a [ className "btn btn-outline-primary btn-sm spacing-class" docButton (Button b) =
, href b.href H.a { className: "btn btn-outline-primary btn-sm spacing-class"
, target "blank" , href: b.href
, title b.title , target: "blank"
] [ span [ aria {hidden : true} , title: b.title
, className "glyphicon glyphicon-hand-right" } [ H.span { aria: {hidden : true}
] [] , className: "glyphicon glyphicon-hand-right"
, text b.text } []
] , H.text b.text
]
jumboTitle :: LandingData -> Boolean -> ReactElement
jumboTitle (LandingData hd) b = div jumbo jumboTitle :: LandingData -> Boolean -> R.Element
[ div [className "row" ] jumboTitle (LandingData hd) b =
[ div [ className "col-md-12 content"] H.div {className: jumbo}
[ div [ className "center" ] [ H.div { className: "row" }
[ div [_id "logo-designed" ] [ H.div { className: "col-md-12 content" }
[ img [ src "images/logo.png" [ H.div { className: "center" }
, title hd.logoTitle [ H.div { id: "logo-designed" }
] [ H.img { src: "images/logo.png"
] , title: hd.logoTitle
] }
] ]
] ]
] ]
where ]
jumbo = case b of ]
true -> [className "jumbotron"] where
false -> [] jumbo = case b of
true -> "jumbotron"
imageEnter :: LandingData -> Props -> ReactElement false -> ""
imageEnter (LandingData hd) action = div [className "row"]
[ div [className "col-md-offset-5 col-md-6 content"] imageEnter :: LandingData -> Props -> R.Element
[ img [ src "images/Gargantextuel-212x300.jpg" imageEnter (LandingData hd) action =
, _id "funnyimg" H.div {className: "row"}
, title hd.imageTitle [ H.div {className: "col-md-offset-5 col-md-6 content"}
, action [ H.img { src: "images/Gargantextuel-212x300.jpg"
] , id: "funnyimg"
] , title: hd.imageTitle
] , action
}
]
]
...@@ -3,14 +3,12 @@ module Gargantext.Pages.Layout where ...@@ -3,14 +3,12 @@ module Gargantext.Pages.Layout where
import Prelude hiding (div) import Prelude hiding (div)
-- import Gargantext.Components.Login as LN -- import Gargantext.Components.Login as LN
import Gargantext.Pages.Layout.Actions (Action(..)) import Gargantext.Pages.Layout.Actions (Action(..))
import Gargantext.Pages.Layout.Specs.AddCorpus as AC
-- import Gargantext.Pages.Corpus.Tabs as TV -- import Gargantext.Pages.Corpus.Tabs as TV
import Gargantext.Pages.Corpus.Graph as GE import Gargantext.Pages.Corpus.Graph as GE
-- import Gargantext.Pages.Corpus.Tabs.Terms.NgramsTable as NG -- import Gargantext.Pages.Corpus.Tabs.Terms.NgramsTable as NG
-- import Gargantext.Pages.Home as L -- import Gargantext.Pages.Home as L
-- import Gargantext.Pages.Layout.Specs.Search as S
import Gargantext.Router (Routes(..)) import Gargantext.Router (Routes(..))
dispatchAction :: forall ignored m. dispatchAction :: forall ignored m.
...@@ -25,17 +23,9 @@ dispatchAction dispatcher _ Login = do ...@@ -25,17 +23,9 @@ dispatchAction dispatcher _ Login = do
dispatcher $ SetRoute Login dispatcher $ SetRoute Login
-- dispatcher $ LoginA TODO -- dispatcher $ LoginA TODO
dispatchAction dispatcher _ AddCorpus = do
dispatcher $ SetRoute AddCorpus
dispatcher $ AddCorpusA AC.LoadDatabaseDetails
dispatchAction dispatcher _ (Corpus n) = do dispatchAction dispatcher _ (Corpus n) = do
dispatcher $ SetRoute $ Corpus n dispatcher $ SetRoute $ Corpus n
dispatchAction dispatcher _ SearchView = do
dispatcher $ SetRoute SearchView
-- dispatcher $ SearchA TODO
dispatchAction dispatcher _ (UserPage id) = do dispatchAction dispatcher _ (UserPage id) = do
dispatcher $ SetRoute $ UserPage id dispatcher $ SetRoute $ UserPage id
...@@ -48,6 +38,9 @@ dispatchAction dispatcher _ (Annuaire id) = do ...@@ -48,6 +38,9 @@ dispatchAction dispatcher _ (Annuaire id) = do
dispatchAction dispatcher _ (Folder id) = do dispatchAction dispatcher _ (Folder id) = do
dispatcher $ SetRoute $ Folder id dispatcher $ SetRoute $ Folder id
dispatchAction dispatcher _ (CorpusDocument c i n) = do
dispatcher $ SetRoute $ CorpusDocument c i n
dispatchAction dispatcher _ (Document i n) = do dispatchAction dispatcher _ (Document i n) = do
dispatcher $ SetRoute $ Document i n dispatcher $ SetRoute $ Document i n
...@@ -56,5 +49,11 @@ dispatchAction dispatcher _ (PGraphExplorer nid) = do ...@@ -56,5 +49,11 @@ dispatchAction dispatcher _ (PGraphExplorer nid) = do
-- dispatcher $ GraphExplorerA $ GE.LoadGraph nid -- dispatcher $ GraphExplorerA $ GE.LoadGraph nid
--dispatcher $ GraphExplorerA $ GE.LoadGraph "imtNew.json" --dispatcher $ GraphExplorerA $ GE.LoadGraph "imtNew.json"
dispatchAction dispatcher _ (Texts nid) = do
dispatcher $ SetRoute $ Texts nid
dispatchAction dispatcher _ (Lists nid) = do
dispatcher $ SetRoute $ Lists nid
dispatchAction dispatcher _ Dashboard = do dispatchAction dispatcher _ Dashboard = do
dispatcher $ SetRoute Dashboard dispatcher $ SetRoute Dashboard
...@@ -12,9 +12,7 @@ import Routing.Hash (setHash) ...@@ -12,9 +12,7 @@ import Routing.Hash (setHash)
import Gargantext.Components.Login as LN import Gargantext.Components.Login as LN
import Gargantext.Components.Modals.Modal (modalShow) import Gargantext.Components.Modals.Modal (modalShow)
import Gargantext.Pages.Annuaire as Annuaire import Gargantext.Pages.Annuaire as Annuaire
--import Gargantext.Pages.Corpus.Graph as GE import Gargantext.Pages.Corpus.Graph as GE
import Gargantext.Pages.Layout.Specs.AddCorpus as AC
import Gargantext.Pages.Layout.Specs.Search as S
import Gargantext.Pages.Layout.States (AppState) import Gargantext.Pages.Layout.States (AppState)
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Router (Routes) import Gargantext.Router (Routes)
...@@ -24,9 +22,7 @@ import Gargantext.Router (Routes) ...@@ -24,9 +22,7 @@ import Gargantext.Router (Routes)
data Action data Action
= LoginA LN.Action = LoginA LN.Action
| SetRoute Routes | SetRoute Routes
| SearchA S.Action | GraphExplorerA GE.Action
| AddCorpusA AC.Action
-- | GraphExplorerA GE.Action
| AnnuaireAction Annuaire.Action | AnnuaireAction Annuaire.Action
| ShowLogin | ShowLogin
| Logout | Logout
...@@ -61,9 +57,7 @@ performAction ShowAddCorpus _ _ = void do ...@@ -61,9 +57,7 @@ performAction ShowAddCorpus _ _ = void do
--------------------------------------------------------- ---------------------------------------------------------
performAction (LoginA _) _ _ = pure unit performAction (LoginA _) _ _ = pure unit
performAction (AddCorpusA _) _ _ = pure unit performAction (GraphExplorerA _) _ _ = pure unit
performAction (SearchA _) _ _ = pure unit
-- performAction (GraphExplorerA _) _ _ = pure unit
performAction (AnnuaireAction _) _ _ = pure unit performAction (AnnuaireAction _) _ _ = pure unit
-- liftEffect $ modalShow "addCorpus" -- liftEffect $ modalShow "addCorpus"
-- modifyState $ _ {showCorpus = true} -- modifyState $ _ {showCorpus = true}
...@@ -76,18 +70,6 @@ _loginAction = prism LoginA \action -> ...@@ -76,18 +70,6 @@ _loginAction = prism LoginA \action ->
LoginA caction -> Right caction LoginA caction -> Right caction
_-> Left action _-> Left action
_addCorpusAction :: Prism' Action AC.Action
_addCorpusAction = prism AddCorpusA \action ->
case action of
AddCorpusA caction -> Right caction
_-> Left action
_searchAction :: Prism' Action S.Action
_searchAction = prism SearchA \action ->
case action of
SearchA caction -> Right caction
_-> Left action
_annuaireAction :: Prism' Action Annuaire.Action _annuaireAction :: Prism' Action Annuaire.Action
_annuaireAction = prism AnnuaireAction \action -> _annuaireAction = prism AnnuaireAction \action ->
case action of case action of
......
This diff is collapsed.
module Gargantext.Pages.Layout.Specs.AddCorpus
( module Gargantext.Pages.Layout.Specs.AddCorpus.States
, module Gargantext.Pages.Layout.Specs.AddCorpus.Actions
, module Gargantext.Pages.Layout.Specs.AddCorpus.Specs
) where
import Gargantext.Pages.Layout.Specs.AddCorpus.States
import Gargantext.Pages.Layout.Specs.AddCorpus.Actions
import Gargantext.Pages.Layout.Specs.AddCorpus.Specs
module Gargantext.Pages.Layout.Specs.AddCorpus.Actions where
import Control.Monad.Cont.Trans (lift)
import Data.Argonaut (class EncodeJson, jsonEmptyObject, (:=), (~>))
import Effect.Aff (Aff)
import Effect.Class (liftEffect)
import Routing.Hash (setHash)
import Thermite (PerformAction, modifyState)
import Gargantext.Prelude
import Gargantext.Config.REST (post)
import Gargantext.Components.Modals.Modal (modalHide)
import Gargantext.Pages.Layout.Specs.AddCorpus.States (Response, State)
data Action
= SelectDatabase Boolean
| UnselectDatabase Boolean
| LoadDatabaseDetails
| GO
performAction :: PerformAction State {} Action
performAction (SelectDatabase selected) _ _ = void do
modifyState $ _ { select_database = selected }
performAction (UnselectDatabase unselected) _ _ = void do
modifyState $ _ { unselect_database = unselected }
performAction (LoadDatabaseDetails) _ _ = do
res <- lift $ getDatabaseDetails $ QueryString { query_query: "string",query_name: ["Pubmed"]}
void $ modifyState $ _ {response = res}
performAction GO _ _ = do
liftEffect $ setHash "/corpus"
liftEffect $ modalHide "addCorpus"
pure unit
newtype QueryString = QueryString
{
query_query :: String
, query_name :: Array String
}
queryString :: QueryString
queryString = QueryString
{
query_query: "string",
query_name: [
"Pubmed"
]
}
instance encodeJsonQueryString :: EncodeJson QueryString where
encodeJson (QueryString obj) =
"query_query" := obj.query_query
~> "query_name" := obj.query_name
~> jsonEmptyObject
getDatabaseDetails :: QueryString -> Aff (Array Response)
getDatabaseDetails reqBody = do
-- TODO let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MTk5OTg1ODMsInVzZXJfaWQiOjUsImVtYWlsIjoiYWxleGFuZHJlLmRlbGFub2VAaXNjcGlmLmZyIiwidXNlcm5hbWUiOiJkZXZlbG9wZXIifQ.Os-3wuFNSmRIxCZi98oFNBu2zqGc0McO-dgDayozHJg"
post "http://localhost:8009/count" reqBody
module Gargantext.Pages.Layout.Specs.AddCorpus.Specs where
import Data.Lens (over)
import Effect.Aff (Aff)
import React (ReactElement)
import React.DOM (button, div, h3, h5, li, span, text, ul)
import React.DOM.Props (_data, _id, _type, aria, className, onClick, role)
import Thermite (Render, Spec, _render, simpleSpec)
import Gargantext.Prelude
import Gargantext.Config.REST (post)
import Gargantext.Pages.Layout.Specs.AddCorpus.Actions (Action(..), performAction)
import Gargantext.Pages.Layout.Specs.AddCorpus.States (Query, Response(..), State)
modalSpec :: Boolean -> String -> Spec State {} Action -> Spec State {} Action
modalSpec sm t = over _render \render d p s c ->
[ div [ _id "addCorpus", className $ "modal myModal" <> if sm then "" else " fade"
, role "dialog"
, _data {show : true}
][ div [ className "modal-dialog", role "document"]
[ div [ className "modal-content"]
[ div [ className "modal-header"]
[ h5 [ className "modal-title" ] [ text $ t ]
, button [ _type "button"
, className "close"
, _data { dismiss : "modal"}
] [ span [ aria {hidden : true}] [ text "X"] ]
]
, div [ className "modal-body"] (render d p s c)
]
]
]
]
spec' :: Spec State {} Action
spec' = modalSpec true "Search Results" layoutAddcorpus
layoutModal :: forall e. { response :: Array Response | e} -> Array ReactElement
layoutModal state =
[button [ _type "button"
, _data { "toggle" : "modal"
, "target" : ".myModal"
}
][text "Launch modal"]
, div [ className "modal fade myModal"
, role "dialog"
, _data {show : true}
][ div [ className "modal-dialog"
, role "document"
] [ div [ className "modal-content"]
[ div [ className "modal-header"]
[ h5 [className "modal-title"]
[text "CorpusView" ]
, button [ _type "button"
, className "close"
, _data { dismiss : "modal"}
] [ span [ aria {hidden : true}]
[ text "X"]
]
]
, div [ className "modal-body"]
[ ul [ className "list-group"] ( map fn1 state.response ) ]
, div [className "modal-footer"]
[ button [ _type "button"
, className "btn btn-secondary"
, _data {dismiss : "modal"}
] [ text "GO"]
]
]
]
]
]
where
fn1 (Response o) =
li [className "list-group-item justify-content-between"]
[
span [] [text o.name]
, span [className "badge badge-default badge-pill"] [ text $ show o.count]
]
layoutAddcorpus :: Spec State {} Action
layoutAddcorpus = simpleSpec performAction render
where
render :: Render State {} Action
render dispatch _ state _ =
[ div [className "container1"] []
, div [className "container1"]
[ div [className "jumbotron"]
[ div [className "row"]
[ div [className "col-md-6"] (layoutModal state)
, div [className "col-md-6"]
[ h3 [] [text "Corpusview"]
, ul [className "list-group"] $ map fn1 state.response
, button [onClick \_ -> dispatch GO] [text "GO"]
]
]
]
]
]
where
fn1 (Response o) =
li [className "list-group-item justify-content-between"]
[
span [] [text o.name]
, span [className "badge badge-default badge-pill"] [ text $ show o.count]
]
countResults :: Query -> Aff Int
countResults = post "http://localhost:8008/count"
module Gargantext.Pages.Layout.Specs.AddCorpus.States where
import Prelude hiding (div)
import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, encodeJson, jsonEmptyObject, (.?), (:=), (~>))
type State =
{ select_database :: Boolean
, unselect_database :: Boolean -- dummy state
, response :: Array Response
}
newtype Response = Response
{
count :: Int
, name :: String
}
newtype Query = Query
{
query_query :: String
, query_name :: Array String
}
instance encodeJsonQuery :: EncodeJson Query where
encodeJson (Query post)
= "query_query" := post.query_query
~> "query_name" := post.query_name
~> jsonEmptyObject
instance decodeJsonresponse :: DecodeJson Response where
decodeJson json = do
obj <- decodeJson json
count <- obj .? "count"
name <- obj .? "name"
pure $ Response {count,name }
initialState :: State
initialState =
{
select_database : true
, unselect_database : true
, response : []
}
module Gargantext.Pages.Layout.Specs.Search where
import Prelude hiding (div)
import Effect.Class (liftEffect)
import React.DOM (br', button, div, input, text)
import React.DOM.Props (_id, _type, className, name, onClick, onInput, placeholder, value)
import Routing.Hash (setHash)
import Thermite (PerformAction, Render, Spec, modifyState, simpleSpec)
import Unsafe.Coerce (unsafeCoerce)
type State =
{
query :: String
}
initialState :: State
initialState =
{
query : "empty query"
}
data Action
= GO
| SetQuery String
unsafeEventValue :: forall event. event -> String
unsafeEventValue e = (unsafeCoerce e).target.value
searchSpec :: Spec State {} Action
searchSpec = simpleSpec performAction render
where
performAction :: PerformAction State {} Action
performAction (SetQuery q) _ _ = void do
modifyState $ _ { query = q }
performAction GO _ _ = void do
liftEffect $ setHash "/addCorpus"
render :: Render State {} Action
render dispatch _ state _ =
[ div [className "container1"] []
, div [className "container1"]
[ div [className "jumbotron" ]
[ div [className "row" ]
[ div [className "col-md-10" ]
[ br'
, br'
, div [ className "form-group"][]
{-[ input [ className "form-control"
, _id "id_password"
, name "query"
, placeholder "Query, URL or FILE (works best with Firefox or Chromium browsers)"
, _type "text"
, value state.query
, onInput \e -> dispatch (SetQuery (unsafeEventValue e))
]
, br'
]
-}
]
, div [ className "col-md-2"]
[ br'
, br'
, button [onClick \_ -> dispatch GO] [text "GO"]
]
, br'
]
]
]
]
...@@ -11,7 +11,6 @@ import Data.Tuple (fst) ...@@ -11,7 +11,6 @@ import Data.Tuple (fst)
import Data.Tuple.Nested ( (/\) ) import Data.Tuple.Nested ( (/\) )
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Effect.Uncurried (EffectFn1, mkEffectFn1) import Effect.Uncurried (EffectFn1, mkEffectFn1)
import Thermite (Spec, defaultPerformAction, simpleSpec)
import Reactix as R import Reactix as R
import DOM.Simple.Console import DOM.Simple.Console
import Effect.Aff (launchAff) import Effect.Aff (launchAff)
...@@ -53,11 +52,13 @@ onSearchChange (search /\ setSearch) = ...@@ -53,11 +52,13 @@ onSearchChange (search /\ setSearch) =
where where
triggerSearch q = do triggerSearch q = do
launchAff $ do launchAff $ do
liftEffect $ log2 "Searching db: " $ show q.database
liftEffect $ log2 "Searching term: " q.term liftEffect $ log2 "Searching term: " q.term
(r :: Unit) <- Ajax.search (searchQuery q) (r :: Unit) <- Ajax.search (searchQuery q)
liftEffect $ log2 "Return:" r liftEffect $ log2 "Return:" r
liftEffect $ modalShow "addCorpus" liftEffect $ modalShow "addCorpus"
searchQuery {term} = over SearchQuery (_ {query=term}) defaultSearchQuery searchQuery {database: Nothing, term} = over SearchQuery (_ {query=term}) defaultSearchQuery
searchQuery {database: Just db, term} = over SearchQuery (_ {databases=[db], query=term}) defaultSearchQuery
toggleButton :: R.State Boolean -> R.Element toggleButton :: R.State Boolean -> R.Element
toggleButton open = toggleButton open =
......
This diff is collapsed.
This diff is collapsed.
module Gargantext.Pages.Lists.Tabs
( module Gargantext.Pages.Lists.Tabs.Specs
) where
import Gargantext.Pages.Lists.Tabs.Specs
This diff is collapsed.
module Gargantext.Pages.Texts.Tabs
( module Gargantext.Pages.Texts.Tabs.Specs
) where
import Gargantext.Pages.Texts.Tabs.Specs
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// This file is just a wrapper so that webpack will call our main function
require('./Main.purs').main();
This diff is collapsed.
This diff is collapsed.
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