Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
purescript-gargantext
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Grégoire Locqueville
purescript-gargantext
Commits
64b242fc
Unverified
Commit
64b242fc
authored
Apr 23, 2019
by
Nicolas Pouillard
Browse files
Options
Browse Files
Download
Plain Diff
Finish multi-node selection
Merge remote-tracking branch 'origin/multinode-test' into dev-selector
parents
cf762e19
7a74bebd
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
69 additions
and
31 deletions
+69
-31
FacetsTable.purs
src/Gargantext/Components/FacetsTable.purs
+13
-13
Graph.purs
src/Gargantext/Pages/Corpus/Graph.purs
+43
-13
Tabs.purs
src/Gargantext/Pages/Corpus/Graph/Tabs.purs
+5
-5
Utils.purs
src/Gargantext/Utils.purs
+8
-0
No files found.
src/Gargantext/Components/FacetsTable.purs
View file @
64b242fc
...
...
@@ -9,7 +9,7 @@ import Affjax.ResponseFormat (printResponseFormatError)
import Affjax.ResponseFormat as ResponseFormat
import Control.Monad.Cont.Trans (lift)
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.Foldable (intercalate)
import Data.Generic.Rep (class Generic)
...
...
@@ -30,6 +30,7 @@ import Gargantext.Config (End(..), NodeType(..), OrderBy(..), Path(..), TabType,
import Gargantext.Config.REST (put, post, deleteWithBody)
import Gargantext.Components.Loader as Loader
import Gargantext.Components.Table as T
import Gargantext.Utils (toggleSet)
import Gargantext.Utils.DecodeMaybe ((.|))
import React.DOM (a, br', button, div, i, input, p, text, span)
import React.DOM.Props (_type, className, href, onClick, placeholder, style, checked, target)
...
...
@@ -43,14 +44,19 @@ import Thermite (PerformAction, Render, Spec, defaultPerformAction, modifyState_
type NodeID = 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
{ query ::
Array String
{ query ::
TextQuery
, id :: Int
}
instance encodeJsonSearchQuery :: EncodeJson SearchQuery where
encodeJson (SearchQuery post)
= "query" := post.query
= "query" := post.query
!! 0 -- TODO anoe
~> "corpus_id" := post.id
~> jsonEmptyObject
...
...
@@ -64,7 +70,7 @@ instance decodeSearchResults :: DecodeJson SearchResults where
type Props =
{ nodeId :: Int
, query ::
Array String
, query ::
TextQuery
, totalRecords :: Int
, chart :: ReactElement
, container :: T.TableContainerProps -> Array ReactElement
...
...
@@ -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}
loadPage :: PageParams -> Aff (Array DocumentsView)
...
...
@@ -325,7 +331,7 @@ type PageLoaderProps row =
}
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
, dispatch :: Action -> Effect Unit
, deletionState :: State
...
...
@@ -425,9 +431,3 @@ deleteFavorites nodeId = deleteWithBody (toUrl Back Node (Just nodeId) <> "/favo
deleteDocuments :: Int -> DeleteDocumentQuery -> Aff (Array Int)
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
src/Gargantext/Pages/Corpus/Graph.purs
View file @
64b242fc
...
...
@@ -9,17 +9,19 @@ import Affjax.ResponseFormat as ResponseFormat
import Control.Monad.Cont.Trans (lift)
import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, jsonEmptyObject, (.?), (.??), (:=), (~>))
import Data.Argonaut (decodeJson)
import Data.Array (fold, length, mapWithIndex, (!!))
import Data.Array (fold, length, mapWithIndex, (!!)
, null
)
import Data.Either (Either(..))
import Data.HTTP.Method (Method(..))
import Data.Int (fromString, toNumber)
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.Maybe (Maybe(..), fromJust, fromMaybe, isNothing)
import Data.Newtype (class Newtype)
import Data.Number as Num
import Data.String (joinWith)
import Data.Set (Set)
import Data.Set as Set
import Data.Symbol (SProxy(..))
import Data.Traversable (for_)
import Effect (Effect)
...
...
@@ -38,7 +40,7 @@ import Gargantext.Config.REST (get, post)
import Gargantext.Pages.Corpus.Graph.Tabs as GT
import Gargantext.Prelude (flip)
import Gargantext.Types (class Optional)
import Gargantext.Utils (getter)
import Gargantext.Utils (getter
, toggleSet
)
import Math (cos, sin)
import Partial.Unsafe (unsafePartial)
import React (ReactElement)
...
...
@@ -51,7 +53,6 @@ import Web.HTML (window)
import Web.HTML.Window (localStorage)
import Web.Storage.Storage (getItem)
data Action
= LoadGraph Int
| SelectNode SelectedNode
...
...
@@ -61,12 +62,21 @@ data Action
| ChangeLabelSize Number
| ChangeNodeSize Number
| DisplayEdges
| ToggleMultiNodeSelection
-- | Zoom Boolean
newtype SelectedNode = SelectedNode {id :: String, label :: String}
derive instance eqSelectedNode :: Eq 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 a. Lens' { settings :: a | s } a
...
...
@@ -106,7 +116,8 @@ newtype State = State
, filePath :: String
, sigmaGraphData :: Maybe SigmaGraphData
, legendData :: Array Legend
, selectedNode :: Maybe SelectedNode
, selectedNodes :: Set SelectedNode
, multiNodeSelection :: Boolean
, showSidePanel :: Boolean
, showControls :: Boolean
, showTree :: Boolean
...
...
@@ -123,7 +134,8 @@ initialState = State
, filePath : ""
, sigmaGraphData : Nothing
, legendData : []
, selectedNode : Nothing
, selectedNodes : Set.empty
, multiNodeSelection : false
, showSidePanel : false
, showControls : false
, showTree : false
...
...
@@ -154,8 +166,11 @@ performAction (LoadGraph fp) _ _ = void do
-- graph.
--modifyState \(State s) -> State s {graphData = resp, sigmaGraphData = Just $ convert resp, legendData = getLegendData resp}
performAction (SelectNode (SelectedNode node)) _ (State state) =
modifyState_ $ \(State s) -> State s {selectedNode = pure $ SelectedNode node}
performAction (SelectNode selectedNode@(SelectedNode node)) _ (State state) =
modifyState_ $ \(State s) ->
State s {selectedNodes = toggleSet selectedNode
(if s.multiNodeSelection then s.selectedNodes
else Set.empty) }
performAction (ShowSidePanel b) _ (State state) = void do
modifyState $ \(State s) -> State s {showSidePanel = b }
...
...
@@ -181,6 +196,10 @@ performAction DisplayEdges _ _ =
modifyState_ $ \(State s) -> do
State $ ((_settings <<< _drawEdges) %~ not) s
performAction ToggleMultiNodeSelection _ _ =
modifyState_ $ \(State s) -> do
State $ s # _multiNodeSelection %~ not
--performAction (Zoom True) _ _ =
-- modifyState_ $ \() -> do
-- State $
...
...
@@ -535,6 +554,15 @@ specOld = fold [treespec treeSpec, graphspec $ simpleSpec performAction render']
modCamera0 (const {ratio})
]
]
, li [className "col-me-2"]
[ span [] [text "MultiNode"]
, input
[ _type "checkbox"
, className "checkbox"
-- , checked
, onChange $ const $ d ToggleMultiNodeSelection
]
]
, li'
[ button [ className "btn btn-primary"
, onClick \_ -> pauseForceAtlas2
...
...
@@ -569,7 +597,8 @@ specOld = fold [treespec treeSpec, graphspec $ simpleSpec performAction render']
, onClickNode : \e ->
unsafePerformEffect $ do
_ <- 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
}
[ sigmaEnableWebGL
...
...
@@ -664,10 +693,11 @@ specOld = fold [treespec treeSpec, graphspec $ simpleSpec performAction render']
[ div []
[ p [] []
, div [className "col-md-12"]
[ case st.selectedNode of
Just (SelectedNode {label}) ->
GT.tabsElt {query: words label, sides}
Nothing -> p [] []
[ let query = (\(SelectedNode {label}) -> words label) <$> Set.toUnfoldable st.selectedNodes in
if null query then
p [] []
else
GT.tabsElt {query, sides}
, p [] []
]
]
...
...
src/Gargantext/Pages/Corpus/Graph/Tabs.purs
View file @
64b242fc
...
...
@@ -6,7 +6,7 @@ import Data.List (fromFoldable)
import Data.Tuple (Tuple(..))
import Gargantext.Config (TabType(..), TabSubType(..))
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.Tab as Tab
import React (ReactElement, ReactClass, Children, createElement)
...
...
@@ -14,23 +14,23 @@ import Thermite ( Spec, PerformAction, Render, _performAction, _render
, 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 = createElement tabsClass props []
-- 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 {})
pureTabs :: Spec {} Props Void
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}) =
Tuple corpusLabel $
cmapProps (const {nodeId, query, chart, totalRecords: 4736, container}) $
noState
FT.
docViewSpec
noState docViewSpec
where
-- TODO totalRecords: probably need to insert a corpusLoader.
chart = mempty
...
...
src/Gargantext/Utils.purs
View file @
64b242fc
...
...
@@ -3,6 +3,8 @@ module Gargantext.Utils where
import Prelude
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 fn v t = (setter (flip fn v) t)
...
...
@@ -12,3 +14,9 @@ setter fn = wrap <<< fn <<< unwrap
getter :: forall record field nt. Newtype nt record => (record -> field) -> nt -> field
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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment