Validate the code as submitted, not as it is in the database
[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.closeAllTabs: 'contentTabPanel' does not exist.");
384                 }
385         };
386         
387         this.closeTab = function(tabname) {
388                 var cmp = Ext.getCmp('contentTabPanel');
389                 if (cmp) {
390                         var tab = this.getTab(tabname);
391                         if (tab) {
392                                 console.error("Lseed.Communication.closeTab: '"+tabname+"' does not exist.");
393                         }
394                         cmp.remove(tab);
395                 } else {
396                         console.error("Lseed.Communication.closeTab: 'contentTabPanel' does not exist.");
397                 }
398         };
399         
400         this.loadTab = function (content, name) {
401                 var cmp = Ext.getCmp("contentTabPanel");
402                 if (cmp) {
403                         cmp.add(content);
404                         this.activateTab(name)
405                 } else {
406                         console.error("Lseed.Communication.showTab: 'contentTabPanel' does not exist.");
407                 }
408         };
409         
410         this.getTab = function (tabname) {
411                 var result = null;
412                 
413                 var cmp = Ext.getCmp("contentTabPanel");
414                 if (cmp) {
415                         result = cmp.findById("ContentPanel_"+tabname);
416                 } else {
417                         console.error("Lseed.Communication.activateTab: 'contentTabPanel' does not exist.");
418                 }
419                 
420                 return result;
421         };
422         
423         this.activateTab = function (tabname) {
424                 var done = false;
425                 
426                 var tab = this.getTab(tabname);
427                 
428                 if (tab) {
429                         var cmp = Ext.getCmp("contentTabPanel");
430                         if (cmp) {
431                                 cmp.setActiveTab(tab);
432                                 done = true;
433                         } else {
434                                 console.error("Lseed.Communication.activateTab: 'contentTabPanel' does not exist.");
435                         }
436                 }
437                 
438                 return done;
439         };
440         
441         this.showTab = function (tabname) {
442                 var done = false;
443                 
444                 done = this.activateTab(tabname);
445                         
446                 if (!done) {
447                         this.waitForPage();
448                         
449                         this.sendMessage(Lseed.MessageCommands.ContentRequest, {content: tabname});
450                 }
451         };
452         
453         this.waitForPage = function() {
454                 var cmp = Ext.getCmp("loadPageProgressbar");
455                 if (cmp) {
456                         cmp.show();
457                         cmp.wait({
458                                 interval: 200,
459                                 increment: 15,
460                                 text: 'Lädt...'
461                         });
462                 } else {
463                         console.error("Lseed.Communication.waitForPage: loadPageProgressbar is not defined.");
464                 }
465         };
466         
467         this.stopWaitingForPage = function() {
468                 var cmp = Ext.getCmp("loadPageProgressbar");
469                 if (cmp) {
470                         cmp.updateText("");
471                         cmp.reset();
472                 } else {
473                         console.error("Lseed.Communication.stopWaitingForPage: loadPageProgressbar is not defined.");
474                 }
475         };
476         
477         // === Season Managerment ===
478         
479         this.GetSeasonList = function() {
480                 Ext.MessageBox.wait("Saisons werden geladen.", "Wird geladen...");
481                 
482                 this.sendMessage(Lseed.MessageCommands.RPC, { func: 'GetSeasonList' });
483         };
484         
485         this.GetSeasonListCallback = function(data) {
486                 var grid = Ext.getCmp("seasonlistgrid");
487                 if (grid) {
488                         grid.store.loadData(data.list);
489                 } else {
490                         console.error("Lseed.Communication.GetSeasonList: 'seasonlistgrid' could not be found.");
491                 }
492         }
493         
494
495         this.Init = function(editor) {
496                 Ext.MessageBox.wait("Programmeinstellungen werden geladen.", "Wird geladen...");
497
498                 this.AddCallback("IsLoggedIn", this.isLoggedInCallback.createDelegate(this));
499                 this.AddCallback("Auth", this.AuthCallback.createDelegate(this));
500                 this.AddCallback("Register", this.RegisterCallback.createDelegate(this));
501                 this.AddCallback("GetPlantList", this.GetPlantListCallback.createDelegate(this));
502                 this.AddCallback("GetSeasonList", this.GetSeasonListCallback.createDelegate(this));
503                 
504                 this.AddCallback("SavePlant", editor.SaveCallback.createDelegate(editor));
505                 this.AddCallback("DeletePlant", editor.DeleteCallback.createDelegate(editor));
506                 this.AddCallback("ValidatePlant", editor.HandleSyntaxCheckAnswerForEditor.createDelegate(editor));
507                 this.AddCallback("ActivatePlant", editor.ActivateCallback.createDelegate(editor));
508                 
509                 this.sendMessage(Lseed.MessageCommands.RPC, {func: 'IsLoggedIn'});
510         };
511 };
512
513
514 Lseed.Editor = function() {
515         this.CurrentPlant = {
516                 Name: ''
517                 ,Definition: ''
518         };
519         
520         this.Save = function(plant) {
521                 
522                 communication.sendMessage(Lseed.MessageCommands.RPC, { 
523                         func: 'SavePlant'
524                         ,plant: plant.data.Name
525                         ,code: plant.data.Code
526                 });
527         };
528         
529         this.SaveCallback = function(data) {
530                 if (data.success) {
531                         communication.showMessage("Erfolgreich gespeichert.", "info");
532                 } else {
533                         communication.showMessage(data.msg, "error");
534                 }
535         };
536         
537         this.Activate = function(plant) {
538                 console.log(arguments);
539                 communication.sendMessage(Lseed.MessageCommands.RPC, { 
540                         func: 'ActivatePlant'
541                         ,plant: plant.data.Name
542                         ,user: communication.Username
543                 });
544         };
545         
546         this.ActivateCallback = function(data) {
547                 if (data.success) {
548                         communication.showMessage("Erfolgreich aktiviert.", "info");
549                         communication.GetPlantList();
550                 } else {
551                         communication.showMessage(data.msg, "error");
552                 }
553         };
554         
555         this.Edit = function(plant) {
556                 communication.sendMessage(Lseed.MessageCommands.ContentRequest, {content: 'editplant'});
557                 this.LastEditPlant = plant;
558         };
559         this.EditCallback = function() {
560                 var cmp = Ext.getCmp("editplantdefinitionnamefield");
561                 if (cmp) {
562                         cmp.setValue(this.LastEditPlant.data.Name);
563                 }
564                 var cmp = Ext.getCmp("editplantdefinitioneditor");
565                 if (cmp) {
566                         cmp.setValue(this.LastEditPlant.data.Code);
567                 }
568         };
569         
570         this.Test = function(plant, callback) {
571                 communication.showMessage("Diese Funktion ist leider momentan nicht verfügbar", "error");
572         };
573         
574         this.TestCallback = function() {
575         };
576         
577         this.CheckSyntax = function(plant, callback) {
578                 if (typeof callback != 'undefined' && callback != null) {
579                         this.CheckSyntaxCallback = callback;
580                 }
581                 
582                 communication.sendMessage(Lseed.MessageCommands.RPC, { 
583                         func: 'ValidatePlant'
584                         ,plant: plant.data.Name
585                         ,code: plant.data.Code
586                 });
587         };
588         
589         this.HandleSyntaxCheckAnswerForEditor = function(data) {
590                 if (data.success || data.valid) {
591                         Ext.MessageBox.show({
592                                 title:'Valide'
593                                 ,msg: "Alles Super."
594                                 ,buttons: Ext.Msg.OK
595                                 ,icon: Ext.MessageBox.Info
596                         });
597                 } else {
598                         // This is a hack for now:
599                         var pdEditor = Ext.getCmp("plantdefinitioneditor");
600                         if (!pdEditor) {
601                                 var pdEditor = Ext.getCmp("editplantdefinitioneditor");
602                         }
603                         if (pdEditor) {
604                                 communication.stopWaitingForPage();
605                                 Ext.MessageBox.show({
606                                         title:'Fehler'
607                                         ,msg: data.msg
608                                         ,buttons: Ext.Msg.OK
609                                         ,fn: function() {
610                                                 if (typeof data.line != "undefined") {
611                                                         var index = editor.GetStartFromField(pdEditor, data.line-1, data.column);
612                                                         if (index != -1) {
613                                                                 pdEditor.selectText(index-1, index);
614                                                         }
615                                                 }
616                                         }
617                                         ,icon: Ext.MessageBox.ERROR
618                                 });
619                         } else {
620                                 console.error("Lseed.Editor.CheckSyntaxCallback_Callback: 'plantdefinitioneditor' Could not be found.");
621                                 alert("Es trat ein Fehler auf...sowas.");
622                         }
623                 }
624         };
625         
626         this.Delete = function(plant) {
627                 communication.sendMessage(Lseed.MessageCommands.RPC, { 
628                         func: 'DeletePlant'
629                         ,id: plant.data.ID
630                 });
631         };
632         
633         this.DeleteCallback = function(data) {
634                 if (!data.success) {
635                         communication.showMessage("Diese Pflanze konnte leider nicht gelöscht werden.", "error");
636                 }
637                 communication.GetPlantList();
638         };
639         
640         this.GetStartFromField = function(field, row, column) {
641                 var result = 0;
642                 var content = field.getValue();
643                 var lines = content.split("\n");
644                 if (lines.length >= row) {
645                         for (var i=0; i<row; i++) {
646                                 result += lines[i].length + 1;
647                         }
648                 }
649                 result += column;
650                 
651                 console.info("error in row: " + row + " column: " + column + " at: " + result);
652                 
653                 return result;
654         };
655 };
656
657 Lseed.Plant = Ext.data.Record.create([{
658         name: 'ID'
659         ,type: 'int'
660 }, {
661         name: 'Name'
662         ,type: 'string'
663 }, {
664         name: 'Code'
665         ,type: 'string'
666 }, {
667         name: 'IsActive'
668         ,type: 'boolean'
669 }]);
670
671 Lseed.Season = Ext.data.Record.create([{
672         name: 'ID'
673         ,type: 'int'
674 }, {
675         name: 'User'
676         ,type: 'string'
677 }, {
678         name: 'IsRunning'
679         ,type: 'boolean'
680 }, {
681         name: 'Score'
682         ,type: 'float'
683 }]);
684