]> gitweb @ CieloNegro.org - Rakka.git/blob - js/systemConfig.js
misc changes
[Rakka.git] / js / systemConfig.js
1 (function () {
2
3     var identityDecoder = function (src) {
4         return src;
5     };
6
7     var identityEncoder = function (src) {
8         return src;
9     };
10
11     var mapDecoder = function (src) {
12         var map   = {};
13         var lines = src.split(/\n/);
14
15         $.each(lines, function () {
16            var m = this.match(/^(\S+)\s+(\S+)$/);
17
18                    map[ m[1] ] = m[2];
19                });
20
21         return map;
22     };
23
24     var mapEncoder = function (map) {
25         var lines = [];
26
27         $.each(map, function (key) {
28                    lines.push(key + " " + this);
29                });
30
31         return lines.join("\n");
32     };
33
34     var boolDecoder = function (src) {
35         return src == "*";
36     };
37
38     var boolEncoder = function (bool) {
39         return bool ? "*" : "";
40     };
41
42     var decoder_of = {
43         siteName   : identityDecoder,
44         baseURI    : identityDecoder,
45         defaultPage: identityDecoder,
46         styleSheet : identityDecoder,
47         languages  : mapDecoder,
48         globalLock : boolDecoder
49     };
50
51     var encoder_of = {
52         siteName   : identityEncoder,
53         baseURI    : identityEncoder,
54         defaultPage: identityEncoder,
55         styleSheet : identityEncoder,
56         languages  : mapEncoder,
57         globalLock : boolEncoder
58     };
59
60     var cachedConf = null;
61
62     var isValidBaseURI = function (str) {
63         parseUri.options.strictMode = true;
64         var uri = parseUri(str);
65
66         return (uri.protocol  != "" &&
67                 uri.authority != "" &&
68                 uri.path      != "" &&
69                 uri.path.match(/\/$/) &&
70                 uri.query     == "" &&
71                 uri.anchor    == "");
72     };
73
74      // FIXME: Don't let user to manipulate directly this structure.
75      // FIXME: Values may include spaces.
76     var isValidMap = function (src) {
77         return src.match(/^(?:\S+\s+\S+(?:\n\S+\s+\S+)*\n?)?$/) != null;
78     };
79
80     Rakka.getUserList = function () {
81         var users = [];
82
83         $.ajax({
84            type: "GET",
85            url: Rakka.baseURI + "users",
86            async: false,
87            beforeSend: function (req) {
88                Rakka.setAuthorization(req);
89            },
90            success: function (xml) {
91                $(xml).find("user").each(function () {
92                    users.push(this.getAttribute("id"));
93                });
94            },
95            error: function (req) {
96                throw new Error(req.status + " " + req.statusText);
97            }
98         });
99
100         return users;
101     };
102
103     Rakka.getSystemConfig = function () {
104         if (cachedConf != null) {
105             return cachedConf;
106         }
107
108         var conf = {};
109         cachedConf = conf;
110
111         $.ajax({
112             type   : "GET",
113             url    : Rakka.baseURI + "systemConfig",
114             async  : false,
115             success: function (xml) {
116                 $(xml).find("value").each(function () {
117                     var path    = this.getAttribute("path");
118                     var decoder = decoder_of[path];
119
120                     if (decoder == null) {
121                         throw new Error("unknown config path: " + path);
122                     }
123                     else {
124                         conf[path] = decoder($(this).text());
125                     }
126                 });
127             },
128             error  : function (req) {
129                 throw new Error(req.status + " " + req.statusText);
130             }
131         });
132
133         return conf;
134     };
135
136     var appendConfigPanel = function ($area) {
137         var conf  = Rakka.getSystemConfig();
138         $area.append($.H1({}, "Configuration"));
139
140         var fldSiteName
141             = $.INPUT({type: "text", value: conf.siteName});
142
143         var fldBaseURI
144             = $.INPUT({type: "text", value: conf.baseURI});
145
146         var fldDefaultPage
147             = $.INPUT({type: "text", value: conf.defaultPage});
148
149         var fldStyleSheet
150             = $.INPUT({type: "text", value: conf.styleSheet});
151
152         var fldLanguages
153             = $.TEXTAREA({value: encoder_of.languages(conf.languages)});
154
155         var chkGlobalLock
156             = $.INPUT({type: "checkbox", checked: conf.globalLock});
157
158         var btnSave
159             = $.INPUT({type: "button", value: "Save changes", disabled: "disabled"});
160
161         $(btnSave).click(function () {
162             var NS  = "http://cielonegro.org/schema/Rakka/Config/1.0";
163             var doc = document.implementation.createDocument(NS, "systemConfig", null);
164             var sc  = doc.documentElement;
165
166             var mkValue = function (path, value) {
167                 var elem = doc.createElementNS(NS, "value");
168                 elem.setAttribute("path", path);
169                 elem.appendChild(doc.createTextNode(value));
170                 return elem;
171             };
172
173             sc.appendChild(mkValue("siteName"   , fldSiteName.value));
174             sc.appendChild(mkValue("baseURI"    , fldBaseURI.value));
175             sc.appendChild(mkValue("defaultPage", fldDefaultPage.value));
176             sc.appendChild(mkValue("styleSheet" , fldStyleSheet.value));
177             sc.appendChild(mkValue("languages"  , fldLanguages.value));
178             sc.appendChild(mkValue("globalLock" , encoder_of["globalLock"](chkGlobalLock.checked)));
179
180             Rakka.displayWaitingMessage("Submitting... please wait.");
181
182             var url = Rakka.baseURI + "systemConfig";
183             $.ajax({ type       : "PUT",
184                      url        : url,
185                      contentType: "text/xml",
186                      data       : doc,
187                      processData: false,
188                      beforeSend : function (req) {
189                          Rakka.setAuthorization(req);
190                      },
191                      success    : function () {
192                          cachedConf = null;
193                          Rakka.hideWaitingMessage();
194                          Rakka.restoreScreen();
195                      },
196                      error      : function (req) {
197                          Rakka.hideWaitingMessage();
198
199                          var $area = Rakka.switchScreen();
200                          $area.text("Error: " + req.status + " " + req.statusText);
201                      }
202             });
203         });
204
205         var btnRevert
206             = $.INPUT({type: "button", value: "Revert changes", disabled: "disabled"});
207
208         $(btnRevert).click(function () {
209             if (window.confirm("Do you really want to discard changes?")) {
210                 // FIXME: implement this
211             }
212         });
213
214         var configPanel
215             = $.TABLE({className: "pageEditor"},
216                       $.TBODY({},
217                               $.TR({},
218                                    $.TH({}, "Site name"),
219                                    $.TD({}, fldSiteName)),
220                               $.TR({},
221                                    $.TH({}, "Base URI"),
222                                    $.TD({}, fldBaseURI)),
223                               $.TR({},
224                                    $.TH({}, "Default page"),
225                                    $.TD({}, fldDefaultPage)),
226                               $.TR({},
227                                    $.TH({}, "Style sheet"),
228                                    $.TD({}, fldStyleSheet)),
229                               $.TR({},
230                                    $.TH({}, "Languages"),
231                                    $.TD({}, fldLanguages)),
232                               $.TR({},
233                                    $.TH({}, "Global lock"),
234                                    $.TD({},
235                                         $.LABEL({},
236                                                 chkGlobalLock,
237                                                 "Disallow guest users to edit pages."))),
238                               $.TR({},
239                                    $.TH({}),
240                                    $.TD({}, btnSave, btnRevert))));
241
242         var validate = function () {
243             var isValid = (function () {
244                                if (!isValidBaseURI(fldBaseURI.value)) {
245                                    return false;
246                                }
247
248                                if (fldDefaultPage.value.match(Rakka.rePageName) == null) {
249                                    return false;
250                                }
251
252                                if (fldStyleSheet.value.match(Rakka.rePageName) == null) {
253                                    return false;
254                                }
255
256                                if (!isValidMap(fldLanguages.value)) {
257                                    return false;
258                                }
259
260                                return true;
261                            })();
262
263              $(btnSave).attr({disabled: (isValid ? "" : "disabled")});
264          };
265
266          var isDirty = null;
267          var makeDirty = function () {
268              if (!isDirty) {
269                  $(btnRevert).attr({disabled: ""});
270                  isDirty = true;
271              }
272              validate();
273          };
274
275          $(fldSiteName)
276              .add(fldBaseURI)
277              .add(fldDefaultPage)
278              .add(fldStyleSheet)
279              .add(fldLanguages)
280              .keyup(makeDirty)
281              .change(makeDirty);
282
283          $area.append(configPanel);
284      };
285
286      var appendUsersPanel = function ($area) {
287          $area.append($.H2({}, "Users"));
288          $area.append($.H3({}, "Existing Users"));
289
290          var tbody = $.TBODY();
291
292          var usersPanel
293              = $.TABLE({className: "pageEditor"},
294                        $.THEAD({},
295                                $.TR({},
296                                     $.TH({}, "User ID"),
297                                     $.TH({}, "Change Password"),
298                                     $.TH({}, "Delete User"))),
299                        tbody);
300
301          var updateUserList = function () {
302              var users = Rakka.getUserList();
303
304              $(tbody).empty();
305
306              for (var i = 0; i < users.length; i++) {
307                  var pass1  = $.INPUT({type: "password"});
308                  var pass2  = $.INPUT({type: "password"});
309                  var change = $.INPUT({type: "button", value: "Change"});
310
311                  var chpass = $.TABLE({className: "pageEditor"},
312                                       $.TR({},
313                                            $.TD({}, pass1),
314                                            $.TD({rowSpan: 2}, change)),
315                                       $.TR({},
316                                            $.TD({}, pass2)));
317
318                  var delUser = $.INPUT({type: "button", value: "Delete"});
319
320                  var validatePassword = function () {
321                      var isValid = (function () {
322                                        if (pass1.value == "") {
323                                            return false;
324                                        }
325
326                                        if (pass1.value != pass2.value) {
327                                            return false;
328                                        }
329
330                                        return true;
331                                     })();
332                      $(change).attr({disabled: (isValid ? "" : "disabled")});
333                  };
334                  validatePassword();
335                  $(pass1)
336                      .add(pass2)
337                      .change(validatePassword)
338                      .keyup(validatePassword);
339
340                  $.each(users, function () {
341                      var id = users[i];
342                      var tr = $.TR({},
343                                    $.TD({}, id),
344                                    $.TD({}, chpass),
345                                    $.TD({}, delUser)
346                                   );
347                      tbody.appendChild(tr);
348                  });
349              }
350          };
351          updateUserList();
352
353          $area.append(usersPanel);
354
355          $area.append($.H3({}, "Add new user"));
356
357          var userID  = $.INPUT({type: "text"});
358          var pass1   = $.INPUT({type: "password"});
359          var pass2   = $.INPUT({type: "password"});
360          var addUser = $.INPUT({type: "button", value: "Add"});
361          var addUserPanel = $.TABLE({className: "pageEditor"},
362                                     $.TR({},
363                                          $.TH({}, "User ID"),
364                                          $.TD({}, userID)),
365                                     $.TR({},
366                                          $.TH({}, "Password"),
367                                          $.TD({}, pass1)),
368                                     $.TR({},
369                                          $.TH({}, "Password (retype)"),
370                                          $.TD({}, pass2)),
371                                     $.TR({},
372                                          $.TH({}),
373                                          $.TD({}, addUser)));
374
375          $area.append(addUserPanel);
376      };
377
378      Rakka.showConfigPanel = function () {
379          var $area = Rakka.switchScreen();
380
381          appendConfigPanel($area);
382          appendUsersPanel($area);
383      };
384
385      $(document).ready(function () {
386          $("input.configButton")
387              .click(function () {
388                         Rakka.showConfigPanel();
389                     });
390      });
391 })();