mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-04-04 10:29:34 +00:00
Refresh item after addon is done
This commit is contained in:
parent
5abbe92f2b
commit
29a5894884
@ -83,7 +83,7 @@ object OJob {
|
||||
else
|
||||
pubsub.publish1IgnoreErrors(
|
||||
JobDone.topic,
|
||||
JobDone(job.id, job.group, job.task, job.args, JobState.Cancelled)
|
||||
JobDone(job.id, job.group, job.task, job.args, JobState.Cancelled, None)
|
||||
)
|
||||
} yield JobCancelResult.removed
|
||||
|
||||
|
@ -14,6 +14,8 @@ import docspell.pubsub.api.PubSubT
|
||||
import docspell.restserver.ws.OutputEvent
|
||||
import docspell.scheduler.msg.{JobDone, JobSubmitted}
|
||||
|
||||
import io.circe.parser
|
||||
|
||||
/** Subscribes to those events from docspell that are forwarded to the websocket endpoints
|
||||
*/
|
||||
object Subscriptions {
|
||||
@ -27,7 +29,14 @@ object Subscriptions {
|
||||
def jobDone[F[_]](pubSub: PubSubT[F]): Stream[F, OutputEvent] =
|
||||
pubSub
|
||||
.subscribe(JobDone.topic)
|
||||
.map(m => OutputEvent.JobDone(m.body.group, m.body.task))
|
||||
.map(m =>
|
||||
OutputEvent.JobDone(
|
||||
m.body.group,
|
||||
m.body.task,
|
||||
parser.parse(m.body.args).toOption,
|
||||
m.body.result
|
||||
)
|
||||
)
|
||||
|
||||
def jobSubmitted[F[_]](pubSub: PubSubT[F]): Stream[F, OutputEvent] =
|
||||
pubSub
|
||||
|
@ -40,12 +40,20 @@ object OutputEvent {
|
||||
Msg("job-submitted", task).asJson
|
||||
}
|
||||
|
||||
final case class JobDone(group: Ident, task: Ident) extends OutputEvent {
|
||||
final case class JobDone(
|
||||
group: Ident,
|
||||
task: Ident,
|
||||
args: Option[Json],
|
||||
result: Option[Json]
|
||||
) extends OutputEvent {
|
||||
def forCollective(token: AuthToken): Boolean =
|
||||
token.account.collective == group
|
||||
|
||||
def asJson: Json =
|
||||
Msg("job-done", task).asJson
|
||||
Msg(
|
||||
"job-done",
|
||||
Map("task" -> task.asJson, "args" -> args.asJson, "result" -> result.asJson)
|
||||
).asJson
|
||||
}
|
||||
|
||||
final case class JobsWaiting(collective: Ident, count: Int) extends OutputEvent {
|
||||
|
@ -10,7 +10,7 @@ import docspell.common._
|
||||
import docspell.pubsub.api.{Topic, TypedTopic}
|
||||
|
||||
import io.circe.generic.semiauto.{deriveDecoder, deriveEncoder}
|
||||
import io.circe.{Decoder, Encoder}
|
||||
import io.circe.{Decoder, Encoder, Json}
|
||||
|
||||
/** Message to notify about finished jobs. They have a final state. */
|
||||
final case class JobDone(
|
||||
@ -18,7 +18,8 @@ final case class JobDone(
|
||||
group: Ident,
|
||||
task: Ident,
|
||||
args: String,
|
||||
state: JobState
|
||||
state: JobState,
|
||||
result: Option[Json]
|
||||
)
|
||||
object JobDone {
|
||||
implicit val jsonDecoder: Decoder[JobDone] =
|
||||
|
@ -231,7 +231,7 @@ final class SchedulerImpl[F[_]: Async](
|
||||
_ <- Sync[F].whenA(JobState.isDone(finishState))(
|
||||
pubSub.publish1IgnoreErrors(
|
||||
JobDone.topic,
|
||||
JobDone(job.id, job.group, job.task, job.args, finishState)
|
||||
JobDone(job.id, job.group, job.task, job.args, finishState, result.json)
|
||||
)
|
||||
)
|
||||
_ <- Sync[F].whenA(JobState.isDone(finishState))(
|
||||
|
@ -314,13 +314,16 @@ updateWithSub msg model =
|
||||
|
||||
ReceiveWsMessage data ->
|
||||
case data of
|
||||
Ok (JobDone task) ->
|
||||
Ok (JobDone details) ->
|
||||
let
|
||||
isProcessItem =
|
||||
task == "process-item"
|
||||
details.task == "process-item"
|
||||
|
||||
isDownloadZip =
|
||||
task == "download-query-zip"
|
||||
details.task == "download-query-zip"
|
||||
|
||||
isAddonExistingItem =
|
||||
Data.ServerEvent.isAddonExistingItem model.itemDetailModel.detail.item.id details
|
||||
|
||||
newModel =
|
||||
{ model
|
||||
@ -337,6 +340,9 @@ updateWithSub msg model =
|
||||
else if Page.isDashboardPage model.page && isProcessItem then
|
||||
updateDashboard texts Page.Dashboard.Data.reloadDashboardData newModel
|
||||
|
||||
else if Page.isDetailPage model.page && isAddonExistingItem then
|
||||
updateItemDetail texts (Page.ItemDetail.Data.ReloadItem True) newModel
|
||||
|
||||
else
|
||||
( newModel, Cmd.none, Sub.none )
|
||||
|
||||
|
@ -76,7 +76,7 @@ view texts model =
|
||||
, a
|
||||
[ class S.successMessageLink
|
||||
, href "#"
|
||||
, onClick ReloadItem
|
||||
, onClick (ReloadItem False)
|
||||
]
|
||||
[ text texts.refreshNow
|
||||
]
|
||||
|
@ -281,7 +281,7 @@ initSelectViewModel =
|
||||
|
||||
type Msg
|
||||
= ToggleMenu
|
||||
| ReloadItem
|
||||
| ReloadItem Bool
|
||||
| Init
|
||||
| SetItem ItemDetail
|
||||
| SetActiveAttachment Int
|
||||
|
@ -387,12 +387,22 @@ update inav env msg model =
|
||||
resultModel
|
||||
{ model | menuOpen = not model.menuOpen }
|
||||
|
||||
ReloadItem ->
|
||||
ReloadItem withFile ->
|
||||
if model.item.id == "" then
|
||||
resultModel model
|
||||
|
||||
else
|
||||
resultModelCmd ( model, Api.itemDetail env.flags model.item.id GetItemResp )
|
||||
resultModelCmd
|
||||
( model
|
||||
, Cmd.batch
|
||||
[ Api.itemDetail env.flags model.item.id GetItemResp
|
||||
, if withFile then
|
||||
Ports.refreshFileView "ds-pdf-view-iframe"
|
||||
|
||||
else
|
||||
Cmd.none
|
||||
]
|
||||
)
|
||||
|
||||
FolderDropdownMsg m ->
|
||||
let
|
||||
@ -1002,7 +1012,7 @@ update inav env msg model =
|
||||
|
||||
DeleteAttachResp (Ok res) ->
|
||||
if res.success then
|
||||
update inav env ReloadItem model
|
||||
update inav env (ReloadItem False) model
|
||||
|
||||
else
|
||||
resultModel model
|
||||
|
@ -5,7 +5,7 @@
|
||||
-}
|
||||
|
||||
|
||||
module Data.ServerEvent exposing (AddonInfo, ServerEvent(..), decode)
|
||||
module Data.ServerEvent exposing (AddonInfo, JobDoneDetails, ServerEvent(..), decode, isAddonExistingItem)
|
||||
|
||||
import Json.Decode as D
|
||||
import Json.Decode.Pipeline as P
|
||||
@ -13,7 +13,7 @@ import Json.Decode.Pipeline as P
|
||||
|
||||
type ServerEvent
|
||||
= JobSubmitted String
|
||||
| JobDone String
|
||||
| JobDone JobDoneDetails
|
||||
| JobsWaiting Int
|
||||
| AddonInstalled AddonInfo
|
||||
|
||||
@ -26,6 +26,32 @@ type alias AddonInfo =
|
||||
}
|
||||
|
||||
|
||||
type alias JobDoneDetails =
|
||||
{ task : String
|
||||
, args : Maybe D.Value
|
||||
, result : Maybe D.Value
|
||||
}
|
||||
|
||||
|
||||
{-| Return wether the job done details belong to running an addon of
|
||||
that item with the given id.
|
||||
-}
|
||||
isAddonExistingItem : String -> JobDoneDetails -> Bool
|
||||
isAddonExistingItem itemId details =
|
||||
let
|
||||
itemIdDecoder =
|
||||
D.field "itemId" D.string
|
||||
|
||||
-- This decodes the structure from scalas ItemAddonTaskArgs (only itemId)
|
||||
decodedId =
|
||||
Maybe.map (D.decodeValue itemIdDecoder) details.args
|
||||
|> Maybe.andThen Result.toMaybe
|
||||
in
|
||||
details.task
|
||||
== "addon-existing-item"
|
||||
&& (itemId /= "" && decodedId == Just itemId)
|
||||
|
||||
|
||||
addonInfoDecoder : D.Decoder AddonInfo
|
||||
addonInfoDecoder =
|
||||
D.succeed AddonInfo
|
||||
@ -51,8 +77,7 @@ decodeTag : String -> D.Decoder ServerEvent
|
||||
decodeTag tag =
|
||||
case tag of
|
||||
"job-done" ->
|
||||
D.field "content" D.string
|
||||
|> D.map JobDone
|
||||
D.field "content" (D.map JobDone decodeJobDoneDetails)
|
||||
|
||||
"job-submitted" ->
|
||||
D.field "content" D.string
|
||||
@ -68,3 +93,11 @@ decodeTag tag =
|
||||
|
||||
_ ->
|
||||
D.fail ("Unknown tag: " ++ tag)
|
||||
|
||||
|
||||
decodeJobDoneDetails : D.Decoder JobDoneDetails
|
||||
decodeJobDoneDetails =
|
||||
D.map3 JobDoneDetails
|
||||
(D.field "task" D.string)
|
||||
(D.field "args" (D.maybe D.value))
|
||||
(D.field "result" (D.maybe D.value))
|
||||
|
@ -14,6 +14,7 @@ module Page exposing
|
||||
, hasSidebar
|
||||
, href
|
||||
, isDashboardPage
|
||||
, isDetailPage
|
||||
, isOpen
|
||||
, isSearchPage
|
||||
, isSecured
|
||||
@ -175,6 +176,16 @@ isDashboardPage page =
|
||||
False
|
||||
|
||||
|
||||
isDetailPage : Page -> Bool
|
||||
isDetailPage page =
|
||||
case page of
|
||||
ItemDetailPage _ ->
|
||||
True
|
||||
|
||||
_ ->
|
||||
False
|
||||
|
||||
|
||||
pageName : Page -> String
|
||||
pageName page =
|
||||
case page of
|
||||
|
@ -38,6 +38,7 @@ type Msg
|
||||
| ItemResp (Result Http.Error ItemDetail)
|
||||
| ScrollResult (Result Dom.Error ())
|
||||
| UiSettingsUpdated
|
||||
| ReloadItem Bool
|
||||
|
||||
|
||||
type alias UpdateResult =
|
||||
|
@ -47,6 +47,13 @@ update inav env msg model =
|
||||
, selectedItems = env.selectedItems
|
||||
}
|
||||
|
||||
ReloadItem withFiles ->
|
||||
let
|
||||
m =
|
||||
ItemDetailMsg (Comp.ItemDetail.Model.ReloadItem withFiles)
|
||||
in
|
||||
update inav env m model
|
||||
|
||||
ItemDetailMsg lmsg ->
|
||||
let
|
||||
result =
|
||||
|
@ -11,6 +11,7 @@ port module Ports exposing
|
||||
, printElement
|
||||
, receiveCheckQueryResult
|
||||
, receiveServerEvent
|
||||
, refreshFileView
|
||||
, removeAccount
|
||||
, setAccount
|
||||
, setUiTheme
|
||||
@ -54,6 +55,11 @@ port printElement : String -> Cmd msg
|
||||
port receiveWsMessage : (D.Value -> msg) -> Sub msg
|
||||
|
||||
|
||||
{-| Given an ID of an element that is either EMBED or IFRAME the js will reload its src
|
||||
-}
|
||||
port refreshFileView : String -> Cmd msg
|
||||
|
||||
|
||||
|
||||
--- Higher level functions based on ports
|
||||
|
||||
|
@ -121,6 +121,16 @@ elmApp.ports.printElement.subscribe(function(id) {
|
||||
}
|
||||
});
|
||||
|
||||
elmApp.ports.refreshFileView.subscribe(function(id) {
|
||||
var el = document.getElementById(id);
|
||||
if (el) {
|
||||
var tag = el.tagName;
|
||||
if (tag === "EMBED" || tag === "IFRAME") {
|
||||
var url = el.src;
|
||||
el.src = url;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var dsWebSocket = null;
|
||||
function closeWS() {
|
||||
@ -146,6 +156,8 @@ function initWS() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Websockets are not used yet for communicating to the server
|
||||
// elmApp.ports.sendWsMessage.subscribe(function(msg) {
|
||||
// socket.send(msg);
|
||||
// });
|
||||
|
Loading…
x
Reference in New Issue
Block a user