Commit 873fed14 authored by Alexandre Delanoë's avatar Alexandre Delanoë

Merge branch 'dev-selector' of...

Merge branch 'dev-selector' of ssh://gitlab.iscpif.fr:20022/gargantext/purescript-gargantext into dev-selector
parents 81c46e79 7bd822ea
...@@ -9,7 +9,7 @@ import Affjax.ResponseFormat (printResponseFormatError) ...@@ -9,7 +9,7 @@ import Affjax.ResponseFormat (printResponseFormatError)
import Affjax.ResponseFormat as ResponseFormat import Affjax.ResponseFormat as ResponseFormat
import Control.Monad.Cont.Trans (lift) import Control.Monad.Cont.Trans (lift)
import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, encodeJson, jsonEmptyObject, (.?), (:=), (~>)) import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, encodeJson, jsonEmptyObject, (.?), (:=), (~>))
import Data.Array (drop, take, (:), filter) import Data.Array (drop, take, (:), filter, (!!))
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.Foldable (intercalate) import Data.Foldable (intercalate)
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
...@@ -30,6 +30,7 @@ import Gargantext.Config (End(..), NodeType(..), OrderBy(..), Path(..), TabType, ...@@ -30,6 +30,7 @@ import Gargantext.Config (End(..), NodeType(..), OrderBy(..), Path(..), TabType,
import Gargantext.Config.REST (put, post, deleteWithBody) import Gargantext.Config.REST (put, post, deleteWithBody)
import Gargantext.Components.Loader as Loader import Gargantext.Components.Loader as Loader
import Gargantext.Components.Table as T import Gargantext.Components.Table as T
import Gargantext.Utils (toggleSet)
import Gargantext.Utils.DecodeMaybe ((.|)) import Gargantext.Utils.DecodeMaybe ((.|))
import React.DOM (a, br', button, div, i, input, p, text, span) import React.DOM (a, br', button, div, i, input, p, text, span)
import React.DOM.Props (_type, className, href, onClick, placeholder, style, checked, target) import React.DOM.Props (_type, className, href, onClick, placeholder, style, checked, target)
...@@ -43,14 +44,19 @@ import Thermite (PerformAction, Render, Spec, defaultPerformAction, modifyState_ ...@@ -43,14 +44,19 @@ import Thermite (PerformAction, Render, Spec, defaultPerformAction, modifyState_
type NodeID = Int type NodeID = Int
type TotalRecords = Int type TotalRecords = Int
-- Example:
-- [["machine","learning"],["artificial","intelligence"]]
-- This searches for documents with "machine learning" or "artificial intelligence"
type TextQuery = Array (Array String)
newtype SearchQuery = SearchQuery newtype SearchQuery = SearchQuery
{ query :: Array String { query :: TextQuery
, id :: Int , id :: Int
} }
instance encodeJsonSearchQuery :: EncodeJson SearchQuery where instance encodeJsonSearchQuery :: EncodeJson SearchQuery where
encodeJson (SearchQuery post) encodeJson (SearchQuery post)
= "query" := post.query = "query" := post.query !! 0 -- TODO anoe
~> "corpus_id" := post.id ~> "corpus_id" := post.id
~> jsonEmptyObject ~> jsonEmptyObject
...@@ -64,7 +70,7 @@ instance decodeSearchResults :: DecodeJson SearchResults where ...@@ -64,7 +70,7 @@ instance decodeSearchResults :: DecodeJson SearchResults where
type Props = type Props =
{ nodeId :: Int { nodeId :: Int
, query :: Array String , query :: TextQuery
, totalRecords :: Int , totalRecords :: Int
, chart :: ReactElement , chart :: ReactElement
, container :: T.TableContainerProps -> Array ReactElement , container :: T.TableContainerProps -> Array ReactElement
...@@ -283,9 +289,9 @@ layoutDocviewGraph = simpleSpec performAction render ...@@ -283,9 +289,9 @@ layoutDocviewGraph = simpleSpec performAction render
type PageParams = {nodeId :: Int, query :: Array String, params :: T.Params} type PageParams = {nodeId :: Int, query :: TextQuery, params :: T.Params}
initialPageParams :: {nodeId :: Int, query :: Array String} -> PageParams initialPageParams :: {nodeId :: Int, query :: TextQuery} -> PageParams
initialPageParams {nodeId, query} = {nodeId, query, params: T.initialParams} initialPageParams {nodeId, query} = {nodeId, query, params: T.initialParams}
loadPage :: PageParams -> Aff (Array DocumentsView) loadPage :: PageParams -> Aff (Array DocumentsView)
...@@ -325,7 +331,7 @@ type PageLoaderProps row = ...@@ -325,7 +331,7 @@ type PageLoaderProps row =
} }
renderPage :: forall props path. renderPage :: forall props path.
Render (Loader.State {nodeId :: Int, query :: Array String | path} (Array DocumentsView)) Render (Loader.State {nodeId :: Int, query :: TextQuery | path} (Array DocumentsView))
{ totalRecords :: Int { totalRecords :: Int
, dispatch :: Action -> Effect Unit , dispatch :: Action -> Effect Unit
, deletionState :: State , deletionState :: State
...@@ -425,9 +431,3 @@ deleteFavorites nodeId = deleteWithBody (toUrl Back Node (Just nodeId) <> "/favo ...@@ -425,9 +431,3 @@ deleteFavorites nodeId = deleteWithBody (toUrl Back Node (Just nodeId) <> "/favo
deleteDocuments :: Int -> DeleteDocumentQuery -> Aff (Array Int) deleteDocuments :: Int -> DeleteDocumentQuery -> Aff (Array Int)
deleteDocuments nodeId = deleteWithBody (toUrl Back Node (Just nodeId) <> "/documents") deleteDocuments nodeId = deleteWithBody (toUrl Back Node (Just nodeId) <> "/documents")
-- TODO: not optimal but Data.Set lacks some function (Set.alter)
toggleSet :: forall a. Ord a => a -> Set a -> Set a
toggleSet a s
| Set.member a s = Set.delete a s
| otherwise = Set.insert a s
...@@ -9,17 +9,19 @@ import Affjax.ResponseFormat as ResponseFormat ...@@ -9,17 +9,19 @@ import Affjax.ResponseFormat as ResponseFormat
import Control.Monad.Cont.Trans (lift) import Control.Monad.Cont.Trans (lift)
import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, jsonEmptyObject, (.?), (.??), (:=), (~>)) import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, jsonEmptyObject, (.?), (.??), (:=), (~>))
import Data.Argonaut (decodeJson) import Data.Argonaut (decodeJson)
import Data.Array (fold, length, mapWithIndex, (!!)) import Data.Array (fold, length, mapWithIndex, (!!), null)
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.HTTP.Method (Method(..)) import Data.HTTP.Method (Method(..))
import Data.Int (fromString, toNumber) import Data.Int (fromString, toNumber)
import Data.Int as Int import Data.Int as Int
import Data.Lens (Lens, Lens', over, (%~), (+~), (.~), (^.)) import Data.Lens (Lens, Lens', over, (%~), (+~), (.~), (^.), review)
import Data.Lens.Record (prop) import Data.Lens.Record (prop)
import Data.Maybe (Maybe(..), fromJust, fromMaybe, isNothing) import Data.Maybe (Maybe(..), fromJust, fromMaybe, isNothing)
import Data.Newtype (class Newtype) import Data.Newtype (class Newtype)
import Data.Number as Num import Data.Number as Num
import Data.String (joinWith) import Data.String (joinWith)
import Data.Set (Set)
import Data.Set as Set
import Data.Symbol (SProxy(..)) import Data.Symbol (SProxy(..))
import Data.Traversable (for_) import Data.Traversable (for_)
import Effect (Effect) import Effect (Effect)
...@@ -38,7 +40,7 @@ import Gargantext.Config.REST (get, post) ...@@ -38,7 +40,7 @@ import Gargantext.Config.REST (get, post)
import Gargantext.Pages.Corpus.Graph.Tabs as GT import Gargantext.Pages.Corpus.Graph.Tabs as GT
import Gargantext.Prelude (flip) import Gargantext.Prelude (flip)
import Gargantext.Types (class Optional) import Gargantext.Types (class Optional)
import Gargantext.Utils (getter) import Gargantext.Utils (getter, toggleSet)
import Math (cos, sin) import Math (cos, sin)
import Partial.Unsafe (unsafePartial) import Partial.Unsafe (unsafePartial)
import React (ReactElement) import React (ReactElement)
...@@ -51,7 +53,6 @@ import Web.HTML (window) ...@@ -51,7 +53,6 @@ import Web.HTML (window)
import Web.HTML.Window (localStorage) import Web.HTML.Window (localStorage)
import Web.Storage.Storage (getItem) import Web.Storage.Storage (getItem)
data Action data Action
= LoadGraph Int = LoadGraph Int
| SelectNode SelectedNode | SelectNode SelectedNode
...@@ -61,12 +62,21 @@ data Action ...@@ -61,12 +62,21 @@ data Action
| ChangeLabelSize Number | ChangeLabelSize Number
| ChangeNodeSize Number | ChangeNodeSize Number
| DisplayEdges | DisplayEdges
| ToggleMultiNodeSelection
-- | Zoom Boolean -- | Zoom Boolean
newtype SelectedNode = SelectedNode {id :: String, label :: String} newtype SelectedNode = SelectedNode {id :: String, label :: String}
derive instance eqSelectedNode :: Eq SelectedNode derive instance eqSelectedNode :: Eq SelectedNode
derive instance newtypeSelectedNode :: Newtype SelectedNode _ derive instance newtypeSelectedNode :: Newtype SelectedNode _
derive instance ordSelectedNode :: Ord SelectedNode
instance showSelectedNode :: Show SelectedNode where
show (SelectedNode node) = node.label
_multiNodeSelection :: forall s a. Lens' { multiNodeSelection :: a | s } a
_multiNodeSelection = prop (SProxy :: SProxy "multiNodeSelection")
-- _settings :: forall s t a b. Lens { settings :: a | s } { settings :: b | t } a b -- _settings :: forall s t a b. Lens { settings :: a | s } { settings :: b | t } a b
_settings :: forall s a. Lens' { settings :: a | s } a _settings :: forall s a. Lens' { settings :: a | s } a
...@@ -106,7 +116,8 @@ newtype State = State ...@@ -106,7 +116,8 @@ newtype State = State
, filePath :: String , filePath :: String
, sigmaGraphData :: Maybe SigmaGraphData , sigmaGraphData :: Maybe SigmaGraphData
, legendData :: Array Legend , legendData :: Array Legend
, selectedNode :: Maybe SelectedNode , selectedNodes :: Set SelectedNode
, multiNodeSelection :: Boolean
, showSidePanel :: Boolean , showSidePanel :: Boolean
, showControls :: Boolean , showControls :: Boolean
, showTree :: Boolean , showTree :: Boolean
...@@ -123,7 +134,8 @@ initialState = State ...@@ -123,7 +134,8 @@ initialState = State
, filePath : "" , filePath : ""
, sigmaGraphData : Nothing , sigmaGraphData : Nothing
, legendData : [] , legendData : []
, selectedNode : Nothing , selectedNodes : Set.empty
, multiNodeSelection : false
, showSidePanel : false , showSidePanel : false
, showControls : false , showControls : false
, showTree : false , showTree : false
...@@ -154,8 +166,11 @@ performAction (LoadGraph fp) _ _ = void do ...@@ -154,8 +166,11 @@ performAction (LoadGraph fp) _ _ = void do
-- graph. -- graph.
--modifyState \(State s) -> State s {graphData = resp, sigmaGraphData = Just $ convert resp, legendData = getLegendData resp} --modifyState \(State s) -> State s {graphData = resp, sigmaGraphData = Just $ convert resp, legendData = getLegendData resp}
performAction (SelectNode (SelectedNode node)) _ (State state) = performAction (SelectNode selectedNode@(SelectedNode node)) _ (State state) =
modifyState_ $ \(State s) -> State s {selectedNode = pure $ SelectedNode node} modifyState_ $ \(State s) ->
State s {selectedNodes = toggleSet selectedNode
(if s.multiNodeSelection then s.selectedNodes
else Set.empty) }
performAction (ShowSidePanel b) _ (State state) = void do performAction (ShowSidePanel b) _ (State state) = void do
modifyState $ \(State s) -> State s {showSidePanel = b } modifyState $ \(State s) -> State s {showSidePanel = b }
...@@ -181,6 +196,10 @@ performAction DisplayEdges _ _ = ...@@ -181,6 +196,10 @@ performAction DisplayEdges _ _ =
modifyState_ $ \(State s) -> do modifyState_ $ \(State s) -> do
State $ ((_settings <<< _drawEdges) %~ not) s State $ ((_settings <<< _drawEdges) %~ not) s
performAction ToggleMultiNodeSelection _ _ =
modifyState_ $ \(State s) -> do
State $ s # _multiNodeSelection %~ not
--performAction (Zoom True) _ _ = --performAction (Zoom True) _ _ =
-- modifyState_ $ \() -> do -- modifyState_ $ \() -> do
-- State $ -- State $
...@@ -535,6 +554,15 @@ specOld = fold [treespec treeSpec, graphspec $ simpleSpec performAction render'] ...@@ -535,6 +554,15 @@ specOld = fold [treespec treeSpec, graphspec $ simpleSpec performAction render']
modCamera0 (const {ratio}) modCamera0 (const {ratio})
] ]
] ]
, li [className "col-me-2"]
[ span [] [text "MultiNode"]
, input
[ _type "checkbox"
, className "checkbox"
-- , checked
, onChange $ const $ d ToggleMultiNodeSelection
]
]
, li' , li'
[ button [ className "btn btn-primary" [ button [ className "btn btn-primary"
, onClick \_ -> pauseForceAtlas2 , onClick \_ -> pauseForceAtlas2
...@@ -569,7 +597,8 @@ specOld = fold [treespec treeSpec, graphspec $ simpleSpec performAction render'] ...@@ -569,7 +597,8 @@ specOld = fold [treespec treeSpec, graphspec $ simpleSpec performAction render']
, onClickNode : \e -> , onClickNode : \e ->
unsafePerformEffect $ do unsafePerformEffect $ do
_ <- d $ ShowSidePanel true _ <- d $ ShowSidePanel true
_ <- d $ SelectNode $ SelectedNode {id : (unsafeCoerce e).data.node.id, label : (unsafeCoerce e).data.node.label} let {id, label} = (unsafeCoerce e).data.node
_ <- d $ SelectNode $ SelectedNode {id, label}
pure unit pure unit
} }
[ sigmaEnableWebGL [ sigmaEnableWebGL
...@@ -664,10 +693,11 @@ specOld = fold [treespec treeSpec, graphspec $ simpleSpec performAction render'] ...@@ -664,10 +693,11 @@ specOld = fold [treespec treeSpec, graphspec $ simpleSpec performAction render']
[ div [] [ div []
[ p [] [] [ p [] []
, div [className "col-md-12"] , div [className "col-md-12"]
[ case st.selectedNode of [ let query = (\(SelectedNode {label}) -> words label) <$> Set.toUnfoldable st.selectedNodes in
Just (SelectedNode {label}) -> if null query then
GT.tabsElt {query: words label, sides} p [] []
Nothing -> p [] [] else
GT.tabsElt {query, sides}
, p [] [] , p [] []
] ]
] ]
......
...@@ -6,7 +6,7 @@ import Data.List (fromFoldable) ...@@ -6,7 +6,7 @@ import Data.List (fromFoldable)
import Data.Tuple (Tuple(..)) import Data.Tuple (Tuple(..))
import Gargantext.Config (TabType(..), TabSubType(..)) import Gargantext.Config (TabType(..), TabSubType(..))
import Gargantext.Components.GraphExplorer.Types (GraphSideCorpus(..)) import Gargantext.Components.GraphExplorer.Types (GraphSideCorpus(..))
import Gargantext.Components.FacetsTable as FT import Gargantext.Components.FacetsTable (TextQuery, docViewSpec)
import Gargantext.Components.Table as T import Gargantext.Components.Table as T
import Gargantext.Components.Tab as Tab import Gargantext.Components.Tab as Tab
import React (ReactElement, ReactClass, Children, createElement) import React (ReactElement, ReactClass, Children, createElement)
...@@ -14,23 +14,23 @@ import Thermite ( Spec, PerformAction, Render, _performAction, _render ...@@ -14,23 +14,23 @@ import Thermite ( Spec, PerformAction, Render, _performAction, _render
, hideState, noState, cmapProps, simpleSpec, createClass , hideState, noState, cmapProps, simpleSpec, createClass
) )
type Props = { query :: Array String, sides :: Array GraphSideCorpus } type Props = { query :: TextQuery, sides :: Array GraphSideCorpus }
tabsElt :: Props -> ReactElement tabsElt :: Props -> ReactElement
tabsElt props = createElement tabsClass props [] tabsElt props = createElement tabsClass props []
-- TODO no need for Children here -- TODO no need for Children here
tabsClass :: ReactClass { query :: Array String, sides :: Array GraphSideCorpus, children :: Children } tabsClass :: ReactClass { query :: TextQuery, sides :: Array GraphSideCorpus, children :: Children }
tabsClass = createClass "GraphTabs" pureTabs (const {}) tabsClass = createClass "GraphTabs" pureTabs (const {})
pureTabs :: Spec {} Props Void pureTabs :: Spec {} Props Void
pureTabs = hideState (const {activeTab: 0}) statefulTabs pureTabs = hideState (const {activeTab: 0}) statefulTabs
tab :: forall props state. Array String -> GraphSideCorpus -> Tuple String (Spec state props Tab.Action) tab :: forall props state. TextQuery -> GraphSideCorpus -> Tuple String (Spec state props Tab.Action)
tab query (GraphSideCorpus {corpusId: nodeId, corpusLabel}) = tab query (GraphSideCorpus {corpusId: nodeId, corpusLabel}) =
Tuple corpusLabel $ Tuple corpusLabel $
cmapProps (const {nodeId, query, chart, totalRecords: 4736, container}) $ cmapProps (const {nodeId, query, chart, totalRecords: 4736, container}) $
noState FT.docViewSpec noState docViewSpec
where where
-- TODO totalRecords: probably need to insert a corpusLoader. -- TODO totalRecords: probably need to insert a corpusLoader.
chart = mempty chart = mempty
......
...@@ -3,6 +3,8 @@ module Gargantext.Utils where ...@@ -3,6 +3,8 @@ module Gargantext.Utils where
import Prelude import Prelude
import Data.Newtype (class Newtype, unwrap, wrap) import Data.Newtype (class Newtype, unwrap, wrap)
import Data.Set as Set
import Data.Set (Set)
setterv :: forall nt record field. Newtype nt record => (record -> field -> record) -> field -> nt -> nt setterv :: forall nt record field. Newtype nt record => (record -> field -> record) -> field -> nt -> nt
setterv fn v t = (setter (flip fn v) t) setterv fn v t = (setter (flip fn v) t)
...@@ -12,3 +14,9 @@ setter fn = wrap <<< fn <<< unwrap ...@@ -12,3 +14,9 @@ setter fn = wrap <<< fn <<< unwrap
getter :: forall record field nt. Newtype nt record => (record -> field) -> nt -> field getter :: forall record field nt. Newtype nt record => (record -> field) -> nt -> field
getter fn = fn <<< unwrap getter fn = fn <<< unwrap
-- TODO: not optimal but Data.Set lacks some function (Set.alter)
toggleSet :: forall a. Ord a => a -> Set a -> Set a
toggleSet a s
| Set.member a s = Set.delete a s
| otherwise = Set.insert a s
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