@@ -46,10 +46,7 @@ defmodule Sanbase.Menus do
46
46
47
47
@ type update_menu_item_params :: % {
48
48
optional ( :parent_id ) => menu_id ,
49
- optional ( :position ) => integer ( ) | nil ,
50
- optional ( :query_id ) => Sanbase.Queries.Query . query_id ( ) ,
51
- optional ( :dashboard_id ) => Sanbase.Queries.Dashboard . dashboard_id ( ) ,
52
- optional ( :menu_id ) => menu_id
49
+ optional ( :position ) => integer ( ) | nil
53
50
}
54
51
55
52
@ doc ~s"""
@@ -77,6 +74,10 @@ defmodule Sanbase.Menus do
77
74
"""
78
75
def menu_to_simple_map ( % Menu { } = menu ) do
79
76
% {
77
+ # If this menu is a sub-menu, then the caller from get_menu_items/1 will
78
+ # additionally set the menu_item_id. If this is the top-level menu, then
79
+ # this is not a sub-menu and it does not have a menu_item_id
80
+ menu_item_id: nil ,
80
81
type: :menu ,
81
82
id: menu . id ,
82
83
name: menu . name ,
@@ -95,7 +96,10 @@ defmodule Sanbase.Menus do
95
96
"""
96
97
@ spec create_menu ( create_menu_params , user_id ) :: { :ok , Menu . t ( ) } | { :error , String . t ( ) }
97
98
def create_menu ( params , user_id ) do
98
- params = params |> Map . merge ( % { user_id: user_id } )
99
+ params =
100
+ params
101
+ |> Map . merge ( % { user_id: user_id } )
102
+ |> IO . inspect ( label: "100" , limit: :infinity )
99
103
100
104
Ecto.Multi . new ( )
101
105
|> Ecto.Multi . run ( :create_menu , fn _repo , _changes ->
@@ -121,19 +125,13 @@ defmodule Sanbase.Menus do
121
125
)
122
126
end
123
127
end )
124
- # |> Ecto.Multi.run(
125
- # :get_menu_with_preloads,
126
- # fn _repo, %{create_menu: menu, maybe_create_menu_item: menu_or_nil} ->
127
- # # If the menu was created as a sub-menu, then the `maybe_create_menu_item` step
128
- # # has already returned the menu with preloads. Otherwise, we need to preload it here.
129
- # case menu_or_nil do
130
- # %Menu{} = m -> {:ok, m}
131
- # nil -> get_menu(menu.id, user_id)
132
- # end
133
- # end
134
- # )
128
+ |> Ecto.Multi . run ( :get_menu_with_preloads , fn _repo , % { create_menu: menu } ->
129
+ # There would be no menu items, but this will help to set the menu items to []
130
+ # instead of getting an error when trying to iterate them because they're set to <not preloaded>
131
+ get_menu ( menu . id , user_id )
132
+ end )
135
133
|> Repo . transaction ( )
136
- |> process_transaction_result ( :create_menu )
134
+ |> process_transaction_result ( :get_menu_with_preloads )
137
135
end
138
136
139
137
@ doc ~s"""
@@ -152,7 +150,7 @@ defmodule Sanbase.Menus do
152
150
query = Menu . update ( menu , params )
153
151
Repo . update ( query )
154
152
end )
155
- |> Ecto.Multi . run ( :get_menu_with_preloads , fn _repo , % { create_menu : menu } ->
153
+ |> Ecto.Multi . run ( :get_menu_with_preloads , fn _repo , % { update_menu : menu } ->
156
154
get_menu ( menu . id , user_id )
157
155
end )
158
156
|> Repo . transaction ( )
@@ -235,44 +233,49 @@ defmodule Sanbase.Menus do
235
233
@ doc ~s"""
236
234
Update an existing menu item.
237
235
"""
238
- @ spec update_menu_item ( menu_id , menu_item_id , update_menu_item_params , user_id ) ::
236
+ @ spec update_menu_item ( menu_item_id , update_menu_item_params , user_id ) ::
239
237
{ :ok , Menu . t ( ) } | { :error , String . t ( ) }
240
- def update_menu_item ( menu_id , menu_item_id , params , user_id ) do
238
+ def update_menu_item ( menu_item_id , params , user_id ) do
241
239
Ecto.Multi . new ( )
242
- |> Ecto.Multi . run ( :get_menu_for_update , fn _repo , _changes ->
243
- # Just check that the current user can update the parent menu
244
- get_menu_for_update ( menu_id , user_id )
245
- end )
246
240
|> Ecto.Multi . run ( :get_menu_item_for_update , fn _repo , _changes ->
247
- get_menu_item_for_update ( menu_item_id )
241
+ get_menu_item_for_update ( menu_item_id , user_id )
248
242
end )
243
+ |> Ecto.Multi . run (
244
+ :maybe_update_items_positions ,
245
+ fn _repo , % { get_menu_item_for_update: menu_item } ->
246
+ case Map . get ( params , :position ) do
247
+ nil ->
248
+ { :ok , nil }
249
+
250
+ position when is_integer ( position ) ->
251
+ # If `position` is specified, bump all the positions bigger than it by 1 in
252
+ # order to avoid having multiple items with the same position.
253
+ { :ok , { _ , nil } } = inc_all_positions_after ( menu_item . parent_id , position )
254
+ { :ok , position }
255
+ end
256
+ end
257
+ )
249
258
|> Ecto.Multi . run ( :update_menu_item , fn _repo , % { get_menu_item_for_update: menu_item } ->
250
- # Handle change of entity
251
- params = MenuItem . process_update_params ( params )
252
259
query = MenuItem . update ( menu_item , params )
253
260
Repo . update ( query )
254
261
end )
255
- |> Ecto.Multi . run ( :get_menu_with_preloads , fn _repo , % { get_menu_for_update: menu } ->
256
- get_menu ( menu . id , user_id )
262
+ |> Ecto.Multi . run ( :get_menu_with_preloads , fn _repo , % { update_menu_item: menu_item } ->
263
+ get_menu ( menu_item . parent_id , user_id )
257
264
end )
258
265
|> Repo . transaction ( )
259
266
|> process_transaction_result ( :get_menu_with_preloads )
260
267
end
261
268
262
- def delete_menu_item ( menu_id , menu_item_id , user_id ) do
269
+ def delete_menu_item ( menu_item_id , user_id ) do
263
270
Ecto.Multi . new ( )
264
- |> Ecto.Multi . run ( :check_user_has_write_access , fn _repo , _changes ->
265
- # Just check that the current user can update the parent menu
266
- get_menu_for_update ( menu_id , user_id )
267
- end )
268
271
|> Ecto.Multi . run ( :get_menu_item , fn _repo , _changes ->
269
- get_menu_item_for_update ( menu_item_id )
272
+ get_menu_item_for_update ( menu_item_id , user_id )
270
273
end )
271
274
|> Ecto.Multi . run ( :delete_menu_item , fn _repo , % { get_menu_item: menu_item } ->
272
275
Repo . delete ( menu_item )
273
276
end )
274
- |> Ecto.Multi . run ( :get_menu_with_preloads , fn _repo , % { create_menu: menu } ->
275
- get_menu ( menu . id , user_id )
277
+ |> Ecto.Multi . run ( :get_menu_with_preloads , fn _repo , % { delete_menu_item: menu_item } ->
278
+ get_menu ( menu_item . parent_id , user_id )
276
279
end )
277
280
|> Repo . transaction ( )
278
281
|> process_transaction_result ( :get_menu_with_preloads )
@@ -289,11 +292,8 @@ defmodule Sanbase.Menus do
289
292
end
290
293
end
291
294
292
- defp get_menu_item_for_update ( menu_item_id ) do
293
- # This should be called only after checking that the user
294
- # has write access to the menu. This is done by calling
295
- # get_menu_for_update/2 first.
296
- query = MenuItem . get_for_update ( menu_item_id )
295
+ defp get_menu_item_for_update ( menu_item_id , user_id ) do
296
+ query = MenuItem . get_for_update ( menu_item_id , user_id )
297
297
298
298
case Repo . one ( query ) do
299
299
nil -> { :error , "Menu item does not exist" }
@@ -339,14 +339,17 @@ defmodule Sanbase.Menus do
339
339
defp get_menu_items ( % Menu { menu_items: list } ) when is_list ( list ) do
340
340
list
341
341
|> Enum . map ( fn
342
- % { query: % { id: _ } = map , position: p } ->
343
- Map . take ( map , [ :id , :name , :description ] ) |> Map . merge ( % { type: :query , position: p } )
342
+ % { id: menu_item_id , query: % { id: _ } = map , position: position } ->
343
+ Map . take ( map , [ :id , :name , :description ] )
344
+ |> Map . merge ( % { type: :query , position: position , menu_item_id: menu_item_id } )
344
345
345
- % { dashboard: % { id: _ } = map , position: p } ->
346
- Map . take ( map , [ :id , :name , :description ] ) |> Map . merge ( % { type: :dashboard , position: p } )
346
+ % { id: menu_item_id , dashboard: % { id: _ } = map , position: position } ->
347
+ Map . take ( map , [ :id , :name , :description ] )
348
+ |> Map . merge ( % { type: :dashboard , position: position , menu_item_id: menu_item_id } )
347
349
348
- % { menu: % { id: _ } = map , position: p } ->
349
- menu_to_simple_map ( map ) |> Map . put ( :position , p )
350
+ % { id: menu_item_id , menu: % { id: _ } = map , position: position } ->
351
+ menu_to_simple_map ( map )
352
+ |> Map . merge ( % { type: :menu , position: position , menu_item_id: menu_item_id } )
350
353
end )
351
354
end
352
355
end
0 commit comments