]> granicus.if.org Git - ejabberd/commitdiff
* src/web/ejabberd_web_admin.erl: Use textareas for large input
authorBadlop <badlop@process-one.net>
Mon, 12 Jan 2009 21:48:34 +0000 (21:48 +0000)
committerBadlop <badlop@process-one.net>
Mon, 12 Jan 2009 21:48:34 +0000 (21:48 +0000)
like ejabberd module options and listening port options. Show
result of POST more clearly. Ensure access rules are shown with
some minimum separation. Improve menu headers. (EJAB-562)
* src/web/ejabberd_web_admin.hrl: Likewise
* src/mod_offline.erl: Likewise
* src/mod_offline_odbc.erl: Likewise
* src/mod_roster.erl: Likewise
* src/mod_roster_odbc.erl: Likewise
* src/mod_shared_roster.erl: Likewise

SVN Revision: 1813

ChangeLog
src/mod_offline.erl
src/mod_offline_odbc.erl
src/mod_roster.erl
src/mod_roster_odbc.erl
src/mod_shared_roster.erl
src/web/ejabberd_web_admin.erl
src/web/ejabberd_web_admin.hrl

index 6270afdc30e38d5f9dfa2a0222d5c3ed0facd9c2..aaae27172326ee688fd83e93773129beaa88ab8a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2009-01-12  Badlop  <badlop@process-one.net>
 
+       * src/web/ejabberd_web_admin.erl: Use textareas for large input
+       like ejabberd module options and listening port options. Show
+       result of POST more clearly. Ensure access rules are shown with
+       some minimum separation. Improve menu headers. (EJAB-562)
+       * src/web/ejabberd_web_admin.hrl: Likewise
+       * src/mod_offline.erl: Likewise
+       * src/mod_offline_odbc.erl: Likewise
+       * src/mod_roster.erl: Likewise
+       * src/mod_roster_odbc.erl: Likewise
+       * src/mod_shared_roster.erl: Likewise
+
        * src/ejabberd_listener.erl: New way to configure IP address and
        IP version of listener. Support for definition of IP address in
        string format, and implicit definition of IP
@@ -13,6 +24,7 @@
        * src/mod_proxy65/mod_proxy65_stream.erl: Likewise
        * src/mod_proxy65/mod_proxy65_service.erl: Likewise
        * src/web/ejabberd_web_admin.erl: Likewise
+
        * doc/guide.tex: Document the new way to configure IP address and
        IP version of listener, undocument options ip and inet6
        * doc/guide.html: Likewise
index b2e2b5db2aaa530727b4d660106b7eca1a76313d..0607ddb8b06055bc8dd19605a1fa46546776e7fc 100644 (file)
@@ -500,7 +500,7 @@ user_queue(User, Server, Query, Lang) ->
     [?XC("h1", io_lib:format(?T("~s's Offline Messages Queue"),
                             [us_to_list(US)]))] ++
        case Res of
