]> gitweb @ CieloNegro.org - Rakka.git/commitdiff
misc changes
authorpho <pho@cielonegro.org>
Thu, 12 Nov 2009 10:26:32 +0000 (19:26 +0900)
committerpho <pho@cielonegro.org>
Thu, 12 Nov 2009 10:26:32 +0000 (19:26 +0900)
Ignore-this: 4d480ac253d37bf3e9f0a508e5843100

darcs-hash:20091112102632-62b54-bd888319e64c39535edd9d2684d1cc910679ccb5.gz

Rakka/Authorization.hs
Rakka/Resource/Users.hs
defaultPages/StyleSheet/CieloNegro.xml
defaultPages/StyleSheet/Default.xml
js/Makefile
js/hashedParam.js [new file with mode: 0644]
js/redirection.js
js/systemConfig.js

index ccc4b36c477318177f064fdca75f79d7ab43b427..adf2da54fc9a520db5273e38acdad9bd7c215876 100644 (file)
@@ -28,7 +28,6 @@ data AuthDB
     = AuthDB {
         adbFilePath    :: !FilePath
       , adbUserMap     :: !(TVar UserMap)
-      , adbSyncRequest :: !(TVar Bool)
       }
 
 
@@ -38,12 +37,10 @@ type UserMap = Map String String
 mkAuthDB :: FilePath -> IO AuthDB
 mkAuthDB lsdir
     = do let path = lsdir </> "authDB"
-         m   <- newTVarIO =<< loadUserMap path
-         req <- newTVarIO False
+         m <- newTVarIO =<< loadUserMap path
          return AuthDB {
-                      adbFilePath    = path
-                    , adbUserMap     = m
-                    , adbSyncRequest = req
+                      adbFilePath = path
+                    , adbUserMap  = m
                     }
 
 
