defmodule ChoreRunnerUI.DownloadsLive do
@moduledoc """
A LiveView used in conjunction with ChoreRunner's regular functionality.
Allows viewing and downloading of files generated by Chores.
## Usage
Make sure that `Chore.Supervisor` is added in your application
```
children = [
{Phoenix.PubSub, name: MyApp.PubSub},
{ChoreRunner, pubsub: MyApp.PubSub}
]
```
A pubsub MUST BE RUNNING and configured for both the Chore supervisor and the ChoreRunner LiveViews for the Downloads UI to function.
Make the Downloads LiveView and downloadable files accessible in your Phoenix web app by modifying the router.
### Router
```
@chore_session %{
"otp_app" => :my_app,
"chore_root" => MyApp.Chores,
"pubsub" => MyApp.PubSub
}
scope "/" do
pipe_through :browser
live_session :chores, session: @chore_session do
live "/", ChoreRunnerUI.ChoreLive, :index
live "/", ChoreRunnerUI.DownloadsLive, :index
end
forward "/chore_downloads", ChoreRunnerUI.DownloadsPlug
end
```
The `"chore_root"` key in the session should be the module root that all of your chore modules use.
For example: if your root is `MyApp.Chores` your chore modules should be named like `MyApp.Chores.MyChore`
Now you can visit the speficied url and start running chores!
"""
use ChoreRunnerUI, :live
alias Phoenix.PubSub
alias ChoreRunner.Downloads
alias ChoreRunner.Downloads.StorageService
require Logger
@impl true
def mount(params, session, socket) do
socket =
assign(socket,
pubsub: subscribe_to_pubsub(session),
download_plug_path: Map.get(params, :download_plug_path, "/chores/download"),
chore_live_path: Map.get(params, :chore_live_path, "/chores")
)
|> refresh_downloads()
{:ok, socket}
end
@impl true
def handle_event("delete", %{"id" => id}, socket) do
with %{} = download <- StorageService.find_file(id) do
Downloads.delete_download(download)
end
PubSub.broadcast(
socket.assigns.pubsub,
ChoreRunner.downloads_pubsub_topic(),
:downloads_updated
)
{:noreply, refresh_downloads(socket)}
end
@impl true
def handle_info(:downloads_updated, socket) do
{:noreply, refresh_downloads(socket)}
end
defp refresh_downloads(socket), do: assign(socket, downloads: Downloads.list_downloads())
defp subscribe_to_pubsub(%{"pubsub" => pubsub}) do
Process.put(:chore_pubsub, pubsub)
PubSub.subscribe(pubsub, ChoreRunner.downloads_pubsub_topic())
pubsub
end
defp download_link(download_plug_path, download),
do:
ChoreRunner.Downloads.StorageService.file_url(download,
download_plug_path: download_plug_path
)
end