Skip to content

Commit 2973909

Browse files
committed
backup
1 parent d170685 commit 2973909

File tree

5 files changed

+124
-54
lines changed

5 files changed

+124
-54
lines changed

lib/sanbase/queries/menu/menu.ex

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,32 @@ defmodule Sanbase.Queries.Menu do
2828
:parent_id,
2929
:root_parent_id
3030
])
31-
|> validate_required([:name])
3231
end
3332

3433
def create(attrs \\ %{}) do
3534
%Menu{}
3635
|> changeset(attrs)
36+
|> validate_required([:name])
37+
|> validate_length(:name, min: 1, max: 256)
3738
end
3839

3940
def update(menu, attrs) do
4041
menu
4142
|> changeset(attrs)
42-
|> Repo.update()
4343
end
4444

45-
def delete(menu) do
46-
Repo.delete(menu)
45+
def get(id) do
46+
base_query()
47+
|> where([m], m.id == ^id)
48+
end
49+
50+
def get_root_parent_id(id) do
51+
base_query()
52+
|> where([m], m.id == ^id)
53+
|> select([m], m.root_parent_id)
4754
end
4855

49-
def get(id) do
50-
from(m in Menu, where: m.id == ^id)
56+
defp base_query() do
57+
__MODULE__
5158
end
5259
end

lib/sanbase/queries/menu/menu_item.ex

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ defmodule Sanbase.Queries.Menu.MenuItem do
99
alias Sanbase.Queries.Dashboard
1010

1111
schema "menu_items" do
12-
belongs_to(:menu, Menu, foreign_key: :menu_id)
13-
belongs_to(:root_menu, Menu, foreign_key: :root_menu_id)
12+
belongs_to(:parent, Menu, foreign_key: :parent_id)
1413

1514
belongs_to(:query, Query, foreign_key: :query_id)
1615
belongs_to(:dashboard, Dashboard, foreign_key: :dashboard_id)
16+
belongs_to(:menu, Menu, foreign_key: :menu_id)
1717

1818
field(:position, :integer)
1919

@@ -30,27 +30,39 @@ defmodule Sanbase.Queries.Menu.MenuItem do
3030
])
3131
end
3232

33+
@doc ~s"""
34+
Get the next position for a menu item inside a specific menu
35+
(it can be either sub-menu or a root menu)
36+
"""
37+
def get_next_position(menu_id) do
38+
base_query()
39+
|> where([m], m.menu_id == ^menu_id)
40+
|> select([m], coalesce(max(m.position), 0) + 1)
41+
end
42+
43+
@doc ~s"""
44+
Get the next position for a menu item inside a specific menu
45+
(it can be either sub-menu or a root menu)
46+
"""
47+
def inc_all_positions_after(menu_id, position) do
48+
base_query()
49+
|> where([m], m.menu_id == ^menu_id and m.position >= ^position)
50+
|> update([m], inc: [position: +1])
51+
end
52+
3353
def create(attrs \\ %{}) do
3454
%__MODULE__{}
3555
|> changeset(attrs)
36-
|> Repo.insert()
3756
end
3857

3958
def update(menu, attrs) do
4059
menu
4160
|> changeset(attrs)
42-
|> Repo.update()
43-
end
44-
45-
def delete(menu) do
46-
Repo.delete(menu)
4761
end
4862

49-
def get(id) do
50-
Repo.get(Menu, id)
51-
end
63+
# Private functions
5264

53-
def list do
54-
Repo.all(Menu)
65+
defp base_query() do
66+
from(m in __MODULE__)
5567
end
5668
end

lib/sanbase/queries/menus.ex

Lines changed: 77 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,89 @@ defmodule Sanbase.Menus do
22
alias Sanbase.Queries.Menu
33
alias Sanbase.Queries.Menu.MenuItem
44

