mirror of
https://github.com/processone/ejabberd.git
synced 2024-12-20 17:27:00 +01:00
WebAdmin: Add make_command functions to produce HTML command element
Support to sort tables using Sortable library from: https://github.com/tofsjonas/sortable
This commit is contained in:
parent
74d6f0a68d
commit
30bd8f1570
@ -26,6 +26,18 @@
|
||||
{tuple, [rterm()]} | {list, rterm()} |
|
||||
rescode | restuple.
|
||||
|
||||
%% The purpose of a command can either be:
|
||||
%% - informative: its purpose is to obtain information
|
||||
%% - modifier: its purpose is to produce some change in the server
|
||||
%%
|
||||
%% A modifier command should be designed just to produce its desired side-effect,
|
||||
%% and its result term should just be success or failure: rescode or restuple.
|
||||
%%
|
||||
%% ejabberd_web_admin:make_command/2 considers that commands
|
||||
%% with result type different than rescode or restuple
|
||||
%% are commands that can be safely executed automatically
|
||||
%% to get information and build the web page.
|
||||
|
||||
-type oauth_scope() :: atom().
|
||||
|
||||
%% ejabberd_commands OAuth ReST ACL definition:
|
||||
|
@ -62,6 +62,11 @@
|
||||
[{<<"type">>, Type}, {<<"name">>, Name},
|
||||
{<<"value">>, Value}])).
|
||||
|
||||
-define(INPUTPH(Type, Name, Value, PlaceHolder),
|
||||
?XA(<<"input">>,
|
||||
[{<<"type">>, Type}, {<<"name">>, Name},
|
||||
{<<"value">>, Value}, {<<"placeholder">>, PlaceHolder}])).
|
||||
|
||||
-define(INPUTT(Type, Name, Value),
|
||||
?INPUT(Type, Name, (translate:translate(Lang, Value)))).
|
||||
|
||||
@ -95,16 +100,27 @@
|
||||
-define(XRES(Text),
|
||||
?XAC(<<"p">>, [{<<"class">>, <<"result">>}], Text)).
|
||||
|
||||
-define(DIVRES(Elements),
|
||||
?XAE(<<"div">>, [{<<"class">>, <<"result">>}], Elements)).
|
||||
|
||||
%% Guide Link
|
||||
-define(XREST(Text), ?XRES((translate:translate(Lang, Text)))).
|
||||
|
||||
-define(GL(Ref, Title),
|
||||
?XAE(<<"div">>, [{<<"class">>, <<"guidelink">>}],
|
||||
[?XAE(<<"a">>,
|
||||
[{<<"href">>, <<"https://docs.ejabberd.im/admin/configuration/", Ref/binary>>},
|
||||
[{<<"href">>, <<"https://docs.ejabberd.im/", Ref/binary>>},
|
||||
{<<"target">>, <<"_blank">>}],
|
||||
[?C(<<"docs: ", Title/binary>>)])])).
|
||||
|
||||
%% h1 with a Guide Link
|
||||
-define(H1GL(Name, Ref, Title),
|
||||
[?XC(<<"h1">>, Name), ?GL(Ref, Title)]).
|
||||
-define(H1GLraw(Name, Ref, Title),
|
||||
[?XC(<<"h1">>, Name), ?GL(Ref, Title), ?BR]).
|
||||
-define(H1GL(Name, RefConf, Title),
|
||||
?H1GLraw(Name, <<"admin/configuration/", RefConf/binary>>, Title)).
|
||||
|
||||
-define(ANCHORL(Ref),
|
||||
?XAE(<<"div">>, [{<<"class">>, <<"anchorlink">>}],
|
||||
[?XAE(<<"a">>,
|
||||
[{<<"href">>, <<"#", Ref/binary>>}],
|
||||
[?C(<<"<=">>)])])).
|
||||
|
1
mix.exs
1
mix.exs
@ -112,6 +112,7 @@ defmodule Ejabberd.MixProject do
|
||||
if_version_below(~c"24", [{:d, :SYSTOOLS_APP_DEF_WITHOUT_OPTIONAL}]) ++
|
||||
if_version_below(~c"24", [{:d, :OTP_BELOW_24}]) ++
|
||||
if_version_below(~c"25", [{:d, :OTP_BELOW_25}]) ++
|
||||
if_version_below(~c"26", [{:d, :OTP_BELOW_26}]) ++
|
||||
if_version_below(~c"27", [{:d, :OTP_BELOW_27}]) ++
|
||||
if_type_exported(:odbc, {:opaque, :connection_reference, 0}, [{:d, :ODBC_HAS_TYPES}])
|
||||
defines = for {:d, value} <- result, do: {:d, value}
|
||||
|
@ -136,11 +136,7 @@ ul li #navhead a, ul li #navheadsub a, ul li #navheadsubsub a {
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
thead tr td {
|
||||
background: #3eaffa;
|
||||
color: #fff;
|
||||
}
|
||||
thead tr td a {
|
||||
color: #fff;
|
||||
background: #cae7e4;
|
||||
}
|
||||
td.copy {
|
||||
text-align: center;
|
||||
@ -227,22 +223,29 @@ h3 {
|
||||
padding-top: 25px;
|
||||
width: 70%;
|
||||
}
|
||||
div.anchorlink {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
margin-top: 1em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
div.anchorlink a {
|
||||
padding: 3px;
|
||||
background: #cae7e4;
|
||||
font-size: 0.75em;
|
||||
color: black;
|
||||
}
|
||||
div.guidelink,
|
||||
p[dir=ltr] {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
|
||||
margin: 0;
|
||||
margin-top: 1em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
div.guidelink a,
|
||||
p[dir=ltr] a {
|
||||
display: inline-block;
|
||||
border-radius: 3px;
|
||||
padding: 3px;
|
||||
|
||||
background: #3eaffa;
|
||||
|
||||
font-size: 0.75em;
|
||||
color: #fff;
|
||||
}
|
||||
@ -265,7 +268,7 @@ input,
|
||||
select {
|
||||
font-size: 1em;
|
||||
}
|
||||
p.result {
|
||||
.result {
|
||||
border: 1px;
|
||||
border-style: dashed;
|
||||
border-color: #FE8A02;
|
||||
@ -284,3 +287,18 @@ p.result {
|
||||
color: #cb2431;
|
||||
transition: none;
|
||||
}
|
||||
h3.api {
|
||||
border-bottom: 1px solid #b6b6b6;
|
||||
}
|
||||
details > summary {
|
||||
background-color: #dbeceb;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
padding: 8px;
|
||||
}
|
||||
details > pre, details > p {
|
||||
background-color: #e6f1f0;
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
}
|
||||
|
1
priv/css/sortable.min.css
vendored
Normal file
1
priv/css/sortable.min.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.sortable thead th:not(.no-sort){cursor:pointer}.sortable thead th:not(.no-sort)::after,.sortable thead th:not(.no-sort)::before{transition:color .1s ease-in-out;font-size:1.2em;color:rgba(0,0,0,0)}.sortable thead th:not(.no-sort)::after{margin-left:3px;content:"▸"}.sortable thead th:not(.no-sort):hover::after{color:inherit}.sortable thead th:not(.no-sort)[aria-sort=descending]::after{color:inherit;content:"▾"}.sortable thead th:not(.no-sort)[aria-sort=ascending]::after{color:inherit;content:"▴"}.sortable thead th:not(.no-sort).indicator-left::after{content:""}.sortable thead th:not(.no-sort).indicator-left::before{margin-right:3px;content:"▸"}.sortable thead th:not(.no-sort).indicator-left:hover::before{color:inherit}.sortable thead th:not(.no-sort).indicator-left[aria-sort=descending]::before{color:inherit;content:"▾"}.sortable thead th:not(.no-sort).indicator-left[aria-sort=ascending]::before{color:inherit;content:"▴"}/*# sourceMappingURL=sortable-base.min.css.map */
|
3
priv/js/sortable.min.js
vendored
Normal file
3
priv/js/sortable.min.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
document.addEventListener("click",function(c){try{function h(b,a){return b.nodeName===a?b:h(b.parentNode,a)}var v=c.shiftKey||c.altKey,d=h(c.target,"TH"),m=d.parentNode,n=m.parentNode,g=n.parentNode;function p(b){var a;return v?b.dataset.sortAlt:null!==(a=b.dataset.sort)&&void 0!==a?a:b.textContent}if("THEAD"===n.nodeName&&g.classList.contains("sortable")&&!d.classList.contains("no-sort")){var q,f=m.cells,r=+d.dataset.sortTbr;for(c=0;c<f.length;c++)f[c]===d?q=+d.dataset.sortCol||c:f[c].setAttribute("aria-sort",
|
||||
"none");f="descending";if("descending"===d.getAttribute("aria-sort")||g.classList.contains("asc")&&"ascending"!==d.getAttribute("aria-sort"))f="ascending";d.setAttribute("aria-sort",f);var w="ascending"===f,x=g.classList.contains("n-last"),t=function(b,a,e){a=p(a.cells[e]);b=p(b.cells[e]);if(x){if(""===a&&""!==b)return-1;if(""===b&&""!==a)return 1}e=+a-+b;a=isNaN(e)?a.localeCompare(b):e;return w?-a:a};for(c=0;c<g.tBodies.length;c++){var k=g.tBodies[c],u=[].slice.call(k.rows,0);u.sort(function(b,a){var e=
|
||||
t(b,a,q);return 0!==e||isNaN(r)?e:t(b,a,r)});var l=k.cloneNode();l.append.apply(l,u);g.replaceChild(l,k)}}}catch(h){}});
|
@ -130,6 +130,7 @@
|
||||
{if_version_below, "24", {d, 'SYSTOOLS_APP_DEF_WITHOUT_OPTIONAL'}},
|
||||
{if_version_below, "24", {d, 'OTP_BELOW_24'}},
|
||||
{if_version_below, "25", {d, 'OTP_BELOW_25'}},
|
||||
{if_version_below, "26", {d, 'OTP_BELOW_26'}},
|
||||
{if_version_below, "27", {d, 'OTP_BELOW_27'}},
|
||||
{if_var_false, debug, no_debug_info},
|
||||
{if_var_true, debug, debug_info},
|
||||
|
@ -344,10 +344,10 @@ validator(from) ->
|
||||
fun(L) when is_list(L) ->
|
||||
lists:map(
|
||||
fun({K, V}) -> {(econf:enum([tag]))(K), (econf:binary())(V)};
|
||||
(A) -> (econf:enum([ejabberd_xmlrpc, mod_cron, mod_http_api, ejabberd_ctl]))(A)
|
||||
(A) -> (econf:enum([ejabberd_xmlrpc, mod_cron, mod_http_api, ejabberd_ctl, ejabberd_web_admin]))(A)
|
||||
end, lists:flatten(L));
|
||||
(A) ->
|
||||
[(econf:enum([ejabberd_xmlrpc, mod_cron, mod_http_api, ejabberd_ctl]))(A)]
|
||||
[(econf:enum([ejabberd_xmlrpc, mod_cron, mod_http_api, ejabberd_ctl, ejabberd_web_admin]))(A)]
|
||||
end;
|
||||
validator(what) ->
|
||||
econf:and_then(
|
||||
|
@ -32,7 +32,8 @@
|
||||
%% gen_server callbacks
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||
terminate/2, code_change/3]).
|
||||
-export([get_commands_spec/0]).
|
||||
-export([get_commands_spec/0, format_arg/2,
|
||||
get_usage_command/4]).
|
||||
|
||||
-include("ejabberd_ctl.hrl").
|
||||
-include("ejabberd_commands.hrl").
|
||||
@ -786,7 +787,7 @@ print_usage_help(MaxC, ShCode) ->
|
||||
longdesc = lists:flatten(LongDesc),
|
||||
args = ArgsDef,
|
||||
result = {help, string}},
|
||||
print_usage_command2("help", C, MaxC, ShCode).
|
||||
print(get_usage_command2("help", C, MaxC, ShCode), []).
|
||||
|
||||
|
||||
%%-----------------------------
|
||||
@ -848,11 +849,14 @@ maybe_add_policy_arguments(Args, _) ->
|
||||
-spec print_usage_command(Cmd::string(), MaxC::integer(),
|
||||
ShCode::boolean(), Version::integer()) -> ok.
|
||||
print_usage_command(Cmd, MaxC, ShCode, Version) ->
|
||||
print(get_usage_command(Cmd, MaxC, ShCode, Version), []).
|
||||
|
||||
get_usage_command(Cmd, MaxC, ShCode, Version) ->
|
||||
Name = list_to_atom(Cmd),
|
||||
C = ejabberd_commands:get_command_definition(Name, Version),
|
||||
print_usage_command2(Cmd, C, MaxC, ShCode).
|
||||
get_usage_command2(Cmd, C, MaxC, ShCode).
|
||||
|
||||
print_usage_command2(Cmd, C, MaxC, ShCode) ->
|
||||
get_usage_command2(Cmd, C, MaxC, ShCode) ->
|
||||
#ejabberd_commands{
|
||||
tags = TagsAtoms,
|
||||
definer = Definer,
|
||||
@ -926,12 +930,12 @@ print_usage_command2(Cmd, C, MaxC, ShCode) ->
|
||||
false -> ""
|
||||
end,
|
||||
|
||||
case Cmd of
|
||||
"help" -> ok;
|
||||
_ -> print([NameFmt, "\n", ArgsFmt, "\n", ReturnsFmt,
|
||||
"\n\n", ExampleFmt, TagsFmt, "\n\n", ModuleFmt, NoteFmt, DescFmt, "\n\n"], [])
|
||||
First = case Cmd of
|
||||
"help" -> "";
|
||||
_ -> [NameFmt, "\n", ArgsFmt, "\n", ReturnsFmt,
|
||||
"\n\n", ExampleFmt, TagsFmt, "\n\n", ModuleFmt, NoteFmt, DescFmt, "\n\n"]
|
||||
end,
|
||||
print([LongDescFmt, NoteEjabberdctlList, NoteEjabberdctlTuple], []).
|
||||
[First, LongDescFmt, NoteEjabberdctlList, NoteEjabberdctlTuple].
|
||||
|
||||
%%-----------------------------
|
||||
%% Format Arguments Help
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user