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 @@
/.purs*
/.psa*
/.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/styles/
/dist/styles/*map
!/dist/examples/
!/dist/fonts/
!/dist/images/
!/dist/js/
/dist/styles/*map
\ No newline at end of file
# css source maps
/dist/styles/*map
......@@ -37,8 +37,25 @@ curl -sL https://deb.nodesource.com/setup_11.x | sudo bash -
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
brew install node
```
......@@ -88,7 +105,43 @@ Or run a 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
yarn build
......@@ -108,6 +161,24 @@ Examples:
<!-- 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
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 @@
<meta charset="utf-8"/>
<title>CNRS GarganText</title>
<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/bootstrap.min.css" rel="stylesheet">
<!-- <link href="css/lavish-bootstrap.css" rel="stylesheet"> -->
<link rel="stylesheet" type="text/css" href="styles/menu.css"/>
<!-- <link href="styles/lavish-bootstrap.css" rel="stylesheet"> -->
<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">
<style>
* {margin: 0; padding: 0; list-style: none;}
......@@ -54,7 +53,7 @@
background-color: "#000";
top: 12px;
}
</style>
</style>
</head>
<body>
<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;
padding-left: 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 @@
"install-ps": "psc-package install",
"compile": "pulp --psc-package build",
"build": "pulp --psc-package browserify -t dist/bundle.js",
"dev": "webpack-dev-server --env dev --mode development",
"repl": "pulp --psc-package repl",
"clean": "rm -Rf output"
},
......@@ -20,6 +21,9 @@
"react-dom": "^16.8.6",
"sigma": "git://github.com/jjl/sigma.js#garg"
},
"eslintConfig": {
"extends": "react-app"
},
"devDependencies": {
"@babel/cli": "^7.1.5",
"@babel/core": "^7.1.6",
......@@ -27,13 +31,30 @@
"@babel/preset-react": "^7.0.0",
"@babel/preset-stage-2": "^7.0.0",
"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",
"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",
"mini-css-extract-plugin": "^0.5.0",
"psc-package": "^3.0.1",
"pulp": "^12.4.0",
"purescript": "^0.12.4",
"purs-loader": "^3.3.0",
"react-testing-library": "^6.1.2",
"spago": "^0.7.5"
},
"version": "0.0.0"
"source-map-loader": "^0.2.4",
"spago": "^0.7.5",
"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 @@
"argonaut",
"console",
"css",
"debug",
"dom-filereader",
"dom-simple",
"effect",
......
#!/bin/bash
rm -rf .psc-package output bower_components node_modules
./build
#!/bin/bash
yarn repl
......@@ -15,6 +15,7 @@ import Prelude
import Data.Lens ((^?), _Just)
import Data.Lens.At (at)
import Data.Maybe ( Maybe(..), maybe, maybe' )
import Data.String.Regex as R
import Data.String as S
import Data.Tuple ( Tuple(..) )
import Data.Tuple.Nested ( (/\) )
......@@ -25,9 +26,10 @@ import Reactix as R
import Reactix.DOM.HTML as HTML
import Reactix.SyntheticEvent as E
import Gargantext.Config (CTabNgramType(..))
import Gargantext.Types ( TermList )
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.Utils.Selection as Sel
......@@ -58,7 +60,7 @@ annotatedFieldComponent = R.hooksComponent "AnnotatedField" cpt
let x = E.clientX event
y = E.clientY event
setList t = do
setTermList (S.toLower text') (Just list) t
setTermList text' (Just list) t
setMenu (const Nothing)
setMenu (const $ Just {x, y, list: Just list, menuType: SetTermListItem, setList} )
......@@ -79,7 +81,7 @@ maybeShowMenu setMenu setTermList ngrams event = do
sel' -> do
let x = E.clientX event
y = E.clientY event
list = findNgram ngrams sel'
list = findNgramTermList CTabTerms ngrams sel'
setList t = do
setTermList sel' list t
setMenu (const Nothing)
......@@ -96,10 +98,7 @@ maybeAddMenu setMenu e (Just props) = annotationMenu setMenu props <> e
maybeAddMenu _ e _ = e
compile :: NgramsTable -> Maybe String -> Array (Tuple String (Maybe TermList))
compile ngrams = maybe [] (highlightNgrams ngrams)
findNgram :: NgramsTable -> String -> Maybe TermList
findNgram (NgramsTable m) s = m ^? at s <<< _Just <<< _NgramsElement <<< _list
compile ngrams = maybe [] (highlightNgrams CTabTerms ngrams)
-- Runs
......
......@@ -49,6 +49,6 @@ addToList {menuType, setList} t = Just $ CM.contextMenuItem [ link ]
where
link = HTML.a { onClick: click, className: className } [ HTML.text (label menuType) ]
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)
click = mkEffectFn1 $ \_ -> setList t
......@@ -19,7 +19,7 @@ import DOM.Simple.Document as Document
import DOM.Simple.Types ( DOMRect )
import Effect (Effect)
import Effect.Uncurried ( mkEffectFn1 )
import FFI.Simple ( (...), (..), (.=), delay )
import FFI.Simple ( (...), (..), delay )
import Reactix as R
import Reactix.DOM.HTML as HTML
import Reactix.SyntheticEvent as E
......@@ -56,8 +56,17 @@ contextMenuCpt = R.hooksComponent "ContextMenu" cpt
]
]
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 _ _ = HTML.div (({ ref, className: "context-menu" } .= "data-toggle" $ "popover") .= "data-placement" $ "right")
elems ref menu (Just rect) = HTML.div
{ 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
:: forall t
......
This diff is collapsed.
......@@ -26,10 +26,12 @@ import React as React
import React (ReactClass, ReactElement, Children)
------------------------------------------------------------------------
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.Components.Loader as Loader
import Gargantext.Components.Search.Types (Category(..), CategoryQuery(..), favCategory, trashCategory, decodeCategory, putCategories)
import Gargantext.Components.Table as T
import Gargantext.Router as Router
import Gargantext.Utils (toggleSet)
import Gargantext.Utils.DecodeMaybe ((.|))
import React.DOM (a, br', button, div, i, input, p, text, span)
......@@ -83,9 +85,9 @@ initialState =
}
data Action
= MarkFavorites (Array Int)
= MarkCategory Category (Array Int)
| ToggleDocumentToDelete Int
| Trash
| TrashDocuments
newtype Pair = Pair
{ id :: Int
......@@ -106,9 +108,9 @@ newtype DocumentsView
, score :: Int
, pairs :: Array Pair
, delete :: Boolean
, category :: Category
}
derive instance genericDocumentsView :: Generic DocumentsView _
instance showDocumentsView :: Show DocumentsView where
......@@ -118,7 +120,7 @@ newtype Response = Response
{ id :: Int
, created :: String
, hyperdata :: Hyperdata
, favorite :: Boolean
, category :: Category
, ngramCount :: Int
-- , date :: String
-- , score :: Int
......@@ -174,7 +176,7 @@ instance decodeResponse :: DecodeJson Response where
hyperdata <- obj .? "hyperdata"
favorite <- obj .? "favorite"
ngramCount <- obj .? "ngramCount"
pure $ Response { id, created, hyperdata, favorite, ngramCount }
pure $ Response { id, created, hyperdata, category: decodeCategory favorite, ngramCount }
-- | Filter
-- TODO: unused
......@@ -194,12 +196,12 @@ layoutDocview :: Spec State Props Action
layoutDocview = simpleSpec performAction render
where
performAction :: PerformAction State Props Action
performAction (MarkFavorites nids) {nodeId} _ =
void $ lift $ putFavorites nodeId (FavoriteQuery {favorites: nids})
performAction (MarkCategory category nids) {nodeId} _ =
void $ lift $ putCategories nodeId $ CategoryQuery {nodeIds: nids, category: favCategory category}
--TODO add array of delete rows here
performAction (ToggleDocumentToDelete nid) _ _ =
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})
modifyState_ \{documentIdsToDelete, documentIdsDeleted} ->
{ documentIdsToDelete: mempty
......@@ -229,7 +231,7 @@ layoutDocview = simpleSpec performAction render
]
, div [className "col-md-12"]
[ 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"}] []
, text "Trash it !"
......@@ -245,12 +247,12 @@ layoutDocviewGraph :: Spec State Props Action
layoutDocviewGraph = simpleSpec performAction render
where
performAction :: PerformAction State Props Action
performAction (MarkFavorites nids) {nodeId} _ =
void $ lift $ putFavorites nodeId (FavoriteQuery {favorites: nids})
performAction (MarkCategory category nids) {nodeId} _ =
void $ lift $ putCategories nodeId $ CategoryQuery {nodeIds: nids, category: favCategory category}
--TODO add array of delete rows here
performAction (ToggleDocumentToDelete nid) _ _ =
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})
modifyState_ \{documentIdsToDelete, documentIdsDeleted} ->
{ documentIdsToDelete: mempty
......@@ -275,7 +277,7 @@ layoutDocviewGraph = simpleSpec performAction render
, container
}
, 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"}] []
, text "Trash it !"
......@@ -303,7 +305,7 @@ loadPage {nodeId, listId, query, params: {limit, offset, orderBy}} = do
res2corpus :: Response -> DocumentsView
res2corpus (Response { id, created: date, ngramCount: score
, hyperdata: Hyperdata {title, source}
-- favorite TODO
, category
}) =
DocumentsView
{ id
......@@ -313,6 +315,7 @@ loadPage {nodeId, listId, query, params: {limit, offset, orderBy}} = do
, score
, pairs: []
, delete: false
, category
}
convOrderBy (T.ASC (T.ColumnName "Date")) = DateAsc
convOrderBy (T.DESC (T.ColumnName "Date")) = DateDesc
......@@ -363,7 +366,7 @@ renderPage loaderDispatch { totalRecords, dispatch, container
]
where
-- TODO: how to interprete other scores?
gi 0 = "glyphicon glyphicon-star-empty"
gi Favorite = "glyphicon glyphicon-star-empty"
gi _ = "glyphicon glyphicon-star"
isChecked id = Set.member id documentIdsToDelete
isDeleted (DocumentsView {id}) = Set.member id documentIdsDeleted
......@@ -371,7 +374,7 @@ renderPage loaderDispatch { totalRecords, dispatch, container
| id > 1 = [a [href (toUrl Front NodeContact (Just id)), target "blank"] [text label]]
| otherwise = [text label]
comma = span [] [text ", "]
rows = (\(DocumentsView {id,score,title,source,date,pairs,delete}) ->
rows = (\(DocumentsView {id,score,title,source,date,pairs,delete,category}) ->
let
strikeIfDeleted
| delete = [style {textDecoration : "line-through"}]
......@@ -379,13 +382,13 @@ renderPage loaderDispatch { totalRecords, dispatch, container
in
{ row:
[ div []
[ a [ className $ gi score
, onClick $ const $ dispatch $ MarkFavorites [id]
[ a [ className $ gi category
, onClick $ const $ dispatch $ MarkCategory category [id]
] []
]
-- TODO show date: Year-Month-Day only
, div strikeIfDeleted [text date]
, a (strikeIfDeleted <> [ href (toUrl Front (ListDocument (Just listId)) (Just id))
, a (strikeIfDeleted <> [ href $ toLink $ Router.Document listId id
, target "blank"])
[ text title ]
, div strikeIfDeleted [text source]
......@@ -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
{
documents :: Array Int
......@@ -425,11 +419,5 @@ instance encodeJsonDDQuery :: EncodeJson DeleteDocumentQuery where
= "documents" := post.documents
~> 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 nodeId = deleteWithBody (toUrl Back Node (Just nodeId) <> "/documents")
......@@ -40,6 +40,7 @@ import Gargantext.Types (class Optional)
import Gargantext.Utils (toggleSet)
import Gargantext.Utils.Reactix as R2
import Partial.Unsafe (unsafePartial)
import Thermite (Spec)
import Unsafe.Coerce (unsafeCoerce)
import Web.HTML (window)
import Web.HTML.Window (localStorage)
......@@ -49,13 +50,14 @@ import Reactix.DOM.HTML as RH
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 props = R.createElement explorerCpt props []
explorerCpt :: forall s fa2. R.Component (Props s fa2)
explorerCpt = R.hooksComponent "Explorer" cpt
explorerCpt = R.hooksComponent "GraphExplorer" cpt
where
cpt props _ = do
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
import Prelude
import Data.Lens (Iso', iso)
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)
type Username = String
......@@ -30,6 +32,12 @@ newtype AuthData = AuthData
, 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 v) -> v) AuthData
......
......@@ -34,12 +34,13 @@ import Thermite (PerformAction, Render, Spec, defaultPerformAction, modifyState_
import Unsafe.Coerce (unsafeCoerce)
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.Table as T
import Gargantext.Prelude
import Gargantext.Components.Loader as Loader
import Gargantext.Components.NgramsTable.Core
import Gargantext.Utils.Reactix as R2
type State =
CoreState
......@@ -119,7 +120,7 @@ tableContainer { pageParams
, name "search", placeholder "Search"
, _type "value"
, value pageParams.searchQuery
, onInput \e -> setSearchQuery (unsafeEventValue e)
, onInput \e -> setSearchQuery (R2.unsafeEventValue e)
]
, div [] (
if A.null props.tableBody && pageParams.searchQuery /= "" then [
......@@ -134,7 +135,7 @@ tableContainer { pageParams
[ select [ _id "picklistmenu"
, className "form-control custom-select"
, value (maybe "" show pageParams.termListFilter)
, onChange (\e -> setTermListFilter $ readTermList $ unsafeEventValue e)
, onChange (\e -> setTermListFilter $ readTermList $ R2.unsafeEventValue e)
] $ map optps1 termLists
]
]
......@@ -143,7 +144,7 @@ tableContainer { pageParams
[ select [ _id "picktermtype"
, className "form-control custom-select"
, value (maybe "" show pageParams.termSizeFilter)
, onChange (\e -> setTermSizeFilter $ readTermSize $ unsafeEventValue e)
, onChange (\e -> setTermSizeFilter $ readTermSize $ R2.unsafeEventValue e)
] $ map optps1 termSizes
]
]
......@@ -197,8 +198,8 @@ toggleMap :: forall a. a -> Maybe a -> Maybe a
toggleMap _ (Just _) = Nothing
toggleMap b Nothing = Just b
ngramsTableSpec :: Spec State LoadedNgramsTableProps Action
ngramsTableSpec = simpleSpec performAction render
ngramsTableSpec :: CTabNgramType -> Spec State LoadedNgramsTableProps Action
ngramsTableSpec ntype = simpleSpec performAction render
where
setParentResetChildren :: Maybe NgramsTerm -> State -> State
setParentResetChildren p = _ { ngramsParent = p, ngramsChildren = mempty }
......@@ -213,9 +214,8 @@ ngramsTableSpec = simpleSpec performAction render
performAction (SetTermListItem n pl) {path: {nodeId, listIds, tabType}} {ngramsVersion} =
commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: pt})
where
listId = Just 10 -- List.head listIds
pe = NgramsPatch { patch_list: pl, patch_children: mempty }
pt = PatchMap $ Map.singleton n pe
pt = singletonNgramsTablePatch ntype n pe
performAction AddTermChildren _ {ngramsParent: Nothing} =
-- impossible but harmless
pure unit
......@@ -227,14 +227,13 @@ ngramsTableSpec = simpleSpec performAction render
modifyState_ $ setParentResetChildren Nothing
commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: pt})
where
listId = Just 10 -- List.head listIds
pc = patchSetFromMap ngramsChildren
pe = NgramsPatch { patch_list: mempty, patch_children: pc }
pt = PatchMap $ Map.fromFoldable [Tuple parent pe]
-- TODO ROOT-UPDATE
-- patch the root of the child to be equal to the root of the parent.
performAction (AddNewNgram ngram) {path: params} _ =
lift $ addNewNgram ngram Nothing params
pt = singletonNgramsTablePatch ntype parent pe
performAction (AddNewNgram ngram) {path: {listIds, nodeId, tabType}} {ngramsVersion} =
commitPatch {listIds, nodeId, tabType} (Versioned {version: ngramsVersion, data: pt})
where
pt = addNewNgram ntype ngram CandidateTerm
render :: Render State LoadedNgramsTableProps Action
render dispatch { path: pageParams
......@@ -251,7 +250,7 @@ ngramsTableSpec = simpleSpec performAction render
, container: tableContainer {pageParams, loaderDispatch, dispatch, ngramsParent, ngramsChildren, ngramsTable}
, colNames:
T.ColumnName <$>
[ "Graph"
[ "Map"
, "Stop"
, "Terms"
, "Score (Occurrences)" -- see convOrderBy
......@@ -294,21 +293,24 @@ ngramsTableSpec = simpleSpec performAction render
, delete: false
}
ngramsTableClass :: Loader.InnerClass PageParams VersionedNgramsTable
ngramsTableClass = createClass "NgramsTable" ngramsTableSpec initialState
ngramsTableClass :: CTabNgramType -> Loader.InnerClass PageParams VersionedNgramsTable
ngramsTableClass ct = createClass "NgramsTable" (ngramsTableSpec ct) initialState
type MainNgramsTableProps =
Loader.InnerProps Int { defaultListId :: Int }
( tabType :: TabType )
{ nodeId :: Int
-- ^ This node can be a corpus or contact.
, defaultListId :: Int
, tabType :: TabType
}
mainNgramsTableSpec :: Spec {} MainNgramsTableProps Void
mainNgramsTableSpec = simpleSpec defaultPerformAction render
mainNgramsTableSpec :: CTabNgramType -> Spec {} MainNgramsTableProps Void
mainNgramsTableSpec nt = simpleSpec defaultPerformAction render
where
render :: Render {} MainNgramsTableProps Void
render _ {path: nodeId, loaded: {defaultListId}, tabType} _ _ =
render _ {nodeId, defaultListId, tabType} _ _ =
[ ngramsLoader
{ path: initialPageParams nodeId [defaultListId] tabType
, component: ngramsTableClass
, component: (ngramsTableClass nt)
} ]
type NgramsDepth = {ngrams :: NgramsTerm, depth :: Int}
......@@ -419,6 +421,3 @@ optps1 :: forall a. Show a => { desc :: String, mval :: Maybe a } -> ReactElemen
optps1 { desc, mval } = option [value val] [text desc]
where
val = maybe "" show mval
unsafeEventValue :: forall event. event -> String
unsafeEventValue e = (unsafeCoerce e).target.value
......@@ -25,10 +25,10 @@ instance decodeNodePoly :: (DecodeJson a)
parentId <- obj .? "parentId"
name <- obj .? "name"
date <- obj .? "date"
hyperdata <- obj .? "hyperdata"
hyperdata' <- decodeJson hyperdata
pure $ NodePoly { id : id
, typename : typename
, userId : userId
......
......@@ -14,7 +14,7 @@ import DOM.Simple.Element as Element
import DOM.Simple.Event as DE
import Effect ( Effect )
import Effect.Uncurried (mkEffectFn1)
import FFI.Simple ((..), (.=))
import FFI.Simple ((..))
import Reactix as R
import Reactix.DOM.HTML as HTML
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
cpt props _ = do
let search = maybe defaultSearch identity (fst props.search)
term <- R.useState' search.term
db <- R.useState' Nothing
db <- R.useState' (Nothing :: Maybe Database)
pure $
div { className: "search-field input-group" }
[ databaseInput db props.databases
......@@ -60,18 +60,18 @@ searchFieldComponent = R.memo (R.hooksComponent "SearchField" cpt) hasChanged
databaseInput :: R.State (Maybe Database) -> Array Database -> R.Element
databaseInput (db /\ setDB) dbs =
div { className: "input-group-btn search-panel dropdown" }
[
dropdownBtn db
, ul {className: "dropdown-menu", role: "menu"} (liItem <$> dbs)
[ dropdownBtn db
, ul {className: "dropdown-menu", role: "menu"} (liItem <$> dbs)
]
where
liItem db = li { onClick }
[ a {href: "#"} [text (show db) ] ]
where
onClick = mkEffectFn1 $ \_ -> setDB (const $ Just db)
liItem db = li { onClick } [ a {href: "#"} [text (show db) ] ]
where
onClick = mkEffectFn1 $ \_ -> setDB $ const $ Just db
dropdownBtnProps = { id: "search-dropdown"
, 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 (Nothing) = button dropdownBtnProps [ span {} [ text "-" ] ]
......@@ -82,7 +82,7 @@ searchInput (term /\ setTerm) =
, type: "text"
, onChange
, 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
......@@ -91,5 +91,5 @@ submitButton (database /\ _) (term /\ _) (_ /\ setSearch) =
where
click = mkEffectFn1 $ \_ -> do
case term of
"" -> setSearch (const Nothing)
_ -> setSearch (const $ Just { database, term })
"" -> setSearch $ const Nothing
_ -> setSearch $ const $ Just { database, term }
module Gargantext.Components.Search.Types where
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.Newtype (class Newtype)
import Data.Tuple (Tuple)
......@@ -13,19 +17,19 @@ import Thermite (PerformAction, modifyState)
import Gargantext.Prelude
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.Pages.Layout.Specs.AddCorpus.States (Response, State)
import Gargantext.Utils (id)
import URI.Extra.QueryPairs as QP
data Database = All | PubMed | HAL | IsTex
instance showDatabase :: Show Database where
show All = "All"
show All = "All"
show PubMed = "PubMed"
show HAL = "HAL"
show IsTex = "IsTex"
show HAL = "HAL"
show IsTex = "IsTex"
readDatabase :: String -> Maybe Database
readDatabase "All" = Just All
......@@ -36,6 +40,10 @@ readDatabase _ = Nothing
derive instance eqDatabase :: Eq Database
instance encodeJsonDatabase :: EncodeJson Database where
encodeJson a = encodeJson (show a)
allDatabases :: Array Database
allDatabases = [All, HAL, IsTex, PubMed]
......@@ -85,8 +93,57 @@ instance searchQueryToQuery :: ToQuery SearchQuery where
[ QP.keyFromString k /\ Just (QP.valueFromString $ show v) ]
instance encodeJsonSearchQuery :: EncodeJson SearchQuery where
encodeJson (SearchQuery {query, corpus_id, files_id})
= "query" := query
~> "corpus_id" := fromMaybe 0 corpus_id
~> "files_id" := files_id
encodeJson (SearchQuery {query, databases, corpus_id, files_id})
= "query" := query
~> "databases" := databases
~> "corpus_id" := fromMaybe 0 corpus_id
~> "files_id" := files_id
~> 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)
import Effect.Class (liftEffect)
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.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 Unsafe.Coerce (unsafeCoerce)
import Gargantext.Prelude
import Gargantext.Utils.Reactix as R2
type TableContainerProps =
{ pageSizeControl :: ReactElement
......@@ -218,7 +219,8 @@ sizeDD :: PageSizes -> (Action -> Effect Unit) -> ReactElement
sizeDD ps d
= span []
[ 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
]
......@@ -316,4 +318,4 @@ string2PageSize "200" = PS200
string2PageSize _ = PS10
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"
module Gargantext.Config where
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.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Data.Map (Map)
import Data.Map as DM
import Data.Maybe (Maybe(..), maybe)
import Data.Tuple (Tuple(..))
import Gargantext.Router as R
import Gargantext.Types
import Gargantext.Types (TermList, TermSize(..))
urlPlease :: End -> String -> String
urlPlease end path = theEnd.baseUrl <> theEnd.prePath <> path
......@@ -31,7 +28,8 @@ endConfig = endConfig' V10
endConfig' :: ApiVersion -> EndConfig
endConfig' v = { front : frontRelative
, back : backDev v
--, back : backLocal v
, back: backDev v
, static : staticRelative
}
-- , back : backDemo v }
......@@ -62,6 +60,11 @@ frontDev = { baseUrl: "https://dev.gargantext.org"
, prePath: "/#/"
}
frontDemo :: Config
frontDemo = { baseUrl: "https://demo.gargantext.org"
, prePath: "/#/"
}
frontProd :: Config
frontProd = { baseUrl: "https://gargantext.org"
, prePath: "/#/"
......@@ -119,11 +122,6 @@ endBaseUrl end c = (endOf end c).baseUrl
endPathUrl :: End -> EndConfig -> Path -> Maybe Id -> UrlPath
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 l = "&limit=" <> show l
......@@ -141,10 +139,26 @@ showTabType' (TabCorpus t) = show t
showTabType' (TabDocument 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 c (Tab t o l s) i =
pathUrl c (NodeAPI Node) i <>
"/" <> tabTypeDocs t <> offsetUrl o <> limitUrl l <> orderUrl s
pathUrl c (Tab t) i =
pathUrl c (NodeAPI Node) i <> "/" <> showTabType' t
pathUrl c (Children n o l s) i =
pathUrl c (NodeAPI Node) i <>
"/" <> "children?type=" <> show n <> offsetUrl o <> limitUrl l <> orderUrl s
......@@ -204,14 +218,16 @@ pathUrl c (Chart {chartType, tabType}) i =
------------------------------------------------------------
routesPath :: R.Routes -> String
routesPath R.Home = ""
routesPath R.Login = "login"
routesPath R.SearchView = "search"
routesPath (R.Folder i) = "folder/" <> 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.PGraphExplorer i) = "#/"
routesPath (R.Texts i) = "texts/" <> show i
routesPath (R.Lists i) = "lists/" <> show i
routesPath R.Dashboard = "dashboard"
routesPath (R.Annuaire i) = "annuaire/" <> show i
routesPath (R.UserPage i) = "user/" <> show i
......@@ -253,6 +269,7 @@ data NodeType = NodeUser
| Nodes
| Tree
| NodeList
| Texts
derive instance eqNodeType :: Eq NodeType
......@@ -273,6 +290,7 @@ instance showNodeType :: Show NodeType where
show Nodes = "Nodes"
show Tree = "NodeTree"
show NodeList = "NodeList"
show Texts = "NodeTexts"
readNodeType :: String -> NodeType
readNodeType "NodeAnnuaire" = Annuaire
......@@ -290,6 +308,7 @@ readNodeType "NodeUser" = NodeUser
readNodeType "NodeContact" = NodeContact
readNodeType "Tree" = Tree
readNodeType "NodeList" = NodeList
readNodeType "NodeTexts" = Texts
readNodeType _ = Error
{-
------------------------------------------------------------
......@@ -320,18 +339,19 @@ nodeTypeUrl Graph = "graph"
nodeTypeUrl Phylo = "phylo"
nodeTypeUrl Individu = "individu"
nodeTypeUrl Node = "node"
nodeTypeUrl Nodes = "nodes"
nodeTypeUrl Nodes = "nodes"
nodeTypeUrl NodeUser = "user"
nodeTypeUrl NodeContact = "contact"
nodeTypeUrl Tree = "tree"
nodeTypeUrl NodeList = "list"
nodeTypeUrl NodeList = "lists"
nodeTypeUrl Texts = "texts"
------------------------------------------------------------
type ListId = Int
data Path
= Auth
| Tab TabType Offset Limit (Maybe OrderBy)
| Tab TabType
| Children NodeType Offset Limit (Maybe OrderBy)
| GetNgrams
{ tabType :: TabType
......@@ -416,7 +436,7 @@ instance showPTabNgramType :: Show PTabNgramType where
show PTabBooks = "Books"
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)
......@@ -424,6 +444,8 @@ instance showTabSubType :: Show a => Show (TabSubType a) where
show TabDocs = "Docs"
show (TabNgramType a) = show a
show TabTrash = "Trash"
show TabMoreLikeFav = "MoreFav"
show TabMoreLikeTrash = "MoreTrash"
data TabType
= TabCorpus (TabSubType CTabNgramType)
......
......@@ -4,4 +4,4 @@ module Gargantext.Pages.Annuaire.User.Contacts
where
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)
import Data.String (joinWith)
import Effect.Aff (Aff, throwError)
import Effect.Exception (error)
import Thermite (Render, Spec, defaultPerformAction, simpleSpec, createClass)
import Thermite (Render, Spec, defaultPerformAction, simpleSpec)
import React as React
import React (ReactClass, ReactElement)
import React.DOM (div, h3, img, li, span, text, ul, text)
import React.DOM.Props (_id, className, src)
import Reactix as R
import Gargantext.Prelude
import Gargantext.Config (toUrl, End(..), NodeType(..), Path(..))
import Gargantext.Config.REST (get)
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.Tabs.Specs as Tabs
--type Props = Loader.InnerProps Int Contact
import Gargantext.Utils.Reactix as R2
display :: String -> Array ReactElement -> Array ReactElement
display title elems =
......@@ -153,30 +153,16 @@ infoRender (Tuple title content) =
-- | Below an example of a loader, use all code below and adapt it
-- to your code
-- 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 = simpleSpec defaultPerformAction render
where
render :: Render {} {nodeId :: Int} Void
render _ {nodeId} _ _ =
[ contactLoader { path: nodeId
, component: createClass "LayoutUser" layoutUser' (const {})
} ]
-- | 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)
]
layoutUser =
R2.elSpec $ R.hooksComponent "LayoutUser" \{nodeId} _ ->
useLoader nodeId getContact $ \{loaded: contactData} ->
let {contactNode: Contact {name, hyperdata}} = contactData in
R2.toElement
[ ul [className "col-md-12 list-group"] $
display (fromMaybe "no name" name) (contactInfos hyperdata)
, Tabs.elt {nodeId, contactData}
]
-- | toUrl to get data
getContact :: Int -> Aff ContactData
......@@ -190,11 +176,3 @@ getContact id = do
-- Nothing ->
-- throwError $ error "Missing default list"
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)
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Data.List (fromFoldable)
import Data.Maybe (Maybe(..))
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.NgramsTable as NT
import Gargantext.Components.Tab as Tab
import Gargantext.Pages.Annuaire.User.Contacts.Types (Props)
import Thermite (Spec, focus, hideState, noState, cmapProps)
import Gargantext.Pages.Annuaire.User.Contacts.Types (ContactData)
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
......@@ -29,6 +35,27 @@ modeTabType Patents = PTabPatents
modeTabType Books = PTabBooks
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 = hideState (const {activeTab: 0}) statefulTabs
......@@ -44,17 +71,21 @@ statefulTabs =
where
chart = mempty
-- TODO totalRecords
docs = cmapProps (\{path: nodeId, loaded} ->
{ nodeId, chart
, tabType: TabPairing TabDocs
, totalRecords: 4736
, listId: loaded.defaultListId}) $
noState DT.docViewSpec
docs = noState $ R2.elSpec $ R.hooksComponent "DocViewSpecWithCorpus" $ \{nodeId, contactData: {defaultListId}} _ -> do
pure $ DT.docViewSpec
{ nodeId
, chart
, tabType: TabPairing TabDocs
, totalRecords: 4736
, listId: defaultListId
, corpusId: Nothing
, showSearch: true
}
ngramsViewSpec :: {mode :: Mode} -> Spec Tab.State Props Tab.Action
ngramsViewSpec {mode} =
cmapProps (\{loaded: {defaultListId}, path, dispatch} ->
{loaded: {defaultListId}, path, dispatch, tabType})
(noState NT.mainNgramsTableSpec)
cmapProps (\{contactData: {defaultListId}, nodeId} ->
{defaultListId, nodeId, tabType})
(noState (NT.mainNgramsTableSpec (modeTabType' mode)))
where
tabType = TabPairing $ TabNgramType $ modeTabType mode
......@@ -162,13 +162,9 @@ instance decodeUser :: DecodeJson Contact where
name <- obj .?? "name"
date <- obj .?| "date"
hyperdata <- obj .? "hyperdata"
pure $ Contact { id, typename, userId
, parentId, name, date
, hyperdata
}
type ContactData = {contactNode :: Contact, defaultListId :: Int}
type PropsRow = Loader.InnerPropsRow Int ContactData ()
type Props = Record PropsRow
module Gargantext.Pages.Corpus where
import Data.Array (head)
import Data.Maybe (Maybe(..))
import Effect.Aff (Aff, throwError)
import Effect.Exception (error)
import React as React
import React (ReactClass, ReactElement)
import Thermite (Spec, Render, simpleSpec, createClass, defaultPerformAction)
import Reactix as R
import Reactix.DOM.HTML as H
import Thermite (Spec)
--------------------------------------------------------
import Gargantext.Prelude
import Gargantext.Components.Node (NodePoly(..), HyperdataList(..))
import Gargantext.Components.Loader as Loader
import Gargantext.Components.Loader (createLoaderClass)
import Gargantext.Components.Node (NodePoly(..), HyperdataList)
import Gargantext.Components.Loader2 (useLoader)
import Gargantext.Components.Table as Table
import Gargantext.Config (toUrl, Path(..), NodeType(..), End(..))
import Gargantext.Config.REST (get)
import Gargantext.Pages.Corpus.Tabs.Types (CorpusData, CorpusInfo(..))
import Gargantext.Pages.Corpus.Tabs.Types (Props) as Tabs
import Gargantext.Pages.Corpus.Tabs.Specs (pureTabs) as Tabs
-------------------------------------------------------------------
type Props = Tabs.Props
import Gargantext.Pages.Texts.Tabs.Types (CorpusData, CorpusInfo(..))
import Gargantext.Pages.Texts.Tabs.Specs (elt) as Tabs
import Gargantext.Utils.Reactix as R2
------------------------------------------------------------------------
layout :: Spec {} {nodeId :: Int} Void
layout = simpleSpec defaultPerformAction render
layout = R2.elSpec $ R.hooksComponent "CorpusLoader" cpt
where
render :: Render {} {nodeId :: Int} Void
render _ {nodeId} _ _ =
[ 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 []
cpt {nodeId} _children = do
pure $ H.div {} [H.text "Empty page"]
module Gargantext.Pages.Corpus.Chart.Histo where
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
import Data.Array (foldl)
import Data.Tuple (Tuple(..))
import Data.Map as Map
import Data.Int (toNumber)
import Data.Map as Map
import Data.Map (Map)
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
import Data.Maybe (Maybe(..), maybe)
import Data.Tuple (Tuple(..))
import Effect.Aff (Aff)
import Gargantext.Config -- (End(..), Path(..), TabType, toUrl)
import Gargantext.Config.REST (get)
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.Types (TermList(..))
import Gargantext.Components.Loader as Loader
import Gargantext.Components.Loader2 (useLoader)
import Gargantext.Components.Charts.Options.ECharts
import Gargantext.Components.Charts.Options.Type
import Gargantext.Components.Charts.Options.Series
import Gargantext.Components.Charts.Options.Color
import Gargantext.Components.Charts.Options.Font
import Gargantext.Components.Charts.Options.Data
import Gargantext.Utils.Reactix as R2
import Gargantext.Pages.Corpus.Chart.Utils as U
type Path =
{ corpusId :: Int
......@@ -51,12 +57,6 @@ instance decodeHistoMetrics :: DecodeJson HistoMetrics where
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 { dates: dates', count: count'}) = Options
{ mainTitle : "Histogram"
......@@ -68,23 +68,27 @@ chartOptions (HistoMetrics { dates: dates', count: count'}) = Options
, 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 {corpusId, tabType} = do
ChartMetrics ms <- get $ toUrl Back (Chart {chartType: Histo, tabType: tabType}) $ Just corpusId
pure ms."data"
getMetrics :: Path -> Aff HistoMetrics
getMetrics {corpusId, tabType} = do
ChartMetrics ms <- get $ toUrl Back (Chart {chartType: Histo, tabType: tabType}) $ Just corpusId
pure ms."data"
histoSpec :: Spec {} Path Void
histoSpec = simpleSpec defaultPerformAction render
histoSpec = R2.elSpec $ R.hooksComponent "LoadedMetricsHisto" cpt
where
render :: Render {} Path Void
render dispatch path {} _ =
[ metricsLoader
{ path
, component: createClass "LoadedMetrics" loadedMetricsSpec (const {})
} ]
cpt p _ = do
setReload <- R.useState' 0
pure $ metricsLoadView setReload p
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
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
import Data.Array (foldl)
import Data.Tuple (Tuple(..))
import Data.Map as Map
import Data.Map (Map)
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
import Data.Maybe (Maybe(..), maybe)
import Data.Tuple (Tuple(..))
import Effect.Aff (Aff)
import Gargantext.Config -- (End(..), Path(..), TabType, toUrl)
import Gargantext.Config.REST (get)
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.Types (TermList(..))
import Gargantext.Components.Loader2 (useLoader)
import Gargantext.Components.Loader as Loader
import Gargantext.Components.Charts.Options.ECharts
import Gargantext.Components.Charts.Options.Type
......@@ -20,6 +24,8 @@ import Gargantext.Components.Charts.Options.Series
import Gargantext.Components.Charts.Options.Color
import Gargantext.Components.Charts.Options.Font
import Gargantext.Components.Charts.Options.Data
import Gargantext.Utils.Reactix as R2
import Gargantext.Pages.Corpus.Chart.Utils as U
type Path =
{ corpusId :: Int
......@@ -56,12 +62,6 @@ instance decodeMetrics :: DecodeJson Metrics where
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 metrics = Options
{ mainTitle : "Ngrams Selection Metrics"
......@@ -101,18 +101,21 @@ getMetrics {corpusId, listId, limit, tabType} = do
Metrics ms <- get $ toUrl Back (CorpusMetrics {listId, tabType, limit}) $ Just corpusId
pure ms."data"
metricsLoaderClass :: ReactClass (Loader.Props Path Loaded)
metricsLoaderClass = Loader.createLoaderClass "MetricsLoader" getMetrics
metricsLoader :: Loader.Props' Path Loaded -> ReactElement
metricsLoader props = createElement metricsLoaderClass props []
metricsSpec = R2.elSpec $ R.hooksComponent "LoadedMetrics" cpt
where
cpt p _ = do
setReload <- R.useState' 0
metricsSpec :: Spec {} Path Void
metricsSpec = simpleSpec defaultPerformAction render
pure $ metricsLoadView setReload p
metricsLoadView :: R.State Int -> Path -> R.Element
metricsLoadView setReload p = R.createElement el p []
where
render :: Render {} Path Void
render dispatch path {} _ =
[ metricsLoader
{ path
, component: createClass "LoadedMetrics" loadedMetricsSpec (const {})
} ]
el = R.hooksComponent "MetricsLoadedView" cpt
cpt p _ = do
useLoader p getMetrics $ \{loaded} ->
loadedMetricsView setReload loaded
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
import Data.String (take, joinWith, Pattern(..), split, length)
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
import Data.Array (foldl, zip, filter)
import Data.Array as A
import Data.Tuple (Tuple(..))
import Data.Map as Map
import Data.Int (toNumber)
import Data.Map (Map)
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
import Data.Maybe (Maybe(..), maybe)
import Data.String (take, joinWith, Pattern(..), split, length)
import Data.Tuple (Tuple(..))
import Effect.Aff (Aff)
import Gargantext.Config -- (End(..), Path(..), TabType, toUrl)
import Gargantext.Config.REST (get)
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.Types (TermList(..))
import Gargantext.Components.Loader as Loader
import Gargantext.Components.Loader2 (useLoader)
import Gargantext.Components.Charts.Options.ECharts
import Gargantext.Components.Charts.Options.Type
import Gargantext.Components.Charts.Options.Series
import Gargantext.Components.Charts.Options.Color
import Gargantext.Components.Charts.Options.Font
import Gargantext.Components.Charts.Options.Data
import Gargantext.Utils.Reactix as R2
import Gargantext.Pages.Corpus.Chart.Utils as U
type Path =
{ corpusId :: Int
......@@ -53,14 +56,8 @@ instance decodeHistoMetrics :: DecodeJson HistoMetrics where
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 : metricsData} {} _ = [chart (chartOptions metricsData)]
chartOptions :: HistoMetrics -> Options
chartOptions (HistoMetrics { dates: dates', count: count'}) = Options
chartOptionsBar :: HistoMetrics -> Options
chartOptionsBar (HistoMetrics { dates: dates', count: count'}) = Options
{ mainTitle : "Bar"
, subTitle : "Count of GraphTerm"
, 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
, 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 { dates: dates', count: count'}) = Options
{ mainTitle : "Pie"
......@@ -89,34 +80,50 @@ chartOptionsPie (HistoMetrics { dates: dates', count: count'}) = Options
}
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 {corpusId, tabType:tabType} = do
ChartMetrics ms <- get $ toUrl Back (Chart {chartType: ChartPie, tabType: tabType}) $ Just corpusId
pure ms."data"
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 = 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
render :: Render {} Path Void
render dispatch path {} _ =
[ metricsLoader
{ path
, component: createClass "LoadedMetrics" loadedMetricsSpecPie (const {})
} ]
el = R.hooksComponent "MetricsLoadedPieView" cpt
cpt p _ = do
useLoader p getMetrics $ \{loaded} ->
loadedMetricsPieView setReload loaded
loadedMetricsPieView :: R.State Int -> HistoMetrics -> R.Element
loadedMetricsPieView setReload loaded = U.reloadButtonWrap setReload $ R2.buff $ chart $ chartOptionsPie loaded
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
render :: Render {} Path Void
render dispatch path {} _ =
[ metricsLoader
{ path
, component: createClass "LoadedMetrics" loadedMetricsSpec (const {})
} ]
el = R.hooksComponent "MetricsLoadedBarView" cpt
cpt p _ = do
useLoader p getMetrics $ \{loaded} ->
loadedMetricsBarView setReload loaded
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
import Data.Array (foldl)
import Data.Tuple (Tuple(..))
import Data.Map as Map
import Data.Map (Map)
import Data.Argonaut (class DecodeJson, decodeJson, (.?))
import Data.Maybe (Maybe(..), maybe)
import Data.Tuple (Tuple(..))
import Effect.Aff (Aff)
import Gargantext.Config -- (End(..), Path(..), TabType, toUrl)
import Gargantext.Config.REST (get)
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.Types (TermList(..))
import Gargantext.Components.Loader as Loader
import Gargantext.Components.Loader2 (useLoader)
import Gargantext.Components.Charts.Options.ECharts
import Gargantext.Components.Charts.Options.Type
import Gargantext.Components.Charts.Options.Series
import Gargantext.Components.Charts.Options.Color
import Gargantext.Components.Charts.Options.Font
import Gargantext.Components.Charts.Options.Data
import Gargantext.Pages.Corpus.Dashboard (treeMapEx)
import Gargantext.Utils.Reactix as R2
import Gargantext.Pages.Corpus.Chart.Utils as U
type Path =
......@@ -44,12 +47,6 @@ instance decodeMetrics :: DecodeJson Metrics where
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 nodes = Options
{ mainTitle : "Tree"
......@@ -69,18 +66,24 @@ getMetrics {corpusId, listId, limit, tabType} = do
Metrics ms <- get $ toUrl Back (Chart {chartType : ChartTree, tabType: tabType}) $ Just corpusId
pure ms."data"
metricsLoaderClass :: ReactClass (Loader.Props Path Loaded)
metricsLoaderClass = Loader.createLoaderClass "MetricsLoader" getMetrics
treeSpec :: Spec {} Path Void
treeSpec = R2.elSpec $ R.hooksComponent "LoadedMetrics" cpt
where
cpt p _ = do
setReload <- R.useState' 0
metricsLoader :: Loader.Props' Path Loaded -> ReactElement
metricsLoader props = createElement metricsLoaderClass props []
pure $ metricsLoadView setReload p
treeSpec :: Spec {} Path Void
treeSpec = simpleSpec defaultPerformAction render
metricsLoadView :: R.State Int -> Path -> R.Element
metricsLoadView setReload p = R.createElement el p []
where
render :: Render {} Path Void
render dispatch path {} _ =
[ metricsLoader
{ path
, component: createClass "LoadedMetrics" loadedMetricsSpec (const {})
} ]
el = R.hooksComponent "MetricsLoadView" cpt
cpt p _ = do
useLoader p getMetrics $ \{loaded} ->
loadedMetricsView setReload loaded
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
import Data.Argonaut (class DecodeJson, decodeJson, (.:), (.:?))
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Data.Map as Map
import Data.Maybe (Maybe(..), maybe)
import Effect.Aff (Aff)
import React (ReactElement, ReactClass)
import React as React
import React (ReactClass, Children)
import React.DOM (div, h4, li, p, span, text, ul)
import React.DOM.Props (className)
import Thermite (PerformAction, Render, Spec, simpleSpec, cmapProps, defaultPerformAction, createClass)
import Control.Monad.Trans.Class (lift)
import Reactix as R
import Thermite (PerformAction, Render, Spec, simpleSpec, cmapProps, createClass)
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.Components.AutoUpdate (autoUpdateElt)
import Gargantext.Components.Loader as Loader
import Gargantext.Components.Loader2 (useLoader)
import Gargantext.Components.Node (NodePoly(..))
import Gargantext.Components.NgramsTable.Core
import Gargantext.Components.Annotation.AnnotatedField as AnnotatedField
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
......@@ -32,7 +30,10 @@ type LoadedData =
{ document :: NodeDocument
, ngramsTable :: VersionedNgramsTable }
type LoadedDataProps = Loader.InnerProps DocPath LoadedData ()
type Props =
{ loaded :: LoadedData
, path :: DocPath
}
-- This is a subpart of NgramsTable.State.
type State = CoreState ()
......@@ -273,24 +274,24 @@ instance decodeDocument :: DecodeJson Document
--, text
}
docViewSpec :: Spec State LoadedDataProps Action
docViewSpec :: Spec State Props Action
docViewSpec = simpleSpec performAction render
where
performAction :: PerformAction State LoadedDataProps Action
performAction :: PerformAction State Props Action
performAction Refresh {path: {nodeId, listIds, tabType}} {ngramsVersion} = do
commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: mempty})
performAction (SetTermListItem n pl) {path: {nodeId, listIds, tabType}} {ngramsVersion} =
commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: pt})
where
pe = NgramsPatch { patch_list: pl, patch_children: mempty }
pt = PatchMap $ Map.singleton n pe
performAction (AddNewNgram ngram termList) {path: params} _ =
lift $ addNewNgram ngram (Just termList) params
pt = singletonNgramsTablePatch CTabTerms n pe
performAction (AddNewNgram ngram termList) {path: {nodeId, listIds, tabType}} {ngramsVersion} =
commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: pt})
where
pt = addNewNgram CTabTerms ngram termList
render :: Render State LoadedDataProps Action
render dispatch { path: pageParams
, loaded: { ngramsTable: Versioned { data: initTable }, document }
, dispatch: loaderDispatch }
render :: Render State Props Action
render dispatch { loaded: { ngramsTable: Versioned { data: initTable }, document } }
{ ngramsTablePatch }
_reactChildren =
[ autoUpdateElt { duration: 3000
......@@ -327,23 +328,27 @@ docViewSpec = simpleSpec performAction render
ngramsTable = applyNgramsTablePatch ngramsTablePatch initTable
setTermList ngram Nothing newList = dispatch $ AddNewNgram ngram 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"]
text' x = text $ maybe "Nothing" identity x
badge s = span [className "badge badge-default badge-pill"] [text s]
NodePoly {hyperdata : Document doc} = document
layout :: Spec {} {nodeId :: Int, listId :: Int} Void
layout = cmapProps (\{nodeId, listId} -> {nodeId, listIds: [listId], tabType})
$ simpleSpec defaultPerformAction render
docViewClass :: ReactClass
{ children :: Children
, 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
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
, termSizeFilter : Nothing
}
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 =
-- where
-- treespec = over _render \frender d p (State s) c ->
-- [ div [ className "col-md-2", _id "graph-tree", style {marginTop: "65px"}] $
-- [
-- button [className "btn btn-primary" , onClick \_ -> d ToggleTree]
-- [text $ if s.showTree then "Hide Tree" else "Show Tree"]
-- ]
-- <>
-- if s.showTree then (frender d p (State s) c) else []
-- ]
-- 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, 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' d _ (State st@{sigmaSettings, graphData: GraphData {sides,metaData }}) _ =
-- [ div [className "container-fluid", style {paddingTop : "90px" }]
......
......@@ -4,7 +4,6 @@ import Prelude hiding (div)
import Data.Lens (view)
import Data.List (fromFoldable)
import Data.Tuple (Tuple(..))
import Gargantext.Config (TabType(..), TabSubType(..))
import Gargantext.Components.GraphExplorer.Types (GraphSideCorpus(..))
import Gargantext.Components.FacetsTable (TextQuery, docViewSpec)
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
import Gargantext.Components.Lang.Landing.FrFR as Fr
import Gargantext.Components.Data.Landing (BlockText(..), BlockTexts(..), Button(..), LandingData(..))
import Gargantext.Components.Data.Lang (Lang(..))
import Gargantext.Pages.Home.States (State, initialState)
import Gargantext.Pages.Home.Actions (Action, performAction)
import Reactix as R
import Reactix.DOM.HTML as H
import React (ReactElement)
import React.DOM (a, div, h3, i, img, p, span, text)
import React.DOM.Props (Props, _id, aria, className, href, src, target, title, height, width)
import Thermite (Render, Spec, simpleSpec, hideState, focusState)
import React.DOM.Props (Props)
import Thermite (Spec, hideState, focusState, Render, simpleSpec)
import Gargantext.Utils.Reactix as R2
-- Layout |
......@@ -26,80 +27,82 @@ landingData FR = Fr.landingData
landingData EN = En.landingData
layoutLanding :: Lang -> Spec {} {} Void
layoutLanding = hideState (const $ unwrap initialState)
<<< focusState (re _Newtype)
<<< layoutLanding' <<< landingData
layoutLanding = layoutLanding' <<< landingData
------------------------------------------------------------------------
layoutLanding' :: LandingData -> Spec State {} Action
layoutLanding' hd = simpleSpec performAction render
layoutLanding' :: LandingData -> Spec {} {} Void
layoutLanding' hd = R2.elSpec $ R.hooksComponent "LayoutLanding" cpt
where
render :: Render State {} Action
render dispatch _ state _ =
[ div [ className "container1" ] [ jumboTitle hd false ]
, div [ className "container1" ] [] -- TODO put research form
, div [ className "container1" ] [ blocksRandomText' hd ]
]
cpt {} _children = do
pure $ H.span {} [
H.div { className: "container1" }
[ jumboTitle hd false ]
, 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 :: BlockTexts -> ReactElement
blocksRandomText :: BlockTexts -> R.Element
blocksRandomText (BlockTexts bt) =
div [ className "row" ] ( map showBlock bt.blocks )
H.div { className: "row" } ( map showBlock bt.blocks )
where
showBlock :: BlockText -> ReactElement
showBlock :: BlockText -> R.Element
showBlock (BlockText b) =
div [ className "col-md-4 content" ]
[ h3 [] [ a [ href b.href, title b.title]
[ i [className b.icon] []
, text (" " <> b.titleText)
]
]
, p [] [ text b.text ]
, p [] [ docButton b.docButton ]
]
docButton :: Button -> ReactElement
docButton (Button b) = a [ className "btn btn-outline-primary btn-sm spacing-class"
, href b.href
, target "blank"
, title b.title
] [ span [ aria {hidden : true}
, className "glyphicon glyphicon-hand-right"
] []
, text b.text
]
jumboTitle :: LandingData -> Boolean -> ReactElement
jumboTitle (LandingData hd) b = div jumbo
[ div [className "row" ]
[ div [ className "col-md-12 content"]
[ div [ className "center" ]
[ div [_id "logo-designed" ]
[ img [ src "images/logo.png"
, title hd.logoTitle
]
]
]
]
]
]
where
jumbo = case b of
true -> [className "jumbotron"]
false -> []
imageEnter :: LandingData -> Props -> ReactElement
imageEnter (LandingData hd) action = div [className "row"]
[ div [className "col-md-offset-5 col-md-6 content"]
[ img [ src "images/Gargantextuel-212x300.jpg"
, _id "funnyimg"
, title hd.imageTitle
, action
]
]
]
H.div { className: "col-md-4 content" }
[ H.h3 {} [ H.a { href: b.href, title: b.title}
[ H.i {className: b.icon} []
, H.text (" " <> b.titleText)
]
]
, H.p {} [ H.text b.text ]
, H.p {} [ docButton b.docButton ]
]
docButton :: Button -> R.Element
docButton (Button b) =
H.a { className: "btn btn-outline-primary btn-sm spacing-class"
, href: b.href
, target: "blank"
, title: b.title
} [ H.span { aria: {hidden : true}
, className: "glyphicon glyphicon-hand-right"
} []
, H.text b.text
]
jumboTitle :: LandingData -> Boolean -> R.Element
jumboTitle (LandingData hd) b =
H.div {className: jumbo}
[ H.div { className: "row" }
[ H.div { className: "col-md-12 content" }
[ H.div { className: "center" }
[ H.div { id: "logo-designed" }
[ H.img { src: "images/logo.png"
, title: hd.logoTitle
}
]
]
]
]
]
where
jumbo = case b of
true -> "jumbotron"
false -> ""
imageEnter :: LandingData -> Props -> R.Element
imageEnter (LandingData hd) action =
H.div {className: "row"}
[ H.div {className: "col-md-offset-5 col-md-6 content"}
[ H.img { src: "images/Gargantextuel-212x300.jpg"
, id: "funnyimg"
, title: hd.imageTitle
, action
}
]
]
......@@ -3,14 +3,12 @@ module Gargantext.Pages.Layout where
import Prelude hiding (div)
-- import Gargantext.Components.Login as LN
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.Graph as GE
-- import Gargantext.Pages.Corpus.Tabs.Terms.NgramsTable as NG
-- import Gargantext.Pages.Home as L
-- import Gargantext.Pages.Layout.Specs.Search as S
import Gargantext.Router (Routes(..))
dispatchAction :: forall ignored m.
......@@ -25,17 +23,9 @@ dispatchAction dispatcher _ Login = do
dispatcher $ SetRoute Login
-- dispatcher $ LoginA TODO
dispatchAction dispatcher _ AddCorpus = do
dispatcher $ SetRoute AddCorpus
dispatcher $ AddCorpusA AC.LoadDatabaseDetails
dispatchAction dispatcher _ (Corpus n) = do
dispatcher $ SetRoute $ Corpus n
dispatchAction dispatcher _ SearchView = do
dispatcher $ SetRoute SearchView
-- dispatcher $ SearchA TODO
dispatchAction dispatcher _ (UserPage id) = do
dispatcher $ SetRoute $ UserPage id
......@@ -48,6 +38,9 @@ dispatchAction dispatcher _ (Annuaire id) = do
dispatchAction dispatcher _ (Folder id) = do
dispatcher $ SetRoute $ Folder id
dispatchAction dispatcher _ (CorpusDocument c i n) = do
dispatcher $ SetRoute $ CorpusDocument c i n
dispatchAction dispatcher _ (Document i n) = do
dispatcher $ SetRoute $ Document i n
......@@ -56,5 +49,11 @@ dispatchAction dispatcher _ (PGraphExplorer nid) = do
-- dispatcher $ GraphExplorerA $ GE.LoadGraph nid
--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
dispatcher $ SetRoute Dashboard
......@@ -12,9 +12,7 @@ import Routing.Hash (setHash)
import Gargantext.Components.Login as LN
import Gargantext.Components.Modals.Modal (modalShow)
import Gargantext.Pages.Annuaire as Annuaire
--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.Corpus.Graph as GE
import Gargantext.Pages.Layout.States (AppState)
import Gargantext.Prelude
import Gargantext.Router (Routes)
......@@ -24,9 +22,7 @@ import Gargantext.Router (Routes)
data Action
= LoginA LN.Action
| SetRoute Routes
| SearchA S.Action
| AddCorpusA AC.Action
-- | GraphExplorerA GE.Action
| GraphExplorerA GE.Action
| AnnuaireAction Annuaire.Action
| ShowLogin
| Logout
......@@ -61,9 +57,7 @@ performAction ShowAddCorpus _ _ = void do
---------------------------------------------------------
performAction (LoginA _) _ _ = pure unit
performAction (AddCorpusA _) _ _ = pure unit
performAction (SearchA _) _ _ = pure unit
-- performAction (GraphExplorerA _) _ _ = pure unit
performAction (GraphExplorerA _) _ _ = pure unit
performAction (AnnuaireAction _) _ _ = pure unit
-- liftEffect $ modalShow "addCorpus"
-- modifyState $ _ {showCorpus = true}
......@@ -76,18 +70,6 @@ _loginAction = prism LoginA \action ->
LoginA caction -> Right caction
_-> 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 AnnuaireAction \action ->
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)
import Data.Tuple.Nested ( (/\) )
import Effect.Class (liftEffect)
import Effect.Uncurried (EffectFn1, mkEffectFn1)
import Thermite (Spec, defaultPerformAction, simpleSpec)
import Reactix as R
import DOM.Simple.Console
import Effect.Aff (launchAff)
......@@ -53,11 +52,13 @@ onSearchChange (search /\ setSearch) =
where
triggerSearch q = do
launchAff $ do
liftEffect $ log2 "Searching db: " $ show q.database
liftEffect $ log2 "Searching term: " q.term
(r :: Unit) <- Ajax.search (searchQuery q)
liftEffect $ log2 "Return:" r
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 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