changed tags editor into live component
This commit is contained in:
@@ -182,10 +182,6 @@ defmodule BDS.Desktop.ShellLive do
|
|||||||
|> assign(:settings_editor_new_category, "")
|
|> assign(:settings_editor_new_category, "")
|
||||||
|> assign(:style_editor_theme, nil)
|
|> assign(:style_editor_theme, nil)
|
||||||
|> assign(:style_editor_preview_mode, "auto")
|
|> assign(:style_editor_preview_mode, "auto")
|
||||||
|> assign(:tags_editor_selected, [])
|
|
||||||
|> assign(:tags_editor_new_tag, %{"name" => "", "color" => ""})
|
|
||||||
|> assign(:tags_editor_edit_draft, %{})
|
|
||||||
|> assign(:tags_editor_merge_target, "")
|
|
||||||
|> assign(:script_editor_drafts, %{})
|
|> assign(:script_editor_drafts, %{})
|
||||||
|> assign(:template_editor_drafts, %{})
|
|> assign(:template_editor_drafts, %{})
|
||||||
|> assign(:chat_editor_inputs, %{})
|
|> assign(:chat_editor_inputs, %{})
|
||||||
@@ -682,42 +678,6 @@ defmodule BDS.Desktop.ShellLive do
|
|||||||
{:noreply, MenuEditor.handle_keydown(socket, key, &reload_shell/2)}
|
{:noreply, MenuEditor.handle_keydown(socket, key, &reload_shell/2)}
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_event("toggle_tag_selection", %{"name" => tag_name}, socket) do
|
|
||||||
{:noreply, TagsEditor.toggle_selection(socket, tag_name, &reload_shell/2)}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_event("change_new_tag_editor", %{"new_tag" => params}, socket) do
|
|
||||||
{:noreply, TagsEditor.update_new_tag(socket, params, &reload_shell/2)}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_event("create_tag_editor", _params, socket) do
|
|
||||||
{:noreply, TagsEditor.create_tag(socket, &reload_shell/2, &append_output_entry/5)}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_event("change_edit_tag_editor", %{"edit_tag" => params}, socket) do
|
|
||||||
{:noreply, TagsEditor.update_edit_tag(socket, params, &reload_shell/2)}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_event("save_tag_editor", _params, socket) do
|
|
||||||
{:noreply, TagsEditor.save_tag(socket, &reload_shell/2, &append_output_entry/5)}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_event("delete_tag_editor", _params, socket) do
|
|
||||||
{:noreply, TagsEditor.delete_selected(socket, &reload_shell/2, &append_output_entry/5)}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_event("change_merge_target", %{"target" => target}, socket) do
|
|
||||||
{:noreply, TagsEditor.update_merge_target(socket, target, &reload_shell/2)}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_event("merge_tags_editor", _params, socket) do
|
|
||||||
{:noreply, TagsEditor.merge_selected(socket, &reload_shell/2, &append_output_entry/5)}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_event("sync_tags_editor", _params, socket) do
|
|
||||||
{:noreply, TagsEditor.sync(socket, &reload_shell/2, &append_output_entry/5)}
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_event("change_script_editor", %{"script_editor" => params}, socket) do
|
def handle_event("change_script_editor", %{"script_editor" => params}, socket) do
|
||||||
{:noreply, CodeEntityEditor.update_script(socket, params, &reload_shell/2)}
|
{:noreply, CodeEntityEditor.update_script(socket, params, &reload_shell/2)}
|
||||||
end
|
end
|
||||||
@@ -1483,6 +1443,14 @@ defmodule BDS.Desktop.ShellLive do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def handle_info({:tags_editor_output, title, message, level}, socket) do
|
||||||
|
{:noreply, append_output_entry(socket, title, message, nil, level)}
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_info(:tags_changed, socket) do
|
||||||
|
{:noreply, reload_shell(socket, socket.assigns.workbench)}
|
||||||
|
end
|
||||||
|
|
||||||
@impl true
|
@impl true
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
UILocale.put(assigns.page_language)
|
UILocale.put(assigns.page_language)
|
||||||
@@ -1555,7 +1523,6 @@ defmodule BDS.Desktop.ShellLive do
|
|||||||
|> assign_media_editor()
|
|> assign_media_editor()
|
||||||
|> assign_settings_editor()
|
|> assign_settings_editor()
|
||||||
|> assign_menu_editor()
|
|> assign_menu_editor()
|
||||||
|> assign_tags_editor()
|
|
||||||
|> assign_code_entity_editor()
|
|> assign_code_entity_editor()
|
||||||
|> assign_chat_editor()
|
|> assign_chat_editor()
|
||||||
|> assign_import_editor()
|
|> assign_import_editor()
|
||||||
@@ -1617,10 +1584,6 @@ defmodule BDS.Desktop.ShellLive do
|
|||||||
MenuEditor.assign_socket(socket)
|
MenuEditor.assign_socket(socket)
|
||||||
end
|
end
|
||||||
|
|
||||||
defp assign_tags_editor(socket) do
|
|
||||||
TagsEditor.assign_socket(socket)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp assign_code_entity_editor(socket) do
|
defp assign_code_entity_editor(socket) do
|
||||||
CodeEntityEditor.assign_socket(socket)
|
CodeEntityEditor.assign_socket(socket)
|
||||||
end
|
end
|
||||||
@@ -1801,7 +1764,8 @@ defmodule BDS.Desktop.ShellLive do
|
|||||||
end
|
end
|
||||||
|
|
||||||
defp save_current_tab(%{assigns: %{current_tab: %{type: :tags}}} = socket) do
|
defp save_current_tab(%{assigns: %{current_tab: %{type: :tags}}} = socket) do
|
||||||
TagsEditor.save_tag(socket, &reload_shell/2, &append_output_entry/5)
|
send_update(TagsEditor, id: "tags-editor", action: :save)
|
||||||
|
socket
|
||||||
end
|
end
|
||||||
|
|
||||||
defp save_current_tab(%{assigns: %{current_tab: %{type: :scripts}}} = socket) do
|
defp save_current_tab(%{assigns: %{current_tab: %{type: :scripts}}} = socket) do
|
||||||
|
|||||||
@@ -397,8 +397,8 @@
|
|||||||
<% @current_tab.type == :menu_editor and @menu_editor -> %>
|
<% @current_tab.type == :menu_editor and @menu_editor -> %>
|
||||||
<MenuEditor.menu_editor menu_editor={@menu_editor} />
|
<MenuEditor.menu_editor menu_editor={@menu_editor} />
|
||||||
|
|
||||||
<% @current_tab.type == :tags and @tags_editor -> %>
|
<% @current_tab.type == :tags and @current_project -> %>
|
||||||
<TagsEditor.tags_editor tags_editor={@tags_editor} />
|
<.live_component module={TagsEditor} id="tags-editor" project_id={@current_project.id} current_tab={@current_tab} tab_meta={@tab_meta} />
|
||||||
|
|
||||||
<% @current_tab.type == :scripts and @script_editor -> %>
|
<% @current_tab.type == :scripts and @script_editor -> %>
|
||||||
<CodeEntityEditor.script_editor script_editor={@script_editor} />
|
<CodeEntityEditor.script_editor script_editor={@script_editor} />
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
defmodule BDS.Desktop.ShellLive.TagsEditor do
|
defmodule BDS.Desktop.ShellLive.TagsEditor do
|
||||||
@moduledoc false
|
@moduledoc false
|
||||||
|
|
||||||
use Phoenix.Component
|
use Phoenix.LiveComponent
|
||||||
|
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
|
||||||
alias BDS.Desktop.ShellData
|
|
||||||
alias BDS.{Repo, Tags}
|
alias BDS.{Repo, Tags}
|
||||||
|
alias BDS.Desktop.ShellData
|
||||||
|
alias BDS.Desktop.UILocale
|
||||||
alias BDS.Posts.Post
|
alias BDS.Posts.Post
|
||||||
alias BDS.Tags.Tag
|
alias BDS.Tags.Tag
|
||||||
alias BDS.Templates.Template
|
alias BDS.Templates.Template
|
||||||
@@ -15,14 +16,37 @@ defmodule BDS.Desktop.ShellLive.TagsEditor do
|
|||||||
|
|
||||||
@tags_sections ~w(cloud manage merge)
|
@tags_sections ~w(cloud manage merge)
|
||||||
|
|
||||||
@spec assign_socket(term()) :: term()
|
@spec update(map(), Phoenix.LiveView.Socket.t()) :: {:ok, Phoenix.LiveView.Socket.t()}
|
||||||
def assign_socket(socket) do
|
@impl true
|
||||||
assign(socket, :tags_editor, build(socket.assigns))
|
def update(%{action: :save} = assigns, socket) do
|
||||||
|
socket =
|
||||||
|
socket
|
||||||
|
|> assign(Map.drop(assigns, [:action]))
|
||||||
|
|> do_save()
|
||||||
|
|
||||||
|
{:ok, socket}
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec toggle_selection(term(), term(), term()) :: term()
|
def update(assigns, socket) do
|
||||||
def toggle_selection(socket, tag_name, reload) do
|
socket =
|
||||||
selected = Map.get(socket.assigns, :tags_editor_selected, [])
|
socket
|
||||||
|
|> assign(assigns)
|
||||||
|
|> load_data()
|
||||||
|
|
||||||
|
{:ok, socket}
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec render(map()) :: Phoenix.LiveView.Rendered.t()
|
||||||
|
@impl true
|
||||||
|
def render(assigns) do
|
||||||
|
tags_editor(assigns)
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec handle_event(String.t(), map(), Phoenix.LiveView.Socket.t()) ::
|
||||||
|
{:noreply, Phoenix.LiveView.Socket.t()}
|
||||||
|
@impl true
|
||||||
|
def handle_event("toggle_tag_selection", %{"name" => tag_name}, socket) do
|
||||||
|
selected = socket.assigns.tags_editor.selected
|
||||||
|
|
||||||
next_selected =
|
next_selected =
|
||||||
if tag_name in selected do
|
if tag_name in selected do
|
||||||
@@ -31,26 +55,27 @@ defmodule BDS.Desktop.ShellLive.TagsEditor do
|
|||||||
selected ++ [tag_name]
|
selected ++ [tag_name]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
socket =
|
||||||
socket
|
socket
|
||||||
|> assign(:tags_editor_selected, next_selected)
|
|> put_in_tags_editor([:selected], next_selected)
|
||||||
|> maybe_seed_edit_draft(next_selected)
|
|> maybe_seed_edit_draft(socket.assigns.project_id, next_selected)
|
||||||
|> reload.(socket.assigns.workbench)
|
|
||||||
|
{:noreply, socket}
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec update_new_tag(term(), term(), term()) :: term()
|
def handle_event("change_new_tag_editor", %{"new_tag" => params}, socket) do
|
||||||
def update_new_tag(socket, params, reload) do
|
tags_editor =
|
||||||
socket
|
Map.put(socket.assigns.tags_editor, :new_tag, %{
|
||||||
|> assign(:tags_editor_new_tag, %{
|
|
||||||
"name" => Map.get(params, "name", ""),
|
"name" => Map.get(params, "name", ""),
|
||||||
"color" => Map.get(params, "color", "")
|
"color" => Map.get(params, "color", "")
|
||||||
})
|
})
|
||||||
|> reload.(socket.assigns.workbench)
|
|
||||||
|
{:noreply, assign(socket, :tags_editor, tags_editor)}
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec create_tag(term(), term(), term()) :: term()
|
def handle_event("create_tag_editor", _params, socket) do
|
||||||
def create_tag(socket, reload, append_output) do
|
project_id = socket.assigns.project_id
|
||||||
project_id = socket.assigns.projects.active_project_id
|
draft = socket.assigns.tags_editor.new_tag
|
||||||
draft = Map.get(socket.assigns, :tags_editor_new_tag, %{})
|
|
||||||
|
|
||||||
case Tags.create_tag(%{
|
case Tags.create_tag(%{
|
||||||
project_id: project_id,
|
project_id: project_id,
|
||||||
@@ -58,115 +83,83 @@ defmodule BDS.Desktop.ShellLive.TagsEditor do
|
|||||||
color: blank_to_nil(Map.get(draft, "color"))
|
color: blank_to_nil(Map.get(draft, "color"))
|
||||||
}) do
|
}) do
|
||||||
{:ok, _tag} ->
|
{:ok, _tag} ->
|
||||||
|
notify_parent(:tags_changed)
|
||||||
|
|
||||||
socket
|
socket
|
||||||
|> assign(:tags_editor_new_tag, %{"name" => "", "color" => ""})
|
|> put_in_tags_editor([:new_tag], %{"name" => "", "color" => ""})
|
||||||
|> reload.(socket.assigns.workbench)
|
|> load_data()
|
||||||
|
|> noreply()
|
||||||
|
|
||||||
{:error, reason} ->
|
{:error, reason} ->
|
||||||
socket
|
notify_output(translated("Tags"), inspect(reason), "error")
|
||||||
|> append_output.(translated("Tags"), inspect(reason), nil, "error")
|
{:noreply, socket}
|
||||||
|> reload.(socket.assigns.workbench)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec update_edit_tag(term(), term(), term()) :: term()
|
def handle_event("change_edit_tag_editor", %{"edit_tag" => params}, socket) do
|
||||||
def update_edit_tag(socket, params, reload) do
|
tags_editor =
|
||||||
socket
|
Map.put(socket.assigns.tags_editor, :edit_draft, %{
|
||||||
|> assign(:tags_editor_edit_draft, %{
|
|
||||||
"name" => Map.get(params, "name", ""),
|
"name" => Map.get(params, "name", ""),
|
||||||
"color" => Map.get(params, "color", ""),
|
"color" => Map.get(params, "color", ""),
|
||||||
"post_template_slug" => Map.get(params, "post_template_slug", "")
|
"post_template_slug" => Map.get(params, "post_template_slug", "")
|
||||||
})
|
})
|
||||||
|> reload.(socket.assigns.workbench)
|
|
||||||
|
{:noreply, assign(socket, :tags_editor, tags_editor)}
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec save_tag(term(), term(), term()) :: term()
|
def handle_event("save_tag_editor", _params, socket) do
|
||||||
def save_tag(socket, reload, append_output) do
|
{:noreply, do_save(socket)}
|
||||||
selected = Map.get(socket.assigns, :tags_editor_selected, [])
|
end
|
||||||
draft = Map.get(socket.assigns, :tags_editor_edit_draft, %{})
|
|
||||||
|
|
||||||
case selected do
|
def handle_event("delete_tag_editor", _params, socket) do
|
||||||
|
case socket.assigns.tags_editor.selected do
|
||||||
[tag_name] ->
|
[tag_name] ->
|
||||||
case Repo.get_by(Tag,
|
case Repo.get_by(Tag,
|
||||||
project_id: socket.assigns.projects.active_project_id,
|
project_id: socket.assigns.project_id,
|
||||||
name: tag_name
|
name: tag_name
|
||||||
) do
|
) do
|
||||||
nil ->
|
nil ->
|
||||||
reload.(socket, socket.assigns.workbench)
|
{:noreply, socket}
|
||||||
|
|
||||||
%Tag{} = tag ->
|
|
||||||
with {:ok, _updated_tag} <-
|
|
||||||
Tags.update_tag(tag.id, %{
|
|
||||||
color: blank_to_nil(Map.get(draft, "color")),
|
|
||||||
post_template_slug: blank_to_nil(Map.get(draft, "post_template_slug"))
|
|
||||||
}),
|
|
||||||
{:ok, renamed_tag} <- maybe_rename_tag(tag, Map.get(draft, "name", tag.name)) do
|
|
||||||
socket
|
|
||||||
|> assign(:tags_editor_selected, [renamed_tag.name])
|
|
||||||
|> maybe_seed_edit_draft([renamed_tag.name])
|
|
||||||
|> reload.(socket.assigns.workbench)
|
|
||||||
else
|
|
||||||
{:error, reason} ->
|
|
||||||
socket
|
|
||||||
|> append_output.(translated("Tags"), inspect(reason), nil, "error")
|
|
||||||
|> reload.(socket.assigns.workbench)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
_other ->
|
|
||||||
reload.(socket, socket.assigns.workbench)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@spec delete_selected(term(), term(), term()) :: term()
|
|
||||||
def delete_selected(socket, reload, append_output) do
|
|
||||||
case Map.get(socket.assigns, :tags_editor_selected, []) do
|
|
||||||
[tag_name] ->
|
|
||||||
case Repo.get_by(Tag,
|
|
||||||
project_id: socket.assigns.projects.active_project_id,
|
|
||||||
name: tag_name
|
|
||||||
) do
|
|
||||||
nil ->
|
|
||||||
reload.(socket, socket.assigns.workbench)
|
|
||||||
|
|
||||||
%Tag{} = tag ->
|
%Tag{} = tag ->
|
||||||
case Tags.delete_tag(tag.id) do
|
case Tags.delete_tag(tag.id) do
|
||||||
{:ok, _deleted} ->
|
{:ok, _deleted} ->
|
||||||
|
notify_parent(:tags_changed)
|
||||||
|
|
||||||
socket
|
socket
|
||||||
|> assign(:tags_editor_selected, [])
|
|> put_in_tags_editor([:selected], [])
|
||||||
|> assign(:tags_editor_edit_draft, %{})
|
|> put_in_tags_editor([:edit_draft], %{})
|
||||||
|> reload.(socket.assigns.workbench)
|
|> load_data()
|
||||||
|
|> noreply()
|
||||||
|
|
||||||
{:error, reason} ->
|
{:error, reason} ->
|
||||||
socket
|
notify_output(translated("Tags"), inspect(reason), "error")
|
||||||
|> append_output.(translated("Tags"), inspect(reason), nil, "error")
|
{:noreply, socket}
|
||||||
|> reload.(socket.assigns.workbench)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
_other ->
|
_other ->
|
||||||
reload.(socket, socket.assigns.workbench)
|
{:noreply, socket}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec update_merge_target(term(), term(), term()) :: term()
|
def handle_event("change_merge_target", %{"target" => target}, socket) do
|
||||||
def update_merge_target(socket, target, reload) do
|
tags_editor =
|
||||||
socket
|
Map.put(socket.assigns.tags_editor, :merge_target, to_string(target || ""))
|
||||||
|> assign(:tags_editor_merge_target, to_string(target || ""))
|
|
||||||
|> reload.(socket.assigns.workbench)
|
{:noreply, assign(socket, :tags_editor, tags_editor)}
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec merge_selected(term(), term(), term()) :: term()
|
def handle_event("merge_tags_editor", _params, socket) do
|
||||||
def merge_selected(socket, reload, append_output) do
|
selected = socket.assigns.tags_editor.selected
|
||||||
selected = Map.get(socket.assigns, :tags_editor_selected, [])
|
target_name = socket.assigns.tags_editor.merge_target
|
||||||
target_name = Map.get(socket.assigns, :tags_editor_merge_target, "")
|
|
||||||
|
|
||||||
cond do
|
cond do
|
||||||
length(selected) < 2 or target_name == "" ->
|
length(selected) < 2 or target_name == "" ->
|
||||||
reload.(socket, socket.assigns.workbench)
|
{:noreply, socket}
|
||||||
|
|
||||||
true ->
|
true ->
|
||||||
project_id = socket.assigns.projects.active_project_id
|
project_id = socket.assigns.project_id
|
||||||
|
|
||||||
tags =
|
tags =
|
||||||
Repo.all(
|
Repo.all(
|
||||||
@@ -178,51 +171,90 @@ defmodule BDS.Desktop.ShellLive.TagsEditor do
|
|||||||
|
|
||||||
case target do
|
case target do
|
||||||
nil ->
|
nil ->
|
||||||
reload.(socket, socket.assigns.workbench)
|
{:noreply, socket}
|
||||||
|
|
||||||
_target ->
|
_target ->
|
||||||
case Tags.merge_tags(Enum.map(sources, & &1.id), target.id) do
|
case Tags.merge_tags(Enum.map(sources, & &1.id), target.id) do
|
||||||
{:ok, _merged} ->
|
{:ok, _merged} ->
|
||||||
|
notify_parent(:tags_changed)
|
||||||
|
|
||||||
socket
|
socket
|
||||||
|> assign(:tags_editor_selected, [target.name])
|
|> put_in_tags_editor([:selected], [target.name])
|
||||||
|> assign(:tags_editor_merge_target, target.name)
|
|> put_in_tags_editor([:merge_target], target.name)
|
||||||
|> maybe_seed_edit_draft([target.name])
|
|> maybe_seed_edit_draft(project_id, [target.name])
|
||||||
|> reload.(socket.assigns.workbench)
|
|> load_data()
|
||||||
|
|> noreply()
|
||||||
|
|
||||||
{:error, reason} ->
|
{:error, reason} ->
|
||||||
socket
|
notify_output(translated("Tags"), inspect(reason), "error")
|
||||||
|> append_output.(translated("Tags"), inspect(reason), nil, "error")
|
{:noreply, socket}
|
||||||
|> reload.(socket.assigns.workbench)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec sync(term(), term(), term()) :: term()
|
def handle_event("sync_tags_editor", _params, socket) do
|
||||||
def sync(socket, reload, append_output) do
|
case Tags.sync_tags_from_posts(socket.assigns.project_id) do
|
||||||
case Tags.sync_tags_from_posts(socket.assigns.projects.active_project_id) do
|
{:ok, _tags} ->
|
||||||
{:ok, _tags} -> reload.(socket, socket.assigns.workbench)
|
notify_parent(:tags_changed)
|
||||||
|
{:noreply, load_data(socket)}
|
||||||
|
|
||||||
{:error, reason} ->
|
{:error, reason} ->
|
||||||
socket
|
notify_output(translated("Tags"), inspect(reason), "error")
|
||||||
|> append_output.(translated("Tags"), inspect(reason), nil, "error")
|
{:noreply, socket}
|
||||||
|> reload.(socket.assigns.workbench)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec build(term()) :: term()
|
defp do_save(socket) do
|
||||||
def build(%{current_tab: %{type: :tags}} = assigns) do
|
selected = socket.assigns.tags_editor.selected
|
||||||
project_id = assigns.projects.active_project_id
|
draft = socket.assigns.tags_editor.edit_draft
|
||||||
|
project_id = socket.assigns.project_id
|
||||||
|
|
||||||
|
case selected do
|
||||||
|
[tag_name] ->
|
||||||
|
case Repo.get_by(Tag, project_id: project_id, name: tag_name) do
|
||||||
|
nil ->
|
||||||
|
socket
|
||||||
|
|
||||||
|
%Tag{} = tag ->
|
||||||
|
with {:ok, _updated_tag} <-
|
||||||
|
Tags.update_tag(tag.id, %{
|
||||||
|
color: blank_to_nil(Map.get(draft, "color")),
|
||||||
|
post_template_slug: blank_to_nil(Map.get(draft, "post_template_slug"))
|
||||||
|
}),
|
||||||
|
{:ok, renamed_tag} <- maybe_rename_tag(tag, Map.get(draft, "name", tag.name)) do
|
||||||
|
notify_parent(:tags_changed)
|
||||||
|
|
||||||
|
socket
|
||||||
|
|> put_in_tags_editor([:selected], [renamed_tag.name])
|
||||||
|
|> maybe_seed_edit_draft(project_id, [renamed_tag.name])
|
||||||
|
|> load_data()
|
||||||
|
else
|
||||||
|
{:error, reason} ->
|
||||||
|
notify_output(translated("Tags"), inspect(reason), "error")
|
||||||
|
socket
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
_other ->
|
||||||
|
socket
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp load_data(socket) do
|
||||||
|
project_id = socket.assigns.project_id
|
||||||
|
|
||||||
tags =
|
tags =
|
||||||
Repo.all(from tag in Tag, where: tag.project_id == ^project_id, order_by: [asc: tag.name])
|
Repo.all(from tag in Tag, where: tag.project_id == ^project_id, order_by: [asc: tag.name])
|
||||||
|
|
||||||
counts = tag_counts(project_id)
|
counts = tag_counts(project_id)
|
||||||
selected = Map.get(assigns, :tags_editor_selected, [])
|
selected = Map.get(socket.assigns, :tags_editor, %{}) |> Map.get(:selected, [])
|
||||||
|
|
||||||
edit_tag =
|
edit_tag =
|
||||||
if length(selected) == 1, do: Enum.find(tags, &(&1.name == hd(selected))), else: nil
|
if length(selected) == 1, do: Enum.find(tags, &(&1.name == hd(selected))), else: nil
|
||||||
|
|
||||||
edit_draft = Map.get(assigns, :tags_editor_edit_draft, edit_draft(edit_tag))
|
edit_draft =
|
||||||
|
Map.get(socket.assigns, :tags_editor, %{}) |> Map.get(:edit_draft, edit_draft(edit_tag))
|
||||||
|
|
||||||
templates =
|
templates =
|
||||||
Repo.all(
|
Repo.all(
|
||||||
@@ -232,27 +264,39 @@ defmodule BDS.Desktop.ShellLive.TagsEditor do
|
|||||||
select: %{slug: template.slug, title: template.title}
|
select: %{slug: template.slug, title: template.title}
|
||||||
)
|
)
|
||||||
|
|
||||||
selected_section = current_tags_section(assigns)
|
selected_section = current_tags_section(socket.assigns)
|
||||||
|
|
||||||
%{
|
data = %{
|
||||||
tags:
|
tags:
|
||||||
Enum.map(tags, fn tag ->
|
Enum.map(tags, fn tag ->
|
||||||
%{name: tag.name, color: tag.color, count: Map.get(counts, tag.name, 0)}
|
%{name: tag.name, color: tag.color, count: Map.get(counts, tag.name, 0)}
|
||||||
end),
|
end),
|
||||||
selected: selected,
|
selected: selected,
|
||||||
new_tag: Map.get(assigns, :tags_editor_new_tag, %{"name" => "", "color" => ""}),
|
new_tag:
|
||||||
|
Map.get(socket.assigns, :tags_editor, %{}) |> Map.get(:new_tag, %{"name" => "", "color" => ""}),
|
||||||
edit_draft: edit_draft,
|
edit_draft: edit_draft,
|
||||||
templates: templates,
|
templates: templates,
|
||||||
merge_target: Map.get(assigns, :tags_editor_merge_target, List.first(selected) || ""),
|
merge_target:
|
||||||
|
Map.get(socket.assigns, :tags_editor, %{}) |> Map.get(:merge_target, List.first(selected) || ""),
|
||||||
selected_section: selected_section
|
selected_section: selected_section
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assign(socket, :tags_editor, data)
|
||||||
end
|
end
|
||||||
|
|
||||||
def build(_assigns), do: nil
|
defp put_in_tags_editor(socket, [key], value) do
|
||||||
|
assign(socket, :tags_editor, Map.put(socket.assigns.tags_editor, key, value))
|
||||||
|
end
|
||||||
|
|
||||||
@spec translated(term(), term()) :: term()
|
defp noreply(socket), do: {:noreply, socket}
|
||||||
def translated(text, bindings \\ %{}),
|
|
||||||
do: ShellData.translate(text, bindings, BDS.Desktop.UILocale.current())
|
defp notify_parent(message) do
|
||||||
|
send(self(), message)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp notify_output(title, message, level) do
|
||||||
|
send(self(), {:tags_editor_output, title, message, level})
|
||||||
|
end
|
||||||
|
|
||||||
@spec tag_font_size(term(), term()) :: term()
|
@spec tag_font_size(term(), term()) :: term()
|
||||||
def tag_font_size(count, counts) do
|
def tag_font_size(count, counts) do
|
||||||
@@ -274,14 +318,18 @@ defmodule BDS.Desktop.ShellLive.TagsEditor do
|
|||||||
|> Enum.join("; ")
|
|> Enum.join("; ")
|
||||||
end
|
end
|
||||||
|
|
||||||
defp maybe_seed_edit_draft(socket, [tag_name]) do
|
defp maybe_seed_edit_draft(socket, project_id, [tag_name]) do
|
||||||
case Repo.get_by(Tag, project_id: socket.assigns.projects.active_project_id, name: tag_name) do
|
case Repo.get_by(Tag, project_id: project_id, name: tag_name) do
|
||||||
%Tag{} = tag -> assign(socket, :tags_editor_edit_draft, edit_draft(tag))
|
%Tag{} = tag ->
|
||||||
_other -> assign(socket, :tags_editor_edit_draft, %{})
|
put_in_tags_editor(socket, [:edit_draft], edit_draft(tag))
|
||||||
|
|
||||||
|
_other ->
|
||||||
|
put_in_tags_editor(socket, [:edit_draft], %{})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp maybe_seed_edit_draft(socket, _selected), do: assign(socket, :tags_editor_edit_draft, %{})
|
defp maybe_seed_edit_draft(socket, _project_id, _selected),
|
||||||
|
do: put_in_tags_editor(socket, [:edit_draft], %{})
|
||||||
|
|
||||||
defp edit_draft(nil), do: %{}
|
defp edit_draft(nil), do: %{}
|
||||||
|
|
||||||
@@ -314,13 +362,12 @@ defmodule BDS.Desktop.ShellLive.TagsEditor do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp current_tab_meta(assigns) do
|
defp current_tab_meta(%{current_tab: %{type: type, id: id}, tab_meta: tab_meta}) do
|
||||||
case Map.get(assigns, :current_tab) do
|
Map.get(tab_meta || %{}, {type, id}, %{})
|
||||||
%{type: type, id: id} -> Map.get(assigns[:tab_meta] || %{}, {type, id}, %{})
|
|
||||||
_other -> %{}
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp current_tab_meta(_assigns), do: %{}
|
||||||
|
|
||||||
defp tag_counts(project_id) do
|
defp tag_counts(project_id) do
|
||||||
Repo.all(from post in Post, where: post.project_id == ^project_id, select: post.tags)
|
Repo.all(from post in Post, where: post.project_id == ^project_id, select: post.tags)
|
||||||
|> List.flatten()
|
|> List.flatten()
|
||||||
@@ -336,4 +383,7 @@ defmodule BDS.Desktop.ShellLive.TagsEditor do
|
|||||||
trimmed -> trimmed
|
trimmed -> trimmed
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp translated(text, bindings \\ %{}),
|
||||||
|
do: ShellData.translate(text, bindings, UILocale.current())
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -18,12 +18,12 @@
|
|||||||
<%= if Enum.empty?(@tags_editor.tags) do %>
|
<%= if Enum.empty?(@tags_editor.tags) do %>
|
||||||
<div class="tags-empty-state">
|
<div class="tags-empty-state">
|
||||||
<p><%= translated("No tags found") %></p>
|
<p><%= translated("No tags found") %></p>
|
||||||
<button class="secondary" type="button" phx-click="sync_tags_editor"><%= translated("Discover") %></button>
|
<button class="secondary" type="button" phx-click="sync_tags_editor" phx-target={@myself}><%= translated("Discover") %></button>
|
||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
<div class="tag-cloud">
|
<div class="tag-cloud">
|
||||||
<%= for tag <- @tags_editor.tags do %>
|
<%= for tag <- @tags_editor.tags do %>
|
||||||
<button class={["tag-cloud-item", if(tag.name in @tags_editor.selected, do: "selected"), if(tag.color, do: "has-color")]} style={tag_style(tag, @tags_editor.tags)} type="button" phx-click="toggle_tag_selection" phx-value-name={tag.name}>
|
<button class={["tag-cloud-item", if(tag.name in @tags_editor.selected, do: "selected"), if(tag.color, do: "has-color")]} style={tag_style(tag, @tags_editor.tags)} type="button" phx-click="toggle_tag_selection" phx-value-name={tag.name} phx-target={@myself}>
|
||||||
<%= tag.name %><span class="tag-count"><%= tag.count %></span>
|
<%= tag.name %><span class="tag-count"><%= tag.count %></span>
|
||||||
</button>
|
</button>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -35,16 +35,16 @@
|
|||||||
<div class="tags-section" id="tags-section-manage">
|
<div class="tags-section" id="tags-section-manage">
|
||||||
<div class="tags-section-header"><h3><%= translated("Create / Edit") %></h3></div>
|
<div class="tags-section-header"><h3><%= translated("Create / Edit") %></h3></div>
|
||||||
<div class="tags-section-content">
|
<div class="tags-section-content">
|
||||||
<form class="tag-create-form" phx-change="change_new_tag_editor">
|
<form class="tag-create-form" phx-change="change_new_tag_editor" phx-target={@myself}>
|
||||||
<div class="tag-form-row">
|
<div class="tag-form-row">
|
||||||
<input type="text" name="new_tag[name]" value={@tags_editor.new_tag["name"]} placeholder={translated("Tag name")} />
|
<input type="text" name="new_tag[name]" value={@tags_editor.new_tag["name"]} placeholder={translated("Tag name")} />
|
||||||
<input type="color" name="new_tag[color]" value={if(@tags_editor.new_tag["color"] in [nil, ""], do: "#3b82f6", else: @tags_editor.new_tag["color"])} />
|
<input type="color" name="new_tag[color]" value={if(@tags_editor.new_tag["color"] in [nil, ""], do: "#3b82f6", else: @tags_editor.new_tag["color"])} />
|
||||||
<button class="primary" type="button" phx-click="create_tag_editor"><%= translated("Create") %></button>
|
<button class="primary" type="button" phx-click="create_tag_editor" phx-target={@myself}><%= translated("Create") %></button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<%= if @tags_editor.edit_draft != %{} do %>
|
<%= if @tags_editor.edit_draft != %{} do %>
|
||||||
<form class="tag-edit-form" phx-change="change_edit_tag_editor">
|
<form class="tag-edit-form" phx-change="change_edit_tag_editor" phx-target={@myself}>
|
||||||
<div class="tag-form-row">
|
<div class="tag-form-row">
|
||||||
<input type="text" name="edit_tag[name]" value={@tags_editor.edit_draft["name"]} />
|
<input type="text" name="edit_tag[name]" value={@tags_editor.edit_draft["name"]} />
|
||||||
<input type="color" name="edit_tag[color]" value={if(@tags_editor.edit_draft["color"] in [nil, ""], do: "#3b82f6", else: @tags_editor.edit_draft["color"])} />
|
<input type="color" name="edit_tag[color]" value={if(@tags_editor.edit_draft["color"] in [nil, ""], do: "#3b82f6", else: @tags_editor.edit_draft["color"])} />
|
||||||
@@ -54,8 +54,8 @@
|
|||||||
<option value={template.slug} selected={template.slug == @tags_editor.edit_draft["post_template_slug"]}><%= template.title %></option>
|
<option value={template.slug} selected={template.slug == @tags_editor.edit_draft["post_template_slug"]}><%= template.title %></option>
|
||||||
<% end %>
|
<% end %>
|
||||||
</select>
|
</select>
|
||||||
<button class="primary" type="button" phx-click="save_tag_editor"><%= translated("Save") %></button>
|
<button class="primary" type="button" phx-click="save_tag_editor" phx-target={@myself}><%= translated("Save") %></button>
|
||||||
<button class="danger" type="button" phx-click="delete_tag_editor"><%= translated("Delete") %></button>
|
<button class="danger" type="button" phx-click="delete_tag_editor" phx-target={@myself}><%= translated("Delete") %></button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -67,12 +67,12 @@
|
|||||||
<div class="tags-section-content">
|
<div class="tags-section-content">
|
||||||
<div class="merge-form">
|
<div class="merge-form">
|
||||||
<div class="tag-form-row">
|
<div class="tag-form-row">
|
||||||
<select phx-change="change_merge_target" name="target">
|
<select phx-change="change_merge_target" name="target" phx-target={@myself}>
|
||||||
<%= for tag_name <- @tags_editor.selected do %>
|
<%= for tag_name <- @tags_editor.selected do %>
|
||||||
<option value={tag_name} selected={tag_name == @tags_editor.merge_target}><%= tag_name %></option>
|
<option value={tag_name} selected={tag_name == @tags_editor.merge_target}><%= tag_name %></option>
|
||||||
<% end %>
|
<% end %>
|
||||||
</select>
|
</select>
|
||||||
<button class="primary" type="button" phx-click="merge_tags_editor" disabled={length(@tags_editor.selected) < 2}><%= translated("Merge") %></button>
|
<button class="primary" type="button" phx-click="merge_tags_editor" disabled={length(@tags_editor.selected) < 2} phx-target={@myself}><%= translated("Merge") %></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
<div class="tags-section" id="tags-section-sync">
|
<div class="tags-section" id="tags-section-sync">
|
||||||
<div class="tags-section-header"><h3><%= translated("Sync") %></h3></div>
|
<div class="tags-section-header"><h3><%= translated("Sync") %></h3></div>
|
||||||
<div class="tags-section-content">
|
<div class="tags-section-content">
|
||||||
<button class="secondary" type="button" phx-click="sync_tags_editor"><%= translated("Discover") %></button>
|
<button class="secondary" type="button" phx-click="sync_tags_editor" phx-target={@myself}><%= translated("Discover") %></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -368,17 +368,34 @@ defmodule BDS.Desktop.ShellLiveTest do
|
|||||||
|> element("[data-testid='sidebar-open-item'][data-item-id='tags-cloud']")
|
|> element("[data-testid='sidebar-open-item'][data-item-id='tags-cloud']")
|
||||||
|> render_click()
|
|> render_click()
|
||||||
|
|
||||||
html = render_click(view, "sync_tags_editor", %{})
|
html =
|
||||||
|
view
|
||||||
|
|> element("#tags-section-sync button[phx-click='sync_tags_editor']")
|
||||||
|
|> render_click()
|
||||||
|
|
||||||
assert Enum.map(Tags.list_tags(project.id), & &1.name) == ["Alpha", "Beta"]
|
assert Enum.map(Tags.list_tags(project.id), & &1.name) == ["Alpha", "Beta"]
|
||||||
assert html =~ "Alpha"
|
assert html =~ "Alpha"
|
||||||
assert html =~ "Beta"
|
assert html =~ "Beta"
|
||||||
|
|
||||||
_html = render_click(view, "toggle_tag_selection", %{"name" => "Alpha"})
|
_html =
|
||||||
_html = render_click(view, "toggle_tag_selection", %{"name" => "Beta"})
|
view
|
||||||
_html = render_change(view, "change_merge_target", %{"target" => "Alpha"})
|
|> element("#tags-editor-shell button[phx-click='toggle_tag_selection'][phx-value-name='Alpha']")
|
||||||
|
|> render_click()
|
||||||
|
|
||||||
html = render_click(view, "merge_tags_editor", %{})
|
_html =
|
||||||
|
view
|
||||||
|
|> element("#tags-editor-shell button[phx-click='toggle_tag_selection'][phx-value-name='Beta']")
|
||||||
|
|> render_click()
|
||||||
|
|
||||||
|
_html =
|
||||||
|
view
|
||||||
|
|> element("#tags-editor-shell select[phx-change='change_merge_target']")
|
||||||
|
|> render_change(%{"target" => "Alpha"})
|
||||||
|
|
||||||
|
html =
|
||||||
|
view
|
||||||
|
|> element("#tags-editor-shell button[phx-click='merge_tags_editor']")
|
||||||
|
|> render_click()
|
||||||
|
|
||||||
assert Enum.map(Tags.list_tags(project.id), & &1.name) == ["Alpha"]
|
assert Enum.map(Tags.list_tags(project.id), & &1.name) == ["Alpha"]
|
||||||
assert Repo.get!(Post, post.id).tags == ["Alpha"]
|
assert Repo.get!(Post, post.id).tags == ["Alpha"]
|
||||||
|
|||||||
Reference in New Issue
Block a user