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
6cf771f9
Commit
6cf771f9
authored
Sep 20, 2019
by
James Laver
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor table components to use reactix
parent
6213f074
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
584 additions
and
743 deletions
+584
-743
DocsTable.purs
src/Gargantext/Components/DocsTable.purs
+53
-68
FacetsTable.purs
src/Gargantext/Components/FacetsTable.purs
+182
-269
NgramsTable.purs
src/Gargantext/Components/NgramsTable.purs
+163
-176
Core.purs
src/Gargantext/Components/NgramsTable/Core.purs
+34
-31
Types.purs
src/Gargantext/Components/Search/Types.purs
+4
-4
Table.purs
src/Gargantext/Components/Table.purs
+148
-195
No files found.
src/Gargantext/Components/DocsTable.purs
View file @
6cf771f9
...
@@ -18,12 +18,13 @@ import Data.Tuple.Nested ((/\))
...
@@ -18,12 +18,13 @@ import Data.Tuple.Nested ((/\))
import DOM.Simple.Event as DE
import DOM.Simple.Event as DE
import Effect (Effect)
import Effect (Effect)
import Effect.Aff (Aff, launchAff)
import Effect.Aff (Aff, launchAff)
import Effect.Uncurried (mkEffectFn1)
import Effect.Class (liftEffect)
import Effect.Uncurried (EffectFn1, mkEffectFn1)
import Reactix as R
import Reactix as R
import Reactix.DOM.HTML as H
import Reactix.DOM.HTML as H
------------------------------------------------------------------------
------------------------------------------------------------------------
import Gargantext.Prelude
import Gargantext.Prelude
import Gargantext.Config (End
(..), NodeType(..), OrderBy(..), Path(..), TabType, TabPostQuery(..), toUrl, endConfigStateful, toLink
)
import Gargantext.Config (End
s, NodeType(..), OrderBy(..), BackendRoute(..), TabType, TabPostQuery(..), url
)
import Gargantext.Config.REST (get, put, post, deleteWithBody, delete)
import Gargantext.Config.REST (get, put, post, deleteWithBody, delete)
import Gargantext.Components.Node (NodePoly(..))
import Gargantext.Components.Node (NodePoly(..))
import Gargantext.Components.Search.Types (Category(..), CategoryQuery(..), favCategory, trashCategory, decodeCategory, putCategories)
import Gargantext.Components.Search.Types (Category(..), CategoryQuery(..), favCategory, trashCategory, decodeCategory, putCategories)
...
@@ -38,25 +39,25 @@ type NodeID = Int
...
@@ -38,25 +39,25 @@ type NodeID = Int
type TotalRecords = Int
type TotalRecords = Int
type Props =
type Props =
{
nodeId :: Int
(
nodeId :: Int
, totalRecords :: Int
, totalRecords :: Int
, chart :: R.Element
, chart :: R.Element
, tabType :: TabType
, tabType :: TabType
, listId :: Int
, listId :: Int
, corpusId :: Maybe Int
, corpusId :: Maybe Int
, showSearch :: Boolean
, showSearch :: Boolean
, ends :: Ends )
-- ^ tabType is not ideal here since it is too much entangled with tabs and
-- ^ tabType is not ideal here since it is too much entangled with tabs and
-- ngramtable. Let's see how this evolves.
-- ngramtable. Let's see how this evolves. )
}
type PageLoaderProps =
type PageLoaderProps =
{
nodeId :: Int
(
nodeId :: Int
, totalRecords :: Int
, totalRecords :: Int
, tabType :: TabType
, tabType :: TabType
, listId :: Int
, listId :: Int
, corpusId :: Maybe Int
, corpusId :: Maybe Int
, query :: Query
, query :: Query
}
)
type LocalCategories = Map Int Category
type LocalCategories = Map Int Category
type Query = String
type Query = String
...
@@ -119,18 +120,19 @@ instance decodeResponse :: DecodeJson Response where
...
@@ -119,18 +120,19 @@ instance decodeResponse :: DecodeJson Response where
pure $ Response { cid, category: decodeCategory favorite, ngramCount, hyperdata }
pure $ Response { cid, category: decodeCategory favorite, ngramCount, hyperdata }
docViewSpec :: Props -> R.Element
docView :: Record Props -> R.Element
docViewSpec p = R.createElement el p []
docView p = R.createElement docViewCpt p []
docViewCpt :: R.Component Props
docViewCpt = R.hooksComponent "DocView" cpt
where
where
el = R.hooksComponent "DocView" cpt
cpt p _children = do
cpt p _children = do
query <- R.useState' ("" :: Query)
query <- R.useState' ("" :: Query)
tableParams <- R.useState' T.initialParams
tableParams <- R.useState' T.initialParams
pure $ layoutDocview query tableParams p
pure $ layoutDocview query tableParams p
-- | Main layout of the Documents Tab of a Corpus
-- | Main layout of the Documents Tab of a Corpus
layoutDocview :: R.State Query -> R.State T.Params -> Props -> R.Element
layoutDocview :: R.State Query -> R.State T.Params ->
Record
Props -> R.Element
layoutDocview query tableParams@(params /\ _) p = R.createElement el p []
layoutDocview query tableParams@(params /\ _) p = R.createElement el p []
where
where
el = R.hooksComponent "LayoutDocView" cpt
el = R.hooksComponent "LayoutDocView" cpt
...
@@ -140,9 +142,13 @@ layoutDocview query tableParams@(params /\ _) p = R.createElement el p []
...
@@ -140,9 +142,13 @@ layoutDocview query tableParams@(params /\ _) p = R.createElement el p []
[ chart
[ chart
, if showSearch then searchBar query else H.div {} []
, if showSearch then searchBar query else H.div {} []
, H.div {className: "col-md-12"}
, H.div {className: "col-md-12"}
[ pageLoader tableParams {nodeId, totalRecords, tabType, listId, corpusId, query: fst query} ]
[ pageLoader tableParams {nodeId, totalRecords, tabType, listId, corpusId, query: fst query} ] ] ]
onClickTrashAll nodeId = mkEffectFn1 $ \_ -> do
launchAff $ deleteAllDocuments p.ends nodeId
{-, H.div {className: "col-md-1 col-md-offset-11"}
{-, H.div {className: "col-md-1 col-md-offset-11"}
[ pageLoader p.ends tableParams {nodeId, totalRecords, tabType, listId, corpusId, query: fst query} ]
, H.div {className: "col-md-1 col-md-offset-11"}
[ H.button { className: "btn"
[ H.button { className: "btn"
, style: {backgroundColor: "peru", color : "white", border : "white"}
, style: {backgroundColor: "peru", color : "white", border : "white"}
, onClick: onClickTrashAll nodeId
, onClick: onClickTrashAll nodeId
...
@@ -152,11 +158,6 @@ layoutDocview query tableParams@(params /\ _) p = R.createElement el p []
...
@@ -152,11 +158,6 @@ layoutDocview query tableParams@(params /\ _) p = R.createElement el p []
]
]
]
]
-}
-}
]
]
onClickTrashAll nodeId = mkEffectFn1 $ \_ -> do
launchAff $ deleteAllDocuments nodeId
searchBar :: R.State Query -> R.Element
searchBar :: R.State Query -> R.Element
searchBar (query /\ setQuery) = R.createElement el {} []
searchBar (query /\ setQuery) = R.createElement el {} []
...
@@ -210,12 +211,12 @@ type PageParams = { nodeId :: Int
...
@@ -210,12 +211,12 @@ type PageParams = { nodeId :: Int
, query :: Query
, query :: Query
, params :: T.Params}
, params :: T.Params}
loadPage :: PageParams -> Aff (Array DocumentsView)
loadPage ::
Ends ->
PageParams -> Aff (Array DocumentsView)
loadPage {nodeId, tabType, query, listId, corpusId, params: {limit, offset, orderBy}} = do
loadPage
ends
{nodeId, tabType, query, listId, corpusId, params: {limit, offset, orderBy}} = do
logs "loading documents page: loadPage with Offset and limit"
logs "loading documents page: loadPage with Offset and limit"
-- res <- get $ toUrl endConfigStateful Back (Tab tabType offset limit (convOrderBy <$> orderBy)) (Just nodeId)
-- res <- get $ toUrl endConfigStateful Back (Tab tabType offset limit (convOrderBy <$> orderBy)) (Just nodeId)
let url
= (toUrl endConfigStateful Back Node (Just nodeId
)) <> "/table"
let url
2 = (url ends (NodeAPI Node (Just nodeId)
)) <> "/table"
res <- post url $ TabPostQuery {
res <- post url
2
$ TabPostQuery {
offset
offset
, limit
, limit
, orderBy: convOrderBy orderBy
, orderBy: convOrderBy orderBy
...
@@ -246,8 +247,8 @@ loadPage {nodeId, tabType, query, listId, corpusId, params: {limit, offset, orde
...
@@ -246,8 +247,8 @@ loadPage {nodeId, tabType, query, listId, corpusId, params: {limit, offset, orde
convOrderBy _ = DateAsc -- TODO
convOrderBy _ = DateAsc -- TODO
renderPage ::
R.State T.Params ->
PageLoaderProps -> Array DocumentsView -> R.Element
renderPage ::
Ends -> R.State T.Params -> Record
PageLoaderProps -> Array DocumentsView -> R.Element
renderPage
(tableParams
/\ setTableParams) p res = R.createElement el p []
renderPage
ends (_
/\ setTableParams) p res = R.createElement el p []
where
where
el = R.hooksComponent "RenderPage" cpt
el = R.hooksComponent "RenderPage" cpt
...
@@ -260,61 +261,46 @@ renderPage (tableParams /\ setTableParams) p res = R.createElement el p []
...
@@ -260,61 +261,46 @@ renderPage (tableParams /\ setTableParams) p res = R.createElement el p []
cpt {nodeId, corpusId, listId, totalRecords} _children = do
cpt {nodeId, corpusId, listId, totalRecords} _children = do
localCategories <- R.useState' (mempty :: LocalCategories)
localCategories <- R.useState' (mempty :: LocalCategories)
pure $ T.table
pure $ R2.buff $ T.tableEltWithInitialState
(T.paramsState tableParams)
{ rows: rows localCategories
{ rows: rows localCategories
-- , setParams: \params -> liftEffect $ loaderDispatch (Loader.SetPath {nodeId, tabType, listId, corpusId, params, query})
-- , setParams: \params -> liftEffect $ loaderDispatch (Loader.SetPath {nodeId, tabType, listId, corpusId, params, query})
, setParams: setTableParams <<< const
, setParams: setTableParams <<< const
, container: T.defaultContainer { title: "Documents" }
, container: T.defaultContainer { title: "Documents" }
, colNames:
, colNames
T.ColumnName <$>
[ "Favorites"
, "Trash"
, "Date"
, "Title"
, "Source"
]
, totalRecords
, totalRecords
}
}
where
where
colNames = T.ColumnName <$> [ "Map", "Stop", "Date", "Title", "Source"]
getCategory (localCategories /\ _) {_id, category} = maybe category identity (localCategories ^. at _id)
getCategory (localCategories /\ _) {_id, category} = maybe category identity (localCategories ^. at _id)
rows localCategories = (\(DocumentsView r) ->
rows localCategories = row <$> res
let cat = getCategory localCategories r
where
isDel = Trash == cat in
row (DocumentsView r) =
{ row: map R2.scuff $ [
{ row:
H.div {}
[ H.div {} [ H.a { className, style, on: {click: click Favorite} } [] ]
[ H.a { className: gi cat
, H.input { type: "checkbox", checked, on: {click: click Trash} }
, style: trashStyle cat
, on: {click: onClick localCategories Favorite r._id cat}
} []
]
, H.input { type: "checkbox"
, defaultChecked: isDel
, on: {click: onClick localCategories Trash r._id cat}
}
-- TODO show date: Year-Month-Day only
-- TODO show date: Year-Month-Day only
, H.div { style: trashStyle cat } [ H.text (show r.date) ]
, H.div { style } [ R2.showText r.date ]
, H.a { href: toLink $ (corpusDocument corpusId) listId r._id
, H.div { style } [ H.text r.source ]
, style: trashStyle cat
, target: "_blank"
} [ H.text r.title ]
, H.div { style: trashStyle cat} [ H.text r.source ]
]
]
, delete: true
, delete: true }
}) <$> res
where
cat = getCategory localCategories r
click cat2 = onClick localCategories cat2 r._id cat
checked = Trash == cat
style = trashStyle cat
className = gi cat
onClick (_ /\ setLocalCategories) catType nid cat = \_-> do
onClick (_ /\ setLocalCategories) catType nid cat = \_-> do
let newCat = if (catType == Favorite) then (favCategory cat) else (trashCategory cat)
let newCat = if (catType == Favorite) then (favCategory cat) else (trashCategory cat)
setLocalCategories $ insert nid newCat
setLocalCategories $ insert nid newCat
void $ launchAff $ putCategories nodeId $ CategoryQuery {nodeIds: [nid], category: newCat}
void $ launchAff $ putCategories
ends
nodeId $ CategoryQuery {nodeIds: [nid], category: newCat}
pageLoader ::
R.State T.Params ->
PageLoaderProps -> R.Element
pageLoader ::
Ends -> R.State T.Params -> Record
PageLoaderProps -> R.Element
pageLoader tableParams@(pageParams /\ _) p = R.createElement el p []
pageLoader
ends
tableParams@(pageParams /\ _) p = R.createElement el p []
where
where
el = R.hooksComponent "PageLoader" cpt
el = R.hooksComponent "PageLoader" cpt
cpt p@{nodeId, listId, corpusId, tabType, query} _children = do
cpt p@{nodeId, listId, corpusId, tabType, query} _children = do
useLoader {nodeId, listId, corpusId, tabType, query, params: pageParams}
loadPage $ \{loaded} ->
useLoader {nodeId, listId, corpusId, tabType, query, params: pageParams}
(loadPage ends) $
renderPage
tableParams p loaded
\loaded -> renderPage ends
tableParams p loaded
---------------------------------------------------------
---------------------------------------------------------
sampleData' :: DocumentsView
sampleData' :: DocumentsView
...
@@ -358,7 +344,6 @@ searchResults :: SearchQuery -> Aff Int
...
@@ -358,7 +344,6 @@ searchResults :: SearchQuery -> Aff Int
searchResults squery = post "http://localhost:8008/count" unit
searchResults squery = post "http://localhost:8008/count" unit
-- TODO
-- TODO
newtype CategoryQuery = CategoryQuery {
newtype CategoryQuery = CategoryQuery {
nodeIds :: Array Int
nodeIds :: Array Int
, category :: Category
, category :: Category
...
@@ -376,11 +361,11 @@ categoryUrl nodeId = toUrl endConfigStateful Back Node (Just nodeId) <> "/catego
...
@@ -376,11 +361,11 @@ categoryUrl nodeId = toUrl endConfigStateful Back Node (Just nodeId) <> "/catego
putCategories :: Int -> CategoryQuery -> Aff (Array Int)
putCategories :: Int -> CategoryQuery -> Aff (Array Int)
putCategories nodeId = put $ categoryUrl nodeId
putCategories nodeId = put $ categoryUrl nodeId
documentsUrl :: Int -> String
documentsUrl ::
Ends ->
Int -> String
documentsUrl
nodeId = toUrl endConfigStateful Back Node (Just nodeId
) <> "/documents"
documentsUrl
ends nodeId = url ends (NodeAPI Node (Just nodeId)
) <> "/documents"
deleteAllDocuments :: Int -> Aff (Array Int)
deleteAllDocuments ::
Ends ->
Int -> Aff (Array Int)
deleteAllDocuments
nodeId = delete $ documentsUrl nodeId
deleteAllDocuments
ends = delete <<< documentsUrl ends
-- TODO: not optimal but Data.Set lacks some function (Set.alter)
-- TODO: not optimal but Data.Set lacks some function (Set.alter)
toggleSet :: forall a. Ord a => a -> Set a -> Set a
toggleSet :: forall a. Ord a => a -> Set a -> Set a
...
...
src/Gargantext/Components/FacetsTable.purs
View file @
6cf771f9
...
@@ -12,24 +12,25 @@ import Data.Generic.Rep.Show (genericShow)
...
@@ -12,24 +12,25 @@ import Data.Generic.Rep.Show (genericShow)
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..))
import Data.Set (Set)
import Data.Set (Set)
import Data.Set as Set
import Data.Set as Set
import Data.Tuple (fst)
import Data.Tuple.Nested ((/\))
import Effect (Effect)
import Effect (Effect)
import Effect.Aff (Aff)
import Effect.Aff (Aff
, launchAff_
)
import Effect.Class (liftEffect)
import Effect.Class (liftEffect)
import React
as React
import React
ix as R
import React
(ReactClass, ReactElement, Children)
import React
ix.DOM.HTML as H
------------------------------------------------------------------------
------------------------------------------------------------------------
import Gargantext.Prelude
import Gargantext.Prelude
import Gargantext.Config (End
(..), NodeType(..), OrderBy(..), Path(..), TabType, toUrl, endConfigStatefu
l)
import Gargantext.Config (End
s, NodeType(..), OrderBy(..), NodePath(..), BackendRoute(..), TabType, ur
l)
import Gargantext.Config.REST (put, post, deleteWithBody)
import Gargantext.Config.REST (put, post, deleteWithBody)
import Gargantext.Components.Loader as Loader
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Components.Search.Types (Category(..), CategoryQuery(..), favCategory, decodeCategory, putCategories)
import Gargantext.Components.Search.Types (Category(..), CategoryQuery(..), favCategory, trashCategory, decodeCategory, putCategories)
import Gargantext.Components.Table as T
import Gargantext.Components.Table as T
import Gargantext.Router as Router
import Gargantext.Router as Router
import Gargantext.Utils (toggleSet)
import Gargantext.Utils (toggleSet)
import Gargantext.Utils.DecodeMaybe ((.|))
import Gargantext.Utils.DecodeMaybe ((.|))
import React.DOM (a, br', button, div, i, input, p, text, span)
import Gargantext.Utils.Reactix as R2
import React.DOM.Props (_type, className, href, onClick, style, checked, target)
import Thermite (PerformAction, Render, Spec, defaultPerformAction, modifyState_, simpleSpec, hideState)
------------------------------------------------------------------------
------------------------------------------------------------------------
type NodeID = Int
type NodeID = Int
...
@@ -40,9 +41,7 @@ type TotalRecords = Int
...
@@ -40,9 +41,7 @@ type TotalRecords = Int
-- This searches for documents with "machine learning" or "artificial intelligence"
-- This searches for documents with "machine learning" or "artificial intelligence"
type TextQuery = Array (Array String)
type TextQuery = Array (Array String)
newtype SearchQuery = SearchQuery
newtype SearchQuery = SearchQuery { query :: TextQuery }
{ query :: TextQuery
}
instance encodeJsonSearchQuery :: EncodeJson SearchQuery where
instance encodeJsonSearchQuery :: EncodeJson SearchQuery where
encodeJson (SearchQuery post)
encodeJson (SearchQuery post)
...
@@ -58,42 +57,30 @@ instance decodeSearchResults :: DecodeJson SearchResults where
...
@@ -58,42 +57,30 @@ instance decodeSearchResults :: DecodeJson SearchResults where
pure $ SearchResults {results}
pure $ SearchResults {results}
type Props =
type Props =
{
nodeId :: Int
(
nodeId :: Int
, listId :: Int
, listId :: Int
, query :: TextQuery
, query :: TextQuery
, totalRecords :: Int
, totalRecords :: Int
, chart :: ReactElement
, chart :: R.Element
, container :: T.TableContainerProps -> Array ReactElement
, container :: Record T.TableContainerProps -> R.Element
}
, ends :: Ends
)
type State =
-- | Tracks the ids of documents to delete and that have been deleted
{ documentIdsToDelete :: Set Int
type Deletions = { pending :: Set Int, deleted :: Set Int }
, documentIdsDeleted :: Set Int
}
initialState :: State
initialDeletions :: Deletions
initialState =
initialDeletions = { pending: mempty, deleted: mempty }
{ documentIdsToDelete: mempty
, documentIdsDeleted: mempty
}
data Action
newtype Pair = Pair { id :: Int, label :: String }
= MarkCategory Category (Array Int)
| ToggleDocumentToDelete Int
| TrashDocuments
newtype Pair = Pair
{ id :: Int
, label :: String
}
derive instance genericPair :: Generic Pair _
derive instance genericPair :: Generic Pair _
instance showPair :: Show Pair where
instance showPair :: Show Pair where
show = genericShow
show = genericShow
newtype DocumentsView
newtype DocumentsView
=
=
DocumentsView
DocumentsView
{ id :: Int
{ id :: Int
, date :: String
, date :: String
, title :: String
, title :: String
...
@@ -120,7 +107,6 @@ newtype Response = Response
...
@@ -120,7 +107,6 @@ newtype Response = Response
-- , pairs :: Array Pair
-- , pairs :: Array Pair
}
}
newtype Hyperdata = Hyperdata
newtype Hyperdata = Hyperdata
{ title :: String
{ title :: String
, source :: String
, source :: String
...
@@ -133,7 +119,6 @@ newtype Hyperdata = Hyperdata
...
@@ -133,7 +119,6 @@ newtype Hyperdata = Hyperdata
-- source <- obj .: "source"
-- source <- obj .: "source"
-- pure $ Hyperdata { title,source }
-- pure $ Hyperdata { title,source }
instance decodePair :: DecodeJson Pair where
instance decodePair :: DecodeJson Pair where
decodeJson json = do
decodeJson json = do
obj <- decodeJson json
obj <- decodeJson json
...
@@ -172,252 +157,180 @@ instance decodeResponse :: DecodeJson Response where
...
@@ -172,252 +157,180 @@ instance decodeResponse :: DecodeJson Response where
let ngramCount = 1
let ngramCount = 1
pure $ Response { id, created, hyperdata, category: decodeCategory favorite, ngramCount}
pure $ Response { id, created, hyperdata, category: decodeCategory favorite, ngramCount}
-- | Filter
-- TODO: unused
filterSpec :: forall state props action. Spec state props action
filterSpec = simpleSpec defaultPerformAction render
where
render d p s c = [] {-[div [ className "col-md-2", style {textAlign : "center", marginLeft : "0px", paddingLeft : "0px"}] [ text " Filter "
, input [className "form-control", placeholder "Filter here"]
]]
-}
docViewSpec :: Spec {} Props Void
docViewSpec = hideState (const initialState) layoutDocviewGraph
-- | Main layout of the Documents Tab of a Corpus
-- | Main layout of the Documents Tab of a Corpus
layoutDocview :: Spec State Props Action
docView :: Record Props -> R.Element
layoutDocview = simpleSpec performAction render
docView props = R.createElement docViewCpt props []
where
performAction :: PerformAction State Props Action
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 TrashDocuments {nodeId} {documentIdsToDelete} = do
void $ lift $ deleteDocuments nodeId (DeleteDocumentQuery {documents: Set.toUnfoldable documentIdsToDelete})
modifyState_ \{documentIdsToDelete, documentIdsDeleted} ->
{ documentIdsToDelete: mempty
, documentIdsDeleted: documentIdsDeleted <> documentIdsToDelete
}
render :: Render State Props Action
docViewCpt :: R.Component Props
render dispatch {nodeId, listId, query, totalRecords, chart, container} deletionState _ =
docViewCpt = R.hooksComponent "G.C.FacetsTable.DocView" cpt
[ {- br'
where
, div [ style {textAlign : "center"}] [ text " Filter "
cpt {ends, nodeId, listId, query, totalRecords, chart, container} _ = do
, input [className "form-control", style {width : "120px", display : "inline-block"}, placeholder "Filter here"]
deletions <- R.useState' initialDeletions
]
path <- R.useState' $ initialPagePath {nodeId, listId, query, ends}
, p [] [text ""]
pure $ H.div { className: "container1" }
, br'
[ H.div { className: "row" }
-}
div [className "container1"]
[ div [className "row"]
[ chart
[ chart
, div [className "col-md-12"]
, H.div { className: "col-md-12" }
[ pageLoader
[ pageLayout { deletions, totalRecords, container, ends, path } ]
{ path: initialPageParams {nodeId, listId, query}
, H.div { className: "col-md-12" }
, totalRecords
[ H.button { style: buttonStyle, on: { click: trashClick deletions } }
, deletionState
[ H.i { className: "glyphitem glyphicon glyphicon-trash"
, dispatch
, style: { marginRight : "9px" }} []
, container
, H.text "Delete document!" ] ] ] ]
}
]
, div [className "col-md-12"]
[ button [ style {backgroundColor: "peru", padding : "9px", color : "white", border : "white", float: "right"}
, onClick $ (\_ -> dispatch TrashDocuments)
]
[ i [className "glyphitem glyphicon glyphicon-trash", style {marginRight : "9px"}] []
, text "Trash it !"
]
]
]
]
]
layoutDocviewGraph :: Spec State Props Action
layoutDocviewGraph = simpleSpec performAction render
where
where
performAction :: PerformAction State Props Action
buttonStyle =
performAction (MarkCategory category nids) {nodeId} _ =
{ backgroundColor: "peru", padding: "9px", color: "white"
void $ lift $ putCategories nodeId $ CategoryQuery {nodeIds: nids, category: favCategory category}
, border: "white", float: "right" }
--TODO add array of delete rows here
trashClick deletions _ = performDeletions ends nodeId deletions
performAction (ToggleDocumentToDelete nid) _ _ =
modifyState_ \state -> state {documentIdsToDelete = toggleSet nid state.documentIdsToDelete}
performDeletions :: Ends -> Int -> R.State Deletions -> Effect Unit
performAction TrashDocuments {nodeId} {documentIdsToDelete} = do
performDeletions ends nodeId (deletions /\ setDeletions) =
void $ lift $ deleteDocuments nodeId (DeleteDocumentQuery {documents: Set.toUnfoldable documentIdsToDelete})
launchAff_ call *> setDeletions del
modifyState_ \{documentIdsToDelete, documentIdsDeleted} ->
where
{ documentIdsToDelete: mempty
q = {documents: Set.toUnfoldable deletions.pending}
, documentIdsDeleted: documentIdsDeleted <> documentIdsToDelete
call = deleteDocuments ends nodeId (DeleteDocumentQuery q)
}
del {pending, deleted} = {pending: mempty, deleted: deleted <> pending}
render :: Render State Props Action
render dispatch {nodeId, listId, query, totalRecords, chart, container} deletionState _ =
[ br'
, p [] [text ""]
-- markCategory :: Ends -> NodeID -> _ -> Array NodeID -> Effect Unit
, br'
markCategory ends nodeId category nids =
, div [className "container-fluid"]
void $ launchAff_ $putCategories ends nodeId (CategoryQuery q)
[ div [className "row"]
where -- TODO add array of delete rows here
[ chart
q = {nodeIds: nids, category: favCategory category}
, div [className "col-md-12"]
[ pageLoader
{ path: initialPageParams {nodeId, listId, query}
, totalRecords
, deletionState
, dispatch
, container
}
, button [ style {backgroundColor: "peru", padding : "9px", color : "white", border : "white", float: "right"}
, onClick $ (\_ -> dispatch TrashDocuments)
]
[ i [className "glyphitem glyphicon glyphicon-trash", style {marginRight : "9px"}] []
, text "Trash it !"
]
]
]
togglePendingDeletion :: R.State Deletions -> NodeID -> Effect Unit
]
togglePendingDeletion (_ /\ setDeletions) nid = setDeletions setter
]
where setter deletions@{pending} = deletions { pending = toggleSet nid pending }
docViewGraph :: Record Props -> R.Element
docViewGraph props = R.createElement docViewCpt props []
docViewGraphCpt :: R.Component Props
docViewGraphCpt = R.hooksComponent "FacetsDocViewGraph" cpt
where
cpt {ends, nodeId, listId, query, totalRecords, chart, container} _ = do
deletions <- R.useState' initialDeletions
let buttonStyle = { backgroundColor: "peru", padding : "9px"
, color : "white", border : "white", float: "right"}
let performClick = \_ -> performDeletions ends nodeId deletions
path <- R.useState' $ initialPagePath { nodeId, listId, query, ends }
pure $ R.fragment
[ H.br {}
, H.p {} [ H.text "" ]
, H.br {}
, H.div { className: "container-fluid" }
[ H.div { className: "row" }
[ chart
, H.div { className: "col-md-12" }
[ pageLayout { totalRecords, deletions, container, ends, path }
, H.button { style: buttonStyle, on: { click: performClick } }
[ H.i { className: "glyphitem glyphicon glyphicon-trash"
, style: { marginRight : "9px" } } []
, H.text "Delete document!" ] ] ] ] ]
type PagePa
rams = {nodeId :: Int, listId :: Int, query :: TextQuery, params :: T.Param
s}
type PagePa
th = {nodeId :: Int, listId :: Int, query :: TextQuery, params :: T.Params, ends :: End
s}
initialPagePa
rams :: {nodeId :: Int, listId :: Int, query :: TextQuery} -> PageParams
initialPagePa
th :: {ends :: Ends, nodeId :: Int, listId :: Int, query :: TextQuery} -> PagePath
initialPagePa
rams {nodeId, listId, query} = {
nodeId, listId, query, params: T.initialParams}
initialPagePa
th {ends, nodeId, listId, query} = {ends,
nodeId, listId, query, params: T.initialParams}
loadPage :: PagePa
rams
-> Aff (Array DocumentsView)
loadPage :: PagePa
th
-> Aff (Array DocumentsView)
loadPage {nodeId, listId, query, params: {limit, offset, orderBy}} = do
loadPage {
ends,
nodeId, listId, query, params: {limit, offset, orderBy}} = do
logs "loading documents page: loadPage with Offset and limit"
logs "loading documents page: loadPage with Offset and limit"
let url
= toUrl endConfigStateful Back (Search { listId, offset, limit, orderBy: convOrderBy <$> orderBy })
(Just nodeId)
let url
2 = url ends $ Search { listId, offset, limit, orderBy: convOrderBy <$> orderBy }
(Just nodeId)
SearchResults res <- post url $ SearchQuery {query}
SearchResults res <- post url
2
$ SearchQuery {query}
pure $ res2corpus <$> res.results
pure $ res2corpus <$> res.results
where
where
res2corpus :: Response -> DocumentsView
res2corpus :: Response -> DocumentsView
res2corpus (Response { id, created: date, ngramCount: score
res2corpus (Response { id, created: date, ngramCount: score, category
, hyperdata: Hyperdata {title, source}
, hyperdata: Hyperdata {title, source} }) =
, category
DocumentsView { id, date, title, source, score, category, pairs: [], delete: false }
}) =
DocumentsView
{ id
, date
, title
, source
, score
, pairs: []
, delete: false
, category
}
convOrderBy (T.ASC (T.ColumnName "Date")) = DateAsc
convOrderBy (T.ASC (T.ColumnName "Date")) = DateAsc
convOrderBy (T.DESC (T.ColumnName "Date")) = DateDesc
convOrderBy (T.DESC (T.ColumnName "Date")) = DateDesc
convOrderBy (T.ASC (T.ColumnName "Title")) = TitleAsc
convOrderBy (T.ASC (T.ColumnName "Title")) = TitleAsc
convOrderBy (T.DESC (T.ColumnName "Title")) = TitleDesc
convOrderBy (T.DESC (T.ColumnName "Title")) = TitleDesc
convOrderBy (T.ASC (T.ColumnName "Source")) = SourceAsc
convOrderBy (T.ASC (T.ColumnName "Source")) = SourceAsc
convOrderBy (T.DESC (T.ColumnName "Source")) = SourceDesc
convOrderBy (T.DESC (T.ColumnName "Source")) = SourceDesc
convOrderBy _ = DateAsc -- TODO
convOrderBy _ = DateAsc -- TODO
type PageLoaderProps row =
type PageLayoutProps =
{ path :: PageParams
( totalRecords :: Int
, totalRecords :: Int
, deletions :: R.State Deletions
, dispatch :: Action -> Effect Unit
, container :: Record T.TableContainerProps -> R.Element
, deletionState :: State
, ends :: Ends
, container :: T.TableContainerProps -> Array ReactElement
, path :: R.State PagePath
| row
)
}
renderPage :: forall props path.
type PageProps = ( documents :: Array DocumentsView | PageLayoutProps )
Render (Loader.State {nodeId :: Int, listId :: Int, query :: TextQuery | path} (Array DocumentsView))
{ totalRecords :: Int
-- | Loads and renders a page
, dispatch :: Action -> Effect Unit
pageLayout :: Record PageLayoutProps -> R.Element
, deletionState :: State
pageLayout props = R.createElement pageLayoutCpt props []
, container :: T.TableContainerProps -> Array ReactElement
| props
pageLayoutCpt :: R.Component PageLayoutProps
}
pageLayoutCpt = R.hooksComponent "G.C.FacetsTable.PageLayout" cpt
(Loader.Action PageParams)
where
renderPage _ _ {loaded: Nothing} _ = [] -- TODO loading spinner
cpt {totalRecords, deletions, container, ends, path} _ = do
renderPage loaderDispatch { totalRecords, dispatch, container
useLoader (fst path) loadPage $ \documents ->
, deletionState: {documentIdsToDelete, documentIdsDeleted}}
page {totalRecords, deletions, container, ends, path, documents}
{currentPath: {nodeId, listId, query}, loaded: Just res} _ =
[ T.tableElt
page :: Record PageProps -> R.Element
{ rows
page props = R.createElement pageCpt props []
, setParams: \params -> liftEffect $ loaderDispatch (Loader.SetPath {nodeId, listId, query, params})
, container
pageCpt :: R.Component PageProps
, colNames:
pageCpt = R.staticComponent "G.C.FacetsTable.Page" cpt
T.ColumnName <$>
where
[ ""
cpt {totalRecords, container, deletions, documents, ends, path: path@({nodeId, listId, query} /\ setPath)} _ = do
, "Date"
T.table { rows, container, colNames, totalRecords, setParams }
, "Title"
, "Source"
, "Authors"
, "Delete"
]
, totalRecords
}
]
where
where
setParams params = setPath (_ {params = params})
colNames = T.ColumnName <$> [ "", "Date", "Title", "Source", "Authors", "Delete" ]
-- TODO: how to interprete other scores?
-- TODO: how to interprete other scores?
gi Favorite = "glyphicon glyphicon-star-empty"
gi Favorite = "glyphicon glyphicon-star-empty"
gi _ = "glyphicon glyphicon-star"
gi _ = "glyphicon glyphicon-star"
isChecked id = Set.member id documentIdsToDelete
isChecked id = Set.member id (fst deletions).pending
isDeleted (DocumentsView {id}) = Set.member id documentIdsD
eleted
isDeleted (DocumentsView {id}) = Set.member id (fst deletions).d
eleted
pairUrl (Pair {id,label})
pairUrl (Pair {id,label})
| id > 1 = [a [href (toUrl endConfigStateful Front NodeContact (Just id)), target "blank"] [text label]]
| id > 1 = H.a { href, target: "blank" } [ H.text label ]
| otherwise = [text label]
where href = url ends $ NodePath NodeContact (Just id)
comma = span [] [text ", "]
| otherwise = H.text label
rows = (\(DocumentsView {id,score,title,source,date,pairs,delete,category}) ->
comma = H.span {} [ H.text ", " ]
let
rows = row <$> filter (not <<< isDeleted) documents
strikeIfDeleted
where
| delete = [style {textDecoration : "line-through"}]
row (DocumentsView {id,score,title,source,date,pairs,delete,category}) =
| otherwise = []
in
{ row:
{ row:
[ div []
[ H.div {}
[ a [ className $ gi category
[ H.a { className, on: {click: markClick} } []
, onClick $ const $ dispatch $ MarkCategory category [id]
] []
]
-- TODO show date: Year-Month-Day only
-- TODO show date: Year-Month-Day only
, div strikeIfDeleted [text date]
, maybeStricken [ H.text date ]
, a (strikeIfDeleted <> [ href $ toLink endConfigStateful $ Router.Document listId id
, maybeStricken [ H.text source ]
, target "blank"])
-- , maybeStricken $ intercalate [comma] (pairUrl <$> pairs)
[ text title ]
, H.input { type: "checkbox", checked: isChecked id, on: { click: toggleClick } }
, div strikeIfDeleted [text source]
] ]
, div strikeIfDeleted $ intercalate [comma] $ pairUrl <$> pairs
, delete: true }
, input [ _type "checkbox"
where
, checked (isChecked id)
markClick _ = markCategory ends nodeId category [id]
, onClick $ const $ dispatch $ ToggleDocumentToDelete id]
toggleClick _ = togglePendingDeletion deletions id
]
className = gi category
, delete: true
maybeStricken
}) <$> filter (not <<< isDeleted) res
| delete = H.div { style: { textDecoration: "line-through" } }
| otherwise = H.div {}
pageLoaderClass :: ReactClass (PageLoaderProps (children :: Children))
pageLoaderClass = Loader.createLoaderClass' "PageLoader" loadPage renderPage
pageLoader :: PageLoaderProps () -> ReactElement
pageLoader props = React.createElement pageLoaderClass props []
---------------------------------------------------------
newtype DeleteDocumentQuery = DeleteDocumentQuery
---------------------------------------------------------
{
documents :: Array Int
}
newtype DeleteDocumentQuery = DeleteDocumentQuery { documents :: Array Int }
instance encodeJsonDDQuery :: EncodeJson DeleteDocumentQuery where
instance encodeJsonDDQuery :: EncodeJson DeleteDocumentQuery where
encodeJson (DeleteDocumentQuery post)
encodeJson (DeleteDocumentQuery post) =
= "documents" := post.documents
"documents" := post.documents ~> jsonEmptyObject
~> jsonEmptyObject
putFavorites :: Int -> FavoriteQuery -> Aff (Array Int)
putFavorites :: Ends -> Int -> FavoriteQuery -> Aff (Array Int)
putFavorites nodeId = put (toUrl endConfigStateful Back Node (Just nodeId) <> "/favorites")
putFavorites ends nodeId = put to
where to = url endst (NodeAPI Node (Just nodeId)) <> "/favorites"
deleteFavorites :: Int -> FavoriteQuery -> Aff (Array Int)
deleteFavorites :: Int -> FavoriteQuery -> Aff (Array Int)
deleteFavorites nodeId = deleteWithBody (toUrl endConfigStateful Back Node (Just nodeId) <> "/favorites")
deleteFavorites nodeId = deleteWithBody to
where to = url ends (NodeAPI Node (Just nodeId)) <> "/favorites"
deleteDocuments :: Int -> DeleteDocumentQuery -> Aff (Array Int)
deleteDocuments :: Ends -> Int -> DeleteDocumentQuery -> Aff (Array Int)
deleteDocuments nodeId = deleteWithBody (toUrl endConfigStateful Back Node (Just nodeId) <> "/documents")
deleteDocuments ends nodeId = deleteWithBody to
where to = url ends (NodeAPI Node (Just nodeId)) <> "/documents"
src/Gargantext/Components/NgramsTable.purs
View file @
6cf771f9
module Gargantext.Components.NgramsTable
module Gargantext.Components.NgramsTable where
( Action
, MainNgramsTableProps
, initialState
, mainNgramsTableSpec
, ngramsTableClass
, ngramsTableSpec
, termStyle
)
where
import Data.Array as A
import Data.Array as A
import Data.Lens (to, view, (%~), (.~), (^.), (^..))
import Data.Lens (to, view, (%~), (.~), (^.), (^..))
...
@@ -24,7 +15,10 @@ import Data.Monoid.Additive (Additive(..))
...
@@ -24,7 +15,10 @@ import Data.Monoid.Additive (Additive(..))
import Data.Ord.Down (Down(..))
import Data.Ord.Down (Down(..))
import Data.Symbol (SProxy(..))
import Data.Symbol (SProxy(..))
import Data.Tuple (Tuple(..), snd)
import Data.Tuple (Tuple(..), snd)
import Data.Tuple.Nested ((/\))
import Effect (Effect)
import Effect (Effect)
import Reactix as R
import Reactix.DOM.HTML as H
import React (ReactElement)
import React (ReactElement)
import React.DOM (a, button, div, h2, i, input, li, option, p, select, span, table, tbody, text, thead, ul)
import React.DOM (a, button, div, h2, i, input, li, option, p, select, span, table, tbody, text, thead, ul)
import React.DOM.Props (_id, _type, checked, className, name, onChange, onClick, onInput, placeholder, style, value)
import React.DOM.Props (_id, _type, checked, className, name, onChange, onClick, onInput, placeholder, style, value)
...
@@ -32,11 +26,11 @@ import React.DOM.Props as DOM
...
@@ -32,11 +26,11 @@ import React.DOM.Props as DOM
import Thermite (PerformAction, Render, Spec, defaultPerformAction, modifyState_, simpleSpec, createClass)
import Thermite (PerformAction, Render, Spec, defaultPerformAction, modifyState_, simpleSpec, createClass)
import Gargantext.Types (TermList(..), readTermList, readTermSize, termLists, termSizes)
import Gargantext.Types (TermList(..), readTermList, readTermSize, termLists, termSizes)
import Gargantext.Config (OrderBy(..), TabType, CTabNgramType(..))
import Gargantext.Config (
Ends,
OrderBy(..), TabType, CTabNgramType(..))
import Gargantext.Components.AutoUpdate (autoUpdateElt)
import Gargantext.Components.AutoUpdate (autoUpdateElt)
import Gargantext.Components.Table as T
import Gargantext.Components.Table as T
import Gargantext.Prelude
import Gargantext.Prelude
import Gargantext.
Components.Loader as Loader
import Gargantext.
Hooks.Loader (useLoader, useLoader2)
import Gargantext.Components.NgramsTable.Core
import Gargantext.Components.NgramsTable.Core
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Reactix as R2
...
@@ -52,9 +46,8 @@ type State =
...
@@ -52,9 +46,8 @@ type State =
_ngramsChildren = prop (SProxy :: SProxy "ngramsChildren")
_ngramsChildren = prop (SProxy :: SProxy "ngramsChildren")
initialState :: forall props. { loaded :: VersionedNgramsTable | props }
initialState :: VersionedNgramsTable -> State
-> State
initialState (Versioned {version}) =
initialState {loaded: Versioned {version}} =
{ ngramsTablePatch: mempty
{ ngramsTablePatch: mempty
, ngramsVersion: version
, ngramsVersion: version
, ngramsParent: Nothing
, ngramsParent: Nothing
...
@@ -78,86 +71,66 @@ data Action
...
@@ -78,86 +71,66 @@ data Action
type Dispatch = Action -> Effect Unit
type Dispatch = Action -> Effect Unit
type LoaderAction = Loader.Action PageParams
type LoaderDispatch = LoaderAction -> Effect Unit
tableContainer :: { pageParams :: PageParams
tableContainer :: { pageParams :: PageParams
, dispatch :: Dispatch
, dispatch :: Dispatch
,
loaderDispatch :: LoaderDispatch
,
setPath :: R2.Setter PageParams
, ngramsParent :: Maybe NgramsTerm
, ngramsParent :: Maybe NgramsTerm
, ngramsChildren :: Map NgramsTerm Boolean
, ngramsChildren :: Map NgramsTerm Boolean
, ngramsTable :: NgramsTable
, ngramsTable :: NgramsTable
}
}
->
T.TableContainerProps -> Array React
Element
->
Record T.TableContainerProps -> R.
Element
tableContainer { pageParams
tableContainer { pageParams
, dispatch
, dispatch
,
loaderDispatc
h
,
setPat
h
, ngramsParent
, ngramsParent
, ngramsChildren
, ngramsChildren
, ngramsTable: ngramsTableCache
, ngramsTable: ngramsTableCache
} props =
} props =
[ div [className "container-fluid"]
H.div {className: "container-fluid"}
[ div [className "jumbotron1"]
[ H.div {className: "jumbotron1"}
[ div [className "row"]
[ H.div {className: "row"}
[ div [className "panel panel-default"]
[ H.div {className: "panel panel-default"}
[ div [className "panel-heading"]
[ H.div {className: "panel-heading"}
[ h2 [className "panel-title", style {textAlign : "center"}]
[ H.h2 {className: "panel-title", style: {textAlign : "center"}}
[ span [className "glyphicon glyphicon-hand-down"] []
[ H.span {className: "glyphicon glyphicon-hand-down"} []
, text "Extracted Terms"
, H.text "Extracted Terms"
]
, div [className "row"]
[
{-div [className "savediv pull-left col-md-2", style { marginTop :"35px"}]
[ button [_id "ImportListOrSaveAll", className "btn btn-warning", style {fontSize : "120%"}]
[ text "Import a Termlist" ]
]
]
,-
}
, H.div {className: "row"
}
div [className "col-md-3", style {marginTop : "6px"}]
[ H.div {className: "col-md-3", style: {marginTop: "6px"}}
[ input [ className "form-control
"
[ H.input { className: "form-control
"
, name
"search", placeholder "S
earch"
, name
: "s
earch"
,
_type "value
"
,
placeholder: "Search
"
,
value pageParams.searchQuery
,
type: "value"
,
onInput \e -> setSearchQuery (R2.unsafeEventValue e)
,
value: pageParams.searchQuery
]
, on: {input: \e -> setSearchQuery (R2.unsafeEventValue e)}}
, div []
(
, H.div {}
(
if A.null props.tableBody && pageParams.searchQuery /= "" then [
if A.null props.tableBody && pageParams.searchQuery /= "" then [
button [ className "btn btn-primary"
H.button { className: "btn btn-primary"
, onClick $ const $ dispatch $ AddNewNgram pageParams.searchQuery
, on: {click: const $ dispatch $ AddNewNgram pageParams.searchQuery}}
] [text $ "Add " <> pageParams.searchQuery]
[ H.text ("Add " <> pageParams.searchQuery) ]
] else []
] else [])]
)
, H.div {className: "col-md-2", style: {marginTop : "6px"}}
]
[ H.li {className: " list-group-item"}
, div [className "col-md-2", style {marginTop : "6px"}]
[ R2.select { id: "picklistmenu"
[ li [className " list-group-item"]
, className: "form-control custom-select"
[ select [ _id "picklistmenu"
, value: (maybe "" show pageParams.termListFilter)
, className "form-control custom-select"
, on: {change: (\e -> setTermListFilter $ readTermList $ R2.unsafeEventValue e)}}
, value (maybe "" show pageParams.termListFilter)
(map optps1 termLists)]]
, onChange (\e -> setTermListFilter $ readTermList $ R2.unsafeEventValue e)
, H.div {className: "col-md-2", style: {marginTop : "6px"}}
] $ map optps1 termLists
[ H.li {className: "list-group-item"}
]
[ R2.select {id: "picktermtype"
]
, className: "form-control custom-select"
, div [className "col-md-2", style {marginTop : "6px"}]
, value: (maybe "" show pageParams.termSizeFilter)
[ li [className "list-group-item"]
, on: {change: (\e -> setTermSizeFilter $ readTermSize $ R2.unsafeEventValue e)}}
[ select [ _id "picktermtype"
(map optps1 termSizes)]]
, className "form-control custom-select"
, H.div {className: "col-md-4", style: {marginTop : "6px", marginBottom : "1px"}}
, value (maybe "" show pageParams.termSizeFilter)
[ H.li {className: " list-group-item"}
, onChange (\e -> setTermSizeFilter $ readTermSize $ R2.unsafeEventValue e)
[ props.pageSizeDescription
] $ map optps1 termSizes
]
]
, div [className "col-md-4", style {marginTop : "6px", marginBottom : "1px"}]
[ li [className " list-group-item"] [ props.pageSizeDescription
, props.pageSizeControl
, props.pageSizeControl
, text " items / "
, H.text " items / "
, props.paginationLinks
, props.paginationLinks]]]]
]
, H.div {}
--, li [className " list-group-item"] [ props.pageSizeControl ]
(maybe [] (\ngrams ->
]
]
]
, div [] (maybe [] (\ngrams ->
let
let
ngramsTable =
ngramsTable =
ngramsTableCache # at ngrams
ngramsTableCache # at ngrams
...
@@ -170,24 +143,17 @@ tableContainer { pageParams
...
@@ -170,24 +143,17 @@ tableContainer { pageParams
ngramsClick _ = Nothing
ngramsClick _ = Nothing
ngramsEdit _ = Nothing
ngramsEdit _ = Nothing
in
in
[
p[] [
text $ "Editing " <> ngrams]
[
H.p {} [H.
text $ "Editing " <> ngrams]
, renderNgramsTree { ngramsTable, ngrams, ngramsStyle: [], ngramsClick, ngramsEdit }
,
R2.buff $
renderNgramsTree { ngramsTable, ngrams, ngramsStyle: [], ngramsClick, ngramsEdit }
,
button [className "btn btn-primary", onClick $ const $ dispatch $ AddTermChildren] [
text "Save"]
,
H.button {className: "btn btn-primary", on: {click: (const $ dispatch $ AddTermChildren)}} [H.
text "Save"]
,
button [className "btn btn-secondary", onClick $ const $ dispatch $ SetParentResetChildren Nothing] [
text "Cancel"]
,
H.button {className: "btn btn-secondary", on: {click: (const $ dispatch $ SetParentResetChildren Nothing)}} [H.
text "Cancel"]
]) ngramsParent)
]) ngramsParent)
, div [ _id "terms_table", className "panel-body" ]
, H.div {id: "terms_table", className: "panel-body"}
[ table [ className "table able" ]
[ H.table {className: "table able"}
[ thead [ className "tableHeader"] [props.tableHead]
[ H.thead {className: "tableHeader"} [props.tableHead]
, tbody [] props.tableBody
, H.tbody {} props.tableBody]]]]]]
]
]
]
]
]
]
]
where
where
setPageParams f =
loaderDispatch $ Loader.SetPath $ f pageParams
setPageParams f =
setPath (const $ f pageParams)
setSearchQuery x = setPageParams $ _ { searchQuery = x }
setSearchQuery x = setPageParams $ _ { searchQuery = x }
setTermListFilter x = setPageParams $ _ { termListFilter = x }
setTermListFilter x = setPageParams $ _ { termListFilter = x }
setTermSizeFilter x = setPageParams $ _ { termSizeFilter = x }
setTermSizeFilter x = setPageParams $ _ { termSizeFilter = x }
...
@@ -196,21 +162,50 @@ toggleMap :: forall a. a -> Maybe a -> Maybe a
...
@@ -196,21 +162,50 @@ toggleMap :: forall a. a -> Maybe a -> Maybe a
toggleMap _ (Just _) = Nothing
toggleMap _ (Just _) = Nothing
toggleMap b Nothing = Just b
toggleMap b Nothing = Just b
ngramsTableSpec :: CTabNgramType -> Spec State LoadedNgramsTableProps Action
data Action'
ngramsTableSpec ntype = simpleSpec performAction render
= SetParentResetChildren' (Maybe NgramsTerm)
| ToggleChild' (Maybe NgramsTerm) NgramsTerm
| Refresh'
performNgramsAction :: State -> Action' -> State
performNgramsAction st (SetParentResetChildren' term) = st
performNgramsAction st (ToggleChild' b c) = st
performNgramsAction st Refresh' = st
useNgramsReducer :: State -> R.Hooks (R.Reducer State Action')
useNgramsReducer init = R.useReducer performNgramsAction identity init
type Props =
( ends :: Ends
, tabNgramType :: CTabNgramType
, path :: R.State PageParams
, versioned :: VersionedNgramsTable )
ngramsTable :: Record Props -> R.Element
ngramsTable props = R.createElement ngramsTableCpt props []
ngramsTableCpt :: R.Component Props
ngramsTableCpt = R.hooksComponent "G.C.NgramsTable.ngramsTable" cpt
where
cpt {versioned} _ = do
state <- useNgramsReducer (initialState versioned)
pure $ R.fragment []
ngramsTableSpec :: Ends -> CTabNgramType -> R2.Setter PageParams -> Spec State (Record LoadedNgramsTableProps) Action
ngramsTableSpec ends ntype setPath = simpleSpec performAction render
where
where
setParentResetChildren :: Maybe NgramsTerm -> State -> State
setParentResetChildren :: Maybe NgramsTerm -> State -> State
setParentResetChildren p = _ { ngramsParent = p, ngramsChildren = mempty }
setParentResetChildren p = _ { ngramsParent = p, ngramsChildren = mempty }
performAction :: PerformAction State
LoadedNgramsTableProps
Action
performAction :: PerformAction State
(Record LoadedNgramsTableProps)
Action
performAction (SetParentResetChildren p) _ _ =
performAction (SetParentResetChildren p) _ _ =
modifyState_ $ setParentResetChildren p
modifyState_ $ setParentResetChildren p
performAction (ToggleChild b c) _ _ =
performAction (ToggleChild b c) _ _ =
modifyState_ $ _ngramsChildren <<< at c %~ toggleMap b
modifyState_ $ _ngramsChildren <<< at c %~ toggleMap b
performAction Refresh {path: {nodeId, listIds, tabType}} {ngramsVersion} = do
performAction Refresh {path: {nodeId, listIds, tabType}} {ngramsVersion} = do
commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: mempty})
commitPatch
ends
{nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: mempty})
performAction (SetTermListItem n pl) {path: {nodeId, listIds, tabType}} {ngramsVersion} =
performAction (SetTermListItem n pl) {path: {nodeId, listIds, tabType}} {ngramsVersion} =
commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: pt})
commitPatch
ends
{nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: pt})
where
where
pe = NgramsPatch { patch_list: pl, patch_children: mempty }
pe = NgramsPatch { patch_list: pl, patch_children: mempty }
pt = singletonNgramsTablePatch ntype n pe
pt = singletonNgramsTablePatch ntype n pe
...
@@ -223,42 +218,29 @@ ngramsTableSpec ntype = simpleSpec performAction render
...
@@ -223,42 +218,29 @@ ngramsTableSpec ntype = simpleSpec performAction render
, ngramsVersion
, ngramsVersion
} = do
} = do
modifyState_ $ setParentResetChildren Nothing
modifyState_ $ setParentResetChildren Nothing
commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: pt})
commitPatch
ends
{nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: pt})
where
where
pc = patchSetFromMap ngramsChildren
pc = patchSetFromMap ngramsChildren
pe = NgramsPatch { patch_list: mempty, patch_children: pc }
pe = NgramsPatch { patch_list: mempty, patch_children: pc }
pt = singletonNgramsTablePatch ntype parent pe
pt = singletonNgramsTablePatch ntype parent pe
performAction (AddNewNgram ngram) {path: {listIds, nodeId, tabType}} {ngramsVersion} =
performAction (AddNewNgram ngram) {path: {listIds, nodeId, tabType}} {ngramsVersion} =
commitPatch {listIds, nodeId, tabType} (Versioned {version: ngramsVersion, data: pt})
commitPatch
ends
{listIds, nodeId, tabType} (Versioned {version: ngramsVersion, data: pt})
where
where
pt = addNewNgram ntype ngram CandidateTerm
pt = addNewNgram ntype ngram CandidateTerm
render :: Render State
LoadedNgramsTableProps
Action
render :: Render State
(Record LoadedNgramsTableProps)
Action
render dispatch { path: pageParams
render dispatch { path: pageParams
, loaded: Versioned { data: initTable }
, loaded: Versioned { data: initTable } }
, dispatch: loaderDispatch }
{ ngramsTablePatch, ngramsParent, ngramsChildren }
{ ngramsTablePatch, ngramsParent, ngramsChildren }
_reactChildren =
_reactChildren =
[ autoUpdateElt { duration: 3000
[ autoUpdateElt { duration: 3000, effect: dispatch Refresh }
, effect: dispatch Refresh
, R2.scuff $ T.table { rows, setParams, container, colNames, totalRecords}
}
, T.tableElt
{ rows
, setParams
, container: tableContainer {pageParams, loaderDispatch, dispatch, ngramsParent, ngramsChildren, ngramsTable}
, colNames:
T.ColumnName <$>
[ "Map"
, "Stop"
, "Terms"
, "Score (Occurrences)" -- see convOrderBy
]
, totalRecords: 47361 -- TODO
}
]
]
where
where
setParams params =
totalRecords = 47361 -- TODO
loaderDispatch $ Loader.SetPath $ pageParams {params = params}
colNames = T.ColumnName <$> ["Map", "Stop", "Terms", "Score (Occurrences)"] -- see convOrderBy
container = tableContainer {pageParams, setPath, dispatch, ngramsParent, ngramsChildren, ngramsTable}
setParams params = setPath $ const (pageParams {params = params})
ngramsTable = applyNgramsTablePatch ngramsTablePatch initTable
ngramsTable = applyNgramsTablePatch ngramsTablePatch initTable
orderWith =
orderWith =
case convOrderBy <$> pageParams.params.orderBy of
case convOrderBy <$> pageParams.params.orderBy of
...
@@ -287,29 +269,35 @@ ngramsTableSpec ntype = simpleSpec performAction render
...
@@ -287,29 +269,35 @@ ngramsTableSpec ntype = simpleSpec performAction render
|| -- Unless they are scheduled to be removed.
|| -- Unless they are scheduled to be removed.
ngramsChildren ^. at ngrams == Just false
ngramsChildren ^. at ngrams == Just false
convertRow (Tuple ngrams ngramsElement) =
convertRow (Tuple ngrams ngramsElement) =
{ row:
renderNgramsItem { ngramsTable, ngrams, ngramsParent, ngramsElement, dispatch}
{ row: R2.buff <$>
renderNgramsItem { ngramsTable, ngrams, ngramsParent, ngramsElement, dispatch}
, delete: false
, delete: false
}
}
ngramsTableClass :: CTabNgramType -> Loader.InnerClass PageParams VersionedNgramsTable
-- ngramsTableClass :: Ends -> CTabNgramType -> R2.Setter PageParams -> Loader.InnerClass PageParams (Versioned NgramsTable)
ngramsTableClass ct = createClass "NgramsTable" (ngramsTableSpec ct) initialState
-- ngramsTableClass ends ct setPath = createClass "NgramsTable" (ngramsTableSpec ends ct setPath) initialState
-- ngramsTable' :: Ends -> CTabNgramType -> R2.Setter PageParams -> Record LoadedNgramsTableProps -> R.Element
-- ngramsTable' ends ct setPath props = R2.createElement' (ngramsTableClass ends ct setPath) props []
type MainNgramsTableProps =
type MainNgramsTableProps =
{
nodeId :: Int
(
nodeId :: Int
-- ^ This node can be a corpus or contact.
-- ^ This node can be a corpus or contact.
, defaultListId :: Int
, defaultListId :: Int
, tabType :: TabType
, tabType :: TabType
}
, ends :: Ends
, tabNgramType :: CTabNgramType
)
mainNgramsTableSpec :: CTabNgramType -> Spec {} MainNgramsTableProps Void
mainNgramsTable :: Record MainNgramsTableProps -> R.Element
mainNgramsTableSpec nt = simpleSpec defaultPerformAction render
mainNgramsTable props = R.createElement mainNgramsTableCpt props []
mainNgramsTableCpt :: R.Component MainNgramsTableProps
mainNgramsTableCpt = R.hooksComponent "MainNgramsTable" cpt
where
where
render :: Render {} MainNgramsTableProps Void
cpt {nodeId, defaultListId, tabType, ends, tabNgramType} _ = do
render _ {nodeId, defaultListId, tabType} _ _ =
path <- R.useState' $ initialPageParams ends nodeId [defaultListId] tabType
[ ngramsLoader
useLoader2 path (loadNgramsTable ends) $
{ path: initialPageParams nodeId [defaultListId] tabType
\versioned -> ngramsTable {ends, tabNgramType, path, versioned}
, component: (ngramsTableClass nt)
} ]
type NgramsDepth = {ngrams :: NgramsTerm, depth :: Int}
type NgramsDepth = {ngrams :: NgramsTerm, depth :: Int}
type NgramsClick = NgramsDepth -> Maybe (Effect Unit)
type NgramsClick = NgramsDepth -> Maybe (Effect Unit)
...
@@ -415,7 +403,6 @@ nextTermList GraphTerm = StopTerm
...
@@ -415,7 +403,6 @@ nextTermList GraphTerm = StopTerm
nextTermList StopTerm = CandidateTerm
nextTermList StopTerm = CandidateTerm
nextTermList CandidateTerm = GraphTerm
nextTermList CandidateTerm = GraphTerm
optps1 :: forall a. Show a => { desc :: String, mval :: Maybe a } -> ReactElement
optps1 :: forall a. Show a => { desc :: String, mval :: Maybe a } -> R.Element
optps1 { desc, mval } = option [value val] [text desc]
optps1 { desc, mval } = H.option {value} [H.text desc]
where
where value = maybe "" show mval
val = maybe "" show mval
src/Gargantext/Components/NgramsTable/Core.purs
View file @
6cf771f9
...
@@ -86,7 +86,7 @@ import Partial.Unsafe (unsafePartial)
...
@@ -86,7 +86,7 @@ import Partial.Unsafe (unsafePartial)
import Gargantext.Utils.KarpRabin (indicesOfAny)
import Gargantext.Utils.KarpRabin (indicesOfAny)
import Gargantext.Types (TermList(..), TermSize)
import Gargantext.Types (TermList(..), TermSize)
import Gargantext.Config (
toUrl, endConfigStateful, End(..), Path(..), TabType, OrderBy(..), CTabNgramType(..)
)
import Gargantext.Config (
Ends, BackendRoute(..), TabType, OrderBy(..), CTabNgramType(..), url
)
import Gargantext.Config.REST (get, put, post)
import Gargantext.Config.REST (get, put, post)
import Gargantext.Components.Table as T
import Gargantext.Components.Table as T
import Gargantext.Prelude
import Gargantext.Prelude
...
@@ -106,10 +106,11 @@ type PageParams =
...
@@ -106,10 +106,11 @@ type PageParams =
, searchQuery :: String
, searchQuery :: String
, termListFilter :: Maybe TermList -- Nothing means all
, termListFilter :: Maybe TermList -- Nothing means all
, termSizeFilter :: Maybe TermSize -- Nothing means all
, termSizeFilter :: Maybe TermSize -- Nothing means all
, ends :: Ends
)
)
initialPageParams :: Int -> Array Int -> TabType -> PageParams
initialPageParams ::
Ends ->
Int -> Array Int -> TabType -> PageParams
initialPageParams nodeId listIds tabType =
initialPageParams
ends
nodeId listIds tabType =
{ nodeId
{ nodeId
, listIds
, listIds
, params: T.initialParams
, params: T.initialParams
...
@@ -117,6 +118,7 @@ initialPageParams nodeId listIds tabType =
...
@@ -117,6 +118,7 @@ initialPageParams nodeId listIds tabType =
, termSizeFilter: Nothing
, termSizeFilter: Nothing
, termListFilter: Just GraphTerm
, termListFilter: Just GraphTerm
, searchQuery: ""
, searchQuery: ""
, ends
}
}
type NgramsTerm = String
type NgramsTerm = String
...
@@ -561,47 +563,48 @@ type CoreState s =
...
@@ -561,47 +563,48 @@ type CoreState s =
| s
| s
}
}
postNewNgrams :: forall s. Array NgramsTerm -> Maybe TermList -> CoreParams s -> Aff Unit
postNewNgrams :: forall s.
Ends ->
Array NgramsTerm -> Maybe TermList -> CoreParams s -> Aff Unit
postNewNgrams newNgrams mayList {nodeId, listIds, tabType} =
postNewNgrams
ends
newNgrams mayList {nodeId, listIds, tabType} =
when (not (A.null newNgrams)) $ do
when (not (A.null newNgrams)) $ do
(_ :: Array Unit) <- post (
toUrl endConfigStateful Back (PutNgrams tabType (head listIds) mayList) $ Just nodeId
) newNgrams
(_ :: Array Unit) <- post (
url ends put
) newNgrams
pure unit
pure unit
where put = PutNgrams tabType (head listIds) mayList (Just nodeId)
postNewElems :: forall s. NewElems -> CoreParams s -> Aff Unit
postNewElems :: forall s.
Ends ->
NewElems -> CoreParams s -> Aff Unit
postNewElems newElems params = void $ traverseWithIndex postNewElem newElems
postNewElems
ends
newElems params = void $ traverseWithIndex postNewElem newElems
where
where
postNewElem ngrams list = postNewNgrams [ngrams] (Just list) params
postNewElem ngrams list = postNewNgrams
ends
[ngrams] (Just list) params
addNewNgram :: CTabNgramType -> NgramsTerm -> TermList -> NgramsTablePatch
addNewNgram :: CTabNgramType -> NgramsTerm -> TermList -> NgramsTablePatch
addNewNgram ntype ngrams list = { ngramsPatches: mempty
addNewNgram ntype ngrams list = { ngramsPatches: mempty
, ngramsNewElems: Map.singleton (normNgram ntype ngrams) list }
, ngramsNewElems: Map.singleton (normNgram ntype ngrams) list }
putNgramsPatches :: {nodeId :: Int, listIds :: Array Int, tabType :: TabType} -> Versioned NgramsPatches -> Aff (Versioned NgramsPatches)
putNgramsPatches ::
Ends ->
{nodeId :: Int, listIds :: Array Int, tabType :: TabType} -> Versioned NgramsPatches -> Aff (Versioned NgramsPatches)
putNgramsPatches
{nodeId, listIds, tabType} =
putNgramsPatches
ends {nodeId, listIds, tabType} = put $ url ends putNgrams
put (toUrl endConfigStateful Back (PutNgrams tabType (head listIds) Nothing) $
Just nodeId)
where putNgrams = PutNgrams tabType (head listIds) Nothing (
Just nodeId)
commitPatch :: forall s. {nodeId :: Int, listIds :: Array Int, tabType :: TabType}
commitPatch :: forall s.
Ends ->
{nodeId :: Int, listIds :: Array Int, tabType :: TabType}
-> Versioned NgramsTablePatch -> StateCoTransformer (CoreState s) Unit
-> Versioned NgramsTablePatch -> StateCoTransformer (CoreState s) Unit
commitPatch props (Versioned {version, data: tablePatch@{ngramsPatches, ngramsNewElems}}) = do
commitPatch
ends
props (Versioned {version, data: tablePatch@{ngramsPatches, ngramsNewElems}}) = do
let pt = Versioned { version, data: ngramsPatches }
let pt = Versioned { version, data: ngramsPatches }
lift $ postNewElems ngramsNewElems props
lift $ postNewElems
ends
ngramsNewElems props
Versioned {version: newVersion, data: newPatch} <- lift $ putNgramsPatches props pt
Versioned {version: newVersion, data: newPatch} <- lift $ putNgramsPatches
ends
props pt
modifyState_ $ \s ->
modifyState_ $ \s ->
s { ngramsVersion = newVersion
s { ngramsVersion = newVersion
, ngramsTablePatch = fromNgramsPatches newPatch <> tablePatch <> s.ngramsTablePatch
, ngramsTablePatch = fromNgramsPatches newPatch <> tablePatch <> s.ngramsTablePatch
}
}
-- TODO: check that pt.version == s.ngramsTablePatch.version
-- TODO: check that pt.version == s.ngramsTablePatch.version
loadNgramsTable :: PageParams -> Aff VersionedNgramsTable
loadNgramsTable :: Ends -> PageParams -> Aff VersionedNgramsTable
loadNgramsTable { nodeId, listIds, termListFilter, termSizeFilter
loadNgramsTable ends
, searchQuery, tabType, params: {offset, limit, orderBy}} =
{ nodeId, listIds, termListFilter, termSizeFilter
get $ toUrl endConfigStateful Back
, searchQuery, tabType, params: {offset, limit, orderBy}}
(GetNgrams { tabType, offset, limit, listIds
= get $ url ends query
where query = GetNgrams { tabType, offset, limit, listIds
, orderBy: convOrderBy <$> orderBy
, orderBy: convOrderBy <$> orderBy
, termListFilter, termSizeFilter
, termListFilter, termSizeFilter
, searchQuery
, searchQuery } (Just nodeId)
})
(Just nodeId)
convOrderBy :: T.OrderByDirection T.ColumnName -> OrderBy
convOrderBy :: T.OrderByDirection T.ColumnName -> OrderBy
convOrderBy (T.ASC (T.ColumnName "Score (Occurrences)")) = ScoreAsc
convOrderBy (T.ASC (T.ColumnName "Score (Occurrences)")) = ScoreAsc
...
@@ -609,10 +612,10 @@ convOrderBy (T.DESC (T.ColumnName "Score (Occurrences)")) = ScoreDesc
...
@@ -609,10 +612,10 @@ convOrderBy (T.DESC (T.ColumnName "Score (Occurrences)")) = ScoreDesc
convOrderBy (T.ASC _) = TermAsc
convOrderBy (T.ASC _) = TermAsc
convOrderBy (T.DESC _) = TermDesc
convOrderBy (T.DESC _) = TermDesc
ngramsLoaderClass :: Loader.LoaderClass PageParams VersionedNgramsTable
ngramsLoaderClass ::
Ends ->
Loader.LoaderClass PageParams VersionedNgramsTable
ngramsLoaderClass
= Loader.createLoaderClass "NgramsTableLoader" loadNgramsTable
ngramsLoaderClass
ends = Loader.createLoaderClass "NgramsTableLoader" (loadNgramsTable ends)
ngramsLoader :: Loader.Props' PageParams VersionedNgramsTable -> ReactElement
ngramsLoader ::
Ends ->
Loader.Props' PageParams VersionedNgramsTable -> ReactElement
ngramsLoader
props = React.createElement ngramsLoaderClass
props []
ngramsLoader
ends props = React.createElement (ngramsLoaderClass ends)
props []
type LoadedNgramsTableProps =
Loader.InnerProps PageParams VersionedNgramsTable (
)
type LoadedNgramsTableProps =
( path :: PageParams, loaded :: VersionedNgramsTable
)
src/Gargantext/Components/Search/Types.purs
View file @
6cf771f9
...
@@ -167,8 +167,8 @@ instance encodeJsonCategoryQuery :: EncodeJson CategoryQuery where
...
@@ -167,8 +167,8 @@ instance encodeJsonCategoryQuery :: EncodeJson CategoryQuery where
~> "ntc_category" := encodeJson post.category
~> "ntc_category" := encodeJson post.category
~> jsonEmptyObject
~> jsonEmptyObject
categoryUrl :: Int -> String
categoryUrl ::
Ends ->
Int -> String
categoryUrl
nodeId = toUrl endConfigStateful Back Node (Just nodeId
) <> "/category"
categoryUrl
ends nodeId = url ends (NodeAPI Node (Just nodeId)
) <> "/category"
putCategories :: Int -> CategoryQuery -> Aff (Array Int)
putCategories ::
Ends ->
Int -> CategoryQuery -> Aff (Array Int)
putCategories
nodeId = put $ categoryUrl nodeId
putCategories
= put <<< categoryUrl
src/Gargantext/Components/Table.purs
View file @
6cf771f9
...
@@ -7,25 +7,25 @@ import Data.Maybe (Maybe(..), maybe)
...
@@ -7,25 +7,25 @@ import Data.Maybe (Maybe(..), maybe)
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Data.Generic.Rep.Show (genericShow)
import Data.Maybe (Maybe(..), maybe)
import Data.Maybe (Maybe(..), maybe)
import Data.Tuple.Nested ((/\))
import Effect (Effect)
import Effect (Effect)
import Effect.Class (liftEffect)
import Effect.Class (liftEffect)
import Reactix as R
import Reactix.DOM.HTML as H
import Unsafe.Coerce (unsafeCoerce)
import Gargantext.Prelude
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Reactix as R2
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, defaultValue, style)
import Thermite (PerformAction, Render, Spec, modifyState_, simpleSpec, StateCoTransformer, createClass)
type TableContainerProps =
type TableContainerProps =
{ pageSizeControl :: React
Element
( pageSizeControl :: R.
Element
, pageSizeDescription :: R
eact
Element
, pageSizeDescription :: R
.
Element
, paginationLinks :: R
eact
Element
, paginationLinks :: R
.
Element
, tableHead :: R
eact
Element
, tableHead :: R
.
Element
, tableBody :: Array R
eact
Element
, tableBody :: Array R
.
Element
}
)
type Rows = Array { row :: Array ReactElement
type Row = { row :: Array R.Element, delete :: Boolean }
, delete :: Boolean
type Rows = Array Row
}
type OrderBy = Maybe (OrderByDirection ColumnName)
type OrderBy = Maybe (OrderByDirection ColumnName)
...
@@ -52,250 +52,203 @@ instance showOrderByDirection :: Show a => Show (OrderByDirection a) where
...
@@ -52,250 +52,203 @@ instance showOrderByDirection :: Show a => Show (OrderByDirection a) where
derive instance eqOrderByDirection :: Eq a => Eq (OrderByDirection a)
derive instance eqOrderByDirection :: Eq a => Eq (OrderByDirection a)
type Props
'
=
type Props =
( colNames :: Array ColumnName
( colNames :: Array ColumnName
, totalRecords :: Int
, totalRecords :: Int
, setParams :: Params -> Effect Unit
, setParams :: Params -> Effect Unit
, rows :: Rows
, rows :: Rows
, container ::
TableContainerProps -> Array React
Element
, container ::
Record TableContainerProps -> R.
Element
)
)
type Props = Record Props'
type State =
type State =
{
currentPage
:: Int
{
page
:: Int
, pageSize :: PageSizes
, pageSize :: PageSizes
, orderBy :: OrderBy
, orderBy :: OrderBy
}
}
initialState :: State
stateParams :: State -> Params
initialState =
stateParams {pageSize, page, orderBy} = {offset, limit, orderBy}
{ currentPage : 1
where
, pageSize : PS10
limit = pageSizes2Int pageSize
, orderBy : Nothing
offset = limit * (page - 1)
}
initialParams :: Params
initialParams = stateParams initialState
data Action
= ChangePageSize PageSizes
| ChangePage Int
| ChangeOrderBy OrderBy
type ChangePageAction = Int -> Effect Unit
-- | Action
-- ChangePageSize
changePageSize :: PageSizes -> State -> State
changePageSize ps td =
td { pageSize = ps
, currentPage = 1
}
-- TODO: Not sure this is the right place for this function.
type TableHeaderLayoutProps =
renderTableHeaderLayout :: {
title :: String
(
title :: String
, desc :: String
, desc :: String
, query :: String
, query :: String
, date :: String
, date :: String
, user :: String
, user :: String
} -> Array ReactElement
)
renderTableHeaderLayout {title, desc, query, date, user} =
[ div [className "row"]
initialParams :: Params
[ div [className "col-md-3"] [ h3 [] [text title] ]
initialParams = stateParams {page: 1, pageSize: PS10, orderBy: Nothing}
, div [className "col-md-9"] [ hr [style {height : "2px",backgroundColor : "black"}] ]
-- TODO: Not sure this is the right place for this
tableHeaderLayout :: Record TableHeaderLayoutProps -> R.Element
tableHeaderLayout props = R.createElement tableHeaderLayoutCpt props []
tableHeaderLayoutCpt :: R.Component TableHeaderLayoutProps
tableHeaderLayoutCpt = R.staticComponent "TableHeaderLayout" cpt
where
cpt {title, desc, query, date, user} _ =
R.fragment
[ H.div {className: "row"}
[ H.div {className: "col-md-3"} [ H.h3 {} [H.text title] ]
, H.div {className: "col-md-9"}
[ H.hr {style: {height: "2px", backgroundColor: "black"}} ]
]
]
, div [className "row"] [ div [className "jumbotron1", style {padding : "12px 0px 20px 12px"}]
, H.div {className: "row"}
[ div [ className "col-md-8 content"]
[ H.div {className: "jumbotron1", style: {padding: "12px 0px 20px 12px"}}
[ p [] [ i [className "glyphicon glyphicon-globe"] []
[ H.div {className: "col-md-8 content"}
, text $ " " <> desc
[ H.p {}
[ H.i {className: "glyphicon glyphicon-globe"} []
, H.text $ " " <> desc
]
]
, p [] [ i [className "glyphicon glyphicon-zoom-in"] []
, H.p {}
, text $ " " <> query
[ H.i {className: "glyphicon glyphicon-zoom-in"} []
, H.text $ " " <> query
]
]
]
]
, div [ className "col-md-4 content"]
, H.div {className: "col-md-4 content"}
[ p [] [ i [className "glyphicon glyphicon-calendar"] []
[ H.p {}
, text $ " " <> date
[ H.i {className: "glyphicon glyphicon-calendar"} []
, H.text $ " " <> date
]
]
, p [] [ i [className "glyphicon glyphicon-user"] []
, H.p {}
, text $ " " <> user
[ H.i {className: "glyphicon glyphicon-user"} []
, H.text $ " " <> user
]
]
]
]
]
]
]
]
]
]
tableSpec :: Spec State Props Action
table :: Record Props -> R.Element
tableSpec = simpleSpec performAction render
table props = R.createElement tableCpt props []
tableCpt :: R.Component Props
tableCpt = R.hooksComponent "Table" cpt
where
where
modifyStateAndReload :: (State -> State) -> Props -> State -> StateCoTransformer State Unit
cpt {container, colNames, totalRecords, rows, setParams} _ = do
modifyStateAndReload f {setParams} state = do
(pageSize /\ setPageSize) <- R.useState' PS10
--logs "modifyStateAndReload" -- TODO rename
(page /\ setPage) <- R.useState' 1
modifyState_ f
(orderBy /\ setOrderBy) <- R.useState' Nothing
liftEffect $ setParams $ stateParams $ f state
let state = {pageSize, orderBy, page}
let ps = pageSizes2Int pageSize
performAction :: PerformAction State Props Action
let totalPages = (totalRecords / ps) + min 1 (totalRecords `mod` ps)
performAction (ChangePageSize ps) =
R.useEffect1' state $ setParams (stateParams state)
modifyStateAndReload $ changePageSize ps
pure $ container
performAction (ChangePage p) =
{ pageSizeControl: sizeDD pageSize setPageSize
modifyStateAndReload $ _ { currentPage = p }
, pageSizeDescription: textDescription page pageSize totalRecords
performAction (ChangeOrderBy mc) =
, paginationLinks: pagination setPage totalPages page
modifyStateAndReload $ _ { orderBy = mc }
, tableHead: H.tr {} (colHeader setOrderBy orderBy <$> colNames)
, tableBody: map (H.tr {} <<< map (\c -> H.td {} [c]) <<< _.row) rows
renderColHeader :: (OrderBy -> Effect Unit)
}
-> OrderBy
colHeader :: (R2.Setter OrderBy) -> OrderBy -> ColumnName -> R.Element
-> ColumnName -> ReactElement
colHeader setOrderBy currentOrderBy c = H.th {scope: "col"} [ H.b {} cs ]
renderColHeader changeOrderBy currentOrderBy c =
th [scope "col"] [ b' cs ]
where
where
lnk mc = effectLink (
changeOrderBy mc
)
lnk mc = effectLink (
setOrderBy (const mc)
)
cs :: Array R
eact
Element
cs :: Array R
.
Element
cs =
cs =
case currentOrderBy of
case currentOrderBy of
Just (ASC d) | c == d -> [lnk (Just (DESC c)) "DESC ", lnk Nothing (columnName c)]
Just (ASC d) | c == d -> [lnk (Just (DESC c)) "DESC ", lnk Nothing (columnName c)]
Just (DESC d) | c == d -> [lnk (Just (ASC c)) "ASC ", lnk Nothing (columnName c)]
Just (DESC d) | c == d -> [lnk (Just (ASC c)) "ASC ", lnk Nothing (columnName c)]
_ -> [lnk (Just (ASC c)) (columnName c)]
_ -> [lnk (Just (ASC c)) (columnName c)]
render :: Render State Props Action
defaultContainer :: {title :: String} -> Record TableContainerProps -> R.Element
render dispatch {container, colNames, totalRecords, rows}
defaultContainer {title} props = R.fragment
{pageSize, currentPage, orderBy} _ =
[ H.div {className: "row"}
container
[ H.div {className: "col-md-4"} [ props.pageSizeDescription ]
{ pageSizeControl: sizeDD pageSize dispatch
, H.div {className: "col-md-4"} [ props.paginationLinks ]
, pageSizeDescription: textDescription currentPage pageSize totalRecords
, H.div {className: "col-md-4"} [ props.pageSizeControl ]
, paginationLinks: pagination (dispatch <<< ChangePage) totalPages currentPage
, tableHead:
tr [] (renderColHeader (dispatch <<< ChangeOrderBy) orderBy <$> colNames)
, tableBody:
map (tr [] <<< map (\c -> td [] [c]) <<< _.row) rows
}
where
ps = pageSizes2Int pageSize
totalPages = (totalRecords / ps) + min 1 (totalRecords `mod` ps)
defaultContainer :: {title :: String} -> TableContainerProps -> Array ReactElement
defaultContainer {title} props =
[ div [className "row"]
[ div [className "col-md-4"] [props.pageSizeDescription]
, div [className "col-md-4"] [props.paginationLinks]
, div [className "col-md-4"] [props.pageSizeControl]
]
]
,
table [ className "table"]
,
H.table {className: "table"}
[
thead [className "thead-dark"]
[ props.tableHead ]
[
H.thead {className: "thead-dark"}
[ props.tableHead ]
,
tbody []
props.tableBody
,
H.tbody {}
props.tableBody
]
]
]
]
-- TODO: this needs to be in Gargantext.Pages.Corpus.Graph.Tabs
-- TODO: this needs to be in Gargantext.Pages.Corpus.Graph.Tabs
graphContainer :: {title :: String} ->
TableContainerProps -> Array React
Element
graphContainer :: {title :: String} ->
Record TableContainerProps -> R.
Element
graphContainer {title} props =
graphContainer {title} props =
[
-- TODO title in tabs name (above)
-- TODO title in tabs name (above)
table [ className "table"]
H.table {className: "table"}
[ thead [className "thead-dark"]
[ props.tableHead ]
[ H.thead {className: "thead-dark"}
[ props.tableHead ]
, tbody []
props.tableBody
, H.tbody {}
props.tableBody
]
]
-- TODO better rendering of the paginationLinks
-- TODO better rendering of the paginationLinks
-- , props.pageSizeControl
-- , props.pageSizeControl
-- , props.pageSizeDescription
-- , props.pageSizeDescription
-- , props.paginationLinks
-- , props.paginationLinks
]
sizeDD :: PageSizes -> R2.Setter PageSizes -> R.Element
stateParams :: State -> Params
sizeDD ps setPageSize = H.span {} [ R2.select { className, on: {change} } sizes ]
stateParams {pageSize, currentPage, orderBy} = {offset, limit, orderBy}
where
where
limit = pageSizes2Int pageSize
className = "form-control"
offset = limit * (currentPage - 1)
change e = setPageSize $ const (string2PageSize $ R2.unsafeEventValue e)
sizes = map (optps ps) pageSizes
paramsState :: Params -> State
paramsState {offset, limit, orderBy} = {pageSize, currentPage, orderBy}
where
pageSize = string2PageSize $ show limit
currentPage = (offset / limit) + 1
tableClass :: ReactClass {children :: Children | Props'}
tableClass = createClass "Table" tableSpec (const initialState)
tableElt :: Props -> ReactElement
tableElt props = createElement tableClass props []
tableEltWithInitialState :: State -> Props -> ReactElement
textDescription :: Int -> PageSizes -> Int -> R.Element
tableEltWithInitialState state props = createElement tc props []
textDescription currPage pageSize totalRecords =
where
H.div {className: "row1"} [ H.div {className: ""} [ H.text msg ] ] -- TODO or col-md-6 ?
tc = createClass "Table" tableSpec (const state)
sizeDD :: PageSizes -> (Action -> Effect Unit) -> ReactElement
sizeDD ps d
= span []
[ select [ className "form-control"
, defaultValue $ show ps
, onChange $ \e -> d (ChangePageSize $ string2PageSize $ R2.unsafeEventValue e)
] $ map (optps ps) aryPS
]
textDescription :: Int -> PageSizes -> Int -> ReactElement
textDescription currPage pageSize totalRecords
= div [className "row1"]
[ div [className ""] -- TODO or col-md-6 ?
[ text $ "Showing " <> show start <> " to " <> show end <> " of " <> show totalRecords ]
]
where
where
start = (currPage - 1) * pageSizes2Int pageSize + 1
start = (currPage - 1) * pageSizes2Int pageSize + 1
end' = currPage * pageSizes2Int pageSize
end' = currPage * pageSizes2Int pageSize
end = if end' > totalRecords then totalRecords else end'
end = if end' > totalRecords then totalRecords else end'
msg = "Showing " <> show start <> " to " <> show end <> " of " <> show totalRecords
effectLink :: Effect Unit -> String -> R
eact
Element
effectLink :: Effect Unit -> String -> R
.
Element
effectLink eff msg =
a [onClick $ const eff] [
text msg]
effectLink eff msg =
H.a {on: {click: const eff}} [H.
text msg]
pagination ::
ChangePageAction -> Int -> Int -> React
Element
pagination ::
(R2.Setter Int) -> Int -> Int -> R.
Element
pagination changePage tp cp
pagination changePage tp cp
=
= span []
$
H.span {}
$
[ text " ", prev, first, ldots]
[
H.
text " ", prev, first, ldots]
<>
<>
lnums
lnums
<>
<>
[
b' [
text $ " " <> show cp <> " "]]
[
H.b {} [H.
text $ " " <> show cp <> " "]]
<>
<>
rnums
rnums
<>
<>
[ rdots, last, next ]
[ rdots, last, next ]
where
where
prev = if cp == 1 then
prev = if cp == 1 then
text " Prev. "
H.
text " Prev. "
else
else
changePageLink (cp - 1) "Prev."
changePageLink (cp - 1) "Prev."
next = if cp == tp then
next = if cp == tp then
text " Next "
H.
text " Next "
else
else
changePageLink (cp + 1) "Next"
changePageLink (cp + 1) "Next"
first = if cp == 1 then
first = if cp == 1 then
text ""
H.
text ""
else
else
changePageLink' 1
changePageLink' 1
last = if cp == tp then
last = if cp == tp then
text ""
H.
text ""
else
else
changePageLink' tp
changePageLink' tp
ldots = if cp >= 5 then
ldots = if cp >= 5 then
text " ... "
H.
text " ... "
else
else
text ""
H.
text ""
rdots = if cp + 3 < tp then
rdots = if cp + 3 < tp then
text " ... "
H.
text " ... "
else
else
text ""
H.
text ""
lnums = map changePageLink' $ filter (1 < _) [cp - 2, cp - 1]
lnums = map changePageLink' $ filter (1 < _) [cp - 2, cp - 1]
rnums = map changePageLink' $ filter (tp > _) [cp + 1, cp + 2]
rnums = map changePageLink' $ filter (tp > _) [cp + 1, cp + 2]
changePageLink :: Int -> String -> ReactElement
changePageLink :: Int -> String -> R.Element
changePageLink i s = span []
changePageLink i s =
[ text " "
H.span {}
, effectLink (changePage i) s
[ H.text " "
, text " "
, effectLink (changePage (const i)) s
, H.text " "
]
]
changePageLink' :: Int -> R
eact
Element
changePageLink' :: Int -> R
.
Element
changePageLink' i = changePageLink i (show i)
changePageLink' i = changePageLink i (show i)
data PageSizes = PS10 | PS20 | PS50 | PS100 | PS200
data PageSizes = PS10 | PS20 | PS50 | PS100 | PS200
...
@@ -316,8 +269,8 @@ pageSizes2Int PS50 = 50
...
@@ -316,8 +269,8 @@ pageSizes2Int PS50 = 50
pageSizes2Int PS100 = 100
pageSizes2Int PS100 = 100
pageSizes2Int PS200 = 200
pageSizes2Int PS200 = 200
aryPS
:: Array PageSizes
pageSizes
:: Array PageSizes
aryPS
= [PS10, PS20, PS50, PS100, PS200]
pageSizes
= [PS10, PS20, PS50, PS100, PS200]
string2PageSize :: String -> PageSizes
string2PageSize :: String -> PageSizes
string2PageSize "10" = PS10
string2PageSize "10" = PS10
...
@@ -327,5 +280,5 @@ string2PageSize "100" = PS100
...
@@ -327,5 +280,5 @@ string2PageSize "100" = PS100
string2PageSize "200" = PS200
string2PageSize "200" = PS200
string2PageSize _ = PS10
string2PageSize _ = PS10
optps :: PageSizes -> PageSizes -> R
eact
Element
optps :: PageSizes -> PageSizes -> R
.
Element
optps cv val =
option [ value $ show val ] [text $ show
val]
optps cv val =
H.option {selected: (cv == val), value: show val} [R2.showText
val]
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