102 lines
2.9 KiB
Elixir
102 lines
2.9 KiB
Elixir
defmodule BDS.Desktop.ShellLive.MenuEditor.State do
|
|
@moduledoc false
|
|
|
|
use Phoenix.Component
|
|
|
|
alias BDS.Menu
|
|
alias BDS.Desktop.ShellLive.MenuEditor.{PageCategory, TreeOps, TreePredicates}
|
|
use Gettext, backend: BDS.Gettext
|
|
|
|
@spec ensure_state(term()) :: term()
|
|
def ensure_state(assigns) do
|
|
project_id = assigns.projects.active_project_id
|
|
|
|
case assigns[:menu_editor_state] do
|
|
%{project_id: ^project_id} = state -> state
|
|
_other -> load_state(project_id)
|
|
end
|
|
end
|
|
|
|
@spec update_state(term(), term()) :: term()
|
|
def update_state(socket, updater) do
|
|
state = ensure_state(socket.assigns)
|
|
assign(socket, :menu_editor_state, updater.(state))
|
|
end
|
|
|
|
@spec build(term(), term()) :: term()
|
|
def build(_assigns, state) do
|
|
categories = PageCategory.category_options(state.project_id)
|
|
draft = state.draft
|
|
draft_query = Map.get(draft || %{}, :query, "")
|
|
|
|
%{
|
|
title: dgettext("ui", "Blog Menu Editor"),
|
|
description:
|
|
dgettext(
|
|
"ui",
|
|
"Manage the central blog navigation outline and save it to meta/menu.opml."
|
|
),
|
|
items: state.items,
|
|
selected_id: state.selected_id,
|
|
draft: draft,
|
|
draft_query: draft_query,
|
|
filtered_pages:
|
|
if(match?(%{type: :page}, draft),
|
|
do:
|
|
PageCategory.filter_page_posts(PageCategory.page_posts(state.project_id), draft_query),
|
|
else: []
|
|
),
|
|
filtered_categories:
|
|
if(match?(%{type: :category}, draft),
|
|
do: PageCategory.filter_categories(categories, draft_query),
|
|
else: []
|
|
),
|
|
category_titles: Map.new(categories, &{&1.name, &1.title}),
|
|
can_move_up?: TreePredicates.can_move_up?(state.items, state.selected_id),
|
|
can_move_down?: TreePredicates.can_move_down?(state.items, state.selected_id),
|
|
can_indent?: TreePredicates.can_indent?(state.items, state.selected_id),
|
|
can_unindent?: TreePredicates.can_unindent?(state.items, state.selected_id),
|
|
can_delete?: TreePredicates.can_delete?(state.selected_id),
|
|
has_items?: state.items != []
|
|
}
|
|
end
|
|
|
|
@spec save(term(), term(), term()) :: term()
|
|
def save(socket, reload, append_output) do
|
|
state = socket.assigns.menu_editor_state
|
|
|
|
{:ok, _menu} =
|
|
Menu.update_menu(state.project_id, Enum.map(state.items, &TreeOps.persisted_item/1))
|
|
|
|
socket
|
|
|> append_output.(
|
|
dgettext("ui", "Blog Menu"),
|
|
dgettext("ui", "Blog menu saved"),
|
|
nil,
|
|
"info"
|
|
)
|
|
|> reload.(socket.assigns.workbench)
|
|
end
|
|
|
|
defp load_state(nil) do
|
|
%{
|
|
project_id: nil,
|
|
items: [TreeOps.home_item()],
|
|
selected_id: TreeOps.home_item_id(),
|
|
draft: nil
|
|
}
|
|
end
|
|
|
|
defp load_state(project_id) do
|
|
{:ok, %{items: items}} = Menu.get_menu(project_id)
|
|
items = Enum.map(items, &TreeOps.ui_item/1)
|
|
|
|
%{
|
|
project_id: project_id,
|
|
items: items,
|
|
selected_id: TreeOps.first_item_id(items),
|
|
draft: nil
|
|
}
|
|
end
|
|
end
|