defmodule OutlookWeb.TranslationLive.FormComponent do use OutlookWeb, :live_component alias Outlook.{Translations,InternalTree} alias Outlook.InternalTree.TranslationUnit @impl true def render(assigns) do ~H"""
<.header> <%= @title %> <:subtitle>Use this form to manage translation records in your database. <.simple_form :let={f} for={@changeset} id="translation-form" phx-target={@myself} phx-change="validate" phx-submit="save" > <.input field={{f, :article_id}} type="hidden" /> <.input field={{f, :language}} type="select" label="language" options={Application.get_env(:outlook,:deepl)[:target_langs]} /> <.input field={{f, :title}} type="text" label="title" /> <.input field={{f, :teaser}} type="textarea" label="teaser" class="h-28" /> <.input field={{f, :date}} type="datetime-local" label="date" />
<.input field={{f, :public}} type="checkbox" label="public" /> <.input field={{f, :unauthorized}} type="checkbox" label="unauthorized" />
<:actions> <.button phx-click={JS.set_attribute({"value", "false"}, to: "#continue_edit") |> JS.set_attribute({"value", "false"}, to: "#publish")} phx-disable-with="Saving...">Save Translation <.button phx-click={JS.set_attribute({"value", "false"}, to: "#continue_edit") |> JS.set_attribute({"value", "true"}, to: "#publish")} phx-disable-with="Saving...">Save and Publish <.button phx-click={JS.set_attribute({"value", "true"}, to: "#continue_edit") |> JS.set_attribute({"value", "false"}, to: "#publish")} phx-disable-with="Saving...">Save and Edit <.tunit_editor current_tunit={@current_tunit} target={@myself} />
<.button phx-disable-with="Translating..." phx-click="translate-deepl" phx-target={@myself} data-confirm-not="Are you sure? All previously translated text will be lost.">Translate with Deepl <.render_doc tree={@article_tree} />
""" end @impl true def update(%{translation: translation} = assigns, socket) do changeset = Translations.change_translation(translation) {:ok, socket |> assign(assigns) |> assign(:current_tunit, %TranslationUnit{status: nil}) |> assign(:changeset, changeset) |> assign_article_tree(translation) |> assign(:deepl_progress, nil)} end def update(%{progress: progress}, socket) do {:ok, socket |> assign(deepl_progress: progress)} end def update(%{deepl_translation: translation}, socket) do tunit_keys = Map.keys(socket.assigns.translation_content) case Outlook.Translators.process_translation_result(translation, tunit_keys, socket.assigns.current_user) do {:ok, new_translation_content} -> {:ok, socket |> assign(translation_content: new_translation_content) |> update_current_tunit(socket.assigns.current_tunit.status)} {:error, message} -> {:ok, socket |> put_flash(:error, message)} end end @impl true def handle_event("translate-deepl", _, socket) do Outlook.Translators.translate(socket.assigns.translation, socket.assigns.current_user) {:noreply, socket} end def handle_event("validate", %{"translation" => translation_params}, socket) do changeset = socket.assigns.translation |> Translations.change_translation(translation_params) |> Map.put(:action, :validate) {:noreply, assign(socket, :changeset, changeset)} end def handle_event("save", %{"translation" => translation_params} = params, socket) do socket = socket |> update_translation_with_current_tunit(socket.assigns.current_tunit.status) params = %{params | "translation" => Map.put( translation_params, "content", socket.assigns.translation_content ) |> publish(params, socket) } save_translation(socket, socket.assigns.action, params) end def handle_event("tunit_status", %{"status" => status}, socket) do tunit = %TranslationUnit{socket.assigns.current_tunit | status: String.to_atom(status)} {:noreply, socket |> assign(:current_tunit, tunit)} end def handle_event("select_current_tunit", %{"nid" => nid}, socket) do {:noreply, socket |> update_translation_with_current_tunit(socket.assigns.current_tunit.status) |> assign(:current_tunit, socket.assigns.translation_content[nid])} end @doc "updating on browser events" def handle_event("update_current_tunit", %{"content" => content}, socket) do tunit = %TranslationUnit{socket.assigns.current_tunit | content: content} {:noreply, socket |> assign(:current_tunit, tunit)} end # updating after Deepl translation defp update_current_tunit(socket, nil), do: socket defp update_current_tunit(socket, _) do assign(socket, :current_tunit, socket.assigns.translation_content[socket.assigns.current_tunit.nid]) end defp assign_article_tree(socket, translation) do socket |> assign( :article_tree, InternalTree.add_phx_click_event(translation.article.content, nodes: :tunits, click: "select_current_tunit", target: socket.assigns.myself)) end defp update_translation_with_current_tunit(socket, nil), do: socket defp update_translation_with_current_tunit(socket, _) do socket |> assign(:translation_content, socket.assigns.translation_content |> Map.put(socket.assigns.current_tunit.nid, socket.assigns.current_tunit)) end defp save_translation(socket, :edit, %{"translation" => translation_params} = params) do case Translations.update_translation(socket.assigns.translation, translation_params) do {:ok, _translation} -> {:noreply, socket |> put_flash(:info, "Translation updated successfully") |> continue_edit(params)} {:error, %Ecto.Changeset{} = changeset} -> {:noreply, assign(socket, :changeset, changeset)} end end defp save_translation(socket, :new, %{"translation" => translation_params} = params) do case Translations.create_translation(translation_params) do {:ok, _translation} -> {:noreply, socket |> put_flash(:info, "Translation created successfully") |> continue_edit(params)} {:error, %Ecto.Changeset{} = changeset} -> {:noreply, assign(socket, changeset: changeset)} end end defp continue_edit(socket, %{"continue_edit" => "true"}) do socket |> assign(:action, :edit) end defp continue_edit(socket, %{"continue_edit" => "false"}) do socket |> push_navigate(to: socket.assigns.navigate) end defp publish(translation_params, %{"publish" => "true"}, socket) do translation_params |> Map.put("public_content", OutlookWeb.HtmlDocComponent.render_doc(%{tree: InternalTree.render_translation(socket.assigns.translation.article.content, translation_params["content"]), tunit_tag: "span"}) |> Phoenix.HTML.Safe.to_iodata() |> IO.iodata_to_binary()) end defp publish(translation_params, %{"publish" => "false"}, _) do translation_params end end