[Loader2] upgrade some loaders

parent 5735f12b
......@@ -8,6 +8,8 @@ import Effect.Class (liftEffect)
import Effect.Exception (error)
import Reactix as R
type Props path loaded = { path :: path, loaded :: loaded }
type State path loaded = { currentPath :: path, loaded :: Maybe loaded }
useLoader
......@@ -16,7 +18,7 @@ useLoader
=> Show path
=> path
-> (path -> Aff loaded)
-> (path -> loaded -> R.Element)
-> (Props path loaded -> R.Element)
-> R.Hooks R.Element
useLoader newPath loader render = do
{currentPath, loaded} /\ setState <- R.useState' { currentPath: newPath, loaded: Nothing }
......@@ -37,4 +39,4 @@ useLoader newPath loader render = do
-- TODO load spinner
R.fragment []
Just loadedData ->
render currentPath loadedData
render {path: currentPath, loaded: loadedData}
......@@ -298,14 +298,17 @@ ngramsTableClass :: Loader.InnerClass PageParams VersionedNgramsTable
ngramsTableClass = createClass "NgramsTable" ngramsTableSpec initialState
type MainNgramsTableProps =
Loader.InnerProps Int { defaultListId :: Int }
( tabType :: TabType )
{ nodeId :: Int
-- ^ This node can be a corpus or contact.
, defaultListId :: Int
, tabType :: TabType
}
mainNgramsTableSpec :: Spec {} MainNgramsTableProps Void
mainNgramsTableSpec = simpleSpec defaultPerformAction render
where
render :: Render {} MainNgramsTableProps Void
render _ {path: nodeId, loaded: {defaultListId}, tabType} _ _ =
render _ {nodeId, defaultListId, tabType} _ _ =
[ ngramsLoader
{ path: initialPageParams nodeId [defaultListId] tabType
, component: ngramsTableClass
......
......@@ -87,6 +87,7 @@ import Gargantext.Components.Loader as Loader
type CoreParams s =
{ nodeId :: Int
-- ^ This node can be a corpus or contact.
, listIds :: Array Int
, tabType :: TabType
| s
......
......@@ -184,7 +184,7 @@ treeLoadView setReload p = R.createElement el p []
where
el = R.hooksComponent "TreeLoadView" cpt
cpt {root, mCurrentRoute} _ = do
useLoader root loadNode $ \currentPath loaded ->
useLoader root loadNode $ \{loaded} ->
loadedTreeView setReload {tree: loaded, mCurrentRoute}
treeview :: Spec {} Props Void
......
......@@ -16,20 +16,20 @@ import Data.Newtype (unwrap)
import Data.String (joinWith)
import Effect.Aff (Aff, throwError)
import Effect.Exception (error)
import Thermite (Render, Spec, defaultPerformAction, simpleSpec, createClass)
import Thermite (Render, Spec, defaultPerformAction, simpleSpec)
import React as React
import React (ReactClass, ReactElement)
import React.DOM (div, h3, img, li, span, text, ul, text)
import React.DOM.Props (_id, className, src)
import Reactix as R
import Gargantext.Prelude
import Gargantext.Config (toUrl, End(..), NodeType(..), Path(..))
import Gargantext.Config.REST (get)
import Gargantext.Components.Node (NodePoly(..), HyperdataList(..))
import Gargantext.Components.Loader as Loader
import Gargantext.Components.Loader2 (useLoader)
import Gargantext.Pages.Annuaire.User.Contacts.Types
import Gargantext.Pages.Annuaire.User.Contacts.Tabs.Specs as Tabs
--type Props = Loader.InnerProps Int Contact
import Gargantext.Utils.Reactix as R2
display :: String -> Array ReactElement -> Array ReactElement
display title elems =
......@@ -153,30 +153,16 @@ infoRender (Tuple title content) =
-- | Below an example of a loader, use all code below and adapt it
-- to your code
-- layoutUser is exported by the module
-- only one subnode: contactLoader which as 2 parameters
-- - path (nodeId)
-- - components (which has to be drawn when loaded
layoutUser :: Spec {} {nodeId :: Int} Void
layoutUser = simpleSpec defaultPerformAction render
where
render :: Render {} {nodeId :: Int} Void
render _ {nodeId} _ _ =
[ contactLoader { path: nodeId
, component: createClass "LayoutUser" layoutUser' (const {})
} ]
-- | Take the spec and transform it in React Class
-- put here how to draw the Composant
-- props loaded: what has been loaded by the component loader
layoutUser' :: Spec {} Props Void
layoutUser' = simpleSpec defaultPerformAction render
<> Tabs.pureTabs
where
render :: Render {} Props Void
render dispatch {loaded: {contactNode: Contact {name, hyperdata}}} _ _ =
[ ul [className "col-md-12 list-group"] $
display (fromMaybe "no name" name) (contactInfos hyperdata)
]
layoutUser =
R2.elSpec $ R.hooksComponent "LayoutUser" \{nodeId} _ ->
useLoader nodeId getContact $ \{loaded: contactData} ->
let {contactNode: Contact {name, hyperdata}} = contactData in
R2.toElement
[ ul [className "col-md-12 list-group"] $
display (fromMaybe "no name" name) (contactInfos hyperdata)
, Tabs.elt {nodeId, contactData}
]
-- | toUrl to get data
getContact :: Int -> Aff ContactData
......@@ -190,11 +176,3 @@ getContact id = do
-- Nothing ->
-- throwError $ error "Missing default list"
pure {contactNode, defaultListId: 424242}
-- | Change name for you
contactLoaderClass :: ReactClass (Loader.Props Int ContactData)
contactLoaderClass = Loader.createLoaderClass "ContactLoader" getContact
-- | Change type according to what has been loaded
contactLoader :: Loader.Props' Int ContactData -> ReactElement
contactLoader props = React.createElement contactLoaderClass props []
......@@ -13,8 +13,10 @@ import Gargantext.Config (TabType(..), TabSubType(..), PTabNgramType(..))
import Gargantext.Components.DocsTable as DT
import Gargantext.Components.NgramsTable as NT
import Gargantext.Components.Tab as Tab
import Gargantext.Pages.Annuaire.User.Contacts.Types (Props)
import Thermite (Spec, focus, hideState, noState, cmapProps)
import Gargantext.Pages.Annuaire.User.Contacts.Types (ContactData)
import React (Children, ReactElement, ReactClass, createElement)
import Thermite (Spec, focus, hideState, noState, cmapProps, createClass)
data Mode = Patents | Books | Communication
......@@ -30,6 +32,19 @@ modeTabType Patents = PTabPatents
modeTabType Books = PTabBooks
modeTabType Communication = PTabCommunication
type PropsRow =
( nodeId :: Int
, contactData :: ContactData
)
type Props = Record PropsRow
elt :: Props -> ReactElement
elt props = createElement tabsClass props []
tabsClass :: ReactClass { children :: Children | PropsRow }
tabsClass = createClass "ContactsTabs" pureTabs (const {})
pureTabs :: Spec {} Props Void
pureTabs = hideState (const {activeTab: 0}) statefulTabs
......@@ -45,18 +60,18 @@ statefulTabs =
where
chart = mempty
-- TODO totalRecords
docs = cmapProps (\{path: nodeId, loaded} ->
docs = cmapProps (\{nodeId, contactData: {defaultListId}} ->
{ nodeId, chart
, tabType: TabPairing TabDocs
, totalRecords: 4736
, listId: loaded.defaultListId
, listId: defaultListId
, corpusId: Nothing}) $
noState DT.docViewSpec
ngramsViewSpec :: {mode :: Mode} -> Spec Tab.State Props Tab.Action
ngramsViewSpec {mode} =
cmapProps (\{loaded: {defaultListId}, path, dispatch} ->
{loaded: {defaultListId}, path, dispatch, tabType})
cmapProps (\{contactData: {defaultListId}, nodeId} ->
{defaultListId, nodeId, tabType})
(noState NT.mainNgramsTableSpec)
where
tabType = TabPairing $ TabNgramType $ modeTabType mode
......@@ -162,13 +162,9 @@ instance decodeUser :: DecodeJson Contact where
name <- obj .?? "name"
date <- obj .?| "date"
hyperdata <- obj .? "hyperdata"
pure $ Contact { id, typename, userId
, parentId, name, date
, hyperdata
}
type ContactData = {contactNode :: Contact, defaultListId :: Int}
type PropsRow = Loader.InnerPropsRow Int ContactData ()
type Props = Record PropsRow
module Gargantext.Pages.Corpus where
import Data.Array (head)
import Data.Maybe (Maybe(..))
import Effect.Aff (Aff, throwError)
import Effect.Exception (error)
import React as React
import React (ReactClass, ReactElement)
import Thermite (Spec, Render, simpleSpec, createClass, defaultPerformAction)
import Reactix as R
import Thermite (Spec)
--------------------------------------------------------
import Gargantext.Prelude
import Gargantext.Components.Node (NodePoly(..), HyperdataList(..))
import Gargantext.Components.Loader as Loader
import Gargantext.Components.Loader (createLoaderClass)
import Gargantext.Components.Node (NodePoly(..), HyperdataList)
import Gargantext.Components.Loader2 (useLoader)
import Gargantext.Components.Table as Table
import Gargantext.Config (toUrl, Path(..), NodeType(..), End(..))
import Gargantext.Config.REST (get)
import Gargantext.Pages.Corpus.Tabs.Types (CorpusData, CorpusInfo(..))
import Gargantext.Pages.Corpus.Tabs.Types (Props) as Tabs
import Gargantext.Pages.Corpus.Tabs.Specs (pureTabs) as Tabs
-------------------------------------------------------------------
type Props = Tabs.Props
import Gargantext.Pages.Corpus.Tabs.Specs (elt) as Tabs
import Gargantext.Utils.Reactix as R2
------------------------------------------------------------------------
layout :: Spec {} {nodeId :: Int} Void
layout = simpleSpec defaultPerformAction render
where
render :: Render {} {nodeId :: Int} Void
render _ {nodeId} _ _ =
[ corpusLoader { path: nodeId
, component: createClass "Layout" layout' (const {})
} ]
layout' :: Spec {} Props Void
layout' = corpusHeaderSpec <> Tabs.pureTabs
corpusHeaderSpec :: Spec {} Props Void
corpusHeaderSpec = simpleSpec defaultPerformAction render
where
render :: Render {} Props Void
render dispatch {loaded: {corpusNode}} _ _ =
Table.renderTableHeaderLayout
{ title: "Corpus " <> title
, desc: corpus.desc
, query: corpus.query
, date: date'
, user: corpus.authors
}
where
NodePoly { name: title
, date: date'
, hyperdata : CorpusInfo corpus
}
= corpusNode
layout =
R2.elSpec $ R.hooksComponent "CorpusLoader" \{nodeId} _ ->
useLoader nodeId getCorpus $ \{path: corpusId
,loaded: corpusData} ->
let {corpusNode:
NodePoly { name: title
, date: date'
, hyperdata: CorpusInfo corpus
}
} = corpusData in
R2.toElement $
Table.renderTableHeaderLayout
{ title: "Corpus " <> title
, desc: corpus.desc
, query: corpus.query
, date: date'
, user: corpus.authors
}
<> [Tabs.elt {corpusId, corpusData}]
------------------------------------------------------------------------
getCorpus :: Int -> Aff CorpusData
......@@ -65,9 +49,3 @@ getCorpus corpusId = do
pure {corpusNode, defaultListId}
Nothing ->
throwError $ error "Missing default list"
corpusLoaderClass :: ReactClass (Loader.Props Int CorpusData)
corpusLoaderClass = createLoaderClass "CorpusLoader" getCorpus
corpusLoader :: Loader.Props' Int CorpusData -> ReactElement
corpusLoader props = React.createElement corpusLoaderClass props []
......@@ -6,23 +6,23 @@ import Data.Generic.Rep.Show (genericShow)
import Data.Map as Map
import Data.Maybe (Maybe(..), maybe)
import Effect.Aff (Aff)
import React (ReactElement, ReactClass)
import React as React
import React (ReactClass, Children)
import React.DOM (div, h4, li, p, span, text, ul)
import React.DOM.Props (className)
import Thermite (PerformAction, Render, Spec, simpleSpec, cmapProps, defaultPerformAction, createClass)
import Reactix as R
import Thermite (PerformAction, Render, Spec, simpleSpec, cmapProps, createClass)
import Control.Monad.Trans.Class (lift)
import Gargantext.Prelude
import Gargantext.Config (toUrl, NodeType(..), End(..), TabSubType(..), TabType(..), CTabNgramType(..))
import Gargantext.Config.REST (get)
import Gargantext.Components.AutoUpdate (autoUpdateElt)
import Gargantext.Components.Loader as Loader
import Gargantext.Components.Loader2 (useLoader)
import Gargantext.Components.Node (NodePoly(..))
import Gargantext.Components.NgramsTable.Core
import Gargantext.Components.Annotation.AnnotatedField as AnnotatedField
import Gargantext.Types (TermList)
import Gargantext.Utils.Reactix ( scuff )
import Gargantext.Utils.Reactix as R2
type DocPath = { nodeId :: Int, listIds :: Array Int, corpusId :: Maybe Int, tabType :: TabType }
......@@ -32,7 +32,10 @@ type LoadedData =
{ document :: NodeDocument
, ngramsTable :: VersionedNgramsTable }
type LoadedDataProps = Loader.InnerProps DocPath LoadedData ()
type Props =
{ loaded :: LoadedData
, path :: DocPath
}
-- This is a subpart of NgramsTable.State.
type State = CoreState ()
......@@ -273,10 +276,10 @@ instance decodeDocument :: DecodeJson Document
--, text
}
docViewSpec :: Spec State LoadedDataProps Action
docViewSpec :: Spec State Props Action
docViewSpec = simpleSpec performAction render
where
performAction :: PerformAction State LoadedDataProps Action
performAction :: PerformAction State Props Action
performAction Refresh {path: {nodeId, listIds, tabType}} {ngramsVersion} = do
commitPatch {nodeId, listIds, tabType} (Versioned {version: ngramsVersion, data: mempty})
performAction (SetTermListItem n pl) {path: {nodeId, listIds, tabType}} {ngramsVersion} =
......@@ -287,10 +290,8 @@ docViewSpec = simpleSpec performAction render
performAction (AddNewNgram ngram termList) {path: params} _ =
lift $ addNewNgram ngram (Just termList) params
render :: Render State LoadedDataProps Action
render dispatch { path: pageParams
, loaded: { ngramsTable: Versioned { data: initTable }, document }
, dispatch: loaderDispatch }
render :: Render State Props Action
render dispatch { loaded: { ngramsTable: Versioned { data: initTable }, document } }
{ ngramsTablePatch }
_reactChildren =
[ autoUpdateElt { duration: 3000
......@@ -327,23 +328,27 @@ docViewSpec = simpleSpec performAction render
ngramsTable = applyNgramsTablePatch ngramsTablePatch initTable
setTermList ngram Nothing newList = dispatch $ AddNewNgram ngram newList
setTermList ngram (Just oldList) newList = dispatch $ SetTermListItem ngram (replace oldList newList)
annotate text = scuff $ AnnotatedField.annotatedField { ngrams: ngramsTable, setTermList, text }
annotate text = R2.scuff $ AnnotatedField.annotatedField { ngrams: ngramsTable, setTermList, text }
li' = li [className "list-group-item justify-content-between"]
text' x = text $ maybe "Nothing" identity x
badge s = span [className "badge badge-default badge-pill"] [text s]
NodePoly {hyperdata : Document doc} = document
docViewClass :: ReactClass
{ children :: Children
, loaded :: LoadedData
, path :: DocPath
}
docViewClass = createClass "DocumentView" docViewSpec initialState
layout :: Spec {} {nodeId :: Int, listId :: Int, corpusId :: Maybe Int} Void
layout = cmapProps (\{nodeId, listId, corpusId} -> {nodeId, listIds: [listId], corpusId, tabType})
$ simpleSpec defaultPerformAction render
layout =
cmapProps (\{nodeId, listId, corpusId} -> {nodeId, listIds: [listId], corpusId, tabType}) $
R2.elSpec $ R.hooksComponent "DocumentLoader" \path _ ->
useLoader path loadData $ \props ->
R2.createElement' docViewClass props []
where
tabType = TabDocument (TabNgramType CTabTerms)
render :: Render {} DocPath Void
render _ path _ _ =
[ documentLoader
{ path
, component: createClass "DocumentView" docViewSpec initialState
} ]
------------------------------------------------------------------------
......@@ -363,9 +368,3 @@ loadData {nodeId, listIds, tabType} = do
, termSizeFilter : Nothing
}
pure {document, ngramsTable}
documentLoaderClass :: ReactClass (Loader.Props DocPath LoadedData)
documentLoaderClass = Loader.createLoaderClass "DocumentLoader" loadData
documentLoader :: Loader.Props' DocPath LoadedData -> ReactElement
documentLoader props = React.createElement documentLoaderClass props []
......@@ -9,7 +9,7 @@ import Data.Maybe (Maybe(..))
import Data.Tuple (Tuple(..))
import Gargantext.Config (CTabNgramType(..), End(..), Path(..), TabSubType(..), TabType(..), toUrl)
import Gargantext.Pages.Corpus.Tabs.Types (Props)
import Gargantext.Pages.Corpus.Tabs.Types (Props, PropsRow)
import Gargantext.Pages.Corpus.Chart.Histo (histoSpec)
import Gargantext.Pages.Corpus.Chart.Metrics (metricsSpec)
......@@ -21,10 +21,11 @@ import Gargantext.Components.NgramsTable as NT
import Gargantext.Components.Charts.Options.ECharts (chart) as ECharts
import Gargantext.Components.DocsTable as DT
import Gargantext.Components.Tab as Tab
import Gargantext.Utils.Reactix as R2
import React (ReactElement)
import React (ReactElement, ReactClass, createElement, Children)
import React.DOM (div)
import Thermite (Spec, hideState, noState, cmapProps)
import Thermite (Spec, hideState, noState, cmapProps, createClass)
data Mode = Authors | Sources | Institutes | Terms
......@@ -41,6 +42,12 @@ modeTabType Sources = CTabSources
modeTabType Institutes = CTabInstitutes
modeTabType Terms = CTabTerms
elt :: Props -> ReactElement
elt props = createElement tabsClass props []
tabsClass :: ReactClass { children :: Children | PropsRow }
tabsClass = createClass "CorpusTabs" pureTabs (const {})
pureTabs :: Spec {} Props Void
pureTabs = hideState (const {activeTab: 0}) statefulTabs
......@@ -58,43 +65,44 @@ statefulTabs =
where
-- TODO totalRecords
docs = noState ( cmapProps (\{path: corpusId} -> {corpusId, tabType: TabCorpus TabDocs}) histoSpec
docs = noState ( cmapProps (\{corpusId} -> {corpusId, tabType: TabCorpus TabDocs}) histoSpec
<>
(cmapProps (\{path: nodeId, loaded} ->
{ nodeId
(cmapProps (\{corpusId, corpusData: {defaultListId}} ->
{ nodeId: corpusId
-- ^ TODO merge nodeId and corpusId in DT
, chart : div [][]
, tabType: TabCorpus TabDocs
, totalRecords: 4737
, listId: loaded.defaultListId
, corpusId: Just nodeId}) $ noState DT.docViewSpec
, listId: defaultListId
, corpusId: Just corpusId}) $ noState DT.docViewSpec
)
)
trash = cmapProps (\{path: nodeId, loaded} ->
{ nodeId
trash = cmapProps (\{corpusId, corpusData: {defaultListId}} ->
{ nodeId: corpusId
, chart: div [][]
, tabType: TabCorpus TabTrash
, totalRecords: 4736
, listId: loaded.defaultListId
, listId: defaultListId
, corpusId: Nothing}) $ noState DT.docViewSpec
ngramsViewSpec :: {mode :: Mode} -> Spec Tab.State Props Tab.Action
ngramsViewSpec {mode} =
noState ( (chart mode) <>
cmapProps (\{loaded: {defaultListId}, path, dispatch} ->
{loaded: {defaultListId}, path, dispatch, tabType})
noState $ chart mode <>
cmapProps (\{corpusData: {defaultListId}, corpusId: nodeId} ->
{defaultListId, nodeId, tabType})
NT.mainNgramsTableSpec
)
where
tabType = TabCorpus $ TabNgramType $ modeTabType mode
chart Authors = cmapProps (\{path: corpusId} -> {corpusId, tabType}) pieSpec
chart Sources = cmapProps (\{path: corpusId} -> {corpusId, tabType}) barSpec
chart Authors = cmapProps (\{corpusId} -> {corpusId, tabType}) pieSpec
chart Sources = cmapProps (\{corpusId} -> {corpusId, tabType}) barSpec
chart Institutes = cmapProps (\{loaded: {defaultListId}, path: corpusId} ->
chart Institutes = cmapProps (\{corpusData: {defaultListId}, corpusId} ->
{corpusId, listId: defaultListId, tabType, limit: (Just 1000)})
treeSpec
chart Terms = cmapProps (\{loaded: {defaultListId}, path: corpusId} ->
chart Terms = cmapProps (\{corpusData: {defaultListId}, corpusId} ->
{corpusId, listId: defaultListId, tabType, limit: (Just 1000)})
-- TODO limit should be select in the chart by default it is 1000
metricsSpec
......@@ -45,8 +45,7 @@ instance decodeCorpusInfo :: DecodeJson CorpusInfo where
type CorpusData = {corpusNode :: NodePoly CorpusInfo, defaultListId :: Int}
-- TODO type Props = {nodeId :: Int, info :: Maybe (NodePoly CorpusInfo) }
type PropsRow = Loader.InnerPropsRow Int CorpusData ()
type PropsRow = ( corpusId :: Int, corpusData :: CorpusData )
type Props = Record PropsRow
-- TODO include Gargantext.Pages.Corpus.Tabs.States
......
......@@ -12,7 +12,8 @@ import Data.Tuple.Nested ((/\))
import Effect (Effect)
import Effect.Uncurried (EffectFn1, mkEffectFn1)
import FFI.Simple ((...), defineProperty)
import React (ReactElement)
import React (ReactClass, ReactElement, Children, class IsReactElement, class ReactPropFields)
import React as React
import Reactix as R
import Reactix.DOM.HTML (ElemFactory)
import Reactix.React (createDOMElement)
......@@ -21,7 +22,7 @@ import Thermite (Spec, simpleSpec, Render, defaultPerformAction)
import Unsafe.Coerce (unsafeCoerce)
newtype Point = Point { x :: Number, y :: Number }
-- | Turns a ReactElement into a Reactix Element
-- | Turns a ReactElement into aReactix Element
-- | buff (v.) to polish
buff :: ReactElement -> R.Element
buff = unsafeCoerce
......@@ -31,6 +32,23 @@ buff = unsafeCoerce
scuff :: R.Element -> ReactElement
scuff = unsafeCoerce
class ToElement a where
toElement :: a -> R.Element
instance toElementElement :: ToElement R.Element where
toElement = identity
instance toElementReactElement :: ToElement ReactElement where
toElement = buff
instance toElementArray :: ToElement a => ToElement (Array a) where
toElement = R.fragment <<< map toElement
{-
instance isReactElementElement :: IsReactElement R.Element where
toElement = scuff
-}
elSpec :: forall component props
. R.IsComponent component props (Array R.Element)
=> component -> Spec {} (Record props) Void
......@@ -39,6 +57,22 @@ elSpec cpt = simpleSpec defaultPerformAction render
render :: Render {} (Record props) Void
render _ props _ children = [scuff $ R.createElement cpt props (buff <$> children)]
createElement' :: forall required given
. ReactPropFields required given
=> ReactClass { children :: Children | required }
-> Record given -> Array R.Element -> R.Element
createElement' reactClass props children =
buff $ React.createElement reactClass props $ scuff <$> children
{-
instance isComponentReactClass
:: R.IsComponent (ReactClass { children :: Children
| props
}) props (Array R.Element) where
createElement reactClass props children =
React.createElement reactClass props children
-}
mousePosition :: RE.SyntheticEvent DE.MouseEvent -> Point
mousePosition e = Point { x: RE.clientX e, y: RE.clientY e }
......
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