Download lib/medicode_web/components/code_select.ex from headway/medicode: direct link, hf CLI and curl.
- Browser
- Download file 4.8 kB
-
https://huggingface.co/spaces/headway/medicode/resolve/main/lib/medicode_web/components/code_select.ex
- Command line
-
hf download hf://spaces/headway/medicode/lib/medicode_web/components/code_select.ex
-
curl -L -o code_select.ex https://huggingface.co/spaces/headway/medicode/resolve/main/lib/medicode_web/components/code_select.ex
4.8 kB
| defmodule MedicodeWeb.Components.CodeSelect do | |
| @moduledoc """ | |
| An auto-complete select field that allows users to search for codes to add by either `code` or `description`. | |
| """ | |
| use MedicodeWeb, :live_component | |
| import MedicodeWeb.Components, only: [code_display: 1] | |
| alias Medicode.Feedback | |
| alias Medicode.Transcriptions | |
| @impl Phoenix.LiveComponent | |
| def mount(socket) do | |
| socket = | |
| socket | |
| |> assign(:codes, []) | |
| |> assign(:selected_code, nil) | |
| |> assign(:submitted_code_feedback, nil) | |
| {:ok, socket} | |
| end | |
| @impl Phoenix.LiveComponent | |
| def update( | |
| %{id: id, text: text, current_user: current_user, chunk: chunk} = _assigns, | |
| socket | |
| ) do | |
| form = to_form(%{"search_term" => ""}, as: id) | |
| socket = | |
| socket | |
| |> assign(:form, form) | |
| |> assign(:text, text) | |
| |> assign(:current_user, current_user) | |
| |> assign(:chunk, chunk) | |
| {:ok, socket} | |
| end | |
| @impl Phoenix.LiveComponent | |
| def render(assigns) do | |
| ~H""" | |
| <div class="w-full" phx-click-away="clear-codes" phx-target={@myself}> | |
| <%= if is_nil(@selected_code) do %> | |
| <.form for={@form} phx-change="suggest-code" phx-target={@myself} class="relative"> | |
| <.input | |
| type="text" | |
| field={@form[:search_term]} | |
| class="w-full rounded" | |
| style={if length(@codes) > 0, do: "border-radius: 0.25rem 0.25rem 0 0 !important;"} | |
| placeholder="Search for another code..." | |
| /> | |
| <div | |
| :if={length(@codes) > 0} | |
| class="absolute z-10 w-full bg-white border-l border-r border-b border-zinc-400 rounded-b overflow-hidden" | |
| > | |
| <button | |
| :for={code <- @codes} | |
| type="button" | |
| class="w-full text-left px-2 py-1 text-sm border-b border-zinc-100 last:border-b-0 hover:bg-blue-200" | |
| phx-click="choose-code" | |
| phx-value-code={code.code} | |
| phx-target={@myself} | |
| > | |
| <%= code.code %>: <%= code.description %> | |
| </button> | |
| </div> | |
| </.form> | |
| <% else %> | |
| <div class="px-[14px]"> | |
| <div class="flex justify-between pb-1 border-b border-zinc-300"> | |
| <p class="leading-normal font-bold text-type-black-primary uppercase"> | |
| User-selected code | |
| </p> | |
| <button type="button" phx-click="clear-code" phx-target={@myself}> | |
| <.icon name="hero-x-circle" /> | |
| </button> | |
| </div> | |
| <.code_display code={@selected_code.code} label={@selected_code.description} /> | |
| </div> | |
| <% end %> | |
| </div> | |
| """ | |
| end | |
| @impl Phoenix.LiveComponent | |
| def handle_event("suggest-code", params, socket) do | |
| form_id = socket.assigns.form.id | |
| %{^form_id => %{"search_term" => value}} = params | |
| suggested_codes = Medicode.Coding.search_for_code_vector(value) | |
| {:noreply, assign(socket, :codes, suggested_codes)} | |
| end | |
| def handle_event("clear-codes", _params, socket) do | |
| {:noreply, assign(socket, :codes, [])} | |
| end | |
| def handle_event("choose-code", %{"code" => code}, socket) do | |
| selected_code = Enum.find(socket.assigns.codes, &(&1.code == code)) | |
| text_vector = Medicode.Coding.compute_vector_as_list(socket.assigns.text) | |
| code_feedback = | |
| Feedback.insert_and_return(%{ | |
| text: socket.assigns.text, | |
| text_vector: text_vector, | |
| response: true, | |
| code_vector_id: selected_code.id | |
| }) | |
| Transcriptions.upsert_code_vector_for_transcription_chunk(%{ | |
| assigned_by_user_id: socket.assigns.current_user.id, | |
| code_vector_id: selected_code.id, | |
| transcription_chunk_id: socket.assigns.chunk.id, | |
| cosine_similarity: | |
| Medicode.Coding.get_cosine_similarity(text_vector, selected_code.description_vector) | |
| }) | |
| Phoenix.PubSub.broadcast( | |
| :medicode_pubsub, | |
| "transcriptions:#{socket.assigns.chunk.transcription_id}", | |
| {:transcription_chunk_updated, socket.assigns.chunk.id} | |
| ) | |
| socket = | |
| if is_nil(code_feedback) do | |
| put_flash(socket, :error, "Failed to record feedback") | |
| else | |
| socket | |
| |> assign(:selected_code, selected_code) | |
| |> assign(:submitted_code_feedback, code_feedback) | |
| |> assign(:codes, []) | |
| end | |
| {:noreply, socket} | |
| end | |
| @impl Phoenix.LiveComponent | |
| def handle_event( | |
| "clear-code", | |
| _params, | |
| %{assigns: %{submitted_code_feedback: submitted_code_feedback}} = socket | |
| ) do | |
| # Delete previous code feedback | |
| Feedback.delete(submitted_code_feedback) | |
| socket = | |
| socket | |
| |> assign(:codes, []) | |
| |> assign(:selected_code, nil) | |
| |> assign(:submitted_code_feedback, nil) | |
| {:noreply, socket} | |
| end | |
| end | |