Commit
•
680c32e
1
Parent(s):
deecaf3
chore: Remove unused logic from HomeLive
Browse files
lib/medical_transcription_web/live/home_live/index.ex
CHANGED
@@ -1,30 +1,13 @@
|
|
1 |
defmodule MedicalTranscriptionWeb.HomeLive.Index do
|
2 |
use MedicalTranscriptionWeb, :live_view
|
3 |
|
4 |
-
alias MedicalTranscription.Audio.RecordingPipeline
|
5 |
alias MedicalTranscription.Transcriptions
|
6 |
|
7 |
@impl Phoenix.LiveView
|
8 |
def mount(_params, session, socket) do
|
9 |
-
if connected?(socket), do: Phoenix.PubSub.subscribe(MedicalTranscription.PubSub, "transcriptions")
|
10 |
-
|
11 |
-
# We're storing atoms in `:status` as LiveView's AsyncResult doesn't support modeling a "pending" state, but only
|
12 |
-
# loading / ok / failed.
|
13 |
-
initial_state = %{
|
14 |
-
current_recording_id: 0,
|
15 |
-
uploaded_file_name: nil,
|
16 |
-
status: :pending,
|
17 |
-
audio_pipeline: nil,
|
18 |
-
summary_keywords: [],
|
19 |
-
transcriptions: list_transcriptions(session["current_user"]),
|
20 |
-
finalized_codes: []
|
21 |
-
}
|
22 |
-
|
23 |
socket =
|
24 |
socket
|
25 |
-
|> assign(
|
26 |
-
|> stream_configure(:transcription_rows, dom_id: &"transcription-row-#{&1.id}")
|
27 |
-
|> stream(:transcription_rows, [])
|
28 |
|> allow_upload(:audio, accept: ~w(.mp3), max_entries: 1)
|
29 |
|
30 |
{:ok, socket}
|
@@ -42,23 +25,11 @@ defmodule MedicalTranscriptionWeb.HomeLive.Index do
|
|
42 |
<main class="flex-1 pl-16 pr-16 pt-[25px]">
|
43 |
<div class="flex flex-col h-full mx-auto max-w-5xl">
|
44 |
<div class="flex-1 flex flex-col space-y-6">
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
summary_keywords={@summary_keywords}
|
51 |
-
finalized_codes={@finalized_codes}
|
52 |
-
/>
|
53 |
-
<% end %>
|
54 |
-
|
55 |
-
<%= if @status == :pending do %>
|
56 |
-
<div class="flex-1 flex flex-col justify-center items-center gap-4">
|
57 |
-
<img src={~p"/images/logo.svg"} width="106" />
|
58 |
-
<p class="text-2xl leading-normal font-semibold">Medical Code Transcriber</p>
|
59 |
-
</div>
|
60 |
-
<.upload_form audio_upload={@uploads.audio} />
|
61 |
-
<% end %>
|
62 |
</div>
|
63 |
</div>
|
64 |
</main>
|
@@ -85,132 +56,15 @@ defmodule MedicalTranscriptionWeb.HomeLive.Index do
|
|
85 |
{:ok, dest}
|
86 |
end)
|
87 |
|
88 |
-
{:ok, transcription} =
|
89 |
-
|
90 |
-
|
91 |
-
|
|
|
92 |
|
93 |
Transcriptions.transcribe_audio(transcription)
|
94 |
|
95 |
{:noreply, push_navigate(socket, to: ~p"/transcriptions/#{transcription.id}")}
|
96 |
-
#
|
97 |
-
# socket =
|
98 |
-
# socket
|
99 |
-
# |> assign(:status, :loading)
|
100 |
-
# |> assign(:summary_keywords, [])
|
101 |
-
# |> assign(:transcription_rows, [])
|
102 |
-
# |> assign(:uploaded_file_name, filename)
|
103 |
-
# |> assign(:transcriptions, list_transcriptions(socket.assigns.current_user))
|
104 |
-
#
|
105 |
-
# {:noreply, socket}
|
106 |
-
end
|
107 |
-
|
108 |
-
@impl true
|
109 |
-
def handle_event("add_feedback", params, socket) do
|
110 |
-
text_vector = MedicalTranscription.Coding.compute_vector_as_list(params["text"])
|
111 |
-
|
112 |
-
result =
|
113 |
-
params
|
114 |
-
|> Map.put("text_vector", text_vector)
|
115 |
-
|> MedicalTranscription.Feedback.track_response()
|
116 |
-
|
117 |
-
socket =
|
118 |
-
case result do
|
119 |
-
{:ok, message} -> put_flash(socket, :info, message)
|
120 |
-
{:error, messages} -> put_flash(socket, :error, messages)
|
121 |
-
end
|
122 |
-
|
123 |
-
{:noreply, socket}
|
124 |
-
end
|
125 |
-
|
126 |
-
@impl true
|
127 |
-
def handle_event("reset_to_pending", _params, socket) do
|
128 |
-
{:noreply, assign(socket, :status, :pending)}
|
129 |
-
end
|
130 |
-
|
131 |
-
@impl true
|
132 |
-
def handle_event("toggle_recording", _params, socket) do
|
133 |
-
socket =
|
134 |
-
if is_nil(socket.assigns.audio_pipeline) do
|
135 |
-
pipeline = RecordingPipeline.start_pipeline(self())
|
136 |
-
|
137 |
-
socket
|
138 |
-
|> assign(:status, :streaming_audio)
|
139 |
-
|> assign(:audio_pipeline, pipeline)
|
140 |
-
else
|
141 |
-
RecordingPipeline.stop_pipeline(socket.assigns.audio_pipeline)
|
142 |
-
|
143 |
-
socket
|
144 |
-
|> assign(:status, :success)
|
145 |
-
|> assign(:audio_pipeline, nil)
|
146 |
-
end
|
147 |
-
|
148 |
-
{:noreply, socket}
|
149 |
-
end
|
150 |
-
|
151 |
-
@impl true
|
152 |
-
def handle_info({:chunk, chunk_result}, socket) do
|
153 |
-
# The processing sends a message as each chunk of text is coded. See here for some background and potential
|
154 |
-
# inspiration for this: https://elixirforum.com/t/liveview-asynchronous-task-patterns/44695
|
155 |
-
|
156 |
-
{:noreply, stream_insert(socket, :transcription_rows, chunk_result)}
|
157 |
-
end
|
158 |
-
|
159 |
-
@impl true
|
160 |
-
def handle_info({:new_keywords, new_keywords}, socket) do
|
161 |
-
socket =
|
162 |
-
update(socket, :summary_keywords, fn keywords -> keywords ++ [new_keywords] end)
|
163 |
-
|
164 |
-
{:noreply, socket}
|
165 |
-
end
|
166 |
-
|
167 |
-
@impl true
|
168 |
-
def handle_info({:received_audio_payload, transcribed_text}, socket) do
|
169 |
-
tags = MedicalTranscription.Coding.process_chunk(transcribed_text)
|
170 |
-
|
171 |
-
result = %{
|
172 |
-
id: socket.assigns.current_recording_id + 1,
|
173 |
-
start_mark: nil,
|
174 |
-
end_mark: nil,
|
175 |
-
text: transcribed_text,
|
176 |
-
tags: tags
|
177 |
-
}
|
178 |
-
|
179 |
-
socket =
|
180 |
-
socket
|
181 |
-
|> assign(:status, :streaming_audio)
|
182 |
-
|> stream_insert(:transcription_rows, result)
|
183 |
-
|> assign(:current_recording_id, result.id)
|
184 |
-
|
185 |
-
{:noreply, socket}
|
186 |
-
end
|
187 |
-
|
188 |
-
@impl Phoenix.LiveView
|
189 |
-
def handle_info({"toggle_user_selected_code", {:add, code}}, socket) do
|
190 |
-
new_codes =
|
191 |
-
if Enum.any?(socket.assigns.finalized_codes, code) do
|
192 |
-
socket.assigns.finalized_codes
|
193 |
-
else
|
194 |
-
socket.assigns.finalized_codes ++ [code]
|
195 |
-
end
|
196 |
-
|
197 |
-
{:noreply, assign(socket, :finalized_codes, new_codes)}
|
198 |
-
end
|
199 |
-
|
200 |
-
@impl Phoenix.LiveView
|
201 |
-
def handle_info({"toggle_user_selected_code", {:remove, code}}, socket) do
|
202 |
-
new_codes = Enum.reject(socket.assigns.finalized_codes, &(&1 == code))
|
203 |
-
|
204 |
-
{:noreply, assign(socket, :finalized_codes, new_codes)}
|
205 |
-
end
|
206 |
-
|
207 |
-
@impl true
|
208 |
-
def handle_info({ref, _result}, socket) do
|
209 |
-
# See this Fly article for the usage of Task.async to start `transcribe_and_tag_audio/2` and handle the end of the
|
210 |
-
# task here: https://fly.io/phoenix-files/liveview-async-task/
|
211 |
-
Process.demonitor(ref, [:flush])
|
212 |
-
|
213 |
-
{:noreply, assign(socket, :status, :success)}
|
214 |
end
|
215 |
|
216 |
def error_to_string(:too_large), do: "Too large"
|
|
|
1 |
defmodule MedicalTranscriptionWeb.HomeLive.Index do
|
2 |
use MedicalTranscriptionWeb, :live_view
|
3 |
|
|
|
4 |
alias MedicalTranscription.Transcriptions
|
5 |
|
6 |
@impl Phoenix.LiveView
|
7 |
def mount(_params, session, socket) do
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
socket =
|
9 |
socket
|
10 |
+
|> assign(:transcriptions, list_transcriptions(session["current_user"]))
|
|
|
|
|
11 |
|> allow_upload(:audio, accept: ~w(.mp3), max_entries: 1)
|
12 |
|
13 |
{:ok, socket}
|
|
|
25 |
<main class="flex-1 pl-16 pr-16 pt-[25px]">
|
26 |
<div class="flex flex-col h-full mx-auto max-w-5xl">
|
27 |
<div class="flex-1 flex flex-col space-y-6">
|
28 |
+
<div class="flex-1 flex flex-col justify-center items-center gap-4">
|
29 |
+
<img src={~p"/images/logo.svg"} width="106" />
|
30 |
+
<p class="text-2xl leading-normal font-semibold">Medical Code Transcriber</p>
|
31 |
+
</div>
|
32 |
+
<.upload_form audio_upload={@uploads.audio} />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
</div>
|
34 |
</div>
|
35 |
</main>
|
|
|
56 |
{:ok, dest}
|
57 |
end)
|
58 |
|
59 |
+
{:ok, transcription} =
|
60 |
+
Transcriptions.create_transcription(%{
|
61 |
+
user_id: socket.assigns.current_user.id,
|
62 |
+
filename: Enum.at(uploaded_files, 0)
|
63 |
+
})
|
64 |
|
65 |
Transcriptions.transcribe_audio(transcription)
|
66 |
|
67 |
{:noreply, push_navigate(socket, to: ~p"/transcriptions/#{transcription.id}")}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
end
|
69 |
|
70 |
def error_to_string(:too_large), do: "Too large"
|