5-
def create_menu(args) do
6-
Menu.create(args)
7-
|> Sanbase.Repo.insert()
5+
import Sanbase.Utils.ErrorHandling, only: [changeset_errors_string: 1]
6+
7+
@doc ~s"""
8+
TODO
9+
"""
10+
def create_menu(params) do
11+
Ecto.Multi.new()
12+
|> Ecto.Multi.run(:get_root_parent_id, fn _repo, _changes ->
13+
case Map.get(params, :parent_id) do
14+
# If there is no parent_id then there is no root_parent_id as well
15+
nil ->
16+
{:ok, nil}
17+
18+
# The root_parent_id of the sub-menu is the same as the root_parent_id
19+
# of the parent menu. Root menus don't have a root_parent_id pointing to themselves
20+
# so in such case we put the parent_id as a root_parent_id (i.e. this new menu
21+
# is a first-level child)
22+
parent_id when is_integer(parent_id) ->
23+
{:ok, root_parent_id} = get_root_parent_id(parent_id)
24+
25+
{:ok, root_parent_id || parent_id}
26+
end
27+
end)
28+
|> Ecto.Multi.run(:create_menu, fn _repo, %{get_root_parent_id: root_parent_id} ->
29+
params = Map.merge(params, %{root_parent_id: root_parent_id})
30+
query = Menu.create(params)
31+
Sanbase.Repo.insert(query)
32+
end)
33+
|> Sanbase.Repo.transaction()
34+
|> process_transaction_result(:create_menu)
835
end
936

37+
@doc ~s"""
38+
TODO
39+
"""
1040
def add_menu_item(menu_id, item_args) do
11-
with {:ok, root_parent_id} <- get_root_parent_id(menu_id),
12-
{:ok, position} <- MenuItem.get_next_position(root_parent_id) do
13-
MenuItem.create(%{menu_id: menu_id, root_menu_id: root_parent_id} ++ item_args)
14-
|> Sanbase.Repo.insert()
15-
end
41+
Ecto.Multi.new()
42+
|> Ecto.Multi.run(:get_root_parent_id, fn _repo, _changes ->
43+
get_root_parent_id(menu_id)
44+
end)
45+
|> Ecto.Multi.run(:get_and_adjust_position, fn _repo, %{get_root_parent_id: root_parent_id} ->
46+
case Map.get(item_args, :position) do
47+
nil ->
48+
# If `position` is not specified, add it at the end by getting the last position + 1
49+
{:ok, get_next_position(menu_id)}
1650

17-
MenuItem.create(%{menu_id: menu_id} ++ item_args)
51+
position when is_integer(position) ->
52+
# If `position` is specified, bump all the positions bigger than it by 1
53+
{:ok, {nil, _}} = inc_all_positions_after(menu_id, position)
54+
{:ok, position}
55+
end
56+
end)
57+
|> Ecto.Multi.run(
58+
:create_menu_item,
59+
fn _repo, %{get_root_parent_id: _, get_and_adjust_position: _} = map ->
60+
params = Map.merge(item_args, map)
61+
query = MenuItem.create(params)
62+
Sanbase.Repo.insert(query)
63+
end
64+
)
1865
end
1966

20-
defp get_root_parent_id(menu_id) do
21-
query = Menu.get(menu_id) |> select(:root_parent_id)
67+
defp get_next_position(menu_id) do
68+
query = MenuItem.get_next_position(menu_id)
69+
{:ok, Sanbase.Repo.one(query)}
70+
end
2271

23-
{:ok, root_parent_id} = Sanbase.Repo.one(query)
72+
defp inc_all_positions_after(menu_id, position) do
73+
query = MenuItem.inc_all_positions_after(menu_id, position)
74+
{:ok, Sanbase.Repo.update_all(query)}
2475
end
76+
77+
defp get_root_parent_id(menu_id) when is_integer(menu_id) do
78+
query = Menu.get_root_parent_id(menu_id)
79+
{:ok, Sanbase.Repo.one(query)}
80+
end
81+
82+
defp process_transaction_result({:ok, map}, ok_field),
83+
do: {:ok, map[ok_field]}
84+
85+
defp process_transaction_result({:error, _, %Ecto.Changeset{} = changeset, _}, _ok_field),
86+
do: {:error, changeset_errors_string(changeset)}
87+
88+
defp process_transaction_result({:error, _, error, _}, _ok_field),
89+
do: {:error, error}
2590
end

priv/repo/migrations/20231110093800_create_menus_table.exs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ defmodule Sanbase.Repo.Migrations.CreatesMenusTable do
99
add(:parent_id, references(:menus, on_delete: :delete_all))
1010
add(:root_parent_id, references(:menus, on_delete: :delete_all))
1111

12-
add(:position, :integer)
13-
1412
add(:user_id, references(:users, on_delete: :delete_all))
1513