-           ok -> [?CT("Submitted"), ?P];
+           ok -> [?XREST("Submitted")];
            nothing -> []
        end ++
        [?XAE("form", [{"action", ""}, {"method", "post"}],
index b3f1ec10a708a5dfcfb1df7afc6ed47e2ac16d57..e70cfbe6930ccbd97756cb25310f4de73237c048 100644 (file)
@@ -358,7 +358,7 @@ user_queue(User, Server, Query, Lang) ->
     [?XC("h1", io_lib:format(?T("~s's Offline Messages Queue"),
                             [us_to_list(US)]))] ++
        case Res of
-           ok -> [?CT("Submitted"), ?P];
+           ok -> [?XREST("Submitted")];
            nothing -> []
        end ++
        [?XAE("form", [{"action", ""}, {"method", "post"}],
index c52ff57f4158ca7fce98e202226c6245b9147291..a1639c55fc9f25cb205340741ab90aa40228c8fd 100644 (file)
@@ -844,8 +844,8 @@ user_roster(User, Server, Query, Lang) ->
        end,
     [?XC("h1", ?T("Roster of ") ++ us_to_list(US))] ++
        case Res of
-           ok -> [?CT("Submitted"), ?P];
-           error -> [?CT("Bad format"), ?P];
+           ok -> [?XREST("Submitted")];
+           error -> [?XREST("Bad format")];
            nothing -> []
        end ++
        [?XAE("form", [{"action", ""}, {"method", "post"}],
index 1678e52591a968c9fafd85232acc618b5f34e823..ee4e326a70dee1c5594d636df94a5b290f94f03a 100644 (file)
@@ -944,8 +944,8 @@ user_roster(User, Server, Query, Lang) ->
        end,
     [?XC("h1", ?T("Roster of ") ++ us_to_list(US))] ++
        case Res of
-           ok -> [?CT("Submitted"), ?P];
-           error -> [?CT("Bad format"), ?P];
+           ok -> [?XREST("Submitted")];
+           error -> [?XREST("Bad format")];
            nothing -> []
        end ++
        [?XAE("form", [{"action", ""}, {"method", "post"}],
index 01bd16622ef2b4d2120e21d56724417c13367932..1a15119b5caeeecb993895943467384330d222f7 100644 (file)
@@ -725,8 +725,8 @@ list_shared_roster_groups(Host, Query, Lang) ->
                 )]),
     ?H1GL(?T("Shared Roster Groups"), "modsharedroster", "mod_shared_roster") ++
        case Res of
-           ok -> [?CT("Submitted"), ?P];
-           error -> [?CT("Bad format"), ?P];
+           ok -> [?XREST("Submitted")];
+           error -> [?XREST("Bad format")];
            nothing -> []
        end ++
        [?XAE("form", [{"action", ""}, {"method", "post"}],
@@ -789,8 +789,9 @@ shared_roster_group(Host, Group, Query, Lang) ->
                []
        end ++ [[us_to_list(Member), $\n] || Member <- Members],
     FDisplayedGroups = [[DG, $\n] || DG <- DisplayedGroups],
+    DescNL = length(element(2, regexp:split(Description, "\n"))),
     FGroup =
-       ?XAE("table", [],
+       ?XAE("table", [{"class", "withtextareas"}],
             [?XE("tbody",
                  [?XE("tr",
                       [?XCT("td", "Name:"),
@@ -799,34 +800,34 @@ shared_roster_group(Host, Group, Query, Lang) ->
                      ),
                   ?XE("tr",
                       [?XCT("td", "Description:"),
-                       ?XE("td", [?XAC("textarea", [{"name", "description"},
-                                                    {"rows", "3"},
-                                                    {"cols", "20"}],
-                                       Description)])
+                       ?XE("td", [
+                                  ?TEXTAREA("description", integer_to_list(lists:max([3, DescNL])), "20", Description)
+                                 ]
+                          )
                       ]
                      ),
                   ?XE("tr",
                       [?XCT("td", "Members:"),
-                       ?XE("td", [?XAC("textarea", [{"name", "members"},
-                                                    {"rows", "3"},
-                                                    {"cols", "20"}],
-                                       FMembers)])
+                       ?XE("td", [
+                                  ?TEXTAREA("members", integer_to_list(lists:max([3, length(FMembers)])), "20", FMembers)
+                                 ]
+                          )
                       ]
                      ),
                   ?XE("tr",
                       [?XCT("td", "Displayed Groups:"),
-                       ?XE("td", [?XAC("textarea", [{"name", "dispgroups"},
-                                                    {"rows", "3"},
-                                                    {"cols", "20"}],
-                                       FDisplayedGroups)])
+                       ?XE("td", [
+                                  ?TEXTAREA("dispgroups", integer_to_list(lists:max([3, length(FDisplayedGroups)])), "20", FDisplayedGroups)
+                                 ]
+                          )
                       ]
                      )]
                 )]),
     ?H1GL(?T("Shared Roster Groups"), "modsharedroster", "mod_shared_roster") ++
        [?XC("h2", ?T("Group ") ++ Group)] ++
        case Res of
-           ok -> [?CT("Submitted"), ?P];
-           error -> [?CT("Bad format"), ?P];
+           ok -> [?XREST("Submitted")];
+           error -> [?XREST("Bad format")];
            nothing -> []
        end ++
        [?XAE("form", [{"action", ""}, {"method", "post"}],
index cf3150b90b53bf21681944709c914935e653470b..ea1a936ebf41586eed88d7eb8f4b3f21fa6dae57 100644 (file)
@@ -157,7 +157,7 @@ make_xhtml(Els, Host, Node, Lang) ->
                 [?XAE("div",
                       [{"id", "header"}],
                       [?XE("h1",
-                           [?ACT("/admin/", "Administration")]
+                           [?ACT("/admin/", "ejabberd Web Admin")]
                           )]),
                  ?XAE("div",
                       [{"id", "navigation"}],
@@ -312,6 +312,7 @@ ul li #navhead a, ul li #navheadsub a, ul li #navheadsubsub a {
   text-align: center;
   border-top: 2px solid #d47911;
   border-bottom: 1px solid #d47911;
+  background: #FED6A6;
 }
 
 #navheadsub, #navitemsub {
@@ -367,10 +368,6 @@ textarea {
   border: 1px solid #d6760e;
   color: #723202;
   background-color: #fff2e8;
-  vertical-align: middle;
-  margin-top: 7px;
-  margin-bottom: 5px;
-  padding: 0.1em;
 }
 
 select {
@@ -538,6 +535,19 @@ div.guidelink {
   padding-right: 1em;
 }
 
+table.withtextareas>tbody>tr>td {
+  vertical-align: top;
+}
+
+p.result {
+  border: 1px;
+  border-style: dashed;
+  border-color: #FE8A02;
+  padding: 1em;
+  margin-right: 1em;
+  background: #FFE3C9;
+}
+
 *.alignright {
   font-size: 10pt;
 }
@@ -633,6 +643,7 @@ process_admin(Host,
              #request{path = ["acls-raw"],
                       q = Query,
                       lang = Lang}) ->
+
     Res = case lists:keysearch("acls", 1, Query) of
              {value, {_, String}} ->
                  case erl_scan:string(String) of
@@ -654,22 +665,17 @@ process_admin(Host,
              _ ->
                  nothing
          end,
-    ACLs = lists:flatten(
-            io_lib:format(
-              "~p.", [lists:keysort(
-                        2, ets:select(acl, [{{acl, {'$1', Host}, '$2'},
-                                             [], [{{acl, '$1', '$2'}}]}]))])),
+    ACLs = lists:keysort(2, ets:select(acl, [{{acl, {'$1', Host}, '$2'},
+                                             [], [{{acl, '$1', '$2'}}]}])),
+    {NumLines, ACLsP} = term_to_paragraph(ACLs, 80),
     make_xhtml(?H1GL(?T("Access Control Lists"), "ACLDefinition", "ACL Definition") ++
               case Res of
-                  ok -> [?CT("Submitted"), ?P];
-                  error -> [?CT("Bad format"), ?P];
+                  ok -> [?XREST("Submitted")];
+                  error -> [?XREST("Bad format")];
                   nothing -> []
               end ++
               [?XAE("form", [{"action", ""}, {"method", "post"}],
-                    [?XAC("textarea", [{"name", "acls"},
-                                       {"rows", "16"},
-                                       {"cols", "80"}],
-                          ACLs),
+                    [?TEXTAREA("acls", integer_to_list(lists:max([16, NumLines])), "80", ACLsP++"."),
                      ?BR,
                      ?INPUTT("submit", "submit", "Submit")
                     ])
@@ -704,8 +710,8 @@ process_admin(Host,
                                  [], [{{acl, '$1', '$2'}}]}])),
     make_xhtml(?H1GL(?T("Access Control Lists"), "ACLDefinition", "ACL Definition") ++
               case Res of
-                  ok -> [?CT("Submitted"), ?P];
-                  error -> [?CT("Bad format"), ?P];
+                  ok -> [?XREST("Submitted")];
+                  error -> [?XREST("Bad format")];
                   nothing -> []
               end ++
               [?XE("p", [?ACT("../acls-raw/", "Raw")])] ++
@@ -764,23 +770,19 @@ process_admin(Host,
                  nothing
          end,
     Access =
-       lists:flatten(
-         io_lib:format(
-           "~p.", [ets:select(config,
+           ets:select(config,
                               [{{config, {access, '$1', Host}, '$2'},
                                 [],
-                                [{{access, '$1', '$2'}}]}])])),
+                                [{{access, '$1', '$2'}}]}]),
+    {NumLines, AccessP} = term_to_paragraph(Access, 80),
     make_xhtml(?H1GL(?T("Access Rules"), "AccessRights", "Access Rights") ++
               case Res of
-                  ok -> [?CT("Submitted"), ?P];
-                  error -> [?CT("Bad format"), ?P];
+                  ok -> [?XREST("Submitted")];
+                  error -> [?XREST("Bad format")];
                   nothing -> []
               end ++
               [?XAE("form", [{"action", ""}, {"method", "post"}],
-                    [?XAC("textarea", [{"name", "access"},
-                                       {"rows", "16"},
-                                       {"cols", "80"}],
-                          Access),
+                    [?TEXTAREA("access", integer_to_list(lists:max([16, NumLines])), "80", AccessP++"."),
                      ?BR,
                      ?INPUTT("submit", "submit", "Submit")
                     ])
@@ -810,8 +812,8 @@ process_admin(Host,
                     [{{access, '$1', '$2'}}]}]),
     make_xhtml(?H1GL(?T("Access Rules"), "AccessRights", "Access Rights") ++
               case Res of
-                  ok -> [?CT("Submitted"), ?P];
-                  error -> [?CT("Bad format"), ?P];
+                  ok -> [?XREST("Submitted")];
+                  error -> [?XREST("Bad format")];
                   nothing -> []
               end ++
               [?XE("p", [?ACT("../access-raw/", "Raw")])] ++
@@ -850,8 +852,8 @@ process_admin(Host,
     make_xhtml([?XC("h1",
                    io_lib:format(?T("~s access rule configuration"), [SName]))] ++
               case Res of
-                  ok -> [?CT("Submitted"), ?P];
-                  error -> [?CT("Bad format"), ?P];
+                  ok -> [?XREST("Submitted")];
+                  error -> [?XREST("Bad format")];
                   nothing -> []
               end ++
               [?XAE("form", [{"action", ""}, {"method", "post"}],
@@ -1054,12 +1056,20 @@ acl_spec_select(ID, Opt) ->
                      node_regexp, user_glob, server_glob, node_glob, all, raw]))]).
 
 
+%% @spec (T::any()) -> StringLine::string()
 term_to_string(T) ->
     StringParagraph = lists:flatten(io_lib:format("~1000000p", [T])),
     %% Remove from the string all the carriage returns characters
     {ok, StringLine, _} = regexp:gsub(StringParagraph, "\\n ", ""),
     StringLine.
 
+%% @spec (T::any()) -> {NumLines::integer(), Paragraph::string()}
+term_to_paragraph(T, Cols) ->
+       Paragraph = erl_prettypr:format(erl_syntax:abstract(T), [{paper, Cols}]),
+       {ok, FieldList} = regexp:split(Paragraph, "\n"),
+       NumLines = length(FieldList),
+       {NumLines, Paragraph}.
+
 term_to_id(T) ->
     jlib:encode_base64(binary_to_list(term_to_binary(T))).
 
@@ -1227,7 +1237,7 @@ access_rule_to_xhtml(Rules) ->
             fun({Access, ACL} = _Rule) ->
                     SAccess = element_to_list(Access),
                     SACL = atom_to_list(ACL),
-                    SAccess ++ "\t" ++ SACL ++ "\n"
+                    SAccess ++ "\s\t" ++ SACL ++ "\n"
             end, Rules),
     ?XAC("textarea", [{"name", "rules"},
                      {"rows", "16"},
@@ -1304,8 +1314,8 @@ list_users(Host, Query, Lang, URLFunc) ->
                  end, lists:seq(1, N, M))
        end,
     case Res of
-       ok -> [?CT("Submitted"), ?P];
-       error -> [?CT("Bad format"), ?P];
+       ok -> [?XREST("Submitted")];
+       error -> [?XREST("Bad format")];
        nothing -> []
     end ++
        [?XAE("form", [{"action", ""}, {"method", "post"}],
@@ -1500,8 +1510,8 @@ user_info(User, Server, Query, Lang) ->
                                        [User, Server, Lang]),
     [?XC("h1", ?T("User ") ++ us_to_list(US))] ++
        case Res of
-           ok -> [?CT("Submitted"), ?P];
-           error -> [?CT("Bad format"), ?P];
+           ok -> [?XREST("Submitted")];
+           error -> [?XREST("Bad format")];
            nothing -> []
        end ++
        [?XAE("form", [{"action", ""}, {"method", "post"}],
@@ -1668,8 +1678,8 @@ get_node(global, Node, [], Query, Lang) ->
     MenuItems2 = make_menu_items(global, Node, Base, Lang),
     [?XC("h1", ?T("Node ") ++ atom_to_list(Node))] ++
        case Res of
-           ok -> [?CT("Submitted"), ?P];
-           error -> [?CT("Bad format"), ?P];
+           ok -> [?XREST("Submitted")];
+           error -> [?XREST("Bad format")];
            nothing -> []
        end ++
        [?XE("ul",
@@ -1698,7 +1708,10 @@ get_node(global, Node, ["db"], Query, Lang) ->
        {badrpc, _Reason} ->
            [?XCT("h1", "RPC Call Error")];
        Tables ->
-           node_db_parse_query(Node, Tables, Query),
+           ResS = case node_db_parse_query(Node, Tables, Query) of
+                      nothing -> [];
+                      ok -> [?XREST("Submitted")]
+                  end,
            STables = lists:sort(Tables),
            Rows = lists:map(
                     fun(Table) ->
@@ -1735,7 +1748,7 @@ get_node(global, Node, ["db"], Query, Lang) ->
                                 ])
                     end, STables),
            [?XC("h1", ?T("Database Tables at ") ++ atom_to_list(Node))] ++
-               [?CT("Submitted"), ?P] ++
+               ResS ++
                [?XAE("form", [{"action", ""}, {"method", "post"}],
                      [?XAE("table", [],
                            [?XE("thead",
@@ -1757,9 +1770,14 @@ get_node(global, Node, ["db"], Query, Lang) ->
     end;
 
 get_node(global, Node, ["backup"], Query, Lang) ->
-    _Res = node_backup_parse_query(Node, Query),
-    [?XC("h1", ?T("Backup of ") ++ atom_to_list(Node)),
-     ?XCT("p", "Remark that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately."),
+    ResS = case node_backup_parse_query(Node, Query) of
+              nothing -> [];
+              ok -> [?XREST("Submitted")];
+              {error, Error} -> [?XRES(?T("Error") ++": " ++ io_lib:format("~p", [Error]))]
+          end,
+    [?XC("h1", ?T("Backup of ") ++ atom_to_list(Node))] ++
+       ResS ++
+       [?XCT("p", "Remark that these options will only backup the builtin Mnesia database. If you are using the ODBC module, you also need to backup your SQL database separately."),
      ?XAE("form", [{"action", ""}, {"method", "post"}],
          [?XAE("table", [],
                [?XE("tbody",
@@ -1822,9 +1840,9 @@ get_node(global, Node, ["ports"], Query, Lang) ->
     H1String = ?T("Listened Ports at ") ++ atom_to_list(Node),
     ?H1GL(H1String, "listened", "Listening Ports") ++
        case Res of
-           ok -> [?CT("Submitted"), ?P];
-           error -> [?CT("Bad format"), ?P];
-           {error, ReasonT} -> [?CT("Problem: "), ?C(ReasonT), ?P];
+           ok -> [?XREST("Submitted")];
+           error -> [?XREST("Bad format")];
+           {error, ReasonT} -> [?XRES(?T("Error") ++ ": " ++ ReasonT)];
            nothing -> []
        end ++
        [?XAE("form", [{"action", ""}, {"method", "post"}],
@@ -1847,8 +1865,8 @@ get_node(Host, Node, ["modules"], Query, Lang) when is_list(Host) ->
     H1String = ?T("Modules at ") ++ atom_to_list(Node),
     ?H1GL(H1String, "modoverview", "Modules Overview") ++
        case Res of
-           ok -> [?CT("Submitted"), ?P];
-           error -> [?CT("Bad format"), ?P];
+           ok -> [?XREST("Submitted")];
+           error -> [?XREST("Bad format")];
            nothing -> []
        end ++
        [?XAE("form", [{"action", ""}, {"method", "post"}],
@@ -1916,17 +1934,19 @@ get_node(global, Node, ["update"], Query, Lang) ->
     FmtLowLevelScript = ?XC("pre", io_lib:format("~p", [LowLevelScript])),
     [?XC("h1", ?T("Update ") ++ atom_to_list(Node))] ++
        case Res of
-           ok -> [?CT("Submitted"), ?P];
-           error -> [?CT("Bad format"), ?P];
+           ok -> [?XREST("Submitted")];
+           error -> [?XREST("Bad format")];
            nothing -> []
        end ++
        [?XAE("form", [{"action", ""}, {"method", "post"}],
-             [?INPUTT("submit", "update", "Update"),
+             [
               ?XCT("h2", "Update plan"),
-              ?XCT("h3", "Updated modules"), Mods,
+              ?XCT("h3", "Modified modules"), Mods,
               ?XCT("h3", "Update script"), FmtScript,
               ?XCT("h3", "Low level update script"), FmtLowLevelScript,
-              ?XCT("h3", "Script check"), ?C(atom_to_list(Check))])
+              ?XCT("h3", "Script check"), ?XC("pre", atom_to_list(Check)),
+              ?INPUTT("submit", "update", "Update")
+             ])
        ];
 
 get_node(Host, Node, NPath, Query, Lang) ->
@@ -1981,6 +2001,8 @@ db_storage_select(ID, Opt, Lang) ->
                 {disc_only_copies, "Disc only copy"},
                 {unknown, "Remote copy"}])).
 
+node_db_parse_query(_Node, _Tables, [{nokey,[]}]) ->
+    nothing;
 node_db_parse_query(Node, Tables, Query) ->
     lists:foreach(
       fun(Table) ->
@@ -2014,6 +2036,8 @@ node_db_parse_query(Node, Tables, Query) ->
       end, Tables),
     ok.
 
+node_backup_parse_query(_Node, [{nokey,[]}]) ->
+    nothing;
 node_backup_parse_query(Node, Query) ->
     lists:foldl(
       fun(Action, nothing) ->
@@ -2040,15 +2064,15 @@ node_backup_parse_query(Node, Query) ->
                                                   load_textfile, [Path])
                                  end,
                              case Res of
-                                 {error, _Reason} ->
-                                     error;
-                                 {badrpc, _Reason} ->
-                                     error;
+                                 {error, Reason} ->
+                                     {error, Reason};
+                                 {badrpc, Reason} ->
+                                     {badrpc, Reason};
                                  _ ->
                                      ok
                              end;
-                         _ ->
-                             error
+                         OtherError ->
+                             {error, OtherError}
                      end;
                  _ ->
                      nothing
@@ -2059,7 +2083,7 @@ node_backup_parse_query(Node, Query) ->
 
 
 node_ports_to_xhtml(Ports, Lang) ->
-    ?XAE("table", [],
+    ?XAE("table", [{"class", "withtextareas"}],
         [?XE("thead",
              [?XE("tr",
                   [?XCT("td", "Port"),
@@ -2073,14 +2097,14 @@ node_ports_to_xhtml(Ports, Lang) ->
                        {_Port, SPort, _TIP, SIP, SSPort, OptsClean} =
                            get_port_data(PortIP, Opts),
                        SModule = atom_to_list(Module),
+                       {NumLines, SOptsClean} = term_to_paragraph(OptsClean, 40),
                        %%ID = term_to_id(E),
                        ?XE("tr",
                            [?XAE("td", [{"size", "6"}], [?C(SPort)]),
                             ?XAE("td", [{"size", "15"}], [?C(SIP)]),
                             ?XE("td", [?INPUTS("text", "module" ++ SSPort,
                                                SModule, "15")]),
-                            ?XE("td", [?INPUTS("text", "opts" ++ SSPort,
-                                               term_to_string(OptsClean), "40")]),
+                            ?XE("td", [?TEXTAREA("opts" ++ SSPort, integer_to_list(NumLines), "35", SOptsClean)]),
                             ?XE("td", [?INPUTT("submit", "add" ++ SSPort,
                                                "Update")]),
                             ?XE("td", [?INPUTT("submit", "delete" ++ SSPort,
@@ -2091,8 +2115,8 @@ node_ports_to_xhtml(Ports, Lang) ->
              [?XE("tr",
                   [?XE("td", [?INPUTS("text", "portnew", "", "6")]),
                    ?XE("td", [?INPUTS("text", "ipnew", "0.0.0.0", "15")]),
-                   ?XE("td", [?INPUTS("text", "modulenew", "", "17")]),
-                   ?XE("td", [?INPUTS("text", "optsnew", "[]", "40")]),
+                   ?XE("td", [?INPUTS("text", "modulenew", "", "15")]),
+                   ?XE("td", [?TEXTAREA("optsnew", "2", "35", "[]")]),
                    ?XAE("td", [{"colspan", "2"}],
                         [?INPUTT("submit", "addnew", "Add New")])
                   ]
@@ -2170,7 +2194,7 @@ node_ports_parse_query(Node, Ports, Query) ->
     end.
 
 node_modules_to_xhtml(Modules, Lang) ->
-    ?XAE("table", [],
+    ?XAE("table", [{"class", "withtextareas"}],
         [?XE("thead",
              [?XE("tr",
                   [?XCT("td", "Module"),
@@ -2180,11 +2204,11 @@ node_modules_to_xhtml(Modules, Lang) ->
              lists:map(
                fun({Module, Opts} = _E) ->
                        SModule = atom_to_list(Module),
+                       {NumLines, SOpts} = term_to_paragraph(Opts, 40),
                        %%ID = term_to_id(E),
                        ?XE("tr",
                            [?XC("td", SModule),
-                            ?XE("td", [?INPUTS("text", "opts" ++ SModule,
-                                               term_to_string(Opts), "40")]),
+                            ?XE("td", [?TEXTAREA("opts" ++ SModule, integer_to_list(NumLines), "40", SOpts)]),
                             ?XE("td", [?INPUTT("submit", "restart" ++ SModule,
                                                "Restart")]),
                             ?XE("td", [?INPUTT("submit", "stop" ++ SModule,
@@ -2194,7 +2218,7 @@ node_modules_to_xhtml(Modules, Lang) ->
                end, Modules) ++
              [?XE("tr",
                   [?XE("td", [?INPUT("text", "modulenew", "")]),
-                   ?XE("td", [?INPUTS("text", "optsnew", "", "40")]),
+                   ?XE("td", [?TEXTAREA("optsnew", "2", "40", "[]")]),
                    ?XAE("td", [{"colspan", "2"}],
                         [?INPUTT("submit", "start", "Start")])
                   ]
@@ -2437,11 +2461,11 @@ make_menu_items2(Lang, Deep, {MURI, MName, [Item | Items]}, Res) ->
     make_menu_items2(Lang, Deep, {MURI, MName, Items}, Res2).
 
 make_menu_item(header, 1, URI, Name, _Lang) ->
-    ?LI([?XAE("div", [{"id", "navhead"}], [?AC(URI, "~ "++Name++" ~")] )]);
+    ?LI([?XAE("div", [{"id", "navhead"}], [?AC(URI, Name)] )]);
 make_menu_item(header, 2, URI, Name, _Lang) ->
-    ?LI([?XAE("div", [{"id", "navheadsub"}], [?AC(URI, "~ "++Name++" ~")] )]);
+    ?LI([?XAE("div", [{"id", "navheadsub"}], [?AC(URI, Name)] )]);
 make_menu_item(header, 3, URI, Name, _Lang) ->
-    ?LI([?XAE("div", [{"id", "navheadsubsub"}], [?AC(URI, "~ "++Name++" ~")] )]);
+    ?LI([?XAE("div", [{"id", "navheadsubsub"}], [?AC(URI, Name)] )]);
 make_menu_item(item, 1, URI, Name, Lang) ->
     ?LI([?XAE("div", [{"id", "navitem"}], [?ACT(URI, Name)] )]);
 make_menu_item(item, 2, URI, Name, Lang) ->
index d197e3abeba216ca96285355054f74b67f4d5ca9..2bf164e0ba2b7da57093619bd1f03a5d1159ae98 100644 (file)
 -define(INPUTST(Type, Name, Value, Size), ?INPUT(Type, Name, ?T(Value), Size)).
 -define(ACLINPUT(Text), ?XE("td", [?INPUT("text", "value" ++ ID, Text)])).
 
+-define(TEXTAREA(Name, Rows, Cols, Value),
+       ?XAC("textarea", [{"name", Name},
+                         {"rows", Rows},
+                         {"cols", Cols}],
+            Value)).
+
+%% Build an xmlelement for result
+-define(XRES(Text), ?XAC("p", [{"class", "result"}], Text)).
+-define(XREST(Text), ?XRES(?T(Text))).
+
 %% Guide Link
 -define(GL(Ref, Title),
        ?XAE("div",