Merge branch 'master' of git+ssh://gitosis@nomeata.de/L-seed
[L-seed.git] / web / js / communication.js
1 if (typeof console == "undefined") {
2     console = {
3         dir: function() { }
4                 , monitor: function() { }
5                 , debug: function() { }
6                 , profile: function() { }
7                 , log: function() { }
8                 , error: function() { }
9                 , warn: function() { }
10                 , info: function() { }
11                 , profileEnd: function() { }
12                 , unmonitor: function() { }
13     };
14 }
15 if (typeof Lseed == "undefined") {
16     Lseed = {};
17 }
18
19 Lseed.MessageCommands = {
20         RPC: 'RPC'
21         ,ContentRequest: 'ContentRequest'
22 };
23
24 Lseed.Communication = function() {
25         
26         this.Username = '';
27
28         // ----- Framework -----
29         
30         this.RequestCallbacks = {};
31         
32         this.sendMessage = function (cmd, opts) {
33                 var params = {};
34                 Ext.apply(params, opts, { cmd: cmd });
35                 Ext.Ajax.request({
36                         url: 'php/Communication.php',
37                         success: this.handleResponse.createDelegate(this)
38                         ,failure: function(response, opts) {
39                                 Ext.MessageBox.alert("Fehler", "Es konnte keine Verbindung zum Server hergestellt werden.")
40                                                           .setIcon(Ext.MessageBox.ERROR);
41                         }
42                         ,params: params
43                 });
44         };
45
46         this.handleResponse = function (response, opts) {
47                 Ext.MessageBox.hide();
48                 console.log("'"+response.responseText+"'");
49                 try {
50                         if (!response.responseText) {
51                                 console.error("empty answer");
52                                 return;
53                         }
54                         var obj = Ext.decode(response.responseText);
55                         var cmd = obj.cmd;
56
57                         switch (cmd) {
58                                 case 'RPC':
59                                         obj.func.CreateDelegate(this)(obj.data);
60                                         break;
61                                 case 'RPC-Response':
62                                         this.RequestCallbacks[obj.calledFunc](obj.data);
63                                         break;
64                                 case 'Message':
65                                         this.showMessage(obj.msg, obj.type);
66                                         break;
67                                 case 'Content':
68                                         this.stopWaitingForPage();
69                                         
70                                         this.showContent(obj.content, obj.contentname);
71                                         break;
72                         }
73                 } catch (e) {
74                         console.error(e);
75                 }
76         };
77         
78         this.showMessage = function (msg, type) {
79                 var title = "Unbekannte Nachricht";
80                 if (type == 'error') {
81                         title = "Fehler";
82                 } else if (type == "info") {
83                         title = "Information";
84                 }
85                 var msgbox = Ext.MessageBox.alert(title, msg);
86                 if (type == 'error') {
87                         msgbox.setIcon(Ext.MessageBox.ERROR);
88                 } else if (type == "info") {
89                         msgbox.setIcon(Ext.MessageBox.INFO);
90                 }
91         };
92         
93         this.AddCallback = function (hook, func) {
94                 this.RequestCallbacks[hook] = func;
95         };
96
97
98         // ----- Application -----
99         
100         this.showContent = function (content, contentname) {
101                 switch(contentname) {
102                         case "nav":
103                         case "adminnav":
104                                 this.loadNavigation(content);
105                                 break;
106                         default:
107                                 this.loadTab(content, contentname);
108                                 if (contentname == "editplant") {
109                                         editor.EditCallback();
110                                 }
111                                 break;
112                 }
113         };
114         
115         // === LOGIN ===
116         
117         this.isLoggedInCallback = function (loggIn) {
118                 if (loggIn) {
119                         Ext.MessageBox.wait("Navigation wird geladen.", "Wird geladen...");
120                         
121                         this.sendMessage(Lseed.MessageCommands.ContentRequest, {content: 'nav'});
122                 } else {
123                         this.showLoginDialog();
124                 }
125         };
126         
127         this.AuthCallback = function (success) {
128                 if (success) {
129                         Ext.MessageBox.wait("Navigation wird geladen.", "Wird geladen...");
130                         
131                         this.sendMessage(Lseed.MessageCommands.ContentRequest, {content: 'nav'});
132                 } else {
133                         this.showLoginDialog();
134                         this.showMessage(
135                                 "Es trat ein Fehler beim einloggen auf. Bitte überprüfen sie ihre eingaben und versuchen sie es erneut.", 
136                                 "error");
137                 }
138         };
139
140         this.showLoginDialog = function () {
141                 var loginDialog = Ext.getCmp("loginDialog");
142                 if (!loginDialog) {
143                         loginDialog = new Ext.Window({
144                                 id: 'loginDialog'
145                                 ,title: 'Login'
146                                 ,modal: true
147                                 ,closable: false
148                                 ,tbar: ['->',{
149                                         text: 'Register'
150                                         ,icon: 'img/icons/user_add.png'
151                                         ,cls: 'x-btn-text-icon'
152                                         ,handler: function() {
153                                                 loginDialog.hide();
154                                                 this.showRegisterDialog();
155                                         }.createDelegate(this)
156                                 }]
157                                 ,items: [{
158                                         id: 'loginDialogForm'
159                                         ,xtype: 'form'
160                                         ,labelWidth: 75
161                                         ,bodyStyle:'padding:5px 5px 0'
162                                         ,width: 350
163                                         ,defaults: {
164                                                 width: 230
165                                                 ,labelStyle: 'padding-right:5px'
166                                         }
167                                         ,defaultType: 'textfield'
168                                         ,items: [{
169                                                 id: 'loginDialogFormUsername'
170                                                 ,fieldLabel: 'Benutzername'
171                                                 ,name: 'username'
172                                                 ,allowBlank:false
173                                         },{
174                                                 id: 'loginDialogFormPassword'
175                                                 ,fieldLabel: 'Password'
176                                                 ,name: 'password'
177                                                 ,inputType: 'password'
178                                                 ,allowBlank:false
179                                         }]
180                                         ,buttons: [{
181                                                 text: 'OK'
182                                                 ,handler: this.login.createDelegate(this)
183                                         }]
184                                 }]
185                         });
186                 }
187                 
188                 loginDialog.show();
189         };
190         
191         this.login = function() {
192                 var cmpUser = Ext.getCmp('loginDialogFormUsername');
193                 var cmpPw = Ext.getCmp('loginDialogFormPassword');
194                 if (cmpUser && cmpUser.isValid() && 
195                     cmpPw && cmpPw.isValid()) {
196                         var user = cmpUser.getValue();
197                         var pw = cmpPw.getValue();
198                         pw = MD5(pw);
199                         Ext.MessageBox.wait("Authentifiziere.", "Wird geladen...");
200                                 
201                         this.Username = user;
202                         
203                         this.sendMessage(Lseed.MessageCommands.RPC, { func: 'Auth', user: user, pw: pw });
204                         this.hideLoginDialog();
205                 } else {
206                         this.showMessage("Ungültige Eingabe. Bitte überprüfen.", "error");
207                 }
208         };
209         
210         this.logout = function() {
211                 Ext.MessageBox.wait("Deauthentifiziere.", "Wird geladen...");
212                 
213                 this.sendMessage(Lseed.MessageCommands.RPC, { func: 'Logout' });
214                 this.clearNavigation();
215                 this.closeAllTabs();
216                 this.showLoginDialog();
217         };
218
219         this.hideLoginDialog = function () {
220                 var cmp = Ext.getCmp('loginDialog');
221                 if (cmp) {
222                         cmp.hide();
223                 } else {
224                         console.error("Lseed.Communication.hideLoginDialog: loginDialog couldn't be found");
225                 }
226         };
227         
228         // === REGISTER ===
229
230         this.showRegisterDialog = function () {
231                 var registerDialog = Ext.getCmp("registerDialog");
232                 if (!registerDialog) {
233                         registerDialog = new Ext.Window({
234                                 id: 'registerDialog'
235                                 ,title: 'Register'
236                                 ,modal: true
237                                 ,closable: true
238                                 ,listeners: {
239                                         close: this.showLoginDialog
240                                 }
241                                 ,items: [{
242                                         id: 'registerDialogForm'
243                                         ,xtype: 'form'
244                                         ,labelWidth: 75
245                                         ,bodyStyle:'padding:5px 5px 0'
246                                         ,width: 350
247                                         ,defaults: {
248                                                 width: 230
249                                                 ,labelStyle: 'padding-right:5px'
250                                         }
251                                         ,defaultType: 'textfield'
252                                         ,items: [{
253                                                 id: 'registerDialogFormUsername'
254                                                 ,fieldLabel: 'Benutzername'
255                                                 ,name: 'username'
256                                                 ,allowBlank:false
257                                         },{
258                                                 id: 'registerDialogFormPassword'
259                                                 ,fieldLabel: 'Password'
260                                                 ,name: 'password'
261                                                 ,inputType: 'password'
262                                                 ,allowBlank:false
263                                         },{
264                                                 id: 'registerDialogFormPasswordRepeat'
265                                                 ,fieldLabel: 'Password Wiederholung'
266                                                 ,name: 'passwordRepeat'
267                                                 ,inputType: 'password'
268                                                 ,allowBlank:false
269                                         }]
270                                         ,buttons: [{
271                                                 text: 'Register'
272                                                 ,handler: this.register.createDelegate(this)
273                                         },{
274                                                 text: 'Cancel'
275                                                 ,handler: function() {
276                                                         this.hideRegisterDialog();
277                                                         this.showLoginDialog();
278                                                 }.createDelegate(this)
279                                         }]
280                                 }]
281                         });
282                 }
283                 
284                 registerDialog.show();
285         };
286
287         this.hideRegisterDialog = function () {
288                 var cmp = Ext.getCmp('registerDialog');
289                 if (cmp) {
290                         cmp.hide();
291                 } else {
292                         console.error("Lseed.Communication.hideRegisterDialog: registerDialog couldn't be found");
293                 }
294         };
295         
296         this.register = function() {
297                 var cmpUser = Ext.getCmp('registerDialogFormUsername');
298                 var cmpPw = Ext.getCmp('registerDialogFormPassword');
299                 var cmpPwRepeat = Ext.getCmp('registerDialogFormPasswordRepeat');
300                 if (cmpUser && cmpUser.isValid() && 
301                     cmpPw && cmpPw.isValid() && 
302                     cmpPwRepeat && cmpPwRepeat.isValid()) {
303                         var user = cmpUser.getValue();
304                         var pw = cmpPw.getValue();
305                         var pwRepeat = cmpPwRepeat.getValue();
306                         if (pw == pwRepeat) {
307                                 pw = MD5(pw);
308                                 Ext.MessageBox.wait("Registriere.", "Wird geladen...");
309                                 
310                                 this.Username = user;
311
312                                 this.sendMessage(Lseed.MessageCommands.RPC, { func: 'Register', user: user, pw: pw });
313                                 this.hideRegisterDialog();
314                         } else {
315                                 this.showMessage("Passwörter stimmen nicht überein. Bitte korrigieren.", "error");
316                         }
317                 } else {
318                         this.showMessage("Ungültige Eingabe. Bitte überprüfen.", "error");
319                 }
320         };
321         
322         this.RegisterCallback = function (data) {
323                 if (data.success) {
324                         Ext.MessageBox.wait("Navigation wird geladen.", "Wird geladen...");
325                         
326                         this.sendMessage(Lseed.MessageCommands.ContentRequest, {content: 'nav'});
327                 } else {
328                         this.showRegisterDialog();
329                         this.showMessage(
330                                 data.msg, 
331                                 "error");
332                 }
333         };
334         
335         // === Plant Managerment ===
336         
337         this.GetPlantList = function() {
338                 Ext.MessageBox.wait("Pflanzen werden geladen.", "Wird geladen...");
339                 
340                 this.sendMessage(Lseed.MessageCommands.RPC, { func: 'GetPlantList' });
341         };
342         
343         this.GetPlantListCallback = function(data) {
344                 var grid = Ext.getCmp("plantlistgrid");
345                 if (grid) {
346                         grid.store.loadData(data.list);
347                 } else {
348                         console.error("Lseed.Communication.GetPlantList: 'plantlistgrid' could not be found.");
349                 }
350         }
351         
352         this.loadNavigation = function(content) {
353                 var cmp = Ext.getCmp('navTree');
354                 if (cmp) {
355                         cmp.setRootNode(content);
356                 } else {
357                         console.error("Lseed.Communication.loadNavigation: 'navTree' does not exist.");
358                 }
359         };
360         
361         this.clearNavigation = function() {
362                 var cmp = Ext.getCmp('navTree');
363                 if (cmp) {
364                         cmp.setRootNode(new Ext.tree.AsyncTreeNode({
365                                 expanded: true
366                                 ,children: [{
367                                         text: 'Start'
368                                         ,leaf: true
369                                 }]
370                         }));
371                 } else {
372                         console.error("Lseed.Communication.clearNavigation: 'navTree' does not exist.");
373                 }
374         };
375         
376         this.closeAllTabs = function() {
377                 var cmp = Ext.getCmp('contentTabPanel');
378                 if (cmp) {
379                         var elem = cmp.get(0);
380                         cmp.removeAll();
381                         cmp.add(elem);
382                 } else {
383                         console.error("Lseed.Communication.clearNavigation: 'navTree' does not exist.");
384                 }
385         };
386         
387         this.loadTab = function (content, name) {
388                 var cmp = Ext.getCmp("contentTabPanel");
389                 if (cmp) {
390                         cmp.add(content);
391                         this.activateTab(name)
392                 } else {
393                         console.error("Lseed.Communication.showTab: 'contentTabPanel' does not exist.");
394                 }
395         };
396         
397         this.getTab = function (tabname) {
398                 var result = null;
399                 
400                 var cmp = Ext.getCmp("contentTabPanel");
401                 if (cmp) {
402                         result = cmp.findById("ContentPanel_"+tabname);
403                 } else {
404                         console.error("Lseed.Communication.activateTab: 'contentTabPanel' does not exist.");
405                 }
406                 
407                 return result;
408         };
409         
410         this.activateTab = function (tabname) {
411                 var done = false;
412                 
413                 var tab = this.getTab(tabname);
414                 
415                 if (tab) {
416                         var cmp = Ext.getCmp("contentTabPanel");
417                         if (cmp) {
418                                 cmp.setActiveTab(tab);
419                                 done = true;
420                         } else {
421                                 console.error("Lseed.Communication.activateTab: 'contentTabPanel' does not exist.");
422                         }
423                 }
424                 
425                 return done;
426         };
427         
428         this.showTab = function (tabname) {
429                 var done = false;
430                 
431                 done = this.activateTab(tabname);
432                         
433                 if (!done) {
434                         this.waitForPage();
435                         
436                         this.sendMessage(Lseed.MessageCommands.ContentRequest, {content: tabname});
437                 }
438         };
439         
440         this.waitForPage = function() {
441                 var cmp = Ext.getCmp("loadPageProgressbar");
442                 if (cmp) {
443                         cmp.show();
444                         cmp.wait({
445                                 interval: 200,
446                                 increment: 15,
447                                 text: 'Lädt...'
448                         });
449                 } else {
450                         console.error("Lseed.Communication.waitForPage: loadPageProgressbar is not defined.");
451                 }
452         };
453         
454         this.stopWaitingForPage = function() {
455                 var cmp = Ext.getCmp("loadPageProgressbar");
456                 if (cmp) {
457                         cmp.updateText("");
458                         cmp.reset();
459                 } else {
460                         console.error("Lseed.Communication.stopWaitingForPage: loadPageProgressbar is not defined.");
461                 }
462         };
463         
464         // === Season Managerment ===
465         
466         this.GetSeasonList = function() {
467                 Ext.MessageBox.wait("Saisons werden geladen.", "Wird geladen...");
468                 
469                 this.sendMessage(Lseed.MessageCommands.RPC, { func: 'GetSeasonList' });
470         };
471         
472         this.GetSeasonListCallback = function(data) {
473                 var grid = Ext.getCmp("seasonlistgrid");
474                 if (grid) {
475                         grid.store.loadData(data.list);
476                 } else {
477                         console.error("Lseed.Communication.GetSeasonList: 'seasonlistgrid' could not be found.");
478                 }
479         }
480         
481
482         this.Init = function(editor) {
483                 Ext.MessageBox.wait("Programmeinstellungen werden geladen.", "Wird geladen...");
484
485                 this.AddCallback("IsLoggedIn", this.isLoggedInCallback.createDelegate(this));
486                 this.AddCallback("Auth", this.AuthCallback.createDelegate(this));
487                 this.AddCallback("Register", this.RegisterCallback.createDelegate(this));
488                 this.AddCallback("GetPlantList", this.GetPlantListCallback.createDelegate(this));
489                 this.AddCallback("GetSeasonList", this.GetSeasonListCallback.createDelegate(this));
490                 
491                 this.AddCallback("SavePlant", editor.SaveCallback.createDelegate(editor));
492                 this.AddCallback("DeletePlant", editor.DeleteCallback.createDelegate(editor));
493                 this.AddCallback("ValidatePlant", editor.HandleSyntaxCheckAnswerForEditor.createDelegate(editor));
494                 this.AddCallback("ActivatePlant", editor.ActivateCallback.createDelegate(editor));
495                 
496                 this.sendMessage(Lseed.MessageCommands.RPC, {func: 'IsLoggedIn'});
497         };
498 };
499
500
501 Lseed.Editor = function() {
502         this.CurrentPlant = {
503                 Name: ''
504                 ,Definition: ''
505         };
506         
507         this.Save = function(plant) {
508                 
509                 communication.sendMessage(Lseed.MessageCommands.RPC, { 
510                         func: 'SavePlant'
511                         ,plant: plant.data.Name
512                         ,code: plant.data.Code
513                 });
514         };
515         
516         this.SaveCallback = function(data) {
517                 if (data.success) {
518                         communication.showMessage("Erfolgreich gespeichert.", "info");
519                 } else {
520                         communication.showMessage(data.msg, "error");
521                 }
522         };
523         
524         this.Activate = function(plant) {
525                 console.log(arguments);
526                 communication.sendMessage(Lseed.MessageCommands.RPC, { 
527                         func: 'ActivatePlant'
528                         ,plant: plant.data.Name
529                         ,user: communication.Username
530                 });
531         };
532         
533         this.ActivateCallback = function(data) {
534                 if (data.success) {
535                         communication.showMessage("Erfolgreich aktiviert.", "info");
536                         communication.GetPlantList();
537                 } else {
538                         communication.showMessage(data.msg, "error");
539                 }
540         };
541         
542         this.Edit = function(plant) {
543                 communication.sendMessage(Lseed.MessageCommands.ContentRequest, {content: 'editplant'});
544                 this.LastEditPlant = plant;
545         };
546         this.EditCallback = function() {
547                 var cmp = Ext.getCmp("editplantdefinitionnamefield");
548                 if (cmp) {
549                         cmp.setValue(this.LastEditPlant.data.Name);
550                 }
551                 var cmp = Ext.getCmp("editplantdefinitioneditor");
552                 if (cmp) {
553                         cmp.setValue(this.LastEditPlant.data.Code);
554                 }
555         };
556         
557         this.Test = function(plant, callback) {
558                 communication.showMessage("Diese Funktion ist leider momentan nicht verfügbar", "error");
559         };
560         
561         this.TestCallback = function() {
562         };
563         
564         this.CheckSyntax = function(plant, callback) {
565                 if (typeof callback != 'undefined' && callback != null) {
566                         this.CheckSyntaxCallback = callback;
567                 }
568                 
569                 communication.sendMessage(Lseed.MessageCommands.RPC, { 
570                         func: 'ValidatePlant'
571                         ,plant: plant.data.Name
572                         ,code: plant.data.Code
573                 });
574         };
575         
576         this.HandleSyntaxCheckAnswerForEditor = function(data) {
577                 if (data.success || data.valid) {
578                         Ext.MessageBox.show({
579                                 title:'Valide'
580                                 ,msg: "Alles Super."
581                                 ,buttons: Ext.Msg.OK
582                                 ,icon: Ext.MessageBox.Info
583                         });
584                 } else {
585                         var pdEditor = Ext.getCmp("plantdefinitioneditor");
586                         if (pdEditor) {
587                                 communication.stopWaitingForPage();
588                                 Ext.MessageBox.show({
589                                         title:'Fehler'
590                                         ,msg: data.msg
591                                         ,buttons: Ext.Msg.OK
592                                         ,fn: function() {
593                                                 if (typeof data.line != "undefined") {
594                                                         var index = editor.GetStartFromField(pdEditor, data.line-1, data.column);
595                                                         if (index != -1) {
596                                                                 pdEditor.selectText(index-1, index);
597                                                         }
598                                                 }
599                                         }
600                                         ,icon: Ext.MessageBox.ERROR
601                                 });
602                         } else {
603                                 console.error("Lseed.Editor.CheckSyntaxCallback_Callback: 'plantdefinitioneditor' Could not be found.");
604                                 alert("Es trat ein Fehler auf...sowas.");
605                         }
606                 }
607         };
608         
609         this.Delete = function(plant) {
610                 communication.sendMessage(Lseed.MessageCommands.RPC, { 
611                         func: 'DeletePlant'
612                         ,id: plant.data.ID
613                 });
614         };
615         
616         this.DeleteCallback = function(data) {
617                 if (!data.success) {
618                         communication.showMessage("Diese Pflanze konnte leider nicht gelöscht werden.", "error");
619                 }
620                 communication.GetPlantList();
621         };
622         
623         this.GetStartFromField = function(field, row, column) {
624                 var result = 0;
625                 var content = field.getValue();
626                 var lines = content.split("\n");
627                 if (lines.length >= row) {
628                         for (var i=0; i<row; i++) {
629                                 result += lines[i].length + 1;
630                         }
631                 }
632                 result += column;
633                 
634                 console.info("error in row: " + row + " column: " + column + " at: " + result);
635                 
636                 return result;
637         };
638 };
639
640 Lseed.Plant = Ext.data.Record.create([{
641         name: 'ID'
642         ,type: 'int'
643 }, {
644         name: 'Name'
645         ,type: 'string'
646 }, {
647         name: 'Code'
648         ,type: 'string'
649 }, {
650         name: 'IsActive'
651         ,type: 'boolean'
652 }]);
653
654 Lseed.Season = Ext.data.Record.create([{
655         name: 'ID'
656         ,type: 'int'
657 }, {
658         name: 'User'
659         ,type: 'string'
660 }, {
661         name: 'IsRunning'
662         ,type: 'boolean'
663 }, {
664         name: 'Score'
665         ,type: 'float'
666 }]);
667