Commit cfed8575 authored by Przemyslaw Kaminski's avatar Przemyslaw Kaminski

Merge branch 'dev' into dev-markdown

parents 004cab75 6eb24204
......@@ -88,8 +88,15 @@ Some options:
Once you have node and yarn installed, you may install deps with:
```shell
yarn install && yarn install-ps
yarn install && yarn add psc-package && yarn install-ps && yarn build
```
You need to copy index.html:
```shell
cp src/index.html dist/
```
(Be careful, to update or upgrade your install, maybe you need to remove
old files in node_modules).
### Development
......
This diff is collapsed.
This diff is collapsed.
.fa{
display:inline-block;
font:normal normal normal 14px/1 ForkAwesome;
font-size:inherit;
text-rendering:auto;
-webkit-font-smoothing:antialiased;
-moz-osx-font-smoothing:grayscale}
.fa-lg{
font-size:1.33333333em;
line-height:.75em;
vertical-align:-15%}
.fa-2x{
font-size:2em}
.fa-3x{
font-size:3em}
.fa-4x{
font-size:4em}
.fa-5x{
font-size:5em}
.fa-fw{
width:1.28571429em;
text-align:center}
.fa-ul{
padding-left:0;
margin-left:2.14285714em;
list-style-type:none}
.fa-ul>li{
position:relative}
.fa-li{
position:absolute;
left:-2.14285714em;
width:2.14285714em;
top:.14285714em;
text-align:center}
.fa-li.fa-lg{
left:-1.85714286em}
.fa-border{
padding:.2em .25em .15em;
border:solid .08em #eee;
border-radius:.1em}
.fa-pull-left{
float:left}
.fa-pull-right{
float:right}
.fa.fa-pull-left{
margin-right:.3em}
.fa.fa-pull-right{
margin-left:.3em}
.pull-right{
float:right}
.pull-left{
float:left}
.fa.pull-left{
margin-right:.3em}
.fa.pull-right{
margin-left:.3em}
.fa-spin{
-webkit-animation:fa-spin 2s infinite linear;
animation:fa-spin 2s infinite linear}
.fa-pulse{
-webkit-animation:fa-spin 1s infinite steps(8);
animation:fa-spin 1s infinite steps(8)}
@-webkit-keyframes fa-spin{
0%{
-webkit-transform:rotate(0);
transform:rotate(0)}
100%{
-webkit-transform:rotate(359deg);
transform:rotate(359deg)}
}
@keyframes fa-spin{
0%{
-webkit-transform:rotate(0);
transform:rotate(0)}
100%{
-webkit-transform:rotate(359deg);
transform:rotate(359deg)}
}
.fa-rotate-90{
-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";
-webkit-transform:rotate(90deg);
-ms-transform:rotate(90deg);
transform:rotate(90deg)}
.fa-rotate-180{
-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";
-webkit-transform:rotate(180deg);
-ms-transform:rotate(180deg);
transform:rotate(180deg)}
.fa-rotate-270{
-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";
-webkit-transform:rotate(270deg);
-ms-transform:rotate(270deg);
transform:rotate(270deg)}
.fa-flip-horizontal{
-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";
-webkit-transform:scale(-1,1);
-ms-transform:scale(-1,1);
transform:scale(-1,1)}
.fa-flip-vertical{
-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";
-webkit-transform:scale(1,-1);
-ms-transform:scale(1,-1);
transform:scale(1,-1)}
:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-rotate-90{
filter:none}
.fa-stack{
position:relative;
display:inline-block;
width:2em;
height:2em;
line-height:2em;
vertical-align:middle}
.fa-stack-1x,.fa-stack-2x{
position:absolute;
left:0;
width:100%;
text-align:center}
.fa-stack-1x{
line-height:inherit}
.fa-stack-2x{
font-size:2em}
.fa-inverse{
color:#fff}
......@@ -13,53 +13,76 @@ dockerrun(){
sudo docker run -u "$UID" -e PATH="$P" -v $PWD:/app -w /app "$@"
}
NODE=node:buster-garg
dockerrunnode(){
dockerrun "$NODE" "$@"
}
unalias npm yarn bower pulp repl &>/dev/null || :
unset npm yarn bower pulp repl &>/dev/null || :
npm(){
dockerrun node npm "$@"
dockerrunnode npm "$@"
}
yarn(){
dockerrun node yarn "$@"
dockerrunnode yarn "$@"
}
bower(){
dockerrun node bower "$@"
dockerrunnode bower "$@"
}
dependencies(){
dockerrun node psc-dependencies "$@"
dockerrunnode psc-dependencies "$@"
}
package(){
dockerrun node psc-package "$@"
dockerrunnode psc-package "$@"
}
pulp(){
dockerrun node pulp --psc-package "$@"
dockerrunnode pulp --psc-package "$@"
}
repl(){
dockerrun -ti node pulp --psc-package repl "$@"
dockerrun -ti "$NODE" pulp --psc-package repl "$@"
}
sass(){
dockerrunnode yarn sass
}
check(){
pulp test "$@"
}
pscpackagehack(){
cp $HOME/bin/psc-package node_modules/.bin
}
setup(){
yarn install &&
yarn rebuild-set &&
pscpackagehack &&
yarn install-ps
}
build(){
pulp browserify --to dist/bundle.js
echo prefer: compile
yarn build
#pulp browserify --to dist/bundle.js
}
compile(){
yarn compile
}
serve(){
dockerrun node http-server -p 2015 --cors dist
#yarn dev
#dockerrunnode http-server -p 2015 --cors dist
dockerrunnode webpack-dev-server --env dev --mode development
}
dev(){
......
{
"name": "gargantext",
"set": "local",
"source": ".psc-package",
"source": ".psc-package/local/.set/packages.json",
"depends": [
"affjax",
"argonaut",
......
......@@ -62,7 +62,7 @@ appCpt = R.hooksComponent "G.C.App.app" cpt where
Corpus sid nodeId -> withSession sid $ \session -> forested $ corpusLayout { key: show nodeId, nodeId, session }
Texts sid nodeId -> withSession sid $ \session -> forested $ textsLayout { nodeId, session, frontends }
Lists sid nodeId -> withSession sid $ \session -> forested $ listsLayout { nodeId, session }
Dashboard sid _nodeId -> withSession sid $ \session -> forested $ dashboardLayout {}
Dashboard sid nodeId -> withSession sid $ \session -> forested $ dashboardLayout { nodeId, session }
Annuaire sid nodeId -> withSession sid $ \session -> forested $ annuaireLayout { frontends, nodeId, session }
UserPage sid nodeId -> withSession sid $ \session -> forested $ userLayout { frontends, nodeId, session }
ContactPage sid aId nodeId -> withSession sid $ \session -> forested $ annuaireUserLayout { annuaireId: aId, frontends, nodeId, session }
......
......@@ -141,8 +141,8 @@ codeEditorCpt = R.hooksComponent "G.C.CE.CodeEditor" cpt
dividerHidden _ = " hidden"
langClass :: CodeType -> String
langClass Haskell = " language-haskell"
langClass JSON = " language-json"
langClass Haskell = " language-haskell"
langClass JSON = " language-json"
langClass Markdown = " language-md"
previewHidden :: ViewType -> String
......@@ -308,7 +308,7 @@ initControls code defaultCodeType = do
codeOverlayElRef <- R.useRef null
codeType <- R.useState' defaultCodeType
error <- R.useState' Nothing
viewType <- R.useState' Both
viewType <- R.useState' Preview
pure $ {
codeElRef
......
......@@ -343,7 +343,7 @@ loadPage session {nodeId, tabType, query, listId, corpusId, params: {limit, offs
let docs = res2corpus <$> res.docs
pure $
if mock then
Tuple 4737 (take limit $ drop offset sampleData)
Tuple 0 (take limit $ drop offset sampleData)
else
Tuple res.count docs
where
......
......@@ -4,16 +4,14 @@ import Gargantext.Prelude
import Data.Array as A
import Data.Maybe (Maybe(..))
import Data.Set (Set)
import Data.Set as Set
import Data.Tuple (fst)
import Data.Tuple.Nested ((/\))
import Gargantext.Components.Forest.Tree (treeView)
import Gargantext.Components.Forest.Tree.Node.Action (Reload)
import Gargantext.Components.Login.Types (TreeId)
import Gargantext.Ends (Frontends)
import Gargantext.Routes (AppRoute)
import Gargantext.Sessions (Session(..), Sessions, unSessions)
import Gargantext.Sessions (Session(..), Sessions, OpenNodes, unSessions)
import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
......@@ -33,7 +31,7 @@ forestCpt = R.hooksComponent "G.C.Forest.forest" cpt where
cpt {frontends, route, sessions, showLogin } _ = do
-- NOTE: this is a hack to reload the tree view on demand
reload <- R.useState' (0 :: Reload)
openNodes <- R2.useLocalStorageState R2.openNodesKey (Set.empty :: Set TreeId)
openNodes <- R2.useLocalStorageState R2.openNodesKey (Set.empty :: OpenNodes)
R2.useCache
(frontends /\ route /\ sessions /\ fst openNodes /\ fst reload)
(cpt' openNodes reload showLogin)
......
module Gargantext.Components.Forest.Tree where
import Gargantext.Components.Forest.Tree.Node.Action (Action(..), CreateValue(..), FTree, ID, LNode(..), NTree(..), Reload, RenameValue(..), Tree, createNode, deleteNode, loadNode, renameNode)
import Gargantext.Prelude (Unit, bind, const, discard, map, pure, void, ($), (+), (/=), (<>))
import DOM.Simple.Console (log2)
import Data.Array as A
import Data.Maybe (Maybe)
import Data.Set (Set)
import Data.Set as Set
import Data.Tuple (Tuple(..), fst, snd)
import Data.Tuple.Nested ((/\))
import Effect.Aff (Aff)
import Effect.Class (liftEffect)
import Reactix as R
import Reactix.DOM.HTML as H
import Gargantext.Components.Forest.Tree.Node.Action (Action(..), CreateValue(..), FTree, ID, LNode(..), NTree(..), Reload, RenameValue(..), Tree, createNode, deleteNode, loadNode, renameNode)
import Gargantext.Components.Forest.Tree.Node.Action.Upload (uploadFile)
import Gargantext.Components.Forest.Tree.Node.Box (nodeMainSpan)
import Gargantext.Components.Loader (loader)
import Gargantext.Components.Login.Types (TreeId)
import Gargantext.Ends (Frontends)
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Prelude (Unit, bind, const, discard, map, pure, void, ($), (+), (/=), (<>))
import Gargantext.Routes (AppRoute)
import Gargantext.Sessions (Session)
import Gargantext.Sessions (OpenNodes, Session, mkNodeId)
import Gargantext.Types as GT
import Reactix as R
import Reactix.DOM.HTML as H
------------------------------------------------------------------------
type Props = ( root :: ID
, mCurrentRoute :: Maybe AppRoute
, session :: Session
, frontends :: Frontends
, openNodes :: R.State (Set TreeId)
, openNodes :: R.State OpenNodes
, reload :: R.State Reload
)
......@@ -47,7 +43,7 @@ type Props' = ( root :: ID
, mCurrentRoute :: Maybe AppRoute
, session :: Session
, frontends :: Frontends
, openNodes :: R.State (Set TreeId)
, openNodes :: R.State OpenNodes
, reload :: R.State Reload
)
......@@ -55,17 +51,18 @@ treeLoadView :: Record Props' -> R.Element
treeLoadView p = R.createElement treeLoadView' p []
treeLoadView' :: R.Component Props'
treeLoadView' = R.staticComponent "TreeLoadView" cpt
treeLoadView' = R.hooksComponent "TreeLoadView" cpt
where
cpt {root, mCurrentRoute, session, frontends, openNodes, reload} _ = do
loader root (loadNode session) $ \loaded ->
loadedTreeView {tree: loaded, mCurrentRoute, session, frontends, openNodes, reload}
let fetch _ = loadNode session root
let paint loaded = loadedTreeView {tree: loaded, mCurrentRoute, session, frontends, openNodes, reload}
useLoader {root, counter: fst reload} fetch paint
type TreeViewProps = ( tree :: FTree
, mCurrentRoute :: Maybe AppRoute
, frontends :: Frontends
, session :: Session
, openNodes :: R.State (Set TreeId)
, openNodes :: R.State OpenNodes
, reload :: R.State Reload
)
......@@ -77,28 +74,30 @@ loadedTreeView' :: R.Component TreeViewProps
loadedTreeView' = R.hooksComponent "LoadedTreeView" cpt
where
cpt {tree, mCurrentRoute, session, frontends, openNodes, reload} _ = do
treeState <- R.useState' {tree, asyncTasks: []}
tasks <- R.useState' []
pure $ H.div {className: "tree"}
[ toHtml reload treeState session frontends mCurrentRoute openNodes ]
[ toHtml reload tree tasks session frontends mCurrentRoute openNodes ]
------------------------------------------------------------------------
toHtml :: R.State Reload
-> R.State Tree
-> FTree
-> R.State (Array GT.AsyncTaskWithType)
-> Session
-> Frontends
-> Maybe AppRoute
-> R.State (Set TreeId)
-> R.State OpenNodes
-> R.Element
toHtml reload treeState@(ts@{tree: (NTree (LNode {id, name, nodeType}) ary), asyncTasks} /\ setTreeState) session frontends mCurrentRoute openNodes = R.createElement el {} []
toHtml reload tree@(NTree (LNode {id, name, nodeType}) ary) tasks@(asyncTasks /\ setAsyncTasks) session frontends mCurrentRoute openNodes = R.createElement el {} []
where
el = R.hooksComponent "NodeView" cpt
pAction = performAction session reload openNodes treeState
pAction = performAction session tree reload openNodes tasks
cpt props _ = do
let folderIsOpen = Set.member id (fst openNodes)
let nodeId = mkNodeId session id
let folderIsOpen = Set.member nodeId (fst openNodes)
let setFn = if folderIsOpen then Set.delete else Set.insert
let toggleFolderIsOpen _ = (snd openNodes) (setFn id)
let toggleFolderIsOpen _ = (snd openNodes) (setFn nodeId)
let folderOpen = Tuple folderIsOpen toggleFolderIsOpen
let withId (NTree (LNode {id: id'}) _) = id'
......@@ -116,7 +115,7 @@ toHtml reload treeState@(ts@{tree: (NTree (LNode {id, name, nodeType}) ary), asy
)
]
onAsyncTaskFinish (GT.AsyncTaskWithType {task: GT.AsyncTask {id: id'}}) = setTreeState $ const $ ts { asyncTasks = newAsyncTasks }
onAsyncTaskFinish (GT.AsyncTaskWithType {task: GT.AsyncTask {id: id'}}) = setAsyncTasks $ const newAsyncTasks
where
newAsyncTasks = A.filter (\(GT.AsyncTaskWithType {task: GT.AsyncTask {id: id''}}) -> id' /= id'') asyncTasks
......@@ -126,7 +125,7 @@ childNodes :: Session
-> R.State Reload
-> R.State Boolean
-> Maybe AppRoute
-> R.State (Set TreeId)
-> R.State OpenNodes
-> Array FTree
-> Array R.Element
childNodes _ _ _ _ _ _ [] = []
......@@ -140,37 +139,37 @@ childNodes session frontends reload (true /\ _) mCurrentRoute openNodes ary =
childNode props = R.createElement el props []
el = R.hooksComponent "ChildNodeView" cpt
cpt {tree, asyncTasks} _ = do
treeState <- R.useState' {tree, asyncTasks}
pure $ toHtml reload treeState session frontends mCurrentRoute openNodes
tasks <- R.useState' asyncTasks
pure $ toHtml reload tree tasks session frontends mCurrentRoute openNodes
performAction :: Session
-> FTree
-> R.State Int
-> R.State (Set TreeId)
-> R.State Tree
-> R.State OpenNodes
-> R.State (Array GT.AsyncTaskWithType)
-> Action
-> Aff Unit
performAction session (_ /\ setReload) (_ /\ setOpenNodes) (s@{tree: NTree (LNode {id}) _} /\ setTree) DeleteNode = do
performAction session (NTree (LNode {id}) _) (_ /\ setReload) (_ /\ setOpenNodes) _ DeleteNode = do
void $ deleteNode session id
liftEffect do
setOpenNodes (Set.delete id)
setOpenNodes (Set.delete (mkNodeId session id))
setReload (_ + 1)
performAction session (_ /\ setReload) _ ({tree: NTree (LNode {id}) _} /\ setTree) (SearchQuery task) = do
liftEffect $ setTree $ \t@{asyncTasks} -> t { asyncTasks = A.cons task asyncTasks }
performAction session (NTree (LNode {id}) _) (_ /\ setReload) _ (_ /\ setAsyncTasks) (SearchQuery task) = do
liftEffect $ setAsyncTasks $ A.cons task
liftEffect $ log2 "[performAction] SearchQuery task:" task
liftEffect $ setReload (_ + 1)
performAction session _ _ ({tree: NTree (LNode {id}) _} /\ setTree) (Submit name) = do
performAction session (NTree (LNode {id}) _) _ _ _ (Submit name) = do
void $ renameNode session id $ RenameValue {name}
liftEffect $ setTree $ \s@{tree: NTree (LNode node) arr} -> s {tree = NTree (LNode node {name = name}) arr}
performAction session (_ /\ setReload) (_ /\ setOpenNodes) (s@{tree: NTree (LNode {id}) _} /\ setTree) (CreateSubmit name nodeType) = do
performAction session (NTree (LNode {id}) _) (_ /\ setReload) (_ /\ setOpenNodes) _ (CreateSubmit name nodeType) = do
void $ createNode session id $ CreateValue {name, nodeType}
liftEffect do
setOpenNodes (Set.insert id)
setOpenNodes (Set.insert (mkNodeId session id))
setReload (_ + 1)
performAction session _ _ ({tree: NTree (LNode {id}) _} /\ setTree) (UploadFile fileType contents) = do
performAction session (NTree (LNode {id}) _) _ _ (_ /\ setAsyncTasks) (UploadFile fileType contents) = do
task <- uploadFile session id fileType contents
liftEffect $ setTree $ \t@{asyncTasks} -> t { asyncTasks = A.cons task asyncTasks }
liftEffect $ setAsyncTasks $ A.cons task
liftEffect $ log2 "uploaded, task:" task
......@@ -57,10 +57,10 @@ nodeMainSpan d p folderOpen session frontends = R.createElement el p []
el = R.hooksComponent "NodeMainSpan" cpt
cpt props@{id, asyncTasks, mCurrentRoute, name, nodeType, onAsyncTaskFinish} _ = do
-- only 1 popup at a time is allowed to be opened
popupOpen <- R.useState' (Nothing :: Maybe NodePopup)
popupOpen <- R.useState' (Nothing :: Maybe NodePopup)
popupPosition <- R.useState' (Nothing :: Maybe R2.Point)
droppedFile <- R.useState' (Nothing :: Maybe DroppedFile)
isDragOver <- R.useState' false
droppedFile <- R.useState' (Nothing :: Maybe DroppedFile)
isDragOver <- R.useState' false
pure $ H.span (dropProps droppedFile isDragOver) $
[ folderIcon nodeType folderOpen
......
......@@ -204,7 +204,7 @@ type SigmaSettings =
-- selected nodes <=> special label
sigmaSettings :: {|SigmaSettings}
sigmaSettings =
{ animationsTime: 5500.0
{ animationsTime: 30000.0
, autoRescale: true
, autoResize: true
, batchEdgesDrawing: true
......@@ -217,7 +217,7 @@ sigmaSettings =
, defaultLabelSize: 8.0 -- (old tina: showLabelsIfZoom)
, defaultNodeBorderColor : "#000" -- <- if nodeBorderColor = 'default'
, defaultNodeColor: "#FFF"
, doubleClickEnabled: false
, doubleClickEnabled: false -- indicates whether or not the graph can be zoomed on double-click
, drawEdgeLabels: true
, drawEdges: true
, drawLabels: true
......@@ -228,12 +228,12 @@ sigmaSettings =
, edgeHoverPrecision: 2.0
, edgeHoverSizeRatio: 2.0
, enableHovering: true
, font: "Droid Sans" -- font params
, font: "arial" -- font params
, fontStyle: "bold"
, hideEdgesOnMove: true
, labelSize : "fixed"
, labelSize : "proportional" -- alt : proportional
, labelSizeRatio: 2.0 -- label size in ratio of node size
, labelThreshold: 5.0 -- min node cam size to start showing label
, labelThreshold: 7.0 -- min node cam size to start showing label
, maxEdgeSize: 1.0
, maxNodeSize: 8.0
, minEdgeSize: 0.5 -- in fact used in tina as edge size
......@@ -256,7 +256,7 @@ sigmaSettings =
, verbose : true
, zoomMax: 1.7
, zoomMin: 0.0
, zoomingRatio: 3.2
, zoomingRatio: 1.7
}
type ForceAtlas2Settings =
......@@ -280,17 +280,17 @@ type ForceAtlas2Settings =
forceAtlas2Settings :: {|ForceAtlas2Settings}
forceAtlas2Settings =
{ adjustSizes : false
{ adjustSizes : true
, barnesHutOptimize : true
, edgeWeightInfluence : 0.0
, edgeWeightInfluence : 1.0
-- fixedY : false
, gravity : 1.0
, iterationsPerRender : 4.0
, linLogMode : true -- false
, iterationsPerRender : 10.0
, linLogMode : false -- false
, outboundAttractionDistribution: false
, scalingRatio : 4.0
, scalingRatio : 10.0
, skipHidden: false
, slowDown : 0.7
, startingIterations : 2.0
, slowDown : 1.0
, startingIterations : 10.0
, strongGravityMode : false
}
......@@ -6,7 +6,6 @@ module Gargantext.Components.GraphExplorer.Search
import Prelude
import Data.Sequence as Seq
import Data.Set as Set
import Data.String as S
import Data.Tuple.Nested ((/\))
import DOM.Simple.Console (log2)
import Effect (Effect)
......@@ -14,6 +13,7 @@ import Reactix as R
import Reactix.DOM.HTML as H
import Gargantext.Components.InputWithAutocomplete (inputWithAutocomplete)
import Gargantext.Utils (queryMatchesLabel)
import Gargantext.Hooks.Sigmax.Types as SigmaxT
type Props = (
......@@ -24,9 +24,7 @@ type Props = (
-- | Whether a node matches a search string
nodeMatchesSearch :: String -> Record SigmaxT.Node -> Boolean
nodeMatchesSearch s n = S.contains (S.Pattern $ normalize s) (normalize n.label)
where
normalize = S.toLower
nodeMatchesSearch s n = queryMatchesLabel s n.label
searchNodes :: String -> Seq.Seq (Record SigmaxT.Node) -> Seq.Seq (Record SigmaxT.Node)
searchNodes "" _ = Seq.empty
......
......@@ -105,9 +105,9 @@ chooserCpt = R.staticComponent "G.C.Login.chooser" cpt where
search = [ H.input {className: "form-control", type:"text", placeholder: "Search for your institute"}]
new = [ H.h3 {} [H.text "Last connection(s)"]
, H.table {className : "table"}
[ H.thead {className: "thead-dark"} [ H.tr {} [ H.th {} [H.text "Label of instance"]
, H.th {} [H.text "Gargurl"]
, H.th {} [ H.text ""]
[ H.thead {className: "thead-dark"} [ H.tr {} [ H.th {} [ H.text ""]
, H.th {} [H.text "Label of instance"]
, H.th {} [H.text "Gargurl"]
]
]
, H.tbody {} (map (renderBackend backend) backends)
......@@ -127,17 +127,18 @@ renderSessions sessions = R.fragment (renderSession sessions <$> unSessions (fst
where
click _ = (snd sessions') (Sessions.Logout session)
renderBackend :: R.State (Maybe Backend) -> Backend -> R.Element
renderBackend state backend@(Backend {name}) =
H.tr {} [ H.td {} [H.a { on : {click}} [H.text label]]
H.tr {} [ iconLog
, H.td {} [H.a { on : {click}} [H.text label]]
, H.td {} [ H.text url ]
, H.td {} [H.a { on : {click}
, className : "glyphitem glyphicon glyphicon-log-in"
, title: "Log In"} []
]
]
where
iconLog = H.td {} [ H.a { on : {click}
, className : "glyphitem glyphicon glyphicon-log-in"
, title: "Log In"} []
]
click _ = (snd state) (const $ Just backend)
label = DST.toUpper $ fromMaybe "" $ head $ DST.split (DST.Pattern ".") name
url = "garg://" <> name
......
module Gargantext.Components.Login.Types where
import Prelude
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)
......
......@@ -6,7 +6,7 @@ module Gargantext.Components.NgramsTable
import Prelude
( class Show, Unit, bind, const, discard, identity, map, mempty, not
, pure, show, unit, (#), ($), (&&), (+), (/=), (<$>), (<<<), (<>), (=<<)
, (==), (||), otherwise )
, (==), (||), otherwise, when )
import Data.Array as A
import Data.FunctorWithIndex (mapWithIndex)
import Data.Lens (Lens', to, view, (%~), (.~), (^.), (^..), (^?))
......@@ -18,7 +18,7 @@ import Data.Lens.Record (prop)
import Data.List as List
import Data.Map (Map)
import Data.Map as Map
import Data.Maybe (Maybe(..), maybe, isNothing)
import Data.Maybe (Maybe(..), maybe, isJust)
import Data.Monoid.Additive (Additive(..))
import Data.Ord.Down (Down(..))
import Data.Set (Set)
......@@ -31,7 +31,8 @@ import Reactix as R
import Reactix.DOM.HTML as H
import React (ReactClass, ReactElement, Children)
import React.DOM (a, i, input, li, span, text, ul)
import React.DOM.Props (_type, checked, className, onChange, onClick, style)
import React.DOM.Props ( _type, checked, className, onChange, onClick, style
, readOnly)
import React.DOM.Props as DOM
import Thermite as Thermite
import Thermite (modifyState_)
......@@ -50,6 +51,7 @@ import Gargantext.Components.NgramsTable.Core
import Gargantext.Components.Loader (loader)
import Gargantext.Components.Table as T
import Gargantext.Sessions (Session)
import Gargantext.Utils (queryMatchesLabel)
import Gargantext.Utils.Reactix as R2
import Unsafe.Coerce (unsafeCoerce)
......@@ -167,7 +169,10 @@ tableContainer { path: {searchQuery, termListFilter, termSizeFilter} /\ setPath
, H.div {} (
if A.null props.tableBody && searchQuery /= "" then [
H.button { className: "btn btn-primary"
, on: {click: const $ dispatch $ addNewNgramA $ normNgram tabNgramType searchQuery}
, on: {click: const $ dispatch
$ addNewNgramA
$ normNgram tabNgramType searchQuery
}
}
[ H.text ("Add " <> searchQuery) ]
] else [])]
......@@ -204,7 +209,7 @@ tableContainer { path: {searchQuery, termListFilter, termSizeFilter} /\ setPath
ngramsClick {depth: 1, ngrams: child} =
Just $ dispatch $ ToggleChild false child
ngramsClick _ = Nothing
ngramsEdit _ = Nothing
ngramsEdit _ = Nothing
in
[ H.p {} [H.text $ "Editing " <> ngramsTermText ngrams]
, R2.buff $ renderNgramsTree { ngramsTable, ngrams, ngramsStyle: [], ngramsClick, ngramsEdit }
......@@ -324,7 +329,7 @@ loadedNgramsTableSpec = Thermite.simpleSpec performAction render
pt = singletonNgramsTablePatch parent pe
render :: Thermite.Render State (Record LoadedNgramsTableProps) Action
render dispatch { path: path@({scoreType, params} /\ setPath)
render dispatch { path: path@({searchQuery, scoreType, params, termListFilter} /\ setPath)
, versioned: Versioned { data: initTable }
, tabNgramType }
state@{ ngramsParent, ngramsChildren, ngramsLocalPatch
......@@ -336,7 +341,7 @@ loadedNgramsTableSpec = Thermite.simpleSpec performAction render
}
]
where
totalRecords = 47361 -- TODO
totalRecords = 0 -- TODO, 0 to show first users that it is fake (until it is fixed)
colNames = T.ColumnName <$> ["Select", "Map", "Stop", "Terms", "Score"] -- see convOrderBy
selected =
input
......@@ -354,7 +359,7 @@ loadedNgramsTableSpec = Thermite.simpleSpec performAction render
ngramsTable = applyNgramsPatches state initTable
orderWith =
case convOrderBy <$> params.orderBy of
Just ScoreAsc -> A.sortWith \x -> (snd x) ^. _NgramsElement <<< _occurrences
Just ScoreAsc -> A.sortWith \x -> (snd x) ^. _NgramsElement <<< _occurrences
Just ScoreDesc -> A.sortWith \x -> Down $ (snd x) ^. _NgramsElement <<< _occurrences
_ -> identity -- the server ordering is enough here
......@@ -365,9 +370,14 @@ loadedNgramsTableSpec = Thermite.simpleSpec performAction render
ngramsParentRoot :: Maybe NgramsTerm
ngramsParentRoot =
(\np -> ngramsTable ^? at np <<< _Just <<< _NgramsElement <<< _root <<< _Just) =<< ngramsParent
displayRow (NgramsElement {ngrams, root}) =
(\np -> ngramsTable ^? at np
<<< _Just
<<< _NgramsElement
<<< _root
<<< _Just
) =<< ngramsParent
displayRow (NgramsElement {ngrams, root, list}) =
root == Nothing
-- ^ Display only nodes without parents
&& ngramsChildren ^. at ngrams /= Just true
......@@ -376,8 +386,14 @@ loadedNgramsTableSpec = Thermite.simpleSpec performAction render
-- ^ and which are not our new parent
&& Just ngrams /= ngramsParentRoot
-- ^ and which are not the root of our new parent
|| -- Unless they are scheduled to be removed.
ngramsChildren ^. at ngrams == Just false
&& queryMatchesLabel searchQuery (ngramsTermText ngrams)
-- ^ and which matches the search query.
&& maybe true (_ == list) termListFilter
-- ^ and which matches the ListType filter.
|| ngramsChildren ^. at ngrams == Just false
-- ^ unless they are scheduled to be removed.
|| tablePatchHasNgrams ngramsLocalPatch ngrams
-- ^ unless they are being processed at the moment.
convertRow (Tuple ngrams ngramsElement) =
{ row: R2.buff <$> renderNgramsItem { ngramsTable, ngrams,
ngramsLocalPatch,
......@@ -493,7 +509,15 @@ renderNgramsItem { ngramsTable, ngrams, ngramsElement, ngramsParent
termList = ngramsElement ^. _NgramsElement <<< _list
ngramsStyle = [termStyle termList ngramsOpacity]
ngramsEdit = Just <<< dispatch <<< SetParentResetChildren <<< Just <<< view _ngrams
ngramsClick = Just <<< dispatch <<< cycleTermListItem <<< view _ngrams
ngramsClick
= Just <<< dispatch <<< cycleTermListItem <<< view _ngrams
-- ^ This is the old behavior it is nicer to use since one can
-- rapidly change the ngram list without waiting for confirmation.
-- However this might expose bugs. One of them can be reproduced
-- by clicking a multiple times on the same ngram, sometimes it stays
-- transient.
-- | ngramsTransient = const Nothing
-- | otherwise = Just <<< dispatch <<< cycleTermListItem <<< view _ngrams
selected =
input
[ _type "checkbox"
......@@ -509,16 +533,22 @@ renderNgramsItem { ngramsTable, ngrams, ngramsElement, ngramsParent
[ _type "checkbox"
, className "checkbox"
, checked chkd
, onChange $ const $ dispatch $
, readOnly ngramsTransient
, onChange $ const $ when (not ngramsTransient) $ dispatch $
setTermListA ngrams (replace termList termList'')
]
ngramsOpacity
| isNothing (ngramsLocalPatch.ngramsPatches ^. _PatchMap <<< at ngrams) = 1.0
ngramsTransient = tablePatchHasNgrams ngramsLocalPatch ngrams
-- ^ TODO here we do not look at ngramsNewElems, shall we?
| otherwise = 0.5
ngramsOpacity
| ngramsTransient = 0.5
| otherwise = 1.0
cycleTermListItem n = setTermListA n (replace termList (nextTermList termList))
tablePatchHasNgrams :: NgramsTablePatch -> NgramsTerm -> Boolean
tablePatchHasNgrams ngramsTablePatch ngrams =
isJust $ ngramsTablePatch.ngramsPatches ^. _PatchMap <<< at ngrams
termStyle :: TermList -> Number -> DOM.Props
termStyle GraphTerm opacity = style {color: "green", opacity}
termStyle StopTerm opacity = style {color: "red", opacity, textDecoration: "line-through"}
......
......@@ -180,13 +180,13 @@ _list = prop (SProxy :: SProxy "list")
derive instance newtypeNgramsElement :: Newtype NgramsElement _
_NgramsElement :: Iso' NgramsElement {
children :: Set NgramsTerm
, list :: TermList
, ngrams :: NgramsTerm
_NgramsElement :: Iso' NgramsElement {
children :: Set NgramsTerm
, list :: TermList
, ngrams :: NgramsTerm
, occurrences :: Int
, parent :: Maybe NgramsTerm
, root :: Maybe NgramsTerm
, parent :: Maybe NgramsTerm
, root :: Maybe NgramsTerm
}
_NgramsElement = _Newtype
......
......@@ -65,12 +65,15 @@ data FieldType =
, text :: MarkdownText
}
isJSON :: FieldType -> Boolean
isJSON (JSON _) = true
isJSON _ = false
isJSON :: Field FieldType -> Boolean
isJSON (Field {typ}) = isJSON' typ
where
isJSON' (JSON _) = true
isJSON' _ = false
getCorpusInfo :: List.List (Field FieldType) -> CorpusInfo
getCorpusInfo as = case List.head as of
getCorpusInfo as = case List.head (List.filter isJSON as) of
Just (Field {typ: JSON {authors, desc,query,title}}) -> CorpusInfo { title
, desc
, query
......
......@@ -57,4 +57,4 @@ ngramsViewCpt = R.staticComponent "ListsNgramsView" cpt
chart Authors = pie {session, path}
chart Sources = bar {session, path}
chart Institutes = tree {session, path: path2}
chart Terms = metrics {session, path: path2}
chart Terms = metrics {session, path: path2}
......@@ -169,14 +169,14 @@ sessionPath (R.CorpusMetrics {tabType, listId, limit} i) =
$ "metrics"
<> "?ngrams=" <> show listId
<> "&ngramsType=" <> showTabType' tabType
<> maybe "" (\x -> "&limit=" <> show x) limit
<> maybe "" limitUrl limit
-- TODO fix this url path
sessionPath (R.Chart {chartType, tabType} i) =
sessionPath $ R.NodeAPI Corpus i
$ show chartType
<> "?ngramsType=" <> showTabType' tabType
<> "&listType=GraphTerm" -- <> show listId
-- <> maybe "" (\x -> "&limit=" <> show x) limit
-- <> maybe "" limitUrl limit
-- sessionPath (R.NodeAPI (NodeContact s a i) i) = sessionPath $ "annuaire/" <> show a <> "/contact/" <> show i
------- misc routing stuff
......
......@@ -12,12 +12,13 @@ import Data.Generic.Rep.Eq (genericEq)
import Data.Maybe (Maybe(..))
import Data.Sequence (Seq)
import Data.Sequence as Seq
import Data.Set (Set)
import Data.Traversable (traverse)
import Effect (Effect)
import Effect.Aff (Aff)
import Gargantext.Components.Login.Types (AuthRequest(..), AuthResponse(..), AuthInvalid(..), AuthData(..))
import Gargantext.Components.Login.Types (AuthData(..), AuthInvalid(..), AuthRequest(..), AuthResponse(..), TreeId)
import Gargantext.Config.REST as REST
import Gargantext.Ends (class ToUrl, Backend, backendUrl, toUrl, sessionPath)
import Gargantext.Ends (class ToUrl, Backend(..), backendUrl, sessionPath, toUrl)
import Gargantext.Routes (SessionRoute)
import Gargantext.Types (NodePath, SessionId(..), nodePath)
import Gargantext.Utils.Reactix (getls)
......@@ -33,7 +34,8 @@ newtype Session = Session
{ backend :: Backend
, username :: String
, token :: String
, treeId :: Int }
, treeId :: TreeId
}
------------------------------------------------------------------------
-- | Main instances
......@@ -58,9 +60,6 @@ sessionUrl (Session {backend}) = backendUrl backend
sessionId :: Session -> SessionId
sessionId = SessionId <<< show
instance toUrlSessionString :: ToUrl Session String where
toUrl = sessionUrl
--------------------
-- | JSON instances
instance encodeJsonSession :: EncodeJson Session where
......@@ -140,6 +139,20 @@ tryRemove sid old@(Sessions ss) = ret where
| new == old = Left unit
| otherwise = Right new
-- open tree nodes data
type OpenNodes = Set NodeId
type NodeId =
{ treeId :: TreeId -- Id of the node
, baseUrl :: String -- the baseUrl of the backend
}
mkNodeId :: Session -> TreeId -> NodeId
mkNodeId (Session {backend: Backend {baseUrl}}) treeId = { treeId, baseUrl }
instance toUrlSessionString :: ToUrl Session String where
toUrl = sessionUrl
data Action
= Login Session
| Logout Session
......
......@@ -150,9 +150,9 @@ instance showNodeType :: Show NodeType where
show NodeUser = "NodeUser"
show Folder = "NodeFolder"
show FolderPrivate = "NodeFolderPrivate"
show FolderPublic = "NodeFolderPublic"
show FolderShared = "NodeFolderShared"
show FolderPrivate = "NodeFolderPrivate" -- Node Private Worktop
show FolderShared = "NodeFolderShared" -- Node Share Worktop
show FolderPublic = "NodeFolderPublic" -- Node Public Worktop
show Annuaire = "Annuaire"
show Corpus = "NodeCorpus"
......@@ -197,19 +197,25 @@ readNodeType _ = Error
fldr :: NodeType -> Boolean -> String
fldr NodeUser false = "fa fa-user-circle"
fldr NodeUser true = "fa fa-user-circle-o"
fldr NodeUser true = "fa fa-user"
------------------------------------------------------
fldr Folder false = "fa fa-folder"
fldr Folder true = "fa fa-folder-open-o"
------------------------------------------------------
fldr FolderPrivate true = "fa fa-lock"
fldr FolderPrivate false = "fa fa-expeditedssl"
fldr FolderPrivate false = "fa fa-lock-circle"
fldr FolderShared true = "fa fa-share-alt"
fldr FolderShared false = "fa fa-share-alt-square"
fldr FolderShared false = "fa fa-share-circle"
fldr Team true = "fa fa-users"
fldr Team false = "fa fa-users"
fldr Team false = "fa fa-users-closed"
fldr FolderPublic _ = "fa fa-globe"
fldr FolderPublic true = "fa fa-globe-circle"
fldr FolderPublic false = "fa fa-globe"
------------------------------------------------------
fldr Corpus _ = "fa fa-book" -- "fa fa-snowflake-o"
fldr Corpus true = "fa fa-book"
fldr Corpus false = "fa fa-book-circle"
fldr Phylo _ = "fa fa-code-fork"
......@@ -218,14 +224,14 @@ fldr Texts _ = "fa fa-newspaper-o"
fldr Dashboard _ = "fa fa-signal"
fldr NodeList _ = "fa fa-list"
fldr Annuaire true = "fa fa-address-book-o"
fldr Annuaire false = "fa fa-address-book"
fldr Annuaire true = "fa fa-address-card-o"
fldr Annuaire false = "fa fa-address-card"
fldr NodeContact true = "fa fa-address-card-o"
fldr NodeContact false = "fa fa-address-card"
fldr _ false = "fa fa-folder"
fldr _ true = "fa fa-folder-o"
fldr _ false = "fa fa-folder-o"
fldr _ true = "fa fa-folder-open"
......
......@@ -5,7 +5,7 @@ import Data.Lens (Lens', lens)
import Data.Newtype (class Newtype, unwrap, wrap)
import Data.Set as Set
import Data.Set (Set)
import Data.String (length)
import Data.String as S
-- | Astonishingly, not in the prelude
id :: forall a. a -> a
......@@ -62,7 +62,12 @@ glyphiconActive icon b = glyphicon icon <> if b then " active" else ""
zeroPad :: Int -> Int -> String
zeroPad pad num = zeros <> (show num)
where
numDigits = length $ show num
numDigits = S.length $ show num
zeros = if numDigits < pad then zeros' (pad - numDigits) else ""
zeros' 0 = ""
zeros' n = "0" <> (zeros' (n - 1))
queryMatchesLabel :: String -> String -> Boolean
queryMatchesLabel q l = S.contains (S.Pattern $ normalize q) (normalize l)
where
normalize = S.toLower
......@@ -5,8 +5,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/styles/all.css" rel="stylesheet">-->
<!--<link rel="stylesheet" href="icons/fork-awesome/css/fork-awesome.css">-->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fork-awesome@1.1.7/css/fork-awesome.min.css" integrity="sha256-gsmEoJAws/Kd3CjuOQzLie5Q3yshhvmo7YNtBG7aaEY=" crossorigin="anonymous">
<link rel="stylesheet" href="icons/forkawesome.css">
<!--<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fork-awesome@1.1.7/css/fork-awesome.min.css" integrity="sha256-gsmEoJAws/Kd3CjuOQzLie5Q3yshhvmo7YNtBG7aaEY=" crossorigin="anonymous">-->
<link href="styles/login.min.css" rel="stylesheet">
<link href="styles/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="styles/context-menu.css"/>
......
......@@ -5174,10 +5174,10 @@ prr@~1.0.1:
resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
psc-package@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/psc-package/-/psc-package-3.0.1.tgz#2b1fd7a45480664b0d783ddb4c6dc5066e4ec12f"
integrity sha512-lBA0vXzxeoftzbtpfgZqr2t0rzzecQ9uCXCQOLd74t+5Z72/HP/u7MRNtx8gyBDdLccY90xdjRfSXYwVrdDvgQ==
psc-package@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/psc-package/-/psc-package-4.0.0.tgz#80cecc88fca0fa82f4e0b23c6f085673c475801e"
integrity sha512-A8MEQQOmOT9wkXsd+fY3UXyWWfSA8WYr23MKJmXdqyXXff1RSOIUitLjh9zsWKXF2Tl9fpZsdx7RC3VfQ0JNXA==
dependencies:
follow-redirects "^1.5.9"
shelljs "^0.8.2"
......
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