AsyncTasks.purs 2.62 KB
Newer Older
1 2
module Gargantext.AsyncTasks where

3
import Data.Argonaut (decodeJson)
4
import Data.Argonaut.Parser (jsonParser)
5
import Data.Array as A
6 7
import Data.Either (Either(..))
import Data.Map as Map
8
import Data.Maybe (Maybe(..), maybe, fromMaybe)
9
import Data.Tuple (snd)
10 11
import DOM.Simple.Console (log2)
import Effect (Effect)
12
import Reactix as R
13 14 15 16
import Web.Storage.Storage as WSS

import Gargantext.Prelude
import Gargantext.Types as GT
17
import Gargantext.Utils as GU
18 19 20 21 22 23
import Gargantext.Utils.Reactix as R2


localStorageKey :: String
localStorageKey = "garg-async-tasks"

24 25 26

type NodeId = Int
type Storage = Map.Map NodeId (Array GT.AsyncTaskWithType)
27 28

empty :: Storage
29 30
empty = Map.empty

31
getAsyncTasks :: Effect Storage
32 33 34 35 36 37 38 39 40
getAsyncTasks = R2.getls >>= WSS.getItem localStorageKey >>= handleMaybe
  where
    handleMaybe (Just val) = handleEither (parse val >>= decode)
    handleMaybe Nothing    = pure empty

    -- either parsing or decoding could fail, hence two errors
    handleEither (Left err) = err *> pure empty
    handleEither (Right ss) = pure ss

41 42
    parse  s = GU.mapLeft (log2 "Error parsing serialised sessions:") (jsonParser s)
    decode j = GU.mapLeft (log2 "Error decoding serialised sessions:") (decodeJson j)
43

44 45 46
getTasks :: Record ReductorProps -> NodeId -> Array GT.AsyncTaskWithType
getTasks { storage } nodeId = fromMaybe [] $ Map.lookup nodeId storage

47 48 49
removeTaskFromList :: Array GT.AsyncTaskWithType -> GT.AsyncTaskWithType -> Array GT.AsyncTaskWithType
removeTaskFromList ts (GT.AsyncTaskWithType { task: GT.AsyncTask { id: id' } }) =
  A.filter (\(GT.AsyncTaskWithType { task: GT.AsyncTask { id: id'' } }) -> id' /= id'') ts
50 51 52 53 54 55

type ReductorProps = (
    reload  :: R.State Int
  , storage :: Storage
  )

56
type Reductor = R2.Reductor (Record ReductorProps) Action
57
type ReductorAction = Action -> Effect Unit
58 59 60

useTasks :: R.State Int -> R.Hooks Reductor
useTasks reload = R2.useReductor act initializer unit
61 62 63
  where
    act :: R2.Actor (Record ReductorProps) Action
    act a s = action s a
64 65 66
    initializer _ = do
      storage <- getAsyncTasks
      pure { reload, storage }
67 68 69 70 71

data Action =
    Insert NodeId GT.AsyncTaskWithType
  | Remove NodeId GT.AsyncTaskWithType

72 73 74 75 76 77 78 79 80
action :: Record ReductorProps -> Action -> Effect (Record ReductorProps)
action { reload, storage } (Insert nodeId t) = do
  _ <- snd reload $ (_ + 1)
  let newStorage = Map.alter (maybe (Just [t]) (\ts -> Just $ A.cons t ts)) nodeId storage
  pure { reload, storage: newStorage }
action { reload, storage } (Remove nodeId t) = do
  _ <- snd reload $ (_ + 1)
  let newStorage = Map.alter (maybe Nothing $ (\ts -> Just $ removeTaskFromList ts t)) nodeId storage
  pure { reload, storage: newStorage }