[notifications] more granular notifications

parent 071a467b
Pipeline #6898 passed with stages
in 14 minutes and 12 seconds
...@@ -19,6 +19,7 @@ import Gargantext.Hooks.FormValidation (VForm, useFormValidation) ...@@ -19,6 +19,7 @@ import Gargantext.Hooks.FormValidation (VForm, useFormValidation)
import Gargantext.Hooks.FormValidation.Unboxed as FV import Gargantext.Hooks.FormValidation.Unboxed as FV
import Gargantext.Hooks.StateRecord (useStateRecord) import Gargantext.Hooks.StateRecord (useStateRecord)
import Gargantext.Sessions (postForgotPasswordRequest) import Gargantext.Sessions (postForgotPasswordRequest)
import Gargantext.Types as GT
import Gargantext.Utils ((?)) import Gargantext.Utils ((?))
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Reactix as R import Reactix as R
...@@ -195,5 +196,5 @@ formValidation r = foldl append mempty rules ...@@ -195,5 +196,5 @@ formValidation r = foldl append mempty rules
sendEmail :: sendEmail ::
Backend Backend
-> FormData -> FormData
-> Aff (Either String { status :: String }) -> Aff (Either String GT.WorkerTask)
sendEmail backend { email } = postForgotPasswordRequest backend email sendEmail backend { email } = postForgotPasswordRequest backend email
...@@ -51,16 +51,19 @@ removeCallback (State state@{ callbacks }) topic uuid = ...@@ -51,16 +51,19 @@ removeCallback (State state@{ callbacks }) topic uuid =
-- | Execute all callbacks for a given Notification -- | Execute all callbacks for a given Notification
callNotification :: State -> Notification -> Effect Unit callNotification :: State -> Notification -> Effect Unit
callNotification (State { callbacks }) (Notification topic message) = do callNotification (State { callbacks }) n = do
-- here.log2 "[callTopic] topic" topic -- here.log2 "[callTopic] topic" topic
-- here.log2 "[callTopic] callbacks" (HM.values callbacks) -- here.log2 "[callTopic] callbacks" (HM.values callbacks)
-- here.log2 "[callTopic] topicCallbacks" (HM.values topicCallbacks) -- here.log2 "[callTopic] topicCallbacks" (HM.values topicCallbacks)
_ <- for (HM.values topicCallbacks) $ \cb -> do
cb message let topic = notificationTopic n
_ <- for (HM.values $ topicCallbacks topic) $ \cb -> do
cb n
pure unit pure unit
where where
topicCallbacks :: CallbacksHM topicCallbacks :: Topic -> CallbacksHM
topicCallbacks = fromMaybe HM.empty $ HM.lookup topic callbacks topicCallbacks topic = fromMaybe HM.empty $ HM.lookup topic callbacks
...@@ -174,7 +177,7 @@ connect ws@(WSNotification ws') url session = do ...@@ -174,7 +177,7 @@ connect ws@(WSNotification ws') url session = do
case parsed of case parsed of
Left err -> do Left err -> do
here.log2 "[connect] Can't parse message" err here.log2 "[connect] Can't parse message" err
Right n@(Notification topic _message) -> do Right n -> do
-- here.log2 "[connect] notification" topic -- here.log2 "[connect] notification" topic
performAction ws (Call n) performAction ws (Call n)
-- Right parsed' -> do -- Right parsed' -> do
......
...@@ -38,6 +38,7 @@ type UUID = String ...@@ -38,6 +38,7 @@ type UUID = String
data Topic = data Topic =
UpdateJobProgress GT.AsyncTaskID UpdateJobProgress GT.AsyncTaskID
| UpdateWorkerProgress GT.WorkerTask
| UpdateTree NodeId | UpdateTree NodeId
derive instance Generic Topic _ derive instance Generic Topic _
instance Eq Topic where eq = genericEq instance Eq Topic where eq = genericEq
...@@ -51,6 +52,9 @@ instance JSON.ReadForeign Topic where ...@@ -51,6 +52,9 @@ instance JSON.ReadForeign Topic where
"update_job_progress" -> do "update_job_progress" -> do
{ j_id } <- JSON.readImpl f :: F.F { j_id :: GT.AsyncTaskID } { j_id } <- JSON.readImpl f :: F.F { j_id :: GT.AsyncTaskID }
pure $ UpdateJobProgress j_id pure $ UpdateJobProgress j_id
"update_worker_progress" -> do
{ ji } <- JSON.readImpl f :: F.F { ji :: GT.WorkerTask }
pure $ UpdateWorkerProgress ji
"update_tree" -> do "update_tree" -> do
{ node_id } <- JSON.readImpl f :: F.F { node_id :: NodeId } { node_id } <- JSON.readImpl f :: F.F { node_id :: NodeId }
pure $ UpdateTree node_id pure $ UpdateTree node_id
...@@ -58,6 +62,8 @@ instance JSON.ReadForeign Topic where ...@@ -58,6 +62,8 @@ instance JSON.ReadForeign Topic where
instance JSON.WriteForeign Topic where instance JSON.WriteForeign Topic where
writeImpl (UpdateJobProgress j_id) = JSON.writeImpl { "type": "update_job_progress" writeImpl (UpdateJobProgress j_id) = JSON.writeImpl { "type": "update_job_progress"
, j_id } , j_id }
writeImpl (UpdateWorkerProgress ji) = JSON.writeImpl { "type": "update_worker_progress"
, ji }
writeImpl (UpdateTree node_id) = JSON.writeImpl { "type": "update_tree" writeImpl (UpdateTree node_id) = JSON.writeImpl { "type": "update_tree"
, node_id } , node_id }
...@@ -78,42 +84,28 @@ instance JSON.WriteForeign WSRequest where ...@@ -78,42 +84,28 @@ instance JSON.WriteForeign WSRequest where
writeImpl WSDeauthorize = JSON.writeImpl { request: "deauthorize" } writeImpl WSDeauthorize = JSON.writeImpl { request: "deauthorize" }
data Message =
-- TODO
-- MJobProgress GT.AsyncProgress
-- MJobProgress GT.AsyncTaskLog
MJobProgress GT.AsyncProgress
| MEmpty
derive instance Generic Message _
instance JSON.ReadForeign Message where
readImpl f = do
{ type: type_ } <- JSON.readImpl f :: F.F { type :: String }
case type_ of
"MJobProgress" -> do
-- TODO
-- { job_progress } <- JSON.readImpl f :: F.F { job_progress :: GT.AsyncProgress }
-- { job_progress } <- JSON.readImpl f :: F.F { job_progress :: GT.AsyncTaskLog }
{ job_status } <- JSON.readImpl f :: F.F { job_status :: GT.AsyncProgress }
pure $ MJobProgress job_status
"MEmpty" -> do
pure MEmpty
s -> do F.fail $ F.ErrorAtProperty "type" $ F.ForeignError $ "unknown Message type: " <> s
data Notification = data Notification =
Notification Topic Message NUpdateJobProgress GT.AsyncTaskID GT.AsyncProgress
| NUpdateTree NodeId
derive instance Generic Notification _ derive instance Generic Notification _
instance JSON.ReadForeign Notification where instance JSON.ReadForeign Notification where
readImpl f = do readImpl f = do
let str = JSON.read_ f :: Maybe String { type: type_ } <- JSON.readImpl f :: F.F { type :: String }
case str of case type_ of
Nothing -> do "update_job_progress" -> do
{ notification } <- JSON.readImpl f :: F.F { notification :: { topic :: Topic, message :: Message } } { j_id, job_status } <- JSON.readImpl f :: F.F { j_id :: GT.AsyncTaskID, job_status :: GT.AsyncProgress }
pure $ Notification notification.topic notification.message pure $ NUpdateJobProgress j_id job_status
Just s -> F.fail $ F.ErrorAtProperty "_" $ F.ForeignError $ "unkown string: " <> s "update_tree" -> do
{ node_id } <- JSON.readImpl f :: F.F { node_id :: NodeId }
pure $ NUpdateTree node_id
s -> F.fail $ F.ErrorAtProperty "type" $ F.ForeignError $ "unkown type: " <> s
notificationTopic :: Notification -> Topic
notificationTopic (NUpdateJobProgress taskId _) = UpdateJobProgress taskId
notificationTopic (NUpdateTree nodeId) = UpdateTree nodeId
type Callback = Message -> Effect Unit type Callback = Notification -> Effect Unit
type CallbacksHM = HM.HashMap UUID Callback type CallbacksHM = HM.HashMap UUID Callback
......
...@@ -15,7 +15,7 @@ import Gargantext.AsyncTasks as GAT ...@@ -15,7 +15,7 @@ import Gargantext.AsyncTasks as GAT
import Gargantext.Components.App.Store as AppStore import Gargantext.Components.App.Store as AppStore
import Gargantext.Components.Forest.Tree.Node.Tools.ProgressBar (QueryProgressData, queryProgress) import Gargantext.Components.Forest.Tree.Node.Tools.ProgressBar (QueryProgressData, queryProgress)
import Gargantext.Components.Notifications as Notifications import Gargantext.Components.Notifications as Notifications
import Gargantext.Components.Notifications.Types as NotificationsT import Gargantext.Components.Notifications.Types as NT
import Gargantext.Config.Utils (handleErrorInAsyncProgress, handleRESTError) import Gargantext.Config.Utils (handleErrorInAsyncProgress, handleRESTError)
import Gargantext.Hooks.FirstEffect (useFirstEffect') import Gargantext.Hooks.FirstEffect (useFirstEffect')
import Gargantext.Prelude import Gargantext.Prelude
...@@ -116,17 +116,21 @@ asyncProgressCpt = R2.hereComponent here "asyncProgress" hCpt where ...@@ -116,17 +116,21 @@ asyncProgressCpt = R2.hereComponent here "asyncProgress" hCpt where
useFirstEffect' $ do useFirstEffect' $ do
let (GT.AsyncTaskWithType { task: GT.AsyncTask { id: taskId } }) = props.asyncTask let (GT.AsyncTaskWithType { task: GT.AsyncTask { id: taskId } }) = props.asyncTask
let cb msg = do let cb n = do
-- here.log2 "callback! for job update" taskId -- here.log2 "callback! for job update" taskId
case msg of case n of
NotificationsT.MJobProgress jobProgress -> launchAff_ $ onProgress jobProgress NT.NUpdateJobProgress _jId jobProgress -> launchAff_ $ onProgress jobProgress
NotificationsT.MEmpty -> fetchJobProgress _ -> pure unit
resetInterval intervalIdRef (Just defaultJobPollInterval) fetchJobProgress resetInterval intervalIdRef (Just defaultJobPollInterval) fetchJobProgress
-- The modal window has some problems closing when we refresh too early. This is a HACK -- The modal window has some problems closing when we refresh too early. This is a HACK
-- void $ setTimeout 400 $ T2.reload reload -- void $ setTimeout 400 $ T2.reload reload
let action = NotificationsT.InsertCallback (NotificationsT.UpdateJobProgress taskId) ("task-" <> show taskId) cb let action = NT.InsertCallback (NT.UpdateJobProgress taskId) ("task-" <> show taskId) cb
ws <- T.read wsNotification
Notifications.performAction ws action
-- let action = NT.InsertCallback (NT.UpdateWorkerProgress $ GT.WorkerTask { message_id: taskId }) ("worker-job-" <> show taskId) cb
let action = NT.InsertCallback (NT.UpdateJobProgress taskId) ("job-" <> taskId) cb
ws <- T.read wsNotification ws <- T.read wsNotification
Notifications.performAction ws action Notifications.performAction ws action
fetchJobProgress fetchJobProgress
......
...@@ -21,6 +21,7 @@ import Gargantext.Config.REST as REST ...@@ -21,6 +21,7 @@ import Gargantext.Config.REST as REST
import Gargantext.Ends (class ToUrl, Backend, toUrl) import Gargantext.Ends (class ToUrl, Backend, toUrl)
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Sessions.Types (Session(..), Sessions(..), OpenNodes, NodeId, mkNodeId, sessionUrl, sessionId, empty, null, unSessions, lookup, cons, tryCons, update, remove, tryRemove) import Gargantext.Sessions.Types (Session(..), Sessions(..), OpenNodes, NodeId, mkNodeId, sessionUrl, sessionId, empty, null, unSessions, lookup, cons, tryCons, update, remove, tryRemove)
import Gargantext.Types as GT
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Reactix as R import Reactix as R
import Simple.JSON as JSON import Simple.JSON as JSON
...@@ -118,7 +119,7 @@ postAuthRequest backend ar@(AuthRequest {username}) = ...@@ -118,7 +119,7 @@ postAuthRequest backend ar@(AuthRequest {username}) =
decode (Right (AuthData { token, tree_id, user_id })) = decode (Right (AuthData { token, tree_id, user_id })) =
Right $ Session { backend, caches: Map.empty, token, treeId: tree_id, username, userId: user_id } Right $ Session { backend, caches: Map.empty, token, treeId: tree_id, username, userId: user_id }
postForgotPasswordRequest :: Backend -> String -> Aff (Either String { status :: String }) postForgotPasswordRequest :: Backend -> String -> Aff (Either String GT.WorkerTask)
postForgotPasswordRequest backend email = postForgotPasswordRequest backend email =
decode <$> REST.post Nothing (toUrl backend "async/forgot-password") { email } decode <$> REST.post Nothing (toUrl backend "async/forgot-password") { email }
where where
......
...@@ -835,6 +835,18 @@ progressPercent (AsyncProgress { log }) = perc ...@@ -835,6 +835,18 @@ progressPercent (AsyncProgress { log }) = perc
nom = toNumber $ failed + succeeded nom = toNumber $ failed + succeeded
denom = toNumber $ failed + succeeded + remaining denom = toNumber $ failed + succeeded + remaining
-- New type tasks (async workers)
newtype WorkerTask = WorkerTask { message_id :: Number }
derive instance Generic WorkerTask _
derive instance Newtype WorkerTask _
instance Eq WorkerTask where
eq = genericEq
instance Show WorkerTask where
show = genericShow
derive newtype instance JSON.ReadForeign WorkerTask
derive newtype instance JSON.WriteForeign WorkerTask
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
-- | GarganText Internal Sugar -- | GarganText Internal Sugar
......
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