1614
add(:is_admin_controlled, :boolean, default: false)
@@ -25,22 +23,18 @@ defmodule Sanbase.Repo.Migrations.CreatesMenusTable do
2523
create(index(:menus, [:user_id]))
2624

2725
create table(:menu_items) do
28-
add(:menu_id, references(:menus, on_delete: :delete_all))
29-
add(:root_menu_id, references(:menus, on_delete: :delete_all))
26+
add(:parent_id, references(:menus, on_delete: :delete_all))
27+
# add(:root_parent_id, references(:menus, on_delete: :delete_all))
3028

3129
add(:query_id, references(:queries, on_delete: :delete_all))
3230
add(:dashboard_id, references(:dashboards, on_delete: :delete_all))
31+
add(:menu_id, references(:menus, on_delete: :delete_all))
3332

3433
add(:position, :integer)
3534

3635
timestamps()
3736
end
3837

39-
# When searching for all menu items of a menu, the `where` clause will
40-
# find these items by the root_menu_id, hence the index. The
41-
# menu_id is used only to build the hierarchy after that.
42-
create(index(:menu_items, [:root_menu_id]))
43-
4438
fk_check = """
4539
(CASE WHEN query_id IS NULL THEN 0 ELSE 1 END) +
4640
(CASE WHEN dashboard_id IS NULL THEN 0 ELSE 1 END) = 1

priv/repo/structure.sql

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2011,10 +2011,10 @@ ALTER SEQUENCE public.market_segments_id_seq OWNED BY public.market_segments.id;
20112011

20122012
CREATE TABLE public.menu_items (
20132013
id bigint NOT NULL,
2014-
menu_id bigint,
2015-
root_menu_id bigint,
2014+
parent_id bigint,
20162015
query_id bigint,
20172016
dashboard_id bigint,
2017+
menu_id bigint,
20182018
"position" integer,
20192019
inserted_at timestamp without time zone NOT NULL,
20202020
updated_at timestamp without time zone NOT NULL,
@@ -2059,7 +2059,6 @@ CREATE TABLE public.menus (
20592059
description character varying(255),
20602060
parent_id bigint,
20612061
root_parent_id bigint,
2062-
"position" integer,
20632062
user_id bigint,
20642063
is_admin_controlled boolean DEFAULT false,
20652064
inserted_at timestamp without time zone NOT NULL,
@@ -6732,13 +6731,6 @@ CREATE UNIQUE INDEX list_items_user_list_id_project_id_index ON public.list_item
67326731
CREATE UNIQUE INDEX market_segments_name_index ON public.market_segments USING btree (name);
67336732

67346733

6735-
--
6736-
-- Name: menu_items_root_menu_id_index; Type: INDEX; Schema: public; Owner: -
6737-
--
6738-
6739-
CREATE INDEX menu_items_root_menu_id_index ON public.menu_items USING btree (root_menu_id);
6740-
6741-
67426734
--
67436735
-- Name: menus_root_parent_id_index; Type: INDEX; Schema: public; Owner: -
67446736
--
@@ -7906,19 +7898,19 @@ ALTER TABLE ONLY public.menu_items
79067898

79077899

79087900
--
7909-
-- Name: menu_items menu_items_query_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
7901+
-- Name: menu_items menu_items_parent_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
79107902
--
79117903

79127904
ALTER TABLE ONLY public.menu_items
7913-
ADD CONSTRAINT menu_items_query_id_fkey FOREIGN KEY (query_id) REFERENCES public.queries(id) ON DELETE CASCADE;
7905+
ADD CONSTRAINT menu_items_parent_id_fkey FOREIGN KEY (parent_id) REFERENCES public.menus(id) ON DELETE CASCADE;
79147906

79157907

79167908
--
7917-
-- Name: menu_items menu_items_root_menu_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
7909+
-- Name: menu_items menu_items_query_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
79187910
--
79197911

79207912
ALTER TABLE ONLY public.menu_items
7921-
ADD CONSTRAINT menu_items_root_menu_id_fkey FOREIGN KEY (root_menu_id) REFERENCES public.menus(id) ON DELETE CASCADE;
7913+
ADD CONSTRAINT menu_items_query_id_fkey FOREIGN KEY (query_id) REFERENCES public.queries(id) ON DELETE CASCADE;
79227914

79237915

79247916
--

0 commit comments

Comments
 (0)