index a4bf60204b047d54944afb08dadc62fd08386f13..fa61ad86fbe373bf38133dd365a004d6cf4f2f2d 100644 (file)
@@ -16,14 +16,14 @@ import           Text.XML.HXT.Arrow hiding (when)
 resUsers :: Environment -> ResourceDef
 resUsers env
     = ResourceDef {
-                  resUsesNativeThread = False
-                 , resIsGreedy        = True
-                 , resGet             = Just $ handleGet env
-                 , resHead            = Nothing
-                 , resPost            = Nothing
-                 , resPut             = Just $ handlePut env
-                 , resDelete          = Just $ handleDelete env
-                 }
+       resUsesNativeThread = False
+      , resIsGreedy        = True
+      , resGet             = Just $ handleGet env
+      , resHead            = Nothing
+      , resPost            = Nothing
+      , resPut             = Just $ handlePut env
+      , resDelete          = Just $ handleDelete env
+      }
 
 
 {-
@@ -44,13 +44,13 @@ handleGet :: Environment -> Resource ()
 handleGet env
     = do userID <- getUserID env
         when (isNothing userID)
-                 $ abort Forbidden [] Nothing
+                  $ abort Forbidden [] Nothing
 
         path <- getPathInfo
         case path of
-                  []     -> returnUserList
-                  [name] -> returnUser name
-                  _      -> foundNoEntity Nothing
+          []     -> returnUserList
+          [name] -> returnUser name
+          _      -> foundNoEntity Nothing
     where
     returnUserList :: Resource ()
     returnUserList
@@ -92,17 +92,17 @@ handlePut env
 
         path <- getPathInfo
         case path of
-                  [name] -> do mimeType <- getContentType
-                               case mimeType of
-                                             Nothing
-                                                 -> abort BadRequest [] (Just "Missing Content-Type")
-                                             Just (MIMEType "text" "plain" _)
-                                                 -> do pass <- input defaultLimit
-                                                       addUser (envAuthDB env) name pass
-                                             Just t
-                                                 -> abort UnsupportedMediaType [] (Just $ "Unsupported media type: " ++ show t)
-                               setStatus Created
-                  _      -> abort BadRequest [] (Just "Invalid URI")
+          [name] -> do mimeType <- getContentType
+                       case mimeType of
+                         Nothing
+                             -> abort BadRequest [] (Just "Missing Content-Type")
+                         Just (MIMEType "text" "plain" _)
+                             -> do pass <- input defaultLimit
+                                   addUser (envAuthDB env) name pass
+                         Just t
+                             -> abort UnsupportedMediaType [] (Just $ "Unsupported media type: " ++ show t)
+                        setStatus Created
+          _      -> abort BadRequest [] (Just "Invalid URI")
 
 
 handleDelete :: Environment -> Resource ()
@@ -113,6 +113,6 @@ handleDelete env
 
         path <- getPathInfo
         case path of
-                  [name] -> delUser (envAuthDB env) name
-                  _      -> abort BadRequest [] (Just "Invalid URI")
+          [name] -> delUser (envAuthDB env) name
+          _      -> abort BadRequest [] (Just "Invalid URI")
         setStatus NoContent
index e89e3ab09ec04067a22525c69f0e326c52ecd9dc..9e808ea2cf5e75dd45e02db16a101705a39a0c7b 100644 (file)
@@ -93,6 +93,10 @@ option {
     margin: 5px 0px;
 }
 
+.body * + h2 {
+    margin-top: 20px;
+}
+
 .body ul, .body ol {
     list-style-position: inside;
     margin: 0 0 0.8em 0;
@@ -171,6 +175,9 @@ option {
 table.pageEditor {
     width: 100%;
 }
+table.pageEditor td {
+    text-align: center;
+}
 .pageEditor th {
     width: 6em;
 }
@@ -280,6 +287,7 @@ th, td {
 th {
     background-color: #aaaaaa;
     font-weight: bold;
+    text-align: center;
 }
 td {
     background-color: #cccccc;
index 06b84e8358e692f9560dedadab1e0f20b49c1f08..5f2126aaf4d2dfb685bdc57016daeaff93b34d08 100644 (file)
@@ -93,6 +93,10 @@ option {
     margin: 5px 0px;
 }
 
+.body * + h2 {
+    margin-top: 20px;
+}
+
 .body ul, .body ol {
     list-style-position: inside;
     margin: 0 0 0.8em 0;
@@ -175,6 +179,9 @@ table.configPanel {
 table.pageEditor {
     width: 100%;
 }
+table.pageEditor td {
+    text-align: center;
+}
 .pageEditor th {
     width: 6em;
 }
@@ -276,6 +283,7 @@ th, td {
 th {
     background-color: #eeeeee;
     font-weight: bold;
+    text-align: center;
 }
 td {
     background-color: #fafafa;
index 1fc9cee3461e560a11349f7a54a1c2e96433a2e5..e3f1623716753621f0ec2a8394ca74f62b460a4f 100644 (file)
@@ -7,6 +7,7 @@ SOURCES = \
        base.js \
        base64.js \
        editPage.js \
+       hashedParam.js \
        hexDump.js \
        localFile.js \
        login.js \
diff --git a/js/hashedParam.js b/js/hashedParam.js
new file mode 100644 (file)
index 0000000..8942626
--- /dev/null
@@ -0,0 +1,55 @@
+$(document).ready(function () {
+
+    /* Example of hashed params:
+     *
+     * /Foo/Bar.html#Redirect:Baz
+     * /Foo/Bar.html#EditPage
+     * /Foo/Bar.html#Redirect:Baz|EditPage
+     */
+
+    var cached_rawHash;
+    var cached_map;
+
+    Rakka.getRawHash = function () {
+        // Don't use window.location.hash as it isn't portable.
+        var r = window.location.hash;
+        var i = r.indexOf("#");
+        return (i >= 0
+                ? r.substr(i + 1)
+                : "");
+    };
+
+    Rakka.getHashedParamMap = function () {
+        var raw = Rakka.getRawHash();
+
+        if (cached_rawHash != raw) {
+            var src = decodeURIComponent(raw);
+
+            // Split the source by '|' letters.
+            cached_map = {};
+            $.each(src.split("|"), function () {
+                // tuple ::= key ':' value
+                //         | key           (value is empty)
+                var i = this.indexOf(":");
+                if (i >= 0) {
+                    cached_map[this.substr(0, i)] = this.substr(i + 1);
+                }
+                else {
+                    cached_map[this.substr(0, i)] = "";
+                }
+            });
+
+            cached_rawHash = raw;
+        }
+
+        return cached_map;
+    };
+
+    Rakka.getHashedParam = function (key) {
+        return Rakka.getHashedParamMap()[key];
+    };
+
+    Rakka.setHashedParamMap = function (map) {
+        //////////
+    };
+});
\ No newline at end of file
index 1a0c99b0bf4aceac2dabd0e286bceb81166d4c0a..5ceff2680f4823bb6a0e59893f6a756398a62430 100644 (file)
@@ -1,17 +1,8 @@
 $(document).ready(function () {
-    var fragment;
-    
-    if ($.browser.mozilla) {
-        fragment = window.location.hash; // 何故か勝手に URI デコードされる
-    }
-    else {
-        fragment = decodeURIComponent(window.location.hash);
-    }
 
-    var m = fragment.match(/^#Redirect:(.*)$/);
-    if (m) {
-        var from = m[1];
+    var from = Rakka.getHashedParam("Redirect");
 
+    if (from != null) {
         var editButton
             = $.INPUT({className: "editButton",
                        type:      "button",
@@ -26,4 +17,5 @@ $(document).ready(function () {
 
         $("div.title").after(box);
     }
+
 });
\ No newline at end of file
index fee6d367ed094f6f079dbbaf63d6c56441eef005..82abaeeb9dbfc587fbc5739121fc70fb6afa252b 100644 (file)
@@ -13,7 +13,7 @@
         var lines = src.split(/\n/);
 
         $.each(lines, function () {
-                  var m = this.match(/^(\S+)\s+(\S+)$/);
+           var m = this.match(/^(\S+)\s+(\S+)$/);
 
                    map[ m[1] ] = m[2];
                });
         parseUri.options.strictMode = true;
         var uri = parseUri(str);
 
-        return (uri.protocol != "" &&
+        return (uri.protocol  != "" &&
                 uri.authority != "" &&
-                uri.path != "" &&
+                uri.path      != "" &&
                 uri.path.match(/\/$/) &&
-                uri.query == "" &&
-                uri.anchor == "");
+                uri.query     == "" &&
+                uri.anchor    == "");
     };
 
+     // FIXME: Don't let user to manipulate directly this structure.
+     // FIXME: Values may include spaces.
     var isValidMap = function (src) {
-       return src.match(/^\S+\s+\S+(?:\n\S+\s+\S+)*\n?$/) != null;
+        return src.match(/^(?:\S+\s+\S+(?:\n\S+\s+\S+)*\n?)?$/) != null;
     };
 
     Rakka.getUserList = function () {
-       var users = [];
-
-       $.ajax({
-                  type: "GET",
-                  url: Rakka.baseURI + "users",
-                  async: false,
-                  beforeSend: function (req) {
-                      Rakka.setAuthorization(req);
-                  },
-                  success: function (xml) {
-                      $(xml).find("user").each(function () {
-                          users.push(this.getAttribute("id"));
-                      });
-                  },
-                  error: function (req) {
-                      throw new Error(req.status + " " + req.statusText);
-                  }
-       });
-
-       return users;
+        var users = [];
+
+        $.ajax({
+           type: "GET",
+           url: Rakka.baseURI + "users",
+           async: false,
+           beforeSend: function (req) {
+               Rakka.setAuthorization(req);
+           },
+           success: function (xml) {
+               $(xml).find("user").each(function () {
+                   users.push(this.getAttribute("id"));
+               });
+           },
+           error: function (req) {
+               throw new Error(req.status + " " + req.statusText);
+           }
+        });
+
+        return users;
     };
 
     Rakka.getSystemConfig = function () {
     };
 
     var appendConfigPanel = function ($area) {
-       var conf  = Rakka.getSystemConfig();
-       $area.append($.H1({}, "Configuration"));
-
-         var fldSiteName
-             = $.INPUT({type: "text", value: conf.siteName});
-
-         var fldBaseURI
-             = $.INPUT({type: "text", value: conf.baseURI});
-
-         var fldDefaultPage
-             = $.INPUT({type: "text", value: conf.defaultPage});
-
-         var fldStyleSheet
-             = $.INPUT({type: "text", value: conf.styleSheet});
-
-         var fldLanguages
-             = $.TEXTAREA({value: encoder_of.languages(conf.languages)});
-
-         var chkGlobalLock
-             = $.INPUT({type: "checkbox", checked: conf.globalLock});
-
-         var btnSave
-             = $.INPUT({type: "button", value: "Save"});
-
-        $(btnSave).click(function () {
-                             var NS  = "http://cielonegro.org/schema/Rakka/Config/1.0";
-                             var doc = document.implementation.createDocument(NS, "systemConfig", null);
-                             var sc  = doc.documentElement;
-
-                             var mkValue = function (path, value) {
-                                 var elem = doc.createElementNS(NS, "value");
-                                 elem.setAttribute("path", path);
-                                 elem.appendChild(doc.createTextNode(value));
-                                 return elem;
-                             };
-
-                             sc.appendChild(mkValue("siteName"   , fldSiteName.value));
-                             sc.appendChild(mkValue("baseURI"    , fldBaseURI.value));
-                             sc.appendChild(mkValue("defaultPage", fldDefaultPage.value));
-                             sc.appendChild(mkValue("styleSheet" , fldStyleSheet.value));
-                             sc.appendChild(mkValue("languages"  , fldLanguages.value));
-                             sc.appendChild(mkValue("globalLock" , encoder_of["globalLock"](chkGlobalLock.checked)));
-
-                             Rakka.displayWaitingMessage("Submitting... please wait.");
-
-                             var url = Rakka.baseURI + "systemConfig";
-                             $.ajax({ type       : "PUT",
-                                      url        : url,
-                                      contentType: "text/xml",
-                                      data       : doc,
-                                      processData: false,
-                                      beforeSend : function (req) {
-                                          Rakka.setAuthorization(req);
-                                      },
-                                      success    : function () {
-                                          cachedConf = null;
-                                          Rakka.hideWaitingMessage();
-                                          Rakka.restoreScreen();
-                                      },
-                                      error      : function (req) {
-                                          Rakka.hideWaitingMessage();
-
-                                          var $area = Rakka.switchScreen();
-                                          $area.text("Error: " + req.status + " " + req.statusText);
-                                      }
-                                    });
-                         });
-
-         var btnCancel
-             = $.INPUT({type: "button", value: "Cancel"});
-
-        $(btnCancel).click(function () {
-            if (isDirty) {
-                if (window.confirm("Do you really want to discard changes?")) {
-                    Rakka.restoreScreen();
-                 }
-             }
-            else {
-                 Rakka.restoreScreen();
-             }
-        });
-
-         var configPanel
-             = $.TABLE({className: "pageEditor"},
-                       $.TBODY({},
-                               $.TR({},
-                                    $.TH({}, "Site name"),
-                                    $.TD({}, fldSiteName)
-                                   ),
-                               $.TR({},
-                                    $.TH({}, "Base URI"),
-                                    $.TD({}, fldBaseURI)
-                                   ),
-                               $.TR({},
-                                    $.TH({}, "Default page"),
-                                    $.TD({}, fldDefaultPage)
-                                   ),
-                               $.TR({},
-                                    $.TH({}, "Style sheet"),
-                                    $.TD({}, fldStyleSheet)
-                                   ),
-                               $.TR({},
-                                    $.TH({}, "Languages"),
-                                    $.TD({}, fldLanguages)
-                                   ),
-                               $.TR({},
-                                    $.TH({}, "Global lock"),
-                                    $.TD({},
-                                         $.LABEL({},
-                                                 chkGlobalLock,
-                                                 "Disallow guest users to edit pages."))
-                                   ),
-                               $.TR({},
-                                    $.TH({}),
-                                    $.TD({}, btnSave, btnCancel)
-                                   )
-                              )
-                      );
-
-         var validate = function () {
-             var isValid = (function () {
-                                if (!isValidBaseURI(fldBaseURI.value)) {
-                                    return false;
-                                }
-
-                                if (fldDefaultPage.value.match(Rakka.rePageName) == null) {
-                                    return false;
-                                }
+        var conf  = Rakka.getSystemConfig();
+        $area.append($.H1({}, "Configuration"));
+
+        var fldSiteName
+            = $.INPUT({type: "text", value: conf.siteName});
+
+        var fldBaseURI
+            = $.INPUT({type: "text", value: conf.baseURI});
+
+        var fldDefaultPage
+            = $.INPUT({type: "text", value: conf.defaultPage});
+
+        var fldStyleSheet
+            = $.INPUT({type: "text", value: conf.styleSheet});
+
+        var fldLanguages
+            = $.TEXTAREA({value: encoder_of.languages(conf.languages)});
+
+        var chkGlobalLock
+            = $.INPUT({type: "checkbox", checked: conf.globalLock});
+
+        var btnSave
+            = $.INPUT({type: "button", value: "Save changes", disabled: "disabled"});
+
+        $(btnSave).click(function () {
+            var NS  = "http://cielonegro.org/schema/Rakka/Config/1.0";
+            var doc = document.implementation.createDocument(NS, "systemConfig", null);
+            var sc  = doc.documentElement;
+
+            var mkValue = function (path, value) {
+                var elem = doc.createElementNS(NS, "value");
+                elem.setAttribute("path", path);
+                elem.appendChild(doc.createTextNode(value));
+                return elem;
+            };
+
+            sc.appendChild(mkValue("siteName"   , fldSiteName.value));
+            sc.appendChild(mkValue("baseURI"    , fldBaseURI.value));
+            sc.appendChild(mkValue("defaultPage", fldDefaultPage.value));
+            sc.appendChild(mkValue("styleSheet" , fldStyleSheet.value));
+            sc.appendChild(mkValue("languages"  , fldLanguages.value));
+            sc.appendChild(mkValue("globalLock" , encoder_of["globalLock"](chkGlobalLock.checked)));
+
+            Rakka.displayWaitingMessage("Submitting... please wait.");
+
+            var url = Rakka.baseURI + "systemConfig";
+            $.ajax({ type       : "PUT",
+                     url        : url,
+                     contentType: "text/xml",
+                     data       : doc,
+                     processData: false,
+                     beforeSend : function (req) {
+                         Rakka.setAuthorization(req);
+                     },
+                     success    : function () {
+                         cachedConf = null;
+                         Rakka.hideWaitingMessage();
+                         Rakka.restoreScreen();
+                     },
+                     error      : function (req) {
+                         Rakka.hideWaitingMessage();
+
+                         var $area = Rakka.switchScreen();
+                         $area.text("Error: " + req.status + " " + req.statusText);
+                     }
+            });
+        });
 
-                                if (fldStyleSheet.value.match(Rakka.rePageName) == null) {
-                                    return false;
-                                }
+        var btnRevert
+            = $.INPUT({type: "button", value: "Revert changes", disabled: "disabled"});
 
-                               if (!isValidMap(fldLanguages.value)) {
-                                   return false;
-                               }
+        $(btnRevert).click(function () {
+            if (window.confirm("Do you really want to discard changes?")) {
+                // FIXME: implement this
+            }
+        });
 
-                                return true;
-                            })();
+        var configPanel
+            = $.TABLE({className: "pageEditor"},
+                      $.TBODY({},
+                              $.TR({},
+                                   $.TH({}, "Site name"),
+                                   $.TD({}, fldSiteName)),
+                              $.TR({},
+                                   $.TH({}, "Base URI"),
+                                   $.TD({}, fldBaseURI)),
+                              $.TR({},
+                                   $.TH({}, "Default page"),
+                                   $.TD({}, fldDefaultPage)),
+                              $.TR({},
+                                   $.TH({}, "Style sheet"),
+                                   $.TD({}, fldStyleSheet)),
+                              $.TR({},
+                                   $.TH({}, "Languages"),
+                                   $.TD({}, fldLanguages)),
+                              $.TR({},
+                                   $.TH({}, "Global lock"),
+                                   $.TD({},
+                                        $.LABEL({},
+                                                chkGlobalLock,
+                                                "Disallow guest users to edit pages."))),
+                              $.TR({},
+                                   $.TH({}),
+                                   $.TD({}, btnSave, btnRevert))));
+
+        var validate = function () {
+            var isValid = (function () {
+                               if (!isValidBaseURI(fldBaseURI.value)) {
+                                   return false;
+                               }
+
+                               if (fldDefaultPage.value.match(Rakka.rePageName) == null) {
+                                   return false;
+                               }
+
+                               if (fldStyleSheet.value.match(Rakka.rePageName) == null) {
+                                   return false;
+                               }
+
+                               if (!isValidMap(fldLanguages.value)) {
+                                   return false;
+                               }
+
+                               return true;
+                           })();
 
              $(btnSave).attr({disabled: (isValid ? "" : "disabled")});
          };
 
          var isDirty = null;
          var makeDirty = function () {
-             isDirty = true;
+             if (!isDirty) {
+                 $(btnRevert).attr({disabled: ""});
+                 isDirty = true;
+             }
+             validate();
          };
 
          $(fldSiteName)
              .add(fldDefaultPage)
              .add(fldStyleSheet)
              .add(fldLanguages)
-             .change(validate)
-             .keyup(validate)
+             .keyup(makeDirty)
              .change(makeDirty);
 
          $area.append(configPanel);
 
      var appendUsersPanel = function ($area) {
          $area.append($.H2({}, "Users"));
-            $area.append($.H3({}, "Existing Users"));
+         $area.append($.H3({}, "Existing Users"));
 
-            var tbody = $.TBODY();
+         var tbody = $.TBODY();
 
-            var usersPanel
+         var usersPanel
              = $.TABLE({className: "pageEditor"},
-                              $.THEAD({},
-                                          $.TR({},
-                                                   $.TH({}, "User ID"),
-                                                   $.TH({}, "Change Password"),
-                                                   $.TH({}, "Delete User")
-                                                  )
-                                         ),
-                                     tbody
-                             );
-
-            var updateUserList = function () {
+                       $.THEAD({},
+                               $.TR({},
+                                    $.TH({}, "User ID"),
+                                    $.TH({}, "Change Password"),
+                                    $.TH({}, "Delete User"))),
+                       tbody);
+
+         var updateUserList = function () {
              var users = Rakka.getUserList();
 
-                $(tbody).empty();
+             $(tbody).empty();
 
-                for (var i = 0; i < users.length; i++) {
-                        var pass1  = $.INPUT({type: "password"});
-                        var pass2  = $.INPUT({type: "password"});
-                        var change = $.INPUT({type: "button", value: "Change"});
+             for (var i = 0; i < users.length; i++) {
+                 var pass1  = $.INPUT({type: "password"});
+                 var pass2  = $.INPUT({type: "password"});
+                 var change = $.INPUT({type: "button", value: "Change"});
 
-                        var chpass = $.TABLE({className: "pageEditor"},
+                 var chpass = $.TABLE({className: "pageEditor"},
                                       $.TR({},
-                                                          $.TD({}, pass1),
-                                                              $.TD({rowSpan: 2}, change)),
-                                                     $.TR({},
-                                                              $.TD({}, pass2)));
+                                           $.TD({}, pass1),
+                                           $.TD({rowSpan: 2}, change)),
+                                      $.TR({},
+                                           $.TD({}, pass2)));
 
-                        var delUser = $.INPUT({type: "button", value: "Delete"});
+                 var delUser = $.INPUT({type: "button", value: "Delete"});
 
                  var validatePassword = function () {
                      var isValid = (function () {
-                                        if (pass1.value == "") {
-                                            return false;
-                                        }
+                                       if (pass1.value == "") {
+                                           return false;
+                                       }
 
-                                        if (pass1.value != pass2.value) {
-                                            return false;
-                                        }
+                                       if (pass1.value != pass2.value) {
+                                           return false;
+                                       }
 
-                                        return true;
+                                       return true;
                                     })();
                      $(change).attr({disabled: (isValid ? "" : "disabled")});
                  };
                      .change(validatePassword)
                      .keyup(validatePassword);
 
-                        $.each(users, function () {
-                                var id = users[i];
-                                var tr = $.TR({},
-                                                  $.TD({}, id),
-                                                      $.TD({}, chpass),
-                                                      $.TD({}, delUser)
-                                                     );
-                                tbody.appendChild(tr);
-                            });
-                }
-            };
-            updateUserList();
-
-            $area.append(usersPanel);
-
-            $area.append($.H3({}, "Add new user"));
-
-            var userID  = $.INPUT({type: "text"});
-            var pass1   = $.INPUT({type: "password"});
-            var pass2   = $.INPUT({type: "password"});
-            var addUser = $.INPUT({type: "button", value: "Add"});
-            var addUserPanel = $.TABLE({className: "pageEditor"},
+                 $.each(users, function () {
+                     var id = users[i];
+                     var tr = $.TR({},
+                                   $.TD({}, id),
+                                   $.TD({}, chpass),
+                                   $.TD({}, delUser)
+                                  );
+                     tbody.appendChild(tr);
+                 });
+             }
+         };
+         updateUserList();
+
+         $area.append(usersPanel);
+
+         $area.append($.H3({}, "Add new user"));
+
+         var userID  = $.INPUT({type: "text"});
+         var pass1   = $.INPUT({type: "password"});
+         var pass2   = $.INPUT({type: "password"});
+         var addUser = $.INPUT({type: "button", value: "Add"});
+         var addUserPanel = $.TABLE({className: "pageEditor"},
                                     $.TR({},
-                                                            $.TH({}, "User ID"),
-                                                            $.TD({}, userID)),
-                                                   $.TR({},
-                                                            $.TH({}, "Password"),
-                                                            $.TD({}, pass1)),
-                                                   $.TR({},
-                                                $.TH({}, "Password (retype)"),
-                                                            $.TD({}, pass2)),
-                                                   $.TR({},
-                                                            $.TH({}),
-                                                            $.TD({}, addUser)));
-
-            $area.append(addUserPanel);
+                                         $.TH({}, "User ID"),
+                                         $.TD({}, userID)),
+                                    $.TR({},
+                                         $.TH({}, "Password"),
+                                         $.TD({}, pass1)),
+                                    $.TR({},
+                                         $.TH({}, "Password (retype)"),
+                                         $.TD({}, pass2)),
+                                    $.TR({},
+                                         $.TH({}),
+                                         $.TD({}, addUser)));
+
+         $area.append(addUserPanel);
      };
 
      Rakka.showConfigPanel = function () {
          var $area = Rakka.switchScreen();
 
-            appendConfigPanel($area);
-            appendUsersPanel($area);
+         appendConfigPanel($area);
+         appendUsersPanel($area);
      };
 
      $(document).ready(function () {
-                          $("input.configButton")
-                              .click(function () {
-                                         Rakka.showConfigPanel();
-                                     });
-                      });
+         $("input.configButton")
+             .click(function () {
+                        Rakka.showConfigPanel();
+                    });
+     });
 })();
\ No newline at end of file