Рефакторинг админских обработчиков - пагинация, сортировка, фильтрация. Финал

This commit is contained in:
2026-05-26 21:50:12 +03:00
parent ed5b275efb
commit 19b3d0dba0
21 changed files with 1833 additions and 421 deletions
@@ -1,6 +1,6 @@
%%%-------------------------------------------------------------------
%%% @doc Административный обработчик бан-слов.
%%% GET – список всех слов с пагинацией.
%%% GET – список всех слов с пагинацией, фильтрацией и сортировкой.
%%% POST – добавить новое слово.
%%% PUT – редактировать существующее слово.
%%% DELETE – удалить слово по :word.
@@ -37,6 +37,9 @@ trails() ->
description => <<"List all banned words (admin)">>,
tags => [<<"Banned Words">>],
parameters => [
#{name => <<"q">>, in => <<"query">>, schema => #{type => string}, description => <<"Search by word">>},
#{name => <<"sort">>, in => <<"query">>, schema => #{type => string, enum => [<<"word">>, <<"added_at">>]}, description => <<"Sort field">>},
#{name => <<"order">>, in => <<"query">>, schema => #{type => string, enum => [<<"asc">>, <<"desc">>]}, description => <<"Sort direction">>},
#{name => <<"limit">>, in => <<"query">>, schema => #{type => integer}, description => <<"Page size">>},
#{name => <<"offset">>, in => <<"query">>, schema => #{type => integer}, description => <<"Offset">>}
],
@@ -141,11 +144,27 @@ banned_word_schema() ->
list_words(Req) ->
case handler_utils:auth_admin(Req) of
{ok, _AdminId, Req1} ->
Qs = cowboy_req:parse_qs(Req1),
Q = proplists:get_value(<<"q">>, Qs),
SortBy = proplists:get_value(<<"sort">>, Qs, <<"word">>),
SortOrder = proplists:get_value(<<"order">>, Qs, <<"asc">>),
Pagination = handler_utils:parse_pagination_params(Req1),
AllWords = core_banned_words:list_banned_words(),
BannedWords = lists:sort(AllWords),
Total = length(BannedWords),
Page = lists:sublist(BannedWords, maps:get(offset, Pagination) + 1, maps:get(limit, Pagination)),
% Фильтрация
Filtered = case Q of
undefined -> AllWords;
_ -> [W || W <- AllWords, string:str(string:lowercase(binary_to_list(W#banned_word.word)), string:lowercase(binary_to_list(Q))) > 0]
end,
% Сортировка
Sorted = case {SortBy, SortOrder} of
{<<"word">>, <<"asc">>} -> lists:keysort(#banned_word.word, Filtered);
{<<"word">>, <<"desc">>} -> lists:reverse(lists:keysort(#banned_word.word, Filtered));
{<<"added_at">>, <<"asc">>} -> lists:keysort(#banned_word.added_at, Filtered);
{<<"added_at">>, <<"desc">>} -> lists:reverse(lists:keysort(#banned_word.added_at, Filtered));
_ -> Filtered
end,
Total = length(Sorted),
Page = lists:sublist(Sorted, maps:get(offset, Pagination) + 1, maps:get(limit, Pagination)),
Json = [word_to_map(W) || W <- Page],
ExtraHeaders = handler_utils:pagination_headers(Pagination, Total),
handler_utils:send_json(Req1, 200, Json, ExtraHeaders);