AsyncTasks.purs 2.83 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
type Storage = Map.Map GT.NodeID (Array GT.AsyncTaskWithType)
26 27

empty :: Storage
28 29
empty = Map.empty

30
getAsyncTasks :: Effect Storage
31 32 33 34 35 36 37 38 39
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

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

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

46 47 48
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
49 50

type ReductorProps = (
51 52
    appReload  :: GT.ReloadS
  , treeReload :: GT.ReloadS
53
  , storage    :: Storage
54 55
  )

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

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

data Action =
70 71 72
    Insert GT.NodeID GT.AsyncTaskWithType
  | Finish GT.NodeID GT.AsyncTaskWithType
  | Remove GT.NodeID GT.AsyncTaskWithType
73

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