(function () { var identityDecoder = function (src) { return src; }; var identityEncoder = function (src) { return src; }; var mapDecoder = function (src) { var map = {}; var lines = src.split(/\n/); $.each(lines, function () { var m = this.match(/^(\S+)\s+(\S+)$/); map[ m[1] ] = m[2]; }); return map; }; var mapEncoder = function (map) { var lines = []; $.each(map, function (key) { lines.push(key + " " + this); }); return lines.join("\n"); }; var boolDecoder = function (src) { return src == "*"; }; var boolEncoder = function (bool) { return bool ? "*" : ""; }; var decoder_of = { siteName : identityDecoder, baseURI : identityDecoder, defaultPage: identityDecoder, styleSheet : identityDecoder, languages : mapDecoder, globalLock : boolDecoder }; var encoder_of = { siteName : identityEncoder, baseURI : identityEncoder, defaultPage: identityEncoder, styleSheet : identityEncoder, languages : mapEncoder, globalLock : boolEncoder }; var cachedConf = null; var isValidBaseURI = function (str) { parseUri.options.strictMode = true; var uri = parseUri(str); return (uri.protocol != "" && uri.authority != "" && uri.path != "" && uri.path.match(/\/$/) && uri.query == "" && uri.anchor == ""); }; var isValidMap = function (src) { 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; }; Rakka.getSystemConfig = function () { if (cachedConf != null) { return cachedConf; } var conf = {}; cachedConf = conf; $.ajax({ type : "GET", url : Rakka.baseURI + "systemConfig", async : false, success: function (xml) { $(xml).find("value").each(function () { var path = this.getAttribute("path"); var decoder = decoder_of[path]; if (decoder == null) { throw new Error("unknown config path: " + path); } else { conf[path] = decoder($(this).text()); } }); }, error : function (req) { throw new Error(req.status + " " + req.statusText); } }); return conf; }; 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; } 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; }; $(fldSiteName) .add(fldBaseURI) .add(fldDefaultPage) .add(fldStyleSheet) .add(fldLanguages) .change(validate) .keyup(validate) .change(makeDirty); $area.append(configPanel); }; var appendUsersPanel = function ($area) { $area.append($.H2({}, "Users")); $area.append($.H3({}, "Existing Users")); var tbody = $.TBODY(); var usersPanel = $.TABLE({className: "pageEditor"}, $.THEAD({}, $.TR({}, $.TH({}, "User ID"), $.TH({}, "Change Password"), $.TH({}, "Delete User") ) ), tbody ); var updateUserList = function () { var users = Rakka.getUserList(); $(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"}); var chpass = $.TABLE({className: "pageEditor"}, $.TR({}, $.TD({}, pass1), $.TD({rowSpan: 2}, change)), $.TR({}, $.TD({}, pass2))); var delUser = $.INPUT({type: "button", value: "Delete"}); var validatePassword = function () { var isValid = (function () { if (pass1.value == "") { return false; } if (pass1.value != pass2.value) { return false; } return true; })(); $(change).attr({disabled: (isValid ? "" : "disabled")}); }; validatePassword(); $(pass1) .add(pass2) .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"}, $.TR({}, $.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); }; $(document).ready(function () { $("input.configButton") .click(function () { Rakka.showConfigPanel(); }); }); })();