Commit 68298c5b authored by Przemyslaw Kaminski's avatar Przemyslaw Kaminski

[toestand] ngramsTable: state is a box now

parent c5b11698
...@@ -271,7 +271,7 @@ type Props = ...@@ -271,7 +271,7 @@ type Props =
( cacheState :: NT.CacheState ( cacheState :: NT.CacheState
, mTotalRows :: Maybe Int , mTotalRows :: Maybe Int
, path :: T.Box PageParams , path :: T.Box PageParams
, state :: R.State State , state :: T.Box State
, versioned :: VersionedNgramsTable , versioned :: VersionedNgramsTable
| CommonProps | CommonProps
) )
...@@ -288,15 +288,12 @@ loadedNgramsTableCpt = here.component "loadedNgramsTable" cpt where ...@@ -288,15 +288,12 @@ loadedNgramsTableCpt = here.component "loadedNgramsTable" cpt where
, reloadForest , reloadForest
, reloadRoot , reloadRoot
, sidePanelTriggers , sidePanelTriggers
, state: (state@{ ngramsChildren , state
, ngramsLocalPatch
, ngramsParent
, ngramsSelection
, ngramsVersion } /\ setState)
, tabNgramType , tabNgramType
, tasks , tasks
, versioned: Versioned { data: initTable } , versioned: Versioned { data: initTable }
, withAutoUpdate } _ = do , withAutoUpdate } _ = do
state'@{ ngramsChildren, ngramsLocalPatch, ngramsParent, ngramsSelection, ngramsVersion } <- T.useLive T.unequal state
path'@{ listIds, params, scoreType, termListFilter, termSizeFilter } <- T.useLive T.unequal path path'@{ listIds, params, scoreType, termListFilter, termSizeFilter } <- T.useLive T.unequal path
params <- T.useFocused (_.params) (\a b -> b { params = a }) path params <- T.useFocused (_.params) (\a b -> b { params = a }) path
params'@{ orderBy } <- T.useLive T.unequal params params'@{ orderBy } <- T.useLive T.unequal params
...@@ -306,26 +303,40 @@ loadedNgramsTableCpt = here.component "loadedNgramsTable" cpt where ...@@ -306,26 +303,40 @@ loadedNgramsTableCpt = here.component "loadedNgramsTable" cpt where
-- R.useEffectOnce' $ do -- R.useEffectOnce' $ do
-- T.listen (\_ -> TT.changePage 1 params) searchQuery -- T.listen (\_ -> TT.changePage 1 params) searchQuery
let rows :: PreConversionRows let ngramsTable = applyNgramsPatches state' initTable
rows = orderWith ( roots = rootsOf ngramsTable
Seq.mapMaybe (\(Tuple ng nre) ->
let Additive s = ng_scores ^. at ng <<< _Just in rowMap (Tuple ng nre) =
addOcc <$> rowsFilter (ngramsRepoElementToNgramsElement ng s nre)) $ let ng_scores :: Map NgramsTerm (Additive Int)
ng_scores = ngramsTable ^. _NgramsTable <<< _ngrams_scores
Additive s = ng_scores ^. at ng <<< _Just
addOcc ne =
let Additive occurrences = sumOccurrences ngramsTable (ngramsElementToNgramsOcc ne) in
ne # _NgramsElement <<< _occurrences .~ occurrences
in
addOcc <$> rowsFilter (ngramsRepoElementToNgramsElement ng s nre)
rows :: PreConversionRows
rows = ngramsTableOrderWith orderBy (
Seq.mapMaybe rowMap $
Map.toUnfoldable (ngramsTable ^. _NgramsTable <<< _ngrams_repo_elements) Map.toUnfoldable (ngramsTable ^. _NgramsTable <<< _ngrams_repo_elements)
) )
rowsFilter :: NgramsElement -> Maybe NgramsElement rowsFilter :: NgramsElement -> Maybe NgramsElement
rowsFilter ne = rowsFilter ngramsElement =
if displayRow state searchQuery' ngramsTable ngramsParentRoot termListFilter termSizeFilter ne then if displayRow { ngramsElement
Just ne , ngramsParentRoot
else , ngramsTable
Nothing , searchQuery: searchQuery'
orderWith = , state: state'
case convOrderBy <$> orderBy of , termListFilter
Just ScoreAsc -> sortWith \x -> x ^. _NgramsElement <<< _occurrences , termSizeFilter } then
Just ScoreDesc -> sortWith \x -> Down $ x ^. _NgramsElement <<< _occurrences Just ngramsElement
Just TermAsc -> sortWith \x -> x ^. _NgramsElement <<< _ngrams else
Just TermDesc -> sortWith \x -> Down $ x ^. _NgramsElement <<< _ngrams Nothing
_ -> identity -- the server ordering is enough here
performAction = mkDispatch { filteredRows
, path: path'
, state
, state' }
-- filteredRows :: PreConversionRows -- filteredRows :: PreConversionRows
-- no need to filter offset if cache is off -- no need to filter offset if cache is off
...@@ -349,28 +360,32 @@ loadedNgramsTableCpt = here.component "loadedNgramsTable" cpt where ...@@ -349,28 +360,32 @@ loadedNgramsTableCpt = here.component "loadedNgramsTable" cpt where
totalRecords = fromMaybe (Seq.length rows) mTotalRows totalRecords = fromMaybe (Seq.length rows) mTotalRows
performAction = mkDispatch { filteredRows afterSync' _ = do
, path: path' chartsAfterSync path' tasks reloadForest unit
, state: state /\ setState } afterSync unit
syncResetButton path' = syncResetButtons { afterSync: afterSync' path' syncResetButton = syncResetButtons { afterSync: afterSync'
, ngramsLocalPatch , ngramsLocalPatch
, performAction: performAction <<< CoreAction } , performAction: performAction <<< CoreAction }
-- autoUpdate :: Array R.Element -- autoUpdate :: Array R.Element
autoUpdate path' = if withAutoUpdate then autoUpdate path' = if withAutoUpdate then
[ R2.buff [ R2.buff
$ autoUpdateElt $ autoUpdateElt
{ duration: 5000 { duration: 5000
, effect: performAction $ CoreAction $ Synchronize { afterSync: afterSync' path' } , effect: performAction $ CoreAction $ Synchronize { afterSync: afterSync' }
} }
] ]
else [] else []
-- This is used to *decorate* the Select header with the checkbox. ngramsParentRoot :: Maybe NgramsTerm
wrapColElts scProps (TT.ColumnName "Select") = const [NTC.selectionCheckbox scProps] ngramsParentRoot =
wrapColElts _ (TT.ColumnName "Score") = (_ <> [H.text ("(" <> show scoreType <> ")")]) (\np -> ngramsTable ^? at np
wrapColElts _ _ = identity <<< _Just
<<< _NgramsRepoElement
<<< _root
<<< _Just
) =<< ngramsParent
pure $ R.fragment $ pure $ R.fragment $
autoUpdate path' <> autoUpdate path' <>
...@@ -388,58 +403,49 @@ loadedNgramsTableCpt = here.component "loadedNgramsTable" cpt where ...@@ -388,58 +403,49 @@ loadedNgramsTableCpt = here.component "loadedNgramsTable" cpt where
, ngramsSelection , ngramsSelection
, ngramsTable , ngramsTable
, path , path
, syncResetButton: [ syncResetButton path' ] , syncResetButton: [ syncResetButton ]
, tabNgramType } , tabNgramType }
, params , params
, rows: filteredConvertedRows , rows: filteredConvertedRows
, syncResetButton: [ syncResetButton path' ] , syncResetButton: [ syncResetButton ]
, totalRecords , totalRecords
, wrapColElts: , wrapColElts:
wrapColElts { allNgramsSelected, dispatch: performAction, ngramsSelection } wrapColElts { allNgramsSelected, dispatch: performAction, ngramsSelection } scoreType
} }
, syncResetButton path' , syncResetButton
] ]
where where
afterSync' path' _ = do colNames = TT.ColumnName <$> ["Show", "Select", "Map", "Stop", "Terms", "Score"] -- see convOrderBy
chartsAfterSync path' tasks reloadForest unit
afterSync unit
ng_scores :: Map NgramsTerm (Additive Int)
ng_scores = ngramsTable ^. _NgramsTable <<< _ngrams_scores
addOcc ngramsElement =
let Additive occurrences = sumOccurrences ngramsTable (ngramsElementToNgramsOcc ngramsElement) in
ngramsElement # _NgramsElement <<< _occurrences .~ occurrences
ngramsTable = applyNgramsPatches state initTable
roots = rootsOf ngramsTable
ngramsParentRoot :: Maybe NgramsTerm
ngramsParentRoot =
(\np -> ngramsTable ^? at np
<<< _Just
<<< _NgramsRepoElement
<<< _root
<<< _Just
) =<< ngramsParent
ngramsTableOrderWith orderBy =
case convOrderBy <$> orderBy of
Just ScoreAsc -> sortWith \x -> x ^. _NgramsElement <<< _occurrences
Just ScoreDesc -> sortWith \x -> Down $ x ^. _NgramsElement <<< _occurrences
Just TermAsc -> sortWith \x -> x ^. _NgramsElement <<< _ngrams
Just TermDesc -> sortWith \x -> Down $ x ^. _NgramsElement <<< _ngrams
_ -> identity -- the server ordering is enough here
colNames = TT.ColumnName <$> ["Show", "Select", "Map", "Stop", "Terms", "Score"] -- see convOrderBy -- This is used to *decorate* the Select header with the checkbox.
wrapColElts scProps _ (TT.ColumnName "Select") = const [NTC.selectionCheckbox scProps]
wrapColElts _ scoreType (TT.ColumnName "Score") = (_ <> [H.text ("(" <> show scoreType <> ")")])
wrapColElts _ _ _ = identity
type MkDispatchProps = ( type MkDispatchProps = (
filteredRows :: PreConversionRows filteredRows :: PreConversionRows
, path :: PageParams , path :: PageParams
, state :: R.State State , state :: T.Box State
, state' :: State
) )
mkDispatch :: Record MkDispatchProps -> (Action -> Effect Unit) mkDispatch :: Record MkDispatchProps -> (Action -> Effect Unit)
mkDispatch { filteredRows mkDispatch { filteredRows
, path , path
, state: (state@{ ngramsChildren , state
, ngramsLocalPatch , state': state'@{ ngramsChildren
, ngramsParent , ngramsLocalPatch
, ngramsSelection , ngramsParent
, ngramsVersion } /\ setState) } = performAction , ngramsSelection
, ngramsVersion } } = performAction
where where
allNgramsSelected = allNgramsSelectedOnFirstPage ngramsSelection filteredRows allNgramsSelected = allNgramsSelectedOnFirstPage ngramsSelection filteredRows
...@@ -448,15 +454,15 @@ mkDispatch { filteredRows ...@@ -448,15 +454,15 @@ mkDispatch { filteredRows
performAction :: Action -> Effect Unit performAction :: Action -> Effect Unit
performAction (SetParentResetChildren p) = performAction (SetParentResetChildren p) =
setState $ setParentResetChildren p T.modify_ (setParentResetChildren p) state
performAction (ToggleChild b c) = performAction (ToggleChild b c) =
setState $ \s@{ ngramsChildren: nc } -> s { ngramsChildren = newNC nc } T.modify_ (\s@{ ngramsChildren: nc } -> s { ngramsChildren = newNC nc }) state
where where
newNC nc = Map.alter (maybe (Just b) (const Nothing)) c nc newNC nc = Map.alter (maybe (Just b) (const Nothing)) c nc
performAction (ToggleSelect c) = performAction (ToggleSelect c) =
setState $ \s@{ ngramsSelection: ns } -> s { ngramsSelection = toggleSet c ns } T.modify_ (\s@{ ngramsSelection: ns } -> s { ngramsSelection = toggleSet c ns }) state
performAction ToggleSelectAll = performAction ToggleSelectAll =
setState toggler T.modify_ toggler state
where where
toggler s = toggler s =
if allNgramsSelected then if allNgramsSelected then
...@@ -472,21 +478,27 @@ mkDispatch { filteredRows ...@@ -472,21 +478,27 @@ mkDispatch { filteredRows
let pc = patchSetFromMap ngramsChildren let pc = patchSetFromMap ngramsChildren
pe = NgramsPatch { patch_list: mempty, patch_children: pc } pe = NgramsPatch { patch_list: mempty, patch_children: pc }
pt = singletonNgramsTablePatch parent pe pt = singletonNgramsTablePatch parent pe
setState $ setParentResetChildren Nothing T.modify_ (setParentResetChildren Nothing) state
commitPatch (Versioned {version: ngramsVersion, data: pt}) (state /\ setState) commitPatch pt state
performAction (CoreAction a) = coreDispatch path (state /\ setState) a performAction (CoreAction a) = coreDispatch path state a
displayRow :: State -> SearchQuery -> NgramsTable -> Maybe NgramsTerm -> Maybe TermList -> Maybe TermSize -> NgramsElement -> Boolean displayRow :: { ngramsElement :: NgramsElement
displayRow state@{ ngramsChildren , ngramsParentRoot :: Maybe NgramsTerm
, ngramsLocalPatch , ngramsTable :: NgramsTable
, ngramsParent } , searchQuery :: SearchQuery
searchQuery , state :: State
ngramsTable , termListFilter :: Maybe TermList
ngramsParentRoot , termSizeFilter :: Maybe TermSize } -> Boolean
termListFilter displayRow { ngramsElement: NgramsElement {ngrams, root, list}
termSizeFilter , ngramsParentRoot
(NgramsElement {ngrams, root, list}) = , ngramsTable
, state: state@{ ngramsChildren
, ngramsLocalPatch
, ngramsParent }
, searchQuery
, termListFilter
, termSizeFilter } =
( (
isNothing root isNothing root
-- ^ Display only nodes without parents -- ^ Display only nodes without parents
...@@ -652,7 +664,7 @@ mainNgramsTablePaintCpt = here.component "mainNgramsTablePaint" cpt ...@@ -652,7 +664,7 @@ mainNgramsTablePaintCpt = here.component "mainNgramsTablePaint" cpt
, tasks , tasks
, versioned , versioned
, withAutoUpdate } _ = do , withAutoUpdate } _ = do
state <- R.useState' $ initialState versioned state <- T.useBox $ initialState versioned
pure $ loadedNgramsTable { afterSync pure $ loadedNgramsTable { afterSync
, cacheState , cacheState
...@@ -693,7 +705,7 @@ mainNgramsTablePaintNoCacheCpt = here.component "mainNgramsTablePaintNoCache" cp ...@@ -693,7 +705,7 @@ mainNgramsTablePaintNoCacheCpt = here.component "mainNgramsTablePaintNoCache" cp
, withAutoUpdate } _ = do , withAutoUpdate } _ = do
let count /\ versioned = toVersioned versionedWithCount let count /\ versioned = toVersioned versionedWithCount
state <- R.useState' $ initialState versioned state <- T.useBox $ initialState versioned
pure $ loadedNgramsTable { pure $ loadedNgramsTable {
afterSync afterSync
......
...@@ -974,12 +974,12 @@ putNgramsPatches :: forall s. CoreParams s -> VersionedNgramsPatches -> Aff Vers ...@@ -974,12 +974,12 @@ putNgramsPatches :: forall s. CoreParams s -> VersionedNgramsPatches -> Aff Vers
putNgramsPatches { listIds, nodeId, session, tabType } = put session putNgrams putNgramsPatches { listIds, nodeId, session, tabType } = put session putNgrams
where putNgrams = PutNgrams tabType (head listIds) Nothing (Just nodeId) where putNgrams = PutNgrams tabType (head listIds) Nothing (Just nodeId)
syncPatches :: forall p s. CoreParams p -> R.State (CoreState s) -> (Unit -> Aff Unit) -> Effect Unit syncPatches :: forall p s. CoreParams p -> T.Box (CoreState s) -> (Unit -> Aff Unit) -> Effect Unit
syncPatches props ({ ngramsLocalPatch: ngramsLocalPatch@{ ngramsPatches } syncPatches props state callback = do
, ngramsStagePatch { ngramsLocalPatch: ngramsLocalPatch@{ ngramsPatches }
, ngramsValidPatch , ngramsStagePatch
, ngramsVersion , ngramsValidPatch
} /\ setState) callback = do , ngramsVersion } <- T.read state
when (isEmptyNgramsTablePatch ngramsStagePatch) $ do when (isEmptyNgramsTablePatch ngramsStagePatch) $ do
let pt = Versioned { data: ngramsPatches, version: ngramsVersion } let pt = Versioned { data: ngramsPatches, version: ngramsVersion }
launchAff_ $ do launchAff_ $ do
...@@ -987,7 +987,7 @@ syncPatches props ({ ngramsLocalPatch: ngramsLocalPatch@{ ngramsPatches } ...@@ -987,7 +987,7 @@ syncPatches props ({ ngramsLocalPatch: ngramsLocalPatch@{ ngramsPatches }
callback unit callback unit
liftEffect $ do liftEffect $ do
log2 "[syncPatches] setting state, newVersion" newVersion log2 "[syncPatches] setting state, newVersion" newVersion
setState $ \s -> T.modify_ (\s ->
-- I think that sometimes this setState does not fully go through. -- I think that sometimes this setState does not fully go through.
-- This is an issue because the version number does not get updated and the subsequent calls -- This is an issue because the version number does not get updated and the subsequent calls
-- can mess up the patches. -- can mess up the patches.
...@@ -997,7 +997,7 @@ syncPatches props ({ ngramsLocalPatch: ngramsLocalPatch@{ ngramsPatches } ...@@ -997,7 +997,7 @@ syncPatches props ({ ngramsLocalPatch: ngramsLocalPatch@{ ngramsPatches }
, ngramsValidPatch = fromNgramsPatches newPatch <> ngramsLocalPatch <> s.ngramsValidPatch , ngramsValidPatch = fromNgramsPatches newPatch <> ngramsLocalPatch <> s.ngramsValidPatch
-- First the already valid patch, then the local patch, then the newly received newPatch. -- First the already valid patch, then the local patch, then the newly received newPatch.
, ngramsVersion = newVersion , ngramsVersion = newVersion
} }) state
log2 "[syncPatches] ngramsVersion" newVersion log2 "[syncPatches] ngramsVersion" newVersion
pure unit pure unit
...@@ -1027,10 +1027,9 @@ syncPatchesAsync props@{ listIds, tabType } ...@@ -1027,10 +1027,9 @@ syncPatchesAsync props@{ listIds, tabType }
log2 "[syncPatches] ngramsVersion" newVersion log2 "[syncPatches] ngramsVersion" newVersion
-} -}
commitPatch :: forall s. Versioned NgramsTablePatch -> R.State (CoreState s) -> Effect Unit commitPatch :: forall s. NgramsTablePatch -> T.Box (CoreState s) -> Effect Unit
commitPatch (Versioned {version, data: tablePatch}) (_ /\ setState) = do commitPatch tablePatch state = do
setState $ \s -> T.modify_ (\s -> s { ngramsLocalPatch = tablePatch <> s.ngramsLocalPatch }) state
s { ngramsLocalPatch = tablePatch <> s.ngramsLocalPatch }
-- First we apply the patches we have locally and then the new patch (tablePatch). -- First we apply the patches we have locally and then the new patch (tablePatch).
loadNgramsTable :: PageParams -> Aff VersionedNgramsTable loadNgramsTable :: PageParams -> Aff VersionedNgramsTable
...@@ -1096,13 +1095,13 @@ data Action ...@@ -1096,13 +1095,13 @@ data Action
type CoreDispatch = CoreAction -> Effect Unit type CoreDispatch = CoreAction -> Effect Unit
type Dispatch = Action -> Effect Unit type Dispatch = Action -> Effect Unit
coreDispatch :: forall p s. CoreParams p -> R.State (CoreState s) -> CoreDispatch coreDispatch :: forall p s. CoreParams p -> T.Box (CoreState s) -> CoreDispatch
coreDispatch path state (Synchronize { afterSync }) = coreDispatch path state (Synchronize { afterSync }) =
syncPatches path state afterSync syncPatches path state afterSync
coreDispatch _ state@({ngramsVersion} /\ _) (CommitPatch pt) = coreDispatch _ state (CommitPatch pt) =
commitPatch (Versioned {version: ngramsVersion, data: pt}) state commitPatch pt state
coreDispatch _ (_ /\ setState) ResetPatches = coreDispatch _ state ResetPatches =
setState $ \s -> s { ngramsLocalPatch = { ngramsPatches: mempty } } T.modify_ (\s -> s { ngramsLocalPatch = { ngramsPatches: mempty } }) state
isSingleNgramsTerm :: NgramsTerm -> Boolean isSingleNgramsTerm :: NgramsTerm -> Boolean
isSingleNgramsTerm nt = isSingleTerm $ ngramsTermText nt isSingleNgramsTerm nt = isSingleTerm $ ngramsTermText nt
......
...@@ -9,6 +9,7 @@ import Effect.Aff (Aff) ...@@ -9,6 +9,7 @@ import Effect.Aff (Aff)
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as H import Reactix.DOM.HTML as H
import Record as Record import Record as Record
import Toestand as T
import Gargantext.Prelude (bind, pure, show, unit, ($), (<>), (<$>), (<<<)) import Gargantext.Prelude (bind, pure, show, unit, ($), (<>), (<$>), (<<<))
...@@ -43,12 +44,12 @@ docViewWrapperCpt :: R.Component Props ...@@ -43,12 +44,12 @@ docViewWrapperCpt :: R.Component Props
docViewWrapperCpt = here.component "docViewWrapper" cpt docViewWrapperCpt = here.component "docViewWrapper" cpt
where where
cpt props@{ loaded } _ = do cpt props@{ loaded } _ = do
state <- R.useState' $ initialState { loaded } state <- T.useBox $ initialState { loaded }
pure $ docView (Record.merge props { state }) [] pure $ docView (Record.merge props { state }) []
type DocViewProps = ( type DocViewProps = (
state :: R.State State state :: T.Box State
| Props | Props
) )
...@@ -60,8 +61,9 @@ docViewCpt = here.component "docView" cpt ...@@ -60,8 +61,9 @@ docViewCpt = here.component "docView" cpt
where where
cpt { path cpt { path
, loaded: loaded@{ ngramsTable: Versioned { data: initTable }, document } , loaded: loaded@{ ngramsTable: Versioned { data: initTable }, document }
, state: state@({ ngramsVersion: version, ngramsLocalPatch } /\ _) , state
} _children = do } _children = do
state'@{ ngramsLocalPatch, ngramsVersion: version } <- T.useLive T.unequal state
let let
afterSync = \_ -> pure unit afterSync = \_ -> pure unit
...@@ -74,6 +76,13 @@ docViewCpt = here.component "docView" cpt ...@@ -74,6 +76,13 @@ docViewCpt = here.component "docView" cpt
then [ autoUpdate { duration: 5000, effect: dispatch $ Synchronize { afterSync } } ] then [ autoUpdate { duration: 5000, effect: dispatch $ Synchronize { afterSync } } ]
else [] else []
ngrams = applyNgramsPatches state' initTable
annotate text = AnnotatedField.annotatedField { ngrams, setTermList, text }
setTermListOrAddA ngram Nothing = addNewNgramA ngram
setTermListOrAddA ngram (Just oldList) = setTermListA ngram <<< replace oldList
setTermList ngram mOldList = dispatch <<< setTermListOrAddA (findNgramRoot ngrams ngram) mOldList
pure $ H.div {} $ pure $ H.div {} $
autoUpd <> syncResetBtns <> autoUpd <> syncResetBtns <>
--DEBUG --DEBUG
...@@ -95,17 +104,12 @@ docViewCpt = here.component "docView" cpt ...@@ -95,17 +104,12 @@ docViewCpt = here.component "docView" cpt
]]]] ]]]]
where where
dispatch = coreDispatch path state dispatch = coreDispatch path state
ngrams = applyNgramsPatches (fst state) initTable
annotate text = AnnotatedField.annotatedField { ngrams, setTermList, text }
badge s = H.span { className: "badge badge-default badge-pill" } [ H.text s ] badge s = H.span { className: "badge badge-default badge-pill" } [ H.text s ]
badgeLi s = badgeLi s =
H.span { className: "list-group-item-heading" } H.span { className: "list-group-item-heading" }
[ H.span { className: "badge-container" } [ H.span { className: "badge-container" }
[ H.span { className: "badge badge-default badge-pill" } [ H.text s ] ]] [ H.span { className: "badge badge-default badge-pill" } [ H.text s ] ]]
li' = H.li { className: "list-group-item justify-content-between" } li' = H.li { className: "list-group-item justify-content-between" }
setTermListOrAddA ngram Nothing = addNewNgramA ngram
setTermListOrAddA ngram (Just oldList) = setTermListA ngram <<< replace oldList
setTermList ngram mOldList = dispatch <<< setTermListOrAddA (findNgramRoot ngrams ngram) mOldList
-- Here the use of findNgramRoot makes that we always target the root of an ngram group. -- Here the use of findNgramRoot makes that we always target the root of an ngram group.
text' x = H.span { className: "list-group-item-text" } [ H.text $ fromMaybe "Nothing" x ] text' x = H.span { className: "list-group-item-text" } [ H.text $ fromMaybe "Nothing" x ]
NodePoly {hyperdata: Document doc} = document NodePoly {hyperdata: Document doc} = document
......
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