From c4568653ed739eb5e114742e3d066d253fdc5538 Mon Sep 17 00:00:00 2001 From: Alexander Moskaliov Date: Fri, 6 Jan 2012 20:47:26 +0000 Subject: [PATCH 1/4] Init commit for git support in PHPDoE. Added simple autoload, local.*.ini settings files, GitClient and some small changes --- error_type.php | 3 +- index.php | 12 +- install/doc-editor.sql | 9 +- install/firstRun.php | 11 +- install/migration.php | 5 +- js/locale/ar.js | 4 - js/locale/fr.js | 2 - js/locale/ru.js | 2 - js/main-all-debug.js | 137 +----- js/main-all.js | 30 +- js/ui/cmp/RepositoryTree.js | 11 - js/ui/task/UpdateSingleFolderTask.js | 125 ------ php/AccountManager.php | 13 +- php/{Conf.php => Config.php} | 196 +++++---- php/CvsClient.php | 1 - php/DBConnection.php | 2 +- php/DictionaryManager.php | 1 - php/ExecStatement.php | 50 +++ php/ExtJsController.php | 70 +-- php/File.php | 9 +- php/GTranslate.php | 1 - php/GitClient.php | 580 +++++++++++++++++++++++++ php/LogManager.php | 1 - php/PreviewFile.php | 2 +- php/ProjectManager.php | 2 - php/RepositoryFetcher.php | 9 +- php/RepositoryManager.php | 478 ++++++++++---------- php/SaferExec.php | 47 -- php/SvnClient.php | 1 - php/ToolsCheckDoc.php | 1 - php/ToolsCheckEntities.php | 2 - php/ToolsError.php | 3 - php/ToolsXmllint.php | 1 - php/TranslationStatistic.php | 12 +- php/TranslatorStatistic.php | 3 - php/UserNotes.php | 1 - php/VCSFactory.php | 9 +- php/conf/project.php.ini | 8 +- php/controller.php | 3 +- php/loader.php | 12 + php/utility.php | 1 - scripts/cron/check_build.php | 6 +- scripts/cron/check_entities.php | 6 +- scripts/cron/send_entities_to_list.php | 6 +- scripts/cron/send_work_to_list.php | 7 +- scripts/cron/update_data.php | 7 +- scripts/utils/static_stats.php | 2 +- themes/loading-min.css | 2 +- themes/login-all.css | 2 +- themes/main-all.css | 32 +- 50 files changed, 1084 insertions(+), 856 deletions(-) delete mode 100644 js/ui/task/UpdateSingleFolderTask.js rename php/{Conf.php => Config.php} (77%) mode change 100644 => 100755 create mode 100755 php/ExecStatement.php create mode 100755 php/GitClient.php create mode 100755 php/loader.php diff --git a/error_type.php b/error_type.php index 952a8040..ccb71fc7 100644 --- a/error_type.php +++ b/error_type.php @@ -2,8 +2,7 @@ session_start(); error_reporting(E_ALL); -require_once "./php/AccountManager.php"; -require_once "./php/ToolsError.php"; +require_once __DIR__.'/php/loader.php'; $am = AccountManager::getInstance(); $am->isLogged(); diff --git a/index.php b/index.php index fa9a30e3..8093163b 100755 --- a/index.php +++ b/index.php @@ -1,8 +1,9 @@ setProject($_project); @@ -59,9 +56,6 @@ $patchID = trim($_REQUEST['patchID'], '/ '); $_project = $_REQUEST['project']; - require_once dirname(__FILE__) . '/php/ProjectManager.php'; - require_once dirname(__FILE__) . '/php/RepositoryManager.php'; - // Set the project ProjectManager::getInstance()->setProject($_project); diff --git a/install/doc-editor.sql b/install/doc-editor.sql index 600a9cf6..c74ba02f 100644 --- a/install/doc-editor.sql +++ b/install/doc-editor.sql @@ -83,8 +83,8 @@ CREATE TABLE IF NOT EXISTS `files` ( `xmlid` varchar(255) DEFAULT NULL, `path` varchar(255) NOT NULL, `name` varchar(255) NOT NULL, - `revision` int(11) unsigned DEFAULT NULL, - `en_revision` int(11) unsigned DEFAULT NULL, + `revision` VARCHAR(255) DEFAULT NULL, + `en_revision` VARCHAR(255) DEFAULT NULL, `reviewed` varchar(20) DEFAULT NULL, `reviewed_maintainer` text, `size` int(11) unsigned DEFAULT NULL, @@ -202,10 +202,11 @@ CREATE TABLE IF NOT EXISTS `work` ( `lang` varchar(10) NOT NULL, `path` varchar(255) NOT NULL, `name` varchar(255) NOT NULL, - `revision` int(11) NOT NULL, - `en_revision` int(11) NOT NULL, + `revision` VARCHAR(255) NOT NULL, + `en_revision` VARCHAR(255) NOT NULL, `reviewed` varchar(50) NOT NULL, `maintainer` varchar(255) NOT NULL, + `reviewed_maintainer` text, `user` varchar(255) NOT NULL, `anonymousIdent` varchar(255) NOT NULL, `date` datetime NOT NULL, diff --git a/install/firstRun.php b/install/firstRun.php index 6c2499df..0e9bb69b 100644 --- a/install/firstRun.php +++ b/install/firstRun.php @@ -2,11 +2,12 @@ error_reporting(E_ALL); set_time_limit(0); -require_once '../php/html.templates.php'; -require_once '../php/ProjectManager.php'; -require_once '../php/RepositoryManager.php'; -require_once '../php/TranslationStatistic.php'; -require_once '../php/TranslatorStatistic.php'; + +chdir(dirname(__FILE__)); + +require_once __DIR__.'/../php/loader.php'; +require_once __DIR__.'/../php/html.templates.php'; + $isCLI = (PHP_SAPI == 'cli'); diff --git a/install/migration.php b/install/migration.php index 375aa579..9e34310f 100644 --- a/install/migration.php +++ b/install/migration.php @@ -2,10 +2,7 @@ error_reporting(E_ALL); set_time_limit(0); -require_once '../php/ProjectManager.php'; -require_once '../php/DBConnection.php'; -require_once '../php/RepositoryManager.php'; -require_once '../php/AccountManager.php'; +require_once __DIR__.'/../php/loader.php'; $am = AccountManager::getInstance(); $rm = RepositoryManager::getInstance(); diff --git a/js/locale/ar.js b/js/locale/ar.js index c685e912..d1d0eb0b 100644 --- a/js/locale/ar.js +++ b/js/locale/ar.js @@ -553,10 +553,6 @@ var i18n = new Array(); i18n["check in progress..."] = "جاري الفحص..."; -// In file: ../../js/ui/task/UpdateSingleFolderTask.js - i18n["Please, wait until update this folder..."] = "يرجى الانتظار حتى يتم تحديث المجلد..."; - - // In file: ../../js/ui/task/SaveTransFileTask.js i18n["Saving data..."] = "حفظ البيانات..."; i18n["Document saved"] = "تم حفظ الوثيقة"; diff --git a/js/locale/fr.js b/js/locale/fr.js index 1b9c5cd7..6a5866f0 100644 --- a/js/locale/fr.js +++ b/js/locale/fr.js @@ -571,8 +571,6 @@ var i18n = new Array(); i18n["Retrying in {0} second(s)."] = "Nouvelle tentative de connexion dans {0} seconde(s)."; -// In file: ../../js/ui/task/UpdateSingleFolderTask.js - i18n["Please, wait until update this folder..."] = "Merci de patienter pendant la mise à jour de ce dossier..."; // In file: ../../js/ui/task/SaveTransFileTask.js diff --git a/js/locale/ru.js b/js/locale/ru.js index 754ee7c3..0472a15a 100644 --- a/js/locale/ru.js +++ b/js/locale/ru.js @@ -565,8 +565,6 @@ var i18n = new Array(); i18n["Retrying in {0} second(s)."] = "Повторное подключение через {0} секунд."; -// In file: ../../js/ui/task/UpdateSingleFolderTask.js - i18n["Please, wait until update this folder..."] = "Пожалуйста, подождите обновления этой папки..."; // In file: ../../js/ui/task/SaveTransFileTask.js diff --git a/js/main-all-debug.js b/js/main-all-debug.js index dd381ee0..6c5e501d 100644 --- a/js/main-all-debug.js +++ b/js/main-all-debug.js @@ -11751,130 +11751,6 @@ ui.task.UpdateConfTask = function(config) } } }); -};Ext.namespace('ui','ui.task','ui.task._UpdateSingleFolderTask'); - -ui.task._UpdateSingleFolderTask.getUpdateFolderResponse = function(node) -{ - XHR({ - params : { - task: 'getUpdateFolderResponse' - }, - success : function(r) - { - var o = Ext.util.JSON.decode(r.responseText); - ui.task._UpdateSingleFolderTask.afterUpdate(o, node); - } - }); -} - -ui.task._UpdateSingleFolderTask.poll = new Ext.util.DelayedTask(function() -{ - var node = arguments[0], - u = node.attributes.id.split('/'), - FirstFolder, t = new Array(); - - u.shift(); - FirstFolder = u[0]; - - t.push(node); - - XHR({ - params : { - task : 'checkLockFile', - lockFile : 'project_' + PhDOE.project + '_' + FirstFolder + '_lock_update_folder' - }, - success : function() - { - ui.task._UpdateSingleFolderTask.poll.delay(5000, null, this, t); - }, - failure : function(response) - { - var o = Ext.util.JSON.decode(response.responseText); - - if (o && o.success === false) { - new ui.task._UpdateSingleFolderTask.getUpdateFolderResponse(node); - - } else { - ui.task._UpdateSingleFolderTask.poll.delay(5000, null, this, t); - } - } - }); -}); - -ui.task._UpdateSingleFolderTask.afterUpdate = function(o, node) -{ - Ext.getBody().unmask(); - - // Re-enable TaskPing - ui.task.PingTask.getInstance().delay(30000); - - // TODO: we must handle the response here - var r = Ext.util.JSON.decode(o.result); - - // We reload and highlight the modified node - node.reload(function() { - - Ext.iterate(r.newFiles, function(prop, val){ - node.findChild('text', prop).getUI().addClass('treeFileUpdated'); - }); - - }, this); - - // Reload all store - PhDOE.reloadAllStore(); - -}; - -ui.task._UpdateSingleFolderTask.update = function(node) -{ - var t = new Array(); - t.push(node); - - Ext.getBody().mask( - ' ' + - _('Please, wait until update this folder...') - ); - - // We need to stop ping test during this process - ui.task.PingTask.getInstance().cancel(); - - XHR({ - params : { - task : 'updateFolder', - path : node.id - }, - success : function(r) - { - var o = Ext.util.JSON.decode(r.responseText); - ui.task._UpdateSingleFolderTask.afterUpdate(o, node); - }, - failure : function(r) - { - var o = Ext.util.JSON.decode(r.responseText); - - if (o && o.success === false) { - // Re-enable TaskPing - ui.task.PingTask.getInstance().delay(30000); - Ext.getBody().unmask(); - PhDOE.winForbidden(); - } else { - // take over 30sec (max Keep-Alive time) - // poll every XX secondes if the update is finish - ui.task._UpdateSingleFolderTask.poll.delay(5000, null, this, t); - } - } - }); -}; - -ui.task.UpdateSingleFolderTask = function(node) -{ - // If the user is anonymous, we don't update anything - if (PhDOE.user.isAnonymous) { - Ext.getCmp('winVCSCommit').close(); - PhDOE.winForbidden(); - return; - } - ui.task._UpdateSingleFolderTask.update(node); };Ext.namespace('ui','ui.task','ui.task._VCSCommitTask'); ui.task._VCSCommitTask.getCommitResponse = function() @@ -22342,17 +22218,6 @@ Ext.extend(ui.cmp._RepositoryTree.menu.folder, Ext.menu.Menu, { } } }, '-', { - text: _('Update this folder'), - iconCls: 'iconFilesNeedUpdate', - scope: this, - handler: function(){ - // We start by expand this node. - this.node.expand(); - - //... and fire the update processus - new ui.task.UpdateSingleFolderTask(this.node); - } - }, { text: _('Add a new folder'), iconCls: 'iconFolderNew', hidden: (this.node.id === '/' || @@ -24727,7 +24592,7 @@ var PhDOE = function() name: 'Php Docbook Online Editor', ver : 'X.XX', loaded: false, - uiRevision: '$Revision: 321288 $', + uiRevision: '$Revision: 321700 $', conf: '', extJsVersion: '3.3.1', codeMirror: '2.2' diff --git a/js/main-all.js b/js/main-all.js index cb2bb698..eeeb1dba 100644 --- a/js/main-all.js +++ b/js/main-all.js @@ -1,99 +1,99 @@ var CodeMirror=(function(){function s(aE,aB){var bN={},ba=s.defaults;for(var aq in ba){if(ba.hasOwnProperty(aq)){bN[aq]=(aB&&aB.hasOwnProperty(aq)?aB:ba)[aq]}}var cx=bN.document;var av=cx.createElement("div");av.className="CodeMirror"+(bN.lineWrapping?" CodeMirror-wrap":"");av.innerHTML='
 
';if(aE.appendChild){aE.appendChild(av)}else{aE(av)}var bK=av.firstChild,bd=bK.firstChild,bb=av.lastChild,bA=bb.firstChild,b2=bA.firstChild,az=b2.firstChild,aR=az.firstChild,bl=az.nextSibling.firstChild,am=bl.firstChild,a4=am.nextSibling,ai=a4.nextSibling;co();if(/AppleWebKit/.test(navigator.userAgent)&&/Mobile\/\w+/.test(navigator.userAgent)){bd.style.width="0px"}if(!f){bl.draggable=true}if(bN.tabindex!=null){bd.tabIndex=bN.tabindex}if(!bN.gutter&&!bN.lineNumbers){az.style.display="none"}try{ce("x")}catch(bU){if(bU.message.match(/runtime/i)){bU=new Error("A CodeMirror inside a P-style element does not work in Internet Explorer. (innerHTML bug)")}throw bU}var bT=new w(),an=new w(),cB;var bX,cj=new h([new aa([new e("")])]),b3,b5;bG();var cI={from:{line:0,ch:0},to:{line:0,ch:0},inverted:false};var b4,bg,aS,a3,b9=false;var cb,bS,at,cy,aH,a7,aK,cl;var a5=0,cC=0,bz=0,bB=0;var bQ;var bs="",ax,bk=aO();aj(function(){aP(bN.value||"");cb=false})();var a1=new k();q(bb,"mousedown",aj(b6));q(bb,"dblclick",aj(bJ));q(bl,"dragstart",aA);q(bl,"selectstart",O);if(!J){q(bb,"contextmenu",aU)}q(bb,"scroll",function(){bZ([]);if(bN.fixedGutter){az.style.left=bb.scrollLeft+"px"}if(bN.onScroll){bN.onScroll(bV)}});q(window,"resize",function(){bZ(true)});q(bd,"keyup",aj(b7));q(bd,"input",aI);q(bd,"keydown",aj(bY));q(bd,"keypress",aj(be));q(bd,"focus",cG);q(bd,"blur",aw);q(bb,"dragenter",u);q(bb,"dragover",u);q(bb,"drop",aj(ag));q(bb,"paste",function(){bq();aI()});q(bd,"paste",aI);q(bd,"cut",aj(function(){bi("")}));var ch;try{ch=(cx.activeElement==bd)}catch(bU){}if(ch){setTimeout(cG,20)}else{aw()}function bh(cL){return cL>=0&&cLcL&&cP.y>cN.offsetHeight){cQ=cP.y-cN.offsetHeight}if(cM+cN.offsetWidth>cS){cM=cS-cN.offsetWidth}}}cN.style.top=(cQ+cd())+"px";cN.style.left=cN.style.right="";if(cT=="right"){cM=bA.clientWidth-cN.offsetWidth;cN.style.right="0px"}else{if(cT=="left"){cM=0}else{if(cT=="middle"){cM=(bA.clientWidth-cN.offsetWidth)/2}}cN.style.left=(cM+aY())+"px"}if(cR){ar(cM,cQ,cM+cN.offsetWidth,cQ+cN.offsetHeight)}},lineCount:function(){return cj.size},clipPos:aL,getCursor:function(cL){if(cL==null){cL=cI.inverted}return V(cL?cI.from:cI.to)},somethingSelected:function(){return !X(cI.from,cI.to)},setCursor:aj(function(cL,cN,cM){if(cN==null&&typeof cL.line=="number"){aZ(cL.line,cL.ch,cM)}else{aZ(cL,cN,cM)}}),setSelection:aj(function(cN,cM,cL){(cL?bo:bn)(aL(cN),aL(cM||cN))}),getLine:function(cL){if(bh(cL)){return cq(cL).text}},getLineHandle:function(cL){if(bh(cL)){return cq(cL)}},setLine:aj(function(cL,cM){if(bh(cL)){bD(cM,{line:cL,ch:0},{line:cL,ch:cq(cL).text.length})}}),removeLine:aj(function(cL){if(bh(cL)){bD("",{line:cL,ch:0},aL({line:cL+1,ch:0}))}}),replaceRange:aj(bD),getRange:function(cM,cL){return cA(aL(cM),aL(cL))},execCommand:function(cL){return G[cL](bV)},moveH:aj(cp),deleteH:aj(b8),moveV:aj(ci),toggleOverwrite:function(){b9=!b9},posFromIndex:function(cM){var cN=0,cL;cj.iter(0,cj.size,function(cO){var cP=cO.text.length+1;if(cP>cM){cL=cM;return true}cM-=cP;++cN});return aL({line:cN,ch:cL})},indexFromPos:function(cM){if(cM.line<0||cM.ch<0){return 0}var cL=cM.ch;cj.iter(0,cM.line,function(cN){cL+=cN.text.length+1});return cL},operation:function(cL){return aj(cL)()},refresh:function(){bZ(true)},getInputField:function(){return bd},getWrapperElement:function(){return av},getScrollerElement:function(){return bb},getGutterElement:function(){return az}};function cq(cL){return y(cj,cL)}function aV(cM,cL){aK=true;var cN=cL-cM.height;for(var cO=cM;cO;cO=cO.parent){cO.height+=cN}}function aP(cL){var cM={line:0,ch:0};aG(cM,{line:cj.size-1,ch:cq(cj.size-1).text.length},x(cL),cM,cM);cb=true}function bO(cL){var cM=[];cj.iter(0,cj.size,function(cN){cM.push(cN.text)});return cM.join("\n")}function b6(cR){aX(cR.shiftKey);for(var cO=j(cR);cO!=av;cO=cO.parentNode){if(cO.parentNode==bA&&cO!=b2){return}}for(var cO=j(cR);cO!=av;cO=cO.parentNode){if(cO.parentNode==aR){if(bN.onGutterClick){bN.onGutterClick(bV,p(aR.childNodes,cO)+cC,cR)}return O(cR)}}var cL=aW(cR);switch(v(cR)){case 3:if(J&&!H){aU(cR)}return;case 2:if(cL){aZ(cL.line,cL.ch,true)}return}if(!cL){if(j(cR)==bb){O(cR)}return}if(!b5){cG()}var cM=+new Date;if(aS&&aS.time>cM-400&&X(aS.pos,cL)){O(cR);setTimeout(bq,20);return aC(cL.line)}else{if(bg&&bg.time>cM-400&&X(bg.pos,cL)){aS={time:cM,pos:cL};O(cR);return bw(cL)}else{bg={time:cM,pos:cL}}}var cT=cL,cN;if(B&&!X(cI.from,cI.to)&&!U(cL,cI.from)&&!U(cI.to,cL)){if(f){bl.draggable=true}var cQ=q(cx,"mouseup",aj(function(cU){if(f){bl.draggable=false}a3=false;cQ();if(Math.abs(cR.clientX-cU.clientX)+Math.abs(cR.clientY-cU.clientY)<10){O(cU);aZ(cL.line,cL.ch,true);bq()}}),true);a3=true;return}O(cR);aZ(cL.line,cL.ch,true);function cS(cU){var cW=aW(cU,true);if(cW&&!X(cW,cT)){if(!b5){cG()}cT=cW;bo(cL,cW);cb=false;var cV=br();if(cW.line>=cV.to||cW.line-1){setTimeout(aj(function(){bp(cI.to.line,"smart")}),75)}}aI()}function b7(cL){if(bN.onKeyEvent&&bN.onKeyEvent(bV,I(cL))){return}if(cL.keyCode==16){b4=null}}function cG(){if(bN.readOnly){return}if(!b5){if(bN.onFocus){bN.onFocus(bV)}b5=true;if(av.className.search(/\bCodeMirror-focused\b/)==-1){av.className+=" CodeMirror-focused"}if(!a7){cn(true)}}af();cz()}function aw(){if(b5){if(bN.onBlur){bN.onBlur(bV)}b5=false;av.className=av.className.replace(" CodeMirror-focused","")}clearInterval(cB);setTimeout(function(){if(!b5){b4=null}},150)}function aG(cQ,cP,cO,cM,cL){if(a1){var cN=[];cj.iter(cQ.line,cP.line+1,function(cR){cN.push(cR.text)});a1.addChange(cQ.line,cO.length,cN);while(a1.done.length>bN.undoDepth){a1.done.shift()}}ak(cQ,cP,cO,cM,cL)}function bW(cQ,cP){var cO=cQ.pop();if(cO){var cM=[],cL=cO.start+cO.added;cj.iter(cO.start,cL,function(cR){cM.push(cR.text)});cP.push({start:cO.start,added:cO.old.length,old:cM});var cN=aL({line:cO.start+cO.old.length-1,ch:R(cM[cM.length-1],cO.old[cO.old.length-1])});ak({line:cO.start,ch:0},{line:cL-1,ch:cq(cL-1).text.length},cO.old,cN,cN);cb=true}}function cF(){bW(a1.done,a1.undone)}function cu(){bW(a1.undone,a1.done)}function ak(c0,cP,c6,cL,c7){var c5=false,cO=bs.length;if(!bN.lineWrapping){cj.iter(c0.line,cP.line,function(c8){if(c8.text.length==cO){c5=true;return true}})}if(c0.line!=cP.line||c6.length>1){aK=true}var cX=cP.line-c0.line,cW=cq(c0.line),cM=cq(cP.line);if(c0.ch==0&&cP.ch==0&&c6[c6.length-1]==""){var cU=[],cV=null;if(c0.line){cV=cq(c0.line-1);cV.fixMarkEnds(cM)}else{cM.fixMarkStarts()}for(var c2=0,c4=c6.length-1;c21){cj.remove(c0.line+1,cX-1,cl)}cj.insert(c0.line+1,cU)}}}if(bN.lineWrapping){var cR=bb.clientWidth/a9()-3;cj.iter(c0.line,c0.line+c6.length,function(c8){if(c8.hidden){return}var c9=Math.ceil(c8.text.length/cR)||1;if(c9!=c8.height){aV(c8,c9)}})}else{cj.iter(c0.line,c2+c6.length,function(c9){var c8=c9.text;if(c8.length>cO){bs=c8;cO=c8.length;ax=null;c5=false}});if(c5){cO=0;bs="";ax=null;cj.iter(0,cj.size,function(c9){var c8=c9.text;if(c8.length>cO){cO=c8.length;bs=c8}})}}var cN=[],cT=c6.length-cX-1;for(var c2=0,cZ=b3.length;c2cP.line){cN.push(c3+cT)}}}var c1=c0.line+Math.min(c6.length,500);cs(c0.line,c1);cN.push(c1);b3=cN;bu(100);at.push({from:c0.line,to:cP.line+1,diff:cT});var cS={from:c0,to:cP,text:c6};if(cy){for(var cQ=cy;cQ.next;cQ=cQ.next){}cQ.next=cS}else{cy=cS}function cY(c8){return c8<=Math.min(cP.line,cP.line+cT)?c8:c8+cT}bn(cL,c7,cY(cI.from.line),cY(cI.to.line));bA.style.height=(cj.height*bC()+2*cd())+"px"}function bD(cM,cP,cO){cP=aL(cP);if(!cO){cO=cP}else{cO=aL(cO)}cM=x(cM);function cN(cS){if(U(cS,cP)){return cS}if(!U(cO,cS)){return cL}var cQ=cS.line+cM.length-(cO.line-cP.line)-1;var cR=cS.ch;if(cS.line==cO.line){cR+=cM[cM.length-1].length-(cO.ch-(cO.line==cP.line?cP.ch:0))}return{line:cQ,ch:cR}}var cL;au(cM,cP,cO,function(cQ){cL=cQ;return{from:cN(cI.from),to:cN(cI.to)}});return cL}function bi(cL,cM){au(x(cL),cI.from,cI.to,function(cN){if(cM=="end"){return{from:cN,to:cN}}else{if(cM=="start"){return{from:cI.from,to:cI.from}}else{return{from:cI.from,to:cN}}}})}function au(cO,cQ,cP,cL){var cN=cO.length==1?cO[0].length+cQ.ch:cO[cO.length-1].length;var cM=cL({line:cQ.line+cO.length-1,ch:cN});aG(cQ,cP,cO,cM.from,cM.to)}function cA(cP,cO){var cM=cP.line,cL=cO.line;if(cM==cL){return cq(cM).text.slice(cP.ch,cO.ch)}var cN=[cq(cM).text.slice(cP.ch)];cj.iter(cM+1,cL,function(cQ){cN.push(cQ.text)});cN.push(cq(cL).text.slice(0,cO.ch));return cN.join("\n")}function bP(){return cA(cI.from,cI.to)}var bj=false;function af(){if(bj){return}bT.set(bN.pollInterval,function(){aF();by();if(b5){af()}ap()})}function aI(){var cL=false;bj=true;function cM(){aF();var cN=by();if(!cN&&!cL){cL=true;bT.set(60,cM)}else{bj=false;af()}ap()}bT.set(20,cM)}var a2="";function by(){if(a7||!b5||Y(bd)){return false}var cM=bd.value;if(cM==a2){return false}b4=null;var cN=0,cL=Math.min(a2.length,cM.length);while(cNcM){a4.scrollIntoView()}}function b1(){var cM=cD(cI.inverted?cI.from:cI.to);var cL=bN.lineWrapping?Math.min(cM.x,bl.offsetWidth):cM.x;return ar(cL,cM.y,cL,cM.yBot)}function ar(cN,cS,cL,cR){var cP=aY(),cY=cd(),cU=bC();cS+=cY;cR+=cY;cN+=cP;cL+=cP;var cV=bb.clientHeight,cO=bb.scrollTop,cM=false,cX=true;if(cScO+cV){bb.scrollTop=cR+cU-cV;cM=true}}var cT=bb.clientWidth,cW=bb.scrollLeft;var cQ=bN.fixedGutter?az.clientWidth:0;if(cNcT+cW-3){bb.scrollLeft=cL+10-cT;cM=true;if(cL>bA.clientWidth){cX=false}}}if(cM&&bN.onScroll){bN.onScroll(bV)}return cX}function br(){var cM=bC(),cO=bb.scrollTop-cd();var cL=Math.max(0,Math.floor(cO/cM));var cN=Math.ceil((cO+bb.clientHeight)/cM);return{from:S(cj,cL),to:S(cj,cN)}}function bZ(cU,cQ){if(!bb.clientWidth){cC=bz=a5=0;return}var cO=br();if(cU!==true&&cU.length==0&&cO.from>=cC&&cO.to<=bz){return}var cV=Math.max(cO.from-100,0),cW=Math.min(cj.size,cO.to+100);if(cCcW&&bz-cW<20){cW=Math.min(cj.size,bz)}var cX=cU===true?[]:bM([{from:cC,to:bz,domStart:0}],cU);var cT=0;for(var cR=0;cRcW){cS.to=cW}if(cS.from>=cS.to){cX.splice(cR--,1)}else{cT+=cS.to-cS.from}}if(cT==cW-cV){return}cX.sort(function(cZ,cY){return cZ.domStart-cY.domStart});var cN=bC(),cL=az.style.display;ai.style.display=az.style.display="none";aJ(cV,cW,cX);ai.style.display="";var cM=cV!=cC||cW!=bz||bB!=bb.clientHeight+cN;if(cM){bB=bb.clientHeight+cN}cC=cV;bz=cW;a5=g(cj,cV);b2.style.top=(a5*cN)+"px";bA.style.height=(cj.height*cN+2*cd())+"px";if(ai.childNodes.length!=bz-cC){throw new Error("BAD PATCH! "+JSON.stringify(cX)+" size="+(bz-cC)+" nodes="+ai.childNodes.length)}if(bN.lineWrapping){ax=bb.clientWidth;var cP=ai.firstChild;cj.iter(cC,bz,function(cZ){if(!cZ.hidden){var cY=Math.round(cP.offsetHeight/cN)||1;if(cZ.height!=cY){aV(cZ,cY);aK=true}}cP=cP.nextSibling})}else{if(ax==null){ax=ce(bs)}if(ax>bb.clientWidth){bl.style.width=ax+"px";bA.style.width="";bA.style.width=bb.scrollWidth+"px"}else{bl.style.width=bA.style.width=""}}az.style.display=cL;if(cM||aK){aD()}a8();if(!cQ&&bN.onUpdate){bN.onUpdate(bV)}return true}function bM(cU,cS){for(var cP=0,cN=cS.length||0;cP=cQ.to){cL.push(cQ)}else{if(cR.from>cQ.from){cL.push({from:cQ.from,to:cR.from,domStart:cQ.domStart})}if(cR.tocR){cO=cL(cO);cR++}for(var cQ=0,cU=c0.to-c0.from;cQ=cY;var cV=cx.createElement("div"),cN;cj.iter(cY,cZ,function(c2){var c4=null,c3=null;if(cP){c4=0;if(cW==cQ){cP=false;c3=cI.to.ch}}else{if(cX==cQ){if(cW==cQ){c4=cI.from.ch;c3=cI.to.ch}else{cP=true;c4=cI.from.ch}}}if(cT&&cT.to==cQ){cT=c1.shift()}if(!cT||cT.from>cQ){if(c2.hidden){cV.innerHTML="
"}else{cV.innerHTML=c2.getHTML(c4,c3,true,bk)}ai.insertBefore(cV.firstChild,cO)}else{cO=cO.nextSibling}++cQ})}function aD(){if(!bN.gutter&&!bN.lineNumbers){return}var cL=b2.offsetHeight,cS=bb.clientHeight;az.style.height=(cL-cS<2?cS:cL)+"px";var cN=[],cM=cC;cj.iter(cC,Math.max(bz,cC+1),function(cU){if(cU.hidden){cN.push("
")}else{var cT=cU.gutterMarker;var cW=bN.lineNumbers?cM+bN.firstLineNumber:null;if(cT&&cT.text){cW=cT.text.replace("%N%",cW!=null?cW:"")}else{if(cW==null){cW="\u00a0"}}cN.push((cT&&cT.style?'
':"
"),cW);for(var cV=1;cV ")}cN.push("
")}++cM});az.style.display="none";aR.innerHTML=cN.join("");var cR=String(cj.size).length,cP=aR.firstChild,cQ=C(cP),cO="";while(cQ.length+cO.lengthcN||cT>cQ.text.length){cT=cQ.text.length}return{line:cU,ch:cT}}cU+=cS}}var cL=cq(cP.line);if(!cL.hidden){return cP}if(cP.line>=cM){return cO(1)||cO(-1)}else{return cO(-1)||cO(1)}}function aZ(cL,cN,cM){var cO=aL({line:cL,ch:cN||0});(cM?bo:bn)(cO,cO)}function bL(cL){return Math.max(0,Math.min(cL,cj.size-1))}function aL(cN){if(cN.line<0){return{line:0,ch:0}}if(cN.line>=cj.size){return{line:cj.size-1,ch:cq(cj.size-1).text.length}}var cL=cN.ch,cM=cq(cN.line).text.length;if(cL==null||cL>cM){return{line:cN.line,ch:cM}}else{if(cL<0){return{line:cN.line,ch:0}}else{return cN}}}function ca(cO,cS){var cP=cI.inverted?cI.from:cI.to,cT=cP.line,cL=cP.ch;var cR=cq(cT);function cM(){for(var cU=cT+cO,cW=cO<0?-1:cj.size;cU!=cW;cU+=cO){var cV=cq(cU);if(!cV.hidden){cT=cU;cR=cV;return true}}}function cQ(cU){if(cL==(cO<0?0:cR.text.length)){if(!cU&&cM()){cL=cO<0?cR.text.length:0}else{return false}}else{cL+=cO}return true}if(cS=="char"){cQ()}else{if(cS=="column"){cQ(true)}else{if(cS=="word"){var cN=false;for(;;){if(cO<0){if(!cQ()){break}}if(Z(cR.text.charAt(cL))){cN=true}else{if(cN){if(cO<0){cO=1;cQ()}break}}if(cO>0){if(!cQ()){break}}}}}}return{line:cT,ch:cL}}function cp(cL,cM){var cN=cL<0?cI.from:cI.to;if(b4||X(cI.from,cI.to)){cN=ca(cL,cM)}aZ(cN.line,cN.ch,true)}function b8(cL,cM){if(!X(cI.from,cI.to)){bD("",cI.from,cI.to)}else{if(cL<0){bD("",ca(cL,cM),cI.to)}else{bD("",cI.from,ca(cL,cM))}}bS=true}var cg=null;function ci(cL,cM){var cO=0,cP=cD(cI.inverted?cI.from:cI.to,true);if(cg!=null){cP.x=cg}if(cM=="page"){cO=bb.clientHeight}else{if(cM=="line"){cO=bC()}}var cN=bv(cP.x,cP.y+cO*cL+2);aZ(cN.line,cN.ch,true);cg=cP.x}function bw(cO){var cM=cq(cO.line).text;var cN=cO.ch,cL=cO.ch;while(cN>0&&Z(cM.charAt(cN-1))){--cN}while(cLbs.length){bs=cO.text}})}at.push({from:0,to:cj.size})}function aO(){for(var cM='',cL=0;cL"}function cH(){bk=aO();bZ(true)}function co(){bb.className=bb.className.replace(/\s*cm-s-\w+/g,"")+bN.theme.replace(/(^|\s)\s*/g," cm-s-")}function cJ(){this.set=[]}cJ.prototype.clear=aj(function(){var cQ=Infinity,cM=-Infinity;for(var cP=0,cS=this.set.length;cP
";return am.firstChild.firstChild.offsetWidth}var cS=0,cQ=0,cT=cU.length,cP;var cM=Math.min(cT,Math.ceil(cR/a9()));for(;;){var cN=cV(cM);if(cN<=cR&&cMcP){return cT}cM=Math.floor(cT*0.8);cN=cV(cM);if(cNcR-cQ)?cS:cT}var cW=Math.ceil((cS+cT)/2),cL=cV(cW);if(cL>cR){cT=cW;cP=cL}else{cS=cW;cQ=cL}}}var ck=Math.floor(Math.random()*16777215).toString(16);function bR(cN,cQ){var cL="";if(bN.lineWrapping){var cM=cN.text.indexOf(" ",cQ+2);cL=K(cN.text.slice(cQ+1,cM<0?cN.text.length:cM+(D?5:0)))}am.innerHTML="
"+cN.getHTML(null,null,false,bk,cQ)+''+K(cN.text.charAt(cQ)||" ")+""+cL+"
";var cP=document.getElementById("CodeMirror-temp-"+ck);var cS=cP.offsetTop,cR=cP.offsetLeft;if(D&&cQ&&cS==0&&cR==0){var cO=document.createElement("span");cO.innerHTML="x";cP.parentNode.insertBefore(cO,cP.nextSibling);cS=cO.offsetTop}return{top:cS,left:cR}}function cD(cQ,cO){var cL,cM=bC(),cP=cM*(g(cj,cQ.line)-(cO?a5:0));if(cQ.ch==0){cL=0}else{var cN=bR(cq(cQ.line),cQ.ch);cL=cN.left;if(bN.lineWrapping){cP+=Math.max(0,cN.top)}}return{x:cL,y:cP,yBot:cP+cM}}function bv(cU,cT){if(cT<0){cT=0}var cR=bC(),cP=a9(),c0=a5+Math.floor(cT/cR);var cV=S(cj,c0);if(cV>=cj.size){return{line:cj.size-1,ch:cq(cj.size-1).text.length}}var cM=cq(cV),cX=cM.text;var c2=bN.lineWrapping,cS=c2?c0-g(cj,cV):0;if(cU<=0&&cS==0){return{line:cV,ch:0}}function c1(c4){var c5=bR(cM,c4);if(c2){var c6=Math.round(c5.top/cR);return Math.max(0,c5.left+(c6-cS)*bb.clientWidth)}return c5.left}var cZ=0,cY=0,cN=cX.length,cL;var cW=Math.min(cN,Math.ceil((cU+cS*bb.clientWidth*0.9)/cP));for(;;){var cQ=c1(cW);if(cQ<=cU&&cWcL){return{line:cV,ch:cN}}cW=Math.floor(cN*0.8);cQ=c1(cW);if(cQcU-cY)?cZ:cN}}var c3=Math.ceil((cZ+cN)/2),cO=c1(c3);if(cO>cU){cN=c3;cL=cO}else{cZ=c3;cY=cO}}}function ah(cN){var cL=cD(cN,true),cM=ad(bl);return{x:cM.left+cL.x,y:cM.top+cL.y,yBot:cM.top+cL.yBot}}var aT,ao,bH;function bC(){if(bH==null){bH="
";for(var cM=0;cM<49;++cM){bH+="x
"}bH+="x
"}var cL=ai.clientHeight;if(cL==ao){return aT}ao=cL;am.innerHTML=bH;aT=am.firstChild.offsetHeight/50||1;am.innerHTML="";return aT}var cE,bm=0;function a9(){if(bb.clientWidth==bm){return cE}bm=bb.clientWidth;return(cE=ce("x"))}function cd(){return bl.offsetTop}function aY(){return bl.offsetLeft}function aW(cP,cO){var cN=ad(bb,true),cL,cQ;try{cL=cP.clientX;cQ=cP.clientY}catch(cP){return null}if(!cO&&(cL-cN.left>bb.clientWidth||cQ-cN.top>bb.clientHeight)){return null}var cM=ad(bl,true);return bv(cL-cM.left,cQ-cM.top)}function aU(cM){var cQ=aW(cM);if(!cQ||window.opera){return}if(X(cI.from,cI.to)||U(cQ,cI.from)||!U(cQ,cI.to)){aj(aZ)(cQ.line,cQ.ch)}var cP=bd.style.cssText;bK.style.position="absolute";bd.style.cssText="position: fixed; width: 30px; height: 30px; top: "+(cM.clientY-5)+"px; left: "+(cM.clientX-5)+"px; z-index: 1000; background: white; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);";a7=true;var cO=bd.value=bP();bq();bd.select();function cL(){var cR=x(bd.value).join("\n");if(cR!=cO){aj(bi)(cR,"end")}bK.style.position="relative";bd.style.cssText=cP;a7=false;cn(true);af()}if(J){u(cM);var cN=q(window,"mouseup",function(){cN();setTimeout(cL,20)},true)}else{setTimeout(cL,50)}}function cz(){clearInterval(cB);var cL=true;a4.style.visibility="";cB=setInterval(function(){a4.style.visibility=(cL=!cL)?"":"hidden"},650)}var bf={"(":")>",")":"(<","[":"]>","]":"[<","{":"}>","}":"{<"};function b0(cR){var cL=cI.inverted?cI.from:cI.to,cT=cq(cL.line),cM=cL.ch-1;var cQ=(cM>=0&&bf[cT.text.charAt(cM)])||bf[cT.text.charAt(++cM)];if(!cQ){return}var cU=cQ.charAt(0),cS=cQ.charAt(1)==">",c4=cS?1:-1,cZ=cT.styles;for(var c5=cM+1,c1=0,c3=cZ.length;c1=dc&&db"==cS){cO.push(de)}else{if(cO.pop()!=c9.charAt(0)){return{pos:db,match:false}}else{if(!cO.length){return{pos:db,match:true}}}}}}}}for(var c1=cL.line,c3=cS?Math.min(c1+100,cj.size):Math.max(-1,c1-100);c1!=c3;c1+=c4){var cT=cq(c1),cP=c1==cL.line;var cV=cW(cT,cP&&cS?cM+1:0,cP&&!cS?cM:cT.text.length);if(cV){break}}if(!cV){cV={pos:null,match:false}}var c2=cV.match?"CodeMirror-matchingbracket":"CodeMirror-nonmatchingbracket";var c0=bt({line:cL.line,ch:cM},{line:cL.line,ch:cM+1},c2),cN=cV.pos!=null&&bt({line:c1,ch:cV.pos},{line:c1,ch:cV.pos+1},c2);var cX=aj(function(){c0.clear();cN&&cN.clear()});if(cR){setTimeout(cX,800)}else{bQ=cX}}function a0(cR){var cQ,cN;for(var cM=cR,cO=cR-40;cM>cO;--cM){if(cM==0){return 0}var cL=cq(cM-1);if(cL.stateAfter){return cM}var cP=cL.indentation(bN.tabSize);if(cN==null||cQ>cP){cN=cM-1;cQ=cP}}return cN}function cf(cN){var cM=a0(cN),cL=cM&&cq(cM-1).stateAfter;if(!cL){cL=Q(bX)}else{cL=o(bX,cL)}cj.iter(cM,cN,function(cO){cO.highlight(bX,cL,bN.tabSize);cO.stateAfter=o(bX,cL)});if(cM=cj.size){continue}var cM=a0(cO),cL=cM&&cq(cM-1).stateAfter;if(cL){cL=o(bX,cL)}else{cL=Q(bX)}var cQ=0,cN=bX.compareStates,cT=false,cS=cM,cP=false;cj.iter(cS,cj.size,function(cV){var cW=cV.stateAfter;if(+new Date>cR){b3.push(cS);bu(bN.workDelay);if(cT){at.push({from:cO,to:cS+1})}return(cP=true)}var cX=cV.highlight(bX,cL,bN.tabSize);if(cX){cT=true}cV.stateAfter=o(bX,cL);if(cN){if(cW&&cN(cW,cL)){return true}}else{if(cX!==false||!cW){cQ=0}else{if(++cQ>3&&(!bX.indent||bX.indent(cW,"")==bX.indent(cL,""))){return true}}}++cS});if(cP){return}if(cT){at.push({from:cO,to:cS+1})}}if(cU&&bN.onHighlightComplete){bN.onHighlightComplete(bV)}}function bu(cL){if(!b3.length){return}an.set(cL,aj(bF))}function aF(){cb=bS=cy=null;at=[];aH=false;cl=[]}function ap(){var cP=false,cM;if(aH){cP=!b1()}if(at.length){cM=bZ(at,true)}else{if(aH){a8()}if(aK){aD()}}if(cP){b1()}if(aH){cK();cz()}if(b5&&!a7&&(cb===true||(cb!==false&&aH))){cn(bS)}if(aH&&bN.matchBrackets){setTimeout(aj(function(){if(bQ){bQ();bQ=null}if(X(cI.from,cI.to)){b0(false)}}),20)}var cL=cy,cN=cl;if(aH&&bN.onCursorActivity){bN.onCursorActivity(bV)}if(cL&&bN.onChange&&bV){bN.onChange(bV,cL)}for(var cO=0;cO0&&ah.ch=this.string.length},sol:function(){return this.pos==0},peek:function(){return this.string.charAt(this.pos)},next:function(){if(this.posag},eatSpace:function(){var af=this.pos;while(/[\s\u00a0]/.test(this.string.charAt(this.pos))){++this.pos}return this.pos>af},skipToEnd:function(){this.pos=this.string.length},skipTo:function(af){var ag=this.string.indexOf(af,this.pos);if(ag>-1){this.pos=ag;return true}},backUp:function(af){this.pos-=af},column:function(){return m(this.string,this.start,this.tabSize)},indentation:function(){return m(this.string,null,this.tabSize)},match:function(ai,ag,af){if(typeof ai=="string"){function aj(ak){return af?ak.toLowerCase():ak}if(aj(this.string).indexOf(aj(ai),this.pos)==this.pos){if(ag!==false){this.pos+=ai.length}return true}}else{var ah=this.string.slice(this.pos).match(ai);if(ah&&ag!==false){this.pos+=ah[0].length}return ah}},current:function(){return this.string.slice(this.start,this.pos)}};s.StringStream=c;function F(ai,ah,af,ag){this.from=ai;this.to=ah;this.style=af;this.set=ag}F.prototype={attach:function(af){this.set.push(af)},detach:function(ag){var af=p(this.set,ag);if(af>-1){this.set.splice(af,1)}},split:function(ai,af){if(this.to<=ai&&this.to!=null){return null}var ah=this.from=aj){this.from=Math.max(ai,this.from)+ah}if(this.to!=null&&this.to>aj){this.to=aithis.from&&(aithis.from||this.from==null)){this.to=null}},isDead:function(){return this.from!=null&&this.to!=null&&this.from>=this.to},sameSet:function(af){return this.set==af.set}};function A(af){this.from=af;this.to=af;this.line=null}A.prototype={attach:function(af){this.line=af},detach:function(af){if(this.line==af){this.line=null}},split:function(ag,af){if(agthis.to},clipTo:function(ag,aj,af,ai,ah){if((ag||ajthis.to)){this.from=0;this.to=-1}else{if(this.from>aj){this.from=this.to=Math.max(ai,this.from)+ah}}},sameSet:function(af){return false},find:function(){if(!this.line||!this.line.parent){return null}return{line:T(this.line),ch:this.from}},clear:function(){if(this.line){var af=p(this.line.marked,this);if(af!=-1){this.line.marked.splice(af,1)}this.line=null}}};function e(ag,af){this.styles=af||[ag,null];this.text=ag;this.height=1;this.marked=this.gutterMarker=this.className=this.handlers=null;this.stateAfter=this.parent=this.hidden=null}e.inheritMarks=function(aj,am){var ai=new e(aj),af=am&&am.marked;if(af){for(var ah=0;ah5000){ap[am++]=this.text.slice(ao.pos);ap[am++]=null;break}}if(ap.length!=am){ap.length=am;aj=true}if(am&&ap[am-2]!=an){aj=true}return aj||(ap.length<5&&this.text.length<10?null:false)},getTokenAt:function(ak,ai,ah){var af=this.text,aj=new c(af);while(aj.pos':"
")}function az(aI,aH){if(!aI){return}if(ai&&D&&aI.charAt(0)==" "){aI="\u00a0"+aI.slice(1)}ai=false;if(aH){am.push('',K(aI).replace(/\t/g,aq),"")}else{am.push(K(aI).replace(/\t/g,aq))}}var at=this.styles,ak=this.text,ar=this.marked;if(au==ay){au=null}var aB=ak.length;if(aw!=null){aB=Math.min(aw,aB)}if(!ak&&aw==null){az(" ",au!=null&&ay==null?"CodeMirror-selected":null)}else{if(!ar&&au==null){for(var aA=0,an=0;anaB){av=av.slice(0,aB-an)}an+=ax;az(av,aC&&"cm-"+aC)}}else{var ah=0,aA=0,ap="",aC,aF=0;var aD=-1,al=null;function aE(){if(ar){aD+=1;al=(aDah){ao=au}else{if(ay==null||ay>ah){aG=" CodeMirror-selected";if(ay!=null){ao=Math.min(ao,ay)}}}}while(al&&al.to!=null&&al.to<=ah){aE()}if(al){if(al.from>ah){ao=Math.min(ao,al.from)}else{aG+=" "+al.style;if(al.to!=null){ao=Math.min(ao,al.to)}}}for(;;){var ag=ah+ap.length;var af=aC;if(aG){af=aC?aC+aG:aG}az(ag>ao?ap.slice(0,ao-ah):ap,af);if(ag>=ao){ap=ap.slice(ao-ah);ah=ao;break}ah=ag;ap=at[aA++];aC="cm-"+at[aA++]}}if(au!=null&&ay==null){az(" ","CodeMirror-selected")}}}if(aj){am.push("
")}return am.join("")},cleanUp:function(){this.parent=null;if(this.marked){for(var af=0,ag=this.marked.length;afal){an.push(ah.slice(al-ak,Math.min(ah.length,am-ak)),af[aj+1])}if(ai>=al){ag=1}}else{if(ag==1){if(ai>am){an.push(ah.slice(0,am-ak),af[aj+1])}else{an.push(ah,af[aj+1])}}}ak=ai}}function aa(ag){this.lines=ag;this.parent=null;for(var ah=0,ai=ag.length,af=0;ah50){while(af.lines.length>50){var ai=af.lines.splice(af.lines.length-25,25);var al=new aa(ai);af.height-=al.height;this.children.splice(ah+1,0,al);al.parent=this}this.maybeSpill()}break}ag-=ak}},maybeSpill:function(){if(this.children.length<=10){return}var ai=this;do{var ag=ai.children.splice(ai.children.length-5,5);var ah=new h(ag);if(!ai.parent){var aj=new h(ai.children);aj.parent=ai;ai.children=[aj,ah];ai=aj}else{ai.size-=ah.size;ai.height-=ah.height;var af=p(ai.parent.children,ai);ai.parent.children.splice(af+1,0,ah)}ah.parent=ai.parent}while(ai.children.length>10);ai.parent.maybeSpill()},iter:function(ah,ag,af){this.iterN(ah,ag-ah,af)},iterN:function(af,am,al){for(var ag=0,aj=this.children.length;ag400||!aj||aj.start>am+ah||aj.start+aj.added=0;--ag){aj.old.unshift(af[ag])}aj.added+=aj.start-am;aj.start=am}else{if(aj.start-1){d="\r\n"}}());function m(ag,af,ai){if(af==null){af=ag.search(/[^\s\u00a0]/);if(af==-1){af=ag.length}}for(var ah=0,aj=0;ah=0&&af>=0;--ag,--af){if(ai.charAt(ag)!=ah.charAt(af)){break}}return af+1}function p(ai,af){if(ai.indexOf){return ai.indexOf(af)}for(var ag=0,ah=ai.length;ag-1){af.push(ah.slice(ai,ah.charAt(ag-1)=="\r"?ag-1:ag));ai=ag+1}af.push(ah.slice(ai));return af}:function(af){return af.split(/\r?\n/)};s.splitLines=x;var Y=window.getSelection?function(ag){try{return ag.selectionStart!=ag.selectionEnd}catch(af){return false}}:function(ah){try{var af=ah.ownerDocument.selection.createRange()}catch(ag){}if(!af||af.parentElement()!=ah){return false}return af.compareEndPoints("StartToEnd",af)!=0};s.defineMode("null",function(){return{token:function(af){af.skipToEnd()}}});s.defineMIME("text/plain","null");var M={3:"Enter",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",91:"Mod",92:"Mod",93:"Mod",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",63276:"PageUp",63277:"PageDown",63275:"End",63273:"Home",63234:"Left",63232:"Up",63235:"Right",63233:"Down",63302:"Insert",63272:"Delete"};s.keyNames=M;(function(){for(var af=0;af<10;af++){M[af+48]=String(af)}for(var af=65;af<=90;af++){M[af]=String.fromCharCode(af)}for(var af=1;af<=12;af++){M[af+111]=M[af+63235]="F"+af}})();return s})();CodeMirror.defineMode("clojure",function(y,o){var s="builtin",v="comment",m="string",c="tag",g="atom",r="number",k="bracket",l="keyword";var t=2,j=1;function x(C){var A={},B=C.split(" ");for(var z=0;z ->> doto and or dosync doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars binding gen-class gen-and-load-class gen-and-save-class handler-case handle* *1 *2 *3 *agent* *allow-unresolved-vars* *assert *clojure-version* *command-line-args* *compile-files* *compile-path* *e *err* *file* *flush-on-newline* *in* *macro-meta* *math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* *source-path* *use-context-classloader* *warn-on-reflection* + - / < <= = == > >= accessor aclone agent agent-errors aget alength alias all-ns alter alter-meta! alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 bases bean bigdec bigint binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* butlast byte byte-array bytes case cast char char-array char-escape-string char-name-string char? chars chunk chunk-append chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement concat cond condp conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec decimal? declare definline defmacro defmethod defmulti defn defn- defonce defstruct delay delay? deliver deref derive descendants destructure disj disj! dissoc dissoc! distinct distinct? doall doc dorun doseq dosync dotimes doto double double-array doubles drop drop-last drop-while empty empty? ensure enumeration-seq eval even? every? extend extend-protocol extend-type extends? extenders false? ffirst file-seq filter find find-doc find-ns find-var first float float-array float? floats flush fn fn? fnext for force format future future-call future-cancel future-cancelled? future-done? future? gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator hash hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc init-proxy instance? int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array make-hierarchy map map? mapcat max max-key memfn memoize merge merge-with meta method-sig methods min min-key mod name namespace neg? newline next nfirst nil? nnext not not-any? not-empty not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias ns-unmap nth nthnext num number? odd? or parents partial partition pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers primitives-classnames print print-ctor print-doc print-dup print-method print-namespace-doc print-simple print-special-doc print-str printf println println-str prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues quot rand rand-int range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern re-seq read read-line read-string reify reduce ref ref-history-count ref-max-history ref-min-history ref-set refer refer-clojure release-pending-sends rem remove remove-method remove-ns repeat repeatedly replace replicate require reset! reset-meta! resolve rest resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? seque sequence sequential? set set-validator! set? short short-array shorts shutdown-agents slurp some sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? special-form-anchor special-symbol? split-at split-with str stream? string? struct struct-map subs subseq subvec supers swap! symbol symbol? sync syntax-symbol-anchor take take-last take-nth take-while test the-ns time to-array to-array-2d trampoline transient tree-seq true? type unchecked-add unchecked-dec unchecked-divide unchecked-inc unchecked-multiply unchecked-negate unchecked-remainder unchecked-subtract underive unquote unquote-splicing update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector? when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context with-local-vars with-meta with-open with-out-str with-precision xml-seq");var u=x("ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type try catchlet letfn binding loop for doseq dotimes when-let if-letdefstruct struct-map assoctesting deftesthandler-case handle dotrace deftrace");var f={digit:/\d/,digit_or_colon:/[\d:]/,hex:/[0-9a-fA-F]/,sign:/[+-]/,exponent:/[eE]/,keyword_char:/[^\s\(\[\;\)\]]/,basic:/[\w\$_\-]/,lang_keyword:/[\w*+!\-_?:\/]/};function e(z,A,B){this.indent=z;this.type=A;this.prev=B}function w(B,z,A){B.indentStack=new e(z,A,B.indentStack)}function q(z){z.indentStack=z.indentStack.prev}function p(z,A){if(z==="0"&&"x"==A.peek().toLowerCase()){A.eat("x");A.eatWhile(f.hex);return true}if(z=="+"||z=="-"){A.eat(f.sign);z=A.next()}if(f.digit.test(z)){A.eat(z);A.eatWhile(f.digit);if("."==A.peek()){A.eat(".");A.eatWhile(f.digit)}if("e"==A.peek().toLowerCase()){A.eat(f.exponent);A.eat(f.sign);A.eatWhile(f.digit)}return true}return false}return{startState:function(){return{indentStack:null,indentation:0,mode:false,}},token:function(E,C){if(C.indentStack==null&&E.sol()){C.indentation=E.indentation()}if(E.eatSpace()){return null}var z=null;switch(C.mode){case"string":var B,D=false;while((B=E.next())!=null){if(B=='"'&&!D){C.mode=false;break}D=!D&&B=="\\"}z=m;break;default:var A=E.next();if(A=='"'){C.mode="string";z=m}else{if(A=="'"&&!(f.digit_or_colon.test(E.peek()))){z=g}else{if(A==";"){E.skipToEnd();z=v}else{if(p(A,E)){z=r}else{if(A=="("||A=="["){var G="";var F=E.column();while((letter=E.eat(f.keyword_char))!=null){G+=letter}if(G.length>0&&u.propertyIsEnumerable(G)){w(C,F+t,A)}else{E.eatSpace();if(E.eol()||E.peek()==";"){w(C,F+1,A)}else{w(C,F+E.current().length,A)}}E.backUp(E.current().length-1);z=k}else{if(A==")"||A=="]"){z=k;if(C.indentStack!=null&&C.indentStack.type==(A==")"?"(":"[")){q(C)}}else{if(A==":"){E.eatWhile(f.lang_keyword);return c}else{E.eatWhile(f.basic);if(h&&h.propertyIsEnumerable(E.current())){z=s}else{if(d&&d.propertyIsEnumerable(E.current())){z=g}else{z=null}}}}}}}}}}return z},indent:function(A,z){if(A.indentStack==null){return A.indentation}return A.indentStack.indent}}});CodeMirror.defineMIME("text/x-clojure","clojure");CodeMirror.defineMode("xml",function(A,o){var t=A.indentUnit;var z=o.htmlMode?{autoSelfClosers:{br:true,img:true,hr:true,link:true,input:true,meta:true,col:true,frame:true,base:true,area:true},doNotIndent:{pre:true},allowUnquoted:true}:{autoSelfClosers:{},doNotIndent:{},allowUnquoted:false};var c=o.alignCDATA;var h,j;function s(F,E){function C(H){E.tokenize=H;return H(F,E)}var D=F.next();if(D=="<"){if(F.eat("!")){if(F.eat("[")){if(F.match("CDATA[")){return C(y("atom","]]>"))}else{return null}}else{if(F.match("--")){return C(y("comment","-->"))}else{if(F.match("DOCTYPE",true,true)){F.eatWhile(/[\w\._\-]/);return C(B(1))}else{return null}}}}else{if(F.eat("?")){F.eatWhile(/[\w\._\-]/);E.tokenize=y("meta","?>");return"meta"}else{j=F.eat("/")?"closeTag":"openTag";F.eatSpace();h="";var G;while((G=F.eat(/[^\s\u00a0=<>\"\'\/?]/))){h+=G}E.tokenize=r;return"tag"}}}else{if(D=="&"){F.eatWhile(/[^;]/);F.eat(";");return"atom"}else{F.eatWhile(/[^&<]/);return null}}}function r(E,D){var C=E.next();if(C==">"||(C=="/"&&E.eat(">"))){D.tokenize=s;j=C==">"?"endTag":"selfcloseTag";return"tag"}else{if(C=="="){j="equals";return null}else{if(/[\'\"]/.test(C)){D.tokenize=m(C);return D.tokenize(E,D)}else{E.eatWhile(/[^\s\u00a0=<>\"\'\/?]/);return"word"}}}}function m(C){return function(E,D){while(!E.eol()){if(E.next()==C){D.tokenize=r;break}}return"string"}}function y(D,C){return function(F,E){while(!F.eol()){if(F.match(C)){E.tokenize=s;break}F.next()}return D}}function B(C){return function(F,E){var D;while((D=F.next())!=null){if(D=="<"){E.tokenize=B(C+1);return E.tokenize(F,E)}else{if(D==">"){if(C==1){E.tokenize=s;break}else{E.tokenize=B(C-1);return E.tokenize(F,E)}}}}return"meta"}}var p,k;function d(){for(var C=arguments.length-1;C>=0;C--){p.cc.push(arguments[C])}}function g(){d.apply(null,arguments);return true}function l(C,E){var D=z.doNotIndent.hasOwnProperty(C)||(p.context&&p.context.noIndent);p.context={prev:p.context,tagName:C,indent:p.indented,startOfLine:E,noIndent:D}}function w(){if(p.context){p.context=p.context.prev}}function f(C){if(C=="openTag"){p.tagName=h;return g(q,e(p.startOfLine))}else{if(C=="closeTag"){var D=false;if(p.context){D=p.context.tagName!=h}else{D=true}if(D){k="error"}return g(u(D))}}return g()}function e(C){return function(D){if(D=="selfcloseTag"||(D=="endTag"&&z.autoSelfClosers.hasOwnProperty(p.tagName.toLowerCase()))){return g()}if(D=="endTag"){l(p.tagName,C);return g()}return g()}}function u(C){return function(D){if(C){k="error"}if(D=="endTag"){w();return g()}k="error";return g(arguments.callee)}}function q(C){if(C=="word"){k="attribute";return g(q)}if(C=="equals"){return g(x,q)}if(C=="string"){k="error";return g(q)}return d()}function x(C){if(C=="word"&&z.allowUnquoted){k="string";return g()}if(C=="string"){return g(v)}return d()}function v(C){if(C=="string"){return g(v)}else{return d()}}return{startState:function(){return{tokenize:s,cc:[],indented:0,startOfLine:true,tagName:null,context:null}},token:function(F,E){if(F.sol()){E.startOfLine=true;E.indented=F.indentation()}if(F.eatSpace()){return null}k=j=h=null;var D=E.tokenize(F,E);E.type=j;if((D||j)&&D!="comment"){p=E;while(true){var C=E.cc.pop()||f;if(C(j||D)){break}}}E.startOfLine=false;return k||D},indent:function(F,C,E){var D=F.context;if((F.tokenize!=r&&F.tokenize!=s)||D&&D.noIndent){return E?E.match(/^(\s*)/)[0].length:0}if(c&&/!?|]/;function V(Z,Y,X){Y.tokenize=X;return X(Z,Y)}function k(aa,X){var Z=false,Y;while((Y=aa.next())!=null){if(Y==X&&!Z){return false}Z=!Z&&Y=="\\"}return Z}var W,t;function F(Z,Y,X){W=Z;t=X;return Y}function p(ab,Z){var X=ab.next();if(X=='"'||X=="'"){return V(ab,Z,D(X))}else{if(/[\[\]{}\(\),;\:\.]/.test(X)){return F(X)}else{if(X=="0"&&ab.eat(/x/i)){ab.eatWhile(/[\da-f]/i);return F("number","number")}else{if(/\d/.test(X)){ab.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);return F("number","number")}else{if(X=="/"){if(ab.eat("*")){return V(ab,Z,h)}else{if(ab.eat("/")){ab.skipToEnd();return F("comment","comment")}else{if(Z.reAllowed){k(ab,"/");ab.eatWhile(/[gimy]/);return F("regexp","string")}else{ab.eatWhile(R);return F("operator",null,ab.current())}}}}else{if(X=="#"){ab.skipToEnd();return F("error","error")}else{if(R.test(X)){ab.eatWhile(R);return F("operator",null,ab.current())}else{ab.eatWhile(/[\w\$_]/);var aa=ab.current(),Y=d.propertyIsEnumerable(aa)&&d[aa];return(Y&&Z.kwAllowed)?F(Y.type,Y.style,aa):F("variable","variable",aa)}}}}}}}}function D(X){return function(Z,Y){if(!k(Z,X)){Y.tokenize=p}return F("string","string")}}function h(aa,Z){var X=false,Y;while(Y=aa.next()){if(Y=="/"&&X){Z.tokenize=p;break}X=(Y=="*")}return F("comment","comment")}var o={atom:true,number:true,variable:true,string:true,regexp:true};function x(ac,Y,X,ab,Z,aa){this.indented=ac;this.column=Y;this.type=X;this.prev=Z;this.info=aa;if(ab!=null){this.align=ab}}function A(Z,Y){for(var X=Z.localVars;X;X=X.next){if(X.name==Y){return true}}}function I(ab,Y,X,aa,ac){var ad=ab.cc;y.state=ab;y.stream=ac;y.marked=null,y.cc=ad;if(!ab.lexical.hasOwnProperty("align")){ab.lexical.align=true}while(true){var Z=ad.length?ad.pop():U?B:C;if(Z(X,aa)){while(ad.length&&ad[ad.length-1].lex){ad.pop()()}if(y.marked){return y.marked}if(X=="variable"&&A(ab,aa)){return"variable-2"}return Y}}}var y={state:null,column:null,marked:null,cc:null};function c(){for(var X=arguments.length-1;X>=0;X--){y.cc.push(arguments[X])}}function K(){c.apply(null,arguments);return true}function q(Y){var Z=y.state;if(Z.context){y.marked="def";for(var X=Z.localVars;X;X=X.next){if(X.name==Y){return}}Z.localVars={name:Y,next:Z.localVars}}}var H={name:"this",next:{name:"arguments"}};function w(){if(!y.state.context){y.state.localVars=H}y.state.context={prev:y.state.context,vars:y.state.localVars}}function v(){y.state.localVars=y.state.context.vars;y.state.context=y.state.context.prev}function m(Y,Z){var X=function(){var aa=y.state;aa.lexical=new x(aa.indented,y.stream.column(),Y,null,aa.lexical,Z)};X.lex=true;return X}function J(){var X=y.state;if(X.lexical.prev){if(X.lexical.type==")"){X.indented=X.lexical.indented}X.lexical=X.lexical.prev}}J.lex=true;function e(Y){return function X(Z){if(Z==Y){return K()}else{if(Y==";"){return c()}else{return K(arguments.callee)}}}}function C(X){if(X=="var"){return K(m("vardef"),N,e(";"),J)}if(X=="keyword a"){return K(m("form"),B,C,J)}if(X=="keyword b"){return K(m("form"),C,J)}if(X=="{"){return K(m("}"),r,J)}if(X==";"){return K()}if(X=="function"){return K(l)}if(X=="for"){return K(m("form"),e("("),m(")"),j,e(")"),J,C,J)}if(X=="variable"){return K(m("stat"),G)}if(X=="switch"){return K(m("form"),B,m("}","switch"),e("{"),r,J,J)}if(X=="case"){return K(B,e(":"))}if(X=="default"){return K(e(":"))}if(X=="catch"){return K(m("form"),w,e("("),u,e(")"),C,J,v)}return c(m("stat"),B,e(";"),J)}function B(X){if(o.hasOwnProperty(X)){return K(P)}if(X=="function"){return K(l)}if(X=="keyword c"){return K(E)}if(X=="("){return K(m(")"),B,e(")"),J,P)}if(X=="operator"){return K(B)}if(X=="["){return K(m("]"),S(B,"]"),J,P)}if(X=="{"){return K(m("}"),S(s,"}"),J,P)}return K()}function E(X){if(X.match(/[;\}\)\],]/)){return c()}return c(B)}function P(X,Y){if(X=="operator"&&/\+\+|--/.test(Y)){return K(P)}if(X=="operator"){return K(B)}if(X==";"){return}if(X=="("){return K(m(")"),S(B,")"),J,P)}if(X=="."){return K(T,P)}if(X=="["){return K(m("]"),B,e("]"),J,P)}}function G(X){if(X==":"){return K(J,C)}return c(P,e(";"),J)}function T(X){if(X=="variable"){y.marked="property";return K()}}function s(X){if(X=="variable"){y.marked="property"}if(o.hasOwnProperty(X)){return K(e(":"),B)}}function S(Z,X){function Y(ab){if(ab==","){return K(Z,Y)}if(ab==X){return K()}return K(e(X))}return function aa(ab){if(ab==X){return K()}else{return c(Z,Y)}}}function r(X){if(X=="}"){return K()}return c(C,r)}function N(X,Y){if(X=="variable"){q(Y);return K(L)}return K()}function L(X,Y){if(Y=="="){return K(B,L)}if(X==","){return K(N)}}function j(X){if(X=="var"){return K(N,g)}if(X==";"){return c(g)}if(X=="variable"){return K(O)}return c(g)}function O(X,Y){if(Y=="in"){return K(B)}return K(P,g)}function g(X,Y){if(X==";"){return K(f)}if(Y=="in"){return K(B)}return K(B,e(";"),f)}function f(X){if(X!=")"){K(B)}}function l(X,Y){if(X=="variable"){q(Y);return K(l)}if(X=="("){return K(m(")"),w,S(u,")"),J,C,v)}}function u(X,Y){if(X=="variable"){q(Y);return K()}}return{startState:function(X){return{tokenize:p,reAllowed:true,kwAllowed:true,cc:[],lexical:new x((X||0)-z,0,"block",false),localVars:null,context:null,indented:0}},token:function(Z,Y){if(Z.sol()){if(!Y.lexical.hasOwnProperty("align")){Y.lexical.align=false}Y.indented=Z.indentation()}if(Z.eatSpace()){return null}var X=Y.tokenize(Z,Y);if(W=="comment"){return X}Y.reAllowed=W=="operator"||W=="keyword c"||W.match(/^[\[{}\(,;:]$/);Y.kwAllowed=W!=".";return I(Y,X,W,t,Z)},indent:function(ac,X){if(ac.tokenize!=p){return 0}var ab=X&&X.charAt(0),Z=ac.lexical,aa=Z.type,Y=ab==aa;if(aa=="vardef"){return Z.indented+4}else{if(aa=="form"&&ab=="{"){return Z.indented}else{if(aa=="stat"||aa=="form"){return Z.indented+z}else{if(Z.info=="switch"&&!Y){return Z.indented+(/^(?:case|default)\b/.test(X)?z:2*z)}else{if(Z.align){return Z.column+(Y?0:1)}else{return Z.indented+(Y?0:z)}}}}}},electricChars:":{}"}});CodeMirror.defineMIME("text/javascript","javascript");CodeMirror.defineMIME("application/json",{name:"javascript",json:true});CodeMirror.defineMode("clike",function(e,g){var j=e.indentUnit,h=g.keywords||{},c=g.blockKeywords||{},k=g.atoms||{},t=g.hooks||{},l=g.multiLineStrings;var d=/[+\-*&%=<>!?|\/]/;var q;function f(y,w){var v=y.next();if(t[v]){var u=t[v](y,w);if(u!==false){return u}}if(v=='"'||v=="'"){w.tokenize=s(v);return w.tokenize(y,w)}if(/[\[\]{}\(\),;\:\.]/.test(v)){q=v;return null}if(/\d/.test(v)){y.eatWhile(/[\w\.]/);return"number"}if(v=="/"){if(y.eat("*")){w.tokenize=o;return o(y,w)}if(y.eat("/")){y.skipToEnd();return"comment"}}if(d.test(v)){y.eatWhile(d);return"operator"}y.eatWhile(/[\w\$_]/);var x=y.current();if(h.propertyIsEnumerable(x)){if(c.propertyIsEnumerable(x)){q="newstatement"}return"keyword"}if(k.propertyIsEnumerable(x)){return"atom"}return"word"}function s(u){return function(z,x){var y=false,w,v=false;while((w=z.next())!=null){if(w==u&&!y){v=true;break}y=!y&&w=="\\"}if(v||!(y||l)){x.tokenize=f}return"string"}}function o(x,w){var u=false,v;while(v=x.next()){if(v=="/"&&u){w.tokenize=f;break}u=(v=="*")}return"comment"}function r(y,v,u,x,w){this.indented=y;this.column=v;this.type=u;this.align=x;this.prev=w}function m(w,u,v){return w.context=new r(w.indented,u,v,null,w.context)}function p(v){var u=v.context.type;if(u==")"||u=="]"||u=="}"){v.indented=v.context.indented}return v.context=v.context.prev}return{startState:function(u){return{tokenize:null,context:new r((u||0)-j,0,"top",false),indented:0,startOfLine:true}},token:function(x,w){var u=w.context;if(x.sol()){if(u.align==null){u.align=false}w.indented=x.indentation();w.startOfLine=true}if(x.eatSpace()){return null}q=null;var v=(w.tokenize||f)(x,w);if(v=="comment"||v=="meta"){return v}if(u.align==null){u.align=true}if((q==";"||q==":")&&u.type=="statement"){p(w)}else{if(q=="{"){m(w,x.column(),"}")}else{if(q=="["){m(w,x.column(),"]")}else{if(q=="("){m(w,x.column(),")")}else{if(q=="}"){while(u.type=="statement"){u=p(w)}if(u.type=="}"){u=p(w)}while(u.type=="statement"){u=p(w)}}else{if(q==u.type){p(w)}else{if(u.type=="}"||u.type=="top"||(u.type=="statement"&&q=="newstatement")){m(w,x.column(),"statement")}}}}}}}w.startOfLine=false;return v},indent:function(y,v){if(y.tokenize!=f&&y.tokenize!=null){return 0}var u=y.context,x=v&&v.charAt(0);if(u.type=="statement"&&x=="}"){u=u.prev}var w=x==u.type;if(u.type=="statement"){return u.indented+(x=="{"?0:j)}else{if(u.align){return u.column+(w?0:1)}else{return u.indented+(w?0:j)}}},electricChars:"{}"}});(function(){function e(k){var h={},j=k.split(" ");for(var g=0;g",A))}else{if(M.eatSpace()||M.eol()){M.skipToEnd();return E}else{L.tokenize=r;return C}}}}M.skipToEnd();return E}function r(Q,P){var M=Q.pos;if(Q.match(/^[a-zA-Z_:][-a-zA-Z0-9_:.]*/)){var O=Q.string.substring(M,Q.pos);o(P,O);P.tokenize=K;return C}else{if(Q.match(/^\/[a-zA-Z_:][-a-zA-Z0-9_:.]*( )*>/)){var N=Q.string.substring(M+1,Q.pos-1).trim();var L=F(P);P.tokenize=P.context==null?A:m;if(L==null||N!=L.tagName){return E}return C}else{P.tokenize=P.context==null?A:m;Q.eatWhile(/[^>]/);Q.eat(">");return E}}Q.skipToEnd();return null}function K(M,L){if(M.match(/^\/>/)){F(L);L.tokenize=L.context==null?A:m;return C}else{if(M.eat(/^>/)){L.tokenize=m;return C}else{if(g(M)&&M.match(/^[a-zA-Z_:][-a-zA-Z0-9_:.]*( )*=/)){L.tokenize=s;return k}}}L.tokenize=L.context==null?A:A;M.eatWhile(/[^>]/);M.eat(">");return E}function s(N,M){var L=N.next();if(L!='"'&&L!="'"){N.skipToEnd();M.tokenize=K;return E}M.tokParams.quote=L;M.tokenize=h;return I}function h(N,M){var L="";while(!N.eol()){L=N.next();if(L==M.tokParams.quote){M.tokenize=K;return I}else{if(L=="<"){N.skipToEnd();M.tokenize=K;return E}else{if(L=="&"){L=N.next();if(L==";"){N.skipToEnd();M.tokenize=K;return E}while(!N.eol()&&L!=";"){if(L=="<"){N.skipToEnd();M.tokenize=K;return E}L=N.next()}if(N.eol()&&L!=";"){N.skipToEnd();M.tokenize=K;return E}}}}}return I}function m(M,L){if(M.eat("<")){if(M.match("?")){o(L,e);L.tokenize=z;return d}else{if(M.match("!--")){o(L,D);return y(M,L,H(G,"-->",L.context==null?A:m))}else{if(M.match("![CDATA[")){o(L,t);return y(M,L,H(x,"]]>",L.context==null?A:m))}else{if(M.eatSpace()||M.eol()){M.skipToEnd();return E}else{L.tokenize=r;return C}}}}}else{o(L,j);L.tokenize=w;return null}L.tokenize=L.context==null?A:m;M.skipToEnd();return null}function w(M,L){M.eatWhile(/[^<]/);if(!M.eol()){F(L);L.tokenize=m}return x}function z(M,L){if(M.match("xml",true,true)){if(L.lineNumber>1||M.pos>5){L.tokenize=A;M.skipToEnd();return E}else{L.tokenize=u;return d}}if(g(M)||M.match("?>")){L.tokenize=A;M.skipToEnd();return E}L.tokenize=l;return d}function l(M,L){M.eatWhile(/[^?]/);if(M.eat("?")){if(M.eat(">")){F(L);L.tokenize=L.context==null?A:m}}return d}function u(M,L){L.tokenize=q;if(g(M)&&M.match(/^version( )*=( )*"([a-zA-Z0-9_.:]|\-)+"/)){return d}M.skipToEnd();return E}function q(M,L){L.tokenize=B;if(g(M)&&M.match(/^encoding( )*=( )*"[A-Za-z]([A-Za-z0-9._]|\-)*"/)){return d}return null}function B(M,L){L.tokenize=f;if(g(M)&&M.match(/^standalone( )*=( )*"(yes|no)"/)){return d}return null}function f(M,L){L.tokenize=A;if(M.match("?>")&&M.eol()){F(L);return d}M.skipToEnd();return E}return{electricChars:"/[",startState:function(){return{tokenize:A,tokParams:{},lineNumber:0,lineError:false,context:null,indented:0}},token:function(N,M){if(N.sol()){M.lineNumber++;M.lineError=false;M.indented=N.indentation()}if(N.eatSpace()){return null}var L=M.tokenize(N,M);M.lineError=(M.lineError||L=="error");return L},blankLine:function(L){L.lineNumber++;L.lineError=false},indent:function(M,L){if(M.context){if(M.context.noIndent==true){return}if(L.match(/^<\/.*/)){return M.context.indent}if(L.match(/^*\/]/.test(l)){return e(null,"select-op")}else{if(/[;{}:\[\]]/.test(l)){return e(null,l)}else{o.eatWhile(/[\w\\\-]/);return e("variable","variable")}}}}}}}}}}}}function c(p,o){var l=false,m;while((m=p.next())!=null){if(l&&m=="/"){o.tokenize=k;break}l=(m=="*")}return e("comment","comment")}function d(p,o){var m=0,l;while((l=p.next())!=null){if(m>=2&&l==">"){o.tokenize=k;break}m=(l=="-")?m+1:0}return e("comment","comment")}function j(l){return function(q,o){var p=false,m;while((m=q.next())!=null){if(m==l&&!p){break}p=!p&&m=="\\"}if(!p){o.tokenize=k}return e("string","string")}}return{startState:function(l){return{tokenize:k,baseIndent:l||0,stack:[]}},token:function(p,o){if(p.eatSpace()){return null}var m=o.tokenize(p,o);var l=o.stack[o.stack.length-1];if(h=="hash"&&l=="rule"){m="atom"}else{if(m=="variable"){if(l=="rule"){m="number"}else{if(!l||l=="@media{"){m="tag"}}}}if(l=="rule"&&/^[\{\};]$/.test(h)){o.stack.pop()}if(h=="{"){if(l=="@media"){o.stack[o.stack.length-1]="@media{"}else{o.stack.push("{")}}else{if(h=="}"){o.stack.pop()}else{if(h=="@media"){o.stack.push("@media")}else{if(l=="{"&&h!="comment"){o.stack.push("rule")}}}}return m},indent:function(m,l){var o=m.stack.length;if(/^\}/.test(l)){o-=m.stack[m.stack.length-1]=="rule"?2:1}return m.baseIndent+o*f},electricChars:"}"}});CodeMirror.defineMIME("text/css","css");(function(){function e(j){var g={},h=j.split(" ");for(var f=0;f/;p.mode="php"}else{if(o=="tag"&&q.current()==">"&&p.curState.context){if(/^script$/i.test(p.curState.context.tagName)){p.curMode=l;p.curState=l.startState(m.indent(p.curState,""));p.curClose=/^<\/\s*script\s*>/i;p.mode="javascript"}else{if(/^style$/i.test(p.curState.context.tagName)){p.curMode=j;p.curState=j.startState(m.indent(p.curState,""));p.curClose=/^<\/\s*style\s*>/i;p.mode="css"}}}}return o}else{if(q.match(p.curClose,false)){p.curMode=m;p.curState=p.html;p.curClose=null;p.mode="html";return g(q,p)}else{return p.curMode.token(q,p.curState)}}}return{startState:function(){var o=m.startState();return{html:o,php:f.startState(),curMode:k.startOpen?f:m,curState:k.startOpen?f.startState():o,curClose:k.startOpen?/^\?>/:null,mode:k.startOpen?"php":"html"}},copyState:function(r){var p=r.html,q=CodeMirror.copyState(m,p),t=r.php,o=CodeMirror.copyState(f,t),s;if(r.curState==p){s=q}else{if(r.curState==t){s=o}else{s=CodeMirror.copyState(r.curMode,r.curState)}}return{html:q,php:o,curMode:r.curMode,curState:s,curClose:r.curClose}},token:g,indent:function(p,o){if((p.curMode!=f&&/^\s*<\//.test(o))||(p.curMode==f&&/^\?>/.test(o))){return m.indent(p.html,o)}return p.curMode.indent(p.curState,o)},electricChars:"/{}:"}});CodeMirror.defineMIME("application/x-httpd-php","php");CodeMirror.defineMIME("application/x-httpd-php-open",{name:"php",startOpen:true});CodeMirror.defineMIME("text/x-php",d)})();CodeMirror.defineMode("htmlmixed",function(d,f){var c=CodeMirror.getMode(d,{name:"xml",htmlMode:true});var e=CodeMirror.getMode(d,"javascript");var l=CodeMirror.getMode(d,"css");function g(p,o){var m=c.token(p,o.htmlState);if(m=="tag"&&p.current()==">"&&o.htmlState.context){if(/^script$/i.test(o.htmlState.context.tagName)){o.token=k;o.localState=e.startState(c.indent(o.htmlState,""));o.mode="javascript"}else{if(/^style$/i.test(o.htmlState.context.tagName)){o.token=h;o.localState=l.startState(c.indent(o.htmlState,""));o.mode="css"}}}return m}function j(r,m,o){var q=r.current();var p=q.search(m);if(p>-1){r.backUp(q.length-p)}return o}function k(o,m){if(o.match(/^<\/\s*script\s*>/i,false)){m.token=g;m.curState=null;m.mode="html";return g(o,m)}return j(o,/<\/\s*script\s*>/,e.token(o,m.localState))}function h(o,m){if(o.match(/^<\/\s*style\s*>/i,false)){m.token=g;m.localState=null;m.mode="html";return g(o,m)}return j(o,/<\/\s*style\s*>/,l.token(o,m.localState))}return{startState:function(){var m=c.startState();return{token:g,localState:null,mode:"html",htmlState:m}},copyState:function(o){if(o.localState){var m=CodeMirror.copyState(o.token==h?l:e,o.localState)}return{token:o.token,localState:m,mode:o.mode,htmlState:CodeMirror.copyState(c,o.htmlState)}},token:function(o,m){return m.token(o,m)},indent:function(o,m){if(o.token==g||/^\s*<\//.test(m)){return c.indent(o.htmlState,m)}else{if(o.token==k){return e.indent(o.localState,m)}else{return l.indent(o.localState,m)}}},compareStates:function(o,m){return c.compareStates(o.htmlState,m.htmlState)},electricChars:"/{}:"}});CodeMirror.defineMIME("text/html","htmlmixed");CodeMirror.defineMode("rst",function(G,h){function x(K,J,I){K.fn=J;z(K,I)}function z(J,I){J.ctx=I||{}}function y(J,I){if(I&&(typeof I!=="string")){var K=I.current();I=K[K.length-1]}x(J,H,{back:I})}function o(K){if(K){var J=CodeMirror.listModes();for(var I in J){if(J[I]==K){return true}}}return false}function e(I){if(o(I)){return CodeMirror.getMode(G,I)}else{return null}}var C=e(h.verbatim);var u=e("python");var w=/^[!"#$%&'()*+,-./:;<=>?@[\\\]^_`{|}~]/;var k=/^\s*\w([-:.\w]*\w)?::(\s|$)/;var c=/^\s*_[\w-]+:(\s|$)/;var l=/^\s*\[(\d+|#)\](\s|$)/;var E=/^\s*\[[A-Za-z][\w-]*\](\s|$)/;var D=/^\[(\d+|#)\]_/;var m=/^\[[A-Za-z][\w-]*\]_/;var A=/^\.\.(\s|$)/;var t=/^::\s*$/;var f=/^[-\s"([{/:.,;!?\\_]/;var v=/^\s*((\d+|[A-Za-z#])[.)]|\((\d+|[A-Z-a-z#])\))\s/;var B=/^\s*[-\+\*]\s/;var q=/^\s+(>>>|In \[\d+\]:)\s/;function H(T,J){var I,R,N;if(T.eat(/\\/)){I=T.next();y(J,I);return null}R=T.sol();if(R&&(I=T.eat(w))){for(N=0;T.eat(I);N++){}if(N>=3&&T.match(/^\s*$/)){y(J,null);return"header"}else{T.backUp(N+1)}}if(R&&T.match(A)){if(!T.eol()){x(J,s)}return"meta"}if(T.match(t)){if(!C){x(J,F)}else{var O=C;x(J,F,{mode:O,local:O.startState()})}return"meta"}if(R&&T.match(q,false)){if(!u){x(J,F);return"meta"}else{var O=u;x(J,F,{mode:O,local:O.startState()});return null}}function Q(U){return R||!J.ctx.back||U.test(J.ctx.back)}function K(U){return T.eol()||T.match(U,false)}function M(U){return T.match(U)&&Q(/\W/)&&K(/\W/)}if(M(D)){y(J,T);return"footnote"}if(M(m)){y(J,T);return"citation"}I=T.next();if(Q(f)){if((I===":"||I==="|")&&T.eat(/\S/)){var L;if(I===":"){L="builtin"}else{L="atom"}x(J,g,{ch:I,wide:false,prev:null,token:L});return L}if(I==="*"||I==="`"){var S=I,P=false;I=T.next();if(I==S){P=true;I=T.next()}if(I&&!/\s/.test(I)){var L;if(S==="*"){L=P?"strong":"em"}else{L=P?"string":"string-2"}x(J,g,{ch:S,wide:P,prev:null,token:L});return L}}}y(J,I);return null}function g(M,L){var K=M.next(),J=L.ctx.token;function I(N){L.ctx.prev=N;return J}if(K!=L.ctx.ch){return I(K)}if(/\s/.test(L.ctx.prev)){return I(K)}if(L.ctx.wide){K=M.next();if(K!=L.ctx.ch){return I(K)}}if(!M.eol()&&!j.test(M.peek())){if(L.ctx.wide){M.backUp(1)}return I(K)}x(L,H);y(L,K);return J}function s(K,J){var I=null;if(K.match(k)){I="attribute"}else{if(K.match(c)){I="link"}else{if(K.match(l)){I="quote"}else{if(K.match(E)){I="quote"}else{K.eatSpace();if(K.eol()){y(J,K);return null}else{K.skipToEnd();x(J,d);return"comment"}}}}}x(J,r,{start:true});return I}function r(K,J){var I="body";if(!J.ctx.start||K.sol()){return p(K,J,I)}K.skipToEnd();z(J);return I}function d(J,I){return p(J,I,"comment")}function F(J,I){if(!C){return p(J,I,"meta")}else{if(J.sol()){if(!J.eatSpace()){y(I,J)}return null}return C.token(J,I.ctx.local)}}function p(K,J,I){if(K.eol()||K.eatSpace()){K.skipToEnd();return I}else{y(J,K);return null}}return{startState:function(){return{fn:H,ctx:{}}},copyState:function(I){return{fn:I.fn,ctx:I.ctx}},token:function(K,J){var I=J.fn(K,J);return I}}});CodeMirror.defineMIME("text/x-rst","rst");Ext.BLANK_IMAGE_URL="js/ExtJs/resources/images/default/s.gif";String.prototype.ucFirst=function(){return this.substr(0,1).toUpperCase()+this.substr(1,this.length)};Ext.override(Ext.grid.CheckboxSelectionModel,{handleMouseDown:function(h,k,j){if(j.button!==0||this.isLocked()){return}var c=this.grid.getView();if(j.shiftKey&&this.last!==false){var f=this.last;this.selectRange(f,k,j.ctrlKey);this.last=f;c.focusRow(k)}else{var d=this.isSelected(k);if(d){this.deselectRow(k)}else{if(!d){this.selectRow(k,!this.singleSelect);c.focusRow(k)}}}}});function log(){if(console){console.log.apply(this,arguments)}}function _(c){try{var f=i18n[c];if(f===undefined){f=c;log("FIX ME : i18n not found for the string: "+c)}return f}catch(d){return c}}function XHR(e){var d=e.success,f=e.failure,c=e.callback;e.url="./do/"+e.params.task;delete e.params.task;e.params=Ext.applyIf({csrfToken:csrfToken},e.params);e.failure=e.success=Ext.emptyFn;e.callback=function(h,l,g){var k=null;try{k=Ext.decode(g.responseText)}catch(j){log("Invalid XHR JSON Response:"+g.responseText)}if(l&&k&&k.success){if(d!==undefined){Ext.callback(d,e.scope,[g,h])}}else{if(f!==undefined){Ext.callback(f,e.scope,[g,h])}}if(c!==undefined){Ext.callback(c,e.scope,[h,l,g])}};Ext.Ajax.request(e)}Ext.override(Ext.form.Field,{afterRender:function(){var d=function(g){var f=null;var e=null;f=g.getEl().up("div.x-form-item");if(f){e=f.child("label")}if(e){return e}};if(this.tooltipText){var c=d(this);if(c){c.addClass(this.tooltipClass||"x-textfield-tooltip");new Ext.ToolTip({target:c,html:this.tooltipText,trackMouse:true})}}Ext.form.Field.superclass.afterRender.call(this);this.initEvents();this.initValue()}}); -/* +/*! * Ext JS Library 3.2.0 * Copyright(c) 2006-2010 Ext JS, Inc. * licensing@extjs.com * http://www.extjs.com/license */ Ext.ux.PortalColumn=Ext.extend(Ext.Container,{layout:"anchor",defaultType:"portlet",cls:"x-portal-column"});Ext.reg("portalcolumn",Ext.ux.PortalColumn); -/* +/*! * Ext JS Library 3.2.0 * Copyright(c) 2006-2010 Ext JS, Inc. * licensing@extjs.com * http://www.extjs.com/license */ Ext.ux.Portal=Ext.extend(Ext.Panel,{layout:"column",autoScroll:true,cls:"x-portal",defaultType:"portalcolumn",initComponent:function(){Ext.ux.Portal.superclass.initComponent.call(this);this.addEvents({validatedrop:true,beforedragover:true,dragover:true,beforedrop:true,drop:true})},initEvents:function(){Ext.ux.Portal.superclass.initEvents.call(this);this.dd=new Ext.ux.Portal.DropZone(this,this.dropConfig)},beforeDestroy:function(){if(this.dd){this.dd.unreg()}Ext.ux.Portal.superclass.beforeDestroy.call(this)}});Ext.reg("portal",Ext.ux.Portal);Ext.ux.Portal.DropZone=function(c,d){this.portal=c;Ext.dd.ScrollManager.register(c.body);Ext.ux.Portal.DropZone.superclass.constructor.call(this,c.bwrap.dom,d);c.body.ddScrollConfig=this.ddScrollConfig};Ext.extend(Ext.ux.Portal.DropZone,Ext.dd.DropTarget,{ddScrollConfig:{vthresh:50,hthresh:-1,animate:true,increment:200},createEvent:function(d,h,g,f,k,j){return{portal:this.portal,panel:g.panel,columnIndex:f,column:k,position:j,data:g,source:d,rawEvent:h,status:this.dropAllowed}},notifyOver:function(z,x,A){var j=x.getXY(),d=this.portal,s=z.proxy;if(!this.grid){this.grid=this.getGrid()}var f=d.body.dom.clientWidth;if(!this.lastCW){this.lastCW=f}else{if(this.lastCW!=f){this.lastCW=f;d.doLayout();this.grid=this.getGrid()}}var g=0,q=this.grid.columnX,r=false;for(var w=q.length;gj[1]){o=true;break}}}l=(o&&u?l:y.items.getCount())+(m?-1:0);var k=this.createEvent(z,x,A,g,y,l);if(d.fireEvent("validatedrop",k)!==false&&d.fireEvent("beforedragover",k)!==false){s.getProxy().setWidth("auto");if(u){s.moveProxy(u.el.dom.parentNode,o?u.el.dom:null)}else{s.moveProxy(y.el.dom,null)}this.lastPos={c:y,col:g,p:m||(o&&u)?l:false};this.scrollPos=d.body.getScroll();d.fireEvent("dragover",k);return k.status}else{return k.status}},notifyOut:function(){delete this.grid},notifyDrop:function(o,j,h){delete this.grid;if(!this.lastPos){return}var l=this.lastPos.c,g=this.lastPos.col,m=this.lastPos.p;var f=this.createEvent(o,j,h,g,l,m!==false?m:l.items.getCount());if(this.portal.fireEvent("validatedrop",f)!==false&&this.portal.fireEvent("beforedrop",f)!==false){o.proxy.getProxy().remove();o.panel.el.dom.parentNode.removeChild(o.panel.el.dom);if(m!==false){if(l==o.panel.ownerCt&&(l.items.items.indexOf(o.panel)<=m)){m++}l.insert(m,o.panel)}else{l.add(o.panel)}l.doLayout();this.portal.fireEvent("drop",f);var p=this.scrollPos.top;if(p){var k=this.portal.body.dom;setTimeout(function(){k.scrollTop=p},10)}}delete this.lastPos},getGrid:function(){var c=this.portal.bwrap.getBox();c.columnX=[];this.portal.items.each(function(d){c.columnX.push({x:d.el.getX(),w:d.el.getWidth()})});return c},unreg:function(){Ext.ux.Portal.DropZone.superclass.unreg.call(this)}}); -/* +/*! * Ext JS Library 3.2.0 * Copyright(c) 2006-2010 Ext JS, Inc. * licensing@extjs.com * http://www.extjs.com/license */ Ext.ux.Portlet=Ext.extend(Ext.Panel,{anchor:"100%",frame:true,collapsible:true,draggable:true,cls:"x-portlet"});Ext.reg("portlet",Ext.ux.Portlet); -/* +/*! * Ext JS Library 3.3.1 * Copyright(c) 2006-2010 Sencha Inc. * licensing@sencha.com * http://www.sencha.com/license */ Ext.ns("Ext.ux.grid");Ext.ux.grid.RowEditor=Ext.extend(Ext.Panel,{floating:true,shadow:false,layout:"hbox",cls:"x-small-editor",buttonAlign:"center",baseCls:"x-row-editor",elements:"header,footer,body",frameWidth:5,buttonPad:3,clicksToEdit:"auto",monitorValid:true,focusDelay:250,errorSummary:true,saveText:"Save",cancelText:"Cancel",commitChangesText:"You need to commit or cancel your changes",errorText:"Errors",defaults:{normalWidth:true},initComponent:function(){Ext.ux.grid.RowEditor.superclass.initComponent.call(this);this.addEvents("beforeedit","canceledit","validateedit","afteredit")},init:function(c){this.grid=c;this.ownerCt=c;if(this.clicksToEdit===2){c.on("rowdblclick",this.onRowDblClick,this)}else{c.on("rowclick",this.onRowClick,this);if(Ext.isIE){c.on("rowdblclick",this.onRowDblClick,this)}}c.getStore().on("remove",function(){this.stopEditing(false)},this);c.on({scope:this,keydown:this.onGridKey,columnresize:this.verifyLayout,columnmove:this.refreshFields,reconfigure:this.refreshFields,beforedestroy:this.beforedestroy,destroy:this.destroy,bodyscroll:{buffer:250,fn:this.positionButtons}});c.getColumnModel().on("hiddenchange",this.verifyLayout,this,{delay:1});c.getView().on("refresh",this.stopEditing.createDelegate(this,[]))},beforedestroy:function(){this.stopMonitoring();this.grid.getStore().un("remove",this.onStoreRemove,this);this.stopEditing(false);Ext.destroy(this.btns,this.tooltip)},refreshFields:function(){this.initFields();this.verifyLayout()},isDirty:function(){var c;this.items.each(function(d){if(String(this.values[d.id])!==String(d.getValue())){c=true;return false}},this);return c},startEditing:function(m,s){if(this.editing&&this.isDirty()){this.showTooltip(this.commitChangesText);return}if(Ext.isObject(m)){m=this.grid.getStore().indexOf(m)}if(this.fireEvent("beforeedit",this,m)!==false){this.editing=true;var j=this.grid,o=j.getView(),r=o.getRow(m),e=j.store.getAt(m);this.record=e;this.rowIndex=m;this.values={};if(!this.rendered){this.render(o.getEditorParent())}var p=Ext.fly(r).getWidth();this.setSize(p);if(!this.initialized){this.initFields()}var q=j.getColumnModel(),h=this.items.items,l,c;for(var d=0,k=q.getColumnCount();d=k){f=e;break}}}return f},startMonitoring:function(){if(!this.bound&&this.monitorValid){this.bound=true;Ext.TaskMgr.start({run:this.bindHandler,interval:this.monitorPoll||200,scope:this})}},stopMonitoring:function(){this.bound=false;if(this.tooltip){this.tooltip.hide()}},isValid:function(){var c=true;this.items.each(function(d){if(!d.isValid(true)){c=false;return false}});return c},bindHandler:function(){if(!this.bound){return false}var c=this.isValid();if(!c&&this.errorSummary){this.showTooltip(this.getErrorText().join(""))}this.btns.saveBtn.setDisabled(!c);this.fireEvent("validation",this,c)},lastVisibleColumn:function(){var d=this.items.getCount()-1,e;for(;d>=0;d--){e=this.items.items[d];if(!e.hidden){return e}}},showTooltip:function(j){var e=this.tooltip;if(!e){e=this.tooltip=new Ext.ToolTip({maxWidth:600,cls:"errorTip",width:300,title:this.errorText,autoHide:false,anchor:"left",anchorToTarget:true,mouseOffset:[40,0]})}var d=this.grid.getView(),g=parseInt(this.el.dom.style.top,10),c=d.scroller.dom.scrollTop,f=this.el.getHeight();if(g+f>=c){e.initTarget(this.lastVisibleColumn().getEl());if(!e.rendered){e.show();e.hide()}e.body.update(j);e.doAutoWidth(20);e.show()}else{if(e.rendered){e.hide()}}},getErrorText:function(){var c=["
    "];this.items.each(function(d){if(!d.isValid(true)){c.push("
  • ",d.getActiveError(),"
  • ")}});c.push("
");return c}});Ext.preg("roweditor",Ext.ux.grid.RowEditor); -/* +/*! * Ext JS Library 3.2.0 * Copyright(c) 2006-2010 Ext JS, Inc. * licensing@extjs.com * http://www.extjs.com/license */ Ext.ns("Ext.ux.form");Ext.ux.form.SpinnerField=Ext.extend(Ext.form.NumberField,{actionMode:"wrap",deferHeight:true,autoSize:Ext.emptyFn,onBlur:Ext.emptyFn,adjustSize:Ext.BoxComponent.prototype.adjustSize,constructor:function(e){var d=Ext.copyTo({},e,"incrementValue,alternateIncrementValue,accelerate,defaultValue,triggerClass,splitterClass");var f=this.spinner=new Ext.ux.Spinner(d);var c=e.plugins?(Ext.isArray(e.plugins)?e.plugins.push(f):[e.plugins,f]):f;Ext.ux.form.SpinnerField.superclass.constructor.call(this,Ext.apply(e,{plugins:c}))},getResizeEl:function(){return this.wrap},getPositionEl:function(){return this.wrap},alignErrorIcon:function(){if(this.wrap){this.errorIcon.alignTo(this.wrap,"tl-tr",[2,0])}},validateBlur:function(){return true}});Ext.reg("spinnerfield",Ext.ux.form.SpinnerField);Ext.form.SpinnerField=Ext.ux.form.SpinnerField; -/* +/*! * Ext JS Library 3.2.0 * Copyright(c) 2006-2010 Ext JS, Inc. * licensing@extjs.com * http://www.extjs.com/license */ Ext.ux.Spinner=Ext.extend(Ext.util.Observable,{incrementValue:1,alternateIncrementValue:5,triggerClass:"x-form-spinner-trigger",splitterClass:"x-form-spinner-splitter",alternateKey:Ext.EventObject.shiftKey,defaultValue:0,accelerate:false,constructor:function(c){Ext.ux.Spinner.superclass.constructor.call(this,c);Ext.apply(this,c);this.mimicing=false},init:function(c){this.field=c;c.afterMethod("onRender",this.doRender,this);c.afterMethod("onEnable",this.doEnable,this);c.afterMethod("onDisable",this.doDisable,this);c.afterMethod("afterRender",this.doAfterRender,this);c.afterMethod("onResize",this.doResize,this);c.afterMethod("onFocus",this.doFocus,this);c.beforeMethod("onDestroy",this.doDestroy,this)},doRender:function(d,c){var e=this.el=this.field.getEl();var g=this.field;if(!g.wrap){g.wrap=this.wrap=e.wrap({cls:"x-form-field-wrap"})}else{this.wrap=g.wrap.addClass("x-form-field-wrap")}this.trigger=this.wrap.createChild({tag:"img",src:Ext.BLANK_IMAGE_URL,cls:"x-form-trigger "+this.triggerClass});if(!g.width){this.wrap.setWidth(e.getWidth()+this.trigger.getWidth())}this.splitter=this.wrap.createChild({tag:"div",cls:this.splitterClass,style:"width:13px; height:2px;"});this.splitter.setRight((Ext.isIE)?1:2).setTop(10).show();this.proxy=this.trigger.createProxy("",this.splitter,true);this.proxy.addClass("x-form-spinner-proxy");this.proxy.setStyle("left","0px");this.proxy.setSize(14,1);this.proxy.hide();this.dd=new Ext.dd.DDProxy(this.splitter.dom.id,"SpinnerDrag",{dragElId:this.proxy.id});this.initTrigger();this.initSpinner()},doAfterRender:function(){var c;if(Ext.isIE&&this.el.getY()!=(c=this.trigger.getY())){this.el.position();this.el.setY(c)}},doEnable:function(){if(this.wrap){this.wrap.removeClass(this.field.disabledClass)}},doDisable:function(){if(this.wrap){this.wrap.addClass(this.field.disabledClass);this.el.removeClass(this.field.disabledClass)}},doResize:function(c,d){if(typeof c=="number"){this.el.setWidth(c-this.trigger.getWidth())}this.wrap.setWidth(this.el.getWidth()+this.trigger.getWidth())},doFocus:function(){if(!this.mimicing){this.wrap.addClass("x-trigger-wrap-focus");this.mimicing=true;Ext.get(Ext.isIE?document.body:document).on("mousedown",this.mimicBlur,this,{delay:10});this.el.on("keydown",this.checkTab,this)}},checkTab:function(c){if(c.getKey()==c.TAB){this.triggerBlur()}},mimicBlur:function(c){if(!this.wrap.contains(c.target)&&this.field.validateBlur(c)){this.triggerBlur()}},triggerBlur:function(){this.mimicing=false;Ext.get(Ext.isIE?document.body:document).un("mousedown",this.mimicBlur,this);this.el.un("keydown",this.checkTab,this);this.field.beforeBlur();this.wrap.removeClass("x-trigger-wrap-focus");this.field.onBlur.call(this.field)},initTrigger:function(){this.trigger.addClassOnOver("x-form-trigger-over");this.trigger.addClassOnClick("x-form-trigger-click")},initSpinner:function(){this.field.addEvents({spin:true,spinup:true,spindown:true});this.keyNav=new Ext.KeyNav(this.el,{up:function(c){c.preventDefault();this.onSpinUp()},down:function(c){c.preventDefault();this.onSpinDown()},pageUp:function(c){c.preventDefault();this.onSpinUpAlternate()},pageDown:function(c){c.preventDefault();this.onSpinDownAlternate()},scope:this});this.repeater=new Ext.util.ClickRepeater(this.trigger,{accelerate:this.accelerate});this.field.mon(this.repeater,"click",this.onTriggerClick,this,{preventDefault:true});this.field.mon(this.trigger,{mouseover:this.onMouseOver,mouseout:this.onMouseOut,mousemove:this.onMouseMove,mousedown:this.onMouseDown,mouseup:this.onMouseUp,scope:this,preventDefault:true});this.field.mon(this.wrap,"mousewheel",this.handleMouseWheel,this);this.dd.setXConstraint(0,0,10);this.dd.setYConstraint(1500,1500,10);this.dd.endDrag=this.endDrag.createDelegate(this);this.dd.startDrag=this.startDrag.createDelegate(this);this.dd.onDrag=this.onDrag.createDelegate(this)},onMouseOver:function(){if(this.disabled){return}var c=this.getMiddle();this.tmpHoverClass=(Ext.EventObject.getPageY()c)&&this.tmpHoverClass=="x-form-spinner-overup")||((Ext.EventObject.getPageY()0){this.onSpinUp();c.stopEvent()}else{if(d<0){this.onSpinDown();c.stopEvent()}}},startDrag:function(){this.proxy.show();this._previousY=Ext.fly(this.dd.getDragEl()).getTop()},endDrag:function(){this.proxy.hide()},onDrag:function(){if(this.disabled){return}var d=Ext.fly(this.dd.getDragEl()).getTop();var c="";if(this._previousY>d){c="Up"}if(this._previousYthis.field.maxValue){c=this.field.maxValue}return this.fixPrecision(c)},fixPrecision:function(d){var c=isNaN(d);if(!this.field.allowDecimals||this.field.decimalPrecision==-1||c||!d){return c?"":d}return parseFloat(parseFloat(d).toFixed(this.field.decimalPrecision))},doDestroy:function(){if(this.trigger){this.trigger.remove()}if(this.wrap){this.wrap.remove();delete this.field.wrap}if(this.splitter){this.splitter.remove()}if(this.dd){this.dd.unreg();this.dd=null}if(this.proxy){this.proxy.remove()}if(this.repeater){this.repeater.purgeListeners()}}});Ext.form.Spinner=Ext.ux.Spinner; -/* +/*! * Ext JS Library 3.2.0 * Copyright(c) 2006-2010 Ext JS, Inc. * licensing@extjs.com * http://www.extjs.com/license */ Ext.ux.StatusBar=Ext.extend(Ext.Toolbar,{cls:"x-statusbar",busyIconCls:"x-status-busy",busyText:"Loading...",autoClear:5000,emptyText:" ",activeThreadId:0,initComponent:function(){if(this.statusAlign=="right"){this.cls+=" x-status-right"}Ext.ux.StatusBar.superclass.initComponent.call(this)},afterRender:function(){Ext.ux.StatusBar.superclass.afterRender.call(this);var c=this.statusAlign=="right";this.currIconCls=this.iconCls||this.defaultIconCls;this.statusEl=new Ext.Toolbar.TextItem({cls:"x-status-text "+(this.currIconCls||""),text:this.text||this.defaultText||""});if(c){this.add("->");this.add(this.statusEl)}else{this.insert(0,this.statusEl);this.insert(1,"->")}this.doLayout()},setStatus:function(f){f=f||{};if(typeof f=="string"){f={text:f}}if(f.text!==undefined){this.setText(f.text)}if(f.iconCls!==undefined){this.setIcon(f.iconCls)}if(f.clear){var g=f.clear,e=this.autoClear,d={useDefaults:true,anim:true};if(typeof g=="object"){g=Ext.applyIf(g,d);if(g.wait){e=g.wait}}else{if(typeof g=="number"){e=g;g=d}else{if(typeof g=="boolean"){g=d}}}g.threadId=this.activeThreadId;this.clearStatus.defer(e,this,[g])}return this},clearStatus:function(e){e=e||{};if(e.threadId&&e.threadId!==this.activeThreadId){return this}var d=e.useDefaults?this.defaultText:this.emptyText,c=e.useDefaults?(this.defaultIconCls?this.defaultIconCls:""):"";if(e.anim){this.statusEl.el.fadeOut({remove:false,useDisplay:true,scope:this,callback:function(){this.setStatus({text:d,iconCls:c});this.statusEl.el.show()}})}else{this.statusEl.hide();this.setStatus({text:d,iconCls:c});this.statusEl.show()}return this},setText:function(c){this.activeThreadId++;this.text=c||"";if(this.rendered){this.statusEl.setText(this.text)}return this},getText:function(){return this.text},setIcon:function(c){this.activeThreadId++;c=c||"";if(this.rendered){if(this.currIconCls){this.statusEl.removeClass(this.currIconCls);this.currIconCls=null}if(c.length>0){this.statusEl.addClass(c);this.currIconCls=c}}else{this.currIconCls=c}return this},showBusy:function(c){if(typeof c=="string"){c={text:c}}c=Ext.applyIf(c||{},{text:this.busyText,iconCls:this.busyIconCls});return this.setStatus(c)}});Ext.reg("statusbar",Ext.ux.StatusBar); -/* +/*! * Ext JS Library 3.2.0 * Copyright(c) 2006-2010 Ext JS, Inc. * licensing@extjs.com * http://www.extjs.com/license */ Ext.ux.TabCloseMenu=Ext.extend(Object,{closeTabText:_("Close Tab"),closeOtherTabsText:_("Close Other Tabs"),showCloseAll:true,closeAllTabsText:_("Close All Tabs"),constructor:function(c){Ext.apply(this,c||{})},init:function(c){this.tabs=c;c.on({scope:this,contextmenu:this.onContextMenu,destroy:this.destroy})},destroy:function(){Ext.destroy(this.menu);delete this.menu;delete this.tabs;delete this.active},onContextMenu:function(d,f,j){this.active=f;var c=this.createMenu(),g=true,k=true,h=c.getComponent("closeall");c.getComponent("close").setDisabled(!f.closable);d.items.each(function(){if(this.closable){g=false;if(this!=f){k=false;return false}}});c.getComponent("closeothers").setDisabled(k);if(h){h.setDisabled(g)}j.stopEvent();c.showAt(j.getPoint())},createMenu:function(){if(!this.menu){var c=[{itemId:"close",text:this.closeTabText,scope:this,handler:this.onClose}];if(this.showCloseAll){c.push("-")}c.push({itemId:"closeothers",iconCls:"iconCloseOthersTabs",text:this.closeOtherTabsText,scope:this,handler:this.onCloseOthers});if(this.showCloseAll){c.push({itemId:"closeall",text:this.closeAllTabsText,scope:this,handler:this.onCloseAll})}this.menu=new Ext.menu.Menu({items:c})}return this.menu},onClose:function(){this.tabs.remove(this.active)},onCloseOthers:function(){this.doClose(true)},onCloseAll:function(){this.doClose(false)},doClose:function(d){var c=[];this.tabs.items.each(function(e){if(e.closable){if(!d||e!=this.active){c.push(e)}}},this);Ext.each(c,function(e){this.tabs.remove(e)},this)}});Ext.preg("tabclosemenu",Ext.ux.TabCloseMenu); -/* +/*! * Ext JS Library 3.2.0 * Copyright(c) 2006-2010 Ext JS, Inc. * licensing@extjs.com * http://www.extjs.com/license */ Ext.ns("Ext.ux.tree");Ext.ux.tree.TreeGridSorter=Ext.extend(Ext.tree.TreeSorter,{sortClasses:["sort-asc","sort-desc"],sortAscText:"Sort Ascending",sortDescText:"Sort Descending",constructor:function(c,d){if(!Ext.isObject(d)){d={property:c.columns[0].dataIndex||"text",folderSort:true}}Ext.ux.tree.TreeGridSorter.superclass.constructor.apply(this,arguments);this.tree=c;c.on("headerclick",this.onHeaderClick,this);c.ddAppendOnly=true;me=this;this.defaultSortFn=function(m,l){var h=me.dir&&me.dir.toLowerCase()=="desc";var e=me.property||"text";var g=me.sortType;var j=me.folderSort;var k=me.caseSensitive===true;var f=me.leafAttr||"leaf";if(j){if(m.attributes[f]&&!l.attributes[f]){return 1}if(!m.attributes[f]&&l.attributes[f]){return -1}}var q=g?g(m):(k?m.attributes[e]:m.attributes[e].toUpperCase());var o=g?g(l):(k?l.attributes[e]:l.attributes[e].toUpperCase());if(qo){return h?-1:+1}else{return 0}}};c.on("afterrender",this.onAfterTreeRender,this,{single:true});c.on("headermenuclick",this.onHeaderMenuClick,this)},onAfterTreeRender:function(){if(this.tree.hmenu){this.tree.hmenu.insert(0,{itemId:"asc",text:this.sortAscText,cls:"xg-hmenu-sort-asc"},{itemId:"desc",text:this.sortDescText,cls:"xg-hmenu-sort-desc"})}this.updateSortIcon(0,"asc")},onHeaderMenuClick:function(f,e,d){if(e==="asc"||e==="desc"){this.onHeaderClick(f,null,d);return false}},onHeaderClick:function(g,e,d){if(g&&!this.tree.headersDisabled){var f=this;f.property=g.dataIndex;f.dir=g.dir=(g.dir==="desc"?"asc":"desc");f.sortType=g.sortType;f.caseSensitive===Ext.isBoolean(g.caseSensitive)?g.caseSensitive:this.caseSensitive;f.sortFn=g.sortFn||this.defaultSortFn;this.tree.root.cascade(function(c){if(!c.isLeaf()){f.updateSort(f.tree,c)}});this.updateSortIcon(d,g.dir)}},updateSortIcon:function(d,c){var f=this.sortClasses;var e=this.tree.innerHd.select("td").removeClass(f);e.item(d).addClass(f[c=="desc"?1:0])}}); -/* +/*! * Ext JS Library 3.2.0 * Copyright(c) 2006-2010 Ext JS, Inc. * licensing@extjs.com * http://www.extjs.com/license */ Ext.tree.ColumnResizer=Ext.extend(Ext.util.Observable,{minWidth:14,constructor:function(c){Ext.apply(this,c);Ext.tree.ColumnResizer.superclass.constructor.call(this)},init:function(c){this.tree=c;c.on("render",this.initEvents,this)},initEvents:function(c){c.mon(c.innerHd,"mousemove",this.handleHdMove,this);this.tracker=new Ext.dd.DragTracker({onBeforeStart:this.onBeforeStart.createDelegate(this),onStart:this.onStart.createDelegate(this),onDrag:this.onDrag.createDelegate(this),onEnd:this.onEnd.createDelegate(this),tolerance:3,autoStart:300});this.tracker.initEl(c.innerHd);c.on("beforedestroy",this.tracker.destroy,this.tracker)},handleHdMove:function(h,m){var j=5,l=h.getPageX(),g=h.getTarget(".x-treegrid-hd",3,true);if(g){var d=g.getRegion(),o=g.dom.style,f=g.dom.parentNode;if(l-d.left<=j&&g.dom!==f.firstChild){var c=g.dom.previousSibling;while(c&&Ext.fly(c).hasClass("x-treegrid-hd-hidden")){c=c.previousSibling}if(c){this.activeHd=Ext.get(c);o.cursor=Ext.isWebKit?"e-resize":"col-resize"}}else{if(d.right-l<=j){var k=g.dom;while(k&&Ext.fly(k).hasClass("x-treegrid-hd-hidden")){k=k.previousSibling}if(k){this.activeHd=Ext.get(k);o.cursor=Ext.isWebKit?"w-resize":"col-resize"}}else{delete this.activeHd;o.cursor=""}}}},onBeforeStart:function(c){this.dragHd=this.activeHd;return !!this.dragHd},onStart:function(d){this.tree.headersDisabled=true;this.proxy=this.tree.body.createChild({cls:"x-treegrid-resizer"});this.proxy.setHeight(this.tree.body.getHeight());var c=this.tracker.getXY()[0];this.hdX=this.dragHd.getX();this.hdIndex=this.tree.findHeaderIndex(this.dragHd);this.proxy.setX(this.hdX);this.proxy.setWidth(c-this.hdX);this.maxWidth=this.tree.outerCt.getWidth()-this.tree.innerBody.translatePoints(this.hdX).left},onDrag:function(d){var c=this.tracker.getXY()[0];this.proxy.setWidth((c-this.hdX).constrain(this.minWidth,this.maxWidth))},onEnd:function(f){var d=this.proxy.getWidth(),c=this.tree;this.proxy.remove();delete this.dragHd;c.columns[this.hdIndex].width=d;c.updateColumnWidths();setTimeout(function(){c.headersDisabled=false},100)}}); -/* +/*! * Ext JS Library 3.2.0 * Copyright(c) 2006-2010 Ext JS, Inc. * licensing@extjs.com * http://www.extjs.com/license */ Ext.ux.tree.TreeGridNodeUI=Ext.extend(Ext.tree.TreeNodeUI,{isTreeGridNodeUI:true,renderElements:function(e,m,j,o){var p=e.getOwnerTree(),l=p.columns,k=l[0],f,d,h;this.indentMarkup=e.parentNode?e.parentNode.ui.getChildIndent():"";d=['','','','',this.indentMarkup,"",'','','",'',(k.tpl?k.tpl.apply(m):m[k.dataIndex]||k.text),"",""];for(f=1,h=l.length;f','
",(k.tpl?k.tpl.apply(m):m[k.dataIndex]),"
","")}d.push('','');for(f=0,h=l.length;f')}d.push("");if(o!==true&&e.nextSibling&&e.nextSibling.ui.getEl()){this.wrap=Ext.DomHelper.insertHtml("beforeBegin",e.nextSibling.ui.getEl(),d.join(""))}else{this.wrap=Ext.DomHelper.insertHtml("beforeEnd",j,d.join(""))}this.elNode=this.wrap.childNodes[0];this.ctNode=this.wrap.childNodes[1].firstChild.firstChild;var g=this.elNode.firstChild.childNodes;this.indentNode=g[0];this.ecNode=g[1];this.iconNode=g[2];this.anchor=g[3];this.textNode=g[3].firstChild},animExpand:function(c){this.ctNode.style.display="";Ext.ux.tree.TreeGridNodeUI.superclass.animExpand.call(this,c)}});Ext.ux.tree.TreeGridRootNodeUI=Ext.extend(Ext.tree.TreeNodeUI,{isTreeGridNodeUI:true,render:function(){if(!this.rendered){this.wrap=this.ctNode=this.node.ownerTree.innerCt.dom;this.node.expanded=true}if(Ext.isWebKit){var c=this.ctNode;c.style.tableLayout=null;(function(){c.style.tableLayout="fixed"}).defer(1)}},destroy:function(){if(this.elNode){Ext.dd.Registry.unregister(this.elNode.id)}delete this.node},collapse:Ext.emptyFn,expand:Ext.emptyFn}); -/* +/*! * Ext JS Library 3.2.0 * Copyright(c) 2006-2010 Ext JS, Inc. * licensing@extjs.com * http://www.extjs.com/license */ Ext.ux.tree.TreeGridLoader=Ext.extend(Ext.tree.TreeLoader,{createNode:function(c){if(!c.uiProvider){c.uiProvider=Ext.ux.tree.TreeGridNodeUI}return Ext.tree.TreeLoader.prototype.createNode.call(this,c)}}); -/* +/*! * Ext JS Library 3.2.0 * Copyright(c) 2006-2010 Ext JS, Inc. * licensing@extjs.com * http://www.extjs.com/license */ (function(){Ext.override(Ext.list.Column,{init:function(){var d=Ext.data.Types,c=this.sortType;if(this.type){if(Ext.isString(this.type)){this.type=Ext.data.Types[this.type.toUpperCase()]||d.AUTO}}else{this.type=d.AUTO}if(Ext.isString(c)){this.sortType=Ext.data.SortTypes[c]}else{if(Ext.isEmpty(c)){this.sortType=this.type.sortType}}}});Ext.tree.Column=Ext.extend(Ext.list.Column,{});Ext.tree.NumberColumn=Ext.extend(Ext.list.NumberColumn,{});Ext.tree.DateColumn=Ext.extend(Ext.list.DateColumn,{});Ext.tree.BooleanColumn=Ext.extend(Ext.list.BooleanColumn,{});Ext.reg("tgcolumn",Ext.tree.Column);Ext.reg("tgnumbercolumn",Ext.tree.NumberColumn);Ext.reg("tgdatecolumn",Ext.tree.DateColumn);Ext.reg("tgbooleancolumn",Ext.tree.BooleanColumn)})(); -/* +/*! * Ext JS Library 3.2.0 * Copyright(c) 2006-2010 Ext JS, Inc. * licensing@extjs.com * http://www.extjs.com/license */ -Ext.ux.tree.TreeGrid=Ext.extend(Ext.tree.TreePanel,{rootVisible:false,useArrows:true,lines:false,borderWidth:Ext.isBorderBox?0:2,cls:"x-treegrid",columnResize:true,enableSort:true,reserveScrollOffset:true,enableHdMenu:true,columnsText:"Columns",initComponent:function(){if(!this.root){this.root=new Ext.tree.AsyncTreeNode({text:"Root"})}var d=this.loader;if(!d){d=new Ext.ux.tree.TreeGridLoader({dataUrl:this.dataUrl,requestMethod:this.requestMethod,store:this.store})}else{if(Ext.isObject(d)&&!d.load){d=new Ext.ux.tree.TreeGridLoader(d)}else{if(d){d.createNode=function(c){if(!c.uiProvider){c.uiProvider=Ext.ux.tree.TreeGridNodeUI}return Ext.tree.TreeLoader.prototype.createNode.call(this,c)}}}}this.loader=d;Ext.ux.tree.TreeGrid.superclass.initComponent.call(this);this.initColumns();if(this.enableSort){this.treeGridSorter=new Ext.ux.tree.TreeGridSorter(this,this.enableSort)}if(this.columnResize){this.colResizer=new Ext.tree.ColumnResizer(this.columnResize);this.colResizer.init(this)}var e=this.columns;if(!this.internalTpl){this.internalTpl=new Ext.XTemplate('
','
','
','','','','","","
','
',this.enableHdMenu?'':"",'{header}',"
","
","
","
",'
','
',"
")}if(!this.colgroupTpl){this.colgroupTpl=new Ext.XTemplate('')}},initColumns:function(){var g=this.columns,d=g.length,f=[],e,h;for(e=0;e10)){this.setScrollOffset(c)}else{var f=this;setTimeout(function(){f.setScrollOffset(g.offsetWidth-g.clientWidth>10?c:0)},10)}}},updateColumnWidths:function(){var m=this.columns,p=m.length,d=this.outerCt.query("colgroup"),o=d.length,l,h,f,e;for(f=0;f0&&this.columns[c]){this.setColumnVisible(c,!d.checked)}}return true},setColumnVisible:function(c,d){this.columns[c].hidden=!d;this.updateColumnWidths()},scrollToTop:function(){this.innerBody.dom.scrollTop=0;this.innerBody.dom.scrollLeft=0},syncScroll:function(){this.syncHeaderScroll();var c=this.innerBody.dom;this.fireEvent("bodyscroll",c.scrollLeft,c.scrollTop)},syncHeaderScroll:function(){var c=this.innerBody.dom;this.innerHd.dom.scrollLeft=c.scrollLeft;this.innerHd.dom.scrollLeft=c.scrollLeft},registerNode:function(c){Ext.ux.tree.TreeGrid.superclass.registerNode.call(this,c);if(!c.uiProvider&&!c.isRoot&&!c.ui.isTreeGridNodeUI){c.ui=new Ext.ux.tree.TreeGridNodeUI(c)}}});Ext.reg("treegrid",Ext.ux.tree.TreeGrid);Ext.override(Ext.ux.tree.TreeGrid,{onResize:function(d,f){Ext.ux.tree.TreeGrid.superclass.onResize.apply(this,arguments);var j=this.innerBody.dom;var k=this.innerHd.dom;if(!j){return}if(Ext.isNumber(f)){j.style.height=this.body.getHeight(true)-24+"px"}if(Ext.isNumber(d)){if(Ext.isIE&&!(Ext.isStrict&&Ext.isIE8)){var e=this.body.getWidth(true)+"px";j.style.width=e;k.style.width=e}var c=Ext.num(this.scrollOffset,Ext.getScrollBarWidth());if(this.reserveScrollOffset||((j.offsetWidth-j.clientWidth)>10)){this.setScrollOffset(c)}else{var g=this;setTimeout(function(){g.setScrollOffset(j.offsetWidth-j.clientWidth>10?c:0)},10)}}}});Ext.ux.DblClickCloseTabs=Ext.extend(Object,{init:function(c){this.panel=c;c.initEvents=c.initEvents.createSequence(this.initEvents,this)},initEvents:function(){this.panel.mon(this.panel.strip,{dblclick:this.onDblClick.createDelegate(this,[this.panel],0)});delete this.panel},onDblClick:function(c,d){if(c.getActiveTab().closable){c.remove(c.getActiveTab())}}});Ext.preg("dblclickclosetabs",Ext.ux.DblClickCloseTabs);Ext.util.md5=function(u,c,q,m){c=(typeof c==="undefined"?false:c);q=(typeof q==="undefined"?false:q);m=(typeof m==="undefined"?8:m);function k(r,w){var v=((r&65535)+(w&65535)),s=((r>>16)+(w>>16)+(v>>16));return(s<<16)|(v&65535)}function p(r,s){return(r<>>(32-s))}function f(A,w,v,r,z,y){return k(p(k(k(w,A),k(r,y)),z),v)}function l(w,v,B,A,r,z,y){return f((v&B)|((~v)&A),w,v,r,z,y)}function e(w,v,B,A,r,z,y){return f((v&A)|(B&(~A)),w,v,r,z,y)}function o(w,v,B,A,r,z,y){return f(v^B^A,w,v,r,z,y)}function j(w,v,B,A,r,z,y){return f(B^(v|(~A)),w,v,r,z,y)}function h(E,z){var D=1732584193,C=-271733879,B=-1732584194,A=271733878,v,y,w,s,r;E[z>>5]|=128<<((z)%32);E[(((z+64)>>>9)<<4)+14]=z;for(v=0;v>5]|=(w.charCodeAt(s/m)&r)<<(s%32)}return v}function g(v){var w="",r=((1<>5]>>>(s%32))&r)}return w}function t(v){var s=((q)?"0123456789ABCDEF":"0123456789abcdef"),w="",r;for(r=0;r>2]>>((r%4)*8+4))&15)+s.charAt((v[r>>2]>>((r%4)*8))&15)}return w}return(c?g(h(d(u),u.length*m)):t(h(d(u),u.length*m)))};Ext.ux.CodeMirror=Ext.extend(Ext.BoxComponent,{lineWrapping:false,previousLine:false,readOnly:false,originalContent:false,documentDurty:false,mode:(this.parser||"xml"),theme:(this.theme==="undefined")?"default":this.theme,initComponent:function(){this.initialized=false;Ext.ux.CodeMirror.superclass.initComponent.apply(this,arguments);this.theme=(Ext.isDefined(this.theme))?this.theme:"default";switch(this.mode){case"html":case"htm":this.mode="text/html";break;case"css":this.mode="text/css";break;case"php":this.mode="application/x-httpd-php";break;case"xml":case"ent":this.mode={name:"xml",alignCDATA:true};break;case"bat":this.mode="text/x-clojure";break;case"README":this.mode="text/x-rst";break;default:this.mode={name:"xmlpure"};break}this.addEvents("initialize");this.addEvents("codemodified");this.addEvents("coderestored");this.addEvents("cursormove");this.addEvents("scroll");this.ownerCt.on("resize",function(f,e,d){this.fireEvent("resize",this,e,d)},this);this.on({resize:function(e,d,c){this.resize(d,c)},afterrender:function(){var c=this;c.codeEditor=new CodeMirror(Ext.get(c.id),{theme:c.theme,readOnly:false,mode:c.mode,lineNumbers:true,matchBrackets:true,lineWrapping:c.lineWrapping,indentUnit:1,tabMode:"indent",value:"",onScroll:function(){c.fireEvent("scroll",c.el.child(".CodeMirror-scroll").dom.scrollTop)},onKeyEvent:function(g,d){if(d.ctrlKey&&d.keyCode==83){d.preventDefault();c.onSave()}var f=g.getCursor();c.fireEvent("cursormove",f.line,f.ch)},onCursorActivity:function(e){var d=e.getCursor();if(c.previousLine!==false){e.setLineClass(c.previousLine,null)}c.previousLine=e.setLineClass(d.line,"cm2-activeline");c.fireEvent("cursormove",d.line,d.ch)},onChange:function(d){c.manageCodeChange()}});c.initialized=true;c.fireEvent("initialize",true)}})},focus:function(){if(this.initialized){return this.codeEditor.focus()}return this.initialConfig.value},getCursor:function(){return this.codeEditor.getCursor()},getLine:function(c){return this.codeEditor.getLine(c)},getValue:function(){if(this.initialized){return this.codeEditor.getValue()}return this.initialConfig.value},insertLine:function(d,e){var c=this.codeEditor.getLine(d);this.codeEditor.setLine(d,c+"\n"+e)},manageCodeChange:function(){var c=this.originalContent,d=this.getValue();btnUndo=Ext.getCmp(this.id+"-btn-undo");if(c){if(c===d){if(this.documentDurty===true){this.fireEvent("coderestored");this.documentDurty=false}}else{if(btnUndo){btnUndo.enable()}if(this.documentDurty===false){this.fireEvent("codemodified");this.documentDurty=true}}}},onSave:function(){var c=Ext.getCmp(this.id+"-btn-save");if(!c.disabled){c.handler.call(c.scope||c,c)}},redo:function(c,d){this.codeEditor.redo();Ext.getCmp(this.id+"-btn-undo").enable();if(this.codeEditor.historySize().redo==0){Ext.getCmp(this.id+"-btn-redo").disable()}},resize:function(f,c){var e=this.el,d=e.child(".CodeMirror-scroll");d.setHeight(c-89)},removeLine:function(c){return this.codeEditor.removeLine(c)},reIndentAll:function(){var d=this.codeEditor.lineCount(),c;for(c=0;c','',"{cells}","
","");this.rowTpl.disableFormats=true}this.rowTpl.compile();if(!this.cellTpl){this.cellTpl=new Ext.Template('','
{value}
',"");this.cellTpl.disableFormats=true}this.cellTpl.compile()},calculate:function(e,o){var g={},m=o.config,h,d,k,f,c,l,p;for(h=0,l=m.length;h '+_("Loading..."));var e=document.createElement("iframe"),f=function(g){d.unmask()};e.id=this.id;e.name=this.id;e.src=this.url;e.frameBorder=0;this.el=d.appendChild(e);if(Ext.isIE){document.frames[this.url].name=this.id}e[Ext.isIE?"onreadystatechange":"onload"]=f.createDelegate(e)}});Ext.ux.FixedMultiSelectionModel=Ext.extend(Ext.tree.MultiSelectionModel,{normalClick:false,init:function(c){this.tree=c;c.getTreeEl().on("keydown",this.onKeyDown,this);c.on("dblclick",this.onDoubleClick,this);c.on("click",this.onNodeClick,this)},onDrag:function(){this.normalClick=false},onNodeClick:function(c,d){if(d.shiftKey){d.preventDefault()}if(!this.tree.dragZone||!this.tree.dragZone.isMultiSelect){this.onMouseDown(c,d);this.onMouseUp(c,d)}},onMouseDown:function(c,d){if(c.isSelected()){if(d.ctrlKey){this.unselect(c);this.normalClick=false;return}this.normalClick=!d.shiftKey}else{this.select(c,d,d.ctrlKey);this.normalClick=false}},onMouseUp:function(c,d){if(this.normalClick){this.select(c,d,d.ctrlKey);this.normalClick=false}},onDoubleClick:function(){this.normalClick=false},compareNodeOrder:document.compareDocumentPosition?function(d,c){return 3-(d.ui.elNode.compareDocumentPosition(c.ui.elNode)&6)}:(typeof document.documentElement.sourceIndex!=="undefined"?function(d,c){return d.ui.elNode.sourceIndex-c.ui.elNode.sourceIndex}:function(f,e){if(f==e){return 0}var d=document.createRange();d.selectNode(a.ui.elNode);d.collapse(true);var c=document.createRange();c.selectNode(b.ui.elNode);c.collapse(true);return d.compareBoundaryPoints(Range.START_TO_END,c)}),sortSelNodes:function(){if(this.selNodes.length>1){if(!this.selNodes[0].ui.elNode){return}this.selNodes.sort(this.compareNodeOrder)}},selectNode:function(d,c){if(!this.isSelected(d)){this.selNodes.push(d);this.selMap[d.id]=d;d.ui.onSelectedChange(true)}},select:function(d,h,m){if(d instanceof Array){for(var j=0;j0){this.lastSelNode=this.lastSelNode||this.selNodes[0];var k=this.compareNodeOrder(this.lastSelNode,d)>0;this.clearSelections(true);var o=true;var f=false;var l=this.lastSelNode;do{for(var g=l;g!=null;g=(k?g.previousSibling:g.nextSibling)){f=f||(k&&(g==d||g.contains(d)));if(g.isExpanded()){g.cascade(function(c){if(o!=f){this.selectNode(c)}o=(o&&c!=d);return true},this)}else{this.selectNode(g);o=(g!=d)}if(!o){break}}if(!o){break}while((l=l.parentNode)!=null){if(k){this.selectNode(l)}o=(o&&l!=d);if(k&&l.previousSibling){l=l.previousSibling;break}if(!k&&l.nextSibling){l=l.nextSibling;break}}if(!o){break}}while(l!=null);this.selectNode(d);this.sortSelNodes();this.fireEvent("selectionchange",this,this.selNodes,d);h.preventDefault();return d}else{if(m!==true){this.clearSelections(true)}}if(this.isSelected(d)){if(m===true){this.unselect(d);if(this.lastSelNode===d){this.lastSelNode=this.selNodes[0]}return d}this.lastSelNode=d;return d}this.selectNode(d);this.sortSelNodes();this.lastSelNode=d;this.fireEvent("selectionchange",this,this.selNodes,this.lastSelNode);return d},getUniqueSelectedNodes:function(){var d=[];for(var f=0;f=0;f--){if(this.selNodes[f].isAncestor(d)){Ext.ux.FixedMultiSelectionModel.superclass.unselect.call(this,this.selNodes[f])}}}return Ext.ux.FixedMultiSelectionModel.superclass.unselect.call(this,d)},selectPrevious:function(e){var c=this.selNodes[0];if(!c){return null}var f=c.previousSibling;if(f){if(!f.isExpanded()||f.childNodes.length<1){return this.select(f,null,e)}else{var d=f.lastChild;while(d&&d.isExpanded()&&d.childNodes.length>0){d=d.lastChild}return this.select(d,null,e)}}else{if(c.parentNode&&(this.tree.rootVisible||!c.parentNode.isRoot)){return this.select(c.parentNode,null,e)}}return null},selectNext:function(e){var d=this.selNodes[this.selNodes.length-1];if(!d){return null}if(d.firstChild&&d.isExpanded()){return this.select(d.firstChild,null,e)}else{if(d.nextSibling){return this.select(d.nextSibling,null,e)}else{if(d.parentNode){var c=null;d.parentNode.bubble(function(){if(this.nextSibling){c=this.getOwnerTree().selModel.select(this.nextSibling,null,e);return false}});return c}}}return null},onKeyDown:function(f){var d=this.selNode||this.lastSelNode;var g=this;if(!d){return}var c=f.getKey();switch(c){case f.DOWN:f.stopEvent();this.selectNext(f.shiftKey||f.ctrlKey);break;case f.UP:f.stopEvent();this.selectPrevious(f.shiftKey||f.ctrlKey);break;case f.RIGHT:f.preventDefault();if(d.hasChildNodes()){if(!d.isExpanded()){d.expand()}else{if(d.firstChild){this.select(d.firstChild,f,f.shiftKey||f.ctrlKey)}}}break;case f.LEFT:f.preventDefault();if(d.hasChildNodes()&&d.isExpanded()){d.collapse()}else{if(d.parentNode&&(this.tree.rootVisible||d.parentNode!=this.tree.getRootNode())){this.select(d.parentNode,f,f.shiftKey||f.ctrlKey)}}break}}});Ext.ux.MultiSelectTreeDragZone=Ext.extend(Ext.tree.TreeDragZone,{isMultiSelect:true,onBeforeDrag:function(d,f){if(d.nodes&&d.nodes.length>0){for(var g=0;g0){var w=Ext.query(h[k].ui.indentNode.nodeName+".x-tree-node-indent",v);for(var s=0,t=w.length;s=r&&k<(r+c)&&this.isValidDropPoint(g,"above",o,j,h)){return"above"}else{if(!f&&(m||k>=l-c&&k<=l)&&this.isValidDropPoint(g,"below",o,j,h)){return"below"}}}return m?false:"append"},onNodeOver:function(d,k,j,h){var m=this.getDropPoint(j,d,k,h);var f=d.node;if(!this.expandProcId&&m=="append"&&f.hasChildNodes()&&!d.node.isExpanded()){this.queueExpand(f)}else{if(m!="append"){this.cancelExpand()}}var g=this.dropNotAllowed;if(m){var c=d.ddel;var l;if(m=="above"){g=d.node.isFirst()?"x-tree-drop-ok-above":"x-tree-drop-ok-between";l="x-tree-drag-insert-above"}else{if(m=="below"){g=d.node.isLast()?"x-tree-drop-ok-below":"x-tree-drop-ok-between";l="x-tree-drag-insert-below"}else{g="x-tree-drop-ok-append";l="x-tree-drag-append"}}if(this.lastInsertClass!=l){Ext.fly(c).replaceClass(this.lastInsertClass,l);this.lastInsertClass=l}}return g},onNodeDrop:function(f,m,h,g){var l=this.getDropPoint(h,f,m,g);var j=f.node;j.ui.startDrop();if(l===false){j.ui.endDrop();return false}var k=g.node||(m.getTreeNode?m.getTreeNode(g,j,l,h):null);var d={tree:this.tree,target:j,data:g,point:l,source:m,rawEvent:h,dropNode:k,cancel:!k,dropStatus:false};var c=this.tree.fireEvent("beforenodedrop",d);if(c===false||d.cancel===true||!d.dropNode){j.ui.endDrop();return d.dropStatus}j=d.target;if(l=="append"&&!j.isExpanded()){j.expand(false,null,function(){this.completeDrop(d)}.createDelegate(this))}else{this.completeDrop(d)}return true},afterRepair:function(f){if(f&&Ext.enableFx){var e=f.nodes?f.nodes:[f.node];for(var g=0,d=e.length;g-1){this.pos++}Ext.ux.NotificationMgr.positions.push(this.pos);this.setSize(200,100);this.el.alignTo(document,"br-br",[-20,-20-((this.getSize().height+10)*this.pos)]);this.el.slideIn("b",{duration:1,callback:this.afterShow,scope:this})},animHide:function(){Ext.ux.NotificationMgr.positions.remove(this.pos);this.el.shadow.hide();this.el.ghost("b",{duration:1,remove:false,callback:function(){Ext.ux.NotificationMgr.positions.remove(this.pos);this.destroy()}.createDelegate(this)})},focus:Ext.emptyFn});Ext.ns("Ext.ux");Ext.ux.PanelCollapsedTitle=(function(){var c="x-panel-header-rotated";var e=!!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");var d=function(){var k=((this.region=="east")||(this.region=="west"));var l="overflow: visible; padding: 0; border: none; background: none;";if(k&&e){this.collapsedHeader=this.ownerCt.layout[this.region].getCollapsedEl().createChild({tag:"div",style:"height: 100%; overflow: hidden;"});var j="http://www.w3.org/2000/svg";var h=document.createElementNS(j,"svg");this.collapsedHeader.dom.appendChild(h);h.setAttribute("width","100%");h.setAttribute("height","100%");var m=document.createElementNS(j,"text");m.setAttribute("x",6);m.setAttribute("y",1);m.setAttribute("transform","rotate(90 6 1)");m.setAttribute("class","x-panel-header "+c);h.appendChild(m);this.collapsedHeaderText=document.createTextNode(this.title);m.appendChild(this.collapsedHeaderText);var g=Ext.fly(m).getStyle("color");m.setAttribute("style",l+";fill: "+g+";")}else{var f="position: relative;";if(k){f+="white-space: nowrap; writing-mode: tb-rl; top: 1px; left: 3px;"}else{f+="top: 2px;";l+="padding-left: 4px; margin-right: 18px;"}this.collapsedHeader=this.ownerCt.layout[this.region].getCollapsedEl().createChild({tag:"div",style:l,cls:"x-panel-header "+c,html:''+this.title+""});this.collapsedHeaderText=this.collapsedHeader.first()}if(this.collapsedIconCls){this.setCollapsedIconClass(this.collapsedIconCls)}};this.init=function(g){if(g.collapsible){var f=((g.region=="east")||(g.region=="west"));g.setTitle=Ext.Panel.prototype.setTitle.createSequence(function(h){if(this.rendered&&this.collapsedHeaderText){if(this.collapsedHeaderText.dom){this.collapsedHeaderText.dom.innerHTML=h}else{if(this.collapsedHeaderText.replaceData){this.collapsedHeaderText.nodeValue=h}}}});g.setCollapsedIconClass=function(j){var h=this.collapsedIconCls;this.collapsedIconCls=j;if(this.rendered&&this.collapsedHeader){var l=this.collapsedHeader,k=l.child("img.x-panel-inline-icon");if(k){if(this.collapsedIconCls){Ext.fly(k).replaceClass(h,this.collapsedIconCls)}else{Ext.fly(k).remove()}}else{if(this.collapsedIconCls){Ext.DomHelper.insertBefore(l.dom.firstChild,{tag:"img",src:Ext.BLANK_IMAGE_URL,cls:"x-panel-inline-icon "+this.collapsedIconCls,style:f?"display: block; margin: 1px 2px;":"margin-top: 2px; margin-right: 4px"})}}}};g.on("render",function(){if(this.ownerCt.rendered&&this.ownerCt.layout.hasLayout){d.call(g)}else{this.ownerCt.on("afterlayout",d,g,{single:true})}},g)}};return this})();Ext.ux.SlidingTabPanel=Ext.extend(Ext.TabPanel,{initTab:function(d,c){Ext.ux.SlidingTabPanel.superclass.initTab.call(this,d,c);this.addEvents({startDrag:true,endDrag:true});var e=this.getTemplateArgs(d);if(!this.slidingTabsID){this.slidingTabsID=Ext.id()}new Ext.ux.DDSlidingTab(e,this.slidingTabsID,{tabpanel:this})}});Ext.ux.DDSlidingTab=Ext.extend(Ext.dd.DDProxy,{constructor:function(){Ext.ux.DDSlidingTab.superclass.constructor.apply(this,arguments);this.setYConstraint(0,0,0);this.tabpanel=this.config.tabpanel;this.slideDuration=this.tabpanel.slideDuration;if(!this.slideDuration){this.slideDuration=0.1}},handleMouseDown:function(f,d){if(this.primaryButtonOnly&&f.button!=0){return}if(this.isLocked()){return}this.DDM.refreshCache(this.groups);var c=new Ext.lib.Point(Ext.lib.Event.getPageX(f),Ext.lib.Event.getPageY(f));if(!this.hasOuterHandles&&!this.DDM.isOverTarget(c,this)){}else{if(this.clickValidator(f)){this.setStartPosition();this.b4MouseDown(f);this.onMouseDown(f);this.DDM.handleMouseDown(f,this)}}},startDrag:function(c,k){this.tabpanel.fireEvent("startDrag",this.tabpanel,this.tabpanel.getActiveTab());Ext.dd.DDM.useCache=false;Ext.dd.DDM.mode=1;this.proxyWrapper=Ext.get(this.getDragEl());this.proxyWrapper.update();this.proxyWrapper.applyStyles("z-index:1001;border:0 none;");this.proxyWrapper.addClass("tab-proxy");this.stripWrap=this.proxyWrapper.insertHtml("afterBegin",'
',true);this.dragEl=this.stripWrap.insertHtml("afterBegin","
",true);this.tab=Ext.get(this.getEl());this.tab.applyStyles("visibility:hidden;");this.dragEl.insertHtml("afterBegin",this.tab.dom.innerHTML,false);this.dragEl.dom.className=this.tab.dom.className;var j=this.tabpanel.el.getWidth();var g=this.tabpanel.el.getX();var h=this.tab.getX();var d=this.tab.getWidth();var f=h-g;var e=g+j-h-d;this.resetConstraints();this.setXConstraint(f,e)},onDragOver:function(f,j){f.stopEvent();var g=Ext.get(j[0].id);var l=g.getWidth();var k=g.getX();var h=k+(l/2);var d=this.tab.getX();var m=this.proxyWrapper.getX();var c=this.proxyWrapper.getWidth();if(mh)){if(g.next()!=this.tab){g.applyStyles("visibility:hidden;");this.tab.insertAfter(g);this.targetProxy=this.createSliderProxy(k,g);if(!this.targetProxy.hasActiveFx()){this.animateSliderProxy(g,this.targetProxy,d)}}}if(m>k&&(m',true);e.stripWrapper=e.insertHtml("afterBegin",'
',true);e.dragEl=e.stripWrapper.insertHtml("afterBegin","
",true);e.dragEl.update(f.dom.innerHTML);e.dragEl.dom.className=f.dom.className;var c=parseInt(f.getTop(false));e.setTop(c);return e},onDragDrop:function(d,c){d.stopEvent()},endDrag:function(c){var d=this.tab.getX();this.proxyWrapper.applyStyles("visibility:visible;");this.proxyWrapper.shift({x:d,easing:"easeOut",duration:this.slideDuration,callback:function(){this.proxyWrapper.applyStyles("visibility:hidden;");this.tab.applyStyles("visibility:visible;");this.stripWrap.remove();this.dragEl.remove();if(!this.targetProxy){return}this.targetProxy.stripWrapper.remove();this.targetProxy.dragEl.remove()},scope:this});Ext.dd.DDM.useCache=true;this.reorderTab();this.tabpanel.fireEvent("endDrag",this.tabpanel,this.tabpanel.getActiveTab())},reorderTab:function(){var e=this.tabpanel.header.child("ul").dom.children,c=[],f=[];for(var d=0;d{0})"),text:String.format(_("Notes ({0})"),"-"),initComponent:function(){Ext.ux.UserNotes.superclass.initComponent.apply(this);Ext.apply(this,{iconCls:"iconUserNotes",id:this.fid+"-userNotes",menu:new Ext.menu.Menu({showSeparator:false,allowOtherMenus:true,plain:true,autoHeight:true,forceLayout:true,enableScrolling:false,items:[{xtype:"grid",loadMask:true,width:500,height:200,contextMenuFrom:false,contextMenuRowIndex:false,sm:new Ext.grid.RowSelectionModel({singleSelect:true}),winNotes:new Ext.Window({scope:this,title:_("Add a new note"),iconCls:"iconUserNotes",closeAction:"hide",width:600,height:300,layout:"form",hideLabel:true,modal:true,items:[{xtype:"htmleditor",hideLabel:true,enableLinks:false,anchor:"100%"}],listeners:{show:function(c){c.items.items[0].setValue("")}},buttons:[{text:_("Add"),handler:function(){var e=this.ownerCt.ownerCt.scope,f=this.ownerCt.ownerCt;e.menu.show(e.el);var d=this.ownerCt.ownerCt.items.items[0].getValue();var c=e.file;XHR({scope:this,params:{task:"addUserNote",file:c,note:d},success:function(){f.hide();e.menu.items.items[0].store.reload();PhDOE.notify("info",_("Note added"),_("The note was added successfully !"))},failure:function(){PhDOE.winForbidden()}})}},{text:_("Cancel"),handler:function(){var c=this.ownerCt.ownerCt.scope;c.menu.show(c.el);this.ownerCt.ownerCt.hide()}}]}),contextMenu:new Ext.menu.Menu({scope:this,listeners:{show:function(c){if(this.scope.menu.items.items[0].contextMenuFrom==="containercontextmenu"){this.items.items[2].disable()}else{var d=this.scope.menu.items.items[0];var e=d.store.getAt(d.contextMenuRowIndex).data.user;if(PhDOE.userLogin==e){this.items.items[2].enable()}else{this.items.items[2].disable()}}if(PhDOE.userLogin=="anonymous"){this.items.items[0].disable();this.items.items[2].disable()}}},items:[{text:_("Add a new note"),iconCls:"iconUserNotes",handler:function(){var c=this.ownerCt.scope.menu.items.items[0];c.winNotes.show()}},"-",{text:_("Delete this note"),iconCls:"iconDelete",handler:function(){var d=this.ownerCt.scope.menu.items.items[0],c=d.store.getAt(d.contextMenuRowIndex).data.id;XHR({scope:this,params:{task:"delUserNote",noteID:c},success:function(e){var f=Ext.util.JSON.decode(e.responseText);d.store.reload();if(f.result){PhDOE.notify("info",_("Note deleted"),_("The note was deleted successfully !"))}},failure:function(){PhDOE.winForbidden()}})}},"-",{text:_("Reload data"),iconCls:"iconRefresh",handler:function(){var c=this.ownerCt.scope.menu.items.items[0];c.store.reload()}}]}),store:new Ext.data.Store({autoLoad:true,proxy:new Ext.data.HttpProxy({url:"./do/getUserNotes"}),baseParams:{file:this.file},reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"user"},{name:"note"},{name:"date",type:"date",dateFormat:"Y-m-d H:i:s"}]}),sortInfo:{field:"date",direction:"DESC"},listeners:{scope:this,datachanged:function(d){var c=d.getCount();this.setText(String.format(this.originalTitle,c))}}}),listeners:{scope:this,rowclick:function(c){if(!c.contextMenu.hidden){c.contextMenu.hide()}},containercontextmenu:function(d,f){f.stopEvent();d.getSelectionModel().clearSelections();d.contextMenuFrom="containercontextmenu";d.contextMenu.showAt(f.getXY());this.menu.show(this.el);var c=this.menu.el.zindex+2000;d.contextMenu.el.setStyle("z-index",c)},rowcontextmenu:function(d,g,f){f.stopEvent();d.getSelectionModel().selectRow(g);d.contextMenuFrom="rowcontextmenu";d.contextMenuRowIndex=g;d.contextMenu.showAt(f.getXY());this.menu.show(this.el);var c=this.menu.el.zindex+2000;d.contextMenu.el.setStyle("z-index",c)}},colModel:new Ext.grid.ColumnModel({defaults:{sortable:true},columns:[{id:"user",header:_("By"),sortable:true,dataIndex:"user"},{header:_("Date"),dataIndex:"date",renderer:Ext.util.Format.dateRenderer(_("Y-m-d, H:i"))}]}),autoExpandColumn:"user",viewConfig:{forceFit:true,deferEmptyText:false,emptyText:'
'+_("No user notes")+"

"+_("Right click to add a new note")+"
",enableRowBody:true,getRowClass:function(c,e,d){d.body='

'+c.data.note+"

";return"x-grid3-row-expanded"}}}]})})}});Ext.reg("usernotes",Ext.ux.UserNotes);Ext.namespace("ui","ui.task");ui.task.ChangeFileOwner=function(c){Ext.apply(this,c);var d=Ext.MessageBox.wait(_("Saving data..."));XHR({scope:this,params:{task:"setFileOwner",fileIdDB:this.fileIdDB,newOwnerID:this.newOwnerID},success:function(e){var f=Ext.util.JSON.decode(e.responseText);ui.cmp.WorkTreeGrid.getInstance().getRootNode().reload(function(){ui.cmp.PatchesTreeGrid.getInstance().getRootNode().reload()});ui.cmp.PortletInfo.getInstance().store.reload();d.hide();if(Ext.isDefined(this.fromType)&&this.fromType==="tab"){Ext.getCmp("main-panel").remove(this.from.curTab)}this.from.close();PhDOE.notify("info",_("Owner changed"),_("The owner for this file have been changed successfully !"))},failure:function(e){var f=Ext.util.JSON.decode(e.responseText);d.hide();PhDOE.winForbidden(f.type);if(Ext.isDefined(this.fromType)&&this.fromType==="tab"){Ext.getCmp("main-panel").remove(this.from.curTab)}this.from.close()}})};Ext.namespace("ui","ui.task","ui.task._CheckBuildTask");ui.task._CheckBuildTask.display=function(){XHR({params:{task:"getLogFile",file:"project_"+PhDOE.project+"_log_check_build_"+PhDOE.user.lang},success:function(c){var d=Ext.util.JSON.decode(c.responseText);Ext.getBody().unmask();ui.task.PingTask.getInstance().delay(30000);if(Ext.getCmp("main-panel").findById("check_build_panel_"+PhDOE.user.lang)){Ext.getCmp("main-panel").remove("check_build_panel_"+PhDOE.user.lang)}Ext.getCmp("main-panel").add({xtype:"panel",id:"check_build_panel_"+PhDOE.user.lang,title:String.format(_("Check build result for {0}"),Ext.util.Format.uppercase(PhDOE.user.lang)),tabTip:String.format(_("Check build result for the documentation {0}"),Ext.util.Format.uppercase(PhDOE.user.lang)),closable:true,autoScroll:true,iconCls:"iconCheckBuild",html:'
'+d.mess+"
"});Ext.getCmp("main-panel").setActiveTab("check_build_panel_"+PhDOE.user.lang)}})};ui.task._CheckBuildTask.poll=new Ext.util.DelayedTask(function(){XHR({params:{task:"checkLockFile",lockFile:"project_"+PhDOE.project+"_lock_check_build_"+PhDOE.user.lang},success:function(){ui.task._CheckBuildTask.poll.delay(5000)},failure:function(c){var d=Ext.util.JSON.decode(c.responseText);if(d&&d.success===false){new ui.task._CheckBuildTask.display()}else{ui.task._CheckBuildTask.poll.delay(5000)}}})});ui.task.CheckBuildTask=function(){Ext.getBody().mask(' '+_("Please, wait until the build is checked..."));ui.task.PingTask.getInstance().cancel();XHR({params:{task:"checkBuild",xmlDetails:Ext.getCmp("option-xml-details").checked},success:function(){new ui.task._CheckBuildTask.display()},failure:function(c){var d=Ext.util.JSON.decode(c.responseText);if(d&&d.success===false){ui.task.PingTask.getInstance().delay(30000);Ext.getBody().unmask();PhDOE.winForbidden(d.type)}else{ui.task._CheckBuildTask.poll.delay(5000)}}})};Ext.namespace("ui","ui.task","ui.task._CheckEntitiesTask");ui.task._CheckEntitiesTask.display=function(){BtnViewResult=Ext.getCmp("btn-check-entities-view-last-result");Ext.getBody().unmask();ui.task.PingTask.getInstance().delay(30000);if(Ext.getCmp("main-panel").findById("tab-check-entities")){Ext.getCmp("main-panel").remove("tab-check-entities")}BtnViewResult.handler.call(BtnViewResult.scope||BtnViewResult,BtnViewResult)};ui.task._CheckEntitiesTask.poll=new Ext.util.DelayedTask(function(){XHR({params:{task:"checkLockFile",lockFile:"project_"+PhDOE.project+"_lock_check_entities"},success:function(){ui.task._CheckEntitiesTask.poll.delay(5000)},failure:function(c){var d=Ext.util.JSON.decode(c.responseText);if(d&&d.success===false){new ui.task._CheckEntitiesTask.display()}else{ui.task._CheckEntitiesTask.poll.delay(5000)}}})});ui.task.CheckEntitiesTask=function(){Ext.getBody().mask(' '+_("Please, wait until entities are checked..."));ui.task.PingTask.getInstance().cancel();XHR({params:{task:"checkEntities"},success:function(){new ui.task._CheckEntitiesTask.display()},failure:function(c){var d=Ext.util.JSON.decode(c.responseText);if(d&&d.success===false){ui.task.PingTask.getInstance().delay(30000);Ext.getBody().unmask();PhDOE.winForbidden()}else{ui.task._CheckEntitiesTask.poll.delay(5000)}}})};Ext.namespace("ui","ui.task");ui.task.CheckFileTask=function(c){Ext.apply(this,c);ui.task.PingTask.getInstance().cancel();Ext.getBody().mask(' '+_("Checking for error. Please, wait..."));XHR({scope:this,params:{task:"checkFileError",FilePath:this.fpath,FileName:this.fname,FileLang:this.lang,FileContent:Ext.getCmp(this.prefix+"-"+this.ftype+"-FILE-"+this.fid).getValue()},failure:function(){ui.task.PingTask.getInstance().delay(30000);Ext.getBody().unmask();Ext.MessageBox.alert(_("Error"),_("An error occured while checking this file for errors. Please, try again."))},success:function(d){ui.task.PingTask.getInstance().delay(30000);Ext.getBody().unmask();var e=Ext.util.JSON.decode(d.responseText);if(e.error&&e.error_first!=="-No error-"){Ext.getCmp("main-panel").add({id:"FE-help-"+this.fid,title:"Error in "+this.fname,iconCls:"iconFilesError",closable:true,autoScroll:true,autoLoad:"./error?dir="+this.fpath+"&file="+this.fname});Ext.getCmp("main-panel").setActiveTab("FE-help-"+this.fid)}else{Ext.MessageBox.show({title:_("Check for errors"),msg:_("There is no error."),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.INFO})}new ui.task.SaveFileTask({prefix:this.prefix,ftype:this.ftype,fid:this.fid,fpath:this.fpath,fname:this.fname,lang:this.lang,storeRecord:this.storeRecord});if(this.prefix==="FE"){Ext.getCmp("FE-error-desc-"+this.fid).body.updateManager.refresh()}ui.cmp.ErrorFileGrid.getInstance().store.reload()}})};Ext.namespace("ui","ui.task");ui.task.CheckXml=function(d){Ext.apply(this,d);var c=this.prefix+"-"+this.ftype,e=Ext.MessageBox.wait(_("XML check. Please, wait..."));XHR({scope:this,params:{task:"checkXml",fileContent:Ext.getCmp(this.idPrefix+"-FILE-"+this.fid).getValue()},success:function(f){var g=Ext.util.JSON.decode(f.responseText);e.hide();if(g.errors!=="no_error"){new ui.cmp.CheckXmlWin({errors:g.errors})}else{PhDOE.notify("info",_("XML check"),_("There is no error."))}},failure:function(f){var g=Ext.util.JSON.decode(f.responseText);e.hide()}})};Ext.namespace("ui","ui.task");ui.task.ClearLocalChangeTask=function(d){Ext.apply(this,d);var c=this.ftype,e=this.fpath,f=this.fname;goClear=function(){Ext.getBody().mask(' '+_("Please, wait..."));var g=["FNT","FNU","FE","FNR","FNIEN","AF"];for(var h=0;hYou need confirm."),function(g){if(g==="yes"){goClear()}},this)}};Ext.namespace("ui","ui.task");ui.task.DeletePatchTask=function(c){Ext.apply(this,c);Ext.getBody().mask(' '+_("Please, wait..."));XHR({scope:this,params:{task:"deletePatch",patchID:this.patchID},success:function(){Ext.getBody().unmask();ui.cmp.PatchesTreeGrid.getInstance().deletePatch(this.patchID);PhDOE.notify("info",_("Patch deleted"),_("The patch have been deleted !"))},failure:function(d){var e=Ext.util.JSON.decode(d.responseText);Ext.getBody().unmask();if(e.err){PhDOE.winForbidden(e.err)}else{PhDOE.winForbidden()}}})};Ext.namespace("ui","ui.task");ui.task.GetFileInfoByXmlID=function(c){Ext.apply(this,c);XHR({scope:this,params:{task:"getFileInfoByXmlID",xmlID:this.xmlID},success:function(d){var e=Ext.util.JSON.decode(d.responseText);ui.cmp.RepositoryTree.getInstance().openFile("byPath",e.lang+e.path,e.name)}})};Ext.namespace("ui","ui.task");ui.task.GetFileTask=function(d){Ext.apply(this,d);var c=this.prefix+"-"+this.ftype,f=(this.original)?true:false,e=(this.ftype==="GGTRANS")?true:false,g=(this.ftype==="NEW")?this.skeleton:false;Ext.get(c+"-PANEL-"+this.fid).mask(' '+_("Loading..."));XHR({scope:this,params:{task:"getFile",FilePath:this.fpath,FileName:this.fname,readOriginal:f,ggTranslate:e,skeleton:g},success:function(h){var k=Ext.util.JSON.decode(h.responseText),y="http://"+window.location.host+":"+window.location.port+window.location.pathname+"?perm=/"+this.fpath.split("/")[0]+"/"+k.xmlid.split("|")[0]+".php&project="+PhDOE.project,s='permlink ',j=Ext.getCmp(c+"-PANEL-"+this.fid),w=Ext.get(c+"-PANEL-"+this.fid),v=Ext.getCmp(c+"-FILE-"+this.fid),q=(k.fileModified)?Ext.util.JSON.decode(k.fileModified):false,t,u;w.unmask();if(this.prefix==="PP"||this.ftype==="TRANS"||this.prefix==="FNIEN"){j.permlink=""}else{if(this.ftype==="GGTRANS"){j.setTitle(j.originTitle);j.setIconClass("iconGoogle")}else{j.permlink=(k.xmlid!=="NULL")?s:"";j.setTitle(j.permlink+j.originTitle)}}v.setValue(k.content);if(this.ftype==="GGTRANS"){v.reIndentAll()}if(k.warn_tab&&!this.freadOnly){Ext.MessageBox.show({title:_("Warning"),msg:String.format(_("The file {0} contains some tab characters.
The editor have replace it with space characters."),this.fpath+this.fname),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.WARNING});v.manageCodeChange()}if(k.warn_encoding&&!this.freadOnly){Ext.MessageBox.show({title:_("Warning"),msg:String.format(_("The editor have modified automatically the file {0} into UTF-8 encoding."),this.fpath+this.fname),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.WARNING});v.setLine(1,'');Ext.getCmp(c+"-FILE-"+this.fid+"-btn-save").enable()}if(this.prefix==="FNT"||this.prefix==="FNIEN"){t="fileModified"}if(this.prefix==="FNU"){t=(this.ftype==="LANG")?"fileModifiedLang":"fileModifiedEN"}if(this.prefix==="FE"){t=(this.ftype==="LANG")?"fileModifiedLang":"fileModifiedEN"}if(this.prefix==="FNR"){t=(this.ftype==="LANG")?"fileModifiedLang":"fileModifiedEN"}if(k.fileModified&&this.prefix!=="AF"&&!f){this.storeRecord.set(t,k.fileModified);this.storeRecord.commit()}if(this.prefix==="AF"){this.storeRecord.data={};this.storeRecord.data.fileModified=false;if(k.fileModified){this.storeRecord.data.fileModified=k.fileModified}}if(k.fileModified&&!f&&((!PhDOE.user.isAnonymous&&q.user!==PhDOE.user.login)||(PhDOE.user.isAnonymous&&q.anonymousIdent!==PhDOE.user.anonymousIdent))){if(q.isAnonymous&&!PhDOE.user.isAnonymous&&q.fromModule==="workInProgress"){Ext.MessageBox.show({title:_("Information"),msg:String.format(_("File modified by {0} (anonymous user) but you are an authenticated user, so you can modify it."),q.user),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.INFO})}else{if(q.isAnonymous&&!PhDOE.user.isAnonymous&&q.fromModule==="PatchesForReview"){new ui.cmp.AnonymousPatchWin({fidDB:q.fidDB,fid:this.fid,prefix:this.prefix,ftype:q.ftype,fpath:this.fpath,fname:this.fname,curTab:Ext.getCmp(this.prefix+"-"+this.fid)})}else{if(!this.freadOnly){Ext.getCmp(c+"-FILE-"+this.fid+"-grp-save").disable();Ext.getCmp(c+"-FILE-"+this.fid+"-grp-undoRedo").disable();Ext.getCmp(c+"-FILE-"+this.fid+"-grp-tools").disable()}u=Ext.MessageBox.show({title:_("Information"),msg:String.format(_("File modified by {0}."),q.user),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.INFO});u.getDialog().mask.resize(w.getSize().width,w.getSize().height);u.getDialog().mask.alignTo(w.dom,"tl")}}}else{if(c=="FNT-TRANS"){var x=new RegExp("");v.insertLine(1,"");v.insertLine(2,"");if(!Ext.isEmpty(v.getLine(4))){v.insertLine(3,"")}v.manageCodeChange()}}}},callback:function(){var h=Ext.getCmp(this.prefix+"-"+this.fid);if(this.prefix==="FNT"){if(this.ftype==="TRANS"){h.panTRANSLoaded=true}if(this.ftype==="GGTRANS"||this.ftype==="EN"){h.panTRANSSecondLoaded=true}}if(this.prefix==="FNU"){if(this.ftype==="LANG"){h.panLANGLoaded=true}if(this.ftype==="EN"){h.panENLoaded=true}}if(this.prefix==="FE"){if(this.ftype==="LANG"){h.panLANGLoaded=true}if(this.ftype==="EN"){h.panENLoaded=true}}if(this.prefix==="FNR"){if(this.ftype==="LANG"){h.panLANGLoaded=true}if(this.ftype==="EN"){h.panENLoaded=true}}if(this.prefix==="FNIEN"){h.panLANGLoaded=true}if(this.prefix==="AF"){h.panLoaded=true}Ext.getCmp("main-panel").fireEvent("tabLoaded",this.prefix,this.fid)}})};Ext.namespace("ui","ui.task");ui.task.GetGGTranslation=function(c){Ext.apply(this,c);Ext.get("GGTranslate-result").dom.innerHTML="";Ext.getCmp("GGTranslate-btn").disable();Ext.getCmp("GGTranslate-btn").setText(_("Please, wait..."));XHR({scope:this,params:{task:"getGGTranslation",str:this.str},success:function(d){var e=Ext.util.JSON.decode(d.responseText);Ext.get("GGTranslate-result").dom.innerHTML=Ext.util.Format.htmlEncode(e.translation);Ext.getCmp("GGTranslate-btn").setText(_("Translate !"));Ext.getCmp("GGTranslate-btn").enable()}})};Ext.namespace("ui","ui.task");ui.task.LoadConfigTask=function(c){Ext.apply(this,c);XHR({params:{task:"getConf"},success:function(d){var e=Ext.decode(d.responseText);PhDOE.user.login=e.mess.userLogin;PhDOE.user.userID=e.mess.userID;PhDOE.user.lang=e.mess.userLang;PhDOE.user.authService=e.mess.authService;PhDOE.user.authServiceID=e.mess.authServiceID;PhDOE.user.isAnonymous=e.mess.userIsAnonymous;PhDOE.user.isGlobalAdmin=e.mess.userIsGlobalAdmin;PhDOE.user.isLangAdmin=e.mess.userIsLangAdmin;PhDOE.user.conf=e.mess.userConf;PhDOE.user.anonymousIdent=e.mess.userAnonymousIdent;PhDOE.project=e.mess.project;PhDOE.app.conf=e.mess.appConf;if(e.mess.topicInfo&&e.mess.topicInfo.lang){PhDOE.topic.lang.author=e.mess.topicInfo.lang.author;PhDOE.topic.lang.content=e.mess.topicInfo.lang.content;PhDOE.topic.lang.topicDate=Date.parseDate(e.mess.topicInfo.lang.topicDate,"Y-m-d H:i:s");PhDOE.topic.lang.topicDate=PhDOE.topic.lang.topicDate.format(_("Y-m-d, H:i"))}if(e.mess.topicInfo&&e.mess.topicInfo.global){PhDOE.topic.global.author=e.mess.topicInfo.global.author;PhDOE.topic.global.content=e.mess.topicInfo.global.content;PhDOE.topic.global.topicDate=Date.parseDate(e.mess.topicInfo.global.topicDate,"Y-m-d H:i:s");PhDOE.topic.global.topicDate=PhDOE.topic.global.topicDate.format(_("Y-m-d, H:i"))}Ext.get("appTheme").dom.href=PhDOE.user.conf.main.theme;PhDOE.drawInterface()}})};Ext.namespace("ui","ui.task");ui.task.MarkDeleteTask=function(c){Ext.apply(this,c);Ext.MessageBox.confirm(_("Confirm"),_("This action will mark this file as need deleted.

You need commit this change to take it effect.

Please, confirm this action."),function(d){if(d==="yes"){Ext.getBody().mask(' '+_("Please, wait..."));XHR({scope:this,params:{task:"markAsNeedDelete",FilePath:PhDOE.user.lang+this.fpath,FileName:this.fname},success:function(e){var f=Ext.util.JSON.decode(e.responseText);Ext.getBody().unmask();ui.cmp.WorkTreeGrid.getInstance().addRecord(f.id,PhDOE.user.lang+this.fpath,this.fname,"delete");this.storeRecord.set("fileModified",'{"user":"'+PhDOE.user.login+'", "anonymousIdent":"'+PhDOE.user.anonymousIdent+'"}')}})}},this)};Ext.namespace("ui","ui.task");ui.task.MoveToPatch=function(c){Ext.apply(this,c);var d=[];Ext.each(this.nodesToAdd,function(e){d.push(e.attributes.idDB)});Ext.getBody().mask(' '+_("Please, wait..."));XHR({scope:this,params:{task:"moveToPatch",patchID:this.patchID,filesID:d.join(",")},success:function(){Ext.getBody().unmask();ui.cmp.PatchesTreeGrid.getInstance().addToPatch(this.patchID,this.patchName,this.nodesToAdd,this.patchDescription,this.patchEmail);if(this.nodesToAdd){Ext.each(this.nodesToAdd,function(e){ui.cmp.WorkTreeGrid.getInstance().delRecord(e.attributes.idDB)})}},failure:function(e){var f=Ext.util.JSON.decode(e.responseText);Ext.getBody().unmask();Ext.MessageBox.alert("Error",f.err)}})};Ext.namespace("ui","ui.task");ui.task.MoveToWork=function(c){Ext.apply(this,c);var d=[];Ext.each(this.nodesToAdd,function(e){d.push(e.attributes.idDB)});Ext.getBody().mask(' '+_("Please, wait..."));XHR({scope:this,params:{task:"moveToWork",filesID:d.join(",")},success:function(){Ext.getBody().unmask();ui.cmp.WorkTreeGrid.getInstance().addToWork(this.nodesToAdd);if(this.nodesToAdd){Ext.each(this.nodesToAdd,function(e){ui.cmp.PatchesTreeGrid.getInstance().delRecord(e.attributes.idDB)})}},failure:function(e){var f=Ext.util.JSON.decode(e.responseText);Ext.getBody().unmask();Ext.MessageBox.alert("Error",f.err)}})};Ext.namespace("ui","ui.task","ui.task._PingTask");ui.task.PingTask=function(){this.task=new Ext.util.DelayedTask(function(){XHR({scope:this,params:{task:"ping"},success:function(d){var e=Ext.util.JSON.decode(d.responseText),c;if(e.ping!=="pong"){this.onPingFailed()}else{if(PhDOE.user.lang!=="en"){c=false;if(ui.cmp.PendingTranslateGrid.getInstance().store.getTotalCount()!==e.totalData.NbPendingTranslate){ui.cmp.PendingTranslateGrid.getInstance().store.reload();c=true}if(ui.cmp.StaleFileGrid.getInstance().store.getTotalCount()!==e.totalData.NbPendingUpdate){ui.cmp.StaleFileGrid.getInstance().store.reload();c=true}if(ui.cmp.ErrorFileGrid.getInstance().store.getTotalCount()!==e.totalData.NbFilesError){ui.cmp.ErrorFileGrid.getInstance().store.reload();c=true}if(ui.cmp.PendingReviewGrid.getInstance().store.getTotalCount()!==e.totalData.NbPendingReview){ui.cmp.PendingReviewGrid.getInstance().store.reload();c=true}if(ui.cmp.NotInENGrid.getInstance().store.getTotalCount()!==e.totalData.NbNotInEn){ui.cmp.NotInENGrid.getInstance().store.reload();c=true}if(c){ui.cmp.PortletSummary.getInstance().store.reload()}}if(e.totalData.lastInfoDate!==PhDOE.lastInfoDate){ui.cmp.PortletInfo.getInstance().store.reload()}if(e.totalData.topicInfo){e.totalData.topicInfo.topicDate=Date.parseDate(e.totalData.topicInfo.topicDate,"Y-m-d H:i:s");e.totalData.topicInfo.topicDate=e.totalData.topicInfo.topicDate.format(_("Y-m-d, H:i"));if(e.totalData.topicInfo.topicDate!=PhDOE.topic.topicDate){PhDOE.topic.author=e.totalData.topicInfo.author;PhDOE.topic.content=e.totalData.topicInfo.content;PhDOE.topic.topicDate=e.totalData.topicInfo.topicDate;PhDOE.setTopic()}}}},failure:function(){this.onPingFailed()}});this.task.delay(30000)},this)};ui.task.PingTask.prototype.delay=function(d,f,e,c){this.task.delay(d,f,e,c)};ui.task.PingTask.prototype.cancel=function(){this.task.cancel()};ui.task.PingTask.prototype.onPingFailed=function(){this.cancel();var d=new Ext.ux.Notification({iconCls:"iconError",title:_("Connection lost"),html:String.format(_("Retrying in {0} second(s)."),"30"),autoDestroy:false});d.show(document);this.delay(30000);var e=29;var c=new Ext.util.DelayedTask(function(){if(e>0){d.setMessage(String.format(_("Retrying in {0} second(s)."),e));e-=1;c.delay(1000)}else{if(e==0){d.animHide()}}});c.delay(1000)};ui.task._PingTask.instance=null;ui.task.PingTask.getInstance=function(){if(!ui.task._PingTask.instance){ui.task._PingTask.instance=new ui.task.PingTask()}return ui.task._PingTask.instance};Ext.namespace("ui","ui.task");ui.task.SaveFileTask=function(d){Ext.apply(this,d);var c=this.prefix+"-"+this.ftype,e=Ext.MessageBox.wait(_("Saving data...")),f=Ext.getCmp(this.prefix+"-"+this.ftype+"-FILE-"+this.fid).getValue();XHR({scope:this,params:{task:"saveFile",filePath:this.fpath,fileName:this.fname,fileLang:this.lang,fileContent:f},success:function(h){var j=Ext.util.JSON.decode(h.responseText);if(this.prefix==="FNU"){if(this.ftype==="EN"){this.storeRecord.set("en_revision",j.revision);this.storeRecord.set("fileModifiedEN",'{"user":"'+PhDOE.user.login+'", "anonymousIdent":"'+PhDOE.user.anonymousIdent+'"}')}else{this.storeRecord.set("revision",j.en_revision);this.storeRecord.set("fileModifiedLang",'{"user":"'+PhDOE.user.login+'", "anonymousIdent":"'+PhDOE.user.anonymousIdent+'"}');this.storeRecord.set("maintainer",j.maintainer)}this.storeRecord.commit()}if(this.prefix==="FE"){if(this.ftype==="EN"){this.storeRecord.set("fileModifiedEN",'{"user":"'+PhDOE.user.login+'", "anonymousIdent":"'+PhDOE.user.anonymousIdent+'"}');this.storeRecord.commit()}else{this.storeRecord.set("maintainer",j.maintainer);this.storeRecord.set("fileModifiedLang",'{"user":"'+PhDOE.user.login+'", "anonymousIdent":"'+PhDOE.user.anonymousIdent+'"}');this.storeRecord.commit()}}if(this.prefix==="FNR"){if(this.ftype==="EN"){this.storeRecord.set("reviewed",j.reviewed);this.storeRecord.set("fileModifiedEN",'{"user":"'+PhDOE.user.login+'", "anonymousIdent":"'+PhDOE.user.anonymousIdent+'"}');this.storeRecord.commit()}else{this.storeRecord.set("reviewed",j.reviewed);this.storeRecord.set("maintainer",j.reviewed_maintainer);this.storeRecord.set("fileModifiedLang",'{"user":"'+PhDOE.user.login+'", "anonymousIdent":"'+PhDOE.user.anonymousIdent+'"}');this.storeRecord.commit()}}if(this.prefix==="AF"){this.storeRecord.getUI().addClass("fileModifiedByMe")}Ext.getCmp(this.prefix+"-"+this.ftype+"-FILE-"+this.fid).setOriginalContent(f);ui.cmp.WorkTreeGrid.getInstance().delRecord(j.id);ui.cmp.PatchesTreeGrid.getInstance().delRecord(j.id);ui.cmp.WorkTreeGrid.getInstance().addRecord(j.id,this.lang+this.fpath,this.fname,"update");Ext.getCmp(c+"-FILE-"+this.fid+"-btn-save").disable();Ext.getCmp(c+"-FILE-"+this.fid).isModified=false;Ext.getCmp(c+"-PANEL-"+this.fid).setTitle(Ext.getCmp(c+"-PANEL-"+this.fid).permlink+Ext.getCmp(c+"-PANEL-"+this.fid).originTitle);var g;if(this.lang==="en"){g=Ext.getCmp(this.prefix+"-LANG-FILE-"+this.fid)}else{g=Ext.getCmp(this.prefix+"-EN-FILE-"+this.fid)}if(this.ftype==="ALL"||!g.isModified){Ext.getCmp(this.prefix+"-"+this.fid).setTitle(Ext.getCmp(this.prefix+"-"+this.fid).originTitle)}e.hide();PhDOE.notify("info",_("Document saved"),String.format(_("Document

{0}

was saved successfully !"),this.lang+this.fpath+this.fname))},failure:function(g){var h=Ext.util.JSON.decode(g.responseText);e.hide();if(h.XmlError&&h.XmlError!="no_error"){Ext.MessageBox.alert(_("XML Errors"),_("There is somes XML's errors.

You must fix it before saving this file.

Valid this window to show this errors."),function(){new ui.cmp.CheckXmlWin({errors:h.XmlError})})}if(h.type){PhDOE.winForbidden(h.type)}}})};Ext.namespace("ui","ui.task");ui.task.SaveTransFileTask=function(d){Ext.apply(this,d);var c=this.prefix+"-"+this.ftype,e=Ext.MessageBox.wait(_("Saving data...")),f=Ext.getCmp(this.prefix+"-"+this.ftype+"-FILE-"+this.fid).getValue();XHR({scope:this,params:{task:"saveFile",type:"trans",filePath:this.fpath,fileName:this.fname,fileLang:this.lang,fileContent:f},success:function(g){var h=Ext.util.JSON.decode(g.responseText);if(this.ftype!="NEW"){this.storeRecord.set("fileModified",'{"user":"'+PhDOE.user.login+'", "anonymousIdent":"'+PhDOE.user.anonymousIdent+'"}');this.storeRecord.commit()}else{this.storeRecord.data.node.reload()}Ext.getCmp(this.prefix+"-"+this.ftype+"-FILE-"+this.fid).setOriginalContent(f);ui.cmp.WorkTreeGrid.getInstance().addRecord(h.id,this.lang+this.fpath,this.fname,"new");Ext.getCmp(c+"-FILE-"+this.fid+"-btn-save").disable();Ext.getCmp(c+"-FILE-"+this.fid).isModified=false;Ext.getCmp(c+"-PANEL-"+this.fid).setTitle(Ext.getCmp(c+"-PANEL-"+this.fid).originTitle);Ext.getCmp(this.prefix+"-"+this.fid).setTitle(Ext.getCmp(this.prefix+"-"+this.fid).originTitle);e.hide();PhDOE.notify("info",_("Document saved"),String.format(_("Document

{0}

was saved successfully !"),this.lang+this.fpath+this.fname))},failure:function(g){var h=Ext.util.JSON.decode(g.responseText);e.hide();if(h.XmlError&&h.XmlError!="no_error"){Ext.MessageBox.alert(_("XML Errors"),_("There is somes XML's errors.

You must fix it before saving this file.

Valid this window to show this errors."),function(){new ui.cmp.CheckXmlWin({errors:h.XmlError})})}if(h.type){PhDOE.winForbidden(h.type)}}})};Ext.namespace("ui","ui.task");ui.task.SetFileProgressTask=function(c){Ext.apply(this,c);XHR({scope:this,params:{task:"SetFileProgress",idDB:this.idDB,progress:this.progress},failure:function(d){var e=Ext.util.JSON.decode(d.responseText),f;if(e.err){if(e.err=="file_dont_exist_in_workInProgress"){f=_("The file you want to change the estimated progress don't exist into the database.")}if(e.err=="file_isnt_owned_by_current_user"){f=_("The file you want to change the estimated progress isn't own by you.
You only can modify this information for yours files.")}}if(f){PhDOE.notify("error",_("Error"),f)}}})};Ext.namespace("ui","ui.task");ui.task.setTopicTask=function(c){Ext.apply(this,c);var d=this.isLang;XHR({scope:this,params:{task:"setTopic",content:this.content,lang:d?"lang":"global"},success:function(f){var g=Ext.util.JSON.decode(f.responseText),e=PhDOE.topic[d?"lang":"global"];e.author=g.author;e.content=g.content;e.topicDate=Date.parseDate(g.topicDate,"Y-m-d H:i:s");e.topicDate=e.topicDate.format(_("Y-m-d, H:i"));PhDOE.setTopic(d)}})};Ext.namespace("ui","ui.task","ui.task._SystemUpdateTask");ui.task._SystemUpdateTask.refresh_ui=function(){Ext.get("wizard-step-3").replaceClass("wizard-step-before","wizard-step-working");PhDOE.reloadAllStore();Ext.get("wizard-step-3").replaceClass("wizard-step-working","wizard-step-done");Ext.getCmp("btn-start-refresh").setIconClass("iconFinishRefresh");Ext.getCmp("btn-start-refresh").setText(_("Finish !"));Ext.getCmp("btn-start-refresh").setHandler(function(){Ext.getCmp("sys-update-win").close()});Ext.getCmp("btn-start-refresh").enable();ui.task.PingTask.getInstance().delay(30000);Ext.getCmp("sys-update-win").tools.close.setVisible(true)};ui.task._SystemUpdateTask.poll_apply_tool=new Ext.util.DelayedTask(function(){XHR({params:{task:"checkLockFile",lockFile:"project_"+PhDOE.project+"_lock_apply_tools"},success:function(){ui.task._SystemUpdateTask.poll_apply_tool.delay(5000)},failure:function(c){var d=Ext.util.JSON.decode(c.responseText);if(d&&d.success===false){Ext.get("wizard-step-2").replaceClass("wizard-step-working","wizard-step-done");new ui.task._SystemUpdateTask.refresh_ui()}else{ui.task._SystemUpdateTask.poll_apply_tool.delay(5000)}}})});ui.task._SystemUpdateTask.apply_tool=function(){Ext.get("wizard-step-2").replaceClass("wizard-step-before","wizard-step-working");XHR({params:{task:"applyTools"},success:function(){Ext.get("wizard-step-2").replaceClass("wizard-step-working","wizard-step-done");new ui.task._SystemUpdateTask.refresh_ui()},failure:function(){ui.task._SystemUpdateTask.poll_apply_tool.delay(5000)}})};ui.task._SystemUpdateTask.vcs_poll=new Ext.util.DelayedTask(function(){XHR({params:{task:"checkLockFile",lockFile:"project_"+PhDOE.project+"_lock_update_repository"},success:function(){ui.task._SystemUpdateTask.vcs_poll.delay(5000)},failure:function(c){var d=Ext.util.JSON.decode(c.responseText);if(d&&d.success===false){Ext.get("wizard-step-1").replaceClass("wizard-step-working","wizard-step-done");Ext.get("wizard-step-1.1").replaceClass("wizard-show","wizard-wait");new ui.task._SystemUpdateTask.apply_tool()}else{ui.task._SystemUpdateTask.vcs_poll.delay(5000)}}})});ui.task.SystemUpdateTask=function(){ui.task.PingTask.getInstance().cancel();Ext.get("wizard-step-1").replaceClass("wizard-step-before","wizard-step-working");Ext.get("wizard-step-1.1").replaceClass("wizard-wait","wizard-show");XHR({params:{task:"updateRepository"},success:function(){Ext.get("wizard-step-1").replaceClass("wizard-step-working","wizard-step-done");Ext.get("wizard-step-1.1").replaceClass("wizard-show","wizard-wait");new ui.task._SystemUpdateTask.apply_tool()},failure:function(c){var d=Ext.util.JSON.decode(c.responseText);if(d&&d.success===false){Ext.getCmp("sys-update-win").close();PhDOE.winForbidden(d.type)}else{ui.task._SystemUpdateTask.vcs_poll.delay(5000)}}})};Ext.namespace("ui","ui.task");ui.task.UpdateConfTask=function(c){Ext.apply(this,c);XHR({scope:this,params:{task:"confUpdate",module:this.module,itemName:this.itemName,value:this.value},success:function(){PhDOE.user.conf[this.module][this.itemName]=this.value;if(this.module=="newFile"&&this.itemName=="nbDisplay"){ui.cmp.PendingTranslateGrid.getInstance().store.reload()}if(this.module=="needUpdate"&&this.itemName=="nbDisplay"){ui.cmp.StaleFileGrid.getInstance().store.reload()}if(this.module=="error"&&(this.itemName=="skipNbLiteralTag"||this.itemName=="nbDisplay")){ui.cmp.ErrorFileGrid.getInstance().store.reload()}if(this.module=="reviewed"&&this.itemName=="nbDisplay"){ui.cmp.PendingReviewGrid.getInstance().store.reload()}if(this.module=="main"&&this.itemName=="displayENWork"){ui.cmp.WorkTreeGrid.getInstance().getRootNode().reload(function(){ui.cmp.PatchesTreeGrid.getInstance().getRootNode().reload()})}if(this.notify!==false){PhDOE.notify("info",_("Option saved"),_("Option has been saved successfully !"))}}})};Ext.namespace("ui","ui.task","ui.task._UpdateSingleFolderTask");ui.task._UpdateSingleFolderTask.getUpdateFolderResponse=function(c){XHR({params:{task:"getUpdateFolderResponse"},success:function(d){var e=Ext.util.JSON.decode(d.responseText);ui.task._UpdateSingleFolderTask.afterUpdate(e,c)}})};ui.task._UpdateSingleFolderTask.poll=new Ext.util.DelayedTask(function(){var f=arguments[0],d=f.attributes.id.split("/"),c,e=new Array();d.shift();c=d[0];e.push(f);XHR({params:{task:"checkLockFile",lockFile:"project_"+PhDOE.project+"_"+c+"_lock_update_folder"},success:function(){ui.task._UpdateSingleFolderTask.poll.delay(5000,null,this,e)},failure:function(g){var h=Ext.util.JSON.decode(g.responseText);if(h&&h.success===false){new ui.task._UpdateSingleFolderTask.getUpdateFolderResponse(f)}else{ui.task._UpdateSingleFolderTask.poll.delay(5000,null,this,e)}}})});ui.task._UpdateSingleFolderTask.afterUpdate=function(e,d){Ext.getBody().unmask();ui.task.PingTask.getInstance().delay(30000);var c=Ext.util.JSON.decode(e.result);d.reload(function(){Ext.iterate(c.newFiles,function(g,f){d.findChild("text",g).getUI().addClass("treeFileUpdated")})},this);PhDOE.reloadAllStore()};ui.task._UpdateSingleFolderTask.update=function(d){var c=new Array();c.push(d);Ext.getBody().mask(' '+_("Please, wait until update this folder..."));ui.task.PingTask.getInstance().cancel();XHR({params:{task:"updateFolder",path:d.id},success:function(e){var f=Ext.util.JSON.decode(e.responseText);ui.task._UpdateSingleFolderTask.afterUpdate(f,d)},failure:function(e){var f=Ext.util.JSON.decode(e.responseText);if(f&&f.success===false){ui.task.PingTask.getInstance().delay(30000);Ext.getBody().unmask();PhDOE.winForbidden()}else{ui.task._UpdateSingleFolderTask.poll.delay(5000,null,this,c)}}})};ui.task.UpdateSingleFolderTask=function(c){if(PhDOE.user.isAnonymous){Ext.getCmp("winVCSCommit").close();PhDOE.winForbidden();return}ui.task._UpdateSingleFolderTask.update(c)};Ext.namespace("ui","ui.task","ui.task._VCSCommitTask");ui.task._VCSCommitTask.getCommitResponse=function(){XHR({params:{task:"getCommitResponse"},success:function(c){var d=Ext.util.JSON.decode(c.responseText);ui.task._VCSCommitTask.afterCommit(d.mess)}})};ui.task._VCSCommitTask.poll=new Ext.util.DelayedTask(function(){XHR({params:{task:"checkLockFile",lockFile:"project_"+PhDOE.project+"_lock_"+PhDOE.user.login+"_commit"},success:function(){ui.task._VCSCommitTask.poll.delay(5000)},failure:function(c){var d=Ext.util.JSON.decode(c.responseText);if(d&&d.success===false){new ui.task._VCSCommitTask.getCommitResponse()}else{ui.task._VCSCommitTask.poll.delay(5000)}}})});ui.task._VCSCommitTask.afterCommit=function(c){Ext.getBody().unmask();ui.task.PingTask.getInstance().delay(30000);new Ext.Window({title:_("Status"),width:450,height:350,resizable:false,modal:true,autoScroll:true,bodyStyle:"background-color: white; padding: 5px;",html:c.join("
"),buttons:[{text:_("Close"),handler:function(){this.ownerCt.ownerCt.close()}}]}).show();PhDOE.reloadAllStore()};ui.task._VCSCommitTask.commit=function(h,g){Ext.getBody().mask(' '+_("Please, wait until commit..."));var c=[],f,e,d;for(d=0;d0){for(h=0;h"}Ext.MessageBox.show({title:"Warning",icon:Ext.MessageBox.INFO,buttons:Ext.MessageBox.YESNOCANCEL,msg:(l.length>1)?String.format(_("There are {0} files to close before commit.

{1}

Would you like me to close them for you ?"),l.length,m):String.format(_("There is {0} file to close before commit.

{1}

Would you like me to close it for you ?"),l.length,m),fn:function(u){if(u==="yes"){for(var t=0;t'+PhDOE.app.name+'
'+PhDOE.app.name+" ver "+PhDOE.app.ver+"
UI: "+PhDOE.app.uiRevision+"
Copyright © 2008-2012 The PHP Group
"+_("Author:")+' Yannick Torrès '+_('and others')+"
"},{title:_("Help and support"),bodyStyle:"padding:15px",html:'
'},{title:_("Credits"),bodyStyle:"padding:15px",html:'
"},{title:_("License"),autoLoad:{url:"./LICENSE"}}]}});ui.cmp.About.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._AnonymousPatchWin");ui.cmp._AnonymousPatchWin.form=Ext.extend(Ext.FormPanel,{frame:true,labelWidth:5,bodyStyle:"padding:5px 5px 0",defaultType:"radio",initComponent:function(c){Ext.apply(this,{items:[{xtype:"displayfield",value:_("File: ")+this.fpath+this.fname+"

"+_('You have opened a modified file from the "Patch for review" module.
This file has been modified by an anonymous user.

Please choose one of the following actions:')},{boxLabel:_("Continue to modify this file"),name:"choice",inputValue:"continue",checked:true,listeners:{afterrender:function(){new Ext.ToolTip({title:_("Continue to modify this file"),target:"x-form-el-"+this.id,anchor:"right",html:"
"+_("This action will open this file for modification. Once your modification finish, just save it and this file will be own by you."),width:250,autoHide:true})}}},{boxLabel:_("Reject this patch"),name:"choice",inputValue:"reject",listeners:{afterrender:function(){new Ext.ToolTip({title:_("Reject this patch"),target:"x-form-el-"+this.id,anchor:"right",html:"
"+_("This action will close this file, and clear the local change. This file will return into his original version, as it is on VCS server."),width:250,autoHide:true})}}},{boxLabel:_("Validate this patch"),name:"choice",inputValue:"validate",listeners:{afterrender:function(){new Ext.ToolTip({title:_("Validate this patch"),target:"x-form-el-"+this.id,anchor:"right",html:"
"+_("This action changes the owner of the modification and register it under your name. The file will appear under your name and you can then commit it."),width:250,autoHide:true})}}}]});ui.cmp._AnonymousPatchWin.form.superclass.initComponent.call(this)}});ui.cmp.AnonymousPatchWin=Ext.extend(Ext.Window,{id:"anonymous-patch-win",title:_("Anonymous patch manager"),iconCls:"iconPatch",width:450,height:250,layout:"fit",resizable:false,modal:true,autoScroll:true,closable:false,closeAction:"close",buttons:[{text:_("Next"),iconCls:"iconArrowRight",handler:function(){var d=this.ownerCt.ownerCt,c=d.items.items[0].getForm().getValues().choice;switch(c){case"continue":d.close();break;case"reject":ui.task.ClearLocalChangeTask({ftype:d.ftype,fpath:d.fpath,fname:d.fname,noConfirm:true});break;case"validate":ui.task.ChangeFileOwner({fileIdDB:d.fidDB,newOwnerID:PhDOE.user.userID,from:d,fromType:"tab"});break}}}],initComponent:function(){Ext.apply(this,{items:[new ui.cmp._AnonymousPatchWin.form({fpath:this.fpath,fname:this.fname})]});ui.cmp.AnonymousPatchWin.superclass.initComponent.call(this);this.show()}});Ext.namespace("ui","ui.cmp","ui.cmp._BuildStatus");ui.cmp._BuildStatus.display=function(c){Ext.apply(this,c);if(Ext.getCmp("main-panel").findById("last_failed_build_"+this.lang)){Ext.getCmp("main-panel").remove("last_failed_build_"+this.lang)}Ext.getCmp("main-panel").add({xtype:"panel",id:"last_failed_build_"+this.lang,title:String.format(_("Last failed build for {0}"),Ext.util.Format.uppercase(this.lang)),tabTip:String.format(_("Last failed build for the documentation {0}"),Ext.util.Format.uppercase(this.lang)),closable:true,autoScroll:true,iconCls:"iconCheckBuild",html:'
'});Ext.getCmp("main-panel").setActiveTab("last_failed_build_"+this.lang);Ext.getCmp("main-panel").el.mask(_("Please, wait..."));XHR({scope:this,params:{task:"getFailedBuildData",idFailedBuild:this.idFailedBuild},success:function(d){var e=Ext.decode(d.responseText),f=e.mess.join("
");if(e.state==="truncate"){Ext.get("check-build-content").dom.innerHTML=f+'
'+_("This log is too large and have been truncated. Use the following button to download the full content of it.")+'
';new Ext.Button({scope:this,text:_("Download the full content of this log"),renderTo:"check-build-content-download-btn",style:{margin:"auto"},handler:function(){window.location.href="./do/downloadFailedBuildLog?idFailedBuild="+this.idFailedBuild+"&csrfToken="+csrfToken}})}else{Ext.get("check-build-content").dom.innerHTML=f}Ext.getCmp("main-panel").el.unmask()}})};ui.cmp._BuildStatus.ds=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getFailedBuild"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"lang"},{name:"date",type:"date",dateFormat:"Y-m-d H:i:s"}]})});ui.cmp._BuildStatus.ds.setDefaultSort("date","desc");ui.cmp._BuildStatus.rendererLanguage=function(d){var c={cs:"cz",sr:"rs",sv:"se"};return'
'+d+"
"};ui.cmp._BuildStatus.columns=[{id:"date",header:_("Date"),sortable:true,dataIndex:"date",renderer:Ext.util.Format.dateRenderer(_("Y-m-d, H:i"))},{header:_("Language"),width:45,sortable:true,dataIndex:"lang",renderer:ui.cmp._BuildStatus.rendererLanguage}];ui.cmp._BuildStatus.menu=Ext.extend(Ext.menu.Menu,{setRowIndex:function(c){this.rowIndex=c},initComponent:function(){Ext.apply(this,{items:[{scope:this,text:""+_("View in a new Tab")+"",iconCls:"iconOpenInTab",handler:function(){this.grid.fireEvent("rowdblclick",this.grid,this.rowIndex,this.event)}}]});ui.cmp._BuildStatus.menu.superclass.initComponent.call(this)}});ui.cmp.BuildStatus=Ext.extend(Ext.grid.GridPanel,{loadMask:true,bodyBorder:false,autoExpandColumn:"date",store:ui.cmp._BuildStatus.ds,columns:ui.cmp._BuildStatus.columns,view:new Ext.grid.GridView({forceFit:true}),listeners:{render:function(){this.store.load.defer(20,this.store)}},onRowdblclick:function(c,g,f){var d=this.store.getAt(g);new ui.cmp._BuildStatus.display({idFailedBuild:d.id,lang:d.data.lang})},onRowContextMenu:function(c,f,d){if(!this.menu){this.menu=new ui.cmp._BuildStatus.menu({grid:c,rowIdx:"",event:d})}d.stopEvent();this.getSelectionModel().selectRow(f);this.menu.setRowIndex(f);this.menu.showAt(d.getXY())},initComponent:function(c){ui.cmp.BuildStatus.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowdblclick",this.onRowdblclick,this);this.on("rowcontextmenu",this.onRowContextMenu,this)}});Ext.namespace("ui","ui.cmp","ui.cmp._ChangeFileOwner");ui.cmp._ChangeFileOwner.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getVCSUsers"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",fields:[{name:"userID"},{name:"authService"},{name:"userName"}]}),sortInfo:{field:"authService",direction:"ASC"}});ui.cmp.ChangeFileOwner=Ext.extend(Ext.Window,{title:_("Change file's owner"),iconCls:"iconSwitchLang",width:550,height:255,layout:"form",resizable:false,modal:true,autoScroll:true,closeAction:"close",padding:10,buttons:[{text:_("Save"),handler:function(){var d=this.ownerCt.ownerCt,c=d.items.items[1].items.items[0].getValue();new ui.task.ChangeFileOwner({fileIdDB:d.fileIdDB,newOwnerID:c,from:d})}},{text:_("Close"),handler:function(){var c=this.ownerCt.ownerCt;c.close()}}],initComponent:function(){var c=this;Ext.apply(this,{defaults:{labelWidth:120},items:[{xtype:"fieldset",title:_("Information"),iconCls:"iconInfo",width:515,items:[{xtype:"displayfield",fieldLabel:_("File"),value:this.fileFolder+this.fileName},{xtype:"displayfield",fieldLabel:_("Current owner"),value:this.currentOwner}]},{xtype:"fieldset",title:_("Action"),iconCls:"iconSwitchLang",width:515,items:[{xtype:"combo",name:"newOwner",fieldLabel:_("New owner"),editable:false,store:ui.cmp._ChangeFileOwner.store,triggerAction:"all",valueField:"userID",tpl:new Ext.XTemplate('
',"{authService} - {userName}","
"),displayField:"userName",listeners:{afterrender:function(d){d.store.load({callback:function(){d.setValue(PhDOE.user.userID)}})}}}]}]});ui.cmp.ChangeFileOwner.superclass.initComponent.call(this);this.show()}});Ext.namespace("ui","ui.cmp");ui.cmp.Chat=Ext.extend(Ext.Window,{id:"win-chat",iconCls:"iconChat",layout:"fit",width:800,height:600,modal:true,plain:true,bodyStyle:"color:#000",closeAction:"hide",initComponent:function(){var c=PhDOE.user.login;if(PhDOE.user.isAnonymous){c="an%3F%3F%3F"}Ext.apply(this,{title:_("Chat with us on IRC !"),items:[new Ext.ux.IFrameComponent({id:"frame-win-chat",url:"https://widget.mibbit.com/?settings=8eec4034df2eb666b0600bdfe151529a&server=irc.umich.edu&channel=%23php.doc&nick=poe_"+c})]});ui.cmp.Chat.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp");ui.cmp.CheckBuildPrompt=Ext.extend(Ext.Window,{title:_("Check build"),iconCls:"iconCheckBuild",layout:"form",width:350,height:200,resizable:false,modal:true,bodyStyle:"padding:5px 5px 0",labelAlign:"top",buttons:[{id:"win-check-build-btn-submit",text:_("Go !"),handler:function(){new ui.task.CheckBuildTask();this.ownerCt.ownerCt.close()}}],initComponent:function(){Ext.apply(this,{items:[{xtype:"panel",modal:false,baseCls:"x-plain",bodyStyle:"padding:5px 5px 0",html:_("You're about to check the build via this command:")+"

/usr/bin/php configure.php --with-lang="+PhDOE.user.lang+'
"},{xtype:"checkbox",id:"option-xml-details",name:"option-xml-details",checked:false,hideLabel:true,boxLabel:_("Enable detailed XML error messages"),listeners:{check:function(e,d){Ext.get("option-xml-details-span").dom.style.visibility=(d)?"visible":"hidden";Ext.get("option-xml-details-div").dom.style.visibility=(d)?"visible":"hidden"}}}]});ui.cmp.CheckBuildPrompt.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._CheckDoc");ui.cmp._CheckDoc.ds=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getCheckDocData"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"path"},{name:"extension"},{name:"check_oldstyle",type:"int"},{name:"check_undoc",type:"int"},{name:"check_roleerror",type:"int"},{name:"check_badorder",type:"int"},{name:"check_noseealso",type:"int"},{name:"check_noreturnvalues",type:"int"},{name:"check_noparameters",type:"int"},{name:"check_noexamples",type:"int"},{name:"check_noerrors",type:"int"}]})});ui.cmp._CheckDoc.ds.setDefaultSort("extension","asc");ui.cmp._CheckDoc.renderer=function(d,c){if(d>0){c.css="check_doc_cell";c.attr="ext:qtip=\" "+_("Double-click the cell to open the file selection")+'"';return d}else{return}};ui.cmp._CheckDoc.columns=[new Ext.grid.RowNumberer(),{id:"extension",header:_("Extension"),sortable:true,dataIndex:"extension"},{header:_("Not documented"),width:45,sortable:true,dataIndex:"check_undoc",renderer:ui.cmp._CheckDoc.renderer},{header:_("Old style"),width:45,sortable:true,dataIndex:"check_oldstyle",renderer:ui.cmp._CheckDoc.renderer},{header:_("Bad refsect1 order"),width:45,sortable:true,dataIndex:"check_badorder",renderer:ui.cmp._CheckDoc.renderer},{header:_("No parameters"),width:45,sortable:true,dataIndex:"check_noparameters",renderer:ui.cmp._CheckDoc.renderer},{header:_("No return values"),width:45,sortable:true,dataIndex:"check_noreturnvalues",renderer:ui.cmp._CheckDoc.renderer},{header:_("No examples"),width:45,sortable:true,dataIndex:"check_noexamples",renderer:ui.cmp._CheckDoc.renderer},{header:_("No errors section"),width:45,sortable:true,dataIndex:"check_noerrors",renderer:ui.cmp._CheckDoc.renderer},{header:_("No see also"),width:45,sortable:true,dataIndex:"check_noseealso",renderer:ui.cmp._CheckDoc.renderer},{header:_("Refsect1 role error"),width:45,sortable:true,dataIndex:"check_roleerror",renderer:ui.cmp._CheckDoc.renderer}];ui.cmp._CheckDoc.fs=new Ext.data.SimpleStore({fields:[{name:"id"},{name:"file"}]});ui.cmp._CheckDoc.FileGrid=Ext.extend(Ext.grid.GridPanel,{id:"check-doc-file-grid",store:ui.cmp._CheckDoc.fs,loadMask:true,bodyBorder:false,autoExpandColumn:"file",sm:new Ext.grid.RowSelectionModel({}),columns:[new Ext.grid.RowNumberer(),{id:"file",header:_("Files"),sortable:true,dataIndex:"file"}],onRowClick:function(){Ext.getCmp("check-doc-btn-open-selected-files").enable()},onRowContextMenu:function(c,f,d){d.stopEvent();c.getSelectionModel().selectRow(f)},onRowDblClick:function(c,d){ui.cmp.RepositoryTree.getInstance().openFile("byPath","en"+c.fpath,c.store.getAt(d).data.file);Ext.getCmp("check-doc-file-win").close()},initComponent:function(c){ui.cmp._CheckDoc.FileGrid.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowcontextmenu",this.onRowContextMenu,this);this.on("rowdblclick",this.onRowDblClick,this);this.on("rowclick",this.onRowClick,this)}});ui.cmp._CheckDoc.FileWin=Ext.extend(Ext.Window,{id:"check-doc-file-win",title:_("Files"),width:450,height:350,labelWidth:50,resizable:false,modal:true,autoScroll:true,layout:"fit",iconCls:"iconFiles",buttons:[{text:_("Open all files"),handler:function(){var e=Ext.getCmp("check-doc-file-win"),c=ui.cmp._CheckDoc.fs,d;PhDOE.AFfilePendingOpen=[];for(d=0;d"+_("Open in a new Tab")+"",iconCls:"iconOpenInTab",handler:function(){this.openTab(this.ctxRowIndex);this.menu.hide()}}]})}this.getSelectionModel().selectRow(f);d.stopEvent();if(this.ctxRowIndex){this.ctxRowIndex=null}this.ctxRowIndex=f;this.menu.showAt(d.getXY())},initComponent:function(c){this.tbar=[{xtype:"label",text:_("Status: ")},{xtype:"combo",typeAhead:true,triggerAction:"all",lazyRender:true,mode:"local",store:new Ext.data.ArrayStore({id:0,fields:["myId","displayText"],data:[["all",_("All status")],["FTP_CONNECT","FTP_CONNECT"],["FTP_LOGIN","FTP_LOGIN"],["FTP_NO_FILE","FTP_NO_FILE"],["HTTP_CONNECT","HTTP_CONNECT"],["HTTP_INTERNAL_ERROR","HTTP_INTERNAL_ERROR"],["HTTP_NOT_FOUND","HTTP_NOT_FOUND"],["HTTP_MOVED","HTTP_MOVED"],["HTTP_WRONG_HEADER","HTTP_WRONG_HEADER"],["SUCCESS","SUCCESS"],["UNKNOWN_HOST","UNKNOWN_HOST"]]}),value:"all",valueField:"myId",displayField:"displayText",editable:false,listeners:{select:function(f,d){var e=d.id;if(e==="all"){Ext.getCmp("check-entities-grid").store.clearFilter()}else{Ext.getCmp("check-entities-grid").store.filter("result",d.id)}}}}];ui.cmp.CheckEntities.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowcontextmenu",this.onContextClick,this);this.on("rowdblclick",this.onRowdblclick,this)}});Ext.namespace("ui","ui.cmp");ui.cmp.CheckEntitiesPrompt=Ext.extend(Ext.Window,{title:_("Check entities"),iconCls:"iconRun",id:"win-check-entities",layout:"fit",width:250,height:140,resizable:false,modal:true,bodyStyle:"padding:5px 5px 0; text-align: center;",labelAlign:"top",closeAction:"hide",buttons:[{id:"win-check-entities-btn",text:_("Go !"),handler:function(){new ui.task.CheckEntitiesTask();Ext.getCmp("win-check-entities").hide()}}],initComponent:function(){Ext.apply(this,{items:[{xtype:"panel",modal:false,baseCls:"x-plain",bodyStyle:"padding:5px 5px 0",html:_("You're about to check all entities.

This action takes time.")}]});ui.cmp.CheckEntitiesPrompt.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp");ui.cmp.CheckXmlWin=Ext.extend(Ext.Window,{title:_("XML Errors"),iconCls:"iconXml",width:650,height:350,layout:"fit",resizable:false,modal:true,autoScroll:true,closeAction:"close",buttons:[{text:_("Close"),handler:function(){this.ownerCt.ownerCt.close()}}],store:new Ext.data.JsonStore({root:"Items",totalProperty:"nbItems",fields:[{name:"line"},{name:"libel"}]}),addErrorsInStore:function(){var c=Ext.data.Record.create({name:"line"},{name:"libel"});this.store.removeAll();for(i=0;i"+Ext.util.Format.htmlEncode(this.errors[i].ctx1)}))}this.store.sort("line","desc")},initComponent:function(){Ext.apply(this,{items:[{xtype:"grid",store:this.store,loadMask:true,autoExpandColumn:"libel_id",colModel:new Ext.grid.ColumnModel([{header:_("Line"),dataIndex:"line",sortable:true},{id:"libel_id",header:_("Libel"),dataIndex:"libel"}]),sm:new Ext.grid.RowSelectionModel({singleSelect:true})}]});ui.cmp.CheckXmlWin.superclass.initComponent.call(this);this.addErrorsInStore();this.show()}});Ext.namespace("ui","ui.cmp","ui.cmp._CommitLogManager");ui.cmp._CommitLogManager.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getCommitLogMessage"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"text"}]})});ui.cmp._CommitLogManager.editor=new Ext.ux.grid.RowEditor({saveText:_("Update"),cancelText:_("Cancel"),listeners:{afteredit:function(e,d,c){XHR({params:{task:"saveLogMessage",messID:c.data.id,mess:c.data.text},success:function(){c.commit();PhDOE.notify("info",_("Message updated"),_("Log Message was updated successfully !"))},failure:function(){PhDOE.winForbidden()}})}}});ui.cmp._CommitLogManager.cm=new Ext.grid.ColumnModel([new Ext.grid.RowNumberer(),{id:"log_msg",header:_("Log message"),dataIndex:"text",editor:{xtype:"textarea"},renderer:function(c){return c.split("\n").join("
")}}]);ui.cmp._CommitLogManager.sm=new Ext.grid.RowSelectionModel({singleSelect:true});ui.cmp._CommitLogManager.menu=Ext.extend(Ext.menu.Menu,{setRowIdx:function(c){this.rowIdx=c},initComponent:function(){Ext.apply(this,{items:[{scope:this,text:_("Delete this Log Message"),iconCls:"iconTrash",handler:function(){XHR({scope:this,params:{task:"deleteLogMessage",messID:ui.cmp._CommitLogManager.store.getAt(this.rowIdx).data.id},success:function(){ui.cmp._CommitLogManager.store.remove(ui.cmp._CommitLogManager.store.getAt(this.rowIdx));PhDOE.notify("info",_("Message deleted"),_("Log Message was deleted successfully !"))},failure:function(){PhDOE.winForbidden()}})}}]});ui.cmp._CommitLogManager.menu.superclass.initComponent.call(this)}});ui.cmp._CommitLogManager.grid=Ext.extend(Ext.grid.GridPanel,{loadMask:true,autoExpandColumn:"log_msg",cm:ui.cmp._CommitLogManager.cm,sm:ui.cmp._CommitLogManager.sm,store:ui.cmp._CommitLogManager.store,plugins:[ui.cmp._CommitLogManager.editor],viewConfig:{emptyText:'
'+_("No log message currently")+"
"},listeners:{render:function(c){c.store.load()}},onRowContextMenu:function(c,f,d){d.stopEvent();this.getSelectionModel().selectRow(f);if(!this.menu){this.menu=new ui.cmp._CommitLogManager.menu()}this.menu.setRowIdx(f);this.menu.showAt(d.getXY())},initComponent:function(c){ui.cmp._CommitLogManager.grid.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowcontextmenu",this.onRowContextMenu,this)}});ui.cmp.CommitLogManager=Ext.extend(Ext.Window,{id:"commit-log-win",title:_("Manage Log Message"),iconCls:"iconWinManageLog",width:650,height:350,layout:"fit",resizable:false,modal:true,autoScroll:true,closeAction:"hide",store:ui.cmp._CommitLogManager.store,buttons:[{text:_("Close"),handler:function(){Ext.getCmp("commit-log-win").hide()}}],initComponent:function(){Ext.apply(this,{items:[new ui.cmp._CommitLogManager.grid()]});ui.cmp.CommitLogManager.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._CommitPrompt");ui.cmp._CommitPrompt.store=new Ext.data.GroupingStore({reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"path"},{name:"name"},{name:"by"},{name:"date",type:"date",dateFormat:"Y-m-d H:i:s"},{name:"type"}]}),sortInfo:{field:"name",direction:"ASC"},groupField:"path"});ui.cmp._CommitPrompt.columns=[new Ext.grid.CheckboxSelectionModel(),{id:"name",header:_("Files"),sortable:true,dataIndex:"name"},{header:_("Modified by"),width:45,sortable:true,dataIndex:"by"},{header:_("Date"),width:45,sortable:true,dataIndex:"date",renderer:Ext.util.Format.dateRenderer(_("Y-m-d, H:i"))},{header:_("Path"),dataIndex:"path",hidden:true}];ui.cmp._CommitPrompt.view=new Ext.grid.GroupingView({forceFit:true,groupTextTpl:'{[values.rs[0].data["path"]]} ({[values.rs.length]} {[values.rs.length > 1 ? "'+_("Files")+'" : "'+_("File")+'"]})'});ui.cmp._CommitPrompt.grid=Ext.extend(Ext.grid.GridPanel,{id:"commit-grid-panel",loadMask:true,autoExpandColumn:"name",height:180,columns:ui.cmp._CommitPrompt.columns,view:ui.cmp._CommitPrompt.view,enableDragDrop:true,sm:new Ext.grid.CheckboxSelectionModel(),listeners:{viewready:function(){this.selModel.selectAll()}},initComponent:function(){Ext.apply(this,{store:ui.cmp._CommitPrompt.store});ui.cmp._CommitPrompt.grid.superclass.initComponent.call(this)}});ui.cmp.CommitPrompt=Ext.extend(Ext.Window,{id:"winVCSCommit",layout:"form",title:_("VCS commit"),iconCls:"iconPendingCommit",closable:false,width:600,height:480,resizable:false,modal:true,bodyStyle:"padding:5px 5px 0",labelAlign:"top",patchID:false,defaultMessage:false,tools:[{id:"gear",qtip:_("Configure this tools"),handler:function(){if(!Ext.getCmp("commit-log-win")){new ui.cmp.CommitLogManager()}Ext.getCmp("commit-log-win").show(this.id)}}],listeners:{show:function(){var c=new Ext.util.DelayedTask(function(){Ext.getCmp("form-commit-message-log").focus()});c.delay(200)}},initComponent:function(){var c;ui.cmp._CommitPrompt.store.removeAll();for(c=0;c
{[values.text.split("\n").join("
")]}
',valueField:"id",displayField:"text",listEmptyText:'
'+_("No log message currently")+"
",listeners:{select:function(e,d){Ext.getCmp("form-commit-message-log").setValue(d.data.text)}}},{xtype:"textarea",id:"form-commit-message-log",name:"first3",fieldLabel:_("Log message"),anchor:"100%",height:150,value:(this.defaultMessage)?this.defaultMessage:""}]});ui.cmp.CommitPrompt.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._DictionaryGrid");ui.cmp._DictionaryGrid.store=Ext.extend(Ext.data.Store,{proxy:new Ext.data.HttpProxy({url:"./do/getDictionaryWords"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"valueEn"},{name:"valueLang"},{name:"lastUser",hideField:true},{name:"lastDate",type:"date",dateFormat:"Y-m-d H:i:s",hideField:true}]}),sortInfo:{field:"valueEn",direction:"ASC"},listeners:{load:function(){if(!PhDOE.user.isAnonymous){Ext.getCmp(this.fid+"-btn-new-word").enable()}}},initComponent:function(c){Ext.apply(this,c);ui.cmp._DictionaryGrid.store.superclass.initComponent.call(this)}});ui.cmp._DictionaryGrid.editor=Ext.extend(Ext.ux.grid.RowEditor,{saveText:_("Update"),cancelText:_("Cancel"),listeners:{afteredit:function(e,d,c,f){XHR({params:{task:"manageDictionaryWord",wordId:c.data.id,valueEn:c.data.valueEn,valueLang:c.data.valueLang},success:function(g){var h=Ext.util.JSON.decode(g.responseText);c.set("lastUser",PhDOE.user.login);c.set("lastDate",Date.parseDate(h.dateUpdate,"Y-m-d H:i:s"));c.commit();PhDOE.notify("info",_("Word in dictionary added/updated"),_("The word have been added/updated successfully !"))},failure:function(){PhDOE.winForbidden()}})},canceledit:function(c){if(c.record.data.id==="new"){c.record.store.remove(c.record)}}}});ui.cmp._DictionaryGrid.sm=Ext.extend(Ext.grid.RowSelectionModel,{singleSelect:true});ui.cmp._DictionaryGrid.viewConfig={forceFit:true,emptyText:'
'+_("You must manually load this data.
Use the refresh button !")+"
",deferEmptyText:false};ui.cmp._DictionaryGrid.menu=Ext.extend(Ext.menu.Menu,{setRowIdx:function(c){this.rowIdx=c},initComponent:function(){Ext.apply(this,{items:[{scope:this,text:_("Delete this word"),iconCls:"iconTrash",disabled:(PhDOE.user.isAnonymous),handler:function(){XHR({scope:this,params:{task:"delDictionaryWord",wordId:this.grid.store.getAt(this.rowIdx).data.id},success:function(){this.grid.store.remove(this.grid.store.getAt(this.rowIdx));PhDOE.notify("info",_("Word deleted"),_("The word was deleted successfully !"))},failure:function(){PhDOE.winForbidden()}})}}]});ui.cmp._DictionaryGrid.menu.superclass.initComponent.call(this)}});ui.cmp._DictionaryGrid.grid=Ext.extend(Ext.grid.GridPanel,{onRowContextMenu:function(c,f,d){d.stopEvent();this.getSelectionModel().selectRow(f);if(!this.menu){this.menu=new ui.cmp._DictionaryGrid.menu({grid:c})}this.menu.setRowIdx(f);this.menu.showAt(d.getXY())},initComponent:function(){Ext.apply(this,{region:"center",split:true,loadMask:true,autoScroll:true,bodyBorder:false,border:false,autoExpandColumn:this.dataType,columns:[{id:"id",header:_("En word"),sortable:true,dataIndex:"valueEn",editor:{xtype:"textfield"}},{header:String.format(_("{0} word"),PhDOE.user.lang.ucFirst()),sortable:true,dataIndex:"valueLang",editor:{xtype:"textfield"}},{header:_("Last User Update"),sortable:true,dataIndex:"lastUser",editor:{xtype:"displayfield",hideField:true}},{header:_("Last Date Update"),sortable:true,dataIndex:"lastDate",editor:{xtype:"displayfield",hideField:true},renderer:Ext.util.Format.dateRenderer(_("Y-m-d, H:i"))}],viewConfig:ui.cmp._DictionaryGrid.viewConfig,sm:new ui.cmp._DictionaryGrid.sm(),store:new ui.cmp._DictionaryGrid.store({fid:this.fid}),plugins:[new ui.cmp._DictionaryGrid.editor()],tbar:[{scope:this,tooltip:_("Load/Refresh"),iconCls:"iconRefresh",handler:function(){this.store.reload()}},"->",{scope:this,id:this.fid+"-btn-new-word",disabled:true,text:_("Add a new word"),iconCls:"iconNewWord",handler:function(){var c=Ext.data.Record.create([{name:"id"},{name:"valueEn"},{name:"valueLang"},{name:"lastUser"},{name:"lastDate"}]),d=new Date(),f=new c({id:"new",valueEn:"",valueLang:"",lastUser:PhDOE.user.login,lastDate:d});this.plugins[0].stopEditing();this.store.insert(0,f);this.getView().refresh();this.getSelectionModel().selectRow(0);this.plugins[0].startEditing(0)}}]});ui.cmp._DictionaryGrid.grid.superclass.initComponent.call(this);this.on("rowcontextmenu",this.onRowContextMenu,this)}});ui.cmp.DictionaryGrid=Ext.extend(Ext.Panel,{initComponent:function(){Ext.apply(this,{layout:"border",border:false,items:[new ui.cmp._DictionaryGrid.grid({dataType:this.dataType,prefix:this.prefix,fid:this.fid,ftype:this.ftype,loadStore:this.loadStore})]});ui.cmp.DictionaryGrid.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._EditorConf","ui.cmp._EditorCmd2Conf");ui.cmp._EditorConf.tplMenu=new Ext.XTemplate('','","");ui.cmp._EditorConf.tplMenu.compile();ui.cmp._EditorConf.menuDefEn=[["1","card1",_("Main")],["4","card4",_('Module "Files with error"')],["6","card6",_('Module "All files"')]];ui.cmp._EditorConf.menuDefNonEn=[["1","card1",_("Main")],["2","card2",_('Module "Files need translate"')],["3","card3",_('Module "Files need update"')],["4","card4",_('Module "Files with error"')],["5","card5",_('Module "Files need reviewed"')],["6","card6",_('Module "All files"')]];ui.cmp._EditorConf.menuStore=new Ext.data.SimpleStore({id:0,fields:[{name:"id"},{name:"card"},{name:"label"}]});ui.cmp._EditorConf.viewMenu=Ext.extend(Ext.DataView,{id:"conf-menu-view",tpl:ui.cmp._EditorConf.tplMenu,singleSelect:true,overClass:"x-view-over",itemSelector:"div.menu-wrap",store:ui.cmp._EditorConf.menuStore,listeners:{selectionchange:function(c){var d=c.getSelectedRecords();Ext.getCmp("confCard").layout.setActiveItem("conf-card-"+d[0].data.id)}}});ui.cmp._EditorCmd2Conf.themeStore=new Ext.data.SimpleStore({fields:["themeFile",{name:"themeName",type:"string"}],data:[[false,_("No theme")],["default",_("Default theme")],["cobalt",_("Cobalt")],["eclipse",_("Eclipse")],["elegant",_("Elegant")],["monokai",_("Monokai")],["neat",_("Neat")],["night",_("Night")],["rubyblue",_("RubyBlue")]]});ui.cmp._EditorConf.themeStore=new Ext.data.SimpleStore({fields:["themeFile",{name:"themeName",type:"string"}],data:[["themes/ExtJsThemes/black/css/xtheme-black.css",_("Black")],["themes/empty.css",_("Default")],["themes/ExtJsThemes/darkgray/css/xtheme-darkgray.css",_("DarkGray")],["js/ExtJs/resources/css/xtheme-gray.css",_("Gray")],["themes/ExtJsThemes/gray-extend/css/xtheme-gray-extend.css",_("Gray Extend")],["themes/ExtJsThemes/indigo/css/xtheme-indigo.css",_("Indigo")],["themes/ExtJsThemes/midnight/css/xtheme-midnight.css",_("Midnight")],["themes/ExtJsThemes/olive/css/xtheme-olive.css",_("Olive")],["themes/ExtJsThemes/purple/css/xtheme-purple.css",_("Purple")],["themes/ExtJsThemes/silverCherry/css/xtheme-silverCherry.css",_("SilverCherry")],["themes/ExtJsThemes/ubuntu_human/css/xtheme-human.css",_("Ubuntu Human")]]});ui.cmp._EditorConf.uiLangStore=new Ext.data.SimpleStore({fields:["uiLang",{name:"uiLangName",type:"string"}],data:[["default",_("Default language, if available")],["en",_("English")],["fr",_("French")],["ru",_("Russian")],["es",_("Spanish")],["ar",_("Arabic")]]});ui.cmp._EditorConf.CommitChange=new Ext.util.DelayedTask(function(){new ui.task.UpdateConfTask({module:this.module,itemName:this.itemName,value:this.getValue()})});ui.cmp._EditorConf.card1=Ext.extend(Ext.TabPanel,{id:"conf-card-1",autoScroll:true,activeTab:0,defaults:{bodyStyle:"padding: 5px;",autoHeight:true,autoScroll:true},initComponent:function(){Ext.apply(this,{items:[{title:_("User Interface"),iconCls:"iconUI",labelAlign:"top",layout:"form",items:[{xtype:"fieldset",title:_("Main menu"),iconCls:"iconMenu",items:[{xtype:"spinnerfield",width:60,name:"PhDOE.user.conf.main.mainMenuWidth",module:"main",itemName:"mainMenuWidth",value:PhDOE.user.conf.main.mainMenuWidth||300,fieldLabel:_("Main menu width"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){var c=Ext.getCmp("main-menu-panel"),d=this.getValue();PhDOE.user.conf.main.mainMenuWidth=d;c.setWidth(d);c.ownerCt.doLayout();ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){var c=Ext.getCmp("main-menu-panel"),d=this.getValue();PhDOE.user.conf.main.mainMenuWidth=d;c.setWidth(d);c.ownerCt.doLayout();ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}}]},{xtype:"fieldset",iconCls:"iconThemes",title:_("Appearance"),items:[{xtype:"combo",fieldLabel:_("Choose a theme"),id:"conf-combo-theme",valueField:"themeFile",displayField:"themeName",triggerAction:"all",mode:"local",forceSelection:true,editable:false,value:PhDOE.user.conf.main.theme,store:ui.cmp._EditorConf.themeStore,listeners:{render:function(){Ext.getCmp("conf-combo-theme").store.sort("themeName")},select:function(e){var d=e.getValue();Ext.get("appTheme").dom.href=d;new ui.task.UpdateConfTask({module:"main",itemName:"theme",value:d})}}},{xtype:"combo",fieldLabel:_("Force an UI language"),id:"conf-combo-ui-lang",valueField:"uiLang",displayField:"uiLangName",triggerAction:"all",mode:"local",forceSelection:true,editable:false,value:PhDOE.user.conf.main.uiLang||"default",store:ui.cmp._EditorConf.uiLangStore,listeners:{select:function(e){var d=e.getValue();new ui.task.UpdateConfTask({module:"main",itemName:"uiLang",value:d})}}}]},{xtype:"fieldset",title:_("On save file"),iconCls:"iconSaveFile",autoHeight:true,defaults:{hideLabel:true},defaultType:"radio",items:[{autoHeight:true,name:"PhDOE.user.conf.main.onSaveFile",module:"main",itemName:"onSaveFile",checked:(PhDOE.user.conf.main.onSaveFile==="ask-me")?true:false,boxLabel:_("Ask me if I want to check for error before saving the file"),inputValue:"ask-me",listeners:{check:function(c){if(c.checked){new ui.task.UpdateConfTask({module:"main",itemName:"onSaveFile",value:c.getRawValue()})}}}},{autoHeight:true,name:"PhDOE.user.conf.main.onSaveFile",module:"main",itemName:"onSaveFile",checked:(PhDOE.user.conf.main.onSaveFile==="always")?true:false,boxLabel:_("Always check for error before saving the file"),inputValue:"always",listeners:{check:function(c){if(c.checked){new ui.task.UpdateConfTask({module:"main",itemName:"onSaveFile",value:c.getRawValue()})}}}},{autoHeight:true,name:"PhDOE.user.conf.main.onSaveFile",module:"main",itemName:"onSaveFile",checked:(PhDOE.user.conf.main.onSaveFile==="never")?true:false,boxLabel:_("Never check for error before saving the file"),inputValue:"never",listeners:{check:function(c){if(c.checked){new ui.task.UpdateConfTask({module:"main",itemName:"onSaveFile",value:c.getRawValue()})}}}}]},{xtype:"checkbox",name:"PhDOE.user.conf.main.displayENWork",checked:PhDOE.user.conf.main.displayENWork,boxLabel:_('Display EN work in "Work in progress" & "Patches for review" modules'),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"main",itemName:"displayENWork",value:c.getValue()})}}}]},{title:_("External Data"),iconCls:"iconExternalData",items:[{xtype:"fieldset",title:_("About mails"),iconCls:"iconMailing",defaults:{hideLabel:true},defaultType:"checkbox",items:[{autoHeight:true,name:"PhDOE.user.conf.main.loadMailsAtStartUp",checked:PhDOE.user.conf.main.loadMailsAtStartUp,boxLabel:_("Load mail at startUp"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"main",itemName:"loadMailsAtStartUp",value:c.getValue()})}}}]},{xtype:"fieldset",title:_("About bugs"),iconCls:"iconBugs",defaults:{hideLabel:true},defaultType:"checkbox",items:[{autoHeight:true,name:"PhDOE.user.conf.main.loadBugsAtStartUp",checked:PhDOE.user.conf.main.loadBugsAtStartUp,boxLabel:_("Load bugs at startUp"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"main",itemName:"loadBugsAtStartUp",value:c.getValue()})}}}]}]},{title:_("Editor"),iconCls:"iconEditor",items:[{xtype:"fieldset",title:_("Editor theme"),iconCls:"iconThemes",items:[{xtype:"combo",fieldLabel:_("Choose a theme"),id:"conf-combo-cm2-theme",valueField:"themeFile",displayField:"themeName",triggerAction:"all",mode:"local",forceSelection:true,editable:false,value:(PhDOE.user.conf.main.editorTheme||"default"),store:ui.cmp._EditorCmd2Conf.themeStore,listeners:{select:function(e){var d=e.getValue();new ui.task.UpdateConfTask({module:"main",itemName:"editorTheme",value:d})}}}]}]}]});ui.cmp._EditorConf.card1.superclass.initComponent.call(this)}});ui.cmp._EditorConf.card2=Ext.extend(Ext.TabPanel,{id:"conf-card-2",autoScroll:true,activeTab:0,defaults:{bodyStyle:"padding: 5px;",autoHeight:true,autoScroll:true},initComponent:function(){Ext.apply(this,{items:[{title:_("Menu"),iconCls:"iconMenu",items:[{xtype:"fieldset",title:_("Nb files to display"),iconCls:"iconFilesToDisplay",defaults:{hideLabel:true},items:[{xtype:"spinnerfield",width:60,name:"PhDOE.user.conf.newFile.nbDisplay",module:"newFile",itemName:"nbDisplay",value:PhDOE.user.conf.newFile.nbDisplay||0,boxLabel:_("files to display"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}},{xtype:"displayfield",value:_("0 means no limit"),style:{fontStyle:"italic"}}]}]},{title:_("User Interface"),iconCls:"iconUI",items:[{xtype:"fieldset",title:_("ScrollBars"),iconCls:"iconScrollBar",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"PhDOE.user.conf.newFile.syncScrollbars",checked:PhDOE.user.conf.newFile.syncScrollbars,boxLabel:_("Synchronize scroll bars"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"newFile",itemName:"syncScrollbars",value:c.getValue()})}}}]},{xtype:"fieldset",title:_("Tools"),iconCls:"iconConf",defaults:{hideLabel:true},defaultType:"checkbox",items:[{xtype:"fieldset",checkboxToggle:true,collapsed:!PhDOE.user.conf.newFile.toolsPanelDisplay,title:_("Start with the panel open"),listeners:{collapse:function(){new ui.task.UpdateConfTask({module:"newFile",itemName:"toolsPanelDisplay",value:false})},expand:function(){new ui.task.UpdateConfTask({module:"newFile",itemName:"toolsPanelDisplay",value:true})}},items:[{xtype:"spinnerfield",width:60,name:"newFile.toolsPanelWidth",module:"newFile",itemName:"toolsPanelWidth",value:PhDOE.user.conf.newFile.toolsPanelWidth||375,fieldLabel:_("Panel width"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}}]}]},{xtype:"fieldset",title:_("Right panel"),iconCls:"iconUI",defaults:{hideLabel:true},defaultType:"radio",items:[{name:"PhDOE.user.conf.newFile.secondPanel",boxLabel:_("Display the Google Translation Panel"),inputValue:"google",checked:(PhDOE.user.conf.newFile.secondPanel==="google")?true:false,listeners:{check:function(c){if(c.checked){new ui.task.UpdateConfTask({module:"newFile",itemName:"secondPanel",value:c.getRawValue()})}}}},{name:"PhDOE.user.conf.newFile.secondPanel",boxLabel:_("Display the original file"),inputValue:"originalFile",checked:(PhDOE.user.conf.newFile.secondPanel==="originalFile")?true:false,listeners:{check:function(c){if(c.checked){new ui.task.UpdateConfTask({module:"newFile",itemName:"secondPanel",value:c.getRawValue()})}}}},{name:"PhDOE.user.conf.newFile.secondPanel",boxLabel:_("Do not display a right panel"),inputValue:"none",checked:(!Ext.isDefined(PhDOE.user.conf.newFile.secondPanel)||PhDOE.user.conf.newFile.secondPanel==="none")?true:false,listeners:{check:function(c){if(c.checked){new ui.task.UpdateConfTask({module:"newFile",itemName:"secondPanel",value:c.getRawValue()})}}}}]}]}]});ui.cmp._EditorConf.card2.superclass.initComponent.call(this)}});ui.cmp._EditorConf.card3=Ext.extend(Ext.TabPanel,{id:"conf-card-3",autoScroll:true,activeTab:0,defaults:{bodyStyle:"padding: 5px;",autoHeight:true,autoScroll:true},initComponent:function(){Ext.apply(this,{items:[{title:_("Menu"),iconCls:"iconMenu",items:[{xtype:"fieldset",title:_("Nb files to display"),iconCls:"iconFilesToDisplay",defaults:{hideLabel:true},defaultType:"spinnerfield",items:[{width:60,name:"PhDOE.user.conf.needUpdate.nbDisplay",module:"needUpdate",itemName:"nbDisplay",value:PhDOE.user.conf.needUpdate.nbDisplay||0,boxLabel:_("files to display"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}},{xtype:"displayfield",value:_("0 means no limit"),style:{fontStyle:"italic"}}]}]},{title:_("User Interface"),iconCls:"iconUI",items:[{xtype:"fieldset",title:_("ScrollBars"),iconCls:"iconScrollBar",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"needUpdate.syncScrollbars",checked:PhDOE.user.conf.needUpdate.syncScrollbars,boxLabel:_("Synchronize scroll bars"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"syncScrollbars",value:c.getValue()})}}}]},{xtype:"fieldset",title:_("Tools"),iconCls:"iconConf",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"needUpdate.toolsPanelLogLoad",checked:PhDOE.user.conf.needUpdate.toolsPanelLogLoad,boxLabel:_("Automatically load the log when displaying the file"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"toolsPanelLogLoad",value:c.getValue()})}}},{xtype:"fieldset",checkboxToggle:true,collapsed:!PhDOE.user.conf.needUpdate.toolsPanelDisplay,title:_("Start with the panel open"),listeners:{collapse:function(){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"toolsPanelDisplay",value:false})},expand:function(){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"toolsPanelDisplay",value:true})}},items:[{xtype:"spinnerfield",width:60,name:"needUpdate.toolsPanelWidth",module:"needUpdate",itemName:"toolsPanelWidth",value:PhDOE.user.conf.needUpdate.toolsPanelWidth||375,fieldLabel:_("Panel width"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}}]}]},{xtype:"fieldset",title:_("Diff view"),iconCls:"iconDiffView",defaults:{hideLabel:true},defaultType:"radio",items:[{xtype:"fieldset",checkboxToggle:true,collapsed:!PhDOE.user.conf.needUpdate.diffPanelDisplay,title:_("Start with the panel open"),listeners:{collapse:function(){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"diffPanelDisplay",value:false})},expand:function(){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"diffPanelDisplay",value:true})}},items:[{xtype:"spinnerfield",width:60,name:"needUpdate.diffPanelHeight",module:"needUpdate",itemName:"diffPanelHeight",value:PhDOE.user.conf.needUpdate.diffPanelHeight||150,fieldLabel:_("Panel height"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}}]},{name:"needUpdate.diffMethod",checked:(PhDOE.user.conf.needUpdate.diffMethod==="using-viewvc")?true:false,boxLabel:_("Using ViewVc from php web site"),inputValue:"using-viewvc",listeners:{check:function(c){if(c.checked){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"diffMethod",value:c.getRawValue()})}}}},{name:"needUpdate.diffMethod",checked:(PhDOE.user.conf.needUpdate.diffMethod==="using-exec")?true:false,boxLabel:_("Using diff -u command line"),inputValue:"using-exec",listeners:{check:function(c){if(c.checked){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"diffMethod",value:c.getRawValue()})}}}}]}]}]});ui.cmp._EditorConf.card3.superclass.initComponent.call(this)}});ui.cmp._EditorConf.card4=Ext.extend(Ext.TabPanel,{id:"conf-card-4",autoScroll:true,activeTab:0,defaults:{bodyStyle:"padding: 5px;",autoHeight:true,autoScroll:true},initComponent:function(){Ext.apply(this,{items:[{title:_("Menu"),iconCls:"iconMenu",items:[{xtype:"fieldset",title:_("Nb files to display"),iconCls:"iconFilesToDisplay",defaults:{hideLabel:true},defaultType:"spinnerfield",items:[{width:60,name:"PhDOE.user.conf.error.nbDisplay",module:"error",itemName:"nbDisplay",value:PhDOE.user.conf.error.nbDisplay||0,boxLabel:_("files to display"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}},{xtype:"displayfield",value:_("0 means no limit"),style:{fontStyle:"italic"}}]},{hidden:(PhDOE.user.lang==="en"),xtype:"fieldset",title:_("Error type"),iconCls:"iconFilesError",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"error.skipNbLiteralTag",checked:PhDOE.user.conf.error.skipNbLiteralTag,boxLabel:_("Skip nbLiteralTag error"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"error",itemName:"skipNbLiteralTag",value:c.getValue()})}}}]}]},{title:_("User Interface"),iconCls:"iconUI",items:[{xtype:"fieldset",title:_("ScrollBars"),iconCls:"iconScrollBar",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"error.syncScrollbars",checked:PhDOE.user.conf.error.syncScrollbars,boxLabel:_("Synchronize scroll bars"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"error",itemName:"syncScrollbars",value:c.getValue()})}}}]},{xtype:"fieldset",title:_("Tools"),iconCls:"iconConf",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"error.toolsPanelLogLoad",checked:PhDOE.user.conf.error.toolsPanelLogLoad,boxLabel:_("Automatically load the log when displaying the file"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"error",itemName:"toolsPanelLogLoad",value:c.getValue()})}}},{name:"error.toolsPanelEntitiesLoad",checked:PhDOE.user.conf.error.toolsPanelEntitiesLoad,boxLabel:_("Automatically load entities data when displaying the file"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"error",itemName:"toolsPanelEntitiesLoad",value:c.getValue()})}}},{name:"error.toolsPanelAcronymsLoad",checked:PhDOE.user.conf.error.toolsPanelAcronymsLoad,boxLabel:_("Automatically load acronyms data when displaying the file"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"error",itemName:"toolsPanelAcronymsLoad",value:c.getValue()})}}},{xtype:"fieldset",checkboxToggle:true,collapsed:!PhDOE.user.conf.error.toolsPanelDisplay,title:_("Start with the panel open"),listeners:{collapse:function(){new ui.task.UpdateConfTask({module:"error",itemName:"toolsPanelDisplay",value:false})},expand:function(){new ui.task.UpdateConfTask({module:"error",itemName:"toolsPanelDisplay",value:true})}},items:[{xtype:"spinnerfield",width:60,name:"error.toolsPanelWidth",module:"error",itemName:"toolsPanelWidth",value:PhDOE.user.conf.error.toolsPanelWidth||375,fieldLabel:_("Panel width"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}}]}]},{xtype:"fieldset",title:_("Error description"),iconCls:"iconFilesError",defaults:{hideLabel:true},defaultType:"radio",items:[{xtype:"fieldset",checkboxToggle:true,collapsed:!PhDOE.user.conf.error.descPanelDisplay,title:_("Start with the panel open"),listeners:{collapse:function(){new ui.task.UpdateConfTask({module:"error",itemName:"descPanelDisplay",value:false})},expand:function(){new ui.task.UpdateConfTask({module:"error",itemName:"descPanelDisplay",value:true})}},items:[{xtype:"spinnerfield",width:60,name:"error.descPanelHeight",module:"error",itemName:"descPanelHeight",value:PhDOE.user.conf.error.descPanelHeight||150,fieldLabel:_("Panel height"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}}]}]}]}]});ui.cmp._EditorConf.card4.superclass.initComponent.call(this)}});ui.cmp._EditorConf.card5=Ext.extend(Ext.TabPanel,{id:"conf-card-5",autoScroll:true,activeTab:0,defaults:{bodyStyle:"padding: 5px;",autoHeight:true,autoScroll:true},initComponent:function(){Ext.apply(this,{items:[{title:_("Menu"),iconCls:"iconMenu",items:[{xtype:"fieldset",title:_("Nb files to display"),iconCls:"iconFilesToDisplay",defaults:{hideLabel:true},defaultType:"spinnerfield",items:[{width:60,name:"reviewed.nbDisplay",module:"reviewed",itemName:"nbDisplay",value:PhDOE.user.conf.reviewed.nbDisplay||0,boxLabel:_("files to display"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}},{xtype:"displayfield",value:_("0 means no limit"),style:{fontStyle:"italic"}}]}]},{title:_("User Interface"),iconCls:"iconUI",items:[{xtype:"fieldset",title:_("ScrollBars"),iconCls:"iconScrollBar",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"reviewed.syncScrollbars",checked:PhDOE.user.conf.reviewed.syncScrollbars,boxLabel:_("Synchronize scroll bars"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"reviewed",itemName:"syncScrollbars",value:c.getValue()})}}}]},{xtype:"fieldset",title:_("Tools"),iconCls:"iconConf",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"reviewed.toolsPanelLogLoad",checked:PhDOE.user.conf.reviewed.toolsPanelLogLoad,boxLabel:_("Automatically load the log when displaying the file"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"reviewed",itemName:"toolsPanelLogLoad",value:c.getValue()})}}},{xtype:"fieldset",checkboxToggle:true,collapsed:!PhDOE.user.conf.reviewed.toolsPanelDisplay,title:_("Start with the panel open"),listeners:{collapse:function(){new ui.task.UpdateConfTask({module:"reviewed",itemName:"toolsPanelDisplay",value:false})},expand:function(){new ui.task.UpdateConfTask({module:"reviewed",itemName:"toolsPanelDisplay",value:true})}},items:[{xtype:"spinnerfield",width:60,name:"reviewed.toolsPanelWidth",module:"reviewed",itemName:"toolsPanelWidth",value:PhDOE.user.conf.reviewed.toolsPanelWidth||375,fieldLabel:_("Panel width"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}}]}]}]}]});ui.cmp._EditorConf.card5.superclass.initComponent.call(this)}});ui.cmp._EditorConf.card6=Ext.extend(Ext.TabPanel,{id:"conf-card-6",autoScroll:true,activeTab:0,defaults:{bodyStyle:"padding: 5px;",autoHeight:true,autoScroll:true},initComponent:function(){Ext.apply(this,{items:[{title:_("User Interface"),iconCls:"iconUI",items:[{xtype:"fieldset",title:_("Tools"),iconCls:"iconConf",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"allFiles.toolsPanelLogLoad",checked:PhDOE.user.conf.allFiles.toolsPanelLogLoad,boxLabel:_("Automatically load the log when displaying the file"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"allFiles",itemName:"toolsPanelLogLoad",value:c.getValue()})}}},{name:"allFiles.toolsPanelEntitiesLoad",checked:PhDOE.user.conf.allFiles.toolsPanelEntitiesLoad,boxLabel:_("Automatically load entities data when displaying the file"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"allFiles",itemName:"toolsPanelEntitiesLoad",value:c.getValue()})}}},{name:"allFiles.toolsPanelAcronymsLoad",checked:PhDOE.user.conf.allFiles.toolsPanelAcronymsLoad,boxLabel:_("Automatically load acronyms data when displaying the file"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"allFiles",itemName:"toolsPanelAcronymsLoad",value:c.getValue()})}}},{xtype:"fieldset",checkboxToggle:true,collapsed:!PhDOE.user.conf.allFiles.toolsPanelDisplay,title:_("Start with the panel open"),listeners:{collapse:function(){new ui.task.UpdateConfTask({module:"allFiles",itemName:"toolsPanelDisplay",value:false})},expand:function(){new ui.task.UpdateConfTask({module:"allFiles",itemName:"toolsPanelDisplay",value:true})}},items:[{xtype:"spinnerfield",width:60,name:"allFiles.toolsPanelWidth",module:"allFiles",itemName:"toolsPanelWidth",value:PhDOE.user.conf.allFiles.toolsPanelWidth||375,fieldLabel:_("Panel width"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}}]}]}]}]});ui.cmp._EditorConf.card6.superclass.initComponent.call(this)}});ui.cmp.EditorConf=Ext.extend(Ext.Window,{id:"win-conf",layout:"border",width:700,height:470,iconCls:"iconConf",title:_("Configuration"),modal:true,plain:true,bodyBorder:false,closeAction:"hide",buttons:[{text:_("Close"),handler:function(){Ext.getCmp("win-conf").hide()}}],listeners:{show:function(){var c=Ext.getCmp("conf-menu-view");c.select(c.getNode(0))}},initComponent:function(){if(PhDOE.user.lang==="en"){ui.cmp._EditorConf.menuStore.loadData(ui.cmp._EditorConf.menuDefEn)}else{ui.cmp._EditorConf.menuStore.loadData(ui.cmp._EditorConf.menuDefNonEn)}Ext.apply(this,{items:[{id:"confMenu",region:"west",border:false,width:190,autoScroll:true,items:[new ui.cmp._EditorConf.viewMenu()]},{id:"confCard",region:"center",border:false,layout:"card",width:375,frame:true,activeItem:0,bbar:new Ext.ux.StatusBar({defaultText:_("All changes take effect immediately"),defaultIconCls:"confStatusBar"}),items:[new ui.cmp._EditorConf.card1(),new ui.cmp._EditorConf.card2(),new ui.cmp._EditorConf.card3(),new ui.cmp._EditorConf.card4(),new ui.cmp._EditorConf.card5(),new ui.cmp._EditorConf.card6()]}]});ui.cmp.EditorConf.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._EmailPrompt");ui.cmp.EmailPrompt=Ext.extend(Ext.Window,{title:_("Send an email"),width:500,height:300,minWidth:300,minHeight:200,layout:"fit",plain:true,bodyStyle:"padding:5px;",buttonAlign:"center",iconCls:"iconSendEmail",closeAction:"hide",buttons:[{text:_("Send"),handler:function(){var d=this.ownerCt.ownerCt,c=d.findByType("form").shift().getForm().getValues();XHR({params:{task:"sendEmail",to:c.to,subject:c.subject,msg:c.msg},success:function(){d.hide();Ext.Msg.alert(_("Status"),String.format(_("Email sent to {0} with success!"),d.name.ucFirst()),Ext.emptyFn)},failure:function(){PhDOE.winForbidden()}})}},{text:_("Cancel"),handler:function(){this.ownerCt.ownerCt.hide()}}],setData:function(d,c){this.name=d;this.email=c;this.items.items[0].items.items[0].setValue('"'+this.name.ucFirst()+'" <'+this.email+">");this.items.items[0].items.items[1].setValue("");this.items.items[0].items.items[2].setValue("")},initComponent:function(){Ext.apply(this,{items:new Ext.form.FormPanel({baseCls:"x-plain",labelWidth:55,defaultType:"textfield",items:[{name:"to",fieldLabel:_("Send To"),readOnly:true,anchor:"100%",value:""},{name:"subject",fieldLabel:_("Subject"),anchor:"100%"},{name:"msg",xtype:"textarea",hideLabel:true,anchor:"100% -53"}]})});ui.cmp.EmailPrompt.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._EntitiesAcronymsPanel");ui.cmp._EntitiesAcronymsPanel.grid=Ext.extend(Ext.grid.GridPanel,{onRowClick:function(c){var d=c.getSelectionModel().getSelected().data;Ext.getCmp(this.dataType+"-details-"+this.fid).update(d.value)},onRowDblClick:function(d){var f=d.getSelectionModel().getSelected().data,e=Ext.getCmp(this.prefix+"-"+this.ftype+"-FILE-"+this.fid),c=Ext.util.JSON.decode(e.getCursorPosition()),g=(this.dataType==="entities")?"&"+f.items+";":""+f.items+"";e.insertIntoLine(c.line,c.caracter,g)},initComponent:function(){var c;if(this.dataType==="entities"){c="./do/getEntities"}else{if(this.dataType==="acronyms"){c="./do/getAcronyms"}}Ext.apply(this,{region:"center",split:true,loadMask:true,autoScroll:true,bodyBorder:false,border:false,autoExpandColumn:this.dataType,columns:[{id:"items",header:_("Items"),sortable:true,dataIndex:"items"},{header:_("From"),sortable:true,dataIndex:"from",width:50}],viewConfig:{forceFit:true,emptyText:'
'+_("You must manually load this data.
Use the refresh button !")+"

"+_("(You can change this behavior by setting an option in the configuration window)")+"
",deferEmptyText:false},sm:new Ext.grid.RowSelectionModel({singleSelect:true}),store:new Ext.data.Store({autoLoad:this.loadStore,proxy:new Ext.data.HttpProxy({url:c}),listeners:{scope:this,load:function(){if(this.dataType==="entities"){Ext.getCmp(this.prefix+"-"+this.fid).panEntities=true}else{if(this.dataType==="acronyms"){Ext.getCmp(this.prefix+"-"+this.fid).panAcronyms=true}}Ext.getCmp("main-panel").fireEvent("tabLoaded",this.prefix,this.fid)}},reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"from"},{name:"items"},{name:"value"}]})}),tbar:[{scope:this,tooltip:_("Load/Refresh"),iconCls:"iconRefresh",handler:function(){this.store.reload()}},_("Filter: ")," ",new Ext.form.TwinTriggerField({width:180,hideTrigger1:true,enableKeyEvents:true,validateOnBlur:false,validationEvent:false,trigger1Class:"x-form-clear-trigger",trigger2Class:"x-form-search-trigger",listeners:{specialkey:function(d,g){if(g.getKey()===g.ENTER){this.onTrigger2Click()}}},onTrigger1Click:function(){this.setValue("");this.triggers[0].hide();this.setSize(180,10);this.ownerCt.ownerCt.store.clearFilter()},onTrigger2Click:function(){var d=this.getValue(),e;if(d===""||d.length<3){this.markInvalid(_("Your filter must contain at least 3 characters"));return}this.clearInvalid();this.triggers[0].show();this.setSize(180,10);e=new RegExp(d,"i");this.ownerCt.ownerCt.store.filterBy(function(f){if(e.test(f.data.from)||e.test(f.data.items)||e.test(f.data.value)){return true}else{return false}},this)}})]});ui.cmp._EntitiesAcronymsPanel.grid.superclass.initComponent.call(this);this.on("rowclick",this.onRowClick,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp.EntitiesAcronymsPanel=Ext.extend(Ext.Panel,{initComponent:function(){var c;if(this.dataType==="entities"){c=_("Click on a row to display the content of the entitie.
Double-click on it to insert it at the cursor position.")}else{if(this.dataType==="acronyms"){c=_("Click on a row to display the content of the acronym.
Double-click on it to insert it at the cursor position.")}}Ext.apply(this,{layout:"border",border:false,items:[new ui.cmp._EntitiesAcronymsPanel.grid({dataType:this.dataType,prefix:this.prefix,fid:this.fid,ftype:this.ftype,loadStore:this.loadStore}),{xtype:"panel",id:this.dataType+"-details-"+this.fid,region:"south",split:true,height:100,autoScroll:true,bodyBorder:false,bodyCssClass:this.dataType+"-details",html:c}]});ui.cmp.EntitiesAcronymsPanel.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._ErrorFileGrid");ui.cmp._ErrorFileGrid.store=new Ext.data.GroupingStore({proxy:new Ext.data.HttpProxy({url:"./do/getFilesError"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"path"},{name:"name"},{name:"maintainer"},{name:"type"},{name:"value_en"},{name:"value_lang"},{name:"fileModifiedEN"},{name:"fileModifiedLang"}]}),sortInfo:{field:"path",direction:"ASC"},groupField:"path",listeners:{datachanged:function(e){var c=e.getCount(),d=false;if(!PhDOE.user.isAnonymous){e.each(function(f){if(f.data.maintainer==PhDOE.user.login){d++}},this)}Ext.getDom("acc-error-nb").innerHTML=c+(d?(" - "+String.format(_("{0} mine"),d)):"")}}});ui.cmp._ErrorFileGrid.columns=[{id:"name",header:_("Files"),sortable:true,dataIndex:"name",renderer:function(c,f,d){var h="",g,e;if(d.data.fileModifiedEN){g=Ext.util.JSON.decode(d.data.fileModifiedEN);if(g.user===PhDOE.user.login&&g.anonymousIdent===PhDOE.user.anonymousIdent){h=_("File EN modified by me")+"
"}else{h=String.format(_("File EN modified by {0}"),g.user)+"
"}}if(d.data.fileModifiedLang){e=Ext.util.JSON.decode(d.data.fileModifiedLang);if(e.user===PhDOE.user.login&&e.anonymousIdent===PhDOE.user.anonymousIdent){h+=String.format(_("File {0} modified by me"),PhDOE.user.lang.ucFirst())}else{h+=String.format(_("File {0} modified by {1}"),PhDOE.user.lang.ucFirst(),e.user)}}if(h!==""){return""+c+""}else{return c}}},{header:_("Type"),width:45,sortable:true,dataIndex:"type"},{header:_("Maintainer"),width:45,sortable:true,dataIndex:"maintainer"},{header:_("Path"),dataIndex:"path",hidden:true}];ui.cmp._ErrorFileGrid.view=new Ext.grid.GroupingView({emptyText:'
'+_("No Files")+"
",deferEmptyText:false,forceFit:true,startCollapsed:true,groupTextTpl:'{[values.rs[0].data.path]} ({[values.rs.length]} {[values.rs.length > 1 ? "'+_("Files")+'" : "'+_("File")+'"]})',getRowClass:function(c){if(c.data.fileModifiedEN||c.data.fileModifiedLang){var e=Ext.util.JSON.decode(c.data.fileModifiedEN),d=Ext.util.JSON.decode(c.data.fileModifiedLang);return((e.user===PhDOE.user.login&&e.anonymousIdent===PhDOE.user.anonymousIdent)||(d.user===PhDOE.user.login&&d.anonymousIdent===PhDOE.user.anonymousIdent))?"fileModifiedByMe":"fileModifiedByAnother"}return false}});ui.cmp._ErrorFileGrid.menu=function(c){Ext.apply(this,c);this.init();ui.cmp._ErrorFileGrid.menu.superclass.constructor.call(this)};Ext.extend(ui.cmp._ErrorFileGrid.menu,Ext.menu.Menu,{init:function(){Ext.apply(this,{items:[{scope:this,text:""+_("Edit in a new tab")+"",iconCls:"iconFilesError",handler:function(){this.grid.fireEvent("rowdblclick",this.grid,this.rowIdx,this.event)}},{scope:this,hidden:this.hideDiffMenu,text:_("View diff..."),iconCls:"iconViewDiff",menu:new Ext.menu.Menu({items:[{scope:this,hidden:(this.grid.store.getAt(this.rowIdx).data.fileModifiedEN===false),text:String.format(_("... of the {0} file"),"EN"),handler:function(){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",FileName:this.fname,FilePath:"en"+this.fpath})}},{scope:this,hidden:(this.grid.store.getAt(this.rowIdx).data.fileModifiedLang===false),text:String.format(_("... of the {0} file"),PhDOE.user.lang.ucFirst()),handler:function(){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",FileName:this.fname,FilePath:PhDOE.user.lang+this.fpath})}}]})},"-",{text:_("About error type"),iconCls:"iconHelp",handler:function(){if(!Ext.getCmp("main-panel").findById("FE-help")){Ext.getCmp("main-panel").add({id:"FE-help",title:_("About error type"),iconCls:"iconHelp",closable:true,autoScroll:true,autoLoad:"./error"})}Ext.getCmp("main-panel").setActiveTab("FE-help")}}]})}});ui.cmp.ErrorFileGrid=Ext.extend(Ext.grid.GridPanel,{loadMask:true,border:false,autoExpandColumn:"name",enableDragDrop:true,ddGroup:"mainPanelDDGroup",view:ui.cmp._ErrorFileGrid.view,columns:ui.cmp._ErrorFileGrid.columns,listeners:{render:function(c){c.view.refresh()}},onRowContextMenu:function(d,j,h){h.stopEvent();var g=d.store.getAt(j).data,f=g.path,c=g.name;d.getSelectionModel().selectRow(j);new ui.cmp._ErrorFileGrid.menu({hideDiffMenu:(g.fileModifiedEN===false&&g.fileModifiedLang===false),grid:d,event:h,rowIdx:j,lang:PhDOE.user.lang,fpath:f,fname:c}).showAt(h.getXY())},onRowDblClick:function(c,f,d){this.openFile(c.store.getAt(f).data.id)},openFile:function(j){var g=this.store.getById(j),f=g.data.path,c=g.data.name,h=Ext.util.md5("FE-"+PhDOE.user.lang+f+c),d=[],k,e;if(!Ext.getCmp("main-panel").findById("FE-"+h)){d=[];this.store.each(function(l){if(l.data.path===f&&l.data.name===c&&!d[l.data.type]){d.push(l.data.type)}});k=(PhDOE.user.lang==="en")?[new ui.cmp.VCSLogGrid({layout:"fit",title:String.format(_("{0} Log"),PhDOE.user.lang.ucFirst()),prefix:"FE-LANG",fid:h,fpath:PhDOE.user.lang+f,fname:c,loadStore:PhDOE.user.conf.error.toolsPanelLogLoad})]:[new ui.cmp.VCSLogGrid({layout:"fit",title:String.format(_("{0} Log"),PhDOE.user.lang.ucFirst()),prefix:"FE-LANG",fid:h,fpath:PhDOE.user.lang+f,fname:c,loadStore:PhDOE.user.conf.error.toolsPanelLogLoad}),new ui.cmp.VCSLogGrid({layout:"fit",title:String.format(_("{0} Log"),"En"),prefix:"FE-EN",fid:h,fpath:"en"+f,fname:c,loadStore:PhDOE.user.conf.error.toolsPanelLogLoad})];e=(PhDOE.user.lang==="en")?[new ui.cmp.FilePanel({id:"FE-LANG-PANEL-"+h,region:"center",title:String.format(_("{0} File: "),PhDOE.user.lang)+f+c,prefix:"FE",ftype:"LANG",spellCheck:PhDOE.user.conf.error.enableSpellCheckLang,spellCheckConf:{module:"error",itemName:"enableSpellCheckLang"},fid:h,fpath:f,fname:c,lang:PhDOE.user.lang,parser:"xml",storeRecord:g,syncScrollCB:false,syncScroll:false})]:[new ui.cmp.FilePanel({id:"FE-LANG-PANEL-"+h,region:"center",title:String.format(_("{0} File: "),PhDOE.user.lang.ucFirst())+f+c,prefix:"FE",ftype:"LANG",spellCheck:PhDOE.user.conf.error.enableSpellCheckLang,spellCheckConf:{module:"error",itemName:"enableSpellCheckLang"},fid:h,fpath:f,fname:c,lang:PhDOE.user.lang,parser:"xml",storeRecord:g,syncScrollCB:true,syncScroll:true,syncScrollConf:{module:"error",itemName:"syncScrollbars"}}),new ui.cmp.FilePanel({id:"FE-EN-PANEL-"+h,region:"east",title:_("en File: ")+f+c,prefix:"FE",ftype:"EN",original:true,readOnly:true,openInNewTabBtn:true,fid:h,fpath:f,fname:c,lang:"en",parser:"xml",storeRecord:g,syncScroll:true,syncScrollConf:{module:"error",itemName:"syncScrollbars"}})];Ext.getCmp("main-panel").add({id:"FE-"+h,title:c,layout:"border",iconCls:"iconTabError",closable:true,tabLoaded:false,panVCSLang:!PhDOE.user.conf.errorDisplayLog,panVCSEn:(PhDOE.user.lang==="en")?true:!PhDOE.user.conf.errorDisplayLog,panLANGLoaded:false,panENLoaded:(PhDOE.user.lang==="en")?true:false,originTitle:c,defaults:{split:true},tabTip:String.format(_("File with error : in {0}"),f),listeners:{resize:function(l){(PhDOE.user.lang!=="en")?Ext.getCmp("FE-EN-PANEL-"+h).setWidth(l.getWidth()/2):""}},items:[{xtype:"panel",id:"FE-error-desc-"+h,region:"north",layout:"fit",title:_("Error description"),iconCls:"iconFilesError",collapsedIconCls:"iconFilesError",plugins:[Ext.ux.PanelCollapsedTitle],height:PhDOE.user.conf.error.descPanelHeight||150,collapsible:true,collapsed:!PhDOE.user.conf.error.descPanelDisplay,autoScroll:true,autoLoad:"./error?dir="+f+"&file="+c,listeners:{collapse:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"error",itemName:"descPanelDisplay",value:false})}},expand:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"error",itemName:"descPanelDisplay",value:true})}},resize:function(o,l,m){if(this.ownerCt.tabLoaded&&m&&m>50&&m!=PhDOE.user.conf.error.descPanelHeight){new ui.task.UpdateConfTask({module:"error",itemName:"descPanelHeight",value:m})}}}},{region:"west",xtype:"panel",title:_("Tools"),iconCls:"iconConf",collapsedIconCls:"iconConf",plugins:[Ext.ux.PanelCollapsedTitle],collapsible:true,collapsed:!PhDOE.user.conf.error.toolsPanelDisplay,layout:"fit",bodyBorder:false,width:PhDOE.user.conf.error.toolsPanelWidth||375,listeners:{collapse:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"error",itemName:"toolsPanelDisplay",value:false})}},expand:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"error",itemName:"toolsPanelDisplay",value:true})}},resize:function(l,m){if(this.ownerCt.tabLoaded&&m&&m!=PhDOE.user.conf.error.toolsPanelWidth){new ui.task.UpdateConfTask({module:"error",itemName:"toolsPanelWidth",value:m})}}},items:{xtype:"tabpanel",activeTab:0,tabPosition:"bottom",enableTabScroll:true,defaults:{autoScroll:true},items:[k,new ui.cmp.DictionaryGrid({layout:"fit",title:_("Dictionary"),prefix:"FE",fid:h}),{title:_("Entities"),layout:"fit",items:[new ui.cmp.EntitiesAcronymsPanel({dataType:"entities",prefix:"FE",ftype:"LANG",fid:h,loadStore:PhDOE.user.conf.error.toolsPanelEntitiesLoad})]},{title:_("Acronyms"),layout:"fit",items:[new ui.cmp.EntitiesAcronymsPanel({dataType:"acronyms",prefix:"FE",ftype:"LANG",fid:h,loadStore:PhDOE.user.conf.error.toolsPanelAcronymsLoad})]}]}},e]})}Ext.getCmp("main-panel").setActiveTab("FE-"+h)},initComponent:function(){Ext.apply(this,{store:ui.cmp._ErrorFileGrid.store,tbar:[_("Filter: ")," ",new Ext.form.TwinTriggerField({id:"FE-filter",width:180,hideTrigger1:true,enableKeyEvents:true,validateOnBlur:false,validationEvent:false,trigger1Class:"x-form-clear-trigger",trigger2Class:"x-form-search-trigger",listeners:{keypress:function(c,d){if(d.getKey()===d.ENTER){this.onTrigger2Click()}}},onTrigger1Click:function(){this.setValue("");this.triggers[0].hide();this.setSize(180,10);ui.cmp._ErrorFileGrid.instance.store.clearFilter()},onTrigger2Click:function(){var c=this.getValue(),d;if(c===""||c.length<3){this.markInvalid(_("Your filter must contain at least 3 characters"));return}this.clearInvalid();this.triggers[0].show();this.setSize(180,10);d=new RegExp(c,"i");ui.cmp._ErrorFileGrid.instance.store.filterBy(function(e){if(d.test(e.data.path)||d.test(e.data.name)||d.test(e.data.maintainer)||d.test(e.data.type)){return true}else{return false}},this)}})]});ui.cmp.ErrorFileGrid.superclass.initComponent.call(this);this.on("rowcontextmenu",this.onRowContextMenu,this);this.on("rowdblclick",this.onRowDblClick,this);if(PhDOE.user.lang==="en"){this.getColumnModel().setHidden(2,true)}}});ui.cmp._ErrorFileGrid.instance=null;ui.cmp.ErrorFileGrid.getInstance=function(c){if(!ui.cmp._ErrorFileGrid.instance){if(!c){c={}}ui.cmp._ErrorFileGrid.instance=new ui.cmp.ErrorFileGrid(c)}return ui.cmp._ErrorFileGrid.instance};Ext.namespace("ui","ui.cmp");ui.cmp.ExecDiff=Ext.extend(Ext.Panel,{layout:"fit",title:_("Diff From VCS"),iconCls:"iconDiffView",collapsedIconCls:"iconDiffView",autoScroll:true,plugins:[Ext.ux.PanelCollapsedTitle],onRender:function(d,c){ui.cmp.ExecDiff.superclass.onRender.call(this,d,c);this.el.mask(' '+_("Loading..."));XHR({scope:this,params:{task:"getDiff",DiffType:"vcs",FilePath:"en"+this.fpath,FileName:this.fname,Rev1:this.rev1,Rev2:this.rev2},success:function(e){var f=Ext.util.JSON.decode(e.responseText);Ext.get(this.prefix+"-diff-"+this.fid).dom.innerHTML=f.content;this.el.unmask()},callback:function(){Ext.getCmp(this.prefix+"-"+this.fid).panDiffLoaded=true;Ext.getCmp("main-panel").fireEvent("tabLoaded",this.prefix,this.fid)}})},initComponent:function(){Ext.apply(this,{html:'
'});ui.cmp.ExecDiff.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._FilePanel");Ext.namespace("ui.cmp._FilePanel.tbar.menu");Ext.namespace("ui.cmp._FilePanel.tbar.items");ui.cmp._FilePanel.tbar.items.undoRedo=function(c){Ext.apply(this,c);this.init();ui.cmp._FilePanel.tbar.items.undoRedo.superclass.constructor.call(this)};Ext.extend(ui.cmp._FilePanel.tbar.items.undoRedo,Ext.ButtonGroup,{init:function(){Ext.apply(this,{id:this.id_prefix+"-FILE-"+this.fid+"-grp-undoRedo",items:[{id:this.id_prefix+"-FILE-"+this.fid+"-btn-undo",scope:this,tooltip:_("Undo"),disabled:true,iconCls:"iconUndo",handler:function(){Ext.getCmp(this.id_prefix+"-FILE-"+this.fid).undo()}},{id:this.id_prefix+"-FILE-"+this.fid+"-btn-redo",scope:this,tooltip:_("Redo"),disabled:true,iconCls:"iconRedo",handler:function(){Ext.getCmp(this.id_prefix+"-FILE-"+this.fid).redo()}}]})}});ui.cmp._FilePanel.tbar.items.usernotes=function(c){Ext.apply(this,c);this.init();ui.cmp._FilePanel.tbar.items.usernotes.superclass.constructor.call(this)};Ext.extend(ui.cmp._FilePanel.tbar.items.usernotes,Ext.ButtonGroup,{init:function(){Ext.apply(this,{items:[{xtype:"usernotes",file:this.file,fid:Ext.id()}]})}});ui.cmp._FilePanel.tbar.items.common=function(c){Ext.apply(this,c);this.init();ui.cmp._FilePanel.tbar.items.common.superclass.constructor.call(this)};Ext.extend(ui.cmp._FilePanel.tbar.items.common,Ext.ButtonGroup,{init:function(){Ext.apply(this,{items:[{scope:this,tooltip:_("Close Tab"),iconCls:"iconClose",handler:function(){Ext.getCmp("main-panel").remove(this.prefix+"-"+this.fid)}},{id:this.prefix+"-"+this.fid+"-btn-tabLeft-"+this.ftype,scope:this,tooltip:_("Go to previous tab"),iconCls:"iconArrowLeft",handler:this.goToPreviousTab},{id:this.prefix+"-"+this.fid+"-btn-tabRight-"+this.ftype,scope:this,tooltip:_("Go to next tab"),disabled:true,iconCls:"iconArrowRight",handler:this.goToNextTab}]})}});ui.cmp._FilePanel.tbar.menu.lang=function(c){Ext.apply(this,c);this.init();ui.cmp._FilePanel.tbar.menu.lang.superclass.constructor.call(this)};Ext.extend(ui.cmp._FilePanel.tbar.menu.lang,Ext.Toolbar.Button,{text:_("MarkUp"),iconCls:"iconInsertCode",init:function(){Ext.apply(this,{menu:new Ext.menu.Menu({items:[{scope:this,text:_("Reviewed tag"),handler:function(){Ext.getCmp(this.comp_id).insertLine(2,"");Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("Revcheck tag"),handler:function(){Ext.getCmp(this.comp_id).insertLine(1,"");Ext.getCmp(this.comp_id).focus()}}]})})}});ui.cmp._FilePanel.tbar.menu.en=function(c){Ext.apply(this,c);this.init();ui.cmp._FilePanel.tbar.menu.en.superclass.constructor.call(this)};Ext.extend(ui.cmp._FilePanel.tbar.menu.en,Ext.Toolbar.Button,{text:_("MarkUp"),iconCls:"iconInsertCode",init:function(){Ext.apply(this,{menu:new Ext.menu.Menu({items:[{scope:this,text:_("Description section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,[' \r\n ',"&reftitle.description;\r\n ","\r\n ","\r\n ","thereturned typefunc_name\r\n ","\r\n ","param1typefirstparameter\r\n ","\r\n ",'intsecondparameter\r\n ',"\r\n ","\r\n ","\r\n ","\r\n ","The function description goes here.\r\n ","\r\n ",""].join(""));Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("Parameters section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,['\r\n\r\n',"&reftitle.parameters;\r\n","\r\n","\r\n","\r\n","firstparameter\r\n","\r\n","\r\n","Its description\r\n","\r\n","\r\n","\r\n","\r\n","\r\n","secondparameter\r\n","\r\n","\r\n","\r\n","Its description\r\n","\r\n","\r\n","\r\n","\r\n","\r\n",""].join(""));Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("Return section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,['\r\n\r\n',"&reftitle.returnvalues;\r\n","\r\n","What this function returns, first on success, then failure.\r\n","If simply true on success and false on failure, just use &return.success; here.\r\n","\r\n",""].join(""));Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("Error section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,['\r\n\r\n',"&reftitle.errors;\r\n","\r\n","When does this function issue E_* level errors, and/or throw exceptions.\r\n","\r\n","\r\n"].join(""));Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("Unicode section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,['\r\n\r\n',"&reftitle.unicode;\r\n","\r\n","Information specific to unicode, from the PHP 6 changes.\r\n","\r\n",""].join(""));Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("Changelog section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,['\r\n\r\n',"&reftitle.changelog;\r\n","\r\n","\r\n",'\r\n',"\r\n","\r\n","&Version;\r\n","&Description;\r\n","\r\n","\r\n","\r\n","\r\n","Enter the version of change here\r\n","\r\n","Describe the change\r\n","\r\n","\r\n","\r\n","\r\n","\r\n","\r\n",""].join(""));Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("Examples section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,['\r\n\r\n',"&reftitle.examples;\r\n","\r\n",'\r\n',"<function>function-name</function> example\r\n","\r\n","Any text that describes the purpose of the example, or what\r\n","goes on in the example should be here. (Inside the tag, not out).\r\n","\r\n",'\r\n',"\r\n","]]>\r\n","\r\n","&example.outputs.similar;\r\n","\r\n","\r\n","\r\n","\r\n","\r\n",""].join(""));Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("Notes section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,['\r\n\r\n',"&reftitle.notes;\r\n","\r\n","\r\n","Any notes that don't fit anywhere else should go here.\r\n","90% of the time, notes, warnings or cautions are better placed in the\r\n","parameters section. Consider that before using this section!\r\n","\r\n","\r\n","¬e.language-construct;\r\n","¬e.not-bin-safe;\r\n","¬e.registerglobals;\r\n",""].join(""));Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("SeeAlso section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,['\r\n\r\n',"&reftitle.seealso;\r\n","\r\n","\r\n","somefunc\r\n","another_func\r\n",'The something appendix\r\n',"\r\n","\r\n",""].join(""));Ext.getCmp(this.comp_id).focus()}}]})})}});ui.cmp._FilePanel.tbar.items.reindentTags=function(c){Ext.apply(this,c);this.init();ui.cmp._FilePanel.tbar.items.reindentTags.superclass.constructor.call(this)};Ext.extend(ui.cmp._FilePanel.tbar.items.reindentTags,Ext.ButtonGroup,{init:function(){Ext.apply(this,{id:this.id_prefix+"-FILE-"+this.fid+"-grp-tools",items:[{scope:this,tooltip:_("Check XML with XmlLint"),iconCls:"iconXml",handler:function(c){new ui.task.CheckXml({idPrefix:this.id_prefix,fid:this.fid})}},(this.lang==="en")?new ui.cmp._FilePanel.tbar.menu.en({comp_id:this.id_prefix+"-FILE-"+this.fid}):new ui.cmp._FilePanel.tbar.menu.lang({comp_id:this.id_prefix+"-FILE-"+this.fid}),{scope:this,text:_("Editor option"),iconCls:"iconConf",menu:[{scope:this,text:_("Re-indent all this file"),iconCls:"iconIndent",handler:function(){Ext.getCmp(this.id_prefix+"-FILE-"+this.fid).reIndentAll()}},{scope:this,text:_("Enable line wrapping"),checked:((PhDOE.user.conf.main.lineWrapping===true)?true:false),checkHandler:function(d,c){var e=(c)?true:false;Ext.getCmp(this.id_prefix+"-FILE-"+this.fid).setOption("lineWrapping",e);new ui.task.UpdateConfTask({module:"main",itemName:"lineWrapping",value:c,notify:false})}},{scope:this,text:_("Choose a Theme"),iconCls:"iconThemes",onThemeChange:function(){var c=Ext.getCmp(this.ownerCt.ownerCt.ownerCt.id_prefix+"-FILE-"+this.ownerCt.ownerCt.ownerCt.fid);Ext.each(this.menu.items.items,function(d){if(d.checked===true){c.switchTheme(d.themeName);new ui.task.UpdateConfTask({module:"main",itemName:"editorTheme",value:d.themeName,notify:false})}})},menu:{items:[{text:_("No theme"),themeName:false,checked:(PhDOE.user.conf.main.editorTheme===false),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}},{text:_("Default theme"),themeName:"default",checked:(PhDOE.user.conf.main.editorTheme==="default"||PhDOE.user.conf.main.editorTheme==="undefined"),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}},{text:_("Cobalt"),themeName:"cobalt",checked:(PhDOE.user.conf.main.editorTheme==="cobalt"),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}},{text:_("Eclipse"),themeName:"eclipse",checked:(PhDOE.user.conf.main.editorTheme==="eclipse"),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}},{text:_("Elegant"),themeName:"elegant",checked:(PhDOE.user.conf.main.editorTheme==="elegant"),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}},{text:_("Monokai"),themeName:"monokai",checked:(PhDOE.user.conf.main.editorTheme==="monokai"),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}},{text:_("Neat"),themeName:"neat",checked:(PhDOE.user.conf.main.editorTheme==="neat"),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}},{text:_("Night"),themeName:"night",checked:(PhDOE.user.conf.main.editorTheme==="night"),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}},{text:_("RubyBlue"),themeName:"rubyblue",checked:(PhDOE.user.conf.main.editorTheme==="rubyblue"),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}}]}}]}]})}});ui.cmp.FilePanel=Ext.extend(Ext.form.FormPanel,{activeScroll:false,goToPreviousTab:function(){var c=this.prefix+"-"+this.fid,e=Ext.getCmp("main-panel").layout.container.items.items,g,f,d;for(d=0;d','',_("Line: "),'-','  ',_("Col: "),'-',"  "].join(""))}}}]:[{xtype:"panel",height:22,baseCls:"",bodyStyle:"padding-top:5px;",html:['
','',_("Line: "),'-','  ',_("Col: "),'-',"
  "].join("")}];if(!this.readOnly){this.tbar=[new ui.cmp._FilePanel.tbar.items.common({prefix:this.prefix,fid:this.fid,ftype:this.ftype,goToPreviousTab:this.goToPreviousTab,goToNextTab:this.goToNextTab}),{xtype:"buttongroup",id:c+"-FILE-"+this.fid+"-grp-save",items:[{id:c+"-FILE-"+this.fid+"-btn-save",scope:this,tooltip:_("Save this file (CTRL+s)"),iconCls:"iconSaveFile",disabled:true,handler:function(){if(this.prefix==="AF"){new ui.task.SaveFileTask({prefix:this.prefix,ftype:this.ftype,fid:this.fid,fpath:this.fpath,fname:this.fname,lang:this.lang,storeRecord:this.storeRecord});return}if(this.prefix==="FNT"){new ui.task.SaveTransFileTask({prefix:this.prefix,ftype:this.ftype,fid:this.fid,fpath:this.fpath,fname:this.fname,lang:this.lang,storeRecord:this.storeRecord});return}if(!PhDOE.user.conf.main.onSaveFile){PhDOE.user.conf.main.onSaveFile="ask-me"}switch(PhDOE.user.conf.main.onSaveFile){case"always":new ui.task.CheckFileTask({prefix:this.prefix,ftype:this.ftype,fid:this.fid,fpath:this.fpath,fname:this.fname,lang:this.lang,storeRecord:this.storeRecord});break;case"never":new ui.task.SaveFileTask({prefix:this.prefix,ftype:this.ftype,fid:this.fid,fpath:this.fpath,fname:this.fname,lang:this.lang,storeRecord:this.storeRecord});break;case"ask-me":Ext.MessageBox.show({title:_("Confirm"),msg:_("Do you want to check for errors before saving?"),icon:Ext.MessageBox.INFO,buttons:Ext.MessageBox.YESNOCANCEL,scope:this,fn:function(d){if(d==="no"){new ui.task.SaveFileTask({prefix:this.prefix,ftype:this.ftype,fid:this.fid,fpath:this.fpath,fname:this.fname,lang:this.lang,storeRecord:this.storeRecord})}else{if(d==="yes"){new ui.task.CheckFileTask({prefix:this.prefix,ftype:this.ftype,fid:this.fid,fpath:this.fpath,fname:this.fname,lang:this.lang,storeRecord:this.storeRecord})}}}});break}}}]},new ui.cmp._FilePanel.tbar.items.undoRedo({id_prefix:c,fid:this.fid}),new ui.cmp._FilePanel.tbar.items.reindentTags({id_prefix:c,fid:this.fid,lang:this.lang}),{scope:this,iconCls:"iconZoom",tooltip:_("Expand in a popup"),handler:function(d){var e=new Ext.Window({title:this.originTitle,bodyStyle:"background-color:white",maximized:true,animateTarget:d.el,items:[{xtype:"codemirror",id:c+"-FILE-"+this.fid+"maximized",readOnly:false,lineWrapping:PhDOE.user.conf.main.lineWrapping,theme:PhDOE.user.conf.main.editorTheme,parser:this.parser,isModified:false,listeners:{scope:this,initialize:function(){var h=Ext.getCmp(c+"-FILE-"+this.fid+"maximized"),f=Ext.getCmp(c+"-FILE-"+this.fid).getValue();h.setValue(f);var g=new Ext.util.DelayedTask(function(){if(e.rendered){h.resize(false,e.getInnerHeight()+89)}else{g.delay(500)}});g.delay(500)}}}],listeners:{scope:this,beforeclose:function(g){var f=g.items.items[0].getValue();Ext.getCmp(c+"-FILE-"+this.fid).setValue(f)}}});e.show()}},{scope:this,iconCls:"iconView",hidden:!(this.lang==="en"&&this.fname.substr(-3)==="xml"),tooltip:_("Preview in a popup"),handler:function(){var d=Ext.getCmp(c+"-FILE-"+this.fid).isModified;if(d){Ext.Msg.alert(_("Information"),_("You must save your file in order to preview the result."),function(e){if(e=="ok"){new ui.cmp.PreviewFile({path:this.lang+this.fpath+this.fname})}},this)}else{new ui.cmp.PreviewFile({path:this.lang+this.fpath+this.fname})}}},"->",new ui.cmp._FilePanel.tbar.items.usernotes({fid:this.fid,file:this.lang+this.fpath+this.fname})]}else{this.tbar=[new ui.cmp._FilePanel.tbar.items.common({prefix:this.prefix,fid:this.fid,ftype:this.ftype,goToPreviousTab:this.goToPreviousTab,goToNextTab:this.goToNextTab}),{xtype:"buttongroup",hidden:(this.openInNewTabBtn!==true),scope:this,items:[{tooltip:_("Open for editing in a new Tab"),iconCls:"iconEditInNewTab",scope:this,handler:function(){ui.cmp.RepositoryTree.getInstance().openFile("byPath",this.lang+this.fpath,this.fname)}}]},"->",((this.ftype!=="GGTRANS")?new ui.cmp._FilePanel.tbar.items.usernotes({fid:this.fid,file:this.lang+this.fpath+this.fname}):"")]}Ext.apply(this,{title:this.title,cls:"code-mirror-panel",originTitle:this.title,items:[{xtype:"codemirror",id:c+"-FILE-"+this.fid,readOnly:this.readOnly,lineWrapping:PhDOE.user.conf.main.lineWrapping,theme:PhDOE.user.conf.main.editorTheme,parser:this.parser,isModified:false,listeners:{scope:this,initialize:function(){var e,d;if(this.isTrans){if(this.storeRecord.data.fileModified){e=this.lang+this.fpath;d=this.fname}else{e="en"+this.fpath;d=this.fname}}else{e=this.lang+this.fpath;d=this.fname}new ui.task.GetFileTask({prefix:this.prefix,ftype:this.ftype,original:this.original,fid:this.fid,fpath:e,freadOnly:this.readOnly,fname:d,skeleton:this.skeleton,storeRecord:this.storeRecord})},coderestored:function(){if(this.readOnly){return}if(Ext.getCmp(c+"-FILE-"+this.fid).isModified){Ext.getCmp(c+"-PANEL-"+this.fid).setTitle(Ext.getCmp(c+"-PANEL-"+this.fid).permlink+Ext.getCmp(c+"-PANEL-"+this.fid).originTitle);if((this.ftype==="LANG"&&PhDOE.user.lang!=="en")||this.ftype==="EN"){if((this.ftype==="EN"&&!Ext.getCmp(this.prefix+"-LANG-FILE-"+this.fid).isModified)||(this.ftype==="LANG"&&!Ext.getCmp(this.prefix+"-EN-FILE-"+this.fid).isModified)){Ext.getCmp(this.prefix+"-"+this.fid).setTitle(Ext.getCmp(this.prefix+"-"+this.fid).originTitle)}}else{Ext.getCmp(this.prefix+"-"+this.fid).setTitle(Ext.getCmp(this.prefix+"-"+this.fid).originTitle)}Ext.getCmp(c+"-FILE-"+this.fid+"-btn-save").disable();Ext.getCmp(c+"-FILE-"+this.fid).isModified=false}},codemodified:function(){if(this.readOnly){return}if(Ext.getCmp(c+"-FILE-"+this.fid+"-grp-save").disabled){return}var e=Ext.getCmp(c+"-FILE-"+this.fid),d=Ext.getCmp(c+"-PANEL-"+this.fid);if(!e.isModified){d.setTitle(d.permlink+d.originTitle+' ['+_("modified")+"]");Ext.getCmp(this.prefix+"-"+this.fid).setTitle(Ext.getCmp(this.prefix+"-"+this.fid).originTitle+' *');Ext.getCmp(c+"-FILE-"+this.fid+"-btn-save").enable();Ext.getCmp(c+"-FILE-"+this.fid+"-btn-undo").enable();e.isModified=true}},cursormove:function(d,e){Ext.get(c+"-status-line-"+this.fid).dom.innerHTML=d;Ext.get(c+"-status-col-"+this.fid).dom.innerHTML=e},scroll:function(g){var e,f,d;if(this.syncScroll&&PhDOE.user.conf[this.syncScrollConf.module][this.syncScrollConf.itemName]){switch(this.ftype){case"EN":if(this.prefix=="FNT"){e=this.prefix+"-TRANS"}else{e=this.prefix+"-LANG"}break;case"LANG":e=this.prefix+"-EN";break;case"TRANS":if(PhDOE.user.conf.newFile.secondPanel=="google"){e=this.prefix+"-GGTRANS"}if(PhDOE.user.conf.newFile.secondPanel=="originalFile"){e=this.prefix+"-EN"}break;case"GGTRANS":e=this.prefix+"-TRANS";break}f=Ext.getCmp(e+"-PANEL-"+this.fid);d=Ext.getCmp(e+"-FILE-"+this.fid);if(f.activeScroll===false){this.activeScroll=true;d.scrollTo(g)}else{f.activeScroll=false}}}}}]});ui.cmp.FilePanel.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp");ui.cmp.GoogleTranslationPanel=Ext.extend(Ext.FormPanel,{border:false,labelAlign:"top",bodyStyle:"padding:5px",autoScroll:true,getTranslation:function(c){new ui.task.GetGGTranslation({str:c})},initComponent:function(){Ext.apply(this,{items:[{xtype:"textarea",anchor:"90%",fieldLabel:String.format(_("String to translate (en => {0})"),PhDOE.user.lang),name:"GGTranslate-string",id:"GGTranslate-string",allowBlank:false},{scope:this,xtype:"button",text:_("Translate !"),id:"GGTranslate-btn",handler:function(){this.getTranslation(Ext.getCmp("GGTranslate-string").getValue())}},{xtype:"panel",anchor:"100%",border:false,bodyStyle:"padding:5px",html:'
'}]});ui.cmp.GoogleTranslationPanel.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._MainMenu");ui.cmp.MainMenu=function(c){Ext.apply(this,c);this.init();ui.cmp.MainMenu.superclass.constructor.call(this)};ui.cmp._MainMenu.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getAvailableLanguage"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"code",fields:[{name:"code"},{name:"iconCls"},{name:"name"}]})});ui.cmp._MainMenu.store.on("load",function(c){Ext.getDom("Info-Language").innerHTML=Ext.getDom("Topic-Language").innerHTML=c.getById(PhDOE.user.lang).data.name;c.each(function(d){var e=new Ext.menu.Item({text:d.data.name+" ("+d.data.code+")",iconCls:"mainMenuLang flags "+d.data.iconCls,disabled:(d.data.code===PhDOE.user.lang),handler:function(){XHR({params:{task:"switchLang",lang:d.data.code},success:function(){window.location.reload()}})}});Ext.getCmp("MenuLang-ct").add(e)})},this);Ext.extend(ui.cmp.MainMenu,Ext.menu.Menu,{id:"mainMenu",init:function(){var c=new Ext.menu.Menu({id:"MenuLang-ct"});Ext.apply(this,{items:[{text:_("Refresh all data"),disabled:(!PhDOE.user.isGlobalAdmin),iconCls:"iconRefresh",handler:function(){Ext.getBody().mask(' '+_("Verify if there is an update in progress. Please, wait..."));XHR({params:{task:"checkLockFile",lockFiles:"project_"+PhDOE.project+"_lock_update_repository|project_"+PhDOE.project+"_lock_apply_tools"},success:function(){Ext.getBody().unmask();Ext.MessageBox.show({title:_("Status"),msg:_("There is currently an update in progress.
You can't perform an update now."),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.INFO})},failure:function(){Ext.getBody().unmask();new ui.cmp.SystemUpdatePrompt().show(Ext.get("acc-need-update"))}})}},{text:_("Build tools"),handler:function(){return false},menu:new Ext.menu.Menu({items:[{text:_("Check build"),disabled:(!PhDOE.user.isGlobalAdmin&&!PhDOE.user.isLangAdmin),iconCls:"iconCheckBuild",handler:function(){Ext.getBody().mask(' '+_("Verify if there is a check in progress. Please, wait..."));XHR({params:{task:"checkLockFile",lockFile:"project_"+PhDOE.project+"_lock_check_build_"+PhDOE.user.lang},success:function(){Ext.getBody().unmask();Ext.MessageBox.show({title:_("Status"),msg:_("There is currently a check in progress for this language.
You can't perform a new check now."),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.INFO})},failure:function(){Ext.getBody().unmask();new ui.cmp.CheckBuildPrompt().show(Ext.get("acc-need-update"))}})}},{text:_("Show last failed build"),iconCls:"iconBuildStatus",handler:function(){var d=Ext.getCmp("tab-build-status");if(!d){Ext.getCmp("main-panel").add({id:"tab-build-status",title:_("Last failed build"),iconCls:"iconBuildStatus",layout:"fit",closable:true,items:[new ui.cmp.BuildStatus()]})}Ext.getCmp("main-panel").setActiveTab("tab-build-status")}}]})},{text:_("EN tools"),handler:function(){return false},menu:new Ext.menu.Menu({items:[{text:_("Script check entities"),iconCls:"iconCheckEntities",handler:function(){return false},menu:new Ext.menu.Menu({items:[{text:_("View the last result"),id:"btn-check-entities-view-last-result",iconCls:"iconTabView",handler:function(){var d=Ext.getCmp("tab-check-entities");if(!d){Ext.getCmp("main-panel").add({id:"tab-check-entities",title:_("Check entities"),iconCls:"iconCheckEntities",layout:"fit",closable:true,items:[new ui.cmp.CheckEntities()]})}Ext.getCmp("main-panel").setActiveTab("tab-check-entities")}},{text:_("Run this script"),iconCls:"iconRun",disabled:(PhDOE.user.isAnonymous),handler:function(){Ext.getBody().mask(' '+_("Verify if there is an entities check in progress. Please, wait..."));XHR({params:{task:"checkLockFile",lockFile:"project_"+PhDOE.project+"_lock_check_entities"},success:function(){Ext.getBody().unmask();Ext.MessageBox.show({title:_("Status"),msg:_("There is currently a check in progress for the entities.
You can't perform a new check now."),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.INFO})},failure:function(){Ext.getBody().unmask();if(!Ext.getCmp("win-check-entities")){new ui.cmp.CheckEntitiesPrompt()}Ext.getCmp("win-check-entities").show(Ext.get("mainMenu"))}})}}]})},{text:_("Script check document"),iconCls:"iconCheckDoc",handler:function(){var d=Ext.getCmp("tab-check-doc");if(!d){Ext.getCmp("main-panel").add({id:"tab-check-doc",title:"Check Doc",iconCls:"iconCheckDoc",layout:"fit",closable:true,items:[new ui.cmp.CheckDoc()]})}Ext.getCmp("main-panel").setActiveTab("tab-check-doc")}}]})},"-",{text:_("Configure"),iconCls:"iconConf",tooltip:"Configure this tool",id:"winconf-btn",handler:function(){if(!Ext.getCmp("win-conf")){new ui.cmp.EditorConf()}Ext.getCmp("win-conf").show(Ext.get("mainMenu"))}},"-",{id:"menuLang",iconCls:"iconSwitchLang",text:_("Switch to language..."),handler:function(){return false},menu:c},{text:_("Erase my personal data"),iconCls:"iconErasePersonalData",disabled:(PhDOE.user.isAnonymous),handler:function(){Ext.MessageBox.confirm(_("Confirm"),_("This action will erase your personal data. All content about this account will be deleted definitively. Are you sure you want to do that ?"),function(d){if(d==="yes"){Ext.getBody().mask(' '+_("Please, wait..."));XHR({params:{task:"erasePersonalData"},success:function(){Ext.getBody().unmask();Ext.MessageBox.show({title:_("Thanks !"),msg:_("Thank you for using this application !"),icon:Ext.MessageBox.INFO,buttons:Ext.MessageBox.OK,fn:function(){window.location.href="./do/logout?csrfToken="+csrfToken}})},failure:function(){Ext.getBody().unmask();PhDOE.winForbidden()}})}})}},{text:_("Log out"),iconCls:"iconLogOut",handler:function(){Ext.MessageBox.confirm(_("Confirm"),_("Are you sure you want to logout?"),function(d){if(d==="yes"){window.location.href="./do/logout?csrfToken="+csrfToken}})}},"-",{id:"tab-report-bug-btn",text:_("Report bugs"),iconCls:"iconBugs",handler:function(){if(!Ext.getCmp("main-panel").findById("tab-report-bug")){Ext.getCmp("main-panel").add({id:"tab-report-bug",xtype:"panel",title:_("Report bugs"),iconCls:"iconBugs",closable:true,layout:"fit",items:[new Ext.ux.IFrameComponent({id:"frame-tab-report-bug",url:"http://bugs.php.net/"})]});Ext.getCmp("main-panel").setActiveTab("tab-report-bug")}else{Ext.getCmp("main-panel").setActiveTab("tab-report-bug")}}},{id:"tab-documentation-btn",text:_("Documentation"),iconCls:"iconBook",handler:function(){if(!Ext.getCmp("main-panel").findById("tab-documentation")){Ext.getCmp("main-panel").add({id:"tab-documentation",xtype:"panel",title:_("Documentation"),iconCls:"iconBook",closable:true,layout:"fit",items:[new Ext.ux.IFrameComponent({id:"frame-tab-documentation",url:"https://wiki.php.net/doc/editor/"})]});Ext.getCmp("main-panel").setActiveTab("tab-documentation")}else{Ext.getCmp("main-panel").setActiveTab("tab-documentation")}}},{id:"tab-chat-btn",text:_("Chat with us on IRC !"),iconCls:"iconChat",handler:function(){if(!Ext.getCmp("main-panel").findById("tab-chat")){var d=PhDOE.user.login;if(PhDOE.user.isAnonymous){d="an%3F%3F%3F"}Ext.getCmp("main-panel").add({id:"tab-chat",xtype:"panel",title:_("Chat"),iconCls:"iconChat",closable:true,layout:"fit",items:[new Ext.ux.IFrameComponent({id:"frame-tab-chat",url:"https://widget.mibbit.com/?settings=8eec4034df2eb666b0600bdfe151529a&server=irc.umich.edu&channel=%23php.doc&nick=poe_"+d})]})}Ext.getCmp("main-panel").setActiveTab("tab-chat")}},"-",{id:"winabout-btn",text:_("About"),iconCls:"iconHelp",handler:function(){new ui.cmp.About().show(Ext.get("winabout-btn"))}}]})}});Ext.namespace("ui","ui.cmp","ui.cmp.MainPanel");ui.cmp.MainPanel=Ext.extend(Ext.ux.SlidingTabPanel,{activeTab:0,enableTabScroll:true,plugins:["tabclosemenu","dblclickclosetabs"],initComponent:function(c){Ext.apply(this,c);ui.cmp.MainPanel.superclass.initComponent.call(this);this.addEvents({tabLoaded:true});this.on("beforeremove",this.onBeforeRemove,this);this.on("tabchange",this.onTabChange,this);this.on("endDrag",this.onTabChange,this);this.on("tabLoaded",this.onTabLoaded,this)},onTabLoaded:function(d,e){var c=Ext.getCmp(d+"-"+e);if(d==="FNT"){if(c.panTRANSLoaded&&c.panTRANSSecondLoaded){c.tabLoaded=true;c.panTRANSLoaded=c.panTRANSSecondLoaded=false;if(PhDOE.FNTfilePendingOpen[0]){ui.cmp.PendingTranslateGrid.getInstance().openFile(PhDOE.FNTfilePendingOpen[0].id);PhDOE.FNTfilePendingOpen.shift()}}}if(d==="FNU"){if(c.panLANGLoaded&&c.panENLoaded&&c.panDiffLoaded&&c.panVCSLang&&c.panVCSEn){c.tabLoaded=true;c.panLANGLoaded=c.panENLoaded=c.panDiffLoaded=c.panVCSLang=c.panVCSEn=false;if(PhDOE.FNUfilePendingOpen[0]){ui.cmp.StaleFileGrid.getInstance().openFile(PhDOE.FNUfilePendingOpen[0].id);PhDOE.FNUfilePendingOpen.shift()}}}if(d==="FE"){if(c.panLANGLoaded&&c.panENLoaded&&c.panVCSLang&&c.panVCSEn){c.tabLoaded=true;c.panLANGLoaded=c.panENLoaded=c.panVCSLang=c.panVCSEn=false;if(PhDOE.FEfilePendingOpen[0]){ui.cmp.ErrorFileGrid.getInstance().openFile(PhDOE.FEfilePendingOpen[0].id);PhDOE.FEfilePendingOpen.shift()}}}if(d==="FNR"){if(c.panLANGLoaded&&c.panENLoaded&&c.panVCSLang&&c.panVCSEn){c.tabLoaded=true;c.panLANGLoaded=c.panENLoaded=c.panVCSLang=c.panVCSEn=false;if(PhDOE.FNRfilePendingOpen[0]){ui.cmp.PendingReviewGrid.getInstance().openFile(PhDOE.FNRfilePendingOpen[0].id);PhDOE.FNRfilePendingOpen.shift()}}}if(d==="FNIEN"){if(c.panLANGLoaded){c.tabLoaded=true;c.panLANGLoaded=false;if(PhDOE.FNIENfilePendingOpen[0]){ui.cmp.NotInENGrid.getInstance().openFile(PhDOE.FNIENfilePendingOpen[0].id);PhDOE.FNIENfilePendingOpen.shift()}}}if(d==="AF"){if(c.panLoaded&&c.panVCS&&c.panEntities&&c.panAcronyms){c.tabLoaded=true;c.panLoaded=c.panVCS=false;if(PhDOE.AFfilePendingOpen[0]){ui.cmp.RepositoryTree.getInstance().openFile((PhDOE.AFfilePendingOpen[0].nodeID)?"byId":"byPath",(PhDOE.AFfilePendingOpen[0].nodeID)?PhDOE.AFfilePendingOpen[0].nodeID:PhDOE.AFfilePendingOpen[0].fpath,(PhDOE.AFfilePendingOpen[0].nodeID)?false:PhDOE.AFfilePendingOpen[0].fname);PhDOE.AFfilePendingOpen.shift()}}}if(d==="PP"){if(c.panPatchLoaded&&c.panOriginLoaded&&c.panVCS&&c.panPatchContent){c.tabLoaded=true;c.panPatchLoaded=c.panOriginLoaded=c.panVCS=c.panPatchContent=false;if(PhDOE.PPfilePendingOpen[0]){ui.cmp.PendingPatchGrid.getInstance().openFile(PhDOE.PPfilePendingOpen[0].id);PhDOE.PPfilePendingOpen.shift()}}}},onTabChange:function(d,g){if(Ext.getCmp(g.id+"-btn-tabRight-LANG")||Ext.getCmp(g.id+"-btn-tabRight-EN")||Ext.getCmp(g.id+"-btn-tabRight-ALL")||Ext.getCmp(g.id+"-btn-tabRight-NotInEN")||Ext.getCmp(g.id+"-btn-tabRight-PATCH")||Ext.getCmp(g.id+"-btn-tabRight-TRANS")||Ext.getCmp(g.id+"-btn-tabRight-NEW")){var c=g.id,f=Ext.getCmp("main-panel").layout.container.items.items,h,e;for(e=0;eDo you really want to close?"),buttons:Ext.Msg.YESNO,icon:Ext.Msg.QUESTION,fn:function(j,k){if(j==="yes"){f.un("beforeremove",this.onBeforeRemove,this);f.remove(g);f.addListener("beforeremove",this.onBeforeRemove,this)}}});return false}else{return true}}else{return true}},openDiffTab:function(d){var f=d.DiffType,k=d.currentOwner||"",h=d.fileIdDB||"",j=d.FileName||"",e=d.FilePath||"",p=d.patchID||"",o=d.patchName||"",g,l=Ext.util.md5(o+p+e+j),q,c,m;if(p!=""){q=String.format(_("Diff for patch: {0}"),o);g="./do/downloadPatch?patchID="+p+"&csrfToken="+csrfToken;c=_("Download the unified diff as a patch")}else{q=String.format(_("Diff for file: {0}"),e+j);g="./do/downloadPatch?FilePath="+e+"&FileName="+j+"&csrfToken="+csrfToken;c=_("Download the diff as a patch")}if(!Ext.getCmp("main-panel").findById("diff_panel_"+l)){m=[{xtype:"buttongroup",items:[{xtype:"button",iconCls:"iconEdit",tooltip:_("Edit in a new tab"),handler:function(){ui.cmp.RepositoryTree.getInstance().openFile("byPath",e,j)}},{xtype:"button",iconCls:"iconDownloadDiff",tooltip:c,handler:function(){window.location.href=g}}]},((PhDOE.user.isGlobalAdmin||PhDOE.user.isLangAdmin)?{xtype:"buttongroup",items:[{xtype:"button",iconCls:"iconPageDelete",tooltip:_("Clear this change"),handler:function(){new ui.task.ClearLocalChangeTask({ftype:"update",fpath:e,fname:j});Ext.getCmp("main-panel").remove("diff_panel_"+l)}},{xtype:"button",iconCls:"iconSwitchLang",tooltip:_("Change file's owner"),handler:function(){new ui.cmp.ChangeFileOwner({fileIdDB:h,fileFolder:e,fileName:j,currentOwner:k})}}]}:"")];Ext.getCmp("main-panel").add({xtype:"panel",id:"diff_panel_"+l,title:_("Diff"),tabTip:q,closable:true,autoScroll:true,iconCls:"iconTabLink",html:'
',tbar:m});Ext.getCmp("main-panel").setActiveTab("diff_panel_"+l);Ext.get("diff_panel_"+l).mask(''+_("Please, wait..."));XHR({params:{task:"getDiff",DiffType:f,FilePath:e,FileName:j,patchID:p},success:function(s){var u=Ext.util.JSON.decode(s.responseText),t="";if(p==""){t='

'+_("Direct link to this patch")+" ; "+_("File: ")+e+j+"

"}else{t='

'+_("Direct link to this patch")+" ; "+_("Patch Name: ")+o+"

"}u.content=t+u.content;Ext.get("diff_content_"+l).dom.innerHTML=u.content;Ext.get("diff_panel_"+l).unmask()}})}else{Ext.getCmp("main-panel").setActiveTab("diff_panel_"+l)}}});Ext.reg("mainpanel",ui.cmp.MainPanel);Ext.namespace("ui","ui.cmp");ui.cmp.ManagePatchPrompt=Ext.extend(Ext.Window,{title:"",width:450,height:260,minWidth:450,minHeight:300,layout:"fit",plain:true,bodyStyle:"padding:5px;",buttonAlign:"center",iconCls:"iconPatch",closeAction:"hide",nodesToAdd:false,patchName:"",patchDescription:"",patchEmail:"",patchID:false,initComponent:function(){Ext.apply(this,{buttons:[{text:(this.patchID)?_("Save"):_("Create"),handler:function(){var d=this.ownerCt.ownerCt,c=d.findByType("form").shift().getForm().getValues();XHR({params:{task:"managePatch",name:c.name,description:c.description,email:c.email,patchID:d.patchID},success:function(e){var f=Ext.util.JSON.decode(e.responseText);d.hide();if(d.patchID){ui.cmp.PatchesTreeGrid.getInstance().modPatchName({newPatchName:c.name,newPatchDescription:c.description,newPatchEmail:c.email,patchID:d.patchID})}if(d.nodesToAdd){ui.task.MoveToPatch({patchID:f.patchID,patchName:c.name,patchDescription:c.description,patchEmail:c.email,nodesToAdd:d.nodesToAdd})}}})}},{text:_("Cancel"),handler:function(){this.ownerCt.ownerCt.hide()}}],items:[{xtype:"form",baseCls:"x-plain",labelWidth:110,defaultType:"textfield",labelAlign:"top",items:[{name:"name",fieldLabel:_("Patch name"),anchor:"100%",value:this.patchName},{name:"description",xtype:"textarea",fieldLabel:_("Patch description"),tooltipText:_("This description will be the default during the validation of the patch by a valid user."),anchor:"100%",value:this.patchDescription},{name:"email",fieldLabel:_("Email"),tooltipText:_("If provided, an email will be send to you to inform that the patch is commited."),anchor:"100%",value:this.patchEmail}]}]});ui.cmp.ManagePatchPrompt.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._NotInENGrid");ui.cmp._NotInENGrid.store=new Ext.data.GroupingStore({proxy:new Ext.data.HttpProxy({url:"./do/getFilesNotInEn"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"path"},{name:"name"},{name:"fileModified"}]}),sortInfo:{field:"path",direction:"ASC"},groupField:"path",listeners:{datachanged:function(c){Ext.getDom("acc-notInEn-nb").innerHTML=c.getCount()}}});ui.cmp._NotInENGrid.columns=[{id:"name",header:_("Files"),sortable:true,dataIndex:"name",renderer:function(d,c,e){if(e.data.fileModified){var f=Ext.util.JSON.decode(e.data.fileModified);if(f.user===PhDOE.user.login&&f.anonymousIdent===PhDOE.user.anonymousIdent){return""+d+""}else{return""+d+""}}else{return d}}},{header:_("Path"),dataIndex:"path",hidden:true}];ui.cmp._NotInENGrid.view=new Ext.grid.GroupingView({forceFit:true,startCollapsed:true,groupTextTpl:'{[values.rs[0].data["path"]]} ({[values.rs.length]} {[values.rs.length > 1 ? "'+_("Files")+'" : "'+_("File")+'"]})',deferEmptyText:false,emptyText:'
'+_("No Files")+"
",getRowClass:function(c){if(c.data.fileModified){var d=Ext.util.JSON.decode(c.data.fileModified);return(d.user===PhDOE.user.login&&d.anonymousIdent===PhDOE.user.anonymousIdent)?"fileModifiedByMe":"fileModifiedByAnother"}return false}});ui.cmp._NotInENGrid.menu=function(c){Ext.apply(this,c);this.init();ui.cmp._NotInENGrid.menu.superclass.constructor.call(this)};Ext.extend(ui.cmp._NotInENGrid.menu,Ext.menu.Menu,{init:function(){Ext.apply(this,{items:[{scope:this,text:""+_("View in a new tab")+"",iconCls:"iconView",handler:function(){this.grid.fireEvent("rowdblclick",this.grid,this.rowIdx,this.event)}},{scope:this,text:_("Remove this file"),hidden:(this.grid.store.getAt(this.rowIdx).data.fileModified),iconCls:"iconTrash",handler:function(){var e=this.grid.store.getAt(this.rowIdx),d=e.data.path,c=e.data.name;new ui.task.MarkDeleteTask({fpath:d,fname:c,storeRecord:e})}}]})}});ui.cmp.NotInENGrid=Ext.extend(Ext.grid.GridPanel,{loadMask:true,border:false,autoExpandColumn:"name",enableDragDrop:true,ddGroup:"mainPanelDDGroup",view:ui.cmp._NotInENGrid.view,columns:ui.cmp._NotInENGrid.columns,onRowContextMenu:function(c,f,d){d.stopEvent();c.getSelectionModel().selectRow(f);new ui.cmp._NotInENGrid.menu({grid:c,rowIdx:f,event:d}).showAt(d.getXY())},onRowDblClick:function(c,f,d){this.openFile(c.store.getAt(f).data.id)},openFile:function(g){var e=this.store.getById(g),d=e.data.path,c=e.data.name,f=Ext.util.md5("FNIEN-"+PhDOE.user.lang+d+c);if(!Ext.getCmp("main-panel").findById("FNIEN-"+f)){Ext.getCmp("main-panel").add({id:"FNIEN-"+f,layout:"border",title:c,originTitle:c,iconCls:"iconTabView",closable:true,tabLoaded:false,panLANGLoaded:false,defaults:{split:true},tabTip:String.format(_("Not In EN: in {0}"),d),items:[new ui.cmp.FilePanel({id:"FNIEN-NotInEN-PANEL-"+f,region:"center",title:_("File: ")+d+c,prefix:"FNIEN",ftype:"NotInEN",fid:f,fpath:d,fname:c,original:true,readOnly:true,lang:PhDOE.user.lang,parser:"xml",storeRecord:e,syncScroll:false})]})}Ext.getCmp("main-panel").setActiveTab("FNIEN-"+f)},initComponent:function(){Ext.apply(this,{store:ui.cmp._NotInENGrid.store});ui.cmp.NotInENGrid.superclass.initComponent.call(this);this.on("rowcontextmenu",this.onRowContextMenu,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp._NotInENGrid.instance=null;ui.cmp.NotInENGrid.getInstance=function(c){if(!ui.cmp._NotInENGrid.instance){if(!c){c={}}ui.cmp._NotInENGrid.instance=new ui.cmp.NotInENGrid(c)}return ui.cmp._NotInENGrid.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PatchesTreeGrid","ui.cmp._PatchesTreeGrid.menu");ui.cmp._PatchesTreeGrid.menu.users=function(c){Ext.apply(this,c);this.init();ui.cmp._PatchesTreeGrid.menu.users.superclass.constructor.call(this)};Ext.extend(ui.cmp._PatchesTreeGrid.menu.users,Ext.menu.Menu,{init:function(){var c=[];this.node.cascade(function(d){if(d.attributes.type!=="folder"&&d.attributes.type!=="patch"&&d.attributes.type!=="user"){c.push(d)}},this);Ext.apply(this,{items:[{scope:this,text:String.format(_("Send an email to {0}"),""+this.node.attributes.task+""),iconCls:"iconSendEmail",hidden:(this.node.attributes.task===PhDOE.user.login||this.node.attributes.email==="false"),handler:function(){var d=new ui.cmp.EmailPrompt();d.setData(this.node.attributes.task,this.node.attributes.email);d.show(this.node.el)}},{text:_("Back all files to work in progress module"),hidden:(this.node.attributes.task!==PhDOE.user.login),disabled:Ext.isEmpty(c),iconCls:"iconWorkInProgress",handler:function(){ui.task.MoveToWork({nodesToAdd:c})}},{xtype:"menuseparator",hidden:(this.node.attributes.task!==PhDOE.user.login||PhDOE.user.isAnonymous)},((this.node.attributes.task===PhDOE.user.login&&!PhDOE.user.isAnonymous)?new ui.cmp._WorkTreeGrid.menu.commit({module:"patches",from:"user",node:false,folderNode:false,patchNode:false,userNode:this.node}):"")]})}});ui.cmp._PatchesTreeGrid.menu.patches=function(c){Ext.apply(this,c);this.init();ui.cmp._PatchesTreeGrid.menu.patches.superclass.constructor.call(this)};Ext.extend(ui.cmp._PatchesTreeGrid.menu.patches,Ext.menu.Menu,{init:function(){var d=this.node,f=[],c=d.parentNode.attributes.task,e=d.parentNode.attributes.isAnonymous;this.node.cascade(function(g){if(g.attributes.type!=="folder"&&g.attributes.type!=="patch"&&g.attributes.type!=="user"){f.push(g)}},this);Ext.apply(this,{items:[{text:_("Edit the description of this patch"),iconCls:"iconPendingPatch",hidden:(c!==PhDOE.user.login),handler:function(){var g=new ui.cmp.ManagePatchPrompt({title:_("Modify this patch description"),patchName:d.attributes.task,patchDescription:d.attributes.patchDescription,patchEmail:d.attributes.patchEmail,patchID:d.attributes.idDB});g.show(this.el)}},{text:_("Delete this patch"),iconCls:"iconTrash",hidden:(c!==PhDOE.user.login),handler:function(){ui.task.DeletePatchTask({patchID:d.attributes.idDB})}},{xtype:"menuseparator",hidden:!((!PhDOE.user.isAnonymous&&c===PhDOE.user.login)||!PhDOE.user.isGlobalAdmin)},{text:_("Back all this patch to work in progress module"),iconCls:"iconWorkInProgress",hidden:(c!==PhDOE.user.login),disabled:Ext.isEmpty(f),handler:function(){ui.task.MoveToWork({nodesToAdd:f})}},{xtype:"menuseparator",hidden:(c!==PhDOE.user.login),},{text:_("View unified diff"),iconCls:"iconViewDiff",handler:function(){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",patchID:d.attributes.idDB,patchName:d.attributes.task})}},{text:_("Download the unified diff as a patch"),iconCls:"iconDownloadDiff",handler:function(){window.location.href="./do/downloadPatch?patchID="+d.attributes.idDB+"&csrfToken="+csrfToken}},{xtype:"menuseparator"},((e&&!PhDOE.user.isAnonymous)?new ui.cmp._WorkTreeGrid.menu.commit({module:"patches",from:"anonymousPatch",node:false,folderNode:false,patchNode:this.node,userNode:this.node.parentNode}):""),((!PhDOE.user.isAnonymous&&c===PhDOE.user.login)?new ui.cmp._WorkTreeGrid.menu.commit({module:"patches",from:"patch",node:false,folderNode:false,patchNode:this.node,userNode:this.node.parentNode}):""),((PhDOE.user.isGlobalAdmin&&c!==PhDOE.user.login)?new ui.cmp._WorkTreeGrid.menu.admin({from:"patch",node:this.node}):"")]})}});ui.cmp._PatchesTreeGrid.menu.folders=function(c){Ext.apply(this,c);this.init();ui.cmp._PatchesTreeGrid.menu.folders.superclass.constructor.call(this)};Ext.extend(ui.cmp._PatchesTreeGrid.menu.folders,Ext.menu.Menu,{init:function(){var c=[];if(this.node.parentNode.parentNode.attributes.task!==PhDOE.user.login){return false}this.node.cascade(function(d){if(d.attributes.type!=="folder"&&d.attributes.type!=="patch"&&d.attributes.type!=="user"){c.push(d)}},this);Ext.apply(this,{items:[{text:_("Back all this folder to work in progress module"),iconCls:"iconWorkInProgress",handler:function(){ui.task.MoveToWork({nodesToAdd:c})}},{xtype:"menuseparator",hidden:(PhDOE.user.isAnonymous)},((!PhDOE.user.isAnonymous)?new ui.cmp._WorkTreeGrid.menu.commit({module:"patches",from:"folder",node:false,folderNode:this.node,patchNode:this.node.parentNode,userNode:this.node.parentNode.parentNode}):"")]})}});ui.cmp._PatchesTreeGrid.menu.files=function(c){Ext.apply(this,c);this.init();ui.cmp._PatchesTreeGrid.menu.files.superclass.constructor.call(this)};Ext.extend(ui.cmp._PatchesTreeGrid.menu.files,Ext.menu.Menu,{init:function(){var h=this.node,m=h.attributes.type,g,c=h.parentNode.attributes.task,f=h.attributes.task,k=h.ownerTree,l=h.attributes.idDB,d=[],e=this.node.parentNode.parentNode.parentNode.attributes.task,j;j=h.parentNode.attributes.task.split("/");g=j[0];this.node.cascade(function(o){if(o.attributes.type!=="folder"&&o.attributes.type!=="patch"&&o.attributes.type!=="user"){d.push(o)}},this);Ext.apply(this,{items:[{text:""+((m==="delete")?_("View in a new tab"):_("Edit in a new tab"))+"",iconCls:"iconEdit",handler:function(){ui.cmp.WorkTreeGrid.getInstance().openFile(h)}},{text:_("Back this file to work in progress module"),hidden:(e!==PhDOE.user.login),iconCls:"iconWorkInProgress",handler:function(){ui.task.MoveToWork({nodesToAdd:d})}},"-",{text:_("View diff"),iconCls:"iconViewDiff",hidden:(m==="delete"||m==="new"),handler:function(){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",FileName:f,FilePath:c,currentOwner:e,fileIdDB:h.attributes.idDB})}},{text:_("Download the diff as a patch"),iconCls:"iconDownloadDiff",hidden:(m==="delete"||m==="new"),handler:function(){window.location.href="./do/downloadPatch?FilePath="+c+"&FileName="+f+"&csrfToken="+csrfToken}},{xtype:"menuseparator",hidden:(m==="delete"||m==="new"||e!==PhDOE.user.login)},{text:((m==="delete")?_("Cancel this deletion"):_("Clear this change")),hidden:(e!==PhDOE.user.login),iconCls:"iconPageDelete",handler:function(){new ui.task.ClearLocalChangeTask({ftype:m,fpath:c,fname:f})}},{xtype:"menuseparator",hidden:(PhDOE.user.isAnonymous||e!==PhDOE.user.login)},((e===PhDOE.user.login&&!PhDOE.user.isAnonymous)?new ui.cmp._WorkTreeGrid.menu.commit({module:"patches",from:"file",node:this.node,folderNode:this.node.parentNode,patchNode:this.node.parentNode.parentNode,userNode:this.node.parentNode.parentNode.parentNode}):""),{xtype:"menuseparator",hidden:(!PhDOE.user.isGlobalAdmin&&!(PhDOE.user.lang===g&&PhDOE.user.isLangAdmin))},((PhDOE.user.isGlobalAdmin||(PhDOE.user.lang===g&&PhDOE.user.isLangAdmin))?new ui.cmp._WorkTreeGrid.menu.admin({fileLang:g,from:"file",node:this.node,folderNode:this.node.parentNode,userNode:this.node.parentNode.parentNode.parentNode}):"")]})}});ui.cmp.PatchesTreeGrid=Ext.extend(Ext.ux.tree.TreeGrid,{onContextMenu:function(f,g){g.stopEvent();var d=f.attributes.type,c;switch(d){case"user":f.select();c=new ui.cmp._PatchesTreeGrid.menu.users({node:f});break;case"folder":f.select();c=new ui.cmp._PatchesTreeGrid.menu.folders({node:f});break;case"patch":f.select();c=new ui.cmp._PatchesTreeGrid.menu.patches({node:f});break;default:f.select();c=new ui.cmp._PatchesTreeGrid.menu.files({node:f});break}c.showAt(g.getXY())},modPatchName:function(c){var d=this.getRootNode(),e=d.findChild("idDB",c.patchID,true);e.setText(c.newPatchName);e.attributes.patchDescription=c.newPatchDescription;e.attributes.patchEmail=c.newPatchEmail;e.attributes.task=c.newPatchName},initComponent:function(){Ext.apply(this,{animate:true,useArrows:true,autoScroll:true,border:false,containerScroll:true,selModel:new Ext.tree.MultiSelectionModel(),columns:[{header:_("Users"),dataIndex:"task",uiProvider:{editable:true,qtip:"help"},tpl:new Ext.XTemplate("{task:this.formatUserName}",{formatUserName:function(c,d){if(d.type==="user"){if(d.userID){d.qtip=_("userID: ")+d.userID}return c}if(d.type==="patch"){if(d.creationDate){d.qtip=_("Creation date: ")+Date.parseDate(d.creationDate,"Y-m-d H:i:s").format(_("Y-m-d, H:i"))}return c}return c}})},{header:_("Last modified"),width:120,dataIndex:"last_modified",align:"center",tpl:new Ext.XTemplate("{last_modified:this.formatDate}",{formatDate:function(c,d){if(d.type!=="user"&&d.type!=="folder"&&d.type!=="patch"){return Date.parseDate(c,"Y-m-d H:i:s").format(_("Y-m-d, H:i"))}else{return""}}})}],loader:{dataUrl:"./do/getWork",baseParams:{module:"PatchesForReview"}}});ui.cmp.PatchesTreeGrid.superclass.initComponent.call(this);this.on("contextmenu",this.onContextMenu,this);this.on("resize",this.resizeCmp,this);this.on("dblclick",ui.cmp.WorkTreeGrid.getInstance().openFile,this);this.getRootNode().on("beforechildrenrendered",function(){this.updateFilesCounter.defer(200,this)},this)},resizeCmp:function(g,f,d,e){this.columns[0].width=e-(this.columns[1].width+5);this.updateColumnWidths()},deletePatch:function(q){var e=this.getRootNode(),o,c,d,f,r=[],p,m,h,g;for(p=0;p"}else{h=String.format(_("File EN modified by {0}"),g.user)+"
"}}if(e.data.fileModifiedLang){f=Ext.util.JSON.decode(e.data.fileModifiedLang);if(f.user===PhDOE.user.login&&f.anonymousIdent===PhDOE.user.anonymousIdent){h+=String.format(_("File {0} modified by me"),PhDOE.user.lang.ucFirst())}else{h+=String.format(_("File {0} modified by {1}"),PhDOE.user.lang.ucFirst(),f.user)}}if(h!==""){return""+d+""}else{return d}}},{header:_("Reviewed"),width:45,sortable:true,dataIndex:"reviewed"},{header:_("Reviewer"),width:45,sortable:true,dataIndex:"maintainer"},{header:_("Path"),dataIndex:"path",hidden:true}];ui.cmp._PendingReviewGrid.view=new Ext.grid.GroupingView({forceFit:true,startCollapsed:true,groupTextTpl:'{[values.rs[0].data["path"]]} ({[values.rs.length]} {[values.rs.length > 1 ? "'+_("Files")+'" : "'+_("File")+'"]})',getRowClass:function(c){if(c.data.fileModifiedEN||c.data.fileModifiedLang){var e=Ext.util.JSON.decode(c.data.fileModifiedEN),d=Ext.util.JSON.decode(c.data.fileModifiedLang);return((e.user===PhDOE.user.login&&e.anonymousIdent===PhDOE.user.anonymousIdent)||(d.user===PhDOE.user.login&&d.anonymousIdent===PhDOE.user.anonymousIdent))?"fileModifiedByMe":"fileModifiedByAnother"}return false},deferEmptyText:false,emptyText:'
'+_("No Files")+"
"});Ext.namespace("ui.cmp._PendingReviewGrid.menu");ui.cmp._PendingReviewGrid.menu.group=function(c){Ext.apply(this,c);this.init();ui.cmp._PendingReviewGrid.menu.group.superclass.constructor.call(this)};Ext.extend(ui.cmp._PendingReviewGrid.menu.group,Ext.menu.Item,{iconCls:"iconViewDiff",init:function(){Ext.apply(this,{text:String.format(_("Open all files about {0} extension"),this.gname.ucFirst()),handler:function(){Ext.getBody().mask(' '+String.format(_("Open all files about {0} extension"),this.gname.ucFirst())+". "+_("Please, wait..."));XHR({params:{task:"getAllFilesAboutExtension",ExtName:this.gname},success:function(d){var e=Ext.util.JSON.decode(d.responseText),c;PhDOE.AFfilePendingOpen=[];for(c=0;c"+_("Edit in a new tab")+"",iconCls:"iconFilesNeedReviewed",scope:this,handler:function(){this.grid.fireEvent("rowdblclick",this.grid,this.rowIdx,this.event)}},{scope:this,hidden:this.hideDiffMenu,text:_("View diff..."),iconCls:"iconViewDiff",menu:new Ext.menu.Menu({items:[{scope:this,hidden:(this.grid.store.getAt(this.rowIdx).data.fileModifiedEN===false),text:String.format(_("... of the {0} file"),"EN"),handler:function(){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",FileName:this.fname,FilePath:"en"+this.fpath})}},{scope:this,hidden:(this.grid.store.getAt(this.rowIdx).data.fileModifiedLang===false),text:String.format(_("... of the {0} file"),PhDOE.user.lang.ucFirst()),handler:function(){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",FileName:this.fname,FilePath:PhDOE.user.lang+this.fpath})}}]})},new Ext.menu.Separator({hidden:this.hideGroup}),new ui.cmp._PendingReviewGrid.menu.group({gname:this.gname,hidden:this.hideGroup})]})}});ui.cmp.PendingReviewGrid=Ext.extend(Ext.grid.GridPanel,{loadMask:true,border:false,autoExpandColumn:"name",enableDragDrop:true,ddGroup:"mainPanelDDGroup",columns:ui.cmp._PendingReviewGrid.columns,view:ui.cmp._PendingReviewGrid.view,onRowContextMenu:function(d,k,h){h.stopEvent();var g=d.store.getAt(k),f=g.data.path,c=g.data.name,j=f.split("/");d.getSelectionModel().selectRow(k);new ui.cmp._PendingReviewGrid.menu.main({grid:d,rowIdx:k,event:h,fpath:f,fname:c,hideDiffMenu:(g.data.fileModifiedEN===false&&g.data.fileModifiedLang===false),hideGroup:(j[1]!=="reference"),gname:(j[2])?j[2]:""}).showAt(h.getXY())},onRowDblClick:function(c,f,d){this.openFile(c.store.getAt(f).data.id)},openFile:function(g){var e=this.store.getById(g),d=e.data.path,c=e.data.name,f=Ext.util.md5("FNR-"+PhDOE.user.lang+d+c);if(!Ext.getCmp("main-panel").findById("FNR-"+f)){Ext.getCmp("main-panel").add({id:"FNR-"+f,title:c,layout:"border",iconCls:"iconTabNeedReviewed",closable:true,tabLoaded:false,panVCSLang:!PhDOE.user.conf.reviewed.toolsPanelLogLoad,panVCSEn:!PhDOE.user.conf.reviewed.toolsPanelLogLoad,panLANGLoaded:false,panENLoaded:false,originTitle:c,defaults:{split:true},tabTip:String.format(_("Need Reviewed in: {0}"),d),listeners:{resize:function(h){Ext.getCmp("FNR-EN-PANEL-"+f).setWidth(h.getWidth()/2)}},items:[{region:"west",xtype:"panel",title:_("Tools"),iconCls:"iconConf",collapsedIconCls:"iconConf",plugins:[Ext.ux.PanelCollapsedTitle],collapsible:true,collapsed:!PhDOE.user.conf.reviewed.toolsPanelDisplay,layout:"fit",bodyBorder:false,width:PhDOE.user.conf.reviewed.toolsPanelWidth||375,listeners:{collapse:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"reviewed",itemName:"toolsPanelDisplay",value:false,notify:false})}},expand:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"reviewed",itemName:"toolsPanelDisplay",value:true,notify:false})}},resize:function(h,j){if(this.ownerCt.tabLoaded&&j&&j!=PhDOE.user.conf.reviewed.toolsPanelWidth){new ui.task.UpdateConfTask({module:"reviewed",itemName:"toolsPanelWidth",value:j,notify:false})}}},items:{xtype:"tabpanel",activeTab:0,tabPosition:"bottom",enableTabScroll:true,defaults:{autoScroll:true},items:[new ui.cmp.VCSLogGrid({layout:"fit",title:String.format(_("{0} Log"),PhDOE.user.lang.ucFirst()),prefix:"FNR-LANG",fid:f,fpath:PhDOE.user.lang+d,fname:c,loadStore:PhDOE.user.conf.reviewed.toolsPanelLogLoad}),new ui.cmp.VCSLogGrid({layout:"fit",title:String.format(_("{0} Log"),"En"),prefix:"FNR-EN",fid:f,fpath:"en"+d,fname:c,loadStore:PhDOE.user.conf.reviewed.toolsPanelLogLoad}),new ui.cmp.DictionaryGrid({layout:"fit",title:_("Dictionary"),prefix:"FNR",fid:f})]}},new ui.cmp.FilePanel({id:"FNR-LANG-PANEL-"+f,region:"center",title:String.format(_("{0} File: "),PhDOE.user.lang.ucFirst())+d+c,prefix:"FNR",ftype:"LANG",spellCheck:PhDOE.user.conf.reviewed.enableSpellCheckLang,spellCheckConf:{module:"reviewed",itemName:"enableSpellCheckLang"},fid:f,fpath:d,fname:c,lang:PhDOE.user.lang,parser:"xml",storeRecord:e,syncScrollCB:true,syncScroll:true,syncScrollConf:{module:"reviewed",itemName:"syncScrollbars"}}),new ui.cmp.FilePanel({id:"FNR-EN-PANEL-"+f,region:"east",title:_("en File: ")+d+c,prefix:"FNR",ftype:"EN",original:true,readOnly:true,openInNewTabBtn:true,fid:f,fpath:d,fname:c,lang:"en",parser:"xml",storeRecord:e,syncScroll:true,syncScrollConf:{module:"reviewed",itemName:"syncScrollbars"}})]})}Ext.getCmp("main-panel").setActiveTab("FNR-"+f)},initComponent:function(){Ext.apply(this,{store:ui.cmp._PendingReviewGrid.store,tbar:[_("Filter: ")," ",new Ext.form.TwinTriggerField({id:"FNR-filter",width:180,hideTrigger1:true,enableKeyEvents:true,validateOnBlur:false,validationEvent:false,trigger1Class:"x-form-clear-trigger",trigger2Class:"x-form-search-trigger",listeners:{keypress:function(d,c){if(c.getKey()===c.ENTER){this.onTrigger2Click()}}},onTrigger1Click:function(){this.setValue("");this.triggers[0].hide();this.setSize(180,10);ui.cmp._PendingReviewGrid.instance.store.clearFilter()},onTrigger2Click:function(){var c=this.getValue(),d;if(c===""||c.length<3){this.markInvalid(_("Your filter must contain at least 3 characters"));return}this.clearInvalid();this.triggers[0].show();this.setSize(180,10);d=new RegExp(c,"i");ui.cmp._PendingReviewGrid.instance.store.filterBy(function(e){if(d.test(e.data.path)||d.test(e.data.name)||d.test(e.data.reviewed)||d.test(e.data.maintainer)){return true}else{return false}},this)}})]});ui.cmp.PendingReviewGrid.superclass.initComponent.call(this);this.on("rowcontextmenu",this.onRowContextMenu,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp._PendingReviewGrid.instance=null;ui.cmp.PendingReviewGrid.getInstance=function(c){if(!ui.cmp._PendingReviewGrid.instance){if(!c){c={}}ui.cmp._PendingReviewGrid.instance=new ui.cmp.PendingReviewGrid(c)}return ui.cmp._PendingReviewGrid.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PendingTranslateGrid");ui.cmp._PendingTranslateGrid.store=new Ext.data.GroupingStore({proxy:new Ext.data.HttpProxy({url:"./do/getFilesNeedTranslate"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"path"},{name:"name"},{name:"fileModified"}]}),sortInfo:{field:"name",direction:"ASC"},groupField:"path",listeners:{datachanged:function(c){Ext.getDom("acc-need-translate-nb").innerHTML=c.getCount()}}});ui.cmp._PendingTranslateGrid.view=new Ext.grid.GroupingView({forceFit:true,startCollapsed:true,groupTextTpl:'{[values.rs[0].data["path"]]} ({[values.rs.length]} {[values.rs.length > 1 ? "'+_("Files")+'" : "'+_("File")+'"]})',deferEmptyText:false,getRowClass:function(c){if(c.data.fileModified){var d=Ext.util.JSON.decode(c.data.fileModified);return(d.user===PhDOE.user.login&&d.anonymousIdent===PhDOE.user.anonymousIdent)?"fileModifiedByMe":"fileModifiedByAnother"}return false},emptyText:'
'+_("No Files")+"
"});ui.cmp._PendingTranslateGrid.columns=[{id:"name",header:_("Files"),sortable:true,dataIndex:"name",renderer:function(c,f,d){if(d.data.fileModified){var e=Ext.util.JSON.decode(d.data.fileModified);if(e.user===PhDOE.user.login&&e.anonymousIdent===PhDOE.user.anonymousIdent){return""+c+""}else{return""+c+""}}else{return c}}},{header:_("Path"),dataIndex:"path",hidden:true}];ui.cmp._PendingTranslateGrid.menu=function(c){Ext.apply(this,c);this.init();ui.cmp._StaleFileGrid.menu.superclass.constructor.call(this)};Ext.extend(ui.cmp._PendingTranslateGrid.menu,Ext.menu.Menu,{init:function(){Ext.apply(this,{items:[{scope:this,text:""+_("Edit in a new tab")+"",iconCls:"iconTabNeedTranslate",handler:function(){this.grid.fireEvent("rowdblclick",this.grid,this.rowIdx,this.event)}}]})}});ui.cmp.PendingTranslateGrid=Ext.extend(Ext.grid.GridPanel,{view:ui.cmp._PendingTranslateGrid.view,loadMask:true,autoExpandColumn:"name",enableDragDrop:true,ddGroup:"mainPanelDDGroup",border:false,onRowContextMenu:function(c,f,d){d.stopEvent();c.getSelectionModel().selectRow(f);new ui.cmp._PendingTranslateGrid.menu({grid:c,event:d,rowIdx:f}).showAt(d.getXY())},onRowDblClick:function(c,d){this.openFile(c.store.getAt(d).data.id)},openFile:function(g){var e=this.store.getById(g),d=e.data.path,c=e.data.name,f=Ext.util.md5("FNT-"+PhDOE.user.lang+d+c),h;if(!Ext.getCmp("main-panel").findById("FNT-"+f)){if(PhDOE.user.conf.newFile.secondPanel=="google"||PhDOE.user.conf.newFile.secondPanel=="originalFile"){h=true}else{h=false}Ext.getCmp("main-panel").add({id:"FNT-"+f,layout:"border",title:c,originTitle:c,iconCls:"iconTabNeedTranslate",closable:true,tabLoaded:false,panTRANSLoaded:false,panTRANSSecondLoaded:!h,defaults:{split:true},tabTip:String.format(_("Need translate: in {0}"),d),listeners:{resize:function(j){if(PhDOE.user.conf.newFile.secondPanel=="google"){Ext.getCmp("FNT-GGTRANS-PANEL-"+f).setWidth(j.getWidth()/2)}if(PhDOE.user.conf.newFile.secondPanel=="originalFile"){Ext.getCmp("FNT-EN-PANEL-"+f).setWidth(j.getWidth()/2)}}},items:[{region:"west",xtype:"panel",title:_("Tools"),iconCls:"iconConf",collapsedIconCls:"iconConf",plugins:[Ext.ux.PanelCollapsedTitle],collapsible:true,collapsed:!PhDOE.user.conf.newFile.toolsPanelDisplay,layout:"fit",bodyBorder:false,width:PhDOE.user.conf.newFile.toolsPanelWidth||375,listeners:{collapse:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"newFile",itemName:"toolsPanelDisplay",value:false,notify:false})}},expand:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"newFile",itemName:"toolsPanelDisplay",value:true,notify:false})}},resize:function(j,k){if(this.ownerCt.tabLoaded&&k&&k!=PhDOE.user.conf.newFile.toolsPanelWidth){new ui.task.UpdateConfTask({module:"newFile",itemName:"toolsPanelWidth",value:k,notify:false})}}},items:{xtype:"tabpanel",activeTab:0,tabPosition:"bottom",defaults:{autoScroll:true},items:[new ui.cmp.DictionaryGrid({layout:"fit",title:_("Dictionary"),prefix:"FNT",fid:f})]}},new ui.cmp.FilePanel({id:"FNT-TRANS-PANEL-"+f,region:"center",title:_("New file: ")+PhDOE.user.lang+d+c,isTrans:true,prefix:"FNT",ftype:"TRANS",spellCheck:PhDOE.user.conf.newFile.enableSpellCheck,spellCheckConf:{module:"newFile",itemName:"enableSpellCheck"},fid:f,fpath:d,fname:c,lang:PhDOE.user.lang,parser:"xml",storeRecord:e,syncScrollCB:h,syncScroll:h,syncScrollConf:{module:"newFile",itemName:"syncScrollbars"}}),((PhDOE.user.conf.newFile.secondPanel=="google")?new ui.cmp.FilePanel({id:"FNT-GGTRANS-PANEL-"+f,region:"east",title:_("Automatic translation: ")+PhDOE.user.lang+d+c,isTrans:true,prefix:"FNT",ftype:"GGTRANS",fid:f,fpath:d,fname:c,readOnly:true,lang:PhDOE.user.lang,parser:"xml",storeRecord:e,syncScroll:true,syncScrollConf:{module:"newFile",itemName:"syncScrollbars"}}):false),((PhDOE.user.conf.newFile.secondPanel=="originalFile")?new ui.cmp.FilePanel({id:"FNT-EN-PANEL-"+f,region:"east",title:_("File: ")+"en"+d+c,prefix:"FNT",ftype:"EN",fid:f,fpath:d,fname:c,original:true,readOnly:true,lang:"en",parser:"xml",storeRecord:e,syncScroll:true,syncScrollConf:{module:"newFile",itemName:"syncScrollbars"}}):false)]})}Ext.getCmp("main-panel").setActiveTab("FNT-"+f)},initComponent:function(){Ext.apply(this,{columns:ui.cmp._PendingTranslateGrid.columns,store:ui.cmp._PendingTranslateGrid.store,tbar:[_("Filter: ")," ",new Ext.form.TwinTriggerField({id:"FNT-filter",width:180,hideTrigger1:true,enableKeyEvents:true,validateOnBlur:false,validationEvent:false,trigger1Class:"x-form-clear-trigger",trigger2Class:"x-form-search-trigger",listeners:{keypress:function(d,c){if(c.getKey()===c.ENTER){this.onTrigger2Click()}}},onTrigger1Click:function(){this.setValue("");this.triggers[0].hide();this.setSize(180,10);ui.cmp._PendingTranslateGrid.instance.store.clearFilter()},onTrigger2Click:function(){var c=this.getValue(),d;if(c===""||c.length<3){this.markInvalid(_("Your filter must contain at least 3 characters"));return}this.clearInvalid();this.triggers[0].show();this.setSize(180,10);d=new RegExp(c,"i");ui.cmp._PendingTranslateGrid.instance.store.filterBy(function(e){if(d.test(e.data.path)||d.test(e.data.name)){return true}else{return false}},this)}})]});ui.cmp.PendingTranslateGrid.superclass.initComponent.call(this);this.on("rowcontextmenu",this.onRowContextMenu,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp._PendingTranslateGrid.instance=null;ui.cmp.PendingTranslateGrid.getInstance=function(c){if(!ui.cmp._PendingTranslateGrid.instance){if(!c){c={}}ui.cmp._PendingTranslateGrid.instance=new ui.cmp.PendingTranslateGrid(c)}return ui.cmp._PendingTranslateGrid.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PortletBugs");ui.cmp._PortletBugs.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getOpenBugs"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"title"},{name:"link"},{name:"description"},{name:"xmlID"}]})});ui.cmp._PortletBugs.gridFormatTitle=function(c){return String.format('
{0}
',c)};ui.cmp._PortletBugs.gridColumns=[{id:"GridBugTitle",header:_("Title"),sortable:true,dataIndex:"title",renderer:ui.cmp._PortletBugs.gridFormatTitle}];ui.cmp._PortletBugs.gridView=new Ext.grid.GridView({forceFit:true,emptyText:'
'+_("You must manually load this data.
Use the refresh button !")+"
",deferEmptyText:false,enableRowBody:true,showPreview:false,getRowClass:function(c,e,d){if(this.showPreview){d.body="

"+c.data.description+"

";return"x-grid3-row-expanded"}return"x-grid3-row-collapsed"}});ui.cmp._PortletBugs.grid=Ext.extend(Ext.grid.GridPanel,{loadMask:true,autoScroll:true,height:250,autoExpandColumn:"GridBugTitle",id:"PortletBugs-grid-id",store:ui.cmp._PortletBugs.store,columns:ui.cmp._PortletBugs.gridColumns,view:ui.cmp._PortletBugs.gridView,sm:new Ext.grid.RowSelectionModel({singleSelect:true}),onRowDblClick:function(e,g){var c=e.store.getAt(g).data.id,d=e.store.getAt(g).data.link,f=e.store.getAt(g).data.title;if(!Ext.getCmp("main-panel").findById("bugs-"+c)){Ext.getCmp("main-panel").add({id:"bugs-"+c,xtype:"panel",title:Ext.util.Format.substr(f,0,20)+"...",tabTip:f,iconCls:"iconBugs",closable:true,layout:"fit",items:[new Ext.ux.IFrameComponent({id:"frame-bugs-"+c,url:d})]})}Ext.getCmp("main-panel").setActiveTab("bugs-"+c)},openRelatedFile:function(c){new ui.task.GetFileInfoByXmlID({xmlID:c})},onContextClick:function(c,f,d){if(!this.menu){this.menu=new Ext.menu.Menu({id:"submenu-bugs",items:[{scope:this,text:""+_("Open in a new Tab")+"",iconCls:"iconOpenInTab",handler:function(){this.fireEvent("rowdblclick",c,this.ctxIndex,d);this.menu.hide()}},"-",{scope:this,text:_("Refresh this grid"),iconCls:"iconRefresh",handler:function(){this.ctxIndex=null;ui.cmp._PortletBugs.reloadData()}},{scope:this,text:_("Open the related file"),iconCls:"iconAllFiles",id:"bugs-open-related-file",handler:function(){this.openRelatedFile(this.ctxXmlID)}}]})}this.getSelectionModel().selectRow(f);d.stopEvent();if(this.ctxIndex){this.ctxIndex=null}if(this.ctxXmlID){this.ctxXmlID=null}this.ctxIndex=f;this.ctxXmlID=c.store.getAt(this.ctxIndex).data.xmlID;this.menu.showAt(d.getXY());if(!this.ctxXmlID){Ext.getCmp("bugs-open-related-file").disable()}else{Ext.getCmp("bugs-open-related-file").enable()}},togglePreview:function(c){this.view.showPreview=c;this.view.refresh()},initComponent:function(c){this.tbar=[{text:_("Summary"),pressed:false,enableToggle:true,iconCls:"iconSummary",scope:this,toggleHandler:function(d,e){this.togglePreview(e)}}];ui.cmp._PortletBugs.grid.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowcontextmenu",this.onContextClick,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp._PortletBugs.reloadData=function(){ui.cmp._PortletBugs.store.reload({callback:function(c,e,d){if(!d){Ext.getCmp("PortletBugs-grid-id").getView().mainBody.update('
'+_("Error when loading open bugs from Php.net !")+"
");Ext.get("PortletBugs-grid-defaultMess-id").highlight()}else{if(ui.cmp._PortletBugs.store.getTotalCount()===0){Ext.getCmp("PortletBugs-grid-id").getView().mainBody.update('
'+_("No open bugs")+"
");Ext.get("PortletBugs-grid-defaultMess-id").highlight()}}}})};ui.cmp.PortletBugs=Ext.extend(Ext.ux.Portlet,{title:"",iconCls:"iconBugs",layout:"fit",store:ui.cmp._PortletBugs.store,reloadData:ui.cmp._PortletBugs.reloadData,tools:[{id:"refresh",qtip:_("Refresh this grid"),handler:function(){ui.cmp._PortletBugs.reloadData()}}],listeners:{expand:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletBugsCollapsed",value:false,notify:false})}},collapse:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletBugsCollapsed",value:true,notify:false})}},afterrender:function(c){if(PhDOE.user.conf.portletBugsCollapsed){c.collapse()}else{c.expand()}}},initComponent:function(c){this.id="portletBugs";this.title=String.format(_("Open bugs for {0}"),"doc-"+this.lang);Ext.apply(this,c);ui.cmp.PortletBugs.superclass.initComponent.apply(this);this.add(new ui.cmp._PortletBugs.grid())}});ui.cmp._PortletBugs.instance=null;ui.cmp.PortletBugs.getInstance=function(c){if(!ui.cmp._PortletBugs.instance){if(!c){c={}}ui.cmp._PortletBugs.instance=new ui.cmp.PortletBugs(c)}return ui.cmp._PortletBugs.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PortletInfo");ui.cmp._PortletInfo.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getInfos"}),baseParams:{start:0,limit:10},reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"field"},{name:"value"},{name:"date",type:"date",dateFormat:"Y-m-d H:i:s"},{name:"elapsedTime"}]}),listeners:{load:function(c){var e=c.data.items[0].data.date;PhDOE.lastInfoDate=e.format("Y-m-d H:i:s")}}});ui.cmp._PortletInfo.store.setDefaultSort("date","desc");ui.cmp._PortletInfo.typeRenderer=function(l,j,g){var d,c,m,o,e,k,h,f;switch(l){case"updateData":d=g.data.value.user;return String.format(_("{0} updated app's data"),d);break;case"changeFilesOwner":d=g.data.value.user;return String.format(_("{0} changed file's owner"),d);break;case"checkEntities":d=g.data.value.user;return String.format(_("{0} check all entitites"),d);break;case"logout":d=g.data.value.user;return String.format(_("{0} logged out"),d);break;case"login":d=g.data.value.user;c=g.data.value.lang;authService=g.data.value.authService;f="";if(authService=="google"){f=' '}else{if(authService=="facebook"){f=' '}}return f+String.format(_("{0} is logged in using the {1} language"),d,c.ucFirst());break;case"commitFolders":d=g.data.value.user;c=g.data.value.lang;m=g.data.value.nbFolders;return String.format(_("{0} committed {1} new folder(s) in the {2} language"),d,m,c.ucFirst());break;case"commitFiles":d=g.data.value.user;c=g.data.value.lang;o=g.data.value.nbFilesCreate;e=g.data.value.nbFilesDelete;k=g.data.value.nbFilesUpdate;h=o+e+k;return String.format(_("{0} committed {1} file(s) ({2} new, {3} update, {4} delete) in the language {5}"),d,h,o,k,e,c.ucFirst());break}};ui.cmp._PortletInfo.gridColumns=[new Ext.grid.RowNumberer(),{id:"Type",header:_("Type"),width:180,sortable:true,dataIndex:"field",renderer:ui.cmp._PortletInfo.typeRenderer},{header:_("Since"),width:110,sortable:false,dataIndex:"elapsedTime",renderer:function(d,c,e){if(!d){d=_("Less than one second")}else{d=String.format(_("{0} "+d.units),d.value)}return""+d+""}},{header:_("Date"),width:110,sortable:true,dataIndex:"date",hidden:true,renderer:Ext.util.Format.dateRenderer(_("Y-m-d, H:i"))}];ui.cmp._PortletInfo.grid=Ext.extend(Ext.grid.GridPanel,{autoExpandColumn:"Type",loadMask:true,autoScroll:true,autoHeight:true,store:ui.cmp._PortletInfo.store,columns:ui.cmp._PortletInfo.gridColumns,view:ui.cmp._PortletInfo.gridView,initComponent:function(){Ext.apply(this,{bbar:new Ext.PagingToolbar({pageSize:10,store:this.store,displayInfo:true})});ui.cmp._PortletInfo.grid.superclass.initComponent.call(this);this.on("rowdblclick",this.onRowdblclick,this)}});ui.cmp.PortletInfo=Ext.extend(Ext.ux.Portlet,{title:_("Information"),iconCls:"iconInfo",layout:"fit",store:ui.cmp._PortletInfo.store,tools:[{id:"refresh",qtip:_("Refresh this grid"),handler:function(){ui.cmp._PortletInfo.store.reload()}}],listeners:{expand:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletInfoCollapsed",value:false,notify:false})}},collapse:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletInfoCollapsed",value:true,notify:false})}},afterrender:function(c){if(PhDOE.user.conf.portletInfoCollapsed){c.collapse()}else{c.expand()}}},initComponent:function(c){this.id="portletInfo";Ext.apply(this,c);ui.cmp.PortletInfo.superclass.initComponent.apply(this);this.add(new ui.cmp._PortletInfo.grid())}});ui.cmp._PortletInfo.instance=null;ui.cmp.PortletInfo.getInstance=function(c){if(!ui.cmp._PortletInfo.instance){if(!c){c={}}ui.cmp._PortletInfo.instance=new ui.cmp.PortletInfo(c)}return ui.cmp._PortletInfo.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PortletLocalMail");ui.cmp._PortletLocalMail.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getLastNews"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"title"},{name:"link"},{name:"description"},{name:"pubDate",type:"date",dateFormat:"Y/m/d H:i:s"}]})});ui.cmp._PortletLocalMail.store.setDefaultSort("pubDate","desc");ui.cmp._PortletLocalMail.columns=[new Ext.grid.RowNumberer(),{id:"GridMailingTitle",header:_("Title"),sortable:true,dataIndex:"title"},{header:_("By"),width:100,sortable:true,dataIndex:"description"},{header:_("Date"),width:100,sortable:true,dataIndex:"pubDate",renderer:Ext.util.Format.dateRenderer(_("Y-m-d, H:i"))}];ui.cmp._PortletLocalMail.grid=Ext.extend(Ext.grid.GridPanel,{loadMask:true,autoScroll:true,height:250,autoExpandColumn:"GridMailingTitle",id:"PortletLocalMail-grid-id",store:ui.cmp._PortletLocalMail.store,columns:ui.cmp._PortletLocalMail.columns,sm:new Ext.grid.RowSelectionModel({singleSelect:true}),view:new Ext.grid.GridView({forceFit:true,enableRowBody:true,ignoreAdd:true,emptyText:'
'+_("You must manually load this data.
Use the refresh button !")+"
",deferEmptyText:false}),onRowDblClick:function(d,g){var c=d.store.getAt(g).data.pubDate,f=d.store.getAt(g).data.link,e=d.store.getAt(g).data.title;if(!Ext.getCmp("main-panel").findById("mail-"+c)){Ext.getCmp("main-panel").add({xtype:"panel",id:"mail-"+c,title:Ext.util.Format.substr(e,0,20)+"...",tabTip:e,iconCls:"iconMailing",closable:true,layout:"fit",items:[new Ext.ux.IFrameComponent({id:"frame-mail-"+c,url:f})]})}Ext.getCmp("main-panel").setActiveTab("mail-"+c)},onContextClick:function(c,f,d){if(!this.menu){this.menu=new Ext.menu.Menu({id:"submenu-mail",items:[{scope:this,text:""+_("Open in a new Tab")+"",iconCls:"iconOpenInTab",handler:function(){this.fireEvent("rowdblclick",c,this.ctxIndex,d);this.menu.hide()}},"-",{scope:this,text:_("Refresh this grid"),iconCls:"iconRefresh",handler:function(){this.ctxIndex=null;ui.cmp._PortletLocalMail.reloadData()}}]})}this.getSelectionModel().selectRow(f);d.stopEvent();if(this.ctxIndex){this.ctxIndex=null}this.ctxIndex=f;this.menu.showAt(d.getXY())},initComponent:function(c){ui.cmp._PortletLocalMail.grid.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowcontextmenu",this.onContextClick,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp._PortletLocalMail.reloadData=function(){ui.cmp._PortletLocalMail.store.reload({callback:function(d,e,c){if(!c){Ext.getCmp("PortletLocalMail-grid-id").getView().mainBody.update('
'+_("Error when loading mails from this mailing list !")+"
");Ext.get("PortletLocalMail-grid-defaultMess-id").highlight()}}})};ui.cmp.PortletLocalMail=Ext.extend(Ext.ux.Portlet,{title:"",iconCls:"iconMailing",layout:"fit",store:ui.cmp._PortletLocalMail.store,reloadData:ui.cmp._PortletLocalMail.reloadData,tools:[{id:"refresh",qtip:_("Refresh this grid"),handler:function(){ui.cmp._PortletLocalMail.reloadData()}}],listeners:{expand:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletLocalMailCollapsed",value:false,notify:false})}},collapse:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletLocalMailCollapsed",value:true,notify:false})}},afterrender:function(c){if(PhDOE.user.conf.portletLocalMailCollapsed){c.collapse()}else{c.expand()}}},initComponent:function(c){this.id="portletLocalMail";Ext.apply(this,c);ui.cmp.PortletLocalMail.superclass.initComponent.apply(this);this.title=String.format(_("Mail from {0}"),"doc-"+this.lang);this.add(new ui.cmp._PortletLocalMail.grid())}});ui.cmp._PortletLocalMail.instance=null;ui.cmp.PortletLocalMail.getInstance=function(c){if(!ui.cmp._PortletLocalMail.instance){if(!c){c={}}ui.cmp._PortletLocalMail.instance=new ui.cmp.PortletLocalMail(c)}return ui.cmp._PortletLocalMail.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PortletSummary");ui.cmp._PortletSummary.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getSummaryInfo"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"libel"},{name:"nbFiles"},{name:"percentFiles"},{name:"sizeFiles"},{name:"percentSize"}]}),listeners:{load:function(){this.each(function(c){switch(c.id){case 1:c.set("libel",_("Up to date files"));break;case 2:c.set("libel",_("Stale files"));break;case 3:c.set("libel",_("Files available for translation"));break;case 4:c.set("libel",_("Total"));break;default:c.set("libel","");break}c.commit()})}}});ui.cmp._PortletSummary.gridColumns=[new Ext.grid.RowNumberer(),{id:"StatusType",header:_("File status type"),width:180,sortable:true,dataIndex:"libel"},{header:_("Number of files"),width:110,sortable:true,dataIndex:"nbFiles"},{header:_("Percent of files"),width:110,sortable:true,dataIndex:"percentFiles"},{header:_("Size of files (kB)"),width:110,sortable:true,dataIndex:"sizeFiles"},{header:_("Percent of size"),width:110,sortable:true,dataIndex:"percentSize"}];ui.cmp._PortletSummary.gridView=new Ext.grid.GridView({getRowClass:function(c){switch(c.data.id){case 1:return"summary_1";case 2:return"summary_2";case 3:return"summary_3";case 4:return"summary_4";default:return""}}});ui.cmp._PortletSummary.grid=Ext.extend(Ext.grid.GridPanel,{loadMask:true,autoScroll:true,autoHeight:true,store:ui.cmp._PortletSummary.store,columns:ui.cmp._PortletSummary.gridColumns,view:ui.cmp._PortletSummary.gridView,onRowdblclick:function(c,e){var d=c.store.getAt(e).data.id;if(d===2){Ext.getCmp("acc-need-update").expand()}if(d===3){Ext.getCmp("acc-need-translate").expand()}},initComponent:function(c){ui.cmp._PortletSummary.grid.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowdblclick",this.onRowdblclick,this)}});ui.cmp.PortletSummary=Ext.extend(Ext.ux.Portlet,{title:_("Summary"),iconCls:"",layout:"fit",store:ui.cmp._PortletSummary.store,tools:[{id:"refresh",qtip:_("Refresh this grid"),handler:function(){ui.cmp._PortletSummary.store.reload()}}],listeners:{expand:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletSummaryCollapsed",value:false,notify:false})}},collapse:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletSummaryCollapsed",value:true,notify:false})}}},initComponent:function(c){this.id="portletSummary";Ext.apply(this,c);ui.cmp.PortletSummary.superclass.initComponent.apply(this);this.add(new ui.cmp._PortletSummary.grid())},afterRender:function(){ui.cmp.PortletSummary.superclass.afterRender.call(this);var c={cs:"cz",sr:"rs",sv:"se"};this.header.insertFirst({tag:"div",id:Ext.id(),style:"float: left; margin-right: 2px;",cls:"flags flag-"+(c[this.lang]||this.lang)},"first");if(PhDOE.user.conf.portletSummaryCollapsed){this.collapse()}else{this.expand()}}});ui.cmp._PortletSummary.instance=null;ui.cmp.PortletSummary.getInstance=function(c){if(!ui.cmp._PortletSummary.instance){if(!c){c={}}ui.cmp._PortletSummary.instance=new ui.cmp.PortletSummary(c)}return ui.cmp._PortletSummary.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PortletTranslationGraph");function renderLibel(c){return _(c)}ui.cmp._PortletTranslationGraph.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getGraphLang"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"libel",convert:renderLibel},{name:"total"}]})});ui.cmp._PortletTranslationGraph.chart=Ext.extend(Ext.chart.PieChart,{height:400,url:"js/ExtJs/resources/charts.swf",dataField:"total",categoryField:"libel",store:ui.cmp._PortletTranslationGraph.store,series:[{style:{colors:["#68D888","#FF6347","#EEE8AA"]}}],extraStyle:{legend:{display:"bottom",padding:5,font:{family:"Tahoma",size:13}}},initComponent:function(c){ui.cmp._PortletTranslationGraph.chart.superclass.initComponent.call(this);Ext.apply(this,c)}});ui.cmp.PortletTranslationGraph=Ext.extend(Ext.ux.Portlet,{title:_("Graphics"),iconCls:"iconGraphic",layout:"fit",store:ui.cmp._PortletTranslationGraph.store,tools:[{id:"refresh",qtip:_("Refresh this graph"),handler:function(){ui.cmp._PortletTranslationGraph.store.reload()}}],initComponent:function(c){this.id="portletTranslationGraph";Ext.apply(this,c);ui.cmp.PortletTranslationGraph.superclass.initComponent.apply(this);this.add(new ui.cmp._PortletTranslationGraph.chart())}});ui.cmp._PortletTranslationGraph.instance=null;ui.cmp.PortletTranslationGraph.getInstance=function(c){if(!ui.cmp._PortletTranslationGraph.instance){if(!c){c={}}ui.cmp._PortletTranslationGraph.instance=new ui.cmp.PortletTranslationGraph(c)}return ui.cmp._PortletTranslationGraph.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PortletTranslationsGraph");ui.cmp._PortletTranslationsGraph.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getGraphLangs"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"libel",type:"string"},{name:"fullLibel",type:"string"},{name:"total",type:"int"},{name:"percent",type:"float"}]})});ui.cmp._PortletTranslationsGraph.chart=Ext.extend(Ext.chart.ColumnChart,{height:400,url:"js/ExtJs/resources/charts.swf",xField:"libel",tipRenderer:function(d,c){return _("Lang:")+" "+c.data.fullLibel+"\r"+_("Total:")+" "+c.data.total+" "+_("files")+" ("+c.data.percent+"%)"},series:[{type:"column",displayName:"Total",yField:"total",style:{image:"themes/img/bar.gif",mode:"stretch",color:10075112}}],store:ui.cmp._PortletTranslationsGraph.store,initComponent:function(c){ui.cmp._PortletTranslationsGraph.chart.superclass.initComponent.call(this);Ext.apply(this,c)}});ui.cmp.PortletTranslationsGraph=Ext.extend(Ext.ux.Portlet,{title:_("Graphics for all languages"),iconCls:"iconGraphic",layout:"fit",store:ui.cmp._PortletTranslationsGraph.store,tools:[{id:"refresh",qtip:_("Refresh this graph"),handler:function(){ui.cmp._PortletTranslationsGraph.store.reload()}}],initComponent:function(c){this.id="portletTranslationsGraph";Ext.apply(this,c);ui.cmp.PortletTranslationsGraph.superclass.initComponent.apply(this);this.add(new ui.cmp._PortletTranslationsGraph.chart())}});ui.cmp._PortletTranslationsGraph.instance=null;ui.cmp.PortletTranslationsGraph.getInstance=function(c){if(!ui.cmp._PortletTranslationsGraph.instance){if(!c){c={}}ui.cmp._PortletTranslationsGraph.instance=new ui.cmp.PortletTranslationsGraph(c)}return ui.cmp._PortletTranslationsGraph.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PortletTranslator","ui.cmp._PortletReviewer");ui.cmp._PortletTranslator.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getTranslatorInfo"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"name"},{name:"email",mapping:"mail"},{name:"nick"},{name:"vcs"},{name:"uptodate",type:"int"},{name:"stale",type:"int"},{name:"sum",type:"int"}]}),listeners:{load:function(){var d=this.getCount(),c=d*20;ui.cmp.PortletTranslator.getInstance().setHeight(c+124);ui.cmp.PortletTranslator.getInstance().doLayout()}}});ui.cmp._PortletTranslator.store.setDefaultSort("nick","asc");ui.cmp._PortletReviewer.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getReviewerInfo"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"name"},{name:"email",mapping:"mail"},{name:"nick"},{name:"vcs"},{name:"reviewedUptodate",type:"int"},{name:"reviewedStale",type:"int"},{name:"reviewedSum",type:"int"}]})});ui.cmp._PortletReviewer.store.setDefaultSort("nick","asc");ui.cmp._PortletTranslator.translatorSumRenderer=function(c){if(c){c=(c===0||c>1)?c:1;return String.format("("+_("{0} Translators")+")",c)}else{return false}};ui.cmp._PortletReviewer.translatorSumRenderer=function(c){if(c){c=(c===0||c>1)?c:1;return String.format("("+_("{0} Reviewers")+")",c)}else{return _("No reviewer")}};ui.cmp._PortletTranslator.uptodateRenderer=function(c){if(c==="0"){return false}else{return''+c+""}};ui.cmp._PortletReviewer.uptodateRenderer=function(c){if(c==="0"){return false}else{return''+c+""}};ui.cmp._PortletTranslator.staleRenderer=function(c){if(c==="0"){return false}else{return''+c+""}};ui.cmp._PortletReviewer.staleRenderer=function(c){if(c==="0"){return false}else{return''+c+""}};ui.cmp._PortletTranslator.sumRenderer=function(c){return(c==="0")?"":c};ui.cmp._PortletReviewer.sumRenderer=function(c){return(c==="0")?"":c};ui.cmp._PortletTranslator.gridColumns=[new Ext.grid.RowNumberer(),{id:"GridTransName",header:_("Name"),sortable:true,dataIndex:"name",summaryType:"count",summaryRenderer:ui.cmp._PortletTranslator.translatorSumRenderer},{header:_("Email"),width:110,sortable:true,dataIndex:"email"},{header:_("Nick"),width:70,sortable:true,dataIndex:"nick"},{header:_("VCS"),width:45,sortable:true,dataIndex:"vcs"},{header:_("UptoDate"),width:60,sortable:true,renderer:ui.cmp._PortletTranslator.uptodateRenderer,dataIndex:"uptodate",summaryType:"sum"},{header:_("Stale"),width:90,sortable:true,renderer:ui.cmp._PortletTranslator.staleRenderer,dataIndex:"stale",summaryType:"sum"},{header:_("Sum"),width:50,sortable:true,renderer:ui.cmp._PortletTranslator.sumRenderer,dataIndex:"sum",summaryType:"sum"}];ui.cmp._PortletReviewer.gridColumns=[new Ext.grid.RowNumberer(),{id:"GridTransName",header:_("Name"),sortable:true,dataIndex:"name",summaryType:"count",summaryRenderer:ui.cmp._PortletReviewer.translatorSumRenderer},{header:_("Email"),width:110,sortable:true,dataIndex:"email"},{header:_("Nick"),width:70,sortable:true,dataIndex:"nick"},{header:_("VCS"),width:45,sortable:true,dataIndex:"vcs"},{header:_("Reviewed"),width:60,sortable:true,renderer:ui.cmp._PortletReviewer.uptodateRenderer,dataIndex:"reviewedUptodate",summaryType:"sum"},{header:_("Must be reviewed"),width:90,sortable:true,renderer:ui.cmp._PortletReviewer.staleRenderer,dataIndex:"reviewedStale",summaryType:"sum"},{header:_("Sum"),width:50,sortable:true,renderer:ui.cmp._PortletReviewer.sumRenderer,dataIndex:"reviewedSum",summaryType:"sum"}];ui.cmp._PortletTranslator.grid=Ext.extend(Ext.grid.GridPanel,{title:_("Translators"),loadMask:true,autoScroll:true,autoHeight:true,plugins:[new Ext.ux.grid.GridSummary()],store:ui.cmp._PortletTranslator.store,columns:ui.cmp._PortletTranslator.gridColumns,autoExpandColumn:"GridTransName",sm:new Ext.grid.RowSelectionModel({singleSelect:true}),lang:this.lang,EmailPrompt:new ui.cmp.EmailPrompt(),onRowDblClick:function(d,e){this.getSelectionModel().selectRow(e);if(this.ctxTranslatorName){this.ctxTranslatorEmail=null;this.ctxTranslatorName=null}this.ctxTranslatorEmail=this.store.getAt(e).data.email;this.ctxTranslatorName=this.store.getAt(e).data.name;var c=this.store.getAt(e).data.nick;if(c==="nobody"){return}this.EmailPrompt.setData(this.ctxTranslatorName,this.ctxTranslatorEmail);this.EmailPrompt.show("lastUpdateTime")},onContextClick:function(d,g,f){if(!this.menu){this.menu=new Ext.menu.Menu({id:"submenu-translators",items:[{scope:this,text:"",iconCls:"iconSendEmail",handler:function(){this.EmailPrompt.setData(this.ctxTranslatorName,this.ctxTranslatorEmail);this.EmailPrompt.show("lastUpdateTime")}},"-",{scope:this,text:String.format(_("Send an email to the {0}"),String.format(PhDOE.app.conf.projectMailList,this.lang)),iconCls:"iconSendEmail",handler:function(){this.EmailPrompt.setData("Php Doc Team "+this.lang,String.format(PhDOE.app.conf.projectMailList,this.lang));this.EmailPrompt.show("lastUpdateTime")}}]})}this.getSelectionModel().selectRow(g);f.stopEvent();if(this.ctxTranslatorName){this.ctxTranslatorName=null;this.ctxTranslatorEmail=null}this.ctxTranslatorName=this.store.getAt(g).data.name;this.ctxTranslatorEmail=this.store.getAt(g).data.email;var c=this.store.getAt(g).data.nick;if(c==="nobody"){return}this.menu.items.items[0].setText(""+String.format(_("Send an email to {0}"),this.ctxTranslatorName)+"");this.menu.showAt(f.getXY())},initComponent:function(c){ui.cmp._PortletTranslator.grid.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowcontextmenu",this.onContextClick,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp._PortletReviewer.grid=Ext.extend(Ext.grid.GridPanel,{title:_("Reviewers"),loadMask:true,autoScroll:true,autoHeight:true,plugins:[new Ext.ux.grid.GridSummary()],store:ui.cmp._PortletReviewer.store,columns:ui.cmp._PortletReviewer.gridColumns,autoExpandColumn:"GridTransName",sm:new Ext.grid.RowSelectionModel({singleSelect:true}),lang:this.lang,EmailPrompt:new ui.cmp.EmailPrompt(),onRowDblClick:function(d,e){this.getSelectionModel().selectRow(e);if(this.ctxTranslatorName){this.ctxTranslatorEmail=null;this.ctxTranslatorName=null}this.ctxTranslatorEmail=this.store.getAt(e).data.email;this.ctxTranslatorName=this.store.getAt(e).data.name;var c=this.store.getAt(e).data.nick;if(c==="nobody"){return}this.EmailPrompt.setData(this.ctxTranslatorName,this.ctxTranslatorEmail);this.EmailPrompt.show("lastUpdateTime")},onContextClick:function(d,g,f){if(!this.menu){this.menu=new Ext.menu.Menu({id:"submenu-translators",items:[{scope:this,text:"",iconCls:"iconSendEmail",handler:function(){this.EmailPrompt.setData(this.ctxTranslatorName,this.ctxTranslatorEmail);this.EmailPrompt.show("lastUpdateTime")}},"-",{scope:this,text:String.format(_("Send an email to the {0}"),String.format(PhDOE.app.conf.projectMailList,this.lang)),iconCls:"iconSendEmail",handler:function(){this.EmailPrompt.setData("Php Doc Team "+this.lang,String.format(PhDOE.app.conf.projectMailList,this.lang));this.EmailPrompt.show("lastUpdateTime")}}]})}this.getSelectionModel().selectRow(g);f.stopEvent();if(this.ctxTranslatorName){this.ctxTranslatorName=null;this.ctxTranslatorEmail=null}this.ctxTranslatorName=this.store.getAt(g).data.name;this.ctxTranslatorEmail=this.store.getAt(g).data.email;var c=this.store.getAt(g).data.nick;if(c==="nobody"){return}this.menu.items.items[0].setText(""+String.format(_("Send an email to {0}"),this.ctxTranslatorName)+"");this.menu.showAt(f.getXY())},initComponent:function(c){ui.cmp._PortletReviewer.grid.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowcontextmenu",this.onContextClick,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp.PortletTranslator=Ext.extend(Ext.ux.Portlet,{title:_("Translators & Reviewer"),iconCls:"iconTranslator",layout:"fit",storeTranslator:ui.cmp._PortletTranslator.store,storeReviewer:ui.cmp._PortletReviewer.store,tools:[{id:"refresh",qtip:_("Refresh this grid"),handler:function(){ui.cmp._PortletTranslator.store.reload({callback:function(){ui.cmp._PortletReviewer.store.reload()}})}}],listeners:{expand:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletTranslatorCollapsed",value:false,notify:false})}},collapse:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletTranslatorCollapsed",value:true,notify:false})}},afterrender:function(c){if(PhDOE.user.conf.portletTranslatorCollapsed){c.collapse()}else{c.expand()}}},initComponent:function(c){this.id="portletTranslator";Ext.apply(this,c);ui.cmp.PortletTranslator.superclass.initComponent.apply(this);this.add({xtype:"tabpanel",activeTab:0,border:false,height:200,tabPosition:"bottom",autoScroll:true,items:[new ui.cmp._PortletTranslator.grid({lang:this.lang}),new ui.cmp._PortletReviewer.grid({lang:this.lang})]})}});ui.cmp._PortletTranslator.instance=null;ui.cmp.PortletTranslator.getInstance=function(c){if(!ui.cmp._PortletTranslator.instance){if(!c){c={}}ui.cmp._PortletTranslator.instance=new ui.cmp.PortletTranslator(c)}return ui.cmp._PortletTranslator.instance};Ext.namespace("ui","ui.cmp");ui.cmp.PreviewFile=Ext.extend(Ext.Window,{id:"winPreviewFile",layout:"fit",title:_("Preview"),iconCls:"iconView",closable:true,closeAction:"close",maximized:true,modal:true,buttons:[{text:_("Close"),handler:function(){this.ownerCt.ownerCt.close()}}],initComponent:function(){var c=this;ui.cmp.PreviewFile.superclass.initComponent.call(this);XHR({params:{task:"previewFile",path:this.path},success:function(d){var f=Ext.util.JSON.decode(d.responseText),e;f.url=f.url+"?"+Math.random();e=new Ext.ux.IFrameComponent({id:"frame-previewFile",url:f.url});c.add(e);c.show()},failure:function(){}})}});Ext.namespace("ui","ui.cmp","ui.cmp._RepositoryTree");ui.cmp._RepositoryTree.root={nodeType:"async",id:"/",text:_("Repository"),draggable:false};ui.cmp._RepositoryTree.loader=new Ext.tree.TreeLoader({dataUrl:"./do/getAllFiles"});ui.cmp._RepositoryTree.winAddNewFile=Ext.extend(Ext.Window,{title:_("Add a new file"),iconCls:"iconFilesNeedTranslate",id:"win-add-new-file",layout:"form",width:350,height:170,resizable:false,modal:true,bodyStyle:"padding:5px 5px 0",labelWidth:150,buttons:[{id:"win-add-new-file-btn",text:_("Open the editor"),disabled:true,handler:function(){var d=Ext.getCmp("win-add-new-file"),f=d.node.id,c=d.items.items[1].getValue(),e=d.items.items[2].getValue();if(d.node.findChild("id",f+"/"+c)){PhDOE.winForbidden("file_already_exist");return true}d.openFile(f+"/",c,e);d.close();return true}}],openFile:function(e,c,j){var h=Ext.util.md5("FNT-"+e+c),g={data:{fileModified:false,node:this.node}},d=e.split("/"),f;d.shift();f=d[0];d.shift();d.pop();e="/"+d.join("/")+"/";if(e==="//"){e="/"}h=Ext.util.md5("FNT-"+e+c);if(!Ext.getCmp("main-panel").findById("FNT-"+h)){Ext.getCmp("main-panel").add({id:"FNT-"+h,layout:"border",title:c,originTitle:c,iconCls:"iconTabNeedTranslate",closable:true,tabLoaded:false,panTRANSLoaded:false,panGGTRANSLoaded:true,defaults:{split:true},tabTip:String.format(_("New file: in {0}"),f+e),items:[new ui.cmp.FilePanel({id:"FNT-NEW-PANEL-"+h,region:"center",title:_("New file: ")+f+e+c,isTrans:true,prefix:"FNT",ftype:"NEW",fid:h,fpath:e,fname:c,lang:f,parser:"xml",storeRecord:g,syncScrollCB:false,syncScroll:false,skeleton:j})]})}Ext.getCmp("main-panel").setActiveTab("FNT-"+h)},initComponent:function(){Ext.apply(this,{items:[{xtype:"displayfield",fieldLabel:_("Parent Folder"),value:this.node.id},{xtype:"textfield",fieldLabel:_("Name for the new file"),name:"newFolderName",listeners:{valid:function(){Ext.getCmp("win-add-new-file-btn").enable()},invalid:function(){Ext.getCmp("win-add-new-file-btn").disable()}}},{xtype:"combo",triggerAction:"all",width:160,editable:false,store:new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getSkeletonsNames"}),reader:new Ext.data.JsonReader({root:"Items",idProperty:"name",fields:[{name:"name"},{name:"path"}]})}),listeners:{select:function(f,d,e){if(f.ownerCt.items.items[1].getValue()===""){f.ownerCt.items.items[1].setValue(d.data.name)}}},valueField:"path",displayField:"name",fieldLabel:_("Chose a skeleton")}]});ui.cmp._RepositoryTree.winAddNewFile.superclass.initComponent.call(this)}});ui.cmp._RepositoryTree.winAddNewFolder=Ext.extend(Ext.Window,{title:_("Add a new folder"),iconCls:"iconFolderNew",id:"win-add-new-folder",layout:"form",width:350,height:200,resizable:false,modal:true,bodyStyle:"padding:5px 5px 0",labelWidth:150,buttons:[{id:"win-add-new-folder-btn",text:"Add",disabled:true,handler:function(){var c=Ext.getCmp("win-add-new-folder"),e=c.node.id,d=c.items.items[1].getValue();XHR({params:{task:"addNewFolder",parentFolder:e,newFolderName:d},success:function(){Ext.getCmp("win-add-new-folder").close();c.node.reload();PhDOE.notify("info",_("Folder created"),String.format(_("Folder

{0}

was created sucessfully under {1} !"),d,e))},failure:function(f){var g=Ext.util.JSON.decode(f.responseText);if(g.type){PhDOE.winForbidden(g.type)}else{PhDOE.winForbidden()}}})}}],initComponent:function(){Ext.apply(this,{items:[{xtype:"displayfield",fieldLabel:_("Parent Folder"),value:this.node.id},{xtype:"textfield",fieldLabel:_("Name for the new folder"),name:"newFolderName",vtype:"alphanum",listeners:{valid:function(){Ext.getCmp("win-add-new-folder-btn").enable()},invalid:function(){Ext.getCmp("win-add-new-folder-btn").disable()}}},{xtype:"box",html:_("Info: This new folder won't be commited until a new file will be commited into it. If you don't commit any new file into it until 8 days, it will be automatically deleted.")}]});ui.cmp._RepositoryTree.winAddNewFolder.superclass.initComponent.call(this)}});Ext.namespace("ui.cmp._RepositoryTree.menu");ui.cmp._RepositoryTree.menu.folder=function(c){Ext.apply(this,c);this.init();ui.cmp._RepositoryTree.menu.folder.superclass.constructor.call(this)};Ext.extend(ui.cmp._RepositoryTree.menu.folder,Ext.menu.Menu,{init:function(){Ext.apply(this,{items:[{text:(this.node.isExpanded())?""+_("Collapse")+"":""+_("Expand")+"",iconCls:"iconFolderClose",scope:this,handler:function(){if(this.node.isExpanded()){this.node.collapse()}else{this.node.expand()}}},"-",{text:_("Update this folder"),iconCls:"iconFilesNeedUpdate",scope:this,handler:function(){this.node.expand();new ui.task.UpdateSingleFolderTask(this.node)}},{text:_("Add a new folder"),iconCls:"iconFolderNew",hidden:(this.node.id==="/"||(Ext.util.Format.substr(this.node.id,0,3)!=="/en"&&Ext.util.Format.substr(this.node.id,0,9)!=="/doc-base")),scope:this,handler:function(){this.node.expand();var c=new ui.cmp._RepositoryTree.winAddNewFolder({node:this.node});c.show(this.node.ui.getEl())}},{text:_("Add a new file"),iconCls:"iconFilesNeedTranslate",hidden:(this.node.id==="/"||(Ext.util.Format.substr(this.node.id,0,3)!=="/en"&&Ext.util.Format.substr(this.node.id,0,9)!=="/doc-base")),scope:this,handler:function(){this.node.expand();var c=new ui.cmp._RepositoryTree.winAddNewFile({node:this.node});c.show(this.node.ui.getEl())}}]})}});ui.cmp._RepositoryTree.menu.file=function(c){Ext.apply(this,c);this.init();ui.cmp._RepositoryTree.menu.file.superclass.constructor.call(this)};Ext.extend(ui.cmp._RepositoryTree.menu.file,Ext.menu.Menu,{init:function(){var c=this.node.attributes.text,d=this.node.attributes.id.split("/"),f,e;d.shift();f=d[0];d.shift();d.pop();e=d.join("/")+"/";Ext.apply(this,{items:[{text:""+_("Edit in a new tab")+"",iconCls:"iconTabNeedReviewed",scope:this,handler:function(){ui.cmp._RepositoryTree.instance.fireEvent("dblclick",this.node)}},{hidden:(this.node.attributes.from==="search"||PhDOE.user.lang==="en"),text:(f==="en")?String.format(_("Open the same file in {0}"),Ext.util.Format.uppercase(PhDOE.user.lang)):String.format(_("Open the same file in {0}"),"EN"),iconCls:"iconTabNeedReviewed",scope:this,handler:function(){if(f==="en"){ui.cmp._RepositoryTree.instance.openFile("byPath",PhDOE.user.lang+"/"+e,c)}else{ui.cmp._RepositoryTree.instance.openFile("byPath","en/"+e,c)}}}]})}});ui.cmp.RepositoryTree=Ext.extend(Ext.ux.MultiSelectTreePanel,{animate:true,enableDD:true,ddGroup:"mainPanelDDGroup",useArrows:true,autoScroll:true,border:false,containerScroll:true,root:ui.cmp._RepositoryTree.root,loader:ui.cmp._RepositoryTree.loader,onContextMenu:function(c,d){d.stopEvent();c.select();if(c.attributes.type==="folder"||c.isRoot){new ui.cmp._RepositoryTree.menu.folder({node:c}).showAt(d.getXY())}else{if(c.attributes.type==="file"){new ui.cmp._RepositoryTree.menu.file({node:c}).showAt(d.getXY())}}},onDblClick:function(c){if(c.attributes.type==="file"){this.openFile("byId",c.attributes.id,false)}},openFile:function(r,m,g){if(r==="byPath"){Ext.getCmp("acc-all-files").expand();var f=m,j=g,u=f.split("/"),l=function(w){w.ensureVisible();if(u[0]&&u[0]!==""){for(var t=0;t0)?"/"+u.join("/")+"/":"/";p=Ext.util.md5("AF-"+h+c+e);if(!Ext.getCmp("main-panel").findById("AF-"+p)){if(s!=="html"){d=s}else{d="xml"}if(s==="gif"||s==="png"||s==="jpg"){o={};q={id:"AF-ALL-FILE-"+p,xtype:"panel",region:"center",layout:"fit",bodyStyle:"padding:5px 5px 0",html:''}}else{o={xtype:"panel",region:"west",title:_("Tools"),iconCls:"iconConf",collapsedIconCls:"iconConf",plugins:[Ext.ux.PanelCollapsedTitle],layout:"fit",bodyBorder:false,split:true,collapsible:true,collapsed:!PhDOE.user.conf.allFiles.toolsPanelDisplay,width:PhDOE.user.conf.allFiles.toolsPanelWidth||375,listeners:{collapse:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"allFiles",itemName:"toolsPanelDisplay",value:false,notify:false})}},expand:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"allFiles",itemName:"toolsPanelDisplay",value:true,notify:false})}},resize:function(t,v){if(this.ownerCt.tabLoaded&&v&&v!=PhDOE.user.conf.allFiles.toolsPanelWidth){new ui.task.UpdateConfTask({module:"allFiles",itemName:"toolsPanelWidth",value:v,notify:false})}}},items:{xtype:"tabpanel",activeTab:0,defaults:{autoScroll:true},items:[{title:_("Log"),layout:"fit",items:[new ui.cmp.VCSLogGrid({prefix:"AF",fid:p,fpath:h+c,fname:e,loadStore:PhDOE.user.conf.allFiles.toolsPanelLogLoad})]},{title:_("Entities"),layout:"fit",items:[new ui.cmp.EntitiesAcronymsPanel({dataType:"entities",prefix:"AF",ftype:"ALL",fid:p,loadStore:PhDOE.user.conf.allFiles.toolsPanelEntitiesLoad})]},{title:_("Acronyms"),layout:"fit",items:[new ui.cmp.EntitiesAcronymsPanel({dataType:"acronyms",prefix:"AF",ftype:"ALL",fid:p,loadStore:PhDOE.user.conf.allFiles.toolsPanelAcronymsLoad})]}]}};q=new ui.cmp.FilePanel({id:"AF-ALL-PANEL-"+p,region:"center",title:_("File: ")+h+c+e,prefix:"AF",ftype:"ALL",spellCheck:PhDOE.user.conf.allFiles.enableSpellCheck,spellCheckConf:{module:"allFiles",itemName:"enableSpellCheck"},fid:p,fpath:c,fname:e,lang:h,parser:d,storeRecord:k,syncScrollCB:false,syncScroll:false})}Ext.getCmp("main-panel").add({id:"AF-"+p,layout:"border",title:e,originTitle:e,closable:true,tabLoaded:false,panEntities:!PhDOE.user.conf.allFiles.toolsPanelEntitiesLoad,panAcronyms:!PhDOE.user.conf.allFiles.toolsPanelAcronymsLoad,panVCS:!PhDOE.user.conf.allFiles.toolsPanelLogLoad,panLoaded:false,tabTip:String.format(_("in {0}"),c),iconCls:"iconAllFiles",items:[q,o]})}Ext.getCmp("main-panel").setActiveTab("AF-"+p)}},initComponent:function(){Ext.apply(this,{tbar:[_("Search: ")," ",new Ext.form.TwinTriggerField({id:"AF-search",validationEvent:false,validateOnBlur:false,trigger1Class:"x-form-clear-trigger",trigger2Class:"x-form-search-trigger",hideTrigger1:true,width:180,enableKeyEvents:true,listeners:{keypress:function(d,c){if(c.getKey()===c.ENTER){this.onTrigger2Click()}}},onTrigger1Click:function(){var c=ui.cmp._RepositoryTree.instance;this.setValue("");this.triggers[0].hide();this.setSize(180,10);c.root.setText(_("Repository"));delete c.loader.baseParams.search;c.root.reload()},onTrigger2Click:function(){var c=ui.cmp._RepositoryTree.instance,d=this.getValue();if(d===""||d.length<3){this.markInvalid(_("Your search must contain at least 3 characters"));return}this.clearInvalid();this.triggers[0].show();this.setSize(180,10);c.loader.baseParams.search=d;c.root.reload(function(){c.root.setText(String.format(_("Search result: {0}"),c.root.childNodes.length))})}})]});ui.cmp.RepositoryTree.superclass.initComponent.call(this);this.on("contextmenu",this.onContextMenu,this);this.on("dblclick",this.onDblClick,this);new Ext.tree.TreeSorter(this,{folderSort:true})}});ui.cmp._RepositoryTree.instance=null;ui.cmp.RepositoryTree.getInstance=function(c){if(!ui.cmp._RepositoryTree.instance){if(!c){c={}}ui.cmp._RepositoryTree.instance=new ui.cmp.RepositoryTree(c)}return ui.cmp._RepositoryTree.instance};Ext.namespace("ui","ui.cmp","ui.cmp._StaleFileGrid");ui.cmp._StaleFileGrid.store=new Ext.data.GroupingStore({proxy:new Ext.data.HttpProxy({url:"./do/getFilesNeedUpdate"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"path"},{name:"name"},{name:"revision"},{name:"original_revision"},{name:"en_revision"},{name:"maintainer"},{name:"fileModifiedEN"},{name:"fileModifiedLang"}]}),sortInfo:{field:"name",direction:"ASC"},groupField:"path",listeners:{datachanged:function(e){var c=e.getCount(),d=false;if(!PhDOE.user.isAnonymous){e.each(function(f){if(f.data.maintainer==PhDOE.user.login){d++}},this)}if(d){Ext.getDom("acc-need-update-nb").innerHTML=c+" - "+String.format(_("{0} mine"),d)}else{Ext.getDom("acc-need-update-nb").innerHTML=c}}}});ui.cmp._StaleFileGrid.view=new Ext.grid.GroupingView({forceFit:true,startCollapsed:true,groupTextTpl:'{[values.rs[0].data["path"]]} ({[values.rs.length]} {[values.rs.length > 1 ? "'+_("Files")+'" : "'+_("File")+'"]})',deferEmptyText:false,getRowClass:function(c){if(c.data.fileModifiedEN||c.data.fileModifiedLang){var e=Ext.util.JSON.decode(c.data.fileModifiedEN),d=Ext.util.JSON.decode(c.data.fileModifiedLang);return((e.user===PhDOE.user.login&&e.anonymousIdent===PhDOE.user.anonymousIdent)||(d.user===PhDOE.user.login&&d.anonymousIdent===PhDOE.user.anonymousIdent))?"fileModifiedByMe":"fileModifiedByAnother"}return false},emptyText:'
'+_("No Files")+"
"});ui.cmp._StaleFileGrid.columns=[{id:"name",header:_("Files"),sortable:true,dataIndex:"name",renderer:function(c,f,d){var h="",g,e;if(d.data.fileModifiedEN){g=Ext.util.JSON.decode(d.data.fileModifiedEN);if(g.user===PhDOE.user.login&&g.anonymousIdent===PhDOE.user.anonymousIdent){h=_("File EN modified by me")+"
"}else{h=String.format(_("File EN modified by {0}"),g.user)+"
"}}if(d.data.fileModifiedLang){e=Ext.util.JSON.decode(d.data.fileModifiedLang);if(e.user===PhDOE.user.login&&e.anonymousIdent===PhDOE.user.anonymousIdent){h+=String.format(_("File {0} modified by me"),PhDOE.user.lang.ucFirst())}else{h+=String.format(_("File {0} modified by {1}"),PhDOE.user.lang.ucFirst(),e.user)}}if(h!==""){return""+c+""}else{return c}}},{header:_("EN revision"),width:45,sortable:true,dataIndex:"en_revision"},{header:"",width:45,sortable:true,dataIndex:"revision"},{header:_("Maintainer"),width:45,sortable:true,dataIndex:"maintainer"},{header:_("Path"),dataIndex:"path",hidden:true}];ui.cmp._StaleFileGrid.menu=function(c){Ext.apply(this,c);this.init();ui.cmp._StaleFileGrid.menu.superclass.constructor.call(this)};Ext.extend(ui.cmp._StaleFileGrid.menu,Ext.menu.Menu,{init:function(){Ext.apply(this,{items:[{scope:this,text:""+_("Edit in a new tab")+"",iconCls:"iconTabNeedUpdate",handler:function(){this.grid.fireEvent("rowdblclick",this.grid,this.rowIdx,this.event)}},{scope:this,hidden:this.hideDiffMenu,text:_("View diff..."),iconCls:"iconViewDiff",menu:new Ext.menu.Menu({items:[{scope:this,hidden:(this.grid.store.getAt(this.rowIdx).data.fileModifiedEN===false),text:String.format(_("... of the {0} file"),"EN"),handler:function(){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",FileName:this.fname,FilePath:"en"+this.fpath})}},{scope:this,hidden:(this.grid.store.getAt(this.rowIdx).data.fileModifiedLang===false),text:String.format(_("... of the {0} file"),PhDOE.user.lang.ucFirst()),handler:function(){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",FileName:this.fname,FilePath:PhDOE.user.lang+this.fpath})}}]})}]})}});ui.cmp.StaleFileGrid=Ext.extend(Ext.grid.GridPanel,{view:ui.cmp._StaleFileGrid.view,loadMask:true,autoExpandColumn:"name",border:false,enableDragDrop:true,ddGroup:"mainPanelDDGroup",onRowContextMenu:function(d,j,h){h.stopEvent();var g=this.store.getAt(j).data,f=g.path,c=g.name;this.getSelectionModel().selectRow(j);new ui.cmp._StaleFileGrid.menu({hideDiffMenu:(g.fileModifiedEN===false&&g.fileModifiedLang===false),grid:this,event:h,rowIdx:j,lang:PhDOE.user.lang,fpath:f,fname:c}).showAt(h.getXY())},onRowDblClick:function(c,d){this.openFile(this.store.getAt(d).data.id)},openFile:function(e){var g=this.store.getById(e),c=g.data.path,d=g.data.name,j=g.data.en_revision,h=g.data.revision,l=g.data.original_revision,f=Ext.util.md5("FNU-"+PhDOE.user.lang+c+d),k="";if(!Ext.getCmp("main-panel").findById("FNU-"+f)){if(PhDOE.user.conf.needUpdate.diffMethod==="using-viewvc"){k=ui.cmp.ViewVCDiff}else{if(PhDOE.user.conf.needUpdate.diffMethod==="using-exec"){k=ui.cmp.ExecDiff}}Ext.getCmp("main-panel").add({id:"FNU-"+f,layout:"border",title:d,originTitle:d,iconCls:"iconTabNeedUpdate",closable:true,tabLoaded:false,panVCSLang:!PhDOE.user.conf.needUpdate.toolsPanelLogLoad,panVCSEn:!PhDOE.user.conf.needUpdate.toolsPanelLogLoad,panDiffLoaded:(PhDOE.user.conf.needUpdate.diffMethod==="using-viewvc"),panLANGLoaded:false,panENLoaded:false,defaults:{split:true},tabTip:String.format(_("Need Update: in {0}"),c),listeners:{resize:function(m){Ext.getCmp("FNU-EN-PANEL-"+f).setWidth(m.getWidth()/2)}},items:[new k({region:"north",collapsible:true,height:PhDOE.user.conf.needUpdate.diffPanelHeight||150,prefix:"FNU",collapsed:!PhDOE.user.conf.needUpdate.diffPanelDisplay,fid:f,fpath:c,fname:d,rev1:(l)?l:h,rev2:j,listeners:{collapse:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"diffPanelDisplay",value:false,notify:false})}},expand:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"diffPanelDisplay",value:true,notify:false})}},resize:function(p,m,o){if(this.ownerCt.tabLoaded&&o&&o>50&&o!=PhDOE.user.conf.needUpdate.diffPanelHeight){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"diffPanelHeight",value:o,notify:false})}}}}),{region:"west",xtype:"panel",title:_("Tools"),iconCls:"iconConf",collapsedIconCls:"iconConf",collapsible:true,collapsed:!PhDOE.user.conf.needUpdate.toolsPanelDisplay,layout:"fit",bodyBorder:false,plugins:[Ext.ux.PanelCollapsedTitle],width:PhDOE.user.conf.needUpdate.toolsPanelWidth||375,listeners:{collapse:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"toolsPanelDisplay",value:false,notify:false})}},expand:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"toolsPanelDisplay",value:true,notify:false})}},resize:function(m,o){if(this.ownerCt.tabLoaded&&o&&o!=PhDOE.user.conf.needUpdate.toolsPanelWidth){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"toolsPanelWidth",value:o,notify:false})}}},items:{xtype:"tabpanel",activeTab:0,tabPosition:"bottom",enableTabScroll:true,defaults:{autoScroll:true},items:[new ui.cmp.VCSLogGrid({layout:"fit",title:String.format(_("{0} Log"),PhDOE.user.lang.ucFirst()),prefix:"FNU-LANG",fid:f,fpath:PhDOE.user.lang+c,fname:d,loadStore:PhDOE.user.conf.needUpdate.toolsPanelLogLoad}),new ui.cmp.VCSLogGrid({layout:"fit",title:String.format(_("{0} Log"),"En"),prefix:"FNU-EN",fid:f,fpath:"en"+c,fname:d,loadStore:PhDOE.user.conf.needUpdate.toolsPanelLogLoad}),new ui.cmp.DictionaryGrid({layout:"fit",title:_("Dictionary"),prefix:"FNU",fid:f})]}},new ui.cmp.FilePanel({id:"FNU-LANG-PANEL-"+f,region:"center",title:String.format(_("{0} File: "),PhDOE.user.lang)+c+d,prefix:"FNU",ftype:"LANG",spellCheck:PhDOE.user.conf.needUpdate.enableSpellCheckLang,spellCheckConf:{module:"needUpdate",itemName:"enableSpellCheckLang"},fid:f,fpath:c,fname:d,lang:PhDOE.user.lang,parser:"xml",storeRecord:g,syncScrollCB:true,syncScroll:true,syncScrollConf:{module:"needUpdate",itemName:"syncScrollbars"}}),new ui.cmp.FilePanel({id:"FNU-EN-PANEL-"+f,region:"east",title:_("en File: ")+c+d,prefix:"FNU",ftype:"EN",original:true,readOnly:true,openInNewTabBtn:true,fid:f,fpath:c,fname:d,lang:"en",parser:"xml",storeRecord:g,syncScroll:true,syncScrollConf:{module:"needUpdate",itemName:"syncScrollbars"}})]})}Ext.getCmp("main-panel").setActiveTab("FNU-"+f)},initComponent:function(){ui.cmp._StaleFileGrid.columns[2].header=String.format(_("{0} revision"),Ext.util.Format.uppercase(PhDOE.user.lang));Ext.apply(this,{columns:ui.cmp._StaleFileGrid.columns,store:ui.cmp._StaleFileGrid.store,tbar:[_("Filter: ")," ",new Ext.form.TwinTriggerField({id:"FNU-filter",width:180,hideTrigger1:true,enableKeyEvents:true,validateOnBlur:false,validationEvent:false,trigger1Class:"x-form-clear-trigger",trigger2Class:"x-form-search-trigger",listeners:{specialkey:function(d,c){if(c.getKey()===c.ENTER){this.onTrigger2Click()}}},onTrigger1Click:function(){this.setValue("");this.triggers[0].hide();this.setSize(180,10);ui.cmp._StaleFileGrid.instance.store.clearFilter()},onTrigger2Click:function(){var c=this.getValue(),d;if(c===""||c.length<3){this.markInvalid(_("Your filter must contain at least 3 characters"));return}this.clearInvalid();this.triggers[0].show();this.setSize(180,10);d=new RegExp(c,"i");ui.cmp._StaleFileGrid.instance.store.filterBy(function(e){if(d.test(e.data.path)||d.test(e.data.name)||d.test(e.data.revision)||d.test(e.data.en_revision)||d.test(e.data.maintainer)){return true}else{return false}},this)}})]});ui.cmp.StaleFileGrid.superclass.initComponent.call(this);this.on("rowcontextmenu",this.onRowContextMenu,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp._StaleFileGrid.instance=null;ui.cmp.StaleFileGrid.getInstance=function(c){if(!ui.cmp._StaleFileGrid.instance){if(!c){c={}}ui.cmp._StaleFileGrid.instance=new ui.cmp.StaleFileGrid(c)}return ui.cmp._StaleFileGrid.instance};Ext.namespace("ui","ui.cmp");ui.cmp.SystemUpdatePrompt=Ext.extend(Ext.Window,{id:"sys-update-win",title:_("Refresh all data"),layout:"form",width:300,height:200,resizable:false,modal:true,bodyStyle:"padding:15px 15px 0",iconCls:"iconRefresh",html:['
',_("Update all files from VCS"),"
",'
',_("This may take time. Thank you for your patience..."),"
",'
',_("Apply all tools"),"
",'
',_("Reload data"),"
"].join(""),buttons:[{id:"btn-start-refresh",text:_("Start"),iconCls:"iconStartRefresh",handler:function(){Ext.getCmp("btn-start-refresh").disable();this.ownerCt.ownerCt.tools.close.setVisible(false);new ui.task.SystemUpdateTask()}}]});Ext.namespace("ui","ui.cmp","ui.cmp._VCSLogGrid");ui.cmp._VCSLogGrid.store=Ext.extend(Ext.data.Store,{reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"revision"},{name:"date",type:"date",dateFormat:"Y/m/d H:i:s"},{name:"author"},{name:"content"}]})});ui.cmp._VCSLogGrid.sm=Ext.extend(Ext.grid.CheckboxSelectionModel,{singleSelect:false,header:"",width:22,listeners:{beforerowselect:function(d){var c=d.getCount();if(c===2){return false}return true},rowselect:function(d){var c=d.getCount();if(c===2){Ext.getCmp(d.prefix+"-PANEL-btn-log-"+d.fid).enable();Ext.get(d.prefix+"-PANEL-btn-log-"+d.fid).frame("3F8538")}else{Ext.getCmp(d.prefix+"-PANEL-btn-log-"+d.fid).disable()}},rowdeselect:function(d){var c=d.getCount();if(c===2){Ext.getCmp(d.prefix+"-PANEL-btn-log-"+d.fid).enable();Ext.get(d.prefix+"-PANEL-btn-log-"+d.fid).frame("3F8538")}else{Ext.getCmp(d.prefix+"-PANEL-btn-log-"+d.fid).disable()}}}});ui.cmp._VCSLogGrid.columns=[{id:"id",header:_("Rev."),width:40,sortable:false,dataIndex:"revision"},{header:_("Content"),width:130,sortable:true,dataIndex:"content"},{header:_("By"),width:50,sortable:true,dataIndex:"author"},{header:_("Date"),width:85,sortable:true,dataIndex:"date",renderer:Ext.util.Format.dateRenderer(_("Y-m-d, H:i"))}];ui.cmp.VCSLogGrid=Ext.extend(Ext.grid.GridPanel,{loadMask:true,autoScroll:true,bodyBorder:false,border:false,autoExpandColumn:"content",initComponent:function(){var f=new ui.cmp._VCSLogGrid.sm({fid:this.fid,prefix:this.prefix}),c=new ui.cmp._VCSLogGrid.store({autoLoad:this.loadStore,proxy:new Ext.data.HttpProxy({url:"./do/getLog"}),baseParams:{Path:this.fpath,File:this.fname},listeners:{scope:this,load:function(h,g){if(this.prefix==="FNU-EN"){Ext.getCmp("FNU-"+this.fid).panVCSEn=true;Ext.getCmp("main-panel").fireEvent("tabLoaded","FNU",this.fid)}if(this.prefix==="FNU-LANG"){Ext.getCmp("FNU-"+this.fid).panVCSLang=true;Ext.getCmp("main-panel").fireEvent("tabLoaded","FNU",this.fid)}if(this.prefix==="FE-EN"){Ext.getCmp("FE-"+this.fid).panVCSEn=true;Ext.getCmp("main-panel").fireEvent("tabLoaded","FE",this.fid)}if(this.prefix==="FE-LANG"){Ext.getCmp("FE-"+this.fid).panVCSLang=true;Ext.getCmp("main-panel").fireEvent("tabLoaded","FE",this.fid)}if(this.prefix==="FNR-EN"){Ext.getCmp("FNR-"+this.fid).panVCSEn=true;Ext.getCmp("main-panel").fireEvent("tabLoaded","FNR",this.fid)}if(this.prefix==="FNR-LANG"){Ext.getCmp("FNR-"+this.fid).panVCSLang=true;Ext.getCmp("main-panel").fireEvent("tabLoaded","FNR",this.fid)}if(this.prefix==="AF"){Ext.getCmp("AF-"+this.fid).panVCS=true;Ext.getCmp("main-panel").fireEvent("tabLoaded","AF",this.fid)}if(this.prefix==="PP"){Ext.getCmp("PP-"+this.fid).panVCS=true;Ext.getCmp("main-panel").fireEvent("tabLoaded","PP",this.fid)}}}}),e=[],d;e.push(f);for(d=0;d'+_("You must manually load this data.
Use the refresh button !")+"

"+_("(You can change this behavior by setting an option in the configuration window)")+"",deferEmptyText:false}),tbar:[{scope:this,id:this.prefix+"-PANEL-btn-refreshlog-"+this.fid,tooltip:_("Load/Refresh revisions"),iconCls:"iconRefresh",handler:function(){this.store.reload()}},{scope:this,id:this.prefix+"-PANEL-btn-log-"+this.fid,tooltip:_("View the diff"),iconCls:"iconViewDiff",disabled:true,handler:function(){var j=this.getSelectionModel().getSelections(),h=j[0].data.revision,g=j[1].data.revision;Ext.getBody().mask(' '+_("Finding the diff. Please, wait..."));XHR({params:{task:"getDiff",DiffType:"vcs",FilePath:this.fpath,FileName:this.fname,Rev1:h,Rev2:g},success:function(l){var m=Ext.util.JSON.decode(l.responseText),k;Ext.getBody().unmask();k=new Ext.Window({title:String.format(_("Diff between {0} & {1}"),h,g),width:650,height:350,resizable:false,modal:true,autoScroll:true,bodyStyle:"background-color: white; padding: 5px;",html:'
'+m.content+"
",buttons:[{text:_("Close"),handler:function(){k.close()}}]});k.show()}})}}]});ui.cmp.VCSLogGrid.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp");ui.cmp.ViewVCDiff=Ext.extend(Ext.Panel,{layout:"fit",title:_("Diff From VCS"),iconCls:"iconDiffView",collapsedIconCls:"iconDiffView",plugins:[Ext.ux.PanelCollapsedTitle],initComponent:function(){Ext.apply(this,{items:{id:this.prefix+"-diff-"+this.fid,xtype:"panel",layout:"fit",items:[new Ext.ux.IFrameComponent({id:"frame-"+this.prefix+"-diff-"+this.fid,url:String.format(PhDOE.app.conf.viewVcUrl,this.fpath+this.fname,this.rev1,this.rev2)})]}});ui.cmp.ViewVCDiff.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._WorkTreeGrid","ui.cmp._WorkTreeGrid.menu");ui.cmp._WorkTreeGrid.SetProgress=new Ext.util.DelayedTask(function(){new ui.task.SetFileProgressTask({idDB:this.node.attributes.idDB,progress:this.node.attributes.progress})});ui.cmp._WorkTreeGrid.menu.admin=function(c){Ext.apply(this,c);this.init();ui.cmp._WorkTreeGrid.menu.admin.superclass.constructor.call(this)};Ext.extend(ui.cmp._WorkTreeGrid.menu.admin,Ext.menu.Item,{init:function(){var c;switch(this.from){case"file":c=[{scope:this,iconCls:"iconSwitchLang",text:_("Change file's owner"),handler:function(){new ui.cmp.ChangeFileOwner({fileIdDB:this.node.attributes.idDB,fileFolder:this.folderNode.attributes.task,fileName:this.node.attributes.task,currentOwner:this.userNode.attributes.task})}},{scope:this,iconCls:"iconPageDelete",text:((this.node.attributes.type==="delete")?_("Cancel this deletion"):_("Clear this change")),handler:function(){new ui.task.ClearLocalChangeTask({ftype:this.node.attributes.type,fpath:this.folderNode.attributes.task,fname:this.node.attributes.task})}}];break;case"patch":c=[{scope:this,iconCls:"iconTrash",text:_("Delete this patch"),handler:function(){ui.task.DeletePatchTask({patchID:this.node.attributes.idDB})}}];break}Ext.apply(this,{text:_("Administrator menu"),iconCls:"iconAdmin",handler:function(){return false},menu:new Ext.menu.Menu({items:c})})}});ui.cmp._WorkTreeGrid.menu.commit=function(c){Ext.apply(this,c);this.init();ui.cmp._WorkTreeGrid.menu.commit.superclass.constructor.call(this)};Ext.extend(ui.cmp._WorkTreeGrid.menu.commit,Ext.menu.Item,{init:function(){Ext.apply(this,{text:_("Commit..."),iconCls:"iconCommitFileVcs",disabled:(PhDOE.user.isAnonymous),handler:function(){return false},menu:new Ext.menu.Menu({items:[{scope:this,text:_("...this file"),hidden:(this.from==="user"||this.from==="folder"||this.from==="patch"||this.from==="anonymousPatch"),iconCls:"iconCommitFileVcs",handler:function(){var c=[{fid:Ext.util.md5(this.folderNode.attributes.task+this.node.attributes.task),fpath:this.folderNode.attributes.task,fname:this.node.attributes.task,fdbid:this.node.attributes.idDB,ftype:this.node.attributes.type,fdate:Date.parseDate(this.node.attributes.last_modified,"Y-m-d H:i:s"),fby:this.userNode.attributes.task}];new ui.cmp.CommitPrompt({files:c}).show()}},{scope:this,text:_("...all files from this folder"),hidden:(this.from==="user"||this.from==="patch"||this.from==="anonymousPatch"),iconCls:"iconCommitFileVcs",handler:function(){var c=[];this.folderNode.cascade(function(d){if(d.attributes.type!=="folder"&&d.attributes.type!=="user"){c.push({fid:Ext.util.md5(this.folderNode.attributes.task+d.attributes.task),fpath:this.folderNode.attributes.task,fname:d.attributes.task,fdbid:d.attributes.idDB,ftype:d.attributes.type,fdate:Date.parseDate(d.attributes.last_modified,"Y-m-d H:i:s"),fby:this.userNode.attributes.task})}},this);new ui.cmp.CommitPrompt({files:c}).show()}},{scope:this,text:_("...all files from this patch"),hidden:(this.module!=="patches"||this.from==="user"),iconCls:"iconCommitFileVcs",handler:function(){var e=[],c="",d=false;if(this.from==="anonymousPatch"){c=this.patchNode.attributes.patchDescription+"\n\n-- \nProvided by "+this.patchNode.parentNode.attributes.task+" ("+this.patchNode.attributes.patchEmail+")";d=this.patchNode.attributes.idDB}this.patchNode.cascade(function(f){if(f.attributes.type!=="folder"&&f.attributes.type!=="user"&&f.attributes.type!=="patch"){e.push({fid:Ext.util.md5(f.parentNode.attributes.task+f.attributes.task),fpath:f.parentNode.attributes.task,fname:f.attributes.task,fdbid:f.attributes.idDB,ftype:f.attributes.type,fdate:Date.parseDate(f.attributes.last_modified,"Y-m-d H:i:s"),fby:this.userNode.attributes.task})}},this);new ui.cmp.CommitPrompt({files:e,defaultMessage:c,patchID:d}).show()}},{scope:this,text:_("...all files modified by me"),hidden:(this.from==="anonymousPatch"),iconCls:"iconCommitFileVcs",handler:function(){var c=[];this.userNode.cascade(function(d){if(d.attributes.type!=="folder"&&d.attributes.type!=="user"&&d.attributes.type!=="patch"){c.push({fid:Ext.util.md5(d.parentNode.attributes.task+d.attributes.task),fpath:d.parentNode.attributes.task,fname:d.attributes.task,fdbid:d.attributes.idDB,ftype:d.attributes.type,fdate:Date.parseDate(d.attributes.last_modified,"Y-m-d H:i:s"),fby:this.userNode.attributes.task})}},this);new ui.cmp.CommitPrompt({files:c}).show()}}]})})}});ui.cmp._WorkTreeGrid.menu.usersPatch=function(d){Ext.apply(this,d);var f=Ext.getCmp(this.menuID),e,c;if(!f.itemRendered){f.removeAll();f.doLayout();c=ui.cmp.PatchesTreeGrid.getInstance().getUserPatchesList();if(c){Ext.each(c,function(g){e=new Ext.menu.Item({id:Ext.id(),text:g.attributes.task,handler:function(){ui.task.MoveToPatch({patchID:g.attributes.idDB,patchName:g.attributes.task,nodesToAdd:f.nodesToAdd})}});f.add(e)},this)}else{e=new Ext.menu.Item({disabled:true,text:_("You have no patch currently. You must create one.")});f.add(e)}e=new Ext.menu.Item({text:_("Create a new patch"),iconCls:"iconAdd",handler:function(){var g=new ui.cmp.ManagePatchPrompt({title:_("Create a new patch"),nodesToAdd:f.nodesToAdd});g.show(this.el)}});f.add("-",e);f.doLayout();f.itemRendered=true}};ui.cmp._WorkTreeGrid.menu.users=function(c){Ext.apply(this,c);this.init();ui.cmp._WorkTreeGrid.menu.users.superclass.constructor.call(this)};Ext.extend(ui.cmp._WorkTreeGrid.menu.users,Ext.menu.Menu,{listeners:{show:function(){if(this.node.attributes.task===PhDOE.user.login){ui.cmp._WorkTreeGrid.menu.usersPatch({menuID:"usersPatchesMenu"})}}},init:function(){var d=[],c;this.node.cascade(function(e){if(e.attributes.type!=="user"&&e.attributes.type!=="folder"){d.push(e)}},this);c=(this.node.attributes.task===PhDOE.user.login)?[{text:_("Submit all files for review in patch:"),iconCls:"iconPendingPatch",handler:function(){return false},menu:new Ext.menu.Menu({id:"usersPatchesMenu",itemRendered:false,nodesToAdd:d})},{xtype:"menuseparator",hidden:(PhDOE.user.isAnonymous)},((!PhDOE.user.isAnonymous)?new ui.cmp._WorkTreeGrid.menu.commit({from:"user",node:false,folderNode:false,userNode:this.node}):"")]:[{scope:this,text:String.format(_("Send an email to {0}"),""+this.node.attributes.task+""),iconCls:"iconSendEmail",hidden:(this.node.attributes.email==="false"),handler:function(){var e=new ui.cmp.EmailPrompt();e.setData(this.node.attributes.task,this.node.attributes.email);e.show(this.node.el)}}];Ext.apply(this,{items:c})}});ui.cmp._WorkTreeGrid.menu.folders=function(c){Ext.apply(this,c);this.init();ui.cmp._WorkTreeGrid.menu.folders.superclass.constructor.call(this)};Ext.extend(ui.cmp._WorkTreeGrid.menu.folders,Ext.menu.Menu,{listeners:{show:function(){if(this.node.parentNode.attributes.task===PhDOE.user.login){ui.cmp._WorkTreeGrid.menu.usersPatch({menuID:"foldersPatchesMenu"})}}},init:function(){var c=[];if(this.node.parentNode.attributes.task!==PhDOE.user.login){return false}this.node.cascade(function(d){if(d.attributes.type!=="folder"){c.push(d)}},this);Ext.apply(this,{items:[{text:_("Submit all files in this directory in patch:"),iconCls:"iconPendingPatch",handler:function(){return false},menu:new Ext.menu.Menu({id:"foldersPatchesMenu",itemRendered:false,nodesToAdd:c})},{xtype:"menuseparator",hidden:(PhDOE.user.isAnonymous)},((!PhDOE.user.isAnonymous)?new ui.cmp._WorkTreeGrid.menu.commit({from:"folder",node:false,folderNode:this.node,userNode:this.node.parentNode}):"")]})}});ui.cmp._WorkTreeGrid.menu.files=function(c){Ext.apply(this,c);this.init();ui.cmp._WorkTreeGrid.menu.files.superclass.constructor.call(this)};Ext.extend(ui.cmp._WorkTreeGrid.menu.files,Ext.menu.Menu,{listeners:{show:function(){if(this.node.parentNode.parentNode.attributes.task===PhDOE.user.login){ui.cmp._WorkTreeGrid.menu.usersPatch({menuID:"filePatchesMenu"})}}},init:function(){var h=this.node,l=h.attributes.type,g,c=h.parentNode.attributes.task,e=h.attributes.task,k=h.ownerTree,f=h.parentNode.parentNode.attributes.task,d=[],j;j=h.parentNode.attributes.task.split("/");g=j[0];d.push(this.node);Ext.apply(this,{items:[{text:""+((l==="delete")?_("View in a new tab"):_("Edit in a new tab"))+"",iconCls:"iconEdit",handler:function(){k.openFile(h)}},{text:_("Submit as patch for review in:"),iconCls:"iconPendingPatch",hidden:(f!==PhDOE.user.login),handler:function(){return false},menu:new Ext.menu.Menu({id:"filePatchesMenu",itemRendered:false,nodesToAdd:d})},{text:_("Set the progress..."),iconCls:"iconProgress",hidden:(l==="delete"||f!==PhDOE.user.login),menu:{xtype:"menu",showSeparator:false,items:[{xtype:"slider",width:200,value:this.node.attributes.progress,increment:10,minValue:0,maxValue:100,plugins:new Ext.slider.Tip({getText:function(m){return String.format(""+_("{0}% complete")+"",m.value)}}),refreshNodeColumns:function(o){var x=o.getOwnerTree(),u=o.attributes,s=x.columns,m=o.ui.getEl().firstChild,y=m.childNodes,p,r,w,q;for(p=1,q=s.length;p1){for(var d=0;d1){f=new Ext.menu.Menu({listeners:{show:function(){ui.cmp._WorkTreeGrid.menu.usersPatch({menuID:"globalPatchesMenu"})}},items:[{text:_("Submit all this files for review in patch:"),iconCls:"iconPendingPatch",handler:function(){return false},menu:new Ext.menu.Menu({id:"globalPatchesMenu",itemRendered:false,nodesToAdd:l})}]});f.showAt(k.getXY());return}g=j.attributes.type;switch(g){case"user":j.select();f=new ui.cmp._WorkTreeGrid.menu.users({node:j});break;case"folder":j.select();f=new ui.cmp._WorkTreeGrid.menu.folders({node:j});break;default:j.select();f=new ui.cmp._WorkTreeGrid.menu.files({node:j});break}f.showAt(k.getXY())},initComponent:function(){function c(d,e){e.css+=" x-grid3-progresscol";return String.format('
{2}
',this.getStyle(d),(d/this.ceiling)*100,this.getText(d))}Ext.apply(this,{animate:true,useArrows:true,autoScroll:true,border:false,containerScroll:true,defaults:{autoScroll:true},selModel:new Ext.tree.MultiSelectionModel(),columns:[{header:_("Users"),dataIndex:"task",tpl:new Ext.XTemplate("{task:this.formatUserName}",{formatUserName:function(d,e){if(e.userID){e.qtip=_("userID: ")+e.userID}return d}})},{header:_("Last modified"),width:120,dataIndex:"last_modified",align:"center",tpl:new Ext.XTemplate("{last_modified:this.formatDate}",{formatDate:function(d,e){if(e.type!=="user"&&e.type!=="folder"){return Date.parseDate(d,"Y-m-d H:i:s").format(_("Y-m-d, H:i"))}else{return""}}})},{header:_("Estimated progress"),dataIndex:"progress",width:100,align:"center",tpl:new Ext.XTemplate("{progress:this.formatProgress}",{formatProgress:function(f,h){if(Ext.util.Format.substr(h,0,4)==="out:"){var g=h.split(":");f=g[1]}if(!f&&f!==0){return""}function e(k){var j=(k<(100/2))?"x-progress-text-back":"x-progress-text-front"+(Ext.isIE6?"-ie6":""),l;l=String.format('
{2}
',j,Ext.id(),k+"%");return(k<(100/1.05))?l.substring(0,l.length-6):l.substr(6)}function d(j){if(j<=100&&j>(100*0.67)){return"-green"}if(j<(100*0.67)&&j>(100*0.33)){return"-orange"}if(j<(100*0.33)){return"-red"}return""}return String.format('
{2}
',d(f),(f/100)*100,e(f))}})}],loader:{dataUrl:"./do/getWork",baseParams:{module:"workInProgress"}}});ui.cmp.WorkTreeGrid.superclass.initComponent.call(this);this.on("contextmenu",this.onContextMenu,this);this.on("resize",this.resizeCmp,this);this.on("dblclick",this.openFile,this);this.getRootNode().on("beforechildrenrendered",function(){this.updateFilesCounter.defer(200,this)},this)},resizeCmp:function(g,f,d,e){this.columns[0].width=e-(this.columns[1].width+this.columns[2].width+5);this.updateColumnWidths()},delRecord:function(m){var d=this.getRootNode(),g,e,k,c,l,f;for(g=0;gPlease delete these characters or change the header of the XML file in UTF-8 ; i.e.:

<?xml version="1.0" encoding="utf-8"?>
');break;case"tabs_found":d=_("Error");e=_('It seems that you have inserted some tabs caracters into this files. Please, replace each one by one space.
Tip: You can use the "Re-indent all this file" button to replace all tabs by spaces.');break;case"folder_already_exist":d=_("Error");e=_("This folder already exist in the current folder.");break;case"file_already_exist":d=_("Error");e=_("This file already exist in the current folder.");break;case"save_you_cant_modify_it":d=_("Error");e=_("You can't modify this file as it was modify by another user. Contact an administrator if you want to be able to modify it.");break;case"file_isnt_owned_by_current_user":d=_("Error");e=_("The file you want to clear local change isn't own by you.
You can only do this action for yours files.");break;case"file_localchange_didnt_exist":d=_("Error");e=_("The file you want to clear local change isn't exist as work in progress.");break;case"changeFilesOwnerNotAdmin":d=_("Error");e=_("You can't change file's owner. You must be a global administrator or an administrator for this lang.");break;case"patch_delete_dont_exist":d=_("Error");e=_("The patch you want to delete didn't exist.");break;case"patch_delete_isnt_own_by_current_user":d=_("Error");e=_("The patch you want to delete isn't own by you. Only the user how create it or a global administrator can delete it.");break;case"action_only_global_admin":d=_("Error");e=_("This action is available only to global administrator.");break;case"action_only_admin":d=_("Error");e=_("This action is available only to global administrator or to administrator for this lang.");break}Ext.MessageBox.alert(d,e)},runDirectAccess:function(){if(directAccess){if(directAccess.link=="perm"){ui.cmp.RepositoryTree.getInstance().openFile("byPath",directAccess.lang+directAccess.path,directAccess.name)}if(directAccess.link=="patch"){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",FilePath:directAccess.path,FileName:directAccess.name})}if(directAccess.link=="patchID"){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",patchID:directAccess.patchID,patchName:directAccess.patchName})}}},afterLoadAllStore:function(){this.app.loaded=true;this.runDirectAccess();if(this.user.conf.main.loadMailsAtStartUp){ui.cmp.PortletLocalMail.getInstance().reloadData()}if(this.user.conf.main.loadBugsAtStartUp){ui.cmp.PortletBugs.getInstance().reloadData()}PhDOE.setTopic();PhDOE.setTopic(true)},loadAllStore:function(){var e=new Ext.ProgressBar({width:300,renderTo:"loading-progressBar"}),c=[],d;if(PhDOE.user.lang!=="en"){c=[ui.cmp._MainMenu.store,ui.cmp.StaleFileGrid.getInstance().store,ui.cmp.ErrorFileGrid.getInstance().store,ui.cmp.PendingReviewGrid.getInstance().store,ui.cmp.NotInENGrid.getInstance().store,ui.cmp.PortletSummary.getInstance().store,ui.cmp.PortletTranslationGraph.getInstance().store,ui.cmp.PortletTranslationsGraph.getInstance().store,ui.cmp.PortletTranslator.getInstance().storeTranslator,ui.cmp.PortletTranslator.getInstance().storeReviewer,ui.cmp.PendingTranslateGrid.getInstance().store,ui.cmp.PortletInfo.getInstance().store]}else{c=[ui.cmp._MainMenu.store,ui.cmp.PortletTranslationsGraph.getInstance().store,ui.cmp.ErrorFileGrid.getInstance().store,ui.cmp.PortletInfo.getInstance().store]}d=function(f){e.updateProgress((f+1)/c.length,(f+1)+" of "+c.length+"...");c[f].load({callback:function(){f++;if(f  '+this.app.name+"",autoHeight:true,border:false,margins:"0 0 5 0"},{region:"west",id:"main-menu-panel",layout:"accordion",collapsible:true,collapseMode:"mini",animate:true,split:true,width:PhDOE.user.conf.main.mainMenuWidth||300,header:false,listeners:{resize:function(j,o){if(o&&o!=PhDOE.user.conf.main.mainMenuWidth){var m=new ui.task.UpdateConfTask({module:"main",itemName:"mainMenuWidth",value:o,notify:false})}}},tbar:[{text:_("Main menu"),iconCls:"MainMenu",menu:new ui.cmp.MainMenu()}],items:[{id:"acc-need-translate",title:_("Files need translate")+' (0)',layout:"fit",border:false,iconCls:"iconFilesNeedTranslate",hidden:(PhDOE.user.lang==="en"),items:[ui.cmp.PendingTranslateGrid.getInstance()],collapsed:true,listeners:{expand:function(j){Ext.getCmp("FNT-filter").wrap.setWidth(180);Ext.getCmp("FNT-filter").syncSize()}}},{id:"acc-need-update",title:_("Files need update")+' (0)',layout:"fit",border:false,iconCls:"iconFilesNeedUpdate",hidden:(PhDOE.user.lang==="en"),items:[ui.cmp.StaleFileGrid.getInstance()],collapsed:true,listeners:{expand:function(j){Ext.getCmp("FNU-filter").wrap.setWidth(180);Ext.getCmp("FNU-filter").syncSize()}}},{id:"acc-error",title:(PhDOE.user.lang==="en")?"Number of failures to meet 'strict standards' (0)":_("Error in current translation")+' (0)',layout:"fit",border:false,iconCls:"iconFilesError",items:[ui.cmp.ErrorFileGrid.getInstance()],collapsed:true,listeners:{expand:function(j){Ext.getCmp("FE-filter").wrap.setWidth(180);Ext.getCmp("FE-filter").syncSize()}}},{id:"acc-need-reviewed",title:_("Files need reviewed")+' (0)',layout:"fit",border:false,iconCls:"iconFilesNeedReviewed",hidden:(PhDOE.user.lang==="en"),items:[ui.cmp.PendingReviewGrid.getInstance()],collapsed:true,listeners:{expand:function(j){Ext.getCmp("FNR-filter").wrap.setWidth(180);Ext.getCmp("FNR-filter").syncSize()}}},{id:"acc-notInEn",title:_("Not in EN tree")+' (0)',layout:"fit",border:false,iconCls:"iconNotInEn",hidden:(PhDOE.user.lang==="en"),items:[ui.cmp.NotInENGrid.getInstance()],collapsed:true},{id:"acc-all-files",title:_("All files"),layout:"fit",border:false,iconCls:"iconAllFiles",items:[ui.cmp.RepositoryTree.getInstance()],collapsed:true,listeners:{expand:function(j){Ext.getCmp("AF-search").wrap.setWidth(180);Ext.getCmp("AF-search").syncSize()}}},{id:"acc-work-in-progress",title:_("Work in progress")+' (0)',layout:"fit",border:false,iconCls:"iconWorkInProgress",items:[ui.cmp.WorkTreeGrid.getInstance()],collapsed:true,tools:[{id:"refresh",qtip:_("Refresh"),handler:function(){ui.cmp.WorkTreeGrid.getInstance().getRootNode().reload()}}]},{id:"acc-patches",tools:[{id:"refresh",qtip:_("Refresh"),handler:function(){ui.cmp.PatchesTreeGrid.getInstance().getRootNode().reload()}},{id:"gear",hidden:(this.user.isAnonymous),qtip:_("Open the Log Message Manager"),handler:function(){if(!Ext.getCmp("commit-log-win")){var j=new ui.cmp.CommitLogManager()}Ext.getCmp("commit-log-win").show("acc-patches")}}],title:_("Patches for review")+' (0)',layout:"fit",border:false,iconCls:"iconPatch",items:[ui.cmp.PatchesTreeGrid.getInstance()],collapsed:true},{id:"acc-google-translate",title:_("Google translation"),layout:"fit",border:false,iconCls:"iconGoogle",hidden:(PhDOE.user.lang==="en"),items:[new ui.cmp.GoogleTranslationPanel()],collapsed:true}]},{xtype:"mainpanel",id:"main-panel",region:"center",items:[{xtype:"panel",id:"MainInfoTabPanel",title:_("Home"),baseCls:"MainInfoTabPanel",autoScroll:true,plain:true,items:[{xtype:"container",layout:"column",border:false,items:[{xtype:"container",columnWidth:0.5,html:'

'+_("Connected as")+' , '+_("Project: ")+''+PhDOE.project+", "+_("Language: ")+' -

',listeners:{afterrender:function(m){var j="",p="",o;o=Ext.get("loginLibel");if(PhDOE.user.isGlobalAdmin||PhDOE.user.isLangAdmin){o.addClass("userAdmin");p=' '+PhDOE.user.login}else{if(PhDOE.user.authService=="VCS"){p=' '+PhDOE.user.login}else{if(PhDOE.user.authService=="google"){p=' '+PhDOE.user.login}else{if(PhDOE.user.authService=="facebook"){p=' '+PhDOE.user.login}}}}o.dom.innerHTML=p;content=_("Connected using")+" "+PhDOE.user.authService+"
";content+=(PhDOE.user.isGlobalAdmin)?_("You are a global Administrator")+"
":"";content+=(PhDOE.user.isLangAdmin)?_("You are an administrator for this language")+"
":"";new Ext.ToolTip({target:"loginLibel",anchor:"top",html:content})}}},{xtype:"container",columnWidth:0.5,html:'

'+_("Topic:")+'

-

-

-'+_("Topic:")+'

-

-
',listeners:{afterrender:function(m){if(PhDOE.user.isAnonymous){return}var j=function(q){var o="topic-info-content"+(q?"-lang":""),p=Ext.get(o).dom.innerHTML;Ext.get(o).dom.innerHTML="";new Ext.FormPanel({renderTo:o,layout:"anchor",border:false,items:[{xtype:"htmleditor",value:p,anchor:"100%"}],buttonAlign:"center",buttons:[{text:_("Save"),handler:function(){PhDOE.saveTopic(this.ownerCt.ownerCt.items.items[0].getValue(),q)}},{text:_("Cancel"),handler:function(){PhDOE.setTopic(q)}}]})};Ext.get("topic-info-container").on("dblclick",function(){j()});Ext.get("topic-info-container-lang").on("dblclick",function(){j(true)})}}}]},{xtype:"portal",border:false,items:[{columnWidth:0.5,style:"padding:10px 5px 10px 5px",items:d},{columnWidth:0.5,style:"padding:10px 5px 10px 5px",items:g}],listeners:{drop:function(o){var m,q=[],s=[],t;for(var r=0;r','
','
','','','','","","
','
',this.enableHdMenu?'':"",'{header}',"
","
","
","
",'
','
',"
")}if(!this.colgroupTpl){this.colgroupTpl=new Ext.XTemplate('')}},initColumns:function(){var g=this.columns,d=g.length,f=[],e,h;for(e=0;e10)){this.setScrollOffset(c)}else{var f=this;setTimeout(function(){f.setScrollOffset(g.offsetWidth-g.clientWidth>10?c:0)},10)}}},updateColumnWidths:function(){var m=this.columns,p=m.length,d=this.outerCt.query("colgroup"),o=d.length,l,h,f,e;for(f=0;f0&&this.columns[c]){this.setColumnVisible(c,!d.checked)}}return true},setColumnVisible:function(c,d){this.columns[c].hidden=!d;this.updateColumnWidths()},scrollToTop:function(){this.innerBody.dom.scrollTop=0;this.innerBody.dom.scrollLeft=0},syncScroll:function(){this.syncHeaderScroll();var c=this.innerBody.dom;this.fireEvent("bodyscroll",c.scrollLeft,c.scrollTop)},syncHeaderScroll:function(){var c=this.innerBody.dom;this.innerHd.dom.scrollLeft=c.scrollLeft;this.innerHd.dom.scrollLeft=c.scrollLeft},registerNode:function(c){Ext.ux.tree.TreeGrid.superclass.registerNode.call(this,c);if(!c.uiProvider&&!c.isRoot&&!c.ui.isTreeGridNodeUI){c.ui=new Ext.ux.tree.TreeGridNodeUI(c)}}});Ext.reg("treegrid",Ext.ux.tree.TreeGrid);Ext.override(Ext.ux.tree.TreeGrid,{onResize:function(d,f){Ext.ux.tree.TreeGrid.superclass.onResize.apply(this,arguments);var j=this.innerBody.dom;var k=this.innerHd.dom;if(!j){return}if(Ext.isNumber(f)){j.style.height=this.body.getHeight(true)-24+"px"}if(Ext.isNumber(d)){if(Ext.isIE&&!(Ext.isStrict&&Ext.isIE8)){var e=this.body.getWidth(true)+"px";j.style.width=e;k.style.width=e}var c=Ext.num(this.scrollOffset,Ext.getScrollBarWidth());if(this.reserveScrollOffset||((j.offsetWidth-j.clientWidth)>10)){this.setScrollOffset(c)}else{var g=this;setTimeout(function(){g.setScrollOffset(j.offsetWidth-j.clientWidth>10?c:0)},10)}}}});Ext.ux.DblClickCloseTabs=Ext.extend(Object,{init:function(c){this.panel=c;c.initEvents=c.initEvents.createSequence(this.initEvents,this)},initEvents:function(){this.panel.mon(this.panel.strip,{dblclick:this.onDblClick.createDelegate(this,[this.panel],0)});delete this.panel},onDblClick:function(c,d){if(c.getActiveTab().closable){c.remove(c.getActiveTab())}}});Ext.preg("dblclickclosetabs",Ext.ux.DblClickCloseTabs);Ext.util.md5=function(u,c,q,m){c=(typeof c==="undefined"?false:c);q=(typeof q==="undefined"?false:q);m=(typeof m==="undefined"?8:m);function k(r,w){var v=((r&65535)+(w&65535)),s=((r>>16)+(w>>16)+(v>>16));return(s<<16)|(v&65535)}function p(r,s){return(r<>>(32-s))}function f(A,w,v,r,z,y){return k(p(k(k(w,A),k(r,y)),z),v)}function l(w,v,B,A,r,z,y){return f((v&B)|((~v)&A),w,v,r,z,y)}function e(w,v,B,A,r,z,y){return f((v&A)|(B&(~A)),w,v,r,z,y)}function o(w,v,B,A,r,z,y){return f(v^B^A,w,v,r,z,y)}function j(w,v,B,A,r,z,y){return f(B^(v|(~A)),w,v,r,z,y)}function h(E,z){var D=1732584193,C=-271733879,B=-1732584194,A=271733878,v,y,w,s,r;E[z>>5]|=128<<((z)%32);E[(((z+64)>>>9)<<4)+14]=z;for(v=0;v>5]|=(w.charCodeAt(s/m)&r)<<(s%32)}return v}function g(v){var w="",r=((1<>5]>>>(s%32))&r)}return w}function t(v){var s=((q)?"0123456789ABCDEF":"0123456789abcdef"),w="",r;for(r=0;r>2]>>((r%4)*8+4))&15)+s.charAt((v[r>>2]>>((r%4)*8))&15)}return w}return(c?g(h(d(u),u.length*m)):t(h(d(u),u.length*m)))};Ext.ux.CodeMirror=Ext.extend(Ext.BoxComponent,{lineWrapping:false,previousLine:false,readOnly:false,originalContent:false,documentDurty:false,mode:(this.parser||"xml"),theme:(this.theme==="undefined")?"default":this.theme,initComponent:function(){this.initialized=false;Ext.ux.CodeMirror.superclass.initComponent.apply(this,arguments);this.theme=(Ext.isDefined(this.theme))?this.theme:"default";switch(this.mode){case"html":case"htm":this.mode="text/html";break;case"css":this.mode="text/css";break;case"php":this.mode="application/x-httpd-php";break;case"xml":case"ent":this.mode={name:"xml",alignCDATA:true};break;case"bat":this.mode="text/x-clojure";break;case"README":this.mode="text/x-rst";break;default:this.mode={name:"xmlpure"};break}this.addEvents("initialize");this.addEvents("codemodified");this.addEvents("coderestored");this.addEvents("cursormove");this.addEvents("scroll");this.ownerCt.on("resize",function(f,e,d){this.fireEvent("resize",this,e,d)},this);this.on({resize:function(e,d,c){this.resize(d,c)},afterrender:function(){var c=this;c.codeEditor=new CodeMirror(Ext.get(c.id),{theme:c.theme,readOnly:false,mode:c.mode,lineNumbers:true,matchBrackets:true,lineWrapping:c.lineWrapping,indentUnit:1,tabMode:"indent",value:"",onScroll:function(){c.fireEvent("scroll",c.el.child(".CodeMirror-scroll").dom.scrollTop)},onKeyEvent:function(g,d){if(d.ctrlKey&&d.keyCode==83){d.preventDefault();c.onSave()}var f=g.getCursor();c.fireEvent("cursormove",f.line,f.ch)},onCursorActivity:function(e){var d=e.getCursor();if(c.previousLine!==false){e.setLineClass(c.previousLine,null)}c.previousLine=e.setLineClass(d.line,"cm2-activeline");c.fireEvent("cursormove",d.line,d.ch)},onChange:function(d){c.manageCodeChange()}});c.initialized=true;c.fireEvent("initialize",true)}})},focus:function(){if(this.initialized){return this.codeEditor.focus()}return this.initialConfig.value},getCursor:function(){return this.codeEditor.getCursor()},getLine:function(c){return this.codeEditor.getLine(c)},getValue:function(){if(this.initialized){return this.codeEditor.getValue()}return this.initialConfig.value},insertLine:function(d,e){var c=this.codeEditor.getLine(d);this.codeEditor.setLine(d,c+"\n"+e)},manageCodeChange:function(){var c=this.originalContent,d=this.getValue();btnUndo=Ext.getCmp(this.id+"-btn-undo");if(c){if(c===d){if(this.documentDurty===true){this.fireEvent("coderestored");this.documentDurty=false}}else{if(btnUndo){btnUndo.enable()}if(this.documentDurty===false){this.fireEvent("codemodified");this.documentDurty=true}}}},onSave:function(){var c=Ext.getCmp(this.id+"-btn-save");if(!c.disabled){c.handler.call(c.scope||c,c)}},redo:function(c,d){this.codeEditor.redo();Ext.getCmp(this.id+"-btn-undo").enable();if(this.codeEditor.historySize().redo==0){Ext.getCmp(this.id+"-btn-redo").disable()}},resize:function(f,c){var e=this.el,d=e.child(".CodeMirror-scroll");d.setHeight(c-89)},removeLine:function(c){return this.codeEditor.removeLine(c)},reIndentAll:function(){var d=this.codeEditor.lineCount(),c;for(c=0;c','',"{cells}","
","");this.rowTpl.disableFormats=true}this.rowTpl.compile();if(!this.cellTpl){this.cellTpl=new Ext.Template('','
{value}
',"");this.cellTpl.disableFormats=true}this.cellTpl.compile()},calculate:function(e,o){var g={},m=o.config,h,d,k,f,c,l,p;for(h=0,l=m.length;h '+_("Loading..."));var e=document.createElement("iframe"),f=function(g){d.unmask()};e.id=this.id;e.name=this.id;e.src=this.url;e.frameBorder=0;this.el=d.appendChild(e);if(Ext.isIE){document.frames[this.url].name=this.id}e[Ext.isIE?"onreadystatechange":"onload"]=f.createDelegate(e)}});Ext.ux.FixedMultiSelectionModel=Ext.extend(Ext.tree.MultiSelectionModel,{normalClick:false,init:function(c){this.tree=c;c.getTreeEl().on("keydown",this.onKeyDown,this);c.on("dblclick",this.onDoubleClick,this);c.on("click",this.onNodeClick,this)},onDrag:function(){this.normalClick=false},onNodeClick:function(c,d){if(d.shiftKey){d.preventDefault()}if(!this.tree.dragZone||!this.tree.dragZone.isMultiSelect){this.onMouseDown(c,d);this.onMouseUp(c,d)}},onMouseDown:function(c,d){if(c.isSelected()){if(d.ctrlKey){this.unselect(c);this.normalClick=false;return}this.normalClick=!d.shiftKey}else{this.select(c,d,d.ctrlKey);this.normalClick=false}},onMouseUp:function(c,d){if(this.normalClick){this.select(c,d,d.ctrlKey);this.normalClick=false}},onDoubleClick:function(){this.normalClick=false},compareNodeOrder:document.compareDocumentPosition?function(d,c){return 3-(d.ui.elNode.compareDocumentPosition(c.ui.elNode)&6)}:(typeof document.documentElement.sourceIndex!=="undefined"?function(d,c){return d.ui.elNode.sourceIndex-c.ui.elNode.sourceIndex}:function(f,e){if(f==e){return 0}var d=document.createRange();d.selectNode(a.ui.elNode);d.collapse(true);var c=document.createRange();c.selectNode(b.ui.elNode);c.collapse(true);return d.compareBoundaryPoints(Range.START_TO_END,c)}),sortSelNodes:function(){if(this.selNodes.length>1){if(!this.selNodes[0].ui.elNode){return}this.selNodes.sort(this.compareNodeOrder)}},selectNode:function(d,c){if(!this.isSelected(d)){this.selNodes.push(d);this.selMap[d.id]=d;d.ui.onSelectedChange(true)}},select:function(d,h,m){if(d instanceof Array){for(var j=0;j0){this.lastSelNode=this.lastSelNode||this.selNodes[0];var k=this.compareNodeOrder(this.lastSelNode,d)>0;this.clearSelections(true);var o=true;var f=false;var l=this.lastSelNode;do{for(var g=l;g!=null;g=(k?g.previousSibling:g.nextSibling)){f=f||(k&&(g==d||g.contains(d)));if(g.isExpanded()){g.cascade(function(c){if(o!=f){this.selectNode(c)}o=(o&&c!=d);return true},this)}else{this.selectNode(g);o=(g!=d)}if(!o){break}}if(!o){break}while((l=l.parentNode)!=null){if(k){this.selectNode(l)}o=(o&&l!=d);if(k&&l.previousSibling){l=l.previousSibling;break}if(!k&&l.nextSibling){l=l.nextSibling;break}}if(!o){break}}while(l!=null);this.selectNode(d);this.sortSelNodes();this.fireEvent("selectionchange",this,this.selNodes,d);h.preventDefault();return d}else{if(m!==true){this.clearSelections(true)}}if(this.isSelected(d)){if(m===true){this.unselect(d);if(this.lastSelNode===d){this.lastSelNode=this.selNodes[0]}return d}this.lastSelNode=d;return d}this.selectNode(d);this.sortSelNodes();this.lastSelNode=d;this.fireEvent("selectionchange",this,this.selNodes,this.lastSelNode);return d},getUniqueSelectedNodes:function(){var d=[];for(var f=0;f=0;f--){if(this.selNodes[f].isAncestor(d)){Ext.ux.FixedMultiSelectionModel.superclass.unselect.call(this,this.selNodes[f])}}}return Ext.ux.FixedMultiSelectionModel.superclass.unselect.call(this,d)},selectPrevious:function(e){var c=this.selNodes[0];if(!c){return null}var f=c.previousSibling;if(f){if(!f.isExpanded()||f.childNodes.length<1){return this.select(f,null,e)}else{var d=f.lastChild;while(d&&d.isExpanded()&&d.childNodes.length>0){d=d.lastChild}return this.select(d,null,e)}}else{if(c.parentNode&&(this.tree.rootVisible||!c.parentNode.isRoot)){return this.select(c.parentNode,null,e)}}return null},selectNext:function(e){var d=this.selNodes[this.selNodes.length-1];if(!d){return null}if(d.firstChild&&d.isExpanded()){return this.select(d.firstChild,null,e)}else{if(d.nextSibling){return this.select(d.nextSibling,null,e)}else{if(d.parentNode){var c=null;d.parentNode.bubble(function(){if(this.nextSibling){c=this.getOwnerTree().selModel.select(this.nextSibling,null,e);return false}});return c}}}return null},onKeyDown:function(f){var d=this.selNode||this.lastSelNode;var g=this;if(!d){return}var c=f.getKey();switch(c){case f.DOWN:f.stopEvent();this.selectNext(f.shiftKey||f.ctrlKey);break;case f.UP:f.stopEvent();this.selectPrevious(f.shiftKey||f.ctrlKey);break;case f.RIGHT:f.preventDefault();if(d.hasChildNodes()){if(!d.isExpanded()){d.expand()}else{if(d.firstChild){this.select(d.firstChild,f,f.shiftKey||f.ctrlKey)}}}break;case f.LEFT:f.preventDefault();if(d.hasChildNodes()&&d.isExpanded()){d.collapse()}else{if(d.parentNode&&(this.tree.rootVisible||d.parentNode!=this.tree.getRootNode())){this.select(d.parentNode,f,f.shiftKey||f.ctrlKey)}}break}}});Ext.ux.MultiSelectTreeDragZone=Ext.extend(Ext.tree.TreeDragZone,{isMultiSelect:true,onBeforeDrag:function(d,f){if(d.nodes&&d.nodes.length>0){for(var g=0;g0){var w=Ext.query(h[k].ui.indentNode.nodeName+".x-tree-node-indent",v);for(var s=0,t=w.length;s=r&&k<(r+c)&&this.isValidDropPoint(g,"above",o,j,h)){return"above"}else{if(!f&&(m||k>=l-c&&k<=l)&&this.isValidDropPoint(g,"below",o,j,h)){return"below"}}}return m?false:"append"},onNodeOver:function(d,k,j,h){var m=this.getDropPoint(j,d,k,h);var f=d.node;if(!this.expandProcId&&m=="append"&&f.hasChildNodes()&&!d.node.isExpanded()){this.queueExpand(f)}else{if(m!="append"){this.cancelExpand()}}var g=this.dropNotAllowed;if(m){var c=d.ddel;var l;if(m=="above"){g=d.node.isFirst()?"x-tree-drop-ok-above":"x-tree-drop-ok-between";l="x-tree-drag-insert-above"}else{if(m=="below"){g=d.node.isLast()?"x-tree-drop-ok-below":"x-tree-drop-ok-between";l="x-tree-drag-insert-below"}else{g="x-tree-drop-ok-append";l="x-tree-drag-append"}}if(this.lastInsertClass!=l){Ext.fly(c).replaceClass(this.lastInsertClass,l);this.lastInsertClass=l}}return g},onNodeDrop:function(f,m,h,g){var l=this.getDropPoint(h,f,m,g);var j=f.node;j.ui.startDrop();if(l===false){j.ui.endDrop();return false}var k=g.node||(m.getTreeNode?m.getTreeNode(g,j,l,h):null);var d={tree:this.tree,target:j,data:g,point:l,source:m,rawEvent:h,dropNode:k,cancel:!k,dropStatus:false};var c=this.tree.fireEvent("beforenodedrop",d);if(c===false||d.cancel===true||!d.dropNode){j.ui.endDrop();return d.dropStatus}j=d.target;if(l=="append"&&!j.isExpanded()){j.expand(false,null,function(){this.completeDrop(d)}.createDelegate(this))}else{this.completeDrop(d)}return true},afterRepair:function(f){if(f&&Ext.enableFx){var e=f.nodes?f.nodes:[f.node];for(var g=0,d=e.length;g-1){this.pos++}Ext.ux.NotificationMgr.positions.push(this.pos);this.setSize(200,100);this.el.alignTo(document,"br-br",[-20,-20-((this.getSize().height+10)*this.pos)]);this.el.slideIn("b",{duration:1,callback:this.afterShow,scope:this})},animHide:function(){Ext.ux.NotificationMgr.positions.remove(this.pos);this.el.shadow.hide();this.el.ghost("b",{duration:1,remove:false,callback:function(){Ext.ux.NotificationMgr.positions.remove(this.pos);this.destroy()}.createDelegate(this)})},focus:Ext.emptyFn});Ext.ns("Ext.ux");Ext.ux.PanelCollapsedTitle=(function(){var c="x-panel-header-rotated";var e=!!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1");var d=function(){var k=((this.region=="east")||(this.region=="west"));var l="overflow: visible; padding: 0; border: none; background: none;";if(k&&e){this.collapsedHeader=this.ownerCt.layout[this.region].getCollapsedEl().createChild({tag:"div",style:"height: 100%; overflow: hidden;"});var j="http://www.w3.org/2000/svg";var h=document.createElementNS(j,"svg");this.collapsedHeader.dom.appendChild(h);h.setAttribute("width","100%");h.setAttribute("height","100%");var m=document.createElementNS(j,"text");m.setAttribute("x",6);m.setAttribute("y",1);m.setAttribute("transform","rotate(90 6 1)");m.setAttribute("class","x-panel-header "+c);h.appendChild(m);this.collapsedHeaderText=document.createTextNode(this.title);m.appendChild(this.collapsedHeaderText);var g=Ext.fly(m).getStyle("color");m.setAttribute("style",l+";fill: "+g+";")}else{var f="position: relative;";if(k){f+="white-space: nowrap; writing-mode: tb-rl; top: 1px; left: 3px;"}else{f+="top: 2px;";l+="padding-left: 4px; margin-right: 18px;"}this.collapsedHeader=this.ownerCt.layout[this.region].getCollapsedEl().createChild({tag:"div",style:l,cls:"x-panel-header "+c,html:''+this.title+""});this.collapsedHeaderText=this.collapsedHeader.first()}if(this.collapsedIconCls){this.setCollapsedIconClass(this.collapsedIconCls)}};this.init=function(g){if(g.collapsible){var f=((g.region=="east")||(g.region=="west"));g.setTitle=Ext.Panel.prototype.setTitle.createSequence(function(h){if(this.rendered&&this.collapsedHeaderText){if(this.collapsedHeaderText.dom){this.collapsedHeaderText.dom.innerHTML=h}else{if(this.collapsedHeaderText.replaceData){this.collapsedHeaderText.nodeValue=h}}}});g.setCollapsedIconClass=function(j){var h=this.collapsedIconCls;this.collapsedIconCls=j;if(this.rendered&&this.collapsedHeader){var l=this.collapsedHeader,k=l.child("img.x-panel-inline-icon");if(k){if(this.collapsedIconCls){Ext.fly(k).replaceClass(h,this.collapsedIconCls)}else{Ext.fly(k).remove()}}else{if(this.collapsedIconCls){Ext.DomHelper.insertBefore(l.dom.firstChild,{tag:"img",src:Ext.BLANK_IMAGE_URL,cls:"x-panel-inline-icon "+this.collapsedIconCls,style:f?"display: block; margin: 1px 2px;":"margin-top: 2px; margin-right: 4px"})}}}};g.on("render",function(){if(this.ownerCt.rendered&&this.ownerCt.layout.hasLayout){d.call(g)}else{this.ownerCt.on("afterlayout",d,g,{single:true})}},g)}};return this})();Ext.ux.SlidingTabPanel=Ext.extend(Ext.TabPanel,{initTab:function(d,c){Ext.ux.SlidingTabPanel.superclass.initTab.call(this,d,c);this.addEvents({startDrag:true,endDrag:true});var e=this.getTemplateArgs(d);if(!this.slidingTabsID){this.slidingTabsID=Ext.id()}new Ext.ux.DDSlidingTab(e,this.slidingTabsID,{tabpanel:this})}});Ext.ux.DDSlidingTab=Ext.extend(Ext.dd.DDProxy,{constructor:function(){Ext.ux.DDSlidingTab.superclass.constructor.apply(this,arguments);this.setYConstraint(0,0,0);this.tabpanel=this.config.tabpanel;this.slideDuration=this.tabpanel.slideDuration;if(!this.slideDuration){this.slideDuration=0.1}},handleMouseDown:function(f,d){if(this.primaryButtonOnly&&f.button!=0){return}if(this.isLocked()){return}this.DDM.refreshCache(this.groups);var c=new Ext.lib.Point(Ext.lib.Event.getPageX(f),Ext.lib.Event.getPageY(f));if(!this.hasOuterHandles&&!this.DDM.isOverTarget(c,this)){}else{if(this.clickValidator(f)){this.setStartPosition();this.b4MouseDown(f);this.onMouseDown(f);this.DDM.handleMouseDown(f,this)}}},startDrag:function(c,k){this.tabpanel.fireEvent("startDrag",this.tabpanel,this.tabpanel.getActiveTab());Ext.dd.DDM.useCache=false;Ext.dd.DDM.mode=1;this.proxyWrapper=Ext.get(this.getDragEl());this.proxyWrapper.update();this.proxyWrapper.applyStyles("z-index:1001;border:0 none;");this.proxyWrapper.addClass("tab-proxy");this.stripWrap=this.proxyWrapper.insertHtml("afterBegin",'
',true);this.dragEl=this.stripWrap.insertHtml("afterBegin","
",true);this.tab=Ext.get(this.getEl());this.tab.applyStyles("visibility:hidden;");this.dragEl.insertHtml("afterBegin",this.tab.dom.innerHTML,false);this.dragEl.dom.className=this.tab.dom.className;var j=this.tabpanel.el.getWidth();var g=this.tabpanel.el.getX();var h=this.tab.getX();var d=this.tab.getWidth();var f=h-g;var e=g+j-h-d;this.resetConstraints();this.setXConstraint(f,e)},onDragOver:function(f,j){f.stopEvent();var g=Ext.get(j[0].id);var l=g.getWidth();var k=g.getX();var h=k+(l/2);var d=this.tab.getX();var m=this.proxyWrapper.getX();var c=this.proxyWrapper.getWidth();if(mh)){if(g.next()!=this.tab){g.applyStyles("visibility:hidden;");this.tab.insertAfter(g);this.targetProxy=this.createSliderProxy(k,g);if(!this.targetProxy.hasActiveFx()){this.animateSliderProxy(g,this.targetProxy,d)}}}if(m>k&&(m',true);e.stripWrapper=e.insertHtml("afterBegin",'
',true);e.dragEl=e.stripWrapper.insertHtml("afterBegin","
",true);e.dragEl.update(f.dom.innerHTML);e.dragEl.dom.className=f.dom.className;var c=parseInt(f.getTop(false));e.setTop(c);return e},onDragDrop:function(d,c){d.stopEvent()},endDrag:function(c){var d=this.tab.getX();this.proxyWrapper.applyStyles("visibility:visible;");this.proxyWrapper.shift({x:d,easing:"easeOut",duration:this.slideDuration,callback:function(){this.proxyWrapper.applyStyles("visibility:hidden;");this.tab.applyStyles("visibility:visible;");this.stripWrap.remove();this.dragEl.remove();if(!this.targetProxy){return}this.targetProxy.stripWrapper.remove();this.targetProxy.dragEl.remove()},scope:this});Ext.dd.DDM.useCache=true;this.reorderTab();this.tabpanel.fireEvent("endDrag",this.tabpanel,this.tabpanel.getActiveTab())},reorderTab:function(){var e=this.tabpanel.header.child("ul").dom.children,c=[],f=[];for(var d=0;d{0})"),text:String.format(_("Notes ({0})"),"-"),initComponent:function(){Ext.ux.UserNotes.superclass.initComponent.apply(this);Ext.apply(this,{iconCls:"iconUserNotes",id:this.fid+"-userNotes",menu:new Ext.menu.Menu({showSeparator:false,allowOtherMenus:true,plain:true,autoHeight:true,forceLayout:true,enableScrolling:false,items:[{xtype:"grid",loadMask:true,width:500,height:200,contextMenuFrom:false,contextMenuRowIndex:false,sm:new Ext.grid.RowSelectionModel({singleSelect:true}),winNotes:new Ext.Window({scope:this,title:_("Add a new note"),iconCls:"iconUserNotes",closeAction:"hide",width:600,height:300,layout:"form",hideLabel:true,modal:true,items:[{xtype:"htmleditor",hideLabel:true,enableLinks:false,anchor:"100%"}],listeners:{show:function(c){c.items.items[0].setValue("")}},buttons:[{text:_("Add"),handler:function(){var e=this.ownerCt.ownerCt.scope,f=this.ownerCt.ownerCt;e.menu.show(e.el);var d=this.ownerCt.ownerCt.items.items[0].getValue();var c=e.file;XHR({scope:this,params:{task:"addUserNote",file:c,note:d},success:function(){f.hide();e.menu.items.items[0].store.reload();PhDOE.notify("info",_("Note added"),_("The note was added successfully !"))},failure:function(){PhDOE.winForbidden()}})}},{text:_("Cancel"),handler:function(){var c=this.ownerCt.ownerCt.scope;c.menu.show(c.el);this.ownerCt.ownerCt.hide()}}]}),contextMenu:new Ext.menu.Menu({scope:this,listeners:{show:function(c){if(this.scope.menu.items.items[0].contextMenuFrom==="containercontextmenu"){this.items.items[2].disable()}else{var d=this.scope.menu.items.items[0];var e=d.store.getAt(d.contextMenuRowIndex).data.user;if(PhDOE.userLogin==e){this.items.items[2].enable()}else{this.items.items[2].disable()}}if(PhDOE.userLogin=="anonymous"){this.items.items[0].disable();this.items.items[2].disable()}}},items:[{text:_("Add a new note"),iconCls:"iconUserNotes",handler:function(){var c=this.ownerCt.scope.menu.items.items[0];c.winNotes.show()}},"-",{text:_("Delete this note"),iconCls:"iconDelete",handler:function(){var d=this.ownerCt.scope.menu.items.items[0],c=d.store.getAt(d.contextMenuRowIndex).data.id;XHR({scope:this,params:{task:"delUserNote",noteID:c},success:function(e){var f=Ext.util.JSON.decode(e.responseText);d.store.reload();if(f.result){PhDOE.notify("info",_("Note deleted"),_("The note was deleted successfully !"))}},failure:function(){PhDOE.winForbidden()}})}},"-",{text:_("Reload data"),iconCls:"iconRefresh",handler:function(){var c=this.ownerCt.scope.menu.items.items[0];c.store.reload()}}]}),store:new Ext.data.Store({autoLoad:true,proxy:new Ext.data.HttpProxy({url:"./do/getUserNotes"}),baseParams:{file:this.file},reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"user"},{name:"note"},{name:"date",type:"date",dateFormat:"Y-m-d H:i:s"}]}),sortInfo:{field:"date",direction:"DESC"},listeners:{scope:this,datachanged:function(d){var c=d.getCount();this.setText(String.format(this.originalTitle,c))}}}),listeners:{scope:this,rowclick:function(c){if(!c.contextMenu.hidden){c.contextMenu.hide()}},containercontextmenu:function(d,f){f.stopEvent();d.getSelectionModel().clearSelections();d.contextMenuFrom="containercontextmenu";d.contextMenu.showAt(f.getXY());this.menu.show(this.el);var c=this.menu.el.zindex+2000;d.contextMenu.el.setStyle("z-index",c)},rowcontextmenu:function(d,g,f){f.stopEvent();d.getSelectionModel().selectRow(g);d.contextMenuFrom="rowcontextmenu";d.contextMenuRowIndex=g;d.contextMenu.showAt(f.getXY());this.menu.show(this.el);var c=this.menu.el.zindex+2000;d.contextMenu.el.setStyle("z-index",c)}},colModel:new Ext.grid.ColumnModel({defaults:{sortable:true},columns:[{id:"user",header:_("By"),sortable:true,dataIndex:"user"},{header:_("Date"),dataIndex:"date",renderer:Ext.util.Format.dateRenderer(_("Y-m-d, H:i"))}]}),autoExpandColumn:"user",viewConfig:{forceFit:true,deferEmptyText:false,emptyText:'
'+_("No user notes")+"

"+_("Right click to add a new note")+"
",enableRowBody:true,getRowClass:function(c,e,d){d.body='

'+c.data.note+"

";return"x-grid3-row-expanded"}}}]})})}});Ext.reg("usernotes",Ext.ux.UserNotes);Ext.namespace("ui","ui.task");ui.task.ChangeFileOwner=function(c){Ext.apply(this,c);var d=Ext.MessageBox.wait(_("Saving data..."));XHR({scope:this,params:{task:"setFileOwner",fileIdDB:this.fileIdDB,newOwnerID:this.newOwnerID},success:function(e){var f=Ext.util.JSON.decode(e.responseText);ui.cmp.WorkTreeGrid.getInstance().getRootNode().reload(function(){ui.cmp.PatchesTreeGrid.getInstance().getRootNode().reload()});ui.cmp.PortletInfo.getInstance().store.reload();d.hide();if(Ext.isDefined(this.fromType)&&this.fromType==="tab"){Ext.getCmp("main-panel").remove(this.from.curTab)}this.from.close();PhDOE.notify("info",_("Owner changed"),_("The owner for this file have been changed successfully !"))},failure:function(e){var f=Ext.util.JSON.decode(e.responseText);d.hide();PhDOE.winForbidden(f.type);if(Ext.isDefined(this.fromType)&&this.fromType==="tab"){Ext.getCmp("main-panel").remove(this.from.curTab)}this.from.close()}})};Ext.namespace("ui","ui.task","ui.task._CheckBuildTask");ui.task._CheckBuildTask.display=function(){XHR({params:{task:"getLogFile",file:"project_"+PhDOE.project+"_log_check_build_"+PhDOE.user.lang},success:function(c){var d=Ext.util.JSON.decode(c.responseText);Ext.getBody().unmask();ui.task.PingTask.getInstance().delay(30000);if(Ext.getCmp("main-panel").findById("check_build_panel_"+PhDOE.user.lang)){Ext.getCmp("main-panel").remove("check_build_panel_"+PhDOE.user.lang)}Ext.getCmp("main-panel").add({xtype:"panel",id:"check_build_panel_"+PhDOE.user.lang,title:String.format(_("Check build result for {0}"),Ext.util.Format.uppercase(PhDOE.user.lang)),tabTip:String.format(_("Check build result for the documentation {0}"),Ext.util.Format.uppercase(PhDOE.user.lang)),closable:true,autoScroll:true,iconCls:"iconCheckBuild",html:'
'+d.mess+"
"});Ext.getCmp("main-panel").setActiveTab("check_build_panel_"+PhDOE.user.lang)}})};ui.task._CheckBuildTask.poll=new Ext.util.DelayedTask(function(){XHR({params:{task:"checkLockFile",lockFile:"project_"+PhDOE.project+"_lock_check_build_"+PhDOE.user.lang},success:function(){ui.task._CheckBuildTask.poll.delay(5000)},failure:function(c){var d=Ext.util.JSON.decode(c.responseText);if(d&&d.success===false){new ui.task._CheckBuildTask.display()}else{ui.task._CheckBuildTask.poll.delay(5000)}}})});ui.task.CheckBuildTask=function(){Ext.getBody().mask(' '+_("Please, wait until the build is checked..."));ui.task.PingTask.getInstance().cancel();XHR({params:{task:"checkBuild",xmlDetails:Ext.getCmp("option-xml-details").checked},success:function(){new ui.task._CheckBuildTask.display()},failure:function(c){var d=Ext.util.JSON.decode(c.responseText);if(d&&d.success===false){ui.task.PingTask.getInstance().delay(30000);Ext.getBody().unmask();PhDOE.winForbidden(d.type)}else{ui.task._CheckBuildTask.poll.delay(5000)}}})};Ext.namespace("ui","ui.task","ui.task._CheckEntitiesTask");ui.task._CheckEntitiesTask.display=function(){BtnViewResult=Ext.getCmp("btn-check-entities-view-last-result");Ext.getBody().unmask();ui.task.PingTask.getInstance().delay(30000);if(Ext.getCmp("main-panel").findById("tab-check-entities")){Ext.getCmp("main-panel").remove("tab-check-entities")}BtnViewResult.handler.call(BtnViewResult.scope||BtnViewResult,BtnViewResult)};ui.task._CheckEntitiesTask.poll=new Ext.util.DelayedTask(function(){XHR({params:{task:"checkLockFile",lockFile:"project_"+PhDOE.project+"_lock_check_entities"},success:function(){ui.task._CheckEntitiesTask.poll.delay(5000)},failure:function(c){var d=Ext.util.JSON.decode(c.responseText);if(d&&d.success===false){new ui.task._CheckEntitiesTask.display()}else{ui.task._CheckEntitiesTask.poll.delay(5000)}}})});ui.task.CheckEntitiesTask=function(){Ext.getBody().mask(' '+_("Please, wait until entities are checked..."));ui.task.PingTask.getInstance().cancel();XHR({params:{task:"checkEntities"},success:function(){new ui.task._CheckEntitiesTask.display()},failure:function(c){var d=Ext.util.JSON.decode(c.responseText);if(d&&d.success===false){ui.task.PingTask.getInstance().delay(30000);Ext.getBody().unmask();PhDOE.winForbidden()}else{ui.task._CheckEntitiesTask.poll.delay(5000)}}})};Ext.namespace("ui","ui.task");ui.task.CheckFileTask=function(c){Ext.apply(this,c);ui.task.PingTask.getInstance().cancel();Ext.getBody().mask(' '+_("Checking for error. Please, wait..."));XHR({scope:this,params:{task:"checkFileError",FilePath:this.fpath,FileName:this.fname,FileLang:this.lang,FileContent:Ext.getCmp(this.prefix+"-"+this.ftype+"-FILE-"+this.fid).getValue()},failure:function(){ui.task.PingTask.getInstance().delay(30000);Ext.getBody().unmask();Ext.MessageBox.alert(_("Error"),_("An error occured while checking this file for errors. Please, try again."))},success:function(d){ui.task.PingTask.getInstance().delay(30000);Ext.getBody().unmask();var e=Ext.util.JSON.decode(d.responseText);if(e.error&&e.error_first!=="-No error-"){Ext.getCmp("main-panel").add({id:"FE-help-"+this.fid,title:"Error in "+this.fname,iconCls:"iconFilesError",closable:true,autoScroll:true,autoLoad:"./error?dir="+this.fpath+"&file="+this.fname});Ext.getCmp("main-panel").setActiveTab("FE-help-"+this.fid)}else{Ext.MessageBox.show({title:_("Check for errors"),msg:_("There is no error."),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.INFO})}new ui.task.SaveFileTask({prefix:this.prefix,ftype:this.ftype,fid:this.fid,fpath:this.fpath,fname:this.fname,lang:this.lang,storeRecord:this.storeRecord});if(this.prefix==="FE"){Ext.getCmp("FE-error-desc-"+this.fid).body.updateManager.refresh()}ui.cmp.ErrorFileGrid.getInstance().store.reload()}})};Ext.namespace("ui","ui.task");ui.task.CheckXml=function(d){Ext.apply(this,d);var c=this.prefix+"-"+this.ftype,e=Ext.MessageBox.wait(_("XML check. Please, wait..."));XHR({scope:this,params:{task:"checkXml",fileContent:Ext.getCmp(this.idPrefix+"-FILE-"+this.fid).getValue()},success:function(f){var g=Ext.util.JSON.decode(f.responseText);e.hide();if(g.errors!=="no_error"){new ui.cmp.CheckXmlWin({errors:g.errors})}else{PhDOE.notify("info",_("XML check"),_("There is no error."))}},failure:function(f){var g=Ext.util.JSON.decode(f.responseText);e.hide()}})};Ext.namespace("ui","ui.task");ui.task.ClearLocalChangeTask=function(d){Ext.apply(this,d);var c=this.ftype,e=this.fpath,f=this.fname;goClear=function(){Ext.getBody().mask(' '+_("Please, wait..."));var g=["FNT","FNU","FE","FNR","FNIEN","AF"];for(var h=0;hYou need confirm."),function(g){if(g==="yes"){goClear()}},this)}};Ext.namespace("ui","ui.task");ui.task.DeletePatchTask=function(c){Ext.apply(this,c);Ext.getBody().mask(' '+_("Please, wait..."));XHR({scope:this,params:{task:"deletePatch",patchID:this.patchID},success:function(){Ext.getBody().unmask();ui.cmp.PatchesTreeGrid.getInstance().deletePatch(this.patchID);PhDOE.notify("info",_("Patch deleted"),_("The patch have been deleted !"))},failure:function(d){var e=Ext.util.JSON.decode(d.responseText);Ext.getBody().unmask();if(e.err){PhDOE.winForbidden(e.err)}else{PhDOE.winForbidden()}}})};Ext.namespace("ui","ui.task");ui.task.GetFileInfoByXmlID=function(c){Ext.apply(this,c);XHR({scope:this,params:{task:"getFileInfoByXmlID",xmlID:this.xmlID},success:function(d){var e=Ext.util.JSON.decode(d.responseText);ui.cmp.RepositoryTree.getInstance().openFile("byPath",e.lang+e.path,e.name)}})};Ext.namespace("ui","ui.task");ui.task.GetFileTask=function(d){Ext.apply(this,d);var c=this.prefix+"-"+this.ftype,f=(this.original)?true:false,e=(this.ftype==="GGTRANS")?true:false,g=(this.ftype==="NEW")?this.skeleton:false;Ext.get(c+"-PANEL-"+this.fid).mask(' '+_("Loading..."));XHR({scope:this,params:{task:"getFile",FilePath:this.fpath,FileName:this.fname,readOriginal:f,ggTranslate:e,skeleton:g},success:function(h){var k=Ext.util.JSON.decode(h.responseText),y="http://"+window.location.host+":"+window.location.port+window.location.pathname+"?perm=/"+this.fpath.split("/")[0]+"/"+k.xmlid.split("|")[0]+".php&project="+PhDOE.project,s='permlink ',j=Ext.getCmp(c+"-PANEL-"+this.fid),w=Ext.get(c+"-PANEL-"+this.fid),v=Ext.getCmp(c+"-FILE-"+this.fid),q=(k.fileModified)?Ext.util.JSON.decode(k.fileModified):false,t,u;w.unmask();if(this.prefix==="PP"||this.ftype==="TRANS"||this.prefix==="FNIEN"){j.permlink=""}else{if(this.ftype==="GGTRANS"){j.setTitle(j.originTitle);j.setIconClass("iconGoogle")}else{j.permlink=(k.xmlid!=="NULL")?s:"";j.setTitle(j.permlink+j.originTitle)}}v.setValue(k.content);if(this.ftype==="GGTRANS"){v.reIndentAll()}if(k.warn_tab&&!this.freadOnly){Ext.MessageBox.show({title:_("Warning"),msg:String.format(_("The file {0} contains some tab characters.
The editor have replace it with space characters."),this.fpath+this.fname),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.WARNING});v.manageCodeChange()}if(k.warn_encoding&&!this.freadOnly){Ext.MessageBox.show({title:_("Warning"),msg:String.format(_("The editor have modified automatically the file {0} into UTF-8 encoding."),this.fpath+this.fname),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.WARNING});v.setLine(1,'');Ext.getCmp(c+"-FILE-"+this.fid+"-btn-save").enable()}if(this.prefix==="FNT"||this.prefix==="FNIEN"){t="fileModified"}if(this.prefix==="FNU"){t=(this.ftype==="LANG")?"fileModifiedLang":"fileModifiedEN"}if(this.prefix==="FE"){t=(this.ftype==="LANG")?"fileModifiedLang":"fileModifiedEN"}if(this.prefix==="FNR"){t=(this.ftype==="LANG")?"fileModifiedLang":"fileModifiedEN"}if(k.fileModified&&this.prefix!=="AF"&&!f){this.storeRecord.set(t,k.fileModified);this.storeRecord.commit()}if(this.prefix==="AF"){this.storeRecord.data={};this.storeRecord.data.fileModified=false;if(k.fileModified){this.storeRecord.data.fileModified=k.fileModified}}if(k.fileModified&&!f&&((!PhDOE.user.isAnonymous&&q.user!==PhDOE.user.login)||(PhDOE.user.isAnonymous&&q.anonymousIdent!==PhDOE.user.anonymousIdent))){if(q.isAnonymous&&!PhDOE.user.isAnonymous&&q.fromModule==="workInProgress"){Ext.MessageBox.show({title:_("Information"),msg:String.format(_("File modified by {0} (anonymous user) but you are an authenticated user, so you can modify it."),q.user),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.INFO})}else{if(q.isAnonymous&&!PhDOE.user.isAnonymous&&q.fromModule==="PatchesForReview"){new ui.cmp.AnonymousPatchWin({fidDB:q.fidDB,fid:this.fid,prefix:this.prefix,ftype:q.ftype,fpath:this.fpath,fname:this.fname,curTab:Ext.getCmp(this.prefix+"-"+this.fid)})}else{if(!this.freadOnly){Ext.getCmp(c+"-FILE-"+this.fid+"-grp-save").disable();Ext.getCmp(c+"-FILE-"+this.fid+"-grp-undoRedo").disable();Ext.getCmp(c+"-FILE-"+this.fid+"-grp-tools").disable()}u=Ext.MessageBox.show({title:_("Information"),msg:String.format(_("File modified by {0}."),q.user),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.INFO});u.getDialog().mask.resize(w.getSize().width,w.getSize().height);u.getDialog().mask.alignTo(w.dom,"tl")}}}else{if(c=="FNT-TRANS"){var x=new RegExp("");v.insertLine(1,"");v.insertLine(2,"");if(!Ext.isEmpty(v.getLine(4))){v.insertLine(3,"")}v.manageCodeChange()}}}},callback:function(){var h=Ext.getCmp(this.prefix+"-"+this.fid);if(this.prefix==="FNT"){if(this.ftype==="TRANS"){h.panTRANSLoaded=true}if(this.ftype==="GGTRANS"||this.ftype==="EN"){h.panTRANSSecondLoaded=true}}if(this.prefix==="FNU"){if(this.ftype==="LANG"){h.panLANGLoaded=true}if(this.ftype==="EN"){h.panENLoaded=true}}if(this.prefix==="FE"){if(this.ftype==="LANG"){h.panLANGLoaded=true}if(this.ftype==="EN"){h.panENLoaded=true}}if(this.prefix==="FNR"){if(this.ftype==="LANG"){h.panLANGLoaded=true}if(this.ftype==="EN"){h.panENLoaded=true}}if(this.prefix==="FNIEN"){h.panLANGLoaded=true}if(this.prefix==="AF"){h.panLoaded=true}Ext.getCmp("main-panel").fireEvent("tabLoaded",this.prefix,this.fid)}})};Ext.namespace("ui","ui.task");ui.task.GetGGTranslation=function(c){Ext.apply(this,c);Ext.get("GGTranslate-result").dom.innerHTML="";Ext.getCmp("GGTranslate-btn").disable();Ext.getCmp("GGTranslate-btn").setText(_("Please, wait..."));XHR({scope:this,params:{task:"getGGTranslation",str:this.str},success:function(d){var e=Ext.util.JSON.decode(d.responseText);Ext.get("GGTranslate-result").dom.innerHTML=Ext.util.Format.htmlEncode(e.translation);Ext.getCmp("GGTranslate-btn").setText(_("Translate !"));Ext.getCmp("GGTranslate-btn").enable()}})};Ext.namespace("ui","ui.task");ui.task.LoadConfigTask=function(c){Ext.apply(this,c);XHR({params:{task:"getConf"},success:function(d){var e=Ext.decode(d.responseText);PhDOE.user.login=e.mess.userLogin;PhDOE.user.userID=e.mess.userID;PhDOE.user.lang=e.mess.userLang;PhDOE.user.authService=e.mess.authService;PhDOE.user.authServiceID=e.mess.authServiceID;PhDOE.user.isAnonymous=e.mess.userIsAnonymous;PhDOE.user.isGlobalAdmin=e.mess.userIsGlobalAdmin;PhDOE.user.isLangAdmin=e.mess.userIsLangAdmin;PhDOE.user.conf=e.mess.userConf;PhDOE.user.anonymousIdent=e.mess.userAnonymousIdent;PhDOE.project=e.mess.project;PhDOE.app.conf=e.mess.appConf;if(e.mess.topicInfo&&e.mess.topicInfo.lang){PhDOE.topic.lang.author=e.mess.topicInfo.lang.author;PhDOE.topic.lang.content=e.mess.topicInfo.lang.content;PhDOE.topic.lang.topicDate=Date.parseDate(e.mess.topicInfo.lang.topicDate,"Y-m-d H:i:s");PhDOE.topic.lang.topicDate=PhDOE.topic.lang.topicDate.format(_("Y-m-d, H:i"))}if(e.mess.topicInfo&&e.mess.topicInfo.global){PhDOE.topic.global.author=e.mess.topicInfo.global.author;PhDOE.topic.global.content=e.mess.topicInfo.global.content;PhDOE.topic.global.topicDate=Date.parseDate(e.mess.topicInfo.global.topicDate,"Y-m-d H:i:s");PhDOE.topic.global.topicDate=PhDOE.topic.global.topicDate.format(_("Y-m-d, H:i"))}Ext.get("appTheme").dom.href=PhDOE.user.conf.main.theme;PhDOE.drawInterface()}})};Ext.namespace("ui","ui.task");ui.task.MarkDeleteTask=function(c){Ext.apply(this,c);Ext.MessageBox.confirm(_("Confirm"),_("This action will mark this file as need deleted.

You need commit this change to take it effect.

Please, confirm this action."),function(d){if(d==="yes"){Ext.getBody().mask(' '+_("Please, wait..."));XHR({scope:this,params:{task:"markAsNeedDelete",FilePath:PhDOE.user.lang+this.fpath,FileName:this.fname},success:function(e){var f=Ext.util.JSON.decode(e.responseText);Ext.getBody().unmask();ui.cmp.WorkTreeGrid.getInstance().addRecord(f.id,PhDOE.user.lang+this.fpath,this.fname,"delete");this.storeRecord.set("fileModified",'{"user":"'+PhDOE.user.login+'", "anonymousIdent":"'+PhDOE.user.anonymousIdent+'"}')}})}},this)};Ext.namespace("ui","ui.task");ui.task.MoveToPatch=function(c){Ext.apply(this,c);var d=[];Ext.each(this.nodesToAdd,function(e){d.push(e.attributes.idDB)});Ext.getBody().mask(' '+_("Please, wait..."));XHR({scope:this,params:{task:"moveToPatch",patchID:this.patchID,filesID:d.join(",")},success:function(){Ext.getBody().unmask();ui.cmp.PatchesTreeGrid.getInstance().addToPatch(this.patchID,this.patchName,this.nodesToAdd,this.patchDescription,this.patchEmail);if(this.nodesToAdd){Ext.each(this.nodesToAdd,function(e){ui.cmp.WorkTreeGrid.getInstance().delRecord(e.attributes.idDB)})}},failure:function(e){var f=Ext.util.JSON.decode(e.responseText);Ext.getBody().unmask();Ext.MessageBox.alert("Error",f.err)}})};Ext.namespace("ui","ui.task");ui.task.MoveToWork=function(c){Ext.apply(this,c);var d=[];Ext.each(this.nodesToAdd,function(e){d.push(e.attributes.idDB)});Ext.getBody().mask(' '+_("Please, wait..."));XHR({scope:this,params:{task:"moveToWork",filesID:d.join(",")},success:function(){Ext.getBody().unmask();ui.cmp.WorkTreeGrid.getInstance().addToWork(this.nodesToAdd);if(this.nodesToAdd){Ext.each(this.nodesToAdd,function(e){ui.cmp.PatchesTreeGrid.getInstance().delRecord(e.attributes.idDB)})}},failure:function(e){var f=Ext.util.JSON.decode(e.responseText);Ext.getBody().unmask();Ext.MessageBox.alert("Error",f.err)}})};Ext.namespace("ui","ui.task","ui.task._PingTask");ui.task.PingTask=function(){this.task=new Ext.util.DelayedTask(function(){XHR({scope:this,params:{task:"ping"},success:function(d){var e=Ext.util.JSON.decode(d.responseText),c;if(e.ping!=="pong"){this.onPingFailed()}else{if(PhDOE.user.lang!=="en"){c=false;if(ui.cmp.PendingTranslateGrid.getInstance().store.getTotalCount()!==e.totalData.NbPendingTranslate){ui.cmp.PendingTranslateGrid.getInstance().store.reload();c=true}if(ui.cmp.StaleFileGrid.getInstance().store.getTotalCount()!==e.totalData.NbPendingUpdate){ui.cmp.StaleFileGrid.getInstance().store.reload();c=true}if(ui.cmp.ErrorFileGrid.getInstance().store.getTotalCount()!==e.totalData.NbFilesError){ui.cmp.ErrorFileGrid.getInstance().store.reload();c=true}if(ui.cmp.PendingReviewGrid.getInstance().store.getTotalCount()!==e.totalData.NbPendingReview){ui.cmp.PendingReviewGrid.getInstance().store.reload();c=true}if(ui.cmp.NotInENGrid.getInstance().store.getTotalCount()!==e.totalData.NbNotInEn){ui.cmp.NotInENGrid.getInstance().store.reload();c=true}if(c){ui.cmp.PortletSummary.getInstance().store.reload()}}if(e.totalData.lastInfoDate!==PhDOE.lastInfoDate){ui.cmp.PortletInfo.getInstance().store.reload()}if(e.totalData.topicInfo){e.totalData.topicInfo.topicDate=Date.parseDate(e.totalData.topicInfo.topicDate,"Y-m-d H:i:s");e.totalData.topicInfo.topicDate=e.totalData.topicInfo.topicDate.format(_("Y-m-d, H:i"));if(e.totalData.topicInfo.topicDate!=PhDOE.topic.topicDate){PhDOE.topic.author=e.totalData.topicInfo.author;PhDOE.topic.content=e.totalData.topicInfo.content;PhDOE.topic.topicDate=e.totalData.topicInfo.topicDate;PhDOE.setTopic()}}}},failure:function(){this.onPingFailed()}});this.task.delay(30000)},this)};ui.task.PingTask.prototype.delay=function(d,f,e,c){this.task.delay(d,f,e,c)};ui.task.PingTask.prototype.cancel=function(){this.task.cancel()};ui.task.PingTask.prototype.onPingFailed=function(){this.cancel();var d=new Ext.ux.Notification({iconCls:"iconError",title:_("Connection lost"),html:String.format(_("Retrying in {0} second(s)."),"30"),autoDestroy:false});d.show(document);this.delay(30000);var e=29;var c=new Ext.util.DelayedTask(function(){if(e>0){d.setMessage(String.format(_("Retrying in {0} second(s)."),e));e-=1;c.delay(1000)}else{if(e==0){d.animHide()}}});c.delay(1000)};ui.task._PingTask.instance=null;ui.task.PingTask.getInstance=function(){if(!ui.task._PingTask.instance){ui.task._PingTask.instance=new ui.task.PingTask()}return ui.task._PingTask.instance};Ext.namespace("ui","ui.task");ui.task.SaveFileTask=function(d){Ext.apply(this,d);var c=this.prefix+"-"+this.ftype,e=Ext.MessageBox.wait(_("Saving data...")),f=Ext.getCmp(this.prefix+"-"+this.ftype+"-FILE-"+this.fid).getValue();XHR({scope:this,params:{task:"saveFile",filePath:this.fpath,fileName:this.fname,fileLang:this.lang,fileContent:f},success:function(h){var j=Ext.util.JSON.decode(h.responseText);if(this.prefix==="FNU"){if(this.ftype==="EN"){this.storeRecord.set("en_revision",j.revision);this.storeRecord.set("fileModifiedEN",'{"user":"'+PhDOE.user.login+'", "anonymousIdent":"'+PhDOE.user.anonymousIdent+'"}')}else{this.storeRecord.set("revision",j.en_revision);this.storeRecord.set("fileModifiedLang",'{"user":"'+PhDOE.user.login+'", "anonymousIdent":"'+PhDOE.user.anonymousIdent+'"}');this.storeRecord.set("maintainer",j.maintainer)}this.storeRecord.commit()}if(this.prefix==="FE"){if(this.ftype==="EN"){this.storeRecord.set("fileModifiedEN",'{"user":"'+PhDOE.user.login+'", "anonymousIdent":"'+PhDOE.user.anonymousIdent+'"}');this.storeRecord.commit()}else{this.storeRecord.set("maintainer",j.maintainer);this.storeRecord.set("fileModifiedLang",'{"user":"'+PhDOE.user.login+'", "anonymousIdent":"'+PhDOE.user.anonymousIdent+'"}');this.storeRecord.commit()}}if(this.prefix==="FNR"){if(this.ftype==="EN"){this.storeRecord.set("reviewed",j.reviewed);this.storeRecord.set("fileModifiedEN",'{"user":"'+PhDOE.user.login+'", "anonymousIdent":"'+PhDOE.user.anonymousIdent+'"}');this.storeRecord.commit()}else{this.storeRecord.set("reviewed",j.reviewed);this.storeRecord.set("maintainer",j.reviewed_maintainer);this.storeRecord.set("fileModifiedLang",'{"user":"'+PhDOE.user.login+'", "anonymousIdent":"'+PhDOE.user.anonymousIdent+'"}');this.storeRecord.commit()}}if(this.prefix==="AF"){this.storeRecord.getUI().addClass("fileModifiedByMe")}Ext.getCmp(this.prefix+"-"+this.ftype+"-FILE-"+this.fid).setOriginalContent(f);ui.cmp.WorkTreeGrid.getInstance().delRecord(j.id);ui.cmp.PatchesTreeGrid.getInstance().delRecord(j.id);ui.cmp.WorkTreeGrid.getInstance().addRecord(j.id,this.lang+this.fpath,this.fname,"update");Ext.getCmp(c+"-FILE-"+this.fid+"-btn-save").disable();Ext.getCmp(c+"-FILE-"+this.fid).isModified=false;Ext.getCmp(c+"-PANEL-"+this.fid).setTitle(Ext.getCmp(c+"-PANEL-"+this.fid).permlink+Ext.getCmp(c+"-PANEL-"+this.fid).originTitle);var g;if(this.lang==="en"){g=Ext.getCmp(this.prefix+"-LANG-FILE-"+this.fid)}else{g=Ext.getCmp(this.prefix+"-EN-FILE-"+this.fid)}if(this.ftype==="ALL"||!g.isModified){Ext.getCmp(this.prefix+"-"+this.fid).setTitle(Ext.getCmp(this.prefix+"-"+this.fid).originTitle)}e.hide();PhDOE.notify("info",_("Document saved"),String.format(_("Document

{0}

was saved successfully !"),this.lang+this.fpath+this.fname))},failure:function(g){var h=Ext.util.JSON.decode(g.responseText);e.hide();if(h.XmlError&&h.XmlError!="no_error"){Ext.MessageBox.alert(_("XML Errors"),_("There is somes XML's errors.

You must fix it before saving this file.

Valid this window to show this errors."),function(){new ui.cmp.CheckXmlWin({errors:h.XmlError})})}if(h.type){PhDOE.winForbidden(h.type)}}})};Ext.namespace("ui","ui.task");ui.task.SaveTransFileTask=function(d){Ext.apply(this,d);var c=this.prefix+"-"+this.ftype,e=Ext.MessageBox.wait(_("Saving data...")),f=Ext.getCmp(this.prefix+"-"+this.ftype+"-FILE-"+this.fid).getValue();XHR({scope:this,params:{task:"saveFile",type:"trans",filePath:this.fpath,fileName:this.fname,fileLang:this.lang,fileContent:f},success:function(g){var h=Ext.util.JSON.decode(g.responseText);if(this.ftype!="NEW"){this.storeRecord.set("fileModified",'{"user":"'+PhDOE.user.login+'", "anonymousIdent":"'+PhDOE.user.anonymousIdent+'"}');this.storeRecord.commit()}else{this.storeRecord.data.node.reload()}Ext.getCmp(this.prefix+"-"+this.ftype+"-FILE-"+this.fid).setOriginalContent(f);ui.cmp.WorkTreeGrid.getInstance().addRecord(h.id,this.lang+this.fpath,this.fname,"new");Ext.getCmp(c+"-FILE-"+this.fid+"-btn-save").disable();Ext.getCmp(c+"-FILE-"+this.fid).isModified=false;Ext.getCmp(c+"-PANEL-"+this.fid).setTitle(Ext.getCmp(c+"-PANEL-"+this.fid).originTitle);Ext.getCmp(this.prefix+"-"+this.fid).setTitle(Ext.getCmp(this.prefix+"-"+this.fid).originTitle);e.hide();PhDOE.notify("info",_("Document saved"),String.format(_("Document

{0}

was saved successfully !"),this.lang+this.fpath+this.fname))},failure:function(g){var h=Ext.util.JSON.decode(g.responseText);e.hide();if(h.XmlError&&h.XmlError!="no_error"){Ext.MessageBox.alert(_("XML Errors"),_("There is somes XML's errors.

You must fix it before saving this file.

Valid this window to show this errors."),function(){new ui.cmp.CheckXmlWin({errors:h.XmlError})})}if(h.type){PhDOE.winForbidden(h.type)}}})};Ext.namespace("ui","ui.task");ui.task.SetFileProgressTask=function(c){Ext.apply(this,c);XHR({scope:this,params:{task:"SetFileProgress",idDB:this.idDB,progress:this.progress},failure:function(d){var e=Ext.util.JSON.decode(d.responseText),f;if(e.err){if(e.err=="file_dont_exist_in_workInProgress"){f=_("The file you want to change the estimated progress don't exist into the database.")}if(e.err=="file_isnt_owned_by_current_user"){f=_("The file you want to change the estimated progress isn't own by you.
You only can modify this information for yours files.")}}if(f){PhDOE.notify("error",_("Error"),f)}}})};Ext.namespace("ui","ui.task");ui.task.setTopicTask=function(c){Ext.apply(this,c);var d=this.isLang;XHR({scope:this,params:{task:"setTopic",content:this.content,lang:d?"lang":"global"},success:function(f){var g=Ext.util.JSON.decode(f.responseText),e=PhDOE.topic[d?"lang":"global"];e.author=g.author;e.content=g.content;e.topicDate=Date.parseDate(g.topicDate,"Y-m-d H:i:s");e.topicDate=e.topicDate.format(_("Y-m-d, H:i"));PhDOE.setTopic(d)}})};Ext.namespace("ui","ui.task","ui.task._SystemUpdateTask");ui.task._SystemUpdateTask.refresh_ui=function(){Ext.get("wizard-step-3").replaceClass("wizard-step-before","wizard-step-working");PhDOE.reloadAllStore();Ext.get("wizard-step-3").replaceClass("wizard-step-working","wizard-step-done");Ext.getCmp("btn-start-refresh").setIconClass("iconFinishRefresh");Ext.getCmp("btn-start-refresh").setText(_("Finish !"));Ext.getCmp("btn-start-refresh").setHandler(function(){Ext.getCmp("sys-update-win").close()});Ext.getCmp("btn-start-refresh").enable();ui.task.PingTask.getInstance().delay(30000);Ext.getCmp("sys-update-win").tools.close.setVisible(true)};ui.task._SystemUpdateTask.poll_apply_tool=new Ext.util.DelayedTask(function(){XHR({params:{task:"checkLockFile",lockFile:"project_"+PhDOE.project+"_lock_apply_tools"},success:function(){ui.task._SystemUpdateTask.poll_apply_tool.delay(5000)},failure:function(c){var d=Ext.util.JSON.decode(c.responseText);if(d&&d.success===false){Ext.get("wizard-step-2").replaceClass("wizard-step-working","wizard-step-done");new ui.task._SystemUpdateTask.refresh_ui()}else{ui.task._SystemUpdateTask.poll_apply_tool.delay(5000)}}})});ui.task._SystemUpdateTask.apply_tool=function(){Ext.get("wizard-step-2").replaceClass("wizard-step-before","wizard-step-working");XHR({params:{task:"applyTools"},success:function(){Ext.get("wizard-step-2").replaceClass("wizard-step-working","wizard-step-done");new ui.task._SystemUpdateTask.refresh_ui()},failure:function(){ui.task._SystemUpdateTask.poll_apply_tool.delay(5000)}})};ui.task._SystemUpdateTask.vcs_poll=new Ext.util.DelayedTask(function(){XHR({params:{task:"checkLockFile",lockFile:"project_"+PhDOE.project+"_lock_update_repository"},success:function(){ui.task._SystemUpdateTask.vcs_poll.delay(5000)},failure:function(c){var d=Ext.util.JSON.decode(c.responseText);if(d&&d.success===false){Ext.get("wizard-step-1").replaceClass("wizard-step-working","wizard-step-done");Ext.get("wizard-step-1.1").replaceClass("wizard-show","wizard-wait");new ui.task._SystemUpdateTask.apply_tool()}else{ui.task._SystemUpdateTask.vcs_poll.delay(5000)}}})});ui.task.SystemUpdateTask=function(){ui.task.PingTask.getInstance().cancel();Ext.get("wizard-step-1").replaceClass("wizard-step-before","wizard-step-working");Ext.get("wizard-step-1.1").replaceClass("wizard-wait","wizard-show");XHR({params:{task:"updateRepository"},success:function(){Ext.get("wizard-step-1").replaceClass("wizard-step-working","wizard-step-done");Ext.get("wizard-step-1.1").replaceClass("wizard-show","wizard-wait");new ui.task._SystemUpdateTask.apply_tool()},failure:function(c){var d=Ext.util.JSON.decode(c.responseText);if(d&&d.success===false){Ext.getCmp("sys-update-win").close();PhDOE.winForbidden(d.type)}else{ui.task._SystemUpdateTask.vcs_poll.delay(5000)}}})};Ext.namespace("ui","ui.task");ui.task.UpdateConfTask=function(c){Ext.apply(this,c);XHR({scope:this,params:{task:"confUpdate",module:this.module,itemName:this.itemName,value:this.value},success:function(){PhDOE.user.conf[this.module][this.itemName]=this.value;if(this.module=="newFile"&&this.itemName=="nbDisplay"){ui.cmp.PendingTranslateGrid.getInstance().store.reload()}if(this.module=="needUpdate"&&this.itemName=="nbDisplay"){ui.cmp.StaleFileGrid.getInstance().store.reload()}if(this.module=="error"&&(this.itemName=="skipNbLiteralTag"||this.itemName=="nbDisplay")){ui.cmp.ErrorFileGrid.getInstance().store.reload()}if(this.module=="reviewed"&&this.itemName=="nbDisplay"){ui.cmp.PendingReviewGrid.getInstance().store.reload()}if(this.module=="main"&&this.itemName=="displayENWork"){ui.cmp.WorkTreeGrid.getInstance().getRootNode().reload(function(){ui.cmp.PatchesTreeGrid.getInstance().getRootNode().reload()})}if(this.notify!==false){PhDOE.notify("info",_("Option saved"),_("Option has been saved successfully !"))}}})};Ext.namespace("ui","ui.task","ui.task._VCSCommitTask");ui.task._VCSCommitTask.getCommitResponse=function(){XHR({params:{task:"getCommitResponse"},success:function(c){var d=Ext.util.JSON.decode(c.responseText);ui.task._VCSCommitTask.afterCommit(d.mess)}})};ui.task._VCSCommitTask.poll=new Ext.util.DelayedTask(function(){XHR({params:{task:"checkLockFile",lockFile:"project_"+PhDOE.project+"_lock_"+PhDOE.user.login+"_commit"},success:function(){ui.task._VCSCommitTask.poll.delay(5000)},failure:function(c){var d=Ext.util.JSON.decode(c.responseText);if(d&&d.success===false){new ui.task._VCSCommitTask.getCommitResponse()}else{ui.task._VCSCommitTask.poll.delay(5000)}}})});ui.task._VCSCommitTask.afterCommit=function(c){Ext.getBody().unmask();ui.task.PingTask.getInstance().delay(30000);new Ext.Window({title:_("Status"),width:450,height:350,resizable:false,modal:true,autoScroll:true,bodyStyle:"background-color: white; padding: 5px;",html:c.join("
"),buttons:[{text:_("Close"),handler:function(){this.ownerCt.ownerCt.close()}}]}).show();PhDOE.reloadAllStore()};ui.task._VCSCommitTask.commit=function(h,g){Ext.getBody().mask(' '+_("Please, wait until commit..."));var c=[],f,e,d;for(d=0;d0){for(h=0;h"}Ext.MessageBox.show({title:"Warning",icon:Ext.MessageBox.INFO,buttons:Ext.MessageBox.YESNOCANCEL,msg:(l.length>1)?String.format(_("There are {0} files to close before commit.

{1}

Would you like me to close them for you ?"),l.length,m):String.format(_("There is {0} file to close before commit.

{1}

Would you like me to close it for you ?"),l.length,m),fn:function(u){if(u==="yes"){for(var t=0;t'+PhDOE.app.name+'
'+PhDOE.app.name+" ver "+PhDOE.app.ver+"
UI: "+PhDOE.app.uiRevision+"
Copyright © 2008-2012 The PHP Group
"+_("Author:")+' Yannick Torrès '+_('and others')+"
"},{title:_("Help and support"),bodyStyle:"padding:15px",html:'
'},{title:_("Credits"),bodyStyle:"padding:15px",html:'
"},{title:_("License"),autoLoad:{url:"./LICENSE"}}]}});ui.cmp.About.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._AnonymousPatchWin");ui.cmp._AnonymousPatchWin.form=Ext.extend(Ext.FormPanel,{frame:true,labelWidth:5,bodyStyle:"padding:5px 5px 0",defaultType:"radio",initComponent:function(c){Ext.apply(this,{items:[{xtype:"displayfield",value:_("File: ")+this.fpath+this.fname+"

"+_('You have opened a modified file from the "Patch for review" module.
This file has been modified by an anonymous user.

Please choose one of the following actions:')},{boxLabel:_("Continue to modify this file"),name:"choice",inputValue:"continue",checked:true,listeners:{afterrender:function(){new Ext.ToolTip({title:_("Continue to modify this file"),target:"x-form-el-"+this.id,anchor:"right",html:"
"+_("This action will open this file for modification. Once your modification finish, just save it and this file will be own by you."),width:250,autoHide:true})}}},{boxLabel:_("Reject this patch"),name:"choice",inputValue:"reject",listeners:{afterrender:function(){new Ext.ToolTip({title:_("Reject this patch"),target:"x-form-el-"+this.id,anchor:"right",html:"
"+_("This action will close this file, and clear the local change. This file will return into his original version, as it is on VCS server."),width:250,autoHide:true})}}},{boxLabel:_("Validate this patch"),name:"choice",inputValue:"validate",listeners:{afterrender:function(){new Ext.ToolTip({title:_("Validate this patch"),target:"x-form-el-"+this.id,anchor:"right",html:"
"+_("This action changes the owner of the modification and register it under your name. The file will appear under your name and you can then commit it."),width:250,autoHide:true})}}}]});ui.cmp._AnonymousPatchWin.form.superclass.initComponent.call(this)}});ui.cmp.AnonymousPatchWin=Ext.extend(Ext.Window,{id:"anonymous-patch-win",title:_("Anonymous patch manager"),iconCls:"iconPatch",width:450,height:250,layout:"fit",resizable:false,modal:true,autoScroll:true,closable:false,closeAction:"close",buttons:[{text:_("Next"),iconCls:"iconArrowRight",handler:function(){var d=this.ownerCt.ownerCt,c=d.items.items[0].getForm().getValues().choice;switch(c){case"continue":d.close();break;case"reject":ui.task.ClearLocalChangeTask({ftype:d.ftype,fpath:d.fpath,fname:d.fname,noConfirm:true});break;case"validate":ui.task.ChangeFileOwner({fileIdDB:d.fidDB,newOwnerID:PhDOE.user.userID,from:d,fromType:"tab"});break}}}],initComponent:function(){Ext.apply(this,{items:[new ui.cmp._AnonymousPatchWin.form({fpath:this.fpath,fname:this.fname})]});ui.cmp.AnonymousPatchWin.superclass.initComponent.call(this);this.show()}});Ext.namespace("ui","ui.cmp","ui.cmp._BuildStatus");ui.cmp._BuildStatus.display=function(c){Ext.apply(this,c);if(Ext.getCmp("main-panel").findById("last_failed_build_"+this.lang)){Ext.getCmp("main-panel").remove("last_failed_build_"+this.lang)}Ext.getCmp("main-panel").add({xtype:"panel",id:"last_failed_build_"+this.lang,title:String.format(_("Last failed build for {0}"),Ext.util.Format.uppercase(this.lang)),tabTip:String.format(_("Last failed build for the documentation {0}"),Ext.util.Format.uppercase(this.lang)),closable:true,autoScroll:true,iconCls:"iconCheckBuild",html:'
'});Ext.getCmp("main-panel").setActiveTab("last_failed_build_"+this.lang);Ext.getCmp("main-panel").el.mask(_("Please, wait..."));XHR({scope:this,params:{task:"getFailedBuildData",idFailedBuild:this.idFailedBuild},success:function(d){var e=Ext.decode(d.responseText),f=e.mess.join("
");if(e.state==="truncate"){Ext.get("check-build-content").dom.innerHTML=f+'
'+_("This log is too large and have been truncated. Use the following button to download the full content of it.")+'
';new Ext.Button({scope:this,text:_("Download the full content of this log"),renderTo:"check-build-content-download-btn",style:{margin:"auto"},handler:function(){window.location.href="./do/downloadFailedBuildLog?idFailedBuild="+this.idFailedBuild+"&csrfToken="+csrfToken}})}else{Ext.get("check-build-content").dom.innerHTML=f}Ext.getCmp("main-panel").el.unmask()}})};ui.cmp._BuildStatus.ds=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getFailedBuild"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"lang"},{name:"date",type:"date",dateFormat:"Y-m-d H:i:s"}]})});ui.cmp._BuildStatus.ds.setDefaultSort("date","desc");ui.cmp._BuildStatus.rendererLanguage=function(d){var c={cs:"cz",sr:"rs",sv:"se"};return'
'+d+"
"};ui.cmp._BuildStatus.columns=[{id:"date",header:_("Date"),sortable:true,dataIndex:"date",renderer:Ext.util.Format.dateRenderer(_("Y-m-d, H:i"))},{header:_("Language"),width:45,sortable:true,dataIndex:"lang",renderer:ui.cmp._BuildStatus.rendererLanguage}];ui.cmp._BuildStatus.menu=Ext.extend(Ext.menu.Menu,{setRowIndex:function(c){this.rowIndex=c},initComponent:function(){Ext.apply(this,{items:[{scope:this,text:""+_("View in a new Tab")+"",iconCls:"iconOpenInTab",handler:function(){this.grid.fireEvent("rowdblclick",this.grid,this.rowIndex,this.event)}}]});ui.cmp._BuildStatus.menu.superclass.initComponent.call(this)}});ui.cmp.BuildStatus=Ext.extend(Ext.grid.GridPanel,{loadMask:true,bodyBorder:false,autoExpandColumn:"date",store:ui.cmp._BuildStatus.ds,columns:ui.cmp._BuildStatus.columns,view:new Ext.grid.GridView({forceFit:true}),listeners:{render:function(){this.store.load.defer(20,this.store)}},onRowdblclick:function(c,g,f){var d=this.store.getAt(g);new ui.cmp._BuildStatus.display({idFailedBuild:d.id,lang:d.data.lang})},onRowContextMenu:function(c,f,d){if(!this.menu){this.menu=new ui.cmp._BuildStatus.menu({grid:c,rowIdx:"",event:d})}d.stopEvent();this.getSelectionModel().selectRow(f);this.menu.setRowIndex(f);this.menu.showAt(d.getXY())},initComponent:function(c){ui.cmp.BuildStatus.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowdblclick",this.onRowdblclick,this);this.on("rowcontextmenu",this.onRowContextMenu,this)}});Ext.namespace("ui","ui.cmp","ui.cmp._ChangeFileOwner");ui.cmp._ChangeFileOwner.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getVCSUsers"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",fields:[{name:"userID"},{name:"authService"},{name:"userName"}]}),sortInfo:{field:"authService",direction:"ASC"}});ui.cmp.ChangeFileOwner=Ext.extend(Ext.Window,{title:_("Change file's owner"),iconCls:"iconSwitchLang",width:550,height:255,layout:"form",resizable:false,modal:true,autoScroll:true,closeAction:"close",padding:10,buttons:[{text:_("Save"),handler:function(){var d=this.ownerCt.ownerCt,c=d.items.items[1].items.items[0].getValue();new ui.task.ChangeFileOwner({fileIdDB:d.fileIdDB,newOwnerID:c,from:d})}},{text:_("Close"),handler:function(){var c=this.ownerCt.ownerCt;c.close()}}],initComponent:function(){var c=this;Ext.apply(this,{defaults:{labelWidth:120},items:[{xtype:"fieldset",title:_("Information"),iconCls:"iconInfo",width:515,items:[{xtype:"displayfield",fieldLabel:_("File"),value:this.fileFolder+this.fileName},{xtype:"displayfield",fieldLabel:_("Current owner"),value:this.currentOwner}]},{xtype:"fieldset",title:_("Action"),iconCls:"iconSwitchLang",width:515,items:[{xtype:"combo",name:"newOwner",fieldLabel:_("New owner"),editable:false,store:ui.cmp._ChangeFileOwner.store,triggerAction:"all",valueField:"userID",tpl:new Ext.XTemplate('
',"{authService} - {userName}","
"),displayField:"userName",listeners:{afterrender:function(d){d.store.load({callback:function(){d.setValue(PhDOE.user.userID)}})}}}]}]});ui.cmp.ChangeFileOwner.superclass.initComponent.call(this);this.show()}});Ext.namespace("ui","ui.cmp");ui.cmp.Chat=Ext.extend(Ext.Window,{id:"win-chat",iconCls:"iconChat",layout:"fit",width:800,height:600,modal:true,plain:true,bodyStyle:"color:#000",closeAction:"hide",initComponent:function(){var c=PhDOE.user.login;if(PhDOE.user.isAnonymous){c="an%3F%3F%3F"}Ext.apply(this,{title:_("Chat with us on IRC !"),items:[new Ext.ux.IFrameComponent({id:"frame-win-chat",url:"https://widget.mibbit.com/?settings=8eec4034df2eb666b0600bdfe151529a&server=irc.umich.edu&channel=%23php.doc&nick=poe_"+c})]});ui.cmp.Chat.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp");ui.cmp.CheckBuildPrompt=Ext.extend(Ext.Window,{title:_("Check build"),iconCls:"iconCheckBuild",layout:"form",width:350,height:200,resizable:false,modal:true,bodyStyle:"padding:5px 5px 0",labelAlign:"top",buttons:[{id:"win-check-build-btn-submit",text:_("Go !"),handler:function(){new ui.task.CheckBuildTask();this.ownerCt.ownerCt.close()}}],initComponent:function(){Ext.apply(this,{items:[{xtype:"panel",modal:false,baseCls:"x-plain",bodyStyle:"padding:5px 5px 0",html:_("You're about to check the build via this command:")+"

/usr/bin/php configure.php --with-lang="+PhDOE.user.lang+'
"},{xtype:"checkbox",id:"option-xml-details",name:"option-xml-details",checked:false,hideLabel:true,boxLabel:_("Enable detailed XML error messages"),listeners:{check:function(e,d){Ext.get("option-xml-details-span").dom.style.visibility=(d)?"visible":"hidden";Ext.get("option-xml-details-div").dom.style.visibility=(d)?"visible":"hidden"}}}]});ui.cmp.CheckBuildPrompt.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._CheckDoc");ui.cmp._CheckDoc.ds=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getCheckDocData"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"path"},{name:"extension"},{name:"check_oldstyle",type:"int"},{name:"check_undoc",type:"int"},{name:"check_roleerror",type:"int"},{name:"check_badorder",type:"int"},{name:"check_noseealso",type:"int"},{name:"check_noreturnvalues",type:"int"},{name:"check_noparameters",type:"int"},{name:"check_noexamples",type:"int"},{name:"check_noerrors",type:"int"}]})});ui.cmp._CheckDoc.ds.setDefaultSort("extension","asc");ui.cmp._CheckDoc.renderer=function(d,c){if(d>0){c.css="check_doc_cell";c.attr="ext:qtip=\" "+_("Double-click the cell to open the file selection")+'"';return d}else{return}};ui.cmp._CheckDoc.columns=[new Ext.grid.RowNumberer(),{id:"extension",header:_("Extension"),sortable:true,dataIndex:"extension"},{header:_("Not documented"),width:45,sortable:true,dataIndex:"check_undoc",renderer:ui.cmp._CheckDoc.renderer},{header:_("Old style"),width:45,sortable:true,dataIndex:"check_oldstyle",renderer:ui.cmp._CheckDoc.renderer},{header:_("Bad refsect1 order"),width:45,sortable:true,dataIndex:"check_badorder",renderer:ui.cmp._CheckDoc.renderer},{header:_("No parameters"),width:45,sortable:true,dataIndex:"check_noparameters",renderer:ui.cmp._CheckDoc.renderer},{header:_("No return values"),width:45,sortable:true,dataIndex:"check_noreturnvalues",renderer:ui.cmp._CheckDoc.renderer},{header:_("No examples"),width:45,sortable:true,dataIndex:"check_noexamples",renderer:ui.cmp._CheckDoc.renderer},{header:_("No errors section"),width:45,sortable:true,dataIndex:"check_noerrors",renderer:ui.cmp._CheckDoc.renderer},{header:_("No see also"),width:45,sortable:true,dataIndex:"check_noseealso",renderer:ui.cmp._CheckDoc.renderer},{header:_("Refsect1 role error"),width:45,sortable:true,dataIndex:"check_roleerror",renderer:ui.cmp._CheckDoc.renderer}];ui.cmp._CheckDoc.fs=new Ext.data.SimpleStore({fields:[{name:"id"},{name:"file"}]});ui.cmp._CheckDoc.FileGrid=Ext.extend(Ext.grid.GridPanel,{id:"check-doc-file-grid",store:ui.cmp._CheckDoc.fs,loadMask:true,bodyBorder:false,autoExpandColumn:"file",sm:new Ext.grid.RowSelectionModel({}),columns:[new Ext.grid.RowNumberer(),{id:"file",header:_("Files"),sortable:true,dataIndex:"file"}],onRowClick:function(){Ext.getCmp("check-doc-btn-open-selected-files").enable()},onRowContextMenu:function(c,f,d){d.stopEvent();c.getSelectionModel().selectRow(f)},onRowDblClick:function(c,d){ui.cmp.RepositoryTree.getInstance().openFile("byPath","en"+c.fpath,c.store.getAt(d).data.file);Ext.getCmp("check-doc-file-win").close()},initComponent:function(c){ui.cmp._CheckDoc.FileGrid.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowcontextmenu",this.onRowContextMenu,this);this.on("rowdblclick",this.onRowDblClick,this);this.on("rowclick",this.onRowClick,this)}});ui.cmp._CheckDoc.FileWin=Ext.extend(Ext.Window,{id:"check-doc-file-win",title:_("Files"),width:450,height:350,labelWidth:50,resizable:false,modal:true,autoScroll:true,layout:"fit",iconCls:"iconFiles",buttons:[{text:_("Open all files"),handler:function(){var e=Ext.getCmp("check-doc-file-win"),c=ui.cmp._CheckDoc.fs,d;PhDOE.AFfilePendingOpen=[];for(d=0;d"+_("Open in a new Tab")+"",iconCls:"iconOpenInTab",handler:function(){this.openTab(this.ctxRowIndex);this.menu.hide()}}]})}this.getSelectionModel().selectRow(f);d.stopEvent();if(this.ctxRowIndex){this.ctxRowIndex=null}this.ctxRowIndex=f;this.menu.showAt(d.getXY())},initComponent:function(c){this.tbar=[{xtype:"label",text:_("Status: ")},{xtype:"combo",typeAhead:true,triggerAction:"all",lazyRender:true,mode:"local",store:new Ext.data.ArrayStore({id:0,fields:["myId","displayText"],data:[["all",_("All status")],["FTP_CONNECT","FTP_CONNECT"],["FTP_LOGIN","FTP_LOGIN"],["FTP_NO_FILE","FTP_NO_FILE"],["HTTP_CONNECT","HTTP_CONNECT"],["HTTP_INTERNAL_ERROR","HTTP_INTERNAL_ERROR"],["HTTP_NOT_FOUND","HTTP_NOT_FOUND"],["HTTP_MOVED","HTTP_MOVED"],["HTTP_WRONG_HEADER","HTTP_WRONG_HEADER"],["SUCCESS","SUCCESS"],["UNKNOWN_HOST","UNKNOWN_HOST"]]}),value:"all",valueField:"myId",displayField:"displayText",editable:false,listeners:{select:function(f,d){var e=d.id;if(e==="all"){Ext.getCmp("check-entities-grid").store.clearFilter()}else{Ext.getCmp("check-entities-grid").store.filter("result",d.id)}}}}];ui.cmp.CheckEntities.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowcontextmenu",this.onContextClick,this);this.on("rowdblclick",this.onRowdblclick,this)}});Ext.namespace("ui","ui.cmp");ui.cmp.CheckEntitiesPrompt=Ext.extend(Ext.Window,{title:_("Check entities"),iconCls:"iconRun",id:"win-check-entities",layout:"fit",width:250,height:140,resizable:false,modal:true,bodyStyle:"padding:5px 5px 0; text-align: center;",labelAlign:"top",closeAction:"hide",buttons:[{id:"win-check-entities-btn",text:_("Go !"),handler:function(){new ui.task.CheckEntitiesTask();Ext.getCmp("win-check-entities").hide()}}],initComponent:function(){Ext.apply(this,{items:[{xtype:"panel",modal:false,baseCls:"x-plain",bodyStyle:"padding:5px 5px 0",html:_("You're about to check all entities.

This action takes time.")}]});ui.cmp.CheckEntitiesPrompt.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp");ui.cmp.CheckXmlWin=Ext.extend(Ext.Window,{title:_("XML Errors"),iconCls:"iconXml",width:650,height:350,layout:"fit",resizable:false,modal:true,autoScroll:true,closeAction:"close",buttons:[{text:_("Close"),handler:function(){this.ownerCt.ownerCt.close()}}],store:new Ext.data.JsonStore({root:"Items",totalProperty:"nbItems",fields:[{name:"line"},{name:"libel"}]}),addErrorsInStore:function(){var c=Ext.data.Record.create({name:"line"},{name:"libel"});this.store.removeAll();for(i=0;i"+Ext.util.Format.htmlEncode(this.errors[i].ctx1)}))}this.store.sort("line","desc")},initComponent:function(){Ext.apply(this,{items:[{xtype:"grid",store:this.store,loadMask:true,autoExpandColumn:"libel_id",colModel:new Ext.grid.ColumnModel([{header:_("Line"),dataIndex:"line",sortable:true},{id:"libel_id",header:_("Libel"),dataIndex:"libel"}]),sm:new Ext.grid.RowSelectionModel({singleSelect:true})}]});ui.cmp.CheckXmlWin.superclass.initComponent.call(this);this.addErrorsInStore();this.show()}});Ext.namespace("ui","ui.cmp","ui.cmp._CommitLogManager");ui.cmp._CommitLogManager.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getCommitLogMessage"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"text"}]})});ui.cmp._CommitLogManager.editor=new Ext.ux.grid.RowEditor({saveText:_("Update"),cancelText:_("Cancel"),listeners:{afteredit:function(e,d,c){XHR({params:{task:"saveLogMessage",messID:c.data.id,mess:c.data.text},success:function(){c.commit();PhDOE.notify("info",_("Message updated"),_("Log Message was updated successfully !"))},failure:function(){PhDOE.winForbidden()}})}}});ui.cmp._CommitLogManager.cm=new Ext.grid.ColumnModel([new Ext.grid.RowNumberer(),{id:"log_msg",header:_("Log message"),dataIndex:"text",editor:{xtype:"textarea"},renderer:function(c){return c.split("\n").join("
")}}]);ui.cmp._CommitLogManager.sm=new Ext.grid.RowSelectionModel({singleSelect:true});ui.cmp._CommitLogManager.menu=Ext.extend(Ext.menu.Menu,{setRowIdx:function(c){this.rowIdx=c},initComponent:function(){Ext.apply(this,{items:[{scope:this,text:_("Delete this Log Message"),iconCls:"iconTrash",handler:function(){XHR({scope:this,params:{task:"deleteLogMessage",messID:ui.cmp._CommitLogManager.store.getAt(this.rowIdx).data.id},success:function(){ui.cmp._CommitLogManager.store.remove(ui.cmp._CommitLogManager.store.getAt(this.rowIdx));PhDOE.notify("info",_("Message deleted"),_("Log Message was deleted successfully !"))},failure:function(){PhDOE.winForbidden()}})}}]});ui.cmp._CommitLogManager.menu.superclass.initComponent.call(this)}});ui.cmp._CommitLogManager.grid=Ext.extend(Ext.grid.GridPanel,{loadMask:true,autoExpandColumn:"log_msg",cm:ui.cmp._CommitLogManager.cm,sm:ui.cmp._CommitLogManager.sm,store:ui.cmp._CommitLogManager.store,plugins:[ui.cmp._CommitLogManager.editor],viewConfig:{emptyText:'
'+_("No log message currently")+"
"},listeners:{render:function(c){c.store.load()}},onRowContextMenu:function(c,f,d){d.stopEvent();this.getSelectionModel().selectRow(f);if(!this.menu){this.menu=new ui.cmp._CommitLogManager.menu()}this.menu.setRowIdx(f);this.menu.showAt(d.getXY())},initComponent:function(c){ui.cmp._CommitLogManager.grid.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowcontextmenu",this.onRowContextMenu,this)}});ui.cmp.CommitLogManager=Ext.extend(Ext.Window,{id:"commit-log-win",title:_("Manage Log Message"),iconCls:"iconWinManageLog",width:650,height:350,layout:"fit",resizable:false,modal:true,autoScroll:true,closeAction:"hide",store:ui.cmp._CommitLogManager.store,buttons:[{text:_("Close"),handler:function(){Ext.getCmp("commit-log-win").hide()}}],initComponent:function(){Ext.apply(this,{items:[new ui.cmp._CommitLogManager.grid()]});ui.cmp.CommitLogManager.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._CommitPrompt");ui.cmp._CommitPrompt.store=new Ext.data.GroupingStore({reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"path"},{name:"name"},{name:"by"},{name:"date",type:"date",dateFormat:"Y-m-d H:i:s"},{name:"type"}]}),sortInfo:{field:"name",direction:"ASC"},groupField:"path"});ui.cmp._CommitPrompt.columns=[new Ext.grid.CheckboxSelectionModel(),{id:"name",header:_("Files"),sortable:true,dataIndex:"name"},{header:_("Modified by"),width:45,sortable:true,dataIndex:"by"},{header:_("Date"),width:45,sortable:true,dataIndex:"date",renderer:Ext.util.Format.dateRenderer(_("Y-m-d, H:i"))},{header:_("Path"),dataIndex:"path",hidden:true}];ui.cmp._CommitPrompt.view=new Ext.grid.GroupingView({forceFit:true,groupTextTpl:'{[values.rs[0].data["path"]]} ({[values.rs.length]} {[values.rs.length > 1 ? "'+_("Files")+'" : "'+_("File")+'"]})'});ui.cmp._CommitPrompt.grid=Ext.extend(Ext.grid.GridPanel,{id:"commit-grid-panel",loadMask:true,autoExpandColumn:"name",height:180,columns:ui.cmp._CommitPrompt.columns,view:ui.cmp._CommitPrompt.view,enableDragDrop:true,sm:new Ext.grid.CheckboxSelectionModel(),listeners:{viewready:function(){this.selModel.selectAll()}},initComponent:function(){Ext.apply(this,{store:ui.cmp._CommitPrompt.store});ui.cmp._CommitPrompt.grid.superclass.initComponent.call(this)}});ui.cmp.CommitPrompt=Ext.extend(Ext.Window,{id:"winVCSCommit",layout:"form",title:_("VCS commit"),iconCls:"iconPendingCommit",closable:false,width:600,height:480,resizable:false,modal:true,bodyStyle:"padding:5px 5px 0",labelAlign:"top",patchID:false,defaultMessage:false,tools:[{id:"gear",qtip:_("Configure this tools"),handler:function(){if(!Ext.getCmp("commit-log-win")){new ui.cmp.CommitLogManager()}Ext.getCmp("commit-log-win").show(this.id)}}],listeners:{show:function(){var c=new Ext.util.DelayedTask(function(){Ext.getCmp("form-commit-message-log").focus()});c.delay(200)}},initComponent:function(){var c;ui.cmp._CommitPrompt.store.removeAll();for(c=0;c
{[values.text.split("\n").join("
")]}
',valueField:"id",displayField:"text",listEmptyText:'
'+_("No log message currently")+"
",listeners:{select:function(e,d){Ext.getCmp("form-commit-message-log").setValue(d.data.text)}}},{xtype:"textarea",id:"form-commit-message-log",name:"first3",fieldLabel:_("Log message"),anchor:"100%",height:150,value:(this.defaultMessage)?this.defaultMessage:""}]});ui.cmp.CommitPrompt.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._DictionaryGrid");ui.cmp._DictionaryGrid.store=Ext.extend(Ext.data.Store,{proxy:new Ext.data.HttpProxy({url:"./do/getDictionaryWords"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"valueEn"},{name:"valueLang"},{name:"lastUser",hideField:true},{name:"lastDate",type:"date",dateFormat:"Y-m-d H:i:s",hideField:true}]}),sortInfo:{field:"valueEn",direction:"ASC"},listeners:{load:function(){if(!PhDOE.user.isAnonymous){Ext.getCmp(this.fid+"-btn-new-word").enable()}}},initComponent:function(c){Ext.apply(this,c);ui.cmp._DictionaryGrid.store.superclass.initComponent.call(this)}});ui.cmp._DictionaryGrid.editor=Ext.extend(Ext.ux.grid.RowEditor,{saveText:_("Update"),cancelText:_("Cancel"),listeners:{afteredit:function(e,d,c,f){XHR({params:{task:"manageDictionaryWord",wordId:c.data.id,valueEn:c.data.valueEn,valueLang:c.data.valueLang},success:function(g){var h=Ext.util.JSON.decode(g.responseText);c.set("lastUser",PhDOE.user.login);c.set("lastDate",Date.parseDate(h.dateUpdate,"Y-m-d H:i:s"));c.commit();PhDOE.notify("info",_("Word in dictionary added/updated"),_("The word have been added/updated successfully !"))},failure:function(){PhDOE.winForbidden()}})},canceledit:function(c){if(c.record.data.id==="new"){c.record.store.remove(c.record)}}}});ui.cmp._DictionaryGrid.sm=Ext.extend(Ext.grid.RowSelectionModel,{singleSelect:true});ui.cmp._DictionaryGrid.viewConfig={forceFit:true,emptyText:'
'+_("You must manually load this data.
Use the refresh button !")+"
",deferEmptyText:false};ui.cmp._DictionaryGrid.menu=Ext.extend(Ext.menu.Menu,{setRowIdx:function(c){this.rowIdx=c},initComponent:function(){Ext.apply(this,{items:[{scope:this,text:_("Delete this word"),iconCls:"iconTrash",disabled:(PhDOE.user.isAnonymous),handler:function(){XHR({scope:this,params:{task:"delDictionaryWord",wordId:this.grid.store.getAt(this.rowIdx).data.id},success:function(){this.grid.store.remove(this.grid.store.getAt(this.rowIdx));PhDOE.notify("info",_("Word deleted"),_("The word was deleted successfully !"))},failure:function(){PhDOE.winForbidden()}})}}]});ui.cmp._DictionaryGrid.menu.superclass.initComponent.call(this)}});ui.cmp._DictionaryGrid.grid=Ext.extend(Ext.grid.GridPanel,{onRowContextMenu:function(c,f,d){d.stopEvent();this.getSelectionModel().selectRow(f);if(!this.menu){this.menu=new ui.cmp._DictionaryGrid.menu({grid:c})}this.menu.setRowIdx(f);this.menu.showAt(d.getXY())},initComponent:function(){Ext.apply(this,{region:"center",split:true,loadMask:true,autoScroll:true,bodyBorder:false,border:false,autoExpandColumn:this.dataType,columns:[{id:"id",header:_("En word"),sortable:true,dataIndex:"valueEn",editor:{xtype:"textfield"}},{header:String.format(_("{0} word"),PhDOE.user.lang.ucFirst()),sortable:true,dataIndex:"valueLang",editor:{xtype:"textfield"}},{header:_("Last User Update"),sortable:true,dataIndex:"lastUser",editor:{xtype:"displayfield",hideField:true}},{header:_("Last Date Update"),sortable:true,dataIndex:"lastDate",editor:{xtype:"displayfield",hideField:true},renderer:Ext.util.Format.dateRenderer(_("Y-m-d, H:i"))}],viewConfig:ui.cmp._DictionaryGrid.viewConfig,sm:new ui.cmp._DictionaryGrid.sm(),store:new ui.cmp._DictionaryGrid.store({fid:this.fid}),plugins:[new ui.cmp._DictionaryGrid.editor()],tbar:[{scope:this,tooltip:_("Load/Refresh"),iconCls:"iconRefresh",handler:function(){this.store.reload()}},"->",{scope:this,id:this.fid+"-btn-new-word",disabled:true,text:_("Add a new word"),iconCls:"iconNewWord",handler:function(){var c=Ext.data.Record.create([{name:"id"},{name:"valueEn"},{name:"valueLang"},{name:"lastUser"},{name:"lastDate"}]),d=new Date(),f=new c({id:"new",valueEn:"",valueLang:"",lastUser:PhDOE.user.login,lastDate:d});this.plugins[0].stopEditing();this.store.insert(0,f);this.getView().refresh();this.getSelectionModel().selectRow(0);this.plugins[0].startEditing(0)}}]});ui.cmp._DictionaryGrid.grid.superclass.initComponent.call(this);this.on("rowcontextmenu",this.onRowContextMenu,this)}});ui.cmp.DictionaryGrid=Ext.extend(Ext.Panel,{initComponent:function(){Ext.apply(this,{layout:"border",border:false,items:[new ui.cmp._DictionaryGrid.grid({dataType:this.dataType,prefix:this.prefix,fid:this.fid,ftype:this.ftype,loadStore:this.loadStore})]});ui.cmp.DictionaryGrid.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._EditorConf","ui.cmp._EditorCmd2Conf");ui.cmp._EditorConf.tplMenu=new Ext.XTemplate('','","");ui.cmp._EditorConf.tplMenu.compile();ui.cmp._EditorConf.menuDefEn=[["1","card1",_("Main")],["4","card4",_('Module "Files with error"')],["6","card6",_('Module "All files"')]];ui.cmp._EditorConf.menuDefNonEn=[["1","card1",_("Main")],["2","card2",_('Module "Files need translate"')],["3","card3",_('Module "Files need update"')],["4","card4",_('Module "Files with error"')],["5","card5",_('Module "Files need reviewed"')],["6","card6",_('Module "All files"')]];ui.cmp._EditorConf.menuStore=new Ext.data.SimpleStore({id:0,fields:[{name:"id"},{name:"card"},{name:"label"}]});ui.cmp._EditorConf.viewMenu=Ext.extend(Ext.DataView,{id:"conf-menu-view",tpl:ui.cmp._EditorConf.tplMenu,singleSelect:true,overClass:"x-view-over",itemSelector:"div.menu-wrap",store:ui.cmp._EditorConf.menuStore,listeners:{selectionchange:function(c){var d=c.getSelectedRecords();Ext.getCmp("confCard").layout.setActiveItem("conf-card-"+d[0].data.id)}}});ui.cmp._EditorCmd2Conf.themeStore=new Ext.data.SimpleStore({fields:["themeFile",{name:"themeName",type:"string"}],data:[[false,_("No theme")],["default",_("Default theme")],["cobalt",_("Cobalt")],["eclipse",_("Eclipse")],["elegant",_("Elegant")],["monokai",_("Monokai")],["neat",_("Neat")],["night",_("Night")],["rubyblue",_("RubyBlue")]]});ui.cmp._EditorConf.themeStore=new Ext.data.SimpleStore({fields:["themeFile",{name:"themeName",type:"string"}],data:[["themes/ExtJsThemes/black/css/xtheme-black.css",_("Black")],["themes/empty.css",_("Default")],["themes/ExtJsThemes/darkgray/css/xtheme-darkgray.css",_("DarkGray")],["js/ExtJs/resources/css/xtheme-gray.css",_("Gray")],["themes/ExtJsThemes/gray-extend/css/xtheme-gray-extend.css",_("Gray Extend")],["themes/ExtJsThemes/indigo/css/xtheme-indigo.css",_("Indigo")],["themes/ExtJsThemes/midnight/css/xtheme-midnight.css",_("Midnight")],["themes/ExtJsThemes/olive/css/xtheme-olive.css",_("Olive")],["themes/ExtJsThemes/purple/css/xtheme-purple.css",_("Purple")],["themes/ExtJsThemes/silverCherry/css/xtheme-silverCherry.css",_("SilverCherry")],["themes/ExtJsThemes/ubuntu_human/css/xtheme-human.css",_("Ubuntu Human")]]});ui.cmp._EditorConf.uiLangStore=new Ext.data.SimpleStore({fields:["uiLang",{name:"uiLangName",type:"string"}],data:[["default",_("Default language, if available")],["en",_("English")],["fr",_("French")],["ru",_("Russian")],["es",_("Spanish")],["ar",_("Arabic")]]});ui.cmp._EditorConf.CommitChange=new Ext.util.DelayedTask(function(){new ui.task.UpdateConfTask({module:this.module,itemName:this.itemName,value:this.getValue()})});ui.cmp._EditorConf.card1=Ext.extend(Ext.TabPanel,{id:"conf-card-1",autoScroll:true,activeTab:0,defaults:{bodyStyle:"padding: 5px;",autoHeight:true,autoScroll:true},initComponent:function(){Ext.apply(this,{items:[{title:_("User Interface"),iconCls:"iconUI",labelAlign:"top",layout:"form",items:[{xtype:"fieldset",title:_("Main menu"),iconCls:"iconMenu",items:[{xtype:"spinnerfield",width:60,name:"PhDOE.user.conf.main.mainMenuWidth",module:"main",itemName:"mainMenuWidth",value:PhDOE.user.conf.main.mainMenuWidth||300,fieldLabel:_("Main menu width"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){var c=Ext.getCmp("main-menu-panel"),d=this.getValue();PhDOE.user.conf.main.mainMenuWidth=d;c.setWidth(d);c.ownerCt.doLayout();ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){var c=Ext.getCmp("main-menu-panel"),d=this.getValue();PhDOE.user.conf.main.mainMenuWidth=d;c.setWidth(d);c.ownerCt.doLayout();ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}}]},{xtype:"fieldset",iconCls:"iconThemes",title:_("Appearance"),items:[{xtype:"combo",fieldLabel:_("Choose a theme"),id:"conf-combo-theme",valueField:"themeFile",displayField:"themeName",triggerAction:"all",mode:"local",forceSelection:true,editable:false,value:PhDOE.user.conf.main.theme,store:ui.cmp._EditorConf.themeStore,listeners:{render:function(){Ext.getCmp("conf-combo-theme").store.sort("themeName")},select:function(e){var d=e.getValue();Ext.get("appTheme").dom.href=d;new ui.task.UpdateConfTask({module:"main",itemName:"theme",value:d})}}},{xtype:"combo",fieldLabel:_("Force an UI language"),id:"conf-combo-ui-lang",valueField:"uiLang",displayField:"uiLangName",triggerAction:"all",mode:"local",forceSelection:true,editable:false,value:PhDOE.user.conf.main.uiLang||"default",store:ui.cmp._EditorConf.uiLangStore,listeners:{select:function(e){var d=e.getValue();new ui.task.UpdateConfTask({module:"main",itemName:"uiLang",value:d})}}}]},{xtype:"fieldset",title:_("On save file"),iconCls:"iconSaveFile",autoHeight:true,defaults:{hideLabel:true},defaultType:"radio",items:[{autoHeight:true,name:"PhDOE.user.conf.main.onSaveFile",module:"main",itemName:"onSaveFile",checked:(PhDOE.user.conf.main.onSaveFile==="ask-me")?true:false,boxLabel:_("Ask me if I want to check for error before saving the file"),inputValue:"ask-me",listeners:{check:function(c){if(c.checked){new ui.task.UpdateConfTask({module:"main",itemName:"onSaveFile",value:c.getRawValue()})}}}},{autoHeight:true,name:"PhDOE.user.conf.main.onSaveFile",module:"main",itemName:"onSaveFile",checked:(PhDOE.user.conf.main.onSaveFile==="always")?true:false,boxLabel:_("Always check for error before saving the file"),inputValue:"always",listeners:{check:function(c){if(c.checked){new ui.task.UpdateConfTask({module:"main",itemName:"onSaveFile",value:c.getRawValue()})}}}},{autoHeight:true,name:"PhDOE.user.conf.main.onSaveFile",module:"main",itemName:"onSaveFile",checked:(PhDOE.user.conf.main.onSaveFile==="never")?true:false,boxLabel:_("Never check for error before saving the file"),inputValue:"never",listeners:{check:function(c){if(c.checked){new ui.task.UpdateConfTask({module:"main",itemName:"onSaveFile",value:c.getRawValue()})}}}}]},{xtype:"checkbox",name:"PhDOE.user.conf.main.displayENWork",checked:PhDOE.user.conf.main.displayENWork,boxLabel:_('Display EN work in "Work in progress" & "Patches for review" modules'),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"main",itemName:"displayENWork",value:c.getValue()})}}}]},{title:_("External Data"),iconCls:"iconExternalData",items:[{xtype:"fieldset",title:_("About mails"),iconCls:"iconMailing",defaults:{hideLabel:true},defaultType:"checkbox",items:[{autoHeight:true,name:"PhDOE.user.conf.main.loadMailsAtStartUp",checked:PhDOE.user.conf.main.loadMailsAtStartUp,boxLabel:_("Load mail at startUp"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"main",itemName:"loadMailsAtStartUp",value:c.getValue()})}}}]},{xtype:"fieldset",title:_("About bugs"),iconCls:"iconBugs",defaults:{hideLabel:true},defaultType:"checkbox",items:[{autoHeight:true,name:"PhDOE.user.conf.main.loadBugsAtStartUp",checked:PhDOE.user.conf.main.loadBugsAtStartUp,boxLabel:_("Load bugs at startUp"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"main",itemName:"loadBugsAtStartUp",value:c.getValue()})}}}]}]},{title:_("Editor"),iconCls:"iconEditor",items:[{xtype:"fieldset",title:_("Editor theme"),iconCls:"iconThemes",items:[{xtype:"combo",fieldLabel:_("Choose a theme"),id:"conf-combo-cm2-theme",valueField:"themeFile",displayField:"themeName",triggerAction:"all",mode:"local",forceSelection:true,editable:false,value:(PhDOE.user.conf.main.editorTheme||"default"),store:ui.cmp._EditorCmd2Conf.themeStore,listeners:{select:function(e){var d=e.getValue();new ui.task.UpdateConfTask({module:"main",itemName:"editorTheme",value:d})}}}]}]}]});ui.cmp._EditorConf.card1.superclass.initComponent.call(this)}});ui.cmp._EditorConf.card2=Ext.extend(Ext.TabPanel,{id:"conf-card-2",autoScroll:true,activeTab:0,defaults:{bodyStyle:"padding: 5px;",autoHeight:true,autoScroll:true},initComponent:function(){Ext.apply(this,{items:[{title:_("Menu"),iconCls:"iconMenu",items:[{xtype:"fieldset",title:_("Nb files to display"),iconCls:"iconFilesToDisplay",defaults:{hideLabel:true},items:[{xtype:"spinnerfield",width:60,name:"PhDOE.user.conf.newFile.nbDisplay",module:"newFile",itemName:"nbDisplay",value:PhDOE.user.conf.newFile.nbDisplay||0,boxLabel:_("files to display"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}},{xtype:"displayfield",value:_("0 means no limit"),style:{fontStyle:"italic"}}]}]},{title:_("User Interface"),iconCls:"iconUI",items:[{xtype:"fieldset",title:_("ScrollBars"),iconCls:"iconScrollBar",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"PhDOE.user.conf.newFile.syncScrollbars",checked:PhDOE.user.conf.newFile.syncScrollbars,boxLabel:_("Synchronize scroll bars"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"newFile",itemName:"syncScrollbars",value:c.getValue()})}}}]},{xtype:"fieldset",title:_("Tools"),iconCls:"iconConf",defaults:{hideLabel:true},defaultType:"checkbox",items:[{xtype:"fieldset",checkboxToggle:true,collapsed:!PhDOE.user.conf.newFile.toolsPanelDisplay,title:_("Start with the panel open"),listeners:{collapse:function(){new ui.task.UpdateConfTask({module:"newFile",itemName:"toolsPanelDisplay",value:false})},expand:function(){new ui.task.UpdateConfTask({module:"newFile",itemName:"toolsPanelDisplay",value:true})}},items:[{xtype:"spinnerfield",width:60,name:"newFile.toolsPanelWidth",module:"newFile",itemName:"toolsPanelWidth",value:PhDOE.user.conf.newFile.toolsPanelWidth||375,fieldLabel:_("Panel width"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}}]}]},{xtype:"fieldset",title:_("Right panel"),iconCls:"iconUI",defaults:{hideLabel:true},defaultType:"radio",items:[{name:"PhDOE.user.conf.newFile.secondPanel",boxLabel:_("Display the Google Translation Panel"),inputValue:"google",checked:(PhDOE.user.conf.newFile.secondPanel==="google")?true:false,listeners:{check:function(c){if(c.checked){new ui.task.UpdateConfTask({module:"newFile",itemName:"secondPanel",value:c.getRawValue()})}}}},{name:"PhDOE.user.conf.newFile.secondPanel",boxLabel:_("Display the original file"),inputValue:"originalFile",checked:(PhDOE.user.conf.newFile.secondPanel==="originalFile")?true:false,listeners:{check:function(c){if(c.checked){new ui.task.UpdateConfTask({module:"newFile",itemName:"secondPanel",value:c.getRawValue()})}}}},{name:"PhDOE.user.conf.newFile.secondPanel",boxLabel:_("Do not display a right panel"),inputValue:"none",checked:(!Ext.isDefined(PhDOE.user.conf.newFile.secondPanel)||PhDOE.user.conf.newFile.secondPanel==="none")?true:false,listeners:{check:function(c){if(c.checked){new ui.task.UpdateConfTask({module:"newFile",itemName:"secondPanel",value:c.getRawValue()})}}}}]}]}]});ui.cmp._EditorConf.card2.superclass.initComponent.call(this)}});ui.cmp._EditorConf.card3=Ext.extend(Ext.TabPanel,{id:"conf-card-3",autoScroll:true,activeTab:0,defaults:{bodyStyle:"padding: 5px;",autoHeight:true,autoScroll:true},initComponent:function(){Ext.apply(this,{items:[{title:_("Menu"),iconCls:"iconMenu",items:[{xtype:"fieldset",title:_("Nb files to display"),iconCls:"iconFilesToDisplay",defaults:{hideLabel:true},defaultType:"spinnerfield",items:[{width:60,name:"PhDOE.user.conf.needUpdate.nbDisplay",module:"needUpdate",itemName:"nbDisplay",value:PhDOE.user.conf.needUpdate.nbDisplay||0,boxLabel:_("files to display"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}},{xtype:"displayfield",value:_("0 means no limit"),style:{fontStyle:"italic"}}]}]},{title:_("User Interface"),iconCls:"iconUI",items:[{xtype:"fieldset",title:_("ScrollBars"),iconCls:"iconScrollBar",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"needUpdate.syncScrollbars",checked:PhDOE.user.conf.needUpdate.syncScrollbars,boxLabel:_("Synchronize scroll bars"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"syncScrollbars",value:c.getValue()})}}}]},{xtype:"fieldset",title:_("Tools"),iconCls:"iconConf",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"needUpdate.toolsPanelLogLoad",checked:PhDOE.user.conf.needUpdate.toolsPanelLogLoad,boxLabel:_("Automatically load the log when displaying the file"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"toolsPanelLogLoad",value:c.getValue()})}}},{xtype:"fieldset",checkboxToggle:true,collapsed:!PhDOE.user.conf.needUpdate.toolsPanelDisplay,title:_("Start with the panel open"),listeners:{collapse:function(){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"toolsPanelDisplay",value:false})},expand:function(){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"toolsPanelDisplay",value:true})}},items:[{xtype:"spinnerfield",width:60,name:"needUpdate.toolsPanelWidth",module:"needUpdate",itemName:"toolsPanelWidth",value:PhDOE.user.conf.needUpdate.toolsPanelWidth||375,fieldLabel:_("Panel width"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}}]}]},{xtype:"fieldset",title:_("Diff view"),iconCls:"iconDiffView",defaults:{hideLabel:true},defaultType:"radio",items:[{xtype:"fieldset",checkboxToggle:true,collapsed:!PhDOE.user.conf.needUpdate.diffPanelDisplay,title:_("Start with the panel open"),listeners:{collapse:function(){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"diffPanelDisplay",value:false})},expand:function(){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"diffPanelDisplay",value:true})}},items:[{xtype:"spinnerfield",width:60,name:"needUpdate.diffPanelHeight",module:"needUpdate",itemName:"diffPanelHeight",value:PhDOE.user.conf.needUpdate.diffPanelHeight||150,fieldLabel:_("Panel height"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}}]},{name:"needUpdate.diffMethod",checked:(PhDOE.user.conf.needUpdate.diffMethod==="using-viewvc")?true:false,boxLabel:_("Using ViewVc from php web site"),inputValue:"using-viewvc",listeners:{check:function(c){if(c.checked){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"diffMethod",value:c.getRawValue()})}}}},{name:"needUpdate.diffMethod",checked:(PhDOE.user.conf.needUpdate.diffMethod==="using-exec")?true:false,boxLabel:_("Using diff -u command line"),inputValue:"using-exec",listeners:{check:function(c){if(c.checked){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"diffMethod",value:c.getRawValue()})}}}}]}]}]});ui.cmp._EditorConf.card3.superclass.initComponent.call(this)}});ui.cmp._EditorConf.card4=Ext.extend(Ext.TabPanel,{id:"conf-card-4",autoScroll:true,activeTab:0,defaults:{bodyStyle:"padding: 5px;",autoHeight:true,autoScroll:true},initComponent:function(){Ext.apply(this,{items:[{title:_("Menu"),iconCls:"iconMenu",items:[{xtype:"fieldset",title:_("Nb files to display"),iconCls:"iconFilesToDisplay",defaults:{hideLabel:true},defaultType:"spinnerfield",items:[{width:60,name:"PhDOE.user.conf.error.nbDisplay",module:"error",itemName:"nbDisplay",value:PhDOE.user.conf.error.nbDisplay||0,boxLabel:_("files to display"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}},{xtype:"displayfield",value:_("0 means no limit"),style:{fontStyle:"italic"}}]},{hidden:(PhDOE.user.lang==="en"),xtype:"fieldset",title:_("Error type"),iconCls:"iconFilesError",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"error.skipNbLiteralTag",checked:PhDOE.user.conf.error.skipNbLiteralTag,boxLabel:_("Skip nbLiteralTag error"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"error",itemName:"skipNbLiteralTag",value:c.getValue()})}}}]}]},{title:_("User Interface"),iconCls:"iconUI",items:[{xtype:"fieldset",title:_("ScrollBars"),iconCls:"iconScrollBar",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"error.syncScrollbars",checked:PhDOE.user.conf.error.syncScrollbars,boxLabel:_("Synchronize scroll bars"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"error",itemName:"syncScrollbars",value:c.getValue()})}}}]},{xtype:"fieldset",title:_("Tools"),iconCls:"iconConf",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"error.toolsPanelLogLoad",checked:PhDOE.user.conf.error.toolsPanelLogLoad,boxLabel:_("Automatically load the log when displaying the file"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"error",itemName:"toolsPanelLogLoad",value:c.getValue()})}}},{name:"error.toolsPanelEntitiesLoad",checked:PhDOE.user.conf.error.toolsPanelEntitiesLoad,boxLabel:_("Automatically load entities data when displaying the file"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"error",itemName:"toolsPanelEntitiesLoad",value:c.getValue()})}}},{name:"error.toolsPanelAcronymsLoad",checked:PhDOE.user.conf.error.toolsPanelAcronymsLoad,boxLabel:_("Automatically load acronyms data when displaying the file"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"error",itemName:"toolsPanelAcronymsLoad",value:c.getValue()})}}},{xtype:"fieldset",checkboxToggle:true,collapsed:!PhDOE.user.conf.error.toolsPanelDisplay,title:_("Start with the panel open"),listeners:{collapse:function(){new ui.task.UpdateConfTask({module:"error",itemName:"toolsPanelDisplay",value:false})},expand:function(){new ui.task.UpdateConfTask({module:"error",itemName:"toolsPanelDisplay",value:true})}},items:[{xtype:"spinnerfield",width:60,name:"error.toolsPanelWidth",module:"error",itemName:"toolsPanelWidth",value:PhDOE.user.conf.error.toolsPanelWidth||375,fieldLabel:_("Panel width"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}}]}]},{xtype:"fieldset",title:_("Error description"),iconCls:"iconFilesError",defaults:{hideLabel:true},defaultType:"radio",items:[{xtype:"fieldset",checkboxToggle:true,collapsed:!PhDOE.user.conf.error.descPanelDisplay,title:_("Start with the panel open"),listeners:{collapse:function(){new ui.task.UpdateConfTask({module:"error",itemName:"descPanelDisplay",value:false})},expand:function(){new ui.task.UpdateConfTask({module:"error",itemName:"descPanelDisplay",value:true})}},items:[{xtype:"spinnerfield",width:60,name:"error.descPanelHeight",module:"error",itemName:"descPanelHeight",value:PhDOE.user.conf.error.descPanelHeight||150,fieldLabel:_("Panel height"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}}]}]}]}]});ui.cmp._EditorConf.card4.superclass.initComponent.call(this)}});ui.cmp._EditorConf.card5=Ext.extend(Ext.TabPanel,{id:"conf-card-5",autoScroll:true,activeTab:0,defaults:{bodyStyle:"padding: 5px;",autoHeight:true,autoScroll:true},initComponent:function(){Ext.apply(this,{items:[{title:_("Menu"),iconCls:"iconMenu",items:[{xtype:"fieldset",title:_("Nb files to display"),iconCls:"iconFilesToDisplay",defaults:{hideLabel:true},defaultType:"spinnerfield",items:[{width:60,name:"reviewed.nbDisplay",module:"reviewed",itemName:"nbDisplay",value:PhDOE.user.conf.reviewed.nbDisplay||0,boxLabel:_("files to display"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}},{xtype:"displayfield",value:_("0 means no limit"),style:{fontStyle:"italic"}}]}]},{title:_("User Interface"),iconCls:"iconUI",items:[{xtype:"fieldset",title:_("ScrollBars"),iconCls:"iconScrollBar",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"reviewed.syncScrollbars",checked:PhDOE.user.conf.reviewed.syncScrollbars,boxLabel:_("Synchronize scroll bars"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"reviewed",itemName:"syncScrollbars",value:c.getValue()})}}}]},{xtype:"fieldset",title:_("Tools"),iconCls:"iconConf",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"reviewed.toolsPanelLogLoad",checked:PhDOE.user.conf.reviewed.toolsPanelLogLoad,boxLabel:_("Automatically load the log when displaying the file"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"reviewed",itemName:"toolsPanelLogLoad",value:c.getValue()})}}},{xtype:"fieldset",checkboxToggle:true,collapsed:!PhDOE.user.conf.reviewed.toolsPanelDisplay,title:_("Start with the panel open"),listeners:{collapse:function(){new ui.task.UpdateConfTask({module:"reviewed",itemName:"toolsPanelDisplay",value:false})},expand:function(){new ui.task.UpdateConfTask({module:"reviewed",itemName:"toolsPanelDisplay",value:true})}},items:[{xtype:"spinnerfield",width:60,name:"reviewed.toolsPanelWidth",module:"reviewed",itemName:"toolsPanelWidth",value:PhDOE.user.conf.reviewed.toolsPanelWidth||375,fieldLabel:_("Panel width"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}}]}]}]}]});ui.cmp._EditorConf.card5.superclass.initComponent.call(this)}});ui.cmp._EditorConf.card6=Ext.extend(Ext.TabPanel,{id:"conf-card-6",autoScroll:true,activeTab:0,defaults:{bodyStyle:"padding: 5px;",autoHeight:true,autoScroll:true},initComponent:function(){Ext.apply(this,{items:[{title:_("User Interface"),iconCls:"iconUI",items:[{xtype:"fieldset",title:_("Tools"),iconCls:"iconConf",defaults:{hideLabel:true},defaultType:"checkbox",items:[{name:"allFiles.toolsPanelLogLoad",checked:PhDOE.user.conf.allFiles.toolsPanelLogLoad,boxLabel:_("Automatically load the log when displaying the file"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"allFiles",itemName:"toolsPanelLogLoad",value:c.getValue()})}}},{name:"allFiles.toolsPanelEntitiesLoad",checked:PhDOE.user.conf.allFiles.toolsPanelEntitiesLoad,boxLabel:_("Automatically load entities data when displaying the file"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"allFiles",itemName:"toolsPanelEntitiesLoad",value:c.getValue()})}}},{name:"allFiles.toolsPanelAcronymsLoad",checked:PhDOE.user.conf.allFiles.toolsPanelAcronymsLoad,boxLabel:_("Automatically load acronyms data when displaying the file"),listeners:{check:function(c){new ui.task.UpdateConfTask({module:"allFiles",itemName:"toolsPanelAcronymsLoad",value:c.getValue()})}}},{xtype:"fieldset",checkboxToggle:true,collapsed:!PhDOE.user.conf.allFiles.toolsPanelDisplay,title:_("Start with the panel open"),listeners:{collapse:function(){new ui.task.UpdateConfTask({module:"allFiles",itemName:"toolsPanelDisplay",value:false})},expand:function(){new ui.task.UpdateConfTask({module:"allFiles",itemName:"toolsPanelDisplay",value:true})}},items:[{xtype:"spinnerfield",width:60,name:"allFiles.toolsPanelWidth",module:"allFiles",itemName:"toolsPanelWidth",value:PhDOE.user.conf.allFiles.toolsPanelWidth||375,fieldLabel:_("Panel width"),minValue:0,maxValue:10000,accelerate:true,enableKeyEvents:true,listeners:{keyup:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)},spin:function(){ui.cmp._EditorConf.CommitChange.delay(1000,null,this)}}}]}]}]}]});ui.cmp._EditorConf.card6.superclass.initComponent.call(this)}});ui.cmp.EditorConf=Ext.extend(Ext.Window,{id:"win-conf",layout:"border",width:700,height:470,iconCls:"iconConf",title:_("Configuration"),modal:true,plain:true,bodyBorder:false,closeAction:"hide",buttons:[{text:_("Close"),handler:function(){Ext.getCmp("win-conf").hide()}}],listeners:{show:function(){var c=Ext.getCmp("conf-menu-view");c.select(c.getNode(0))}},initComponent:function(){if(PhDOE.user.lang==="en"){ui.cmp._EditorConf.menuStore.loadData(ui.cmp._EditorConf.menuDefEn)}else{ui.cmp._EditorConf.menuStore.loadData(ui.cmp._EditorConf.menuDefNonEn)}Ext.apply(this,{items:[{id:"confMenu",region:"west",border:false,width:190,autoScroll:true,items:[new ui.cmp._EditorConf.viewMenu()]},{id:"confCard",region:"center",border:false,layout:"card",width:375,frame:true,activeItem:0,bbar:new Ext.ux.StatusBar({defaultText:_("All changes take effect immediately"),defaultIconCls:"confStatusBar"}),items:[new ui.cmp._EditorConf.card1(),new ui.cmp._EditorConf.card2(),new ui.cmp._EditorConf.card3(),new ui.cmp._EditorConf.card4(),new ui.cmp._EditorConf.card5(),new ui.cmp._EditorConf.card6()]}]});ui.cmp.EditorConf.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._EmailPrompt");ui.cmp.EmailPrompt=Ext.extend(Ext.Window,{title:_("Send an email"),width:500,height:300,minWidth:300,minHeight:200,layout:"fit",plain:true,bodyStyle:"padding:5px;",buttonAlign:"center",iconCls:"iconSendEmail",closeAction:"hide",buttons:[{text:_("Send"),handler:function(){var d=this.ownerCt.ownerCt,c=d.findByType("form").shift().getForm().getValues();XHR({params:{task:"sendEmail",to:c.to,subject:c.subject,msg:c.msg},success:function(){d.hide();Ext.Msg.alert(_("Status"),String.format(_("Email sent to {0} with success!"),d.name.ucFirst()),Ext.emptyFn)},failure:function(){PhDOE.winForbidden()}})}},{text:_("Cancel"),handler:function(){this.ownerCt.ownerCt.hide()}}],setData:function(d,c){this.name=d;this.email=c;this.items.items[0].items.items[0].setValue('"'+this.name.ucFirst()+'" <'+this.email+">");this.items.items[0].items.items[1].setValue("");this.items.items[0].items.items[2].setValue("")},initComponent:function(){Ext.apply(this,{items:new Ext.form.FormPanel({baseCls:"x-plain",labelWidth:55,defaultType:"textfield",items:[{name:"to",fieldLabel:_("Send To"),readOnly:true,anchor:"100%",value:""},{name:"subject",fieldLabel:_("Subject"),anchor:"100%"},{name:"msg",xtype:"textarea",hideLabel:true,anchor:"100% -53"}]})});ui.cmp.EmailPrompt.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._EntitiesAcronymsPanel");ui.cmp._EntitiesAcronymsPanel.grid=Ext.extend(Ext.grid.GridPanel,{onRowClick:function(c){var d=c.getSelectionModel().getSelected().data;Ext.getCmp(this.dataType+"-details-"+this.fid).update(d.value)},onRowDblClick:function(d){var f=d.getSelectionModel().getSelected().data,e=Ext.getCmp(this.prefix+"-"+this.ftype+"-FILE-"+this.fid),c=Ext.util.JSON.decode(e.getCursorPosition()),g=(this.dataType==="entities")?"&"+f.items+";":""+f.items+"";e.insertIntoLine(c.line,c.caracter,g)},initComponent:function(){var c;if(this.dataType==="entities"){c="./do/getEntities"}else{if(this.dataType==="acronyms"){c="./do/getAcronyms"}}Ext.apply(this,{region:"center",split:true,loadMask:true,autoScroll:true,bodyBorder:false,border:false,autoExpandColumn:this.dataType,columns:[{id:"items",header:_("Items"),sortable:true,dataIndex:"items"},{header:_("From"),sortable:true,dataIndex:"from",width:50}],viewConfig:{forceFit:true,emptyText:'
'+_("You must manually load this data.
Use the refresh button !")+"

"+_("(You can change this behavior by setting an option in the configuration window)")+"
",deferEmptyText:false},sm:new Ext.grid.RowSelectionModel({singleSelect:true}),store:new Ext.data.Store({autoLoad:this.loadStore,proxy:new Ext.data.HttpProxy({url:c}),listeners:{scope:this,load:function(){if(this.dataType==="entities"){Ext.getCmp(this.prefix+"-"+this.fid).panEntities=true}else{if(this.dataType==="acronyms"){Ext.getCmp(this.prefix+"-"+this.fid).panAcronyms=true}}Ext.getCmp("main-panel").fireEvent("tabLoaded",this.prefix,this.fid)}},reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"from"},{name:"items"},{name:"value"}]})}),tbar:[{scope:this,tooltip:_("Load/Refresh"),iconCls:"iconRefresh",handler:function(){this.store.reload()}},_("Filter: ")," ",new Ext.form.TwinTriggerField({width:180,hideTrigger1:true,enableKeyEvents:true,validateOnBlur:false,validationEvent:false,trigger1Class:"x-form-clear-trigger",trigger2Class:"x-form-search-trigger",listeners:{specialkey:function(d,g){if(g.getKey()===g.ENTER){this.onTrigger2Click()}}},onTrigger1Click:function(){this.setValue("");this.triggers[0].hide();this.setSize(180,10);this.ownerCt.ownerCt.store.clearFilter()},onTrigger2Click:function(){var d=this.getValue(),e;if(d===""||d.length<3){this.markInvalid(_("Your filter must contain at least 3 characters"));return}this.clearInvalid();this.triggers[0].show();this.setSize(180,10);e=new RegExp(d,"i");this.ownerCt.ownerCt.store.filterBy(function(f){if(e.test(f.data.from)||e.test(f.data.items)||e.test(f.data.value)){return true}else{return false}},this)}})]});ui.cmp._EntitiesAcronymsPanel.grid.superclass.initComponent.call(this);this.on("rowclick",this.onRowClick,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp.EntitiesAcronymsPanel=Ext.extend(Ext.Panel,{initComponent:function(){var c;if(this.dataType==="entities"){c=_("Click on a row to display the content of the entitie.
Double-click on it to insert it at the cursor position.")}else{if(this.dataType==="acronyms"){c=_("Click on a row to display the content of the acronym.
Double-click on it to insert it at the cursor position.")}}Ext.apply(this,{layout:"border",border:false,items:[new ui.cmp._EntitiesAcronymsPanel.grid({dataType:this.dataType,prefix:this.prefix,fid:this.fid,ftype:this.ftype,loadStore:this.loadStore}),{xtype:"panel",id:this.dataType+"-details-"+this.fid,region:"south",split:true,height:100,autoScroll:true,bodyBorder:false,bodyCssClass:this.dataType+"-details",html:c}]});ui.cmp.EntitiesAcronymsPanel.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._ErrorFileGrid");ui.cmp._ErrorFileGrid.store=new Ext.data.GroupingStore({proxy:new Ext.data.HttpProxy({url:"./do/getFilesError"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"path"},{name:"name"},{name:"maintainer"},{name:"type"},{name:"value_en"},{name:"value_lang"},{name:"fileModifiedEN"},{name:"fileModifiedLang"}]}),sortInfo:{field:"path",direction:"ASC"},groupField:"path",listeners:{datachanged:function(e){var c=e.getCount(),d=false;if(!PhDOE.user.isAnonymous){e.each(function(f){if(f.data.maintainer==PhDOE.user.login){d++}},this)}Ext.getDom("acc-error-nb").innerHTML=c+(d?(" - "+String.format(_("{0} mine"),d)):"")}}});ui.cmp._ErrorFileGrid.columns=[{id:"name",header:_("Files"),sortable:true,dataIndex:"name",renderer:function(c,f,d){var h="",g,e;if(d.data.fileModifiedEN){g=Ext.util.JSON.decode(d.data.fileModifiedEN);if(g.user===PhDOE.user.login&&g.anonymousIdent===PhDOE.user.anonymousIdent){h=_("File EN modified by me")+"
"}else{h=String.format(_("File EN modified by {0}"),g.user)+"
"}}if(d.data.fileModifiedLang){e=Ext.util.JSON.decode(d.data.fileModifiedLang);if(e.user===PhDOE.user.login&&e.anonymousIdent===PhDOE.user.anonymousIdent){h+=String.format(_("File {0} modified by me"),PhDOE.user.lang.ucFirst())}else{h+=String.format(_("File {0} modified by {1}"),PhDOE.user.lang.ucFirst(),e.user)}}if(h!==""){return""+c+""}else{return c}}},{header:_("Type"),width:45,sortable:true,dataIndex:"type"},{header:_("Maintainer"),width:45,sortable:true,dataIndex:"maintainer"},{header:_("Path"),dataIndex:"path",hidden:true}];ui.cmp._ErrorFileGrid.view=new Ext.grid.GroupingView({emptyText:'
'+_("No Files")+"
",deferEmptyText:false,forceFit:true,startCollapsed:true,groupTextTpl:'{[values.rs[0].data.path]} ({[values.rs.length]} {[values.rs.length > 1 ? "'+_("Files")+'" : "'+_("File")+'"]})',getRowClass:function(c){if(c.data.fileModifiedEN||c.data.fileModifiedLang){var e=Ext.util.JSON.decode(c.data.fileModifiedEN),d=Ext.util.JSON.decode(c.data.fileModifiedLang);return((e.user===PhDOE.user.login&&e.anonymousIdent===PhDOE.user.anonymousIdent)||(d.user===PhDOE.user.login&&d.anonymousIdent===PhDOE.user.anonymousIdent))?"fileModifiedByMe":"fileModifiedByAnother"}return false}});ui.cmp._ErrorFileGrid.menu=function(c){Ext.apply(this,c);this.init();ui.cmp._ErrorFileGrid.menu.superclass.constructor.call(this)};Ext.extend(ui.cmp._ErrorFileGrid.menu,Ext.menu.Menu,{init:function(){Ext.apply(this,{items:[{scope:this,text:""+_("Edit in a new tab")+"",iconCls:"iconFilesError",handler:function(){this.grid.fireEvent("rowdblclick",this.grid,this.rowIdx,this.event)}},{scope:this,hidden:this.hideDiffMenu,text:_("View diff..."),iconCls:"iconViewDiff",menu:new Ext.menu.Menu({items:[{scope:this,hidden:(this.grid.store.getAt(this.rowIdx).data.fileModifiedEN===false),text:String.format(_("... of the {0} file"),"EN"),handler:function(){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",FileName:this.fname,FilePath:"en"+this.fpath})}},{scope:this,hidden:(this.grid.store.getAt(this.rowIdx).data.fileModifiedLang===false),text:String.format(_("... of the {0} file"),PhDOE.user.lang.ucFirst()),handler:function(){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",FileName:this.fname,FilePath:PhDOE.user.lang+this.fpath})}}]})},"-",{text:_("About error type"),iconCls:"iconHelp",handler:function(){if(!Ext.getCmp("main-panel").findById("FE-help")){Ext.getCmp("main-panel").add({id:"FE-help",title:_("About error type"),iconCls:"iconHelp",closable:true,autoScroll:true,autoLoad:"./error"})}Ext.getCmp("main-panel").setActiveTab("FE-help")}}]})}});ui.cmp.ErrorFileGrid=Ext.extend(Ext.grid.GridPanel,{loadMask:true,border:false,autoExpandColumn:"name",enableDragDrop:true,ddGroup:"mainPanelDDGroup",view:ui.cmp._ErrorFileGrid.view,columns:ui.cmp._ErrorFileGrid.columns,listeners:{render:function(c){c.view.refresh()}},onRowContextMenu:function(d,j,h){h.stopEvent();var g=d.store.getAt(j).data,f=g.path,c=g.name;d.getSelectionModel().selectRow(j);new ui.cmp._ErrorFileGrid.menu({hideDiffMenu:(g.fileModifiedEN===false&&g.fileModifiedLang===false),grid:d,event:h,rowIdx:j,lang:PhDOE.user.lang,fpath:f,fname:c}).showAt(h.getXY())},onRowDblClick:function(c,f,d){this.openFile(c.store.getAt(f).data.id)},openFile:function(j){var g=this.store.getById(j),f=g.data.path,c=g.data.name,h=Ext.util.md5("FE-"+PhDOE.user.lang+f+c),d=[],k,e;if(!Ext.getCmp("main-panel").findById("FE-"+h)){d=[];this.store.each(function(l){if(l.data.path===f&&l.data.name===c&&!d[l.data.type]){d.push(l.data.type)}});k=(PhDOE.user.lang==="en")?[new ui.cmp.VCSLogGrid({layout:"fit",title:String.format(_("{0} Log"),PhDOE.user.lang.ucFirst()),prefix:"FE-LANG",fid:h,fpath:PhDOE.user.lang+f,fname:c,loadStore:PhDOE.user.conf.error.toolsPanelLogLoad})]:[new ui.cmp.VCSLogGrid({layout:"fit",title:String.format(_("{0} Log"),PhDOE.user.lang.ucFirst()),prefix:"FE-LANG",fid:h,fpath:PhDOE.user.lang+f,fname:c,loadStore:PhDOE.user.conf.error.toolsPanelLogLoad}),new ui.cmp.VCSLogGrid({layout:"fit",title:String.format(_("{0} Log"),"En"),prefix:"FE-EN",fid:h,fpath:"en"+f,fname:c,loadStore:PhDOE.user.conf.error.toolsPanelLogLoad})];e=(PhDOE.user.lang==="en")?[new ui.cmp.FilePanel({id:"FE-LANG-PANEL-"+h,region:"center",title:String.format(_("{0} File: "),PhDOE.user.lang)+f+c,prefix:"FE",ftype:"LANG",spellCheck:PhDOE.user.conf.error.enableSpellCheckLang,spellCheckConf:{module:"error",itemName:"enableSpellCheckLang"},fid:h,fpath:f,fname:c,lang:PhDOE.user.lang,parser:"xml",storeRecord:g,syncScrollCB:false,syncScroll:false})]:[new ui.cmp.FilePanel({id:"FE-LANG-PANEL-"+h,region:"center",title:String.format(_("{0} File: "),PhDOE.user.lang.ucFirst())+f+c,prefix:"FE",ftype:"LANG",spellCheck:PhDOE.user.conf.error.enableSpellCheckLang,spellCheckConf:{module:"error",itemName:"enableSpellCheckLang"},fid:h,fpath:f,fname:c,lang:PhDOE.user.lang,parser:"xml",storeRecord:g,syncScrollCB:true,syncScroll:true,syncScrollConf:{module:"error",itemName:"syncScrollbars"}}),new ui.cmp.FilePanel({id:"FE-EN-PANEL-"+h,region:"east",title:_("en File: ")+f+c,prefix:"FE",ftype:"EN",original:true,readOnly:true,openInNewTabBtn:true,fid:h,fpath:f,fname:c,lang:"en",parser:"xml",storeRecord:g,syncScroll:true,syncScrollConf:{module:"error",itemName:"syncScrollbars"}})];Ext.getCmp("main-panel").add({id:"FE-"+h,title:c,layout:"border",iconCls:"iconTabError",closable:true,tabLoaded:false,panVCSLang:!PhDOE.user.conf.errorDisplayLog,panVCSEn:(PhDOE.user.lang==="en")?true:!PhDOE.user.conf.errorDisplayLog,panLANGLoaded:false,panENLoaded:(PhDOE.user.lang==="en")?true:false,originTitle:c,defaults:{split:true},tabTip:String.format(_("File with error : in {0}"),f),listeners:{resize:function(l){(PhDOE.user.lang!=="en")?Ext.getCmp("FE-EN-PANEL-"+h).setWidth(l.getWidth()/2):""}},items:[{xtype:"panel",id:"FE-error-desc-"+h,region:"north",layout:"fit",title:_("Error description"),iconCls:"iconFilesError",collapsedIconCls:"iconFilesError",plugins:[Ext.ux.PanelCollapsedTitle],height:PhDOE.user.conf.error.descPanelHeight||150,collapsible:true,collapsed:!PhDOE.user.conf.error.descPanelDisplay,autoScroll:true,autoLoad:"./error?dir="+f+"&file="+c,listeners:{collapse:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"error",itemName:"descPanelDisplay",value:false})}},expand:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"error",itemName:"descPanelDisplay",value:true})}},resize:function(o,l,m){if(this.ownerCt.tabLoaded&&m&&m>50&&m!=PhDOE.user.conf.error.descPanelHeight){new ui.task.UpdateConfTask({module:"error",itemName:"descPanelHeight",value:m})}}}},{region:"west",xtype:"panel",title:_("Tools"),iconCls:"iconConf",collapsedIconCls:"iconConf",plugins:[Ext.ux.PanelCollapsedTitle],collapsible:true,collapsed:!PhDOE.user.conf.error.toolsPanelDisplay,layout:"fit",bodyBorder:false,width:PhDOE.user.conf.error.toolsPanelWidth||375,listeners:{collapse:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"error",itemName:"toolsPanelDisplay",value:false})}},expand:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"error",itemName:"toolsPanelDisplay",value:true})}},resize:function(l,m){if(this.ownerCt.tabLoaded&&m&&m!=PhDOE.user.conf.error.toolsPanelWidth){new ui.task.UpdateConfTask({module:"error",itemName:"toolsPanelWidth",value:m})}}},items:{xtype:"tabpanel",activeTab:0,tabPosition:"bottom",enableTabScroll:true,defaults:{autoScroll:true},items:[k,new ui.cmp.DictionaryGrid({layout:"fit",title:_("Dictionary"),prefix:"FE",fid:h}),{title:_("Entities"),layout:"fit",items:[new ui.cmp.EntitiesAcronymsPanel({dataType:"entities",prefix:"FE",ftype:"LANG",fid:h,loadStore:PhDOE.user.conf.error.toolsPanelEntitiesLoad})]},{title:_("Acronyms"),layout:"fit",items:[new ui.cmp.EntitiesAcronymsPanel({dataType:"acronyms",prefix:"FE",ftype:"LANG",fid:h,loadStore:PhDOE.user.conf.error.toolsPanelAcronymsLoad})]}]}},e]})}Ext.getCmp("main-panel").setActiveTab("FE-"+h)},initComponent:function(){Ext.apply(this,{store:ui.cmp._ErrorFileGrid.store,tbar:[_("Filter: ")," ",new Ext.form.TwinTriggerField({id:"FE-filter",width:180,hideTrigger1:true,enableKeyEvents:true,validateOnBlur:false,validationEvent:false,trigger1Class:"x-form-clear-trigger",trigger2Class:"x-form-search-trigger",listeners:{keypress:function(c,d){if(d.getKey()===d.ENTER){this.onTrigger2Click()}}},onTrigger1Click:function(){this.setValue("");this.triggers[0].hide();this.setSize(180,10);ui.cmp._ErrorFileGrid.instance.store.clearFilter()},onTrigger2Click:function(){var c=this.getValue(),d;if(c===""||c.length<3){this.markInvalid(_("Your filter must contain at least 3 characters"));return}this.clearInvalid();this.triggers[0].show();this.setSize(180,10);d=new RegExp(c,"i");ui.cmp._ErrorFileGrid.instance.store.filterBy(function(e){if(d.test(e.data.path)||d.test(e.data.name)||d.test(e.data.maintainer)||d.test(e.data.type)){return true}else{return false}},this)}})]});ui.cmp.ErrorFileGrid.superclass.initComponent.call(this);this.on("rowcontextmenu",this.onRowContextMenu,this);this.on("rowdblclick",this.onRowDblClick,this);if(PhDOE.user.lang==="en"){this.getColumnModel().setHidden(2,true)}}});ui.cmp._ErrorFileGrid.instance=null;ui.cmp.ErrorFileGrid.getInstance=function(c){if(!ui.cmp._ErrorFileGrid.instance){if(!c){c={}}ui.cmp._ErrorFileGrid.instance=new ui.cmp.ErrorFileGrid(c)}return ui.cmp._ErrorFileGrid.instance};Ext.namespace("ui","ui.cmp");ui.cmp.ExecDiff=Ext.extend(Ext.Panel,{layout:"fit",title:_("Diff From VCS"),iconCls:"iconDiffView",collapsedIconCls:"iconDiffView",autoScroll:true,plugins:[Ext.ux.PanelCollapsedTitle],onRender:function(d,c){ui.cmp.ExecDiff.superclass.onRender.call(this,d,c);this.el.mask(' '+_("Loading..."));XHR({scope:this,params:{task:"getDiff",DiffType:"vcs",FilePath:"en"+this.fpath,FileName:this.fname,Rev1:this.rev1,Rev2:this.rev2},success:function(e){var f=Ext.util.JSON.decode(e.responseText);Ext.get(this.prefix+"-diff-"+this.fid).dom.innerHTML=f.content;this.el.unmask()},callback:function(){Ext.getCmp(this.prefix+"-"+this.fid).panDiffLoaded=true;Ext.getCmp("main-panel").fireEvent("tabLoaded",this.prefix,this.fid)}})},initComponent:function(){Ext.apply(this,{html:'
'});ui.cmp.ExecDiff.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._FilePanel");Ext.namespace("ui.cmp._FilePanel.tbar.menu");Ext.namespace("ui.cmp._FilePanel.tbar.items");ui.cmp._FilePanel.tbar.items.undoRedo=function(c){Ext.apply(this,c);this.init();ui.cmp._FilePanel.tbar.items.undoRedo.superclass.constructor.call(this)};Ext.extend(ui.cmp._FilePanel.tbar.items.undoRedo,Ext.ButtonGroup,{init:function(){Ext.apply(this,{id:this.id_prefix+"-FILE-"+this.fid+"-grp-undoRedo",items:[{id:this.id_prefix+"-FILE-"+this.fid+"-btn-undo",scope:this,tooltip:_("Undo"),disabled:true,iconCls:"iconUndo",handler:function(){Ext.getCmp(this.id_prefix+"-FILE-"+this.fid).undo()}},{id:this.id_prefix+"-FILE-"+this.fid+"-btn-redo",scope:this,tooltip:_("Redo"),disabled:true,iconCls:"iconRedo",handler:function(){Ext.getCmp(this.id_prefix+"-FILE-"+this.fid).redo()}}]})}});ui.cmp._FilePanel.tbar.items.usernotes=function(c){Ext.apply(this,c);this.init();ui.cmp._FilePanel.tbar.items.usernotes.superclass.constructor.call(this)};Ext.extend(ui.cmp._FilePanel.tbar.items.usernotes,Ext.ButtonGroup,{init:function(){Ext.apply(this,{items:[{xtype:"usernotes",file:this.file,fid:Ext.id()}]})}});ui.cmp._FilePanel.tbar.items.common=function(c){Ext.apply(this,c);this.init();ui.cmp._FilePanel.tbar.items.common.superclass.constructor.call(this)};Ext.extend(ui.cmp._FilePanel.tbar.items.common,Ext.ButtonGroup,{init:function(){Ext.apply(this,{items:[{scope:this,tooltip:_("Close Tab"),iconCls:"iconClose",handler:function(){Ext.getCmp("main-panel").remove(this.prefix+"-"+this.fid)}},{id:this.prefix+"-"+this.fid+"-btn-tabLeft-"+this.ftype,scope:this,tooltip:_("Go to previous tab"),iconCls:"iconArrowLeft",handler:this.goToPreviousTab},{id:this.prefix+"-"+this.fid+"-btn-tabRight-"+this.ftype,scope:this,tooltip:_("Go to next tab"),disabled:true,iconCls:"iconArrowRight",handler:this.goToNextTab}]})}});ui.cmp._FilePanel.tbar.menu.lang=function(c){Ext.apply(this,c);this.init();ui.cmp._FilePanel.tbar.menu.lang.superclass.constructor.call(this)};Ext.extend(ui.cmp._FilePanel.tbar.menu.lang,Ext.Toolbar.Button,{text:_("MarkUp"),iconCls:"iconInsertCode",init:function(){Ext.apply(this,{menu:new Ext.menu.Menu({items:[{scope:this,text:_("Reviewed tag"),handler:function(){Ext.getCmp(this.comp_id).insertLine(2,"");Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("Revcheck tag"),handler:function(){Ext.getCmp(this.comp_id).insertLine(1,"");Ext.getCmp(this.comp_id).focus()}}]})})}});ui.cmp._FilePanel.tbar.menu.en=function(c){Ext.apply(this,c);this.init();ui.cmp._FilePanel.tbar.menu.en.superclass.constructor.call(this)};Ext.extend(ui.cmp._FilePanel.tbar.menu.en,Ext.Toolbar.Button,{text:_("MarkUp"),iconCls:"iconInsertCode",init:function(){Ext.apply(this,{menu:new Ext.menu.Menu({items:[{scope:this,text:_("Description section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,[' \r\n ',"&reftitle.description;\r\n ","\r\n ","\r\n ","thereturned typefunc_name\r\n ","\r\n ","param1typefirstparameter\r\n ","\r\n ",'intsecondparameter\r\n ',"\r\n ","\r\n ","\r\n ","\r\n ","The function description goes here.\r\n ","\r\n ",""].join(""));Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("Parameters section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,['\r\n\r\n',"&reftitle.parameters;\r\n","\r\n","\r\n","\r\n","firstparameter\r\n","\r\n","\r\n","Its description\r\n","\r\n","\r\n","\r\n","\r\n","\r\n","secondparameter\r\n","\r\n","\r\n","\r\n","Its description\r\n","\r\n","\r\n","\r\n","\r\n","\r\n",""].join(""));Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("Return section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,['\r\n\r\n',"&reftitle.returnvalues;\r\n","\r\n","What this function returns, first on success, then failure.\r\n","If simply true on success and false on failure, just use &return.success; here.\r\n","\r\n",""].join(""));Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("Error section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,['\r\n\r\n',"&reftitle.errors;\r\n","\r\n","When does this function issue E_* level errors, and/or throw exceptions.\r\n","\r\n","\r\n"].join(""));Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("Unicode section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,['\r\n\r\n',"&reftitle.unicode;\r\n","\r\n","Information specific to unicode, from the PHP 6 changes.\r\n","\r\n",""].join(""));Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("Changelog section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,['\r\n\r\n',"&reftitle.changelog;\r\n","\r\n","\r\n",'\r\n',"\r\n","\r\n","&Version;\r\n","&Description;\r\n","\r\n","\r\n","\r\n","\r\n","Enter the version of change here\r\n","\r\n","Describe the change\r\n","\r\n","\r\n","\r\n","\r\n","\r\n","\r\n",""].join(""));Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("Examples section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,['\r\n\r\n',"&reftitle.examples;\r\n","\r\n",'\r\n',"<function>function-name</function> example\r\n","\r\n","Any text that describes the purpose of the example, or what\r\n","goes on in the example should be here. (Inside the tag, not out).\r\n","\r\n",'\r\n',"\r\n","]]>\r\n","\r\n","&example.outputs.similar;\r\n","\r\n","\r\n","\r\n","\r\n","\r\n",""].join(""));Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("Notes section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,['\r\n\r\n',"&reftitle.notes;\r\n","\r\n","\r\n","Any notes that don't fit anywhere else should go here.\r\n","90% of the time, notes, warnings or cautions are better placed in the\r\n","parameters section. Consider that before using this section!\r\n","\r\n","\r\n","¬e.language-construct;\r\n","¬e.not-bin-safe;\r\n","¬e.registerglobals;\r\n",""].join(""));Ext.getCmp(this.comp_id).focus()}},{scope:this,text:_("SeeAlso section"),handler:function(){var c=Ext.getCmp(this.comp_id).getCursor();Ext.getCmp(this.comp_id).insertLine(c.line,['\r\n\r\n',"&reftitle.seealso;\r\n","\r\n","\r\n","somefunc\r\n","another_func\r\n",'The something appendix\r\n',"\r\n","\r\n",""].join(""));Ext.getCmp(this.comp_id).focus()}}]})})}});ui.cmp._FilePanel.tbar.items.reindentTags=function(c){Ext.apply(this,c);this.init();ui.cmp._FilePanel.tbar.items.reindentTags.superclass.constructor.call(this)};Ext.extend(ui.cmp._FilePanel.tbar.items.reindentTags,Ext.ButtonGroup,{init:function(){Ext.apply(this,{id:this.id_prefix+"-FILE-"+this.fid+"-grp-tools",items:[{scope:this,tooltip:_("Check XML with XmlLint"),iconCls:"iconXml",handler:function(c){new ui.task.CheckXml({idPrefix:this.id_prefix,fid:this.fid})}},(this.lang==="en")?new ui.cmp._FilePanel.tbar.menu.en({comp_id:this.id_prefix+"-FILE-"+this.fid}):new ui.cmp._FilePanel.tbar.menu.lang({comp_id:this.id_prefix+"-FILE-"+this.fid}),{scope:this,text:_("Editor option"),iconCls:"iconConf",menu:[{scope:this,text:_("Re-indent all this file"),iconCls:"iconIndent",handler:function(){Ext.getCmp(this.id_prefix+"-FILE-"+this.fid).reIndentAll()}},{scope:this,text:_("Enable line wrapping"),checked:((PhDOE.user.conf.main.lineWrapping===true)?true:false),checkHandler:function(d,c){var e=(c)?true:false;Ext.getCmp(this.id_prefix+"-FILE-"+this.fid).setOption("lineWrapping",e);new ui.task.UpdateConfTask({module:"main",itemName:"lineWrapping",value:c,notify:false})}},{scope:this,text:_("Choose a Theme"),iconCls:"iconThemes",onThemeChange:function(){var c=Ext.getCmp(this.ownerCt.ownerCt.ownerCt.id_prefix+"-FILE-"+this.ownerCt.ownerCt.ownerCt.fid);Ext.each(this.menu.items.items,function(d){if(d.checked===true){c.switchTheme(d.themeName);new ui.task.UpdateConfTask({module:"main",itemName:"editorTheme",value:d.themeName,notify:false})}})},menu:{items:[{text:_("No theme"),themeName:false,checked:(PhDOE.user.conf.main.editorTheme===false),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}},{text:_("Default theme"),themeName:"default",checked:(PhDOE.user.conf.main.editorTheme==="default"||PhDOE.user.conf.main.editorTheme==="undefined"),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}},{text:_("Cobalt"),themeName:"cobalt",checked:(PhDOE.user.conf.main.editorTheme==="cobalt"),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}},{text:_("Eclipse"),themeName:"eclipse",checked:(PhDOE.user.conf.main.editorTheme==="eclipse"),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}},{text:_("Elegant"),themeName:"elegant",checked:(PhDOE.user.conf.main.editorTheme==="elegant"),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}},{text:_("Monokai"),themeName:"monokai",checked:(PhDOE.user.conf.main.editorTheme==="monokai"),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}},{text:_("Neat"),themeName:"neat",checked:(PhDOE.user.conf.main.editorTheme==="neat"),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}},{text:_("Night"),themeName:"night",checked:(PhDOE.user.conf.main.editorTheme==="night"),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}},{text:_("RubyBlue"),themeName:"rubyblue",checked:(PhDOE.user.conf.main.editorTheme==="rubyblue"),group:"cmd2-theme",checkHandler:function(){this.ownerCt.ownerCt.onThemeChange()}}]}}]}]})}});ui.cmp.FilePanel=Ext.extend(Ext.form.FormPanel,{activeScroll:false,goToPreviousTab:function(){var c=this.prefix+"-"+this.fid,e=Ext.getCmp("main-panel").layout.container.items.items,g,f,d;for(d=0;d','',_("Line: "),'-','  ',_("Col: "),'-',"  "].join(""))}}}]:[{xtype:"panel",height:22,baseCls:"",bodyStyle:"padding-top:5px;",html:['
','',_("Line: "),'-','  ',_("Col: "),'-',"
  "].join("")}];if(!this.readOnly){this.tbar=[new ui.cmp._FilePanel.tbar.items.common({prefix:this.prefix,fid:this.fid,ftype:this.ftype,goToPreviousTab:this.goToPreviousTab,goToNextTab:this.goToNextTab}),{xtype:"buttongroup",id:c+"-FILE-"+this.fid+"-grp-save",items:[{id:c+"-FILE-"+this.fid+"-btn-save",scope:this,tooltip:_("Save this file (CTRL+s)"),iconCls:"iconSaveFile",disabled:true,handler:function(){if(this.prefix==="AF"){new ui.task.SaveFileTask({prefix:this.prefix,ftype:this.ftype,fid:this.fid,fpath:this.fpath,fname:this.fname,lang:this.lang,storeRecord:this.storeRecord});return}if(this.prefix==="FNT"){new ui.task.SaveTransFileTask({prefix:this.prefix,ftype:this.ftype,fid:this.fid,fpath:this.fpath,fname:this.fname,lang:this.lang,storeRecord:this.storeRecord});return}if(!PhDOE.user.conf.main.onSaveFile){PhDOE.user.conf.main.onSaveFile="ask-me"}switch(PhDOE.user.conf.main.onSaveFile){case"always":new ui.task.CheckFileTask({prefix:this.prefix,ftype:this.ftype,fid:this.fid,fpath:this.fpath,fname:this.fname,lang:this.lang,storeRecord:this.storeRecord});break;case"never":new ui.task.SaveFileTask({prefix:this.prefix,ftype:this.ftype,fid:this.fid,fpath:this.fpath,fname:this.fname,lang:this.lang,storeRecord:this.storeRecord});break;case"ask-me":Ext.MessageBox.show({title:_("Confirm"),msg:_("Do you want to check for errors before saving?"),icon:Ext.MessageBox.INFO,buttons:Ext.MessageBox.YESNOCANCEL,scope:this,fn:function(d){if(d==="no"){new ui.task.SaveFileTask({prefix:this.prefix,ftype:this.ftype,fid:this.fid,fpath:this.fpath,fname:this.fname,lang:this.lang,storeRecord:this.storeRecord})}else{if(d==="yes"){new ui.task.CheckFileTask({prefix:this.prefix,ftype:this.ftype,fid:this.fid,fpath:this.fpath,fname:this.fname,lang:this.lang,storeRecord:this.storeRecord})}}}});break}}}]},new ui.cmp._FilePanel.tbar.items.undoRedo({id_prefix:c,fid:this.fid}),new ui.cmp._FilePanel.tbar.items.reindentTags({id_prefix:c,fid:this.fid,lang:this.lang}),{scope:this,iconCls:"iconZoom",tooltip:_("Expand in a popup"),handler:function(d){var e=new Ext.Window({title:this.originTitle,bodyStyle:"background-color:white",maximized:true,animateTarget:d.el,items:[{xtype:"codemirror",id:c+"-FILE-"+this.fid+"maximized",readOnly:false,lineWrapping:PhDOE.user.conf.main.lineWrapping,theme:PhDOE.user.conf.main.editorTheme,parser:this.parser,isModified:false,listeners:{scope:this,initialize:function(){var h=Ext.getCmp(c+"-FILE-"+this.fid+"maximized"),f=Ext.getCmp(c+"-FILE-"+this.fid).getValue();h.setValue(f);var g=new Ext.util.DelayedTask(function(){if(e.rendered){h.resize(false,e.getInnerHeight()+89)}else{g.delay(500)}});g.delay(500)}}}],listeners:{scope:this,beforeclose:function(g){var f=g.items.items[0].getValue();Ext.getCmp(c+"-FILE-"+this.fid).setValue(f)}}});e.show()}},{scope:this,iconCls:"iconView",hidden:!(this.lang==="en"&&this.fname.substr(-3)==="xml"),tooltip:_("Preview in a popup"),handler:function(){var d=Ext.getCmp(c+"-FILE-"+this.fid).isModified;if(d){Ext.Msg.alert(_("Information"),_("You must save your file in order to preview the result."),function(e){if(e=="ok"){new ui.cmp.PreviewFile({path:this.lang+this.fpath+this.fname})}},this)}else{new ui.cmp.PreviewFile({path:this.lang+this.fpath+this.fname})}}},"->",new ui.cmp._FilePanel.tbar.items.usernotes({fid:this.fid,file:this.lang+this.fpath+this.fname})]}else{this.tbar=[new ui.cmp._FilePanel.tbar.items.common({prefix:this.prefix,fid:this.fid,ftype:this.ftype,goToPreviousTab:this.goToPreviousTab,goToNextTab:this.goToNextTab}),{xtype:"buttongroup",hidden:(this.openInNewTabBtn!==true),scope:this,items:[{tooltip:_("Open for editing in a new Tab"),iconCls:"iconEditInNewTab",scope:this,handler:function(){ui.cmp.RepositoryTree.getInstance().openFile("byPath",this.lang+this.fpath,this.fname)}}]},"->",((this.ftype!=="GGTRANS")?new ui.cmp._FilePanel.tbar.items.usernotes({fid:this.fid,file:this.lang+this.fpath+this.fname}):"")]}Ext.apply(this,{title:this.title,cls:"code-mirror-panel",originTitle:this.title,items:[{xtype:"codemirror",id:c+"-FILE-"+this.fid,readOnly:this.readOnly,lineWrapping:PhDOE.user.conf.main.lineWrapping,theme:PhDOE.user.conf.main.editorTheme,parser:this.parser,isModified:false,listeners:{scope:this,initialize:function(){var e,d;if(this.isTrans){if(this.storeRecord.data.fileModified){e=this.lang+this.fpath;d=this.fname}else{e="en"+this.fpath;d=this.fname}}else{e=this.lang+this.fpath;d=this.fname}new ui.task.GetFileTask({prefix:this.prefix,ftype:this.ftype,original:this.original,fid:this.fid,fpath:e,freadOnly:this.readOnly,fname:d,skeleton:this.skeleton,storeRecord:this.storeRecord})},coderestored:function(){if(this.readOnly){return}if(Ext.getCmp(c+"-FILE-"+this.fid).isModified){Ext.getCmp(c+"-PANEL-"+this.fid).setTitle(Ext.getCmp(c+"-PANEL-"+this.fid).permlink+Ext.getCmp(c+"-PANEL-"+this.fid).originTitle);if((this.ftype==="LANG"&&PhDOE.user.lang!=="en")||this.ftype==="EN"){if((this.ftype==="EN"&&!Ext.getCmp(this.prefix+"-LANG-FILE-"+this.fid).isModified)||(this.ftype==="LANG"&&!Ext.getCmp(this.prefix+"-EN-FILE-"+this.fid).isModified)){Ext.getCmp(this.prefix+"-"+this.fid).setTitle(Ext.getCmp(this.prefix+"-"+this.fid).originTitle)}}else{Ext.getCmp(this.prefix+"-"+this.fid).setTitle(Ext.getCmp(this.prefix+"-"+this.fid).originTitle)}Ext.getCmp(c+"-FILE-"+this.fid+"-btn-save").disable();Ext.getCmp(c+"-FILE-"+this.fid).isModified=false}},codemodified:function(){if(this.readOnly){return}if(Ext.getCmp(c+"-FILE-"+this.fid+"-grp-save").disabled){return}var e=Ext.getCmp(c+"-FILE-"+this.fid),d=Ext.getCmp(c+"-PANEL-"+this.fid);if(!e.isModified){d.setTitle(d.permlink+d.originTitle+' ['+_("modified")+"]");Ext.getCmp(this.prefix+"-"+this.fid).setTitle(Ext.getCmp(this.prefix+"-"+this.fid).originTitle+' *');Ext.getCmp(c+"-FILE-"+this.fid+"-btn-save").enable();Ext.getCmp(c+"-FILE-"+this.fid+"-btn-undo").enable();e.isModified=true}},cursormove:function(d,e){Ext.get(c+"-status-line-"+this.fid).dom.innerHTML=d;Ext.get(c+"-status-col-"+this.fid).dom.innerHTML=e},scroll:function(g){var e,f,d;if(this.syncScroll&&PhDOE.user.conf[this.syncScrollConf.module][this.syncScrollConf.itemName]){switch(this.ftype){case"EN":if(this.prefix=="FNT"){e=this.prefix+"-TRANS"}else{e=this.prefix+"-LANG"}break;case"LANG":e=this.prefix+"-EN";break;case"TRANS":if(PhDOE.user.conf.newFile.secondPanel=="google"){e=this.prefix+"-GGTRANS"}if(PhDOE.user.conf.newFile.secondPanel=="originalFile"){e=this.prefix+"-EN"}break;case"GGTRANS":e=this.prefix+"-TRANS";break}f=Ext.getCmp(e+"-PANEL-"+this.fid);d=Ext.getCmp(e+"-FILE-"+this.fid);if(f.activeScroll===false){this.activeScroll=true;d.scrollTo(g)}else{f.activeScroll=false}}}}}]});ui.cmp.FilePanel.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp");ui.cmp.GoogleTranslationPanel=Ext.extend(Ext.FormPanel,{border:false,labelAlign:"top",bodyStyle:"padding:5px",autoScroll:true,getTranslation:function(c){new ui.task.GetGGTranslation({str:c})},initComponent:function(){Ext.apply(this,{items:[{xtype:"textarea",anchor:"90%",fieldLabel:String.format(_("String to translate (en => {0})"),PhDOE.user.lang),name:"GGTranslate-string",id:"GGTranslate-string",allowBlank:false},{scope:this,xtype:"button",text:_("Translate !"),id:"GGTranslate-btn",handler:function(){this.getTranslation(Ext.getCmp("GGTranslate-string").getValue())}},{xtype:"panel",anchor:"100%",border:false,bodyStyle:"padding:5px",html:'
'}]});ui.cmp.GoogleTranslationPanel.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._MainMenu");ui.cmp.MainMenu=function(c){Ext.apply(this,c);this.init();ui.cmp.MainMenu.superclass.constructor.call(this)};ui.cmp._MainMenu.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getAvailableLanguage"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"code",fields:[{name:"code"},{name:"iconCls"},{name:"name"}]})});ui.cmp._MainMenu.store.on("load",function(c){Ext.getDom("Info-Language").innerHTML=Ext.getDom("Topic-Language").innerHTML=c.getById(PhDOE.user.lang).data.name;c.each(function(d){var e=new Ext.menu.Item({text:d.data.name+" ("+d.data.code+")",iconCls:"mainMenuLang flags "+d.data.iconCls,disabled:(d.data.code===PhDOE.user.lang),handler:function(){XHR({params:{task:"switchLang",lang:d.data.code},success:function(){window.location.reload()}})}});Ext.getCmp("MenuLang-ct").add(e)})},this);Ext.extend(ui.cmp.MainMenu,Ext.menu.Menu,{id:"mainMenu",init:function(){var c=new Ext.menu.Menu({id:"MenuLang-ct"});Ext.apply(this,{items:[{text:_("Refresh all data"),disabled:(!PhDOE.user.isGlobalAdmin),iconCls:"iconRefresh",handler:function(){Ext.getBody().mask(' '+_("Verify if there is an update in progress. Please, wait..."));XHR({params:{task:"checkLockFile",lockFiles:"project_"+PhDOE.project+"_lock_update_repository|project_"+PhDOE.project+"_lock_apply_tools"},success:function(){Ext.getBody().unmask();Ext.MessageBox.show({title:_("Status"),msg:_("There is currently an update in progress.
You can't perform an update now."),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.INFO})},failure:function(){Ext.getBody().unmask();new ui.cmp.SystemUpdatePrompt().show(Ext.get("acc-need-update"))}})}},{text:_("Build tools"),handler:function(){return false},menu:new Ext.menu.Menu({items:[{text:_("Check build"),disabled:(!PhDOE.user.isGlobalAdmin&&!PhDOE.user.isLangAdmin),iconCls:"iconCheckBuild",handler:function(){Ext.getBody().mask(' '+_("Verify if there is a check in progress. Please, wait..."));XHR({params:{task:"checkLockFile",lockFile:"project_"+PhDOE.project+"_lock_check_build_"+PhDOE.user.lang},success:function(){Ext.getBody().unmask();Ext.MessageBox.show({title:_("Status"),msg:_("There is currently a check in progress for this language.
You can't perform a new check now."),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.INFO})},failure:function(){Ext.getBody().unmask();new ui.cmp.CheckBuildPrompt().show(Ext.get("acc-need-update"))}})}},{text:_("Show last failed build"),iconCls:"iconBuildStatus",handler:function(){var d=Ext.getCmp("tab-build-status");if(!d){Ext.getCmp("main-panel").add({id:"tab-build-status",title:_("Last failed build"),iconCls:"iconBuildStatus",layout:"fit",closable:true,items:[new ui.cmp.BuildStatus()]})}Ext.getCmp("main-panel").setActiveTab("tab-build-status")}}]})},{text:_("EN tools"),handler:function(){return false},menu:new Ext.menu.Menu({items:[{text:_("Script check entities"),iconCls:"iconCheckEntities",handler:function(){return false},menu:new Ext.menu.Menu({items:[{text:_("View the last result"),id:"btn-check-entities-view-last-result",iconCls:"iconTabView",handler:function(){var d=Ext.getCmp("tab-check-entities");if(!d){Ext.getCmp("main-panel").add({id:"tab-check-entities",title:_("Check entities"),iconCls:"iconCheckEntities",layout:"fit",closable:true,items:[new ui.cmp.CheckEntities()]})}Ext.getCmp("main-panel").setActiveTab("tab-check-entities")}},{text:_("Run this script"),iconCls:"iconRun",disabled:(PhDOE.user.isAnonymous),handler:function(){Ext.getBody().mask(' '+_("Verify if there is an entities check in progress. Please, wait..."));XHR({params:{task:"checkLockFile",lockFile:"project_"+PhDOE.project+"_lock_check_entities"},success:function(){Ext.getBody().unmask();Ext.MessageBox.show({title:_("Status"),msg:_("There is currently a check in progress for the entities.
You can't perform a new check now."),buttons:Ext.MessageBox.OK,icon:Ext.MessageBox.INFO})},failure:function(){Ext.getBody().unmask();if(!Ext.getCmp("win-check-entities")){new ui.cmp.CheckEntitiesPrompt()}Ext.getCmp("win-check-entities").show(Ext.get("mainMenu"))}})}}]})},{text:_("Script check document"),iconCls:"iconCheckDoc",handler:function(){var d=Ext.getCmp("tab-check-doc");if(!d){Ext.getCmp("main-panel").add({id:"tab-check-doc",title:"Check Doc",iconCls:"iconCheckDoc",layout:"fit",closable:true,items:[new ui.cmp.CheckDoc()]})}Ext.getCmp("main-panel").setActiveTab("tab-check-doc")}}]})},"-",{text:_("Configure"),iconCls:"iconConf",tooltip:"Configure this tool",id:"winconf-btn",handler:function(){if(!Ext.getCmp("win-conf")){new ui.cmp.EditorConf()}Ext.getCmp("win-conf").show(Ext.get("mainMenu"))}},"-",{id:"menuLang",iconCls:"iconSwitchLang",text:_("Switch to language..."),handler:function(){return false},menu:c},{text:_("Erase my personal data"),iconCls:"iconErasePersonalData",disabled:(PhDOE.user.isAnonymous),handler:function(){Ext.MessageBox.confirm(_("Confirm"),_("This action will erase your personal data. All content about this account will be deleted definitively. Are you sure you want to do that ?"),function(d){if(d==="yes"){Ext.getBody().mask(' '+_("Please, wait..."));XHR({params:{task:"erasePersonalData"},success:function(){Ext.getBody().unmask();Ext.MessageBox.show({title:_("Thanks !"),msg:_("Thank you for using this application !"),icon:Ext.MessageBox.INFO,buttons:Ext.MessageBox.OK,fn:function(){window.location.href="./do/logout?csrfToken="+csrfToken}})},failure:function(){Ext.getBody().unmask();PhDOE.winForbidden()}})}})}},{text:_("Log out"),iconCls:"iconLogOut",handler:function(){Ext.MessageBox.confirm(_("Confirm"),_("Are you sure you want to logout?"),function(d){if(d==="yes"){window.location.href="./do/logout?csrfToken="+csrfToken}})}},"-",{id:"tab-report-bug-btn",text:_("Report bugs"),iconCls:"iconBugs",handler:function(){if(!Ext.getCmp("main-panel").findById("tab-report-bug")){Ext.getCmp("main-panel").add({id:"tab-report-bug",xtype:"panel",title:_("Report bugs"),iconCls:"iconBugs",closable:true,layout:"fit",items:[new Ext.ux.IFrameComponent({id:"frame-tab-report-bug",url:"http://bugs.php.net/"})]});Ext.getCmp("main-panel").setActiveTab("tab-report-bug")}else{Ext.getCmp("main-panel").setActiveTab("tab-report-bug")}}},{id:"tab-documentation-btn",text:_("Documentation"),iconCls:"iconBook",handler:function(){if(!Ext.getCmp("main-panel").findById("tab-documentation")){Ext.getCmp("main-panel").add({id:"tab-documentation",xtype:"panel",title:_("Documentation"),iconCls:"iconBook",closable:true,layout:"fit",items:[new Ext.ux.IFrameComponent({id:"frame-tab-documentation",url:"https://wiki.php.net/doc/editor/"})]});Ext.getCmp("main-panel").setActiveTab("tab-documentation")}else{Ext.getCmp("main-panel").setActiveTab("tab-documentation")}}},{id:"tab-chat-btn",text:_("Chat with us on IRC !"),iconCls:"iconChat",handler:function(){if(!Ext.getCmp("main-panel").findById("tab-chat")){var d=PhDOE.user.login;if(PhDOE.user.isAnonymous){d="an%3F%3F%3F"}Ext.getCmp("main-panel").add({id:"tab-chat",xtype:"panel",title:_("Chat"),iconCls:"iconChat",closable:true,layout:"fit",items:[new Ext.ux.IFrameComponent({id:"frame-tab-chat",url:"https://widget.mibbit.com/?settings=8eec4034df2eb666b0600bdfe151529a&server=irc.umich.edu&channel=%23php.doc&nick=poe_"+d})]})}Ext.getCmp("main-panel").setActiveTab("tab-chat")}},"-",{id:"winabout-btn",text:_("About"),iconCls:"iconHelp",handler:function(){new ui.cmp.About().show(Ext.get("winabout-btn"))}}]})}});Ext.namespace("ui","ui.cmp","ui.cmp.MainPanel");ui.cmp.MainPanel=Ext.extend(Ext.ux.SlidingTabPanel,{activeTab:0,enableTabScroll:true,plugins:["tabclosemenu","dblclickclosetabs"],initComponent:function(c){Ext.apply(this,c);ui.cmp.MainPanel.superclass.initComponent.call(this);this.addEvents({tabLoaded:true});this.on("beforeremove",this.onBeforeRemove,this);this.on("tabchange",this.onTabChange,this);this.on("endDrag",this.onTabChange,this);this.on("tabLoaded",this.onTabLoaded,this)},onTabLoaded:function(d,e){var c=Ext.getCmp(d+"-"+e);if(d==="FNT"){if(c.panTRANSLoaded&&c.panTRANSSecondLoaded){c.tabLoaded=true;c.panTRANSLoaded=c.panTRANSSecondLoaded=false;if(PhDOE.FNTfilePendingOpen[0]){ui.cmp.PendingTranslateGrid.getInstance().openFile(PhDOE.FNTfilePendingOpen[0].id);PhDOE.FNTfilePendingOpen.shift()}}}if(d==="FNU"){if(c.panLANGLoaded&&c.panENLoaded&&c.panDiffLoaded&&c.panVCSLang&&c.panVCSEn){c.tabLoaded=true;c.panLANGLoaded=c.panENLoaded=c.panDiffLoaded=c.panVCSLang=c.panVCSEn=false;if(PhDOE.FNUfilePendingOpen[0]){ui.cmp.StaleFileGrid.getInstance().openFile(PhDOE.FNUfilePendingOpen[0].id);PhDOE.FNUfilePendingOpen.shift()}}}if(d==="FE"){if(c.panLANGLoaded&&c.panENLoaded&&c.panVCSLang&&c.panVCSEn){c.tabLoaded=true;c.panLANGLoaded=c.panENLoaded=c.panVCSLang=c.panVCSEn=false;if(PhDOE.FEfilePendingOpen[0]){ui.cmp.ErrorFileGrid.getInstance().openFile(PhDOE.FEfilePendingOpen[0].id);PhDOE.FEfilePendingOpen.shift()}}}if(d==="FNR"){if(c.panLANGLoaded&&c.panENLoaded&&c.panVCSLang&&c.panVCSEn){c.tabLoaded=true;c.panLANGLoaded=c.panENLoaded=c.panVCSLang=c.panVCSEn=false;if(PhDOE.FNRfilePendingOpen[0]){ui.cmp.PendingReviewGrid.getInstance().openFile(PhDOE.FNRfilePendingOpen[0].id);PhDOE.FNRfilePendingOpen.shift()}}}if(d==="FNIEN"){if(c.panLANGLoaded){c.tabLoaded=true;c.panLANGLoaded=false;if(PhDOE.FNIENfilePendingOpen[0]){ui.cmp.NotInENGrid.getInstance().openFile(PhDOE.FNIENfilePendingOpen[0].id);PhDOE.FNIENfilePendingOpen.shift()}}}if(d==="AF"){if(c.panLoaded&&c.panVCS&&c.panEntities&&c.panAcronyms){c.tabLoaded=true;c.panLoaded=c.panVCS=false;if(PhDOE.AFfilePendingOpen[0]){ui.cmp.RepositoryTree.getInstance().openFile((PhDOE.AFfilePendingOpen[0].nodeID)?"byId":"byPath",(PhDOE.AFfilePendingOpen[0].nodeID)?PhDOE.AFfilePendingOpen[0].nodeID:PhDOE.AFfilePendingOpen[0].fpath,(PhDOE.AFfilePendingOpen[0].nodeID)?false:PhDOE.AFfilePendingOpen[0].fname);PhDOE.AFfilePendingOpen.shift()}}}if(d==="PP"){if(c.panPatchLoaded&&c.panOriginLoaded&&c.panVCS&&c.panPatchContent){c.tabLoaded=true;c.panPatchLoaded=c.panOriginLoaded=c.panVCS=c.panPatchContent=false;if(PhDOE.PPfilePendingOpen[0]){ui.cmp.PendingPatchGrid.getInstance().openFile(PhDOE.PPfilePendingOpen[0].id);PhDOE.PPfilePendingOpen.shift()}}}},onTabChange:function(d,g){if(Ext.getCmp(g.id+"-btn-tabRight-LANG")||Ext.getCmp(g.id+"-btn-tabRight-EN")||Ext.getCmp(g.id+"-btn-tabRight-ALL")||Ext.getCmp(g.id+"-btn-tabRight-NotInEN")||Ext.getCmp(g.id+"-btn-tabRight-PATCH")||Ext.getCmp(g.id+"-btn-tabRight-TRANS")||Ext.getCmp(g.id+"-btn-tabRight-NEW")){var c=g.id,f=Ext.getCmp("main-panel").layout.container.items.items,h,e;for(e=0;eDo you really want to close?"),buttons:Ext.Msg.YESNO,icon:Ext.Msg.QUESTION,fn:function(j,k){if(j==="yes"){f.un("beforeremove",this.onBeforeRemove,this);f.remove(g);f.addListener("beforeremove",this.onBeforeRemove,this)}}});return false}else{return true}}else{return true}},openDiffTab:function(d){var f=d.DiffType,k=d.currentOwner||"",h=d.fileIdDB||"",j=d.FileName||"",e=d.FilePath||"",p=d.patchID||"",o=d.patchName||"",g,l=Ext.util.md5(o+p+e+j),q,c,m;if(p!=""){q=String.format(_("Diff for patch: {0}"),o);g="./do/downloadPatch?patchID="+p+"&csrfToken="+csrfToken;c=_("Download the unified diff as a patch")}else{q=String.format(_("Diff for file: {0}"),e+j);g="./do/downloadPatch?FilePath="+e+"&FileName="+j+"&csrfToken="+csrfToken;c=_("Download the diff as a patch")}if(!Ext.getCmp("main-panel").findById("diff_panel_"+l)){m=[{xtype:"buttongroup",items:[{xtype:"button",iconCls:"iconEdit",tooltip:_("Edit in a new tab"),handler:function(){ui.cmp.RepositoryTree.getInstance().openFile("byPath",e,j)}},{xtype:"button",iconCls:"iconDownloadDiff",tooltip:c,handler:function(){window.location.href=g}}]},((PhDOE.user.isGlobalAdmin||PhDOE.user.isLangAdmin)?{xtype:"buttongroup",items:[{xtype:"button",iconCls:"iconPageDelete",tooltip:_("Clear this change"),handler:function(){new ui.task.ClearLocalChangeTask({ftype:"update",fpath:e,fname:j});Ext.getCmp("main-panel").remove("diff_panel_"+l)}},{xtype:"button",iconCls:"iconSwitchLang",tooltip:_("Change file's owner"),handler:function(){new ui.cmp.ChangeFileOwner({fileIdDB:h,fileFolder:e,fileName:j,currentOwner:k})}}]}:"")];Ext.getCmp("main-panel").add({xtype:"panel",id:"diff_panel_"+l,title:_("Diff"),tabTip:q,closable:true,autoScroll:true,iconCls:"iconTabLink",html:'
',tbar:m});Ext.getCmp("main-panel").setActiveTab("diff_panel_"+l);Ext.get("diff_panel_"+l).mask(''+_("Please, wait..."));XHR({params:{task:"getDiff",DiffType:f,FilePath:e,FileName:j,patchID:p},success:function(s){var u=Ext.util.JSON.decode(s.responseText),t="";if(p==""){t='

'+_("Direct link to this patch")+" ; "+_("File: ")+e+j+"

"}else{t='

'+_("Direct link to this patch")+" ; "+_("Patch Name: ")+o+"

"}u.content=t+u.content;Ext.get("diff_content_"+l).dom.innerHTML=u.content;Ext.get("diff_panel_"+l).unmask()}})}else{Ext.getCmp("main-panel").setActiveTab("diff_panel_"+l)}}});Ext.reg("mainpanel",ui.cmp.MainPanel);Ext.namespace("ui","ui.cmp");ui.cmp.ManagePatchPrompt=Ext.extend(Ext.Window,{title:"",width:450,height:260,minWidth:450,minHeight:300,layout:"fit",plain:true,bodyStyle:"padding:5px;",buttonAlign:"center",iconCls:"iconPatch",closeAction:"hide",nodesToAdd:false,patchName:"",patchDescription:"",patchEmail:"",patchID:false,initComponent:function(){Ext.apply(this,{buttons:[{text:(this.patchID)?_("Save"):_("Create"),handler:function(){var d=this.ownerCt.ownerCt,c=d.findByType("form").shift().getForm().getValues();XHR({params:{task:"managePatch",name:c.name,description:c.description,email:c.email,patchID:d.patchID},success:function(e){var f=Ext.util.JSON.decode(e.responseText);d.hide();if(d.patchID){ui.cmp.PatchesTreeGrid.getInstance().modPatchName({newPatchName:c.name,newPatchDescription:c.description,newPatchEmail:c.email,patchID:d.patchID})}if(d.nodesToAdd){ui.task.MoveToPatch({patchID:f.patchID,patchName:c.name,patchDescription:c.description,patchEmail:c.email,nodesToAdd:d.nodesToAdd})}}})}},{text:_("Cancel"),handler:function(){this.ownerCt.ownerCt.hide()}}],items:[{xtype:"form",baseCls:"x-plain",labelWidth:110,defaultType:"textfield",labelAlign:"top",items:[{name:"name",fieldLabel:_("Patch name"),anchor:"100%",value:this.patchName},{name:"description",xtype:"textarea",fieldLabel:_("Patch description"),tooltipText:_("This description will be the default during the validation of the patch by a valid user."),anchor:"100%",value:this.patchDescription},{name:"email",fieldLabel:_("Email"),tooltipText:_("If provided, an email will be send to you to inform that the patch is commited."),anchor:"100%",value:this.patchEmail}]}]});ui.cmp.ManagePatchPrompt.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._NotInENGrid");ui.cmp._NotInENGrid.store=new Ext.data.GroupingStore({proxy:new Ext.data.HttpProxy({url:"./do/getFilesNotInEn"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"path"},{name:"name"},{name:"fileModified"}]}),sortInfo:{field:"path",direction:"ASC"},groupField:"path",listeners:{datachanged:function(c){Ext.getDom("acc-notInEn-nb").innerHTML=c.getCount()}}});ui.cmp._NotInENGrid.columns=[{id:"name",header:_("Files"),sortable:true,dataIndex:"name",renderer:function(d,c,e){if(e.data.fileModified){var f=Ext.util.JSON.decode(e.data.fileModified);if(f.user===PhDOE.user.login&&f.anonymousIdent===PhDOE.user.anonymousIdent){return""+d+""}else{return""+d+""}}else{return d}}},{header:_("Path"),dataIndex:"path",hidden:true}];ui.cmp._NotInENGrid.view=new Ext.grid.GroupingView({forceFit:true,startCollapsed:true,groupTextTpl:'{[values.rs[0].data["path"]]} ({[values.rs.length]} {[values.rs.length > 1 ? "'+_("Files")+'" : "'+_("File")+'"]})',deferEmptyText:false,emptyText:'
'+_("No Files")+"
",getRowClass:function(c){if(c.data.fileModified){var d=Ext.util.JSON.decode(c.data.fileModified);return(d.user===PhDOE.user.login&&d.anonymousIdent===PhDOE.user.anonymousIdent)?"fileModifiedByMe":"fileModifiedByAnother"}return false}});ui.cmp._NotInENGrid.menu=function(c){Ext.apply(this,c);this.init();ui.cmp._NotInENGrid.menu.superclass.constructor.call(this)};Ext.extend(ui.cmp._NotInENGrid.menu,Ext.menu.Menu,{init:function(){Ext.apply(this,{items:[{scope:this,text:""+_("View in a new tab")+"",iconCls:"iconView",handler:function(){this.grid.fireEvent("rowdblclick",this.grid,this.rowIdx,this.event)}},{scope:this,text:_("Remove this file"),hidden:(this.grid.store.getAt(this.rowIdx).data.fileModified),iconCls:"iconTrash",handler:function(){var e=this.grid.store.getAt(this.rowIdx),d=e.data.path,c=e.data.name;new ui.task.MarkDeleteTask({fpath:d,fname:c,storeRecord:e})}}]})}});ui.cmp.NotInENGrid=Ext.extend(Ext.grid.GridPanel,{loadMask:true,border:false,autoExpandColumn:"name",enableDragDrop:true,ddGroup:"mainPanelDDGroup",view:ui.cmp._NotInENGrid.view,columns:ui.cmp._NotInENGrid.columns,onRowContextMenu:function(c,f,d){d.stopEvent();c.getSelectionModel().selectRow(f);new ui.cmp._NotInENGrid.menu({grid:c,rowIdx:f,event:d}).showAt(d.getXY())},onRowDblClick:function(c,f,d){this.openFile(c.store.getAt(f).data.id)},openFile:function(g){var e=this.store.getById(g),d=e.data.path,c=e.data.name,f=Ext.util.md5("FNIEN-"+PhDOE.user.lang+d+c);if(!Ext.getCmp("main-panel").findById("FNIEN-"+f)){Ext.getCmp("main-panel").add({id:"FNIEN-"+f,layout:"border",title:c,originTitle:c,iconCls:"iconTabView",closable:true,tabLoaded:false,panLANGLoaded:false,defaults:{split:true},tabTip:String.format(_("Not In EN: in {0}"),d),items:[new ui.cmp.FilePanel({id:"FNIEN-NotInEN-PANEL-"+f,region:"center",title:_("File: ")+d+c,prefix:"FNIEN",ftype:"NotInEN",fid:f,fpath:d,fname:c,original:true,readOnly:true,lang:PhDOE.user.lang,parser:"xml",storeRecord:e,syncScroll:false})]})}Ext.getCmp("main-panel").setActiveTab("FNIEN-"+f)},initComponent:function(){Ext.apply(this,{store:ui.cmp._NotInENGrid.store});ui.cmp.NotInENGrid.superclass.initComponent.call(this);this.on("rowcontextmenu",this.onRowContextMenu,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp._NotInENGrid.instance=null;ui.cmp.NotInENGrid.getInstance=function(c){if(!ui.cmp._NotInENGrid.instance){if(!c){c={}}ui.cmp._NotInENGrid.instance=new ui.cmp.NotInENGrid(c)}return ui.cmp._NotInENGrid.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PatchesTreeGrid","ui.cmp._PatchesTreeGrid.menu");ui.cmp._PatchesTreeGrid.menu.users=function(c){Ext.apply(this,c);this.init();ui.cmp._PatchesTreeGrid.menu.users.superclass.constructor.call(this)};Ext.extend(ui.cmp._PatchesTreeGrid.menu.users,Ext.menu.Menu,{init:function(){var c=[];this.node.cascade(function(d){if(d.attributes.type!=="folder"&&d.attributes.type!=="patch"&&d.attributes.type!=="user"){c.push(d)}},this);Ext.apply(this,{items:[{scope:this,text:String.format(_("Send an email to {0}"),""+this.node.attributes.task+""),iconCls:"iconSendEmail",hidden:(this.node.attributes.task===PhDOE.user.login||this.node.attributes.email==="false"),handler:function(){var d=new ui.cmp.EmailPrompt();d.setData(this.node.attributes.task,this.node.attributes.email);d.show(this.node.el)}},{text:_("Back all files to work in progress module"),hidden:(this.node.attributes.task!==PhDOE.user.login),disabled:Ext.isEmpty(c),iconCls:"iconWorkInProgress",handler:function(){ui.task.MoveToWork({nodesToAdd:c})}},{xtype:"menuseparator",hidden:(this.node.attributes.task!==PhDOE.user.login||PhDOE.user.isAnonymous)},((this.node.attributes.task===PhDOE.user.login&&!PhDOE.user.isAnonymous)?new ui.cmp._WorkTreeGrid.menu.commit({module:"patches",from:"user",node:false,folderNode:false,patchNode:false,userNode:this.node}):"")]})}});ui.cmp._PatchesTreeGrid.menu.patches=function(c){Ext.apply(this,c);this.init();ui.cmp._PatchesTreeGrid.menu.patches.superclass.constructor.call(this)};Ext.extend(ui.cmp._PatchesTreeGrid.menu.patches,Ext.menu.Menu,{init:function(){var d=this.node,f=[],c=d.parentNode.attributes.task,e=d.parentNode.attributes.isAnonymous;this.node.cascade(function(g){if(g.attributes.type!=="folder"&&g.attributes.type!=="patch"&&g.attributes.type!=="user"){f.push(g)}},this);Ext.apply(this,{items:[{text:_("Edit the description of this patch"),iconCls:"iconPendingPatch",hidden:(c!==PhDOE.user.login),handler:function(){var g=new ui.cmp.ManagePatchPrompt({title:_("Modify this patch description"),patchName:d.attributes.task,patchDescription:d.attributes.patchDescription,patchEmail:d.attributes.patchEmail,patchID:d.attributes.idDB});g.show(this.el)}},{text:_("Delete this patch"),iconCls:"iconTrash",hidden:(c!==PhDOE.user.login),handler:function(){ui.task.DeletePatchTask({patchID:d.attributes.idDB})}},{xtype:"menuseparator",hidden:!((!PhDOE.user.isAnonymous&&c===PhDOE.user.login)||!PhDOE.user.isGlobalAdmin)},{text:_("Back all this patch to work in progress module"),iconCls:"iconWorkInProgress",hidden:(c!==PhDOE.user.login),disabled:Ext.isEmpty(f),handler:function(){ui.task.MoveToWork({nodesToAdd:f})}},{xtype:"menuseparator",hidden:(c!==PhDOE.user.login),},{text:_("View unified diff"),iconCls:"iconViewDiff",handler:function(){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",patchID:d.attributes.idDB,patchName:d.attributes.task})}},{text:_("Download the unified diff as a patch"),iconCls:"iconDownloadDiff",handler:function(){window.location.href="./do/downloadPatch?patchID="+d.attributes.idDB+"&csrfToken="+csrfToken}},{xtype:"menuseparator"},((e&&!PhDOE.user.isAnonymous)?new ui.cmp._WorkTreeGrid.menu.commit({module:"patches",from:"anonymousPatch",node:false,folderNode:false,patchNode:this.node,userNode:this.node.parentNode}):""),((!PhDOE.user.isAnonymous&&c===PhDOE.user.login)?new ui.cmp._WorkTreeGrid.menu.commit({module:"patches",from:"patch",node:false,folderNode:false,patchNode:this.node,userNode:this.node.parentNode}):""),((PhDOE.user.isGlobalAdmin&&c!==PhDOE.user.login)?new ui.cmp._WorkTreeGrid.menu.admin({from:"patch",node:this.node}):"")]})}});ui.cmp._PatchesTreeGrid.menu.folders=function(c){Ext.apply(this,c);this.init();ui.cmp._PatchesTreeGrid.menu.folders.superclass.constructor.call(this)};Ext.extend(ui.cmp._PatchesTreeGrid.menu.folders,Ext.menu.Menu,{init:function(){var c=[];if(this.node.parentNode.parentNode.attributes.task!==PhDOE.user.login){return false}this.node.cascade(function(d){if(d.attributes.type!=="folder"&&d.attributes.type!=="patch"&&d.attributes.type!=="user"){c.push(d)}},this);Ext.apply(this,{items:[{text:_("Back all this folder to work in progress module"),iconCls:"iconWorkInProgress",handler:function(){ui.task.MoveToWork({nodesToAdd:c})}},{xtype:"menuseparator",hidden:(PhDOE.user.isAnonymous)},((!PhDOE.user.isAnonymous)?new ui.cmp._WorkTreeGrid.menu.commit({module:"patches",from:"folder",node:false,folderNode:this.node,patchNode:this.node.parentNode,userNode:this.node.parentNode.parentNode}):"")]})}});ui.cmp._PatchesTreeGrid.menu.files=function(c){Ext.apply(this,c);this.init();ui.cmp._PatchesTreeGrid.menu.files.superclass.constructor.call(this)};Ext.extend(ui.cmp._PatchesTreeGrid.menu.files,Ext.menu.Menu,{init:function(){var h=this.node,m=h.attributes.type,g,c=h.parentNode.attributes.task,f=h.attributes.task,k=h.ownerTree,l=h.attributes.idDB,d=[],e=this.node.parentNode.parentNode.parentNode.attributes.task,j;j=h.parentNode.attributes.task.split("/");g=j[0];this.node.cascade(function(o){if(o.attributes.type!=="folder"&&o.attributes.type!=="patch"&&o.attributes.type!=="user"){d.push(o)}},this);Ext.apply(this,{items:[{text:""+((m==="delete")?_("View in a new tab"):_("Edit in a new tab"))+"",iconCls:"iconEdit",handler:function(){ui.cmp.WorkTreeGrid.getInstance().openFile(h)}},{text:_("Back this file to work in progress module"),hidden:(e!==PhDOE.user.login),iconCls:"iconWorkInProgress",handler:function(){ui.task.MoveToWork({nodesToAdd:d})}},"-",{text:_("View diff"),iconCls:"iconViewDiff",hidden:(m==="delete"||m==="new"),handler:function(){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",FileName:f,FilePath:c,currentOwner:e,fileIdDB:h.attributes.idDB})}},{text:_("Download the diff as a patch"),iconCls:"iconDownloadDiff",hidden:(m==="delete"||m==="new"),handler:function(){window.location.href="./do/downloadPatch?FilePath="+c+"&FileName="+f+"&csrfToken="+csrfToken}},{xtype:"menuseparator",hidden:(m==="delete"||m==="new"||e!==PhDOE.user.login)},{text:((m==="delete")?_("Cancel this deletion"):_("Clear this change")),hidden:(e!==PhDOE.user.login),iconCls:"iconPageDelete",handler:function(){new ui.task.ClearLocalChangeTask({ftype:m,fpath:c,fname:f})}},{xtype:"menuseparator",hidden:(PhDOE.user.isAnonymous||e!==PhDOE.user.login)},((e===PhDOE.user.login&&!PhDOE.user.isAnonymous)?new ui.cmp._WorkTreeGrid.menu.commit({module:"patches",from:"file",node:this.node,folderNode:this.node.parentNode,patchNode:this.node.parentNode.parentNode,userNode:this.node.parentNode.parentNode.parentNode}):""),{xtype:"menuseparator",hidden:(!PhDOE.user.isGlobalAdmin&&!(PhDOE.user.lang===g&&PhDOE.user.isLangAdmin))},((PhDOE.user.isGlobalAdmin||(PhDOE.user.lang===g&&PhDOE.user.isLangAdmin))?new ui.cmp._WorkTreeGrid.menu.admin({fileLang:g,from:"file",node:this.node,folderNode:this.node.parentNode,userNode:this.node.parentNode.parentNode.parentNode}):"")]})}});ui.cmp.PatchesTreeGrid=Ext.extend(Ext.ux.tree.TreeGrid,{onContextMenu:function(f,g){g.stopEvent();var d=f.attributes.type,c;switch(d){case"user":f.select();c=new ui.cmp._PatchesTreeGrid.menu.users({node:f});break;case"folder":f.select();c=new ui.cmp._PatchesTreeGrid.menu.folders({node:f});break;case"patch":f.select();c=new ui.cmp._PatchesTreeGrid.menu.patches({node:f});break;default:f.select();c=new ui.cmp._PatchesTreeGrid.menu.files({node:f});break}c.showAt(g.getXY())},modPatchName:function(c){var d=this.getRootNode(),e=d.findChild("idDB",c.patchID,true);e.setText(c.newPatchName);e.attributes.patchDescription=c.newPatchDescription;e.attributes.patchEmail=c.newPatchEmail;e.attributes.task=c.newPatchName},initComponent:function(){Ext.apply(this,{animate:true,useArrows:true,autoScroll:true,border:false,containerScroll:true,selModel:new Ext.tree.MultiSelectionModel(),columns:[{header:_("Users"),dataIndex:"task",uiProvider:{editable:true,qtip:"help"},tpl:new Ext.XTemplate("{task:this.formatUserName}",{formatUserName:function(c,d){if(d.type==="user"){if(d.userID){d.qtip=_("userID: ")+d.userID}return c}if(d.type==="patch"){if(d.creationDate){d.qtip=_("Creation date: ")+Date.parseDate(d.creationDate,"Y-m-d H:i:s").format(_("Y-m-d, H:i"))}return c}return c}})},{header:_("Last modified"),width:120,dataIndex:"last_modified",align:"center",tpl:new Ext.XTemplate("{last_modified:this.formatDate}",{formatDate:function(c,d){if(d.type!=="user"&&d.type!=="folder"&&d.type!=="patch"){return Date.parseDate(c,"Y-m-d H:i:s").format(_("Y-m-d, H:i"))}else{return""}}})}],loader:{dataUrl:"./do/getWork",baseParams:{module:"PatchesForReview"}}});ui.cmp.PatchesTreeGrid.superclass.initComponent.call(this);this.on("contextmenu",this.onContextMenu,this);this.on("resize",this.resizeCmp,this);this.on("dblclick",ui.cmp.WorkTreeGrid.getInstance().openFile,this);this.getRootNode().on("beforechildrenrendered",function(){this.updateFilesCounter.defer(200,this)},this)},resizeCmp:function(g,f,d,e){this.columns[0].width=e-(this.columns[1].width+5);this.updateColumnWidths()},deletePatch:function(q){var e=this.getRootNode(),o,c,d,f,r=[],p,m,h,g;for(p=0;p"}else{h=String.format(_("File EN modified by {0}"),g.user)+"
"}}if(e.data.fileModifiedLang){f=Ext.util.JSON.decode(e.data.fileModifiedLang);if(f.user===PhDOE.user.login&&f.anonymousIdent===PhDOE.user.anonymousIdent){h+=String.format(_("File {0} modified by me"),PhDOE.user.lang.ucFirst())}else{h+=String.format(_("File {0} modified by {1}"),PhDOE.user.lang.ucFirst(),f.user)}}if(h!==""){return""+d+""}else{return d}}},{header:_("Reviewed"),width:45,sortable:true,dataIndex:"reviewed"},{header:_("Reviewer"),width:45,sortable:true,dataIndex:"maintainer"},{header:_("Path"),dataIndex:"path",hidden:true}];ui.cmp._PendingReviewGrid.view=new Ext.grid.GroupingView({forceFit:true,startCollapsed:true,groupTextTpl:'{[values.rs[0].data["path"]]} ({[values.rs.length]} {[values.rs.length > 1 ? "'+_("Files")+'" : "'+_("File")+'"]})',getRowClass:function(c){if(c.data.fileModifiedEN||c.data.fileModifiedLang){var e=Ext.util.JSON.decode(c.data.fileModifiedEN),d=Ext.util.JSON.decode(c.data.fileModifiedLang);return((e.user===PhDOE.user.login&&e.anonymousIdent===PhDOE.user.anonymousIdent)||(d.user===PhDOE.user.login&&d.anonymousIdent===PhDOE.user.anonymousIdent))?"fileModifiedByMe":"fileModifiedByAnother"}return false},deferEmptyText:false,emptyText:'
'+_("No Files")+"
"});Ext.namespace("ui.cmp._PendingReviewGrid.menu");ui.cmp._PendingReviewGrid.menu.group=function(c){Ext.apply(this,c);this.init();ui.cmp._PendingReviewGrid.menu.group.superclass.constructor.call(this)};Ext.extend(ui.cmp._PendingReviewGrid.menu.group,Ext.menu.Item,{iconCls:"iconViewDiff",init:function(){Ext.apply(this,{text:String.format(_("Open all files about {0} extension"),this.gname.ucFirst()),handler:function(){Ext.getBody().mask(' '+String.format(_("Open all files about {0} extension"),this.gname.ucFirst())+". "+_("Please, wait..."));XHR({params:{task:"getAllFilesAboutExtension",ExtName:this.gname},success:function(d){var e=Ext.util.JSON.decode(d.responseText),c;PhDOE.AFfilePendingOpen=[];for(c=0;c"+_("Edit in a new tab")+"",iconCls:"iconFilesNeedReviewed",scope:this,handler:function(){this.grid.fireEvent("rowdblclick",this.grid,this.rowIdx,this.event)}},{scope:this,hidden:this.hideDiffMenu,text:_("View diff..."),iconCls:"iconViewDiff",menu:new Ext.menu.Menu({items:[{scope:this,hidden:(this.grid.store.getAt(this.rowIdx).data.fileModifiedEN===false),text:String.format(_("... of the {0} file"),"EN"),handler:function(){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",FileName:this.fname,FilePath:"en"+this.fpath})}},{scope:this,hidden:(this.grid.store.getAt(this.rowIdx).data.fileModifiedLang===false),text:String.format(_("... of the {0} file"),PhDOE.user.lang.ucFirst()),handler:function(){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",FileName:this.fname,FilePath:PhDOE.user.lang+this.fpath})}}]})},new Ext.menu.Separator({hidden:this.hideGroup}),new ui.cmp._PendingReviewGrid.menu.group({gname:this.gname,hidden:this.hideGroup})]})}});ui.cmp.PendingReviewGrid=Ext.extend(Ext.grid.GridPanel,{loadMask:true,border:false,autoExpandColumn:"name",enableDragDrop:true,ddGroup:"mainPanelDDGroup",columns:ui.cmp._PendingReviewGrid.columns,view:ui.cmp._PendingReviewGrid.view,onRowContextMenu:function(d,k,h){h.stopEvent();var g=d.store.getAt(k),f=g.data.path,c=g.data.name,j=f.split("/");d.getSelectionModel().selectRow(k);new ui.cmp._PendingReviewGrid.menu.main({grid:d,rowIdx:k,event:h,fpath:f,fname:c,hideDiffMenu:(g.data.fileModifiedEN===false&&g.data.fileModifiedLang===false),hideGroup:(j[1]!=="reference"),gname:(j[2])?j[2]:""}).showAt(h.getXY())},onRowDblClick:function(c,f,d){this.openFile(c.store.getAt(f).data.id)},openFile:function(g){var e=this.store.getById(g),d=e.data.path,c=e.data.name,f=Ext.util.md5("FNR-"+PhDOE.user.lang+d+c);if(!Ext.getCmp("main-panel").findById("FNR-"+f)){Ext.getCmp("main-panel").add({id:"FNR-"+f,title:c,layout:"border",iconCls:"iconTabNeedReviewed",closable:true,tabLoaded:false,panVCSLang:!PhDOE.user.conf.reviewed.toolsPanelLogLoad,panVCSEn:!PhDOE.user.conf.reviewed.toolsPanelLogLoad,panLANGLoaded:false,panENLoaded:false,originTitle:c,defaults:{split:true},tabTip:String.format(_("Need Reviewed in: {0}"),d),listeners:{resize:function(h){Ext.getCmp("FNR-EN-PANEL-"+f).setWidth(h.getWidth()/2)}},items:[{region:"west",xtype:"panel",title:_("Tools"),iconCls:"iconConf",collapsedIconCls:"iconConf",plugins:[Ext.ux.PanelCollapsedTitle],collapsible:true,collapsed:!PhDOE.user.conf.reviewed.toolsPanelDisplay,layout:"fit",bodyBorder:false,width:PhDOE.user.conf.reviewed.toolsPanelWidth||375,listeners:{collapse:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"reviewed",itemName:"toolsPanelDisplay",value:false,notify:false})}},expand:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"reviewed",itemName:"toolsPanelDisplay",value:true,notify:false})}},resize:function(h,j){if(this.ownerCt.tabLoaded&&j&&j!=PhDOE.user.conf.reviewed.toolsPanelWidth){new ui.task.UpdateConfTask({module:"reviewed",itemName:"toolsPanelWidth",value:j,notify:false})}}},items:{xtype:"tabpanel",activeTab:0,tabPosition:"bottom",enableTabScroll:true,defaults:{autoScroll:true},items:[new ui.cmp.VCSLogGrid({layout:"fit",title:String.format(_("{0} Log"),PhDOE.user.lang.ucFirst()),prefix:"FNR-LANG",fid:f,fpath:PhDOE.user.lang+d,fname:c,loadStore:PhDOE.user.conf.reviewed.toolsPanelLogLoad}),new ui.cmp.VCSLogGrid({layout:"fit",title:String.format(_("{0} Log"),"En"),prefix:"FNR-EN",fid:f,fpath:"en"+d,fname:c,loadStore:PhDOE.user.conf.reviewed.toolsPanelLogLoad}),new ui.cmp.DictionaryGrid({layout:"fit",title:_("Dictionary"),prefix:"FNR",fid:f})]}},new ui.cmp.FilePanel({id:"FNR-LANG-PANEL-"+f,region:"center",title:String.format(_("{0} File: "),PhDOE.user.lang.ucFirst())+d+c,prefix:"FNR",ftype:"LANG",spellCheck:PhDOE.user.conf.reviewed.enableSpellCheckLang,spellCheckConf:{module:"reviewed",itemName:"enableSpellCheckLang"},fid:f,fpath:d,fname:c,lang:PhDOE.user.lang,parser:"xml",storeRecord:e,syncScrollCB:true,syncScroll:true,syncScrollConf:{module:"reviewed",itemName:"syncScrollbars"}}),new ui.cmp.FilePanel({id:"FNR-EN-PANEL-"+f,region:"east",title:_("en File: ")+d+c,prefix:"FNR",ftype:"EN",original:true,readOnly:true,openInNewTabBtn:true,fid:f,fpath:d,fname:c,lang:"en",parser:"xml",storeRecord:e,syncScroll:true,syncScrollConf:{module:"reviewed",itemName:"syncScrollbars"}})]})}Ext.getCmp("main-panel").setActiveTab("FNR-"+f)},initComponent:function(){Ext.apply(this,{store:ui.cmp._PendingReviewGrid.store,tbar:[_("Filter: ")," ",new Ext.form.TwinTriggerField({id:"FNR-filter",width:180,hideTrigger1:true,enableKeyEvents:true,validateOnBlur:false,validationEvent:false,trigger1Class:"x-form-clear-trigger",trigger2Class:"x-form-search-trigger",listeners:{keypress:function(d,c){if(c.getKey()===c.ENTER){this.onTrigger2Click()}}},onTrigger1Click:function(){this.setValue("");this.triggers[0].hide();this.setSize(180,10);ui.cmp._PendingReviewGrid.instance.store.clearFilter()},onTrigger2Click:function(){var c=this.getValue(),d;if(c===""||c.length<3){this.markInvalid(_("Your filter must contain at least 3 characters"));return}this.clearInvalid();this.triggers[0].show();this.setSize(180,10);d=new RegExp(c,"i");ui.cmp._PendingReviewGrid.instance.store.filterBy(function(e){if(d.test(e.data.path)||d.test(e.data.name)||d.test(e.data.reviewed)||d.test(e.data.maintainer)){return true}else{return false}},this)}})]});ui.cmp.PendingReviewGrid.superclass.initComponent.call(this);this.on("rowcontextmenu",this.onRowContextMenu,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp._PendingReviewGrid.instance=null;ui.cmp.PendingReviewGrid.getInstance=function(c){if(!ui.cmp._PendingReviewGrid.instance){if(!c){c={}}ui.cmp._PendingReviewGrid.instance=new ui.cmp.PendingReviewGrid(c)}return ui.cmp._PendingReviewGrid.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PendingTranslateGrid");ui.cmp._PendingTranslateGrid.store=new Ext.data.GroupingStore({proxy:new Ext.data.HttpProxy({url:"./do/getFilesNeedTranslate"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"path"},{name:"name"},{name:"fileModified"}]}),sortInfo:{field:"name",direction:"ASC"},groupField:"path",listeners:{datachanged:function(c){Ext.getDom("acc-need-translate-nb").innerHTML=c.getCount()}}});ui.cmp._PendingTranslateGrid.view=new Ext.grid.GroupingView({forceFit:true,startCollapsed:true,groupTextTpl:'{[values.rs[0].data["path"]]} ({[values.rs.length]} {[values.rs.length > 1 ? "'+_("Files")+'" : "'+_("File")+'"]})',deferEmptyText:false,getRowClass:function(c){if(c.data.fileModified){var d=Ext.util.JSON.decode(c.data.fileModified);return(d.user===PhDOE.user.login&&d.anonymousIdent===PhDOE.user.anonymousIdent)?"fileModifiedByMe":"fileModifiedByAnother"}return false},emptyText:'
'+_("No Files")+"
"});ui.cmp._PendingTranslateGrid.columns=[{id:"name",header:_("Files"),sortable:true,dataIndex:"name",renderer:function(c,f,d){if(d.data.fileModified){var e=Ext.util.JSON.decode(d.data.fileModified);if(e.user===PhDOE.user.login&&e.anonymousIdent===PhDOE.user.anonymousIdent){return""+c+""}else{return""+c+""}}else{return c}}},{header:_("Path"),dataIndex:"path",hidden:true}];ui.cmp._PendingTranslateGrid.menu=function(c){Ext.apply(this,c);this.init();ui.cmp._StaleFileGrid.menu.superclass.constructor.call(this)};Ext.extend(ui.cmp._PendingTranslateGrid.menu,Ext.menu.Menu,{init:function(){Ext.apply(this,{items:[{scope:this,text:""+_("Edit in a new tab")+"",iconCls:"iconTabNeedTranslate",handler:function(){this.grid.fireEvent("rowdblclick",this.grid,this.rowIdx,this.event)}}]})}});ui.cmp.PendingTranslateGrid=Ext.extend(Ext.grid.GridPanel,{view:ui.cmp._PendingTranslateGrid.view,loadMask:true,autoExpandColumn:"name",enableDragDrop:true,ddGroup:"mainPanelDDGroup",border:false,onRowContextMenu:function(c,f,d){d.stopEvent();c.getSelectionModel().selectRow(f);new ui.cmp._PendingTranslateGrid.menu({grid:c,event:d,rowIdx:f}).showAt(d.getXY())},onRowDblClick:function(c,d){this.openFile(c.store.getAt(d).data.id)},openFile:function(g){var e=this.store.getById(g),d=e.data.path,c=e.data.name,f=Ext.util.md5("FNT-"+PhDOE.user.lang+d+c),h;if(!Ext.getCmp("main-panel").findById("FNT-"+f)){if(PhDOE.user.conf.newFile.secondPanel=="google"||PhDOE.user.conf.newFile.secondPanel=="originalFile"){h=true}else{h=false}Ext.getCmp("main-panel").add({id:"FNT-"+f,layout:"border",title:c,originTitle:c,iconCls:"iconTabNeedTranslate",closable:true,tabLoaded:false,panTRANSLoaded:false,panTRANSSecondLoaded:!h,defaults:{split:true},tabTip:String.format(_("Need translate: in {0}"),d),listeners:{resize:function(j){if(PhDOE.user.conf.newFile.secondPanel=="google"){Ext.getCmp("FNT-GGTRANS-PANEL-"+f).setWidth(j.getWidth()/2)}if(PhDOE.user.conf.newFile.secondPanel=="originalFile"){Ext.getCmp("FNT-EN-PANEL-"+f).setWidth(j.getWidth()/2)}}},items:[{region:"west",xtype:"panel",title:_("Tools"),iconCls:"iconConf",collapsedIconCls:"iconConf",plugins:[Ext.ux.PanelCollapsedTitle],collapsible:true,collapsed:!PhDOE.user.conf.newFile.toolsPanelDisplay,layout:"fit",bodyBorder:false,width:PhDOE.user.conf.newFile.toolsPanelWidth||375,listeners:{collapse:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"newFile",itemName:"toolsPanelDisplay",value:false,notify:false})}},expand:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"newFile",itemName:"toolsPanelDisplay",value:true,notify:false})}},resize:function(j,k){if(this.ownerCt.tabLoaded&&k&&k!=PhDOE.user.conf.newFile.toolsPanelWidth){new ui.task.UpdateConfTask({module:"newFile",itemName:"toolsPanelWidth",value:k,notify:false})}}},items:{xtype:"tabpanel",activeTab:0,tabPosition:"bottom",defaults:{autoScroll:true},items:[new ui.cmp.DictionaryGrid({layout:"fit",title:_("Dictionary"),prefix:"FNT",fid:f})]}},new ui.cmp.FilePanel({id:"FNT-TRANS-PANEL-"+f,region:"center",title:_("New file: ")+PhDOE.user.lang+d+c,isTrans:true,prefix:"FNT",ftype:"TRANS",spellCheck:PhDOE.user.conf.newFile.enableSpellCheck,spellCheckConf:{module:"newFile",itemName:"enableSpellCheck"},fid:f,fpath:d,fname:c,lang:PhDOE.user.lang,parser:"xml",storeRecord:e,syncScrollCB:h,syncScroll:h,syncScrollConf:{module:"newFile",itemName:"syncScrollbars"}}),((PhDOE.user.conf.newFile.secondPanel=="google")?new ui.cmp.FilePanel({id:"FNT-GGTRANS-PANEL-"+f,region:"east",title:_("Automatic translation: ")+PhDOE.user.lang+d+c,isTrans:true,prefix:"FNT",ftype:"GGTRANS",fid:f,fpath:d,fname:c,readOnly:true,lang:PhDOE.user.lang,parser:"xml",storeRecord:e,syncScroll:true,syncScrollConf:{module:"newFile",itemName:"syncScrollbars"}}):false),((PhDOE.user.conf.newFile.secondPanel=="originalFile")?new ui.cmp.FilePanel({id:"FNT-EN-PANEL-"+f,region:"east",title:_("File: ")+"en"+d+c,prefix:"FNT",ftype:"EN",fid:f,fpath:d,fname:c,original:true,readOnly:true,lang:"en",parser:"xml",storeRecord:e,syncScroll:true,syncScrollConf:{module:"newFile",itemName:"syncScrollbars"}}):false)]})}Ext.getCmp("main-panel").setActiveTab("FNT-"+f)},initComponent:function(){Ext.apply(this,{columns:ui.cmp._PendingTranslateGrid.columns,store:ui.cmp._PendingTranslateGrid.store,tbar:[_("Filter: ")," ",new Ext.form.TwinTriggerField({id:"FNT-filter",width:180,hideTrigger1:true,enableKeyEvents:true,validateOnBlur:false,validationEvent:false,trigger1Class:"x-form-clear-trigger",trigger2Class:"x-form-search-trigger",listeners:{keypress:function(d,c){if(c.getKey()===c.ENTER){this.onTrigger2Click()}}},onTrigger1Click:function(){this.setValue("");this.triggers[0].hide();this.setSize(180,10);ui.cmp._PendingTranslateGrid.instance.store.clearFilter()},onTrigger2Click:function(){var c=this.getValue(),d;if(c===""||c.length<3){this.markInvalid(_("Your filter must contain at least 3 characters"));return}this.clearInvalid();this.triggers[0].show();this.setSize(180,10);d=new RegExp(c,"i");ui.cmp._PendingTranslateGrid.instance.store.filterBy(function(e){if(d.test(e.data.path)||d.test(e.data.name)){return true}else{return false}},this)}})]});ui.cmp.PendingTranslateGrid.superclass.initComponent.call(this);this.on("rowcontextmenu",this.onRowContextMenu,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp._PendingTranslateGrid.instance=null;ui.cmp.PendingTranslateGrid.getInstance=function(c){if(!ui.cmp._PendingTranslateGrid.instance){if(!c){c={}}ui.cmp._PendingTranslateGrid.instance=new ui.cmp.PendingTranslateGrid(c)}return ui.cmp._PendingTranslateGrid.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PortletBugs");ui.cmp._PortletBugs.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getOpenBugs"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"title"},{name:"link"},{name:"description"},{name:"xmlID"}]})});ui.cmp._PortletBugs.gridFormatTitle=function(c){return String.format('
{0}
',c)};ui.cmp._PortletBugs.gridColumns=[{id:"GridBugTitle",header:_("Title"),sortable:true,dataIndex:"title",renderer:ui.cmp._PortletBugs.gridFormatTitle}];ui.cmp._PortletBugs.gridView=new Ext.grid.GridView({forceFit:true,emptyText:'
'+_("You must manually load this data.
Use the refresh button !")+"
",deferEmptyText:false,enableRowBody:true,showPreview:false,getRowClass:function(c,e,d){if(this.showPreview){d.body="

"+c.data.description+"

";return"x-grid3-row-expanded"}return"x-grid3-row-collapsed"}});ui.cmp._PortletBugs.grid=Ext.extend(Ext.grid.GridPanel,{loadMask:true,autoScroll:true,height:250,autoExpandColumn:"GridBugTitle",id:"PortletBugs-grid-id",store:ui.cmp._PortletBugs.store,columns:ui.cmp._PortletBugs.gridColumns,view:ui.cmp._PortletBugs.gridView,sm:new Ext.grid.RowSelectionModel({singleSelect:true}),onRowDblClick:function(e,g){var c=e.store.getAt(g).data.id,d=e.store.getAt(g).data.link,f=e.store.getAt(g).data.title;if(!Ext.getCmp("main-panel").findById("bugs-"+c)){Ext.getCmp("main-panel").add({id:"bugs-"+c,xtype:"panel",title:Ext.util.Format.substr(f,0,20)+"...",tabTip:f,iconCls:"iconBugs",closable:true,layout:"fit",items:[new Ext.ux.IFrameComponent({id:"frame-bugs-"+c,url:d})]})}Ext.getCmp("main-panel").setActiveTab("bugs-"+c)},openRelatedFile:function(c){new ui.task.GetFileInfoByXmlID({xmlID:c})},onContextClick:function(c,f,d){if(!this.menu){this.menu=new Ext.menu.Menu({id:"submenu-bugs",items:[{scope:this,text:""+_("Open in a new Tab")+"",iconCls:"iconOpenInTab",handler:function(){this.fireEvent("rowdblclick",c,this.ctxIndex,d);this.menu.hide()}},"-",{scope:this,text:_("Refresh this grid"),iconCls:"iconRefresh",handler:function(){this.ctxIndex=null;ui.cmp._PortletBugs.reloadData()}},{scope:this,text:_("Open the related file"),iconCls:"iconAllFiles",id:"bugs-open-related-file",handler:function(){this.openRelatedFile(this.ctxXmlID)}}]})}this.getSelectionModel().selectRow(f);d.stopEvent();if(this.ctxIndex){this.ctxIndex=null}if(this.ctxXmlID){this.ctxXmlID=null}this.ctxIndex=f;this.ctxXmlID=c.store.getAt(this.ctxIndex).data.xmlID;this.menu.showAt(d.getXY());if(!this.ctxXmlID){Ext.getCmp("bugs-open-related-file").disable()}else{Ext.getCmp("bugs-open-related-file").enable()}},togglePreview:function(c){this.view.showPreview=c;this.view.refresh()},initComponent:function(c){this.tbar=[{text:_("Summary"),pressed:false,enableToggle:true,iconCls:"iconSummary",scope:this,toggleHandler:function(d,e){this.togglePreview(e)}}];ui.cmp._PortletBugs.grid.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowcontextmenu",this.onContextClick,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp._PortletBugs.reloadData=function(){ui.cmp._PortletBugs.store.reload({callback:function(c,e,d){if(!d){Ext.getCmp("PortletBugs-grid-id").getView().mainBody.update('
'+_("Error when loading open bugs from Php.net !")+"
");Ext.get("PortletBugs-grid-defaultMess-id").highlight()}else{if(ui.cmp._PortletBugs.store.getTotalCount()===0){Ext.getCmp("PortletBugs-grid-id").getView().mainBody.update('
'+_("No open bugs")+"
");Ext.get("PortletBugs-grid-defaultMess-id").highlight()}}}})};ui.cmp.PortletBugs=Ext.extend(Ext.ux.Portlet,{title:"",iconCls:"iconBugs",layout:"fit",store:ui.cmp._PortletBugs.store,reloadData:ui.cmp._PortletBugs.reloadData,tools:[{id:"refresh",qtip:_("Refresh this grid"),handler:function(){ui.cmp._PortletBugs.reloadData()}}],listeners:{expand:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletBugsCollapsed",value:false,notify:false})}},collapse:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletBugsCollapsed",value:true,notify:false})}},afterrender:function(c){if(PhDOE.user.conf.portletBugsCollapsed){c.collapse()}else{c.expand()}}},initComponent:function(c){this.id="portletBugs";this.title=String.format(_("Open bugs for {0}"),"doc-"+this.lang);Ext.apply(this,c);ui.cmp.PortletBugs.superclass.initComponent.apply(this);this.add(new ui.cmp._PortletBugs.grid())}});ui.cmp._PortletBugs.instance=null;ui.cmp.PortletBugs.getInstance=function(c){if(!ui.cmp._PortletBugs.instance){if(!c){c={}}ui.cmp._PortletBugs.instance=new ui.cmp.PortletBugs(c)}return ui.cmp._PortletBugs.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PortletInfo");ui.cmp._PortletInfo.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getInfos"}),baseParams:{start:0,limit:10},reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"field"},{name:"value"},{name:"date",type:"date",dateFormat:"Y-m-d H:i:s"},{name:"elapsedTime"}]}),listeners:{load:function(c){var e=c.data.items[0].data.date;PhDOE.lastInfoDate=e.format("Y-m-d H:i:s")}}});ui.cmp._PortletInfo.store.setDefaultSort("date","desc");ui.cmp._PortletInfo.typeRenderer=function(l,j,g){var d,c,m,o,e,k,h,f;switch(l){case"updateData":d=g.data.value.user;return String.format(_("{0} updated app's data"),d);break;case"changeFilesOwner":d=g.data.value.user;return String.format(_("{0} changed file's owner"),d);break;case"checkEntities":d=g.data.value.user;return String.format(_("{0} check all entitites"),d);break;case"logout":d=g.data.value.user;return String.format(_("{0} logged out"),d);break;case"login":d=g.data.value.user;c=g.data.value.lang;authService=g.data.value.authService;f="";if(authService=="google"){f=' '}else{if(authService=="facebook"){f=' '}}return f+String.format(_("{0} is logged in using the {1} language"),d,c.ucFirst());break;case"commitFolders":d=g.data.value.user;c=g.data.value.lang;m=g.data.value.nbFolders;return String.format(_("{0} committed {1} new folder(s) in the {2} language"),d,m,c.ucFirst());break;case"commitFiles":d=g.data.value.user;c=g.data.value.lang;o=g.data.value.nbFilesCreate;e=g.data.value.nbFilesDelete;k=g.data.value.nbFilesUpdate;h=o+e+k;return String.format(_("{0} committed {1} file(s) ({2} new, {3} update, {4} delete) in the language {5}"),d,h,o,k,e,c.ucFirst());break}};ui.cmp._PortletInfo.gridColumns=[new Ext.grid.RowNumberer(),{id:"Type",header:_("Type"),width:180,sortable:true,dataIndex:"field",renderer:ui.cmp._PortletInfo.typeRenderer},{header:_("Since"),width:110,sortable:false,dataIndex:"elapsedTime",renderer:function(d,c,e){if(!d){d=_("Less than one second")}else{d=String.format(_("{0} "+d.units),d.value)}return""+d+""}},{header:_("Date"),width:110,sortable:true,dataIndex:"date",hidden:true,renderer:Ext.util.Format.dateRenderer(_("Y-m-d, H:i"))}];ui.cmp._PortletInfo.grid=Ext.extend(Ext.grid.GridPanel,{autoExpandColumn:"Type",loadMask:true,autoScroll:true,autoHeight:true,store:ui.cmp._PortletInfo.store,columns:ui.cmp._PortletInfo.gridColumns,view:ui.cmp._PortletInfo.gridView,initComponent:function(){Ext.apply(this,{bbar:new Ext.PagingToolbar({pageSize:10,store:this.store,displayInfo:true})});ui.cmp._PortletInfo.grid.superclass.initComponent.call(this);this.on("rowdblclick",this.onRowdblclick,this)}});ui.cmp.PortletInfo=Ext.extend(Ext.ux.Portlet,{title:_("Information"),iconCls:"iconInfo",layout:"fit",store:ui.cmp._PortletInfo.store,tools:[{id:"refresh",qtip:_("Refresh this grid"),handler:function(){ui.cmp._PortletInfo.store.reload()}}],listeners:{expand:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletInfoCollapsed",value:false,notify:false})}},collapse:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletInfoCollapsed",value:true,notify:false})}},afterrender:function(c){if(PhDOE.user.conf.portletInfoCollapsed){c.collapse()}else{c.expand()}}},initComponent:function(c){this.id="portletInfo";Ext.apply(this,c);ui.cmp.PortletInfo.superclass.initComponent.apply(this);this.add(new ui.cmp._PortletInfo.grid())}});ui.cmp._PortletInfo.instance=null;ui.cmp.PortletInfo.getInstance=function(c){if(!ui.cmp._PortletInfo.instance){if(!c){c={}}ui.cmp._PortletInfo.instance=new ui.cmp.PortletInfo(c)}return ui.cmp._PortletInfo.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PortletLocalMail");ui.cmp._PortletLocalMail.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getLastNews"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"title"},{name:"link"},{name:"description"},{name:"pubDate",type:"date",dateFormat:"Y/m/d H:i:s"}]})});ui.cmp._PortletLocalMail.store.setDefaultSort("pubDate","desc");ui.cmp._PortletLocalMail.columns=[new Ext.grid.RowNumberer(),{id:"GridMailingTitle",header:_("Title"),sortable:true,dataIndex:"title"},{header:_("By"),width:100,sortable:true,dataIndex:"description"},{header:_("Date"),width:100,sortable:true,dataIndex:"pubDate",renderer:Ext.util.Format.dateRenderer(_("Y-m-d, H:i"))}];ui.cmp._PortletLocalMail.grid=Ext.extend(Ext.grid.GridPanel,{loadMask:true,autoScroll:true,height:250,autoExpandColumn:"GridMailingTitle",id:"PortletLocalMail-grid-id",store:ui.cmp._PortletLocalMail.store,columns:ui.cmp._PortletLocalMail.columns,sm:new Ext.grid.RowSelectionModel({singleSelect:true}),view:new Ext.grid.GridView({forceFit:true,enableRowBody:true,ignoreAdd:true,emptyText:'
'+_("You must manually load this data.
Use the refresh button !")+"
",deferEmptyText:false}),onRowDblClick:function(d,g){var c=d.store.getAt(g).data.pubDate,f=d.store.getAt(g).data.link,e=d.store.getAt(g).data.title;if(!Ext.getCmp("main-panel").findById("mail-"+c)){Ext.getCmp("main-panel").add({xtype:"panel",id:"mail-"+c,title:Ext.util.Format.substr(e,0,20)+"...",tabTip:e,iconCls:"iconMailing",closable:true,layout:"fit",items:[new Ext.ux.IFrameComponent({id:"frame-mail-"+c,url:f})]})}Ext.getCmp("main-panel").setActiveTab("mail-"+c)},onContextClick:function(c,f,d){if(!this.menu){this.menu=new Ext.menu.Menu({id:"submenu-mail",items:[{scope:this,text:""+_("Open in a new Tab")+"",iconCls:"iconOpenInTab",handler:function(){this.fireEvent("rowdblclick",c,this.ctxIndex,d);this.menu.hide()}},"-",{scope:this,text:_("Refresh this grid"),iconCls:"iconRefresh",handler:function(){this.ctxIndex=null;ui.cmp._PortletLocalMail.reloadData()}}]})}this.getSelectionModel().selectRow(f);d.stopEvent();if(this.ctxIndex){this.ctxIndex=null}this.ctxIndex=f;this.menu.showAt(d.getXY())},initComponent:function(c){ui.cmp._PortletLocalMail.grid.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowcontextmenu",this.onContextClick,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp._PortletLocalMail.reloadData=function(){ui.cmp._PortletLocalMail.store.reload({callback:function(d,e,c){if(!c){Ext.getCmp("PortletLocalMail-grid-id").getView().mainBody.update('
'+_("Error when loading mails from this mailing list !")+"
");Ext.get("PortletLocalMail-grid-defaultMess-id").highlight()}}})};ui.cmp.PortletLocalMail=Ext.extend(Ext.ux.Portlet,{title:"",iconCls:"iconMailing",layout:"fit",store:ui.cmp._PortletLocalMail.store,reloadData:ui.cmp._PortletLocalMail.reloadData,tools:[{id:"refresh",qtip:_("Refresh this grid"),handler:function(){ui.cmp._PortletLocalMail.reloadData()}}],listeners:{expand:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletLocalMailCollapsed",value:false,notify:false})}},collapse:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletLocalMailCollapsed",value:true,notify:false})}},afterrender:function(c){if(PhDOE.user.conf.portletLocalMailCollapsed){c.collapse()}else{c.expand()}}},initComponent:function(c){this.id="portletLocalMail";Ext.apply(this,c);ui.cmp.PortletLocalMail.superclass.initComponent.apply(this);this.title=String.format(_("Mail from {0}"),"doc-"+this.lang);this.add(new ui.cmp._PortletLocalMail.grid())}});ui.cmp._PortletLocalMail.instance=null;ui.cmp.PortletLocalMail.getInstance=function(c){if(!ui.cmp._PortletLocalMail.instance){if(!c){c={}}ui.cmp._PortletLocalMail.instance=new ui.cmp.PortletLocalMail(c)}return ui.cmp._PortletLocalMail.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PortletSummary");ui.cmp._PortletSummary.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getSummaryInfo"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"libel"},{name:"nbFiles"},{name:"percentFiles"},{name:"sizeFiles"},{name:"percentSize"}]}),listeners:{load:function(){this.each(function(c){switch(c.id){case 1:c.set("libel",_("Up to date files"));break;case 2:c.set("libel",_("Stale files"));break;case 3:c.set("libel",_("Files available for translation"));break;case 4:c.set("libel",_("Total"));break;default:c.set("libel","");break}c.commit()})}}});ui.cmp._PortletSummary.gridColumns=[new Ext.grid.RowNumberer(),{id:"StatusType",header:_("File status type"),width:180,sortable:true,dataIndex:"libel"},{header:_("Number of files"),width:110,sortable:true,dataIndex:"nbFiles"},{header:_("Percent of files"),width:110,sortable:true,dataIndex:"percentFiles"},{header:_("Size of files (kB)"),width:110,sortable:true,dataIndex:"sizeFiles"},{header:_("Percent of size"),width:110,sortable:true,dataIndex:"percentSize"}];ui.cmp._PortletSummary.gridView=new Ext.grid.GridView({getRowClass:function(c){switch(c.data.id){case 1:return"summary_1";case 2:return"summary_2";case 3:return"summary_3";case 4:return"summary_4";default:return""}}});ui.cmp._PortletSummary.grid=Ext.extend(Ext.grid.GridPanel,{loadMask:true,autoScroll:true,autoHeight:true,store:ui.cmp._PortletSummary.store,columns:ui.cmp._PortletSummary.gridColumns,view:ui.cmp._PortletSummary.gridView,onRowdblclick:function(c,e){var d=c.store.getAt(e).data.id;if(d===2){Ext.getCmp("acc-need-update").expand()}if(d===3){Ext.getCmp("acc-need-translate").expand()}},initComponent:function(c){ui.cmp._PortletSummary.grid.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowdblclick",this.onRowdblclick,this)}});ui.cmp.PortletSummary=Ext.extend(Ext.ux.Portlet,{title:_("Summary"),iconCls:"",layout:"fit",store:ui.cmp._PortletSummary.store,tools:[{id:"refresh",qtip:_("Refresh this grid"),handler:function(){ui.cmp._PortletSummary.store.reload()}}],listeners:{expand:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletSummaryCollapsed",value:false,notify:false})}},collapse:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletSummaryCollapsed",value:true,notify:false})}}},initComponent:function(c){this.id="portletSummary";Ext.apply(this,c);ui.cmp.PortletSummary.superclass.initComponent.apply(this);this.add(new ui.cmp._PortletSummary.grid())},afterRender:function(){ui.cmp.PortletSummary.superclass.afterRender.call(this);var c={cs:"cz",sr:"rs",sv:"se"};this.header.insertFirst({tag:"div",id:Ext.id(),style:"float: left; margin-right: 2px;",cls:"flags flag-"+(c[this.lang]||this.lang)},"first");if(PhDOE.user.conf.portletSummaryCollapsed){this.collapse()}else{this.expand()}}});ui.cmp._PortletSummary.instance=null;ui.cmp.PortletSummary.getInstance=function(c){if(!ui.cmp._PortletSummary.instance){if(!c){c={}}ui.cmp._PortletSummary.instance=new ui.cmp.PortletSummary(c)}return ui.cmp._PortletSummary.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PortletTranslationGraph");function renderLibel(c){return _(c)}ui.cmp._PortletTranslationGraph.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getGraphLang"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"libel",convert:renderLibel},{name:"total"}]})});ui.cmp._PortletTranslationGraph.chart=Ext.extend(Ext.chart.PieChart,{height:400,url:"js/ExtJs/resources/charts.swf",dataField:"total",categoryField:"libel",store:ui.cmp._PortletTranslationGraph.store,series:[{style:{colors:["#68D888","#FF6347","#EEE8AA"]}}],extraStyle:{legend:{display:"bottom",padding:5,font:{family:"Tahoma",size:13}}},initComponent:function(c){ui.cmp._PortletTranslationGraph.chart.superclass.initComponent.call(this);Ext.apply(this,c)}});ui.cmp.PortletTranslationGraph=Ext.extend(Ext.ux.Portlet,{title:_("Graphics"),iconCls:"iconGraphic",layout:"fit",store:ui.cmp._PortletTranslationGraph.store,tools:[{id:"refresh",qtip:_("Refresh this graph"),handler:function(){ui.cmp._PortletTranslationGraph.store.reload()}}],initComponent:function(c){this.id="portletTranslationGraph";Ext.apply(this,c);ui.cmp.PortletTranslationGraph.superclass.initComponent.apply(this);this.add(new ui.cmp._PortletTranslationGraph.chart())}});ui.cmp._PortletTranslationGraph.instance=null;ui.cmp.PortletTranslationGraph.getInstance=function(c){if(!ui.cmp._PortletTranslationGraph.instance){if(!c){c={}}ui.cmp._PortletTranslationGraph.instance=new ui.cmp.PortletTranslationGraph(c)}return ui.cmp._PortletTranslationGraph.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PortletTranslationsGraph");ui.cmp._PortletTranslationsGraph.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getGraphLangs"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"libel",type:"string"},{name:"fullLibel",type:"string"},{name:"total",type:"int"},{name:"percent",type:"float"}]})});ui.cmp._PortletTranslationsGraph.chart=Ext.extend(Ext.chart.ColumnChart,{height:400,url:"js/ExtJs/resources/charts.swf",xField:"libel",tipRenderer:function(d,c){return _("Lang:")+" "+c.data.fullLibel+"\r"+_("Total:")+" "+c.data.total+" "+_("files")+" ("+c.data.percent+"%)"},series:[{type:"column",displayName:"Total",yField:"total",style:{image:"themes/img/bar.gif",mode:"stretch",color:10075112}}],store:ui.cmp._PortletTranslationsGraph.store,initComponent:function(c){ui.cmp._PortletTranslationsGraph.chart.superclass.initComponent.call(this);Ext.apply(this,c)}});ui.cmp.PortletTranslationsGraph=Ext.extend(Ext.ux.Portlet,{title:_("Graphics for all languages"),iconCls:"iconGraphic",layout:"fit",store:ui.cmp._PortletTranslationsGraph.store,tools:[{id:"refresh",qtip:_("Refresh this graph"),handler:function(){ui.cmp._PortletTranslationsGraph.store.reload()}}],initComponent:function(c){this.id="portletTranslationsGraph";Ext.apply(this,c);ui.cmp.PortletTranslationsGraph.superclass.initComponent.apply(this);this.add(new ui.cmp._PortletTranslationsGraph.chart())}});ui.cmp._PortletTranslationsGraph.instance=null;ui.cmp.PortletTranslationsGraph.getInstance=function(c){if(!ui.cmp._PortletTranslationsGraph.instance){if(!c){c={}}ui.cmp._PortletTranslationsGraph.instance=new ui.cmp.PortletTranslationsGraph(c)}return ui.cmp._PortletTranslationsGraph.instance};Ext.namespace("ui","ui.cmp","ui.cmp._PortletTranslator","ui.cmp._PortletReviewer");ui.cmp._PortletTranslator.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getTranslatorInfo"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"name"},{name:"email",mapping:"mail"},{name:"nick"},{name:"vcs"},{name:"uptodate",type:"int"},{name:"stale",type:"int"},{name:"sum",type:"int"}]}),listeners:{load:function(){var d=this.getCount(),c=d*20;ui.cmp.PortletTranslator.getInstance().setHeight(c+124);ui.cmp.PortletTranslator.getInstance().doLayout()}}});ui.cmp._PortletTranslator.store.setDefaultSort("nick","asc");ui.cmp._PortletReviewer.store=new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getReviewerInfo"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"name"},{name:"email",mapping:"mail"},{name:"nick"},{name:"vcs"},{name:"reviewedUptodate",type:"int"},{name:"reviewedStale",type:"int"},{name:"reviewedSum",type:"int"}]})});ui.cmp._PortletReviewer.store.setDefaultSort("nick","asc");ui.cmp._PortletTranslator.translatorSumRenderer=function(c){if(c){c=(c===0||c>1)?c:1;return String.format("("+_("{0} Translators")+")",c)}else{return false}};ui.cmp._PortletReviewer.translatorSumRenderer=function(c){if(c){c=(c===0||c>1)?c:1;return String.format("("+_("{0} Reviewers")+")",c)}else{return _("No reviewer")}};ui.cmp._PortletTranslator.uptodateRenderer=function(c){if(c==="0"){return false}else{return''+c+""}};ui.cmp._PortletReviewer.uptodateRenderer=function(c){if(c==="0"){return false}else{return''+c+""}};ui.cmp._PortletTranslator.staleRenderer=function(c){if(c==="0"){return false}else{return''+c+""}};ui.cmp._PortletReviewer.staleRenderer=function(c){if(c==="0"){return false}else{return''+c+""}};ui.cmp._PortletTranslator.sumRenderer=function(c){return(c==="0")?"":c};ui.cmp._PortletReviewer.sumRenderer=function(c){return(c==="0")?"":c};ui.cmp._PortletTranslator.gridColumns=[new Ext.grid.RowNumberer(),{id:"GridTransName",header:_("Name"),sortable:true,dataIndex:"name",summaryType:"count",summaryRenderer:ui.cmp._PortletTranslator.translatorSumRenderer},{header:_("Email"),width:110,sortable:true,dataIndex:"email"},{header:_("Nick"),width:70,sortable:true,dataIndex:"nick"},{header:_("VCS"),width:45,sortable:true,dataIndex:"vcs"},{header:_("UptoDate"),width:60,sortable:true,renderer:ui.cmp._PortletTranslator.uptodateRenderer,dataIndex:"uptodate",summaryType:"sum"},{header:_("Stale"),width:90,sortable:true,renderer:ui.cmp._PortletTranslator.staleRenderer,dataIndex:"stale",summaryType:"sum"},{header:_("Sum"),width:50,sortable:true,renderer:ui.cmp._PortletTranslator.sumRenderer,dataIndex:"sum",summaryType:"sum"}];ui.cmp._PortletReviewer.gridColumns=[new Ext.grid.RowNumberer(),{id:"GridTransName",header:_("Name"),sortable:true,dataIndex:"name",summaryType:"count",summaryRenderer:ui.cmp._PortletReviewer.translatorSumRenderer},{header:_("Email"),width:110,sortable:true,dataIndex:"email"},{header:_("Nick"),width:70,sortable:true,dataIndex:"nick"},{header:_("VCS"),width:45,sortable:true,dataIndex:"vcs"},{header:_("Reviewed"),width:60,sortable:true,renderer:ui.cmp._PortletReviewer.uptodateRenderer,dataIndex:"reviewedUptodate",summaryType:"sum"},{header:_("Must be reviewed"),width:90,sortable:true,renderer:ui.cmp._PortletReviewer.staleRenderer,dataIndex:"reviewedStale",summaryType:"sum"},{header:_("Sum"),width:50,sortable:true,renderer:ui.cmp._PortletReviewer.sumRenderer,dataIndex:"reviewedSum",summaryType:"sum"}];ui.cmp._PortletTranslator.grid=Ext.extend(Ext.grid.GridPanel,{title:_("Translators"),loadMask:true,autoScroll:true,autoHeight:true,plugins:[new Ext.ux.grid.GridSummary()],store:ui.cmp._PortletTranslator.store,columns:ui.cmp._PortletTranslator.gridColumns,autoExpandColumn:"GridTransName",sm:new Ext.grid.RowSelectionModel({singleSelect:true}),lang:this.lang,EmailPrompt:new ui.cmp.EmailPrompt(),onRowDblClick:function(d,e){this.getSelectionModel().selectRow(e);if(this.ctxTranslatorName){this.ctxTranslatorEmail=null;this.ctxTranslatorName=null}this.ctxTranslatorEmail=this.store.getAt(e).data.email;this.ctxTranslatorName=this.store.getAt(e).data.name;var c=this.store.getAt(e).data.nick;if(c==="nobody"){return}this.EmailPrompt.setData(this.ctxTranslatorName,this.ctxTranslatorEmail);this.EmailPrompt.show("lastUpdateTime")},onContextClick:function(d,g,f){if(!this.menu){this.menu=new Ext.menu.Menu({id:"submenu-translators",items:[{scope:this,text:"",iconCls:"iconSendEmail",handler:function(){this.EmailPrompt.setData(this.ctxTranslatorName,this.ctxTranslatorEmail);this.EmailPrompt.show("lastUpdateTime")}},"-",{scope:this,text:String.format(_("Send an email to the {0}"),String.format(PhDOE.app.conf.projectMailList,this.lang)),iconCls:"iconSendEmail",handler:function(){this.EmailPrompt.setData("Php Doc Team "+this.lang,String.format(PhDOE.app.conf.projectMailList,this.lang));this.EmailPrompt.show("lastUpdateTime")}}]})}this.getSelectionModel().selectRow(g);f.stopEvent();if(this.ctxTranslatorName){this.ctxTranslatorName=null;this.ctxTranslatorEmail=null}this.ctxTranslatorName=this.store.getAt(g).data.name;this.ctxTranslatorEmail=this.store.getAt(g).data.email;var c=this.store.getAt(g).data.nick;if(c==="nobody"){return}this.menu.items.items[0].setText(""+String.format(_("Send an email to {0}"),this.ctxTranslatorName)+"");this.menu.showAt(f.getXY())},initComponent:function(c){ui.cmp._PortletTranslator.grid.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowcontextmenu",this.onContextClick,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp._PortletReviewer.grid=Ext.extend(Ext.grid.GridPanel,{title:_("Reviewers"),loadMask:true,autoScroll:true,autoHeight:true,plugins:[new Ext.ux.grid.GridSummary()],store:ui.cmp._PortletReviewer.store,columns:ui.cmp._PortletReviewer.gridColumns,autoExpandColumn:"GridTransName",sm:new Ext.grid.RowSelectionModel({singleSelect:true}),lang:this.lang,EmailPrompt:new ui.cmp.EmailPrompt(),onRowDblClick:function(d,e){this.getSelectionModel().selectRow(e);if(this.ctxTranslatorName){this.ctxTranslatorEmail=null;this.ctxTranslatorName=null}this.ctxTranslatorEmail=this.store.getAt(e).data.email;this.ctxTranslatorName=this.store.getAt(e).data.name;var c=this.store.getAt(e).data.nick;if(c==="nobody"){return}this.EmailPrompt.setData(this.ctxTranslatorName,this.ctxTranslatorEmail);this.EmailPrompt.show("lastUpdateTime")},onContextClick:function(d,g,f){if(!this.menu){this.menu=new Ext.menu.Menu({id:"submenu-translators",items:[{scope:this,text:"",iconCls:"iconSendEmail",handler:function(){this.EmailPrompt.setData(this.ctxTranslatorName,this.ctxTranslatorEmail);this.EmailPrompt.show("lastUpdateTime")}},"-",{scope:this,text:String.format(_("Send an email to the {0}"),String.format(PhDOE.app.conf.projectMailList,this.lang)),iconCls:"iconSendEmail",handler:function(){this.EmailPrompt.setData("Php Doc Team "+this.lang,String.format(PhDOE.app.conf.projectMailList,this.lang));this.EmailPrompt.show("lastUpdateTime")}}]})}this.getSelectionModel().selectRow(g);f.stopEvent();if(this.ctxTranslatorName){this.ctxTranslatorName=null;this.ctxTranslatorEmail=null}this.ctxTranslatorName=this.store.getAt(g).data.name;this.ctxTranslatorEmail=this.store.getAt(g).data.email;var c=this.store.getAt(g).data.nick;if(c==="nobody"){return}this.menu.items.items[0].setText(""+String.format(_("Send an email to {0}"),this.ctxTranslatorName)+"");this.menu.showAt(f.getXY())},initComponent:function(c){ui.cmp._PortletReviewer.grid.superclass.initComponent.call(this);Ext.apply(this,c);this.on("rowcontextmenu",this.onContextClick,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp.PortletTranslator=Ext.extend(Ext.ux.Portlet,{title:_("Translators & Reviewer"),iconCls:"iconTranslator",layout:"fit",storeTranslator:ui.cmp._PortletTranslator.store,storeReviewer:ui.cmp._PortletReviewer.store,tools:[{id:"refresh",qtip:_("Refresh this grid"),handler:function(){ui.cmp._PortletTranslator.store.reload({callback:function(){ui.cmp._PortletReviewer.store.reload()}})}}],listeners:{expand:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletTranslatorCollapsed",value:false,notify:false})}},collapse:function(){if(PhDOE.app.loaded){new ui.task.UpdateConfTask({item:"portletTranslatorCollapsed",value:true,notify:false})}},afterrender:function(c){if(PhDOE.user.conf.portletTranslatorCollapsed){c.collapse()}else{c.expand()}}},initComponent:function(c){this.id="portletTranslator";Ext.apply(this,c);ui.cmp.PortletTranslator.superclass.initComponent.apply(this);this.add({xtype:"tabpanel",activeTab:0,border:false,height:200,tabPosition:"bottom",autoScroll:true,items:[new ui.cmp._PortletTranslator.grid({lang:this.lang}),new ui.cmp._PortletReviewer.grid({lang:this.lang})]})}});ui.cmp._PortletTranslator.instance=null;ui.cmp.PortletTranslator.getInstance=function(c){if(!ui.cmp._PortletTranslator.instance){if(!c){c={}}ui.cmp._PortletTranslator.instance=new ui.cmp.PortletTranslator(c)}return ui.cmp._PortletTranslator.instance};Ext.namespace("ui","ui.cmp");ui.cmp.PreviewFile=Ext.extend(Ext.Window,{id:"winPreviewFile",layout:"fit",title:_("Preview"),iconCls:"iconView",closable:true,closeAction:"close",maximized:true,modal:true,buttons:[{text:_("Close"),handler:function(){this.ownerCt.ownerCt.close()}}],initComponent:function(){var c=this;ui.cmp.PreviewFile.superclass.initComponent.call(this);XHR({params:{task:"previewFile",path:this.path},success:function(d){var f=Ext.util.JSON.decode(d.responseText),e;f.url=f.url+"?"+Math.random();e=new Ext.ux.IFrameComponent({id:"frame-previewFile",url:f.url});c.add(e);c.show()},failure:function(){}})}});Ext.namespace("ui","ui.cmp","ui.cmp._RepositoryTree");ui.cmp._RepositoryTree.root={nodeType:"async",id:"/",text:_("Repository"),draggable:false};ui.cmp._RepositoryTree.loader=new Ext.tree.TreeLoader({dataUrl:"./do/getAllFiles"});ui.cmp._RepositoryTree.winAddNewFile=Ext.extend(Ext.Window,{title:_("Add a new file"),iconCls:"iconFilesNeedTranslate",id:"win-add-new-file",layout:"form",width:350,height:170,resizable:false,modal:true,bodyStyle:"padding:5px 5px 0",labelWidth:150,buttons:[{id:"win-add-new-file-btn",text:_("Open the editor"),disabled:true,handler:function(){var d=Ext.getCmp("win-add-new-file"),f=d.node.id,c=d.items.items[1].getValue(),e=d.items.items[2].getValue();if(d.node.findChild("id",f+"/"+c)){PhDOE.winForbidden("file_already_exist");return true}d.openFile(f+"/",c,e);d.close();return true}}],openFile:function(e,c,j){var h=Ext.util.md5("FNT-"+e+c),g={data:{fileModified:false,node:this.node}},d=e.split("/"),f;d.shift();f=d[0];d.shift();d.pop();e="/"+d.join("/")+"/";if(e==="//"){e="/"}h=Ext.util.md5("FNT-"+e+c);if(!Ext.getCmp("main-panel").findById("FNT-"+h)){Ext.getCmp("main-panel").add({id:"FNT-"+h,layout:"border",title:c,originTitle:c,iconCls:"iconTabNeedTranslate",closable:true,tabLoaded:false,panTRANSLoaded:false,panGGTRANSLoaded:true,defaults:{split:true},tabTip:String.format(_("New file: in {0}"),f+e),items:[new ui.cmp.FilePanel({id:"FNT-NEW-PANEL-"+h,region:"center",title:_("New file: ")+f+e+c,isTrans:true,prefix:"FNT",ftype:"NEW",fid:h,fpath:e,fname:c,lang:f,parser:"xml",storeRecord:g,syncScrollCB:false,syncScroll:false,skeleton:j})]})}Ext.getCmp("main-panel").setActiveTab("FNT-"+h)},initComponent:function(){Ext.apply(this,{items:[{xtype:"displayfield",fieldLabel:_("Parent Folder"),value:this.node.id},{xtype:"textfield",fieldLabel:_("Name for the new file"),name:"newFolderName",listeners:{valid:function(){Ext.getCmp("win-add-new-file-btn").enable()},invalid:function(){Ext.getCmp("win-add-new-file-btn").disable()}}},{xtype:"combo",triggerAction:"all",width:160,editable:false,store:new Ext.data.Store({proxy:new Ext.data.HttpProxy({url:"./do/getSkeletonsNames"}),reader:new Ext.data.JsonReader({root:"Items",idProperty:"name",fields:[{name:"name"},{name:"path"}]})}),listeners:{select:function(f,d,e){if(f.ownerCt.items.items[1].getValue()===""){f.ownerCt.items.items[1].setValue(d.data.name)}}},valueField:"path",displayField:"name",fieldLabel:_("Chose a skeleton")}]});ui.cmp._RepositoryTree.winAddNewFile.superclass.initComponent.call(this)}});ui.cmp._RepositoryTree.winAddNewFolder=Ext.extend(Ext.Window,{title:_("Add a new folder"),iconCls:"iconFolderNew",id:"win-add-new-folder",layout:"form",width:350,height:200,resizable:false,modal:true,bodyStyle:"padding:5px 5px 0",labelWidth:150,buttons:[{id:"win-add-new-folder-btn",text:"Add",disabled:true,handler:function(){var c=Ext.getCmp("win-add-new-folder"),e=c.node.id,d=c.items.items[1].getValue();XHR({params:{task:"addNewFolder",parentFolder:e,newFolderName:d},success:function(){Ext.getCmp("win-add-new-folder").close();c.node.reload();PhDOE.notify("info",_("Folder created"),String.format(_("Folder

{0}

was created sucessfully under {1} !"),d,e))},failure:function(f){var g=Ext.util.JSON.decode(f.responseText);if(g.type){PhDOE.winForbidden(g.type)}else{PhDOE.winForbidden()}}})}}],initComponent:function(){Ext.apply(this,{items:[{xtype:"displayfield",fieldLabel:_("Parent Folder"),value:this.node.id},{xtype:"textfield",fieldLabel:_("Name for the new folder"),name:"newFolderName",vtype:"alphanum",listeners:{valid:function(){Ext.getCmp("win-add-new-folder-btn").enable()},invalid:function(){Ext.getCmp("win-add-new-folder-btn").disable()}}},{xtype:"box",html:_("Info: This new folder won't be commited until a new file will be commited into it. If you don't commit any new file into it until 8 days, it will be automatically deleted.")}]});ui.cmp._RepositoryTree.winAddNewFolder.superclass.initComponent.call(this)}});Ext.namespace("ui.cmp._RepositoryTree.menu");ui.cmp._RepositoryTree.menu.folder=function(c){Ext.apply(this,c);this.init();ui.cmp._RepositoryTree.menu.folder.superclass.constructor.call(this)};Ext.extend(ui.cmp._RepositoryTree.menu.folder,Ext.menu.Menu,{init:function(){Ext.apply(this,{items:[{text:(this.node.isExpanded())?""+_("Collapse")+"":""+_("Expand")+"",iconCls:"iconFolderClose",scope:this,handler:function(){if(this.node.isExpanded()){this.node.collapse()}else{this.node.expand()}}},"-",{text:_("Add a new folder"),iconCls:"iconFolderNew",hidden:(this.node.id==="/"||(Ext.util.Format.substr(this.node.id,0,3)!=="/en"&&Ext.util.Format.substr(this.node.id,0,9)!=="/doc-base")),scope:this,handler:function(){this.node.expand();var c=new ui.cmp._RepositoryTree.winAddNewFolder({node:this.node});c.show(this.node.ui.getEl())}},{text:_("Add a new file"),iconCls:"iconFilesNeedTranslate",hidden:(this.node.id==="/"||(Ext.util.Format.substr(this.node.id,0,3)!=="/en"&&Ext.util.Format.substr(this.node.id,0,9)!=="/doc-base")),scope:this,handler:function(){this.node.expand();var c=new ui.cmp._RepositoryTree.winAddNewFile({node:this.node});c.show(this.node.ui.getEl())}}]})}});ui.cmp._RepositoryTree.menu.file=function(c){Ext.apply(this,c);this.init();ui.cmp._RepositoryTree.menu.file.superclass.constructor.call(this)};Ext.extend(ui.cmp._RepositoryTree.menu.file,Ext.menu.Menu,{init:function(){var c=this.node.attributes.text,d=this.node.attributes.id.split("/"),f,e;d.shift();f=d[0];d.shift();d.pop();e=d.join("/")+"/";Ext.apply(this,{items:[{text:""+_("Edit in a new tab")+"",iconCls:"iconTabNeedReviewed",scope:this,handler:function(){ui.cmp._RepositoryTree.instance.fireEvent("dblclick",this.node)}},{hidden:(this.node.attributes.from==="search"||PhDOE.user.lang==="en"),text:(f==="en")?String.format(_("Open the same file in {0}"),Ext.util.Format.uppercase(PhDOE.user.lang)):String.format(_("Open the same file in {0}"),"EN"),iconCls:"iconTabNeedReviewed",scope:this,handler:function(){if(f==="en"){ui.cmp._RepositoryTree.instance.openFile("byPath",PhDOE.user.lang+"/"+e,c)}else{ui.cmp._RepositoryTree.instance.openFile("byPath","en/"+e,c)}}}]})}});ui.cmp.RepositoryTree=Ext.extend(Ext.ux.MultiSelectTreePanel,{animate:true,enableDD:true,ddGroup:"mainPanelDDGroup",useArrows:true,autoScroll:true,border:false,containerScroll:true,root:ui.cmp._RepositoryTree.root,loader:ui.cmp._RepositoryTree.loader,onContextMenu:function(c,d){d.stopEvent();c.select();if(c.attributes.type==="folder"||c.isRoot){new ui.cmp._RepositoryTree.menu.folder({node:c}).showAt(d.getXY())}else{if(c.attributes.type==="file"){new ui.cmp._RepositoryTree.menu.file({node:c}).showAt(d.getXY())}}},onDblClick:function(c){if(c.attributes.type==="file"){this.openFile("byId",c.attributes.id,false)}},openFile:function(r,m,g){if(r==="byPath"){Ext.getCmp("acc-all-files").expand();var f=m,j=g,u=f.split("/"),l=function(w){w.ensureVisible();if(u[0]&&u[0]!==""){for(var t=0;t0)?"/"+u.join("/")+"/":"/";p=Ext.util.md5("AF-"+h+c+e);if(!Ext.getCmp("main-panel").findById("AF-"+p)){if(s!=="html"){d=s}else{d="xml"}if(s==="gif"||s==="png"||s==="jpg"){o={};q={id:"AF-ALL-FILE-"+p,xtype:"panel",region:"center",layout:"fit",bodyStyle:"padding:5px 5px 0",html:''}}else{o={xtype:"panel",region:"west",title:_("Tools"),iconCls:"iconConf",collapsedIconCls:"iconConf",plugins:[Ext.ux.PanelCollapsedTitle],layout:"fit",bodyBorder:false,split:true,collapsible:true,collapsed:!PhDOE.user.conf.allFiles.toolsPanelDisplay,width:PhDOE.user.conf.allFiles.toolsPanelWidth||375,listeners:{collapse:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"allFiles",itemName:"toolsPanelDisplay",value:false,notify:false})}},expand:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"allFiles",itemName:"toolsPanelDisplay",value:true,notify:false})}},resize:function(t,v){if(this.ownerCt.tabLoaded&&v&&v!=PhDOE.user.conf.allFiles.toolsPanelWidth){new ui.task.UpdateConfTask({module:"allFiles",itemName:"toolsPanelWidth",value:v,notify:false})}}},items:{xtype:"tabpanel",activeTab:0,defaults:{autoScroll:true},items:[{title:_("Log"),layout:"fit",items:[new ui.cmp.VCSLogGrid({prefix:"AF",fid:p,fpath:h+c,fname:e,loadStore:PhDOE.user.conf.allFiles.toolsPanelLogLoad})]},{title:_("Entities"),layout:"fit",items:[new ui.cmp.EntitiesAcronymsPanel({dataType:"entities",prefix:"AF",ftype:"ALL",fid:p,loadStore:PhDOE.user.conf.allFiles.toolsPanelEntitiesLoad})]},{title:_("Acronyms"),layout:"fit",items:[new ui.cmp.EntitiesAcronymsPanel({dataType:"acronyms",prefix:"AF",ftype:"ALL",fid:p,loadStore:PhDOE.user.conf.allFiles.toolsPanelAcronymsLoad})]}]}};q=new ui.cmp.FilePanel({id:"AF-ALL-PANEL-"+p,region:"center",title:_("File: ")+h+c+e,prefix:"AF",ftype:"ALL",spellCheck:PhDOE.user.conf.allFiles.enableSpellCheck,spellCheckConf:{module:"allFiles",itemName:"enableSpellCheck"},fid:p,fpath:c,fname:e,lang:h,parser:d,storeRecord:k,syncScrollCB:false,syncScroll:false})}Ext.getCmp("main-panel").add({id:"AF-"+p,layout:"border",title:e,originTitle:e,closable:true,tabLoaded:false,panEntities:!PhDOE.user.conf.allFiles.toolsPanelEntitiesLoad,panAcronyms:!PhDOE.user.conf.allFiles.toolsPanelAcronymsLoad,panVCS:!PhDOE.user.conf.allFiles.toolsPanelLogLoad,panLoaded:false,tabTip:String.format(_("in {0}"),c),iconCls:"iconAllFiles",items:[q,o]})}Ext.getCmp("main-panel").setActiveTab("AF-"+p)}},initComponent:function(){Ext.apply(this,{tbar:[_("Search: ")," ",new Ext.form.TwinTriggerField({id:"AF-search",validationEvent:false,validateOnBlur:false,trigger1Class:"x-form-clear-trigger",trigger2Class:"x-form-search-trigger",hideTrigger1:true,width:180,enableKeyEvents:true,listeners:{keypress:function(d,c){if(c.getKey()===c.ENTER){this.onTrigger2Click()}}},onTrigger1Click:function(){var c=ui.cmp._RepositoryTree.instance;this.setValue("");this.triggers[0].hide();this.setSize(180,10);c.root.setText(_("Repository"));delete c.loader.baseParams.search;c.root.reload()},onTrigger2Click:function(){var c=ui.cmp._RepositoryTree.instance,d=this.getValue();if(d===""||d.length<3){this.markInvalid(_("Your search must contain at least 3 characters"));return}this.clearInvalid();this.triggers[0].show();this.setSize(180,10);c.loader.baseParams.search=d;c.root.reload(function(){c.root.setText(String.format(_("Search result: {0}"),c.root.childNodes.length))})}})]});ui.cmp.RepositoryTree.superclass.initComponent.call(this);this.on("contextmenu",this.onContextMenu,this);this.on("dblclick",this.onDblClick,this);new Ext.tree.TreeSorter(this,{folderSort:true})}});ui.cmp._RepositoryTree.instance=null;ui.cmp.RepositoryTree.getInstance=function(c){if(!ui.cmp._RepositoryTree.instance){if(!c){c={}}ui.cmp._RepositoryTree.instance=new ui.cmp.RepositoryTree(c)}return ui.cmp._RepositoryTree.instance};Ext.namespace("ui","ui.cmp","ui.cmp._StaleFileGrid");ui.cmp._StaleFileGrid.store=new Ext.data.GroupingStore({proxy:new Ext.data.HttpProxy({url:"./do/getFilesNeedUpdate"}),reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"path"},{name:"name"},{name:"revision"},{name:"original_revision"},{name:"en_revision"},{name:"maintainer"},{name:"fileModifiedEN"},{name:"fileModifiedLang"}]}),sortInfo:{field:"name",direction:"ASC"},groupField:"path",listeners:{datachanged:function(e){var c=e.getCount(),d=false;if(!PhDOE.user.isAnonymous){e.each(function(f){if(f.data.maintainer==PhDOE.user.login){d++}},this)}if(d){Ext.getDom("acc-need-update-nb").innerHTML=c+" - "+String.format(_("{0} mine"),d)}else{Ext.getDom("acc-need-update-nb").innerHTML=c}}}});ui.cmp._StaleFileGrid.view=new Ext.grid.GroupingView({forceFit:true,startCollapsed:true,groupTextTpl:'{[values.rs[0].data["path"]]} ({[values.rs.length]} {[values.rs.length > 1 ? "'+_("Files")+'" : "'+_("File")+'"]})',deferEmptyText:false,getRowClass:function(c){if(c.data.fileModifiedEN||c.data.fileModifiedLang){var e=Ext.util.JSON.decode(c.data.fileModifiedEN),d=Ext.util.JSON.decode(c.data.fileModifiedLang);return((e.user===PhDOE.user.login&&e.anonymousIdent===PhDOE.user.anonymousIdent)||(d.user===PhDOE.user.login&&d.anonymousIdent===PhDOE.user.anonymousIdent))?"fileModifiedByMe":"fileModifiedByAnother"}return false},emptyText:'
'+_("No Files")+"
"});ui.cmp._StaleFileGrid.columns=[{id:"name",header:_("Files"),sortable:true,dataIndex:"name",renderer:function(c,f,d){var h="",g,e;if(d.data.fileModifiedEN){g=Ext.util.JSON.decode(d.data.fileModifiedEN);if(g.user===PhDOE.user.login&&g.anonymousIdent===PhDOE.user.anonymousIdent){h=_("File EN modified by me")+"
"}else{h=String.format(_("File EN modified by {0}"),g.user)+"
"}}if(d.data.fileModifiedLang){e=Ext.util.JSON.decode(d.data.fileModifiedLang);if(e.user===PhDOE.user.login&&e.anonymousIdent===PhDOE.user.anonymousIdent){h+=String.format(_("File {0} modified by me"),PhDOE.user.lang.ucFirst())}else{h+=String.format(_("File {0} modified by {1}"),PhDOE.user.lang.ucFirst(),e.user)}}if(h!==""){return""+c+""}else{return c}}},{header:_("EN revision"),width:45,sortable:true,dataIndex:"en_revision"},{header:"",width:45,sortable:true,dataIndex:"revision"},{header:_("Maintainer"),width:45,sortable:true,dataIndex:"maintainer"},{header:_("Path"),dataIndex:"path",hidden:true}];ui.cmp._StaleFileGrid.menu=function(c){Ext.apply(this,c);this.init();ui.cmp._StaleFileGrid.menu.superclass.constructor.call(this)};Ext.extend(ui.cmp._StaleFileGrid.menu,Ext.menu.Menu,{init:function(){Ext.apply(this,{items:[{scope:this,text:""+_("Edit in a new tab")+"",iconCls:"iconTabNeedUpdate",handler:function(){this.grid.fireEvent("rowdblclick",this.grid,this.rowIdx,this.event)}},{scope:this,hidden:this.hideDiffMenu,text:_("View diff..."),iconCls:"iconViewDiff",menu:new Ext.menu.Menu({items:[{scope:this,hidden:(this.grid.store.getAt(this.rowIdx).data.fileModifiedEN===false),text:String.format(_("... of the {0} file"),"EN"),handler:function(){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",FileName:this.fname,FilePath:"en"+this.fpath})}},{scope:this,hidden:(this.grid.store.getAt(this.rowIdx).data.fileModifiedLang===false),text:String.format(_("... of the {0} file"),PhDOE.user.lang.ucFirst()),handler:function(){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",FileName:this.fname,FilePath:PhDOE.user.lang+this.fpath})}}]})}]})}});ui.cmp.StaleFileGrid=Ext.extend(Ext.grid.GridPanel,{view:ui.cmp._StaleFileGrid.view,loadMask:true,autoExpandColumn:"name",border:false,enableDragDrop:true,ddGroup:"mainPanelDDGroup",onRowContextMenu:function(d,j,h){h.stopEvent();var g=this.store.getAt(j).data,f=g.path,c=g.name;this.getSelectionModel().selectRow(j);new ui.cmp._StaleFileGrid.menu({hideDiffMenu:(g.fileModifiedEN===false&&g.fileModifiedLang===false),grid:this,event:h,rowIdx:j,lang:PhDOE.user.lang,fpath:f,fname:c}).showAt(h.getXY())},onRowDblClick:function(c,d){this.openFile(this.store.getAt(d).data.id)},openFile:function(e){var g=this.store.getById(e),c=g.data.path,d=g.data.name,j=g.data.en_revision,h=g.data.revision,l=g.data.original_revision,f=Ext.util.md5("FNU-"+PhDOE.user.lang+c+d),k="";if(!Ext.getCmp("main-panel").findById("FNU-"+f)){if(PhDOE.user.conf.needUpdate.diffMethod==="using-viewvc"){k=ui.cmp.ViewVCDiff}else{if(PhDOE.user.conf.needUpdate.diffMethod==="using-exec"){k=ui.cmp.ExecDiff}}Ext.getCmp("main-panel").add({id:"FNU-"+f,layout:"border",title:d,originTitle:d,iconCls:"iconTabNeedUpdate",closable:true,tabLoaded:false,panVCSLang:!PhDOE.user.conf.needUpdate.toolsPanelLogLoad,panVCSEn:!PhDOE.user.conf.needUpdate.toolsPanelLogLoad,panDiffLoaded:(PhDOE.user.conf.needUpdate.diffMethod==="using-viewvc"),panLANGLoaded:false,panENLoaded:false,defaults:{split:true},tabTip:String.format(_("Need Update: in {0}"),c),listeners:{resize:function(m){Ext.getCmp("FNU-EN-PANEL-"+f).setWidth(m.getWidth()/2)}},items:[new k({region:"north",collapsible:true,height:PhDOE.user.conf.needUpdate.diffPanelHeight||150,prefix:"FNU",collapsed:!PhDOE.user.conf.needUpdate.diffPanelDisplay,fid:f,fpath:c,fname:d,rev1:(l)?l:h,rev2:j,listeners:{collapse:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"diffPanelDisplay",value:false,notify:false})}},expand:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"diffPanelDisplay",value:true,notify:false})}},resize:function(p,m,o){if(this.ownerCt.tabLoaded&&o&&o>50&&o!=PhDOE.user.conf.needUpdate.diffPanelHeight){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"diffPanelHeight",value:o,notify:false})}}}}),{region:"west",xtype:"panel",title:_("Tools"),iconCls:"iconConf",collapsedIconCls:"iconConf",collapsible:true,collapsed:!PhDOE.user.conf.needUpdate.toolsPanelDisplay,layout:"fit",bodyBorder:false,plugins:[Ext.ux.PanelCollapsedTitle],width:PhDOE.user.conf.needUpdate.toolsPanelWidth||375,listeners:{collapse:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"toolsPanelDisplay",value:false,notify:false})}},expand:function(){if(this.ownerCt.tabLoaded){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"toolsPanelDisplay",value:true,notify:false})}},resize:function(m,o){if(this.ownerCt.tabLoaded&&o&&o!=PhDOE.user.conf.needUpdate.toolsPanelWidth){new ui.task.UpdateConfTask({module:"needUpdate",itemName:"toolsPanelWidth",value:o,notify:false})}}},items:{xtype:"tabpanel",activeTab:0,tabPosition:"bottom",enableTabScroll:true,defaults:{autoScroll:true},items:[new ui.cmp.VCSLogGrid({layout:"fit",title:String.format(_("{0} Log"),PhDOE.user.lang.ucFirst()),prefix:"FNU-LANG",fid:f,fpath:PhDOE.user.lang+c,fname:d,loadStore:PhDOE.user.conf.needUpdate.toolsPanelLogLoad}),new ui.cmp.VCSLogGrid({layout:"fit",title:String.format(_("{0} Log"),"En"),prefix:"FNU-EN",fid:f,fpath:"en"+c,fname:d,loadStore:PhDOE.user.conf.needUpdate.toolsPanelLogLoad}),new ui.cmp.DictionaryGrid({layout:"fit",title:_("Dictionary"),prefix:"FNU",fid:f})]}},new ui.cmp.FilePanel({id:"FNU-LANG-PANEL-"+f,region:"center",title:String.format(_("{0} File: "),PhDOE.user.lang)+c+d,prefix:"FNU",ftype:"LANG",spellCheck:PhDOE.user.conf.needUpdate.enableSpellCheckLang,spellCheckConf:{module:"needUpdate",itemName:"enableSpellCheckLang"},fid:f,fpath:c,fname:d,lang:PhDOE.user.lang,parser:"xml",storeRecord:g,syncScrollCB:true,syncScroll:true,syncScrollConf:{module:"needUpdate",itemName:"syncScrollbars"}}),new ui.cmp.FilePanel({id:"FNU-EN-PANEL-"+f,region:"east",title:_("en File: ")+c+d,prefix:"FNU",ftype:"EN",original:true,readOnly:true,openInNewTabBtn:true,fid:f,fpath:c,fname:d,lang:"en",parser:"xml",storeRecord:g,syncScroll:true,syncScrollConf:{module:"needUpdate",itemName:"syncScrollbars"}})]})}Ext.getCmp("main-panel").setActiveTab("FNU-"+f)},initComponent:function(){ui.cmp._StaleFileGrid.columns[2].header=String.format(_("{0} revision"),Ext.util.Format.uppercase(PhDOE.user.lang));Ext.apply(this,{columns:ui.cmp._StaleFileGrid.columns,store:ui.cmp._StaleFileGrid.store,tbar:[_("Filter: ")," ",new Ext.form.TwinTriggerField({id:"FNU-filter",width:180,hideTrigger1:true,enableKeyEvents:true,validateOnBlur:false,validationEvent:false,trigger1Class:"x-form-clear-trigger",trigger2Class:"x-form-search-trigger",listeners:{specialkey:function(d,c){if(c.getKey()===c.ENTER){this.onTrigger2Click()}}},onTrigger1Click:function(){this.setValue("");this.triggers[0].hide();this.setSize(180,10);ui.cmp._StaleFileGrid.instance.store.clearFilter()},onTrigger2Click:function(){var c=this.getValue(),d;if(c===""||c.length<3){this.markInvalid(_("Your filter must contain at least 3 characters"));return}this.clearInvalid();this.triggers[0].show();this.setSize(180,10);d=new RegExp(c,"i");ui.cmp._StaleFileGrid.instance.store.filterBy(function(e){if(d.test(e.data.path)||d.test(e.data.name)||d.test(e.data.revision)||d.test(e.data.en_revision)||d.test(e.data.maintainer)){return true}else{return false}},this)}})]});ui.cmp.StaleFileGrid.superclass.initComponent.call(this);this.on("rowcontextmenu",this.onRowContextMenu,this);this.on("rowdblclick",this.onRowDblClick,this)}});ui.cmp._StaleFileGrid.instance=null;ui.cmp.StaleFileGrid.getInstance=function(c){if(!ui.cmp._StaleFileGrid.instance){if(!c){c={}}ui.cmp._StaleFileGrid.instance=new ui.cmp.StaleFileGrid(c)}return ui.cmp._StaleFileGrid.instance};Ext.namespace("ui","ui.cmp");ui.cmp.SystemUpdatePrompt=Ext.extend(Ext.Window,{id:"sys-update-win",title:_("Refresh all data"),layout:"form",width:300,height:200,resizable:false,modal:true,bodyStyle:"padding:15px 15px 0",iconCls:"iconRefresh",html:['
',_("Update all files from VCS"),"
",'
',_("This may take time. Thank you for your patience..."),"
",'
',_("Apply all tools"),"
",'
',_("Reload data"),"
"].join(""),buttons:[{id:"btn-start-refresh",text:_("Start"),iconCls:"iconStartRefresh",handler:function(){Ext.getCmp("btn-start-refresh").disable();this.ownerCt.ownerCt.tools.close.setVisible(false);new ui.task.SystemUpdateTask()}}]});Ext.namespace("ui","ui.cmp","ui.cmp._VCSLogGrid");ui.cmp._VCSLogGrid.store=Ext.extend(Ext.data.Store,{reader:new Ext.data.JsonReader({root:"Items",totalProperty:"nbItems",idProperty:"id",fields:[{name:"id"},{name:"revision"},{name:"date",type:"date",dateFormat:"Y/m/d H:i:s"},{name:"author"},{name:"content"}]})});ui.cmp._VCSLogGrid.sm=Ext.extend(Ext.grid.CheckboxSelectionModel,{singleSelect:false,header:"",width:22,listeners:{beforerowselect:function(d){var c=d.getCount();if(c===2){return false}return true},rowselect:function(d){var c=d.getCount();if(c===2){Ext.getCmp(d.prefix+"-PANEL-btn-log-"+d.fid).enable();Ext.get(d.prefix+"-PANEL-btn-log-"+d.fid).frame("3F8538")}else{Ext.getCmp(d.prefix+"-PANEL-btn-log-"+d.fid).disable()}},rowdeselect:function(d){var c=d.getCount();if(c===2){Ext.getCmp(d.prefix+"-PANEL-btn-log-"+d.fid).enable();Ext.get(d.prefix+"-PANEL-btn-log-"+d.fid).frame("3F8538")}else{Ext.getCmp(d.prefix+"-PANEL-btn-log-"+d.fid).disable()}}}});ui.cmp._VCSLogGrid.columns=[{id:"id",header:_("Rev."),width:40,sortable:false,dataIndex:"revision"},{header:_("Content"),width:130,sortable:true,dataIndex:"content"},{header:_("By"),width:50,sortable:true,dataIndex:"author"},{header:_("Date"),width:85,sortable:true,dataIndex:"date",renderer:Ext.util.Format.dateRenderer(_("Y-m-d, H:i"))}];ui.cmp.VCSLogGrid=Ext.extend(Ext.grid.GridPanel,{loadMask:true,autoScroll:true,bodyBorder:false,border:false,autoExpandColumn:"content",initComponent:function(){var f=new ui.cmp._VCSLogGrid.sm({fid:this.fid,prefix:this.prefix}),c=new ui.cmp._VCSLogGrid.store({autoLoad:this.loadStore,proxy:new Ext.data.HttpProxy({url:"./do/getLog"}),baseParams:{Path:this.fpath,File:this.fname},listeners:{scope:this,load:function(h,g){if(this.prefix==="FNU-EN"){Ext.getCmp("FNU-"+this.fid).panVCSEn=true;Ext.getCmp("main-panel").fireEvent("tabLoaded","FNU",this.fid)}if(this.prefix==="FNU-LANG"){Ext.getCmp("FNU-"+this.fid).panVCSLang=true;Ext.getCmp("main-panel").fireEvent("tabLoaded","FNU",this.fid)}if(this.prefix==="FE-EN"){Ext.getCmp("FE-"+this.fid).panVCSEn=true;Ext.getCmp("main-panel").fireEvent("tabLoaded","FE",this.fid)}if(this.prefix==="FE-LANG"){Ext.getCmp("FE-"+this.fid).panVCSLang=true;Ext.getCmp("main-panel").fireEvent("tabLoaded","FE",this.fid)}if(this.prefix==="FNR-EN"){Ext.getCmp("FNR-"+this.fid).panVCSEn=true;Ext.getCmp("main-panel").fireEvent("tabLoaded","FNR",this.fid)}if(this.prefix==="FNR-LANG"){Ext.getCmp("FNR-"+this.fid).panVCSLang=true;Ext.getCmp("main-panel").fireEvent("tabLoaded","FNR",this.fid)}if(this.prefix==="AF"){Ext.getCmp("AF-"+this.fid).panVCS=true;Ext.getCmp("main-panel").fireEvent("tabLoaded","AF",this.fid)}if(this.prefix==="PP"){Ext.getCmp("PP-"+this.fid).panVCS=true;Ext.getCmp("main-panel").fireEvent("tabLoaded","PP",this.fid)}}}}),e=[],d;e.push(f);for(d=0;d'+_("You must manually load this data.
Use the refresh button !")+"

"+_("(You can change this behavior by setting an option in the configuration window)")+"",deferEmptyText:false}),tbar:[{scope:this,id:this.prefix+"-PANEL-btn-refreshlog-"+this.fid,tooltip:_("Load/Refresh revisions"),iconCls:"iconRefresh",handler:function(){this.store.reload()}},{scope:this,id:this.prefix+"-PANEL-btn-log-"+this.fid,tooltip:_("View the diff"),iconCls:"iconViewDiff",disabled:true,handler:function(){var j=this.getSelectionModel().getSelections(),h=j[0].data.revision,g=j[1].data.revision;Ext.getBody().mask(' '+_("Finding the diff. Please, wait..."));XHR({params:{task:"getDiff",DiffType:"vcs",FilePath:this.fpath,FileName:this.fname,Rev1:h,Rev2:g},success:function(l){var m=Ext.util.JSON.decode(l.responseText),k;Ext.getBody().unmask();k=new Ext.Window({title:String.format(_("Diff between {0} & {1}"),h,g),width:650,height:350,resizable:false,modal:true,autoScroll:true,bodyStyle:"background-color: white; padding: 5px;",html:'
'+m.content+"
",buttons:[{text:_("Close"),handler:function(){k.close()}}]});k.show()}})}}]});ui.cmp.VCSLogGrid.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp");ui.cmp.ViewVCDiff=Ext.extend(Ext.Panel,{layout:"fit",title:_("Diff From VCS"),iconCls:"iconDiffView",collapsedIconCls:"iconDiffView",plugins:[Ext.ux.PanelCollapsedTitle],initComponent:function(){Ext.apply(this,{items:{id:this.prefix+"-diff-"+this.fid,xtype:"panel",layout:"fit",items:[new Ext.ux.IFrameComponent({id:"frame-"+this.prefix+"-diff-"+this.fid,url:String.format(PhDOE.app.conf.viewVcUrl,this.fpath+this.fname,this.rev1,this.rev2)})]}});ui.cmp.ViewVCDiff.superclass.initComponent.call(this)}});Ext.namespace("ui","ui.cmp","ui.cmp._WorkTreeGrid","ui.cmp._WorkTreeGrid.menu");ui.cmp._WorkTreeGrid.SetProgress=new Ext.util.DelayedTask(function(){new ui.task.SetFileProgressTask({idDB:this.node.attributes.idDB,progress:this.node.attributes.progress})});ui.cmp._WorkTreeGrid.menu.admin=function(c){Ext.apply(this,c);this.init();ui.cmp._WorkTreeGrid.menu.admin.superclass.constructor.call(this)};Ext.extend(ui.cmp._WorkTreeGrid.menu.admin,Ext.menu.Item,{init:function(){var c;switch(this.from){case"file":c=[{scope:this,iconCls:"iconSwitchLang",text:_("Change file's owner"),handler:function(){new ui.cmp.ChangeFileOwner({fileIdDB:this.node.attributes.idDB,fileFolder:this.folderNode.attributes.task,fileName:this.node.attributes.task,currentOwner:this.userNode.attributes.task})}},{scope:this,iconCls:"iconPageDelete",text:((this.node.attributes.type==="delete")?_("Cancel this deletion"):_("Clear this change")),handler:function(){new ui.task.ClearLocalChangeTask({ftype:this.node.attributes.type,fpath:this.folderNode.attributes.task,fname:this.node.attributes.task})}}];break;case"patch":c=[{scope:this,iconCls:"iconTrash",text:_("Delete this patch"),handler:function(){ui.task.DeletePatchTask({patchID:this.node.attributes.idDB})}}];break}Ext.apply(this,{text:_("Administrator menu"),iconCls:"iconAdmin",handler:function(){return false},menu:new Ext.menu.Menu({items:c})})}});ui.cmp._WorkTreeGrid.menu.commit=function(c){Ext.apply(this,c);this.init();ui.cmp._WorkTreeGrid.menu.commit.superclass.constructor.call(this)};Ext.extend(ui.cmp._WorkTreeGrid.menu.commit,Ext.menu.Item,{init:function(){Ext.apply(this,{text:_("Commit..."),iconCls:"iconCommitFileVcs",disabled:(PhDOE.user.isAnonymous),handler:function(){return false},menu:new Ext.menu.Menu({items:[{scope:this,text:_("...this file"),hidden:(this.from==="user"||this.from==="folder"||this.from==="patch"||this.from==="anonymousPatch"),iconCls:"iconCommitFileVcs",handler:function(){var c=[{fid:Ext.util.md5(this.folderNode.attributes.task+this.node.attributes.task),fpath:this.folderNode.attributes.task,fname:this.node.attributes.task,fdbid:this.node.attributes.idDB,ftype:this.node.attributes.type,fdate:Date.parseDate(this.node.attributes.last_modified,"Y-m-d H:i:s"),fby:this.userNode.attributes.task}];new ui.cmp.CommitPrompt({files:c}).show()}},{scope:this,text:_("...all files from this folder"),hidden:(this.from==="user"||this.from==="patch"||this.from==="anonymousPatch"),iconCls:"iconCommitFileVcs",handler:function(){var c=[];this.folderNode.cascade(function(d){if(d.attributes.type!=="folder"&&d.attributes.type!=="user"){c.push({fid:Ext.util.md5(this.folderNode.attributes.task+d.attributes.task),fpath:this.folderNode.attributes.task,fname:d.attributes.task,fdbid:d.attributes.idDB,ftype:d.attributes.type,fdate:Date.parseDate(d.attributes.last_modified,"Y-m-d H:i:s"),fby:this.userNode.attributes.task})}},this);new ui.cmp.CommitPrompt({files:c}).show()}},{scope:this,text:_("...all files from this patch"),hidden:(this.module!=="patches"||this.from==="user"),iconCls:"iconCommitFileVcs",handler:function(){var e=[],c="",d=false;if(this.from==="anonymousPatch"){c=this.patchNode.attributes.patchDescription+"\n\n-- \nProvided by "+this.patchNode.parentNode.attributes.task+" ("+this.patchNode.attributes.patchEmail+")";d=this.patchNode.attributes.idDB}this.patchNode.cascade(function(f){if(f.attributes.type!=="folder"&&f.attributes.type!=="user"&&f.attributes.type!=="patch"){e.push({fid:Ext.util.md5(f.parentNode.attributes.task+f.attributes.task),fpath:f.parentNode.attributes.task,fname:f.attributes.task,fdbid:f.attributes.idDB,ftype:f.attributes.type,fdate:Date.parseDate(f.attributes.last_modified,"Y-m-d H:i:s"),fby:this.userNode.attributes.task})}},this);new ui.cmp.CommitPrompt({files:e,defaultMessage:c,patchID:d}).show()}},{scope:this,text:_("...all files modified by me"),hidden:(this.from==="anonymousPatch"),iconCls:"iconCommitFileVcs",handler:function(){var c=[];this.userNode.cascade(function(d){if(d.attributes.type!=="folder"&&d.attributes.type!=="user"&&d.attributes.type!=="patch"){c.push({fid:Ext.util.md5(d.parentNode.attributes.task+d.attributes.task),fpath:d.parentNode.attributes.task,fname:d.attributes.task,fdbid:d.attributes.idDB,ftype:d.attributes.type,fdate:Date.parseDate(d.attributes.last_modified,"Y-m-d H:i:s"),fby:this.userNode.attributes.task})}},this);new ui.cmp.CommitPrompt({files:c}).show()}}]})})}});ui.cmp._WorkTreeGrid.menu.usersPatch=function(d){Ext.apply(this,d);var f=Ext.getCmp(this.menuID),e,c;if(!f.itemRendered){f.removeAll();f.doLayout();c=ui.cmp.PatchesTreeGrid.getInstance().getUserPatchesList();if(c){Ext.each(c,function(g){e=new Ext.menu.Item({id:Ext.id(),text:g.attributes.task,handler:function(){ui.task.MoveToPatch({patchID:g.attributes.idDB,patchName:g.attributes.task,nodesToAdd:f.nodesToAdd})}});f.add(e)},this)}else{e=new Ext.menu.Item({disabled:true,text:_("You have no patch currently. You must create one.")});f.add(e)}e=new Ext.menu.Item({text:_("Create a new patch"),iconCls:"iconAdd",handler:function(){var g=new ui.cmp.ManagePatchPrompt({title:_("Create a new patch"),nodesToAdd:f.nodesToAdd});g.show(this.el)}});f.add("-",e);f.doLayout();f.itemRendered=true}};ui.cmp._WorkTreeGrid.menu.users=function(c){Ext.apply(this,c);this.init();ui.cmp._WorkTreeGrid.menu.users.superclass.constructor.call(this)};Ext.extend(ui.cmp._WorkTreeGrid.menu.users,Ext.menu.Menu,{listeners:{show:function(){if(this.node.attributes.task===PhDOE.user.login){ui.cmp._WorkTreeGrid.menu.usersPatch({menuID:"usersPatchesMenu"})}}},init:function(){var d=[],c;this.node.cascade(function(e){if(e.attributes.type!=="user"&&e.attributes.type!=="folder"){d.push(e)}},this);c=(this.node.attributes.task===PhDOE.user.login)?[{text:_("Submit all files for review in patch:"),iconCls:"iconPendingPatch",handler:function(){return false},menu:new Ext.menu.Menu({id:"usersPatchesMenu",itemRendered:false,nodesToAdd:d})},{xtype:"menuseparator",hidden:(PhDOE.user.isAnonymous)},((!PhDOE.user.isAnonymous)?new ui.cmp._WorkTreeGrid.menu.commit({from:"user",node:false,folderNode:false,userNode:this.node}):"")]:[{scope:this,text:String.format(_("Send an email to {0}"),""+this.node.attributes.task+""),iconCls:"iconSendEmail",hidden:(this.node.attributes.email==="false"),handler:function(){var e=new ui.cmp.EmailPrompt();e.setData(this.node.attributes.task,this.node.attributes.email);e.show(this.node.el)}}];Ext.apply(this,{items:c})}});ui.cmp._WorkTreeGrid.menu.folders=function(c){Ext.apply(this,c);this.init();ui.cmp._WorkTreeGrid.menu.folders.superclass.constructor.call(this)};Ext.extend(ui.cmp._WorkTreeGrid.menu.folders,Ext.menu.Menu,{listeners:{show:function(){if(this.node.parentNode.attributes.task===PhDOE.user.login){ui.cmp._WorkTreeGrid.menu.usersPatch({menuID:"foldersPatchesMenu"})}}},init:function(){var c=[];if(this.node.parentNode.attributes.task!==PhDOE.user.login){return false}this.node.cascade(function(d){if(d.attributes.type!=="folder"){c.push(d)}},this);Ext.apply(this,{items:[{text:_("Submit all files in this directory in patch:"),iconCls:"iconPendingPatch",handler:function(){return false},menu:new Ext.menu.Menu({id:"foldersPatchesMenu",itemRendered:false,nodesToAdd:c})},{xtype:"menuseparator",hidden:(PhDOE.user.isAnonymous)},((!PhDOE.user.isAnonymous)?new ui.cmp._WorkTreeGrid.menu.commit({from:"folder",node:false,folderNode:this.node,userNode:this.node.parentNode}):"")]})}});ui.cmp._WorkTreeGrid.menu.files=function(c){Ext.apply(this,c);this.init();ui.cmp._WorkTreeGrid.menu.files.superclass.constructor.call(this)};Ext.extend(ui.cmp._WorkTreeGrid.menu.files,Ext.menu.Menu,{listeners:{show:function(){if(this.node.parentNode.parentNode.attributes.task===PhDOE.user.login){ui.cmp._WorkTreeGrid.menu.usersPatch({menuID:"filePatchesMenu"})}}},init:function(){var h=this.node,l=h.attributes.type,g,c=h.parentNode.attributes.task,e=h.attributes.task,k=h.ownerTree,f=h.parentNode.parentNode.attributes.task,d=[],j;j=h.parentNode.attributes.task.split("/");g=j[0];d.push(this.node);Ext.apply(this,{items:[{text:""+((l==="delete")?_("View in a new tab"):_("Edit in a new tab"))+"",iconCls:"iconEdit",handler:function(){k.openFile(h)}},{text:_("Submit as patch for review in:"),iconCls:"iconPendingPatch",hidden:(f!==PhDOE.user.login),handler:function(){return false},menu:new Ext.menu.Menu({id:"filePatchesMenu",itemRendered:false,nodesToAdd:d})},{text:_("Set the progress..."),iconCls:"iconProgress",hidden:(l==="delete"||f!==PhDOE.user.login),menu:{xtype:"menu",showSeparator:false,items:[{xtype:"slider",width:200,value:this.node.attributes.progress,increment:10,minValue:0,maxValue:100,plugins:new Ext.slider.Tip({getText:function(m){return String.format(""+_("{0}% complete")+"",m.value)}}),refreshNodeColumns:function(o){var x=o.getOwnerTree(),u=o.attributes,s=x.columns,m=o.ui.getEl().firstChild,y=m.childNodes,p,r,w,q;for(p=1,q=s.length;p1){for(var d=0;d1){f=new Ext.menu.Menu({listeners:{show:function(){ui.cmp._WorkTreeGrid.menu.usersPatch({menuID:"globalPatchesMenu"})}},items:[{text:_("Submit all this files for review in patch:"),iconCls:"iconPendingPatch",handler:function(){return false},menu:new Ext.menu.Menu({id:"globalPatchesMenu",itemRendered:false,nodesToAdd:l})}]});f.showAt(k.getXY());return}g=j.attributes.type;switch(g){case"user":j.select();f=new ui.cmp._WorkTreeGrid.menu.users({node:j});break;case"folder":j.select();f=new ui.cmp._WorkTreeGrid.menu.folders({node:j});break;default:j.select();f=new ui.cmp._WorkTreeGrid.menu.files({node:j});break}f.showAt(k.getXY())},initComponent:function(){function c(d,e){e.css+=" x-grid3-progresscol";return String.format('
{2}
',this.getStyle(d),(d/this.ceiling)*100,this.getText(d))}Ext.apply(this,{animate:true,useArrows:true,autoScroll:true,border:false,containerScroll:true,defaults:{autoScroll:true},selModel:new Ext.tree.MultiSelectionModel(),columns:[{header:_("Users"),dataIndex:"task",tpl:new Ext.XTemplate("{task:this.formatUserName}",{formatUserName:function(d,e){if(e.userID){e.qtip=_("userID: ")+e.userID}return d}})},{header:_("Last modified"),width:120,dataIndex:"last_modified",align:"center",tpl:new Ext.XTemplate("{last_modified:this.formatDate}",{formatDate:function(d,e){if(e.type!=="user"&&e.type!=="folder"){return Date.parseDate(d,"Y-m-d H:i:s").format(_("Y-m-d, H:i"))}else{return""}}})},{header:_("Estimated progress"),dataIndex:"progress",width:100,align:"center",tpl:new Ext.XTemplate("{progress:this.formatProgress}",{formatProgress:function(f,h){if(Ext.util.Format.substr(h,0,4)==="out:"){var g=h.split(":");f=g[1]}if(!f&&f!==0){return""}function e(k){var j=(k<(100/2))?"x-progress-text-back":"x-progress-text-front"+(Ext.isIE6?"-ie6":""),l;l=String.format('
{2}
',j,Ext.id(),k+"%");return(k<(100/1.05))?l.substring(0,l.length-6):l.substr(6)}function d(j){if(j<=100&&j>(100*0.67)){return"-green"}if(j<(100*0.67)&&j>(100*0.33)){return"-orange"}if(j<(100*0.33)){return"-red"}return""}return String.format('
{2}
',d(f),(f/100)*100,e(f))}})}],loader:{dataUrl:"./do/getWork",baseParams:{module:"workInProgress"}}});ui.cmp.WorkTreeGrid.superclass.initComponent.call(this);this.on("contextmenu",this.onContextMenu,this);this.on("resize",this.resizeCmp,this);this.on("dblclick",this.openFile,this);this.getRootNode().on("beforechildrenrendered",function(){this.updateFilesCounter.defer(200,this)},this)},resizeCmp:function(g,f,d,e){this.columns[0].width=e-(this.columns[1].width+this.columns[2].width+5);this.updateColumnWidths()},delRecord:function(m){var d=this.getRootNode(),g,e,k,c,l,f;for(g=0;gPlease delete these characters or change the header of the XML file in UTF-8 ; i.e.:

<?xml version="1.0" encoding="utf-8"?>
');break;case"tabs_found":d=_("Error");e=_('It seems that you have inserted some tabs caracters into this files. Please, replace each one by one space.
Tip: You can use the "Re-indent all this file" button to replace all tabs by spaces.');break;case"folder_already_exist":d=_("Error");e=_("This folder already exist in the current folder.");break;case"file_already_exist":d=_("Error");e=_("This file already exist in the current folder.");break;case"save_you_cant_modify_it":d=_("Error");e=_("You can't modify this file as it was modify by another user. Contact an administrator if you want to be able to modify it.");break;case"file_isnt_owned_by_current_user":d=_("Error");e=_("The file you want to clear local change isn't own by you.
You can only do this action for yours files.");break;case"file_localchange_didnt_exist":d=_("Error");e=_("The file you want to clear local change isn't exist as work in progress.");break;case"changeFilesOwnerNotAdmin":d=_("Error");e=_("You can't change file's owner. You must be a global administrator or an administrator for this lang.");break;case"patch_delete_dont_exist":d=_("Error");e=_("The patch you want to delete didn't exist.");break;case"patch_delete_isnt_own_by_current_user":d=_("Error");e=_("The patch you want to delete isn't own by you. Only the user how create it or a global administrator can delete it.");break;case"action_only_global_admin":d=_("Error");e=_("This action is available only to global administrator.");break;case"action_only_admin":d=_("Error");e=_("This action is available only to global administrator or to administrator for this lang.");break}Ext.MessageBox.alert(d,e)},runDirectAccess:function(){if(directAccess){if(directAccess.link=="perm"){ui.cmp.RepositoryTree.getInstance().openFile("byPath",directAccess.lang+directAccess.path,directAccess.name)}if(directAccess.link=="patch"){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",FilePath:directAccess.path,FileName:directAccess.name})}if(directAccess.link=="patchID"){Ext.getCmp("main-panel").openDiffTab({DiffType:"file",patchID:directAccess.patchID,patchName:directAccess.patchName})}}},afterLoadAllStore:function(){this.app.loaded=true;this.runDirectAccess();if(this.user.conf.main.loadMailsAtStartUp){ui.cmp.PortletLocalMail.getInstance().reloadData()}if(this.user.conf.main.loadBugsAtStartUp){ui.cmp.PortletBugs.getInstance().reloadData()}PhDOE.setTopic();PhDOE.setTopic(true)},loadAllStore:function(){var e=new Ext.ProgressBar({width:300,renderTo:"loading-progressBar"}),c=[],d;if(PhDOE.user.lang!=="en"){c=[ui.cmp._MainMenu.store,ui.cmp.StaleFileGrid.getInstance().store,ui.cmp.ErrorFileGrid.getInstance().store,ui.cmp.PendingReviewGrid.getInstance().store,ui.cmp.NotInENGrid.getInstance().store,ui.cmp.PortletSummary.getInstance().store,ui.cmp.PortletTranslationGraph.getInstance().store,ui.cmp.PortletTranslationsGraph.getInstance().store,ui.cmp.PortletTranslator.getInstance().storeTranslator,ui.cmp.PortletTranslator.getInstance().storeReviewer,ui.cmp.PendingTranslateGrid.getInstance().store,ui.cmp.PortletInfo.getInstance().store]}else{c=[ui.cmp._MainMenu.store,ui.cmp.PortletTranslationsGraph.getInstance().store,ui.cmp.ErrorFileGrid.getInstance().store,ui.cmp.PortletInfo.getInstance().store]}d=function(f){e.updateProgress((f+1)/c.length,(f+1)+" of "+c.length+"...");c[f].load({callback:function(){f++;if(f  '+this.app.name+"",autoHeight:true,border:false,margins:"0 0 5 0"},{region:"west",id:"main-menu-panel",layout:"accordion",collapsible:true,collapseMode:"mini",animate:true,split:true,width:PhDOE.user.conf.main.mainMenuWidth||300,header:false,listeners:{resize:function(j,o){if(o&&o!=PhDOE.user.conf.main.mainMenuWidth){var m=new ui.task.UpdateConfTask({module:"main",itemName:"mainMenuWidth",value:o,notify:false})}}},tbar:[{text:_("Main menu"),iconCls:"MainMenu",menu:new ui.cmp.MainMenu()}],items:[{id:"acc-need-translate",title:_("Files need translate")+' (0)',layout:"fit",border:false,iconCls:"iconFilesNeedTranslate",hidden:(PhDOE.user.lang==="en"),items:[ui.cmp.PendingTranslateGrid.getInstance()],collapsed:true,listeners:{expand:function(j){Ext.getCmp("FNT-filter").wrap.setWidth(180);Ext.getCmp("FNT-filter").syncSize()}}},{id:"acc-need-update",title:_("Files need update")+' (0)',layout:"fit",border:false,iconCls:"iconFilesNeedUpdate",hidden:(PhDOE.user.lang==="en"),items:[ui.cmp.StaleFileGrid.getInstance()],collapsed:true,listeners:{expand:function(j){Ext.getCmp("FNU-filter").wrap.setWidth(180);Ext.getCmp("FNU-filter").syncSize()}}},{id:"acc-error",title:(PhDOE.user.lang==="en")?"Number of failures to meet 'strict standards' (0)":_("Error in current translation")+' (0)',layout:"fit",border:false,iconCls:"iconFilesError",items:[ui.cmp.ErrorFileGrid.getInstance()],collapsed:true,listeners:{expand:function(j){Ext.getCmp("FE-filter").wrap.setWidth(180);Ext.getCmp("FE-filter").syncSize()}}},{id:"acc-need-reviewed",title:_("Files need reviewed")+' (0)',layout:"fit",border:false,iconCls:"iconFilesNeedReviewed",hidden:(PhDOE.user.lang==="en"),items:[ui.cmp.PendingReviewGrid.getInstance()],collapsed:true,listeners:{expand:function(j){Ext.getCmp("FNR-filter").wrap.setWidth(180);Ext.getCmp("FNR-filter").syncSize()}}},{id:"acc-notInEn",title:_("Not in EN tree")+' (0)',layout:"fit",border:false,iconCls:"iconNotInEn",hidden:(PhDOE.user.lang==="en"),items:[ui.cmp.NotInENGrid.getInstance()],collapsed:true},{id:"acc-all-files",title:_("All files"),layout:"fit",border:false,iconCls:"iconAllFiles",items:[ui.cmp.RepositoryTree.getInstance()],collapsed:true,listeners:{expand:function(j){Ext.getCmp("AF-search").wrap.setWidth(180);Ext.getCmp("AF-search").syncSize()}}},{id:"acc-work-in-progress",title:_("Work in progress")+' (0)',layout:"fit",border:false,iconCls:"iconWorkInProgress",items:[ui.cmp.WorkTreeGrid.getInstance()],collapsed:true,tools:[{id:"refresh",qtip:_("Refresh"),handler:function(){ui.cmp.WorkTreeGrid.getInstance().getRootNode().reload()}}]},{id:"acc-patches",tools:[{id:"refresh",qtip:_("Refresh"),handler:function(){ui.cmp.PatchesTreeGrid.getInstance().getRootNode().reload()}},{id:"gear",hidden:(this.user.isAnonymous),qtip:_("Open the Log Message Manager"),handler:function(){if(!Ext.getCmp("commit-log-win")){var j=new ui.cmp.CommitLogManager()}Ext.getCmp("commit-log-win").show("acc-patches")}}],title:_("Patches for review")+' (0)',layout:"fit",border:false,iconCls:"iconPatch",items:[ui.cmp.PatchesTreeGrid.getInstance()],collapsed:true},{id:"acc-google-translate",title:_("Google translation"),layout:"fit",border:false,iconCls:"iconGoogle",hidden:(PhDOE.user.lang==="en"),items:[new ui.cmp.GoogleTranslationPanel()],collapsed:true}]},{xtype:"mainpanel",id:"main-panel",region:"center",items:[{xtype:"panel",id:"MainInfoTabPanel",title:_("Home"),baseCls:"MainInfoTabPanel",autoScroll:true,plain:true,items:[{xtype:"container",layout:"column",border:false,items:[{xtype:"container",columnWidth:0.5,html:'

'+_("Connected as")+' , '+_("Project: ")+''+PhDOE.project+", "+_("Language: ")+' -

',listeners:{afterrender:function(m){var j="",p="",o;o=Ext.get("loginLibel");if(PhDOE.user.isGlobalAdmin||PhDOE.user.isLangAdmin){o.addClass("userAdmin");p=' '+PhDOE.user.login}else{if(PhDOE.user.authService=="VCS"){p=' '+PhDOE.user.login}else{if(PhDOE.user.authService=="google"){p=' '+PhDOE.user.login}else{if(PhDOE.user.authService=="facebook"){p=' '+PhDOE.user.login}}}}o.dom.innerHTML=p;content=_("Connected using")+" "+PhDOE.user.authService+"
";content+=(PhDOE.user.isGlobalAdmin)?_("You are a global Administrator")+"
":"";content+=(PhDOE.user.isLangAdmin)?_("You are an administrator for this language")+"
":"";new Ext.ToolTip({target:"loginLibel",anchor:"top",html:content})}}},{xtype:"container",columnWidth:0.5,html:'

'+_("Topic:")+'

-

-

-'+_("Topic:")+'

-

-
',listeners:{afterrender:function(m){if(PhDOE.user.isAnonymous){return}var j=function(q){var o="topic-info-content"+(q?"-lang":""),p=Ext.get(o).dom.innerHTML;Ext.get(o).dom.innerHTML="";new Ext.FormPanel({renderTo:o,layout:"anchor",border:false,items:[{xtype:"htmleditor",value:p,anchor:"100%"}],buttonAlign:"center",buttons:[{text:_("Save"),handler:function(){PhDOE.saveTopic(this.ownerCt.ownerCt.items.items[0].getValue(),q)}},{text:_("Cancel"),handler:function(){PhDOE.setTopic(q)}}]})};Ext.get("topic-info-container").on("dblclick",function(){j()});Ext.get("topic-info-container-lang").on("dblclick",function(){j(true)})}}}]},{xtype:"portal",border:false,items:[{columnWidth:0.5,style:"padding:10px 5px 10px 5px",items:d},{columnWidth:0.5,style:"padding:10px 5px 10px 5px",items:g}],listeners:{drop:function(o){var m,q=[],s=[],t;for(var r=0;r ' + - _('Please, wait until update this folder...') - ); - - // We need to stop ping test during this process - ui.task.PingTask.getInstance().cancel(); - - XHR({ - params : { - task : 'updateFolder', - path : node.id - }, - success : function(r) - { - var o = Ext.util.JSON.decode(r.responseText); - ui.task._UpdateSingleFolderTask.afterUpdate(o, node); - }, - failure : function(r) - { - var o = Ext.util.JSON.decode(r.responseText); - - if (o && o.success === false) { - // Re-enable TaskPing - ui.task.PingTask.getInstance().delay(30000); - Ext.getBody().unmask(); - PhDOE.winForbidden(); - } else { - // take over 30sec (max Keep-Alive time) - // poll every XX secondes if the update is finish - ui.task._UpdateSingleFolderTask.poll.delay(5000, null, this, t); - } - } - }); -}; - -ui.task.UpdateSingleFolderTask = function(node) -{ - // If the user is anonymous, we don't update anything - if (PhDOE.user.isAnonymous) { - Ext.getCmp('winVCSCommit').close(); - PhDOE.winForbidden(); - return; - } - ui.task._UpdateSingleFolderTask.update(node); -}; \ No newline at end of file diff --git a/php/AccountManager.php b/php/AccountManager.php index b22aa663..f72fe732 100644 --- a/php/AccountManager.php +++ b/php/AccountManager.php @@ -4,10 +4,6 @@ * */ -require_once dirname(__FILE__) . '/VCSFactory.php'; -require_once dirname(__FILE__) . '/DBConnection.php'; -require_once dirname(__FILE__) . '/ProjectManager.php'; - class AccountManager { private static $instance; @@ -178,14 +174,11 @@ public function isLogged() * @param $lang The language we want to access. * @return An associated array. */ - public function login($project, $vcsLogin, $vcsPasswd, $email, $lang='en', $authService='VCS', $authServiceID) + public function login($project, $vcsLogin, $vcsPasswd, $email, $lang='en', $authService='VCS', $authServiceID = null) { // Var to return into ExtJs $return = array(); - // Var return from VCS auth system - $AuthReturn = false; - // We manage the project if( ProjectManager::getInstance()->setProject($project) ) { $this->project = strtoupper($project); @@ -310,10 +303,6 @@ public function login($project, $vcsLogin, $vcsPasswd, $email, $lang='en', $auth // We try to authenticate this user to master php server. $AuthReturn = VCSFactory::getInstance()->masterPhpAuthenticate($vcsLogin, $vcsPasswd); $return['authMethod'] = 'masterPhp'; - } else { - // We try to authenticate this user to VCS server. - $AuthReturn = VCSFactory::getInstance()->svnAuthenticate($vcsLogin, $vcsPasswd); - $return['authMethod'] = 'svnServer'; } diff --git a/php/Conf.php b/php/Config.php old mode 100644 new mode 100755 similarity index 77% rename from php/Conf.php rename to php/Config.php index e598f74c..ad0ea8f4 --- a/php/Conf.php +++ b/php/Config.php @@ -1,92 +1,104 @@ -buildConf(); - } - - public function buildConf() - { - $p = dirname(__FILE__).'/conf/'; - - // First, we load the global configuration file - $this->conf['GLOBAL_CONFIGURATION'] = parse_ini_file($p."conf.ini"); - - if( is_file($p."localConf.ini") ) { - $this->conf['GLOBAL_CONFIGURATION'] = array_merge( $this->conf['GLOBAL_CONFIGURATION'], parse_ini_file($p."localConf.ini") ); - } - - // We fix the data path here - $this->conf['GLOBAL_CONFIGURATION']['data.path'] = realpath(dirname(__FILE__).'/../'.$this->conf['GLOBAL_CONFIGURATION']['data.path']).'/'; - - // Second, we load all config project file - $d = dir($p); - while (false !== ($entry = $d->read())) { - if( is_file($p.$entry) && ( $entry != 'conf.ini' && $entry != 'localConf.ini' ) ) { - - // Get the name of the project directly into the filename - $t = explode(".", $entry); - - $this->conf[strtoupper($t[1])] = parse_ini_file($p.$entry); - } - } - $d->close(); - - // Third, we find all marks to be replace by a var from global_configuration array or current project - while( list($project, $value) = each($this->conf) ) { - - if( $project == "GLOBAL_CONFIGURATION" ) { continue; } - - while( list($keys, $v ) = each($value) ) { - - $match = false; - - if( preg_match_all("/\{(.[^}]*?)\['(.*?)'\]\}/", $v,$match) ) { - - $new_val = $v; - for( $i=0; $i < count($match[0]); $i++ ) { - - $new_val = str_replace( $match[0][$i], - $this->conf[$match[1][$i]][$match[2][$i]], - $new_val - ); - - $this->conf[$project][$keys]= $new_val; - } - } - } - } - - reset($this->conf); - return $this->conf; - - } - - public function getConf() { - return $this->conf; - } - - -} - -?> +buildConf(); + } + + public function buildConf() + { + $p = dirname(__FILE__).'/conf/'; + + // First, we load the global configuration file + $this->conf['GLOBAL_CONFIGURATION'] = parse_ini_file($p."conf.ini"); + + if( is_file($p."localConf.ini") ) { + $this->conf['GLOBAL_CONFIGURATION'] = array_merge( $this->conf['GLOBAL_CONFIGURATION'], parse_ini_file($p."localConf.ini") ); + } + + // We fix the data path here + $this->conf['GLOBAL_CONFIGURATION']['data.path'] = realpath(dirname(__FILE__).'/../'.$this->conf['GLOBAL_CONFIGURATION']['data.path']).'/'; + + // Second, we load all config project file + foreach (glob($p."project.*.ini") as $entry) { + $entry = basename($entry); + if( is_file($p.$entry)) { + + // Get the name of the project directly into the filename + $t = explode(".", $entry); + + $this->conf[strtoupper($t[1])] = parse_ini_file($p.$entry); + } + } + + // End, we load all local config project file + foreach (glob($p."local.*.ini") as $entry) { + $entry = basename($entry); + if( is_file($p.$entry)) { + + // Get the name of the project directly into the filename + $t = explode(".", $entry); + + $this->conf[strtoupper($t[1])] = array_merge( $this->conf[strtoupper($t[1])], parse_ini_file($p.$entry) ); + } + } + + + // Third, we find all marks to be replace by a var from global_configuration array or current project + while( list($project, $value) = each($this->conf) ) { + + if( $project == "GLOBAL_CONFIGURATION" ) { continue; } + + while( list($keys, $v ) = each($value) ) { + + $match = false; + + if( preg_match_all("/\{(.[^}]*?)\['(.*?)'\]\}/", $v,$match) ) { + + $new_val = $v; + for( $i=0; $i < count($match[0]); $i++ ) { + + $new_val = str_replace( $match[0][$i], + $this->conf[$match[1][$i]][$match[2][$i]], + $new_val + ); + + $this->conf[$project][$keys]= $new_val; + } + } + } + } + + reset($this->conf); + return $this->conf; + + } + + public function getConf() { + return $this->conf; + } + + +} + +?> diff --git a/php/CvsClient.php b/php/CvsClient.php index c955e304..4094220a 100644 --- a/php/CvsClient.php +++ b/php/CvsClient.php @@ -1,6 +1,5 @@ command = $command; + + // We validate and escape certain types of input. + $this->args = array(); + foreach ($args as $key => $val) + { + if (is_bool($val) || is_float($val) || is_int($val) || is_null($val)) + $this->args[$key] = $val; + else if (is_string($val)) + $this->args[$key] = escapeshellarg($val); + else if (is_object($val)) + $this->args[$key] = escapeshellarg($val->__toString()); + else + trigger_error('Argument with unexpected type used to construct ExecStatement. It has been omitted from the command string.', E_USER_WARNING); + } + } + + public function getCommand() + { + return $this->command; + } + + public function getArgs() + { + return $this->args; + } + + public function __toString() + { + return vsprintf($this->getCommand(), $this->getArgs()); + } +} +?> \ No newline at end of file diff --git a/php/ExtJsController.php b/php/ExtJsController.php index 7a75aad0..91417936 100644 --- a/php/ExtJsController.php +++ b/php/ExtJsController.php @@ -5,25 +5,6 @@ * @todo Add inline documentation for each controller task */ -require_once dirname(__FILE__) . '/AccountManager.php'; -require_once dirname(__FILE__) . '/BugReader.php'; -require_once dirname(__FILE__) . '/DictionaryManager.php'; -require_once dirname(__FILE__) . '/EntitiesAcronymsFetcher.php'; -require_once dirname(__FILE__) . '/File.php'; -require_once dirname(__FILE__) . '/GTranslate.php'; -require_once dirname(__FILE__) . '/JsonResponseBuilder.php'; -require_once dirname(__FILE__) . '/LogManager.php'; -require_once dirname(__FILE__) . '/LockFile.php'; -require_once dirname(__FILE__) . '/NewsReader.php'; -require_once dirname(__FILE__) . '/PreviewFile.php'; -require_once dirname(__FILE__) . '/ProjectManager.php'; -require_once dirname(__FILE__) . '/RepositoryFetcher.php'; -require_once dirname(__FILE__) . '/RepositoryManager.php'; -require_once dirname(__FILE__) . '/ToolsXmllint.php'; -require_once dirname(__FILE__) . '/TranslationStatistic.php'; -require_once dirname(__FILE__) . '/TranslatorStatistic.php'; -require_once dirname(__FILE__) . '/UserNotes.php'; -require_once dirname(__FILE__) . '/VCSFactory.php'; /** * Ext JS controller class @@ -1170,43 +1151,6 @@ public function getAcronyms() ); } - /** - * Update a single folder recursively - */ - public function updateFolder() - { - $am = AccountManager::getInstance(); - if (!$am->isLogged()) { - return JsonResponseBuilder::failure(); - } - - $rm = RepositoryManager::getInstance(); - $path = $this->getRequestVariable('path'); - - $r = $rm->updateFolder($path); - - return JsonResponseBuilder::success( - array( - 'result' => $r - ) - ); - } - - /** - * Get the response after an update single folder - */ - function getUpdateFolderResponse() - { - if (!AccountManager::getInstance()->isLogged()) { - return JsonResponseBuilder::failure(); - } - - return JsonResponseBuilder::success( - array( - 'result' => json_encode($_SESSION['updateFolder']) - ) - ); - } /** * Get Entities to be display into a grid into the "All files modules" @@ -1252,13 +1196,13 @@ public function getDiff() $Rev1 = $this->getRequestVariable('Rev1'); $Rev2 = $this->getRequestVariable('Rev2'); - // Ensure Rev2 is always a value greater than Rev1 - if( $Rev2 < $Rev1 ) - { - $tmp = $Rev2; - $Rev2 = $Rev1; - $Rev1 = $tmp; - } +// // Ensure Rev2 is always a value greater than Rev1 +// if( $Rev2 < $Rev1 ) +// { +// $tmp = $Rev2; +// $Rev2 = $Rev1; +// $Rev1 = $tmp; +// } $opt = Array('rev1'=>$Rev1, 'rev2' => $Rev2); diff --git a/php/File.php b/php/File.php index aac13e10..8066613e 100644 --- a/php/File.php +++ b/php/File.php @@ -1,10 +1,5 @@ /', $content, $match); + preg_match('//', $content, $match); if (!empty($match)) { $info['rev'] = $match[1]; } // Rev tag $match = array(); - preg_match('//U', $content, $match); + preg_match('//U', $content, $match); if (!empty($match)) { $info['en-rev'] = ($match[1] == 'n/a') ? 0 : $match[1]; $info['maintainer'] = $match[4]; diff --git a/php/GTranslate.php b/php/GTranslate.php index 65e09db2..94b30e63 100644 --- a/php/GTranslate.php +++ b/php/GTranslate.php @@ -1,6 +1,5 @@ update_time + (24*60*60)) > time() ) { + $this->updateKarmaList(); + $data = RepositoryFetcher::getStaticValue('karma_list', ''); + } + + return $data->data; + } + + private function updateKarmaList() + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + $file = @file($appConf[$project]['vcs.karma.file']); + + $line_avail = array(); + $user = array(); + + // We cleanUp the content of this file + for( $i=0; $i < count($file); $i++) { + if( substr($file[$i], 0, 6) == 'avail|') { + $line_avail[] = $file[$i]; + + $t = explode("|", $file[$i]); + $users = trim($t[1]); + $karmas = ( isset($t[2]) ) ? trim($t[2]) : 'ALL'; + + $users = explode(",", $users); + $karmas = explode(",", $karmas); + + for( $j=0; $j < count($users); $j++ ) { + if( isset($user[$users[$j]]) ) { + + $user[$users[$j]]['karma'] = array_merge( $karmas, $user[$users[$j]]['karma'] ); + + } else { + + $user[$users[$j]]['karma'] = $karmas; + } + } + + } + } + + // We store this value into DB as json string to retrieve it later + $to_store = array( + "update_time" => time(), + "data" => $user + ); + RepositoryManager::setStaticValue('karma_list', '', json_encode($to_store)); + + } + + // Return true if the $user have the right karma for $module + public function checkKarma($user, $lang) + { + $userList = $this->getKarmaList(); + + $userList = (array) $userList; + + if( isset($userList[$user]) ) { + + $userList[$user] = (array) $userList[$user]; + + $karma = $userList[$user]['karma']; + + // Must have ALL, phpdoc or phpdoc/$lang + if( in_array("ALL", $karma) || in_array("phpdoc", $karma) || in_array("phpdoc/$lang", $karma) ) { + return true; + } else { + return 'You haven\'t good Karma for the chosen language. Your Current karma is : '.implode(", ", $karma); + } + + } + return 'You haven\'t any karma !'; + + } + + public function masterPhpAuthenticate($username, $password) + { + + $post = http_build_query( + array( + "token" => getenv("TOKEN"), + "username" => $username, + "password" => $password + ) + ); + + $opts = array( + "method" => "POST", + "header" => "Content-type: application/x-www-form-urlencoded", + "content" => $post, + ); + + $ctx = stream_context_create(array("http" => $opts)); + + $s = file_get_contents("https://master.php.net/fetch/cvsauth.php", false, $ctx); + + $a = @unserialize($s); + if (!is_array($a)) { + return 'master.php.net seems to be down !'; + } + if (isset($a["errno"])) { + if( $a["errno"] == 0 ) { return 'git login failed'; } + if( $a["errno"] == 1 ) { return 'Bad login'; } + if( $a["errno"] == 2 ) { return 'Bad password'; } + } + + return true; + } + + /** + + * + * @return An associative array{ 'err': git clone return code, 'output': git clone output contained in an array } + * + */ + public function checkout() + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + $server = $appConf[$project]['vcs.server']; + $module = $appConf[$project]['vcs.module']; + + + $commands = array( + new ExecStatement('mkdir %s', array($appConf['GLOBAL_CONFIGURATION']['data.path'].$module)), + new ExecStatement('cd %s', array($appConf['GLOBAL_CONFIGURATION']['data.path'].$module)), + new ExecStatement('git init'), + new ExecStatement('git remote add origin %s', array($server)), + new ExecStatement('git config branch.master.remote origin'), + new ExecStatement('git config branch.master.merge refs/heads/master'), + new ExecStatement('git config user.name %s', array('Online Doc')), + new ExecStatement('git config user.email %s', array('phd@php.net')), + new ExecStatement('git config filter.rcs-keywords.clean %s', array('.git_filters/rcs-keywords.php.clean')), + new ExecStatement('git config filter.rcs-keywords.smudge %s', array('.git_filters/rcs-keywords.php.smudge %f')), + new ExecStatement('git pull 2>&1') + ); + + $err = 1; + $trial_threshold = 3; + $output = array(); + for ($trial = 0; $err != 0 && $trial < $trial_threshold; ++$trial) { + array_push($output, "git clone trial #$trial\n"); + SaferExec::execMulti($commands, $output, $err); // if no err, err = 0 + if ($err == 0) array_push($output, "Success.\n"); + } + + return array('err' => $err, 'output' => $output); + } + + public function fastUpdate() + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + $commands = array( + new ExecStatement('cd %s', array($appConf[$project]['vcs.path'])), + // we separate pull on fetch and merge, because rcs-keywords work wrong with pull + new ExecStatement('git fetch'), + new ExecStatement('git merge origin/master 2>&1') + ); + + $err = 1; + $trial_threshold = 3; + $output = array(); + for ($trial = 0; $err != 0 && $trial < $trial_threshold; ++$trial) { + SaferExec::execMulti($commands, $output, $err); // if no err, err = 0 + } + + if ($err == 0) { + $revisions = ''; + foreach ($output as $string) { + //Updating eccb880..aafe899 + if (preg_match('/^Updating\s([a-f0-9]+\.\.[a-f0-9]+)$/', $string, $matches)) { + $revisions = $matches[1]; + break; + } + } + if (!$revisions) return false; + + $commands = array( + new ExecStatement('cd %s', array($appConf[$project]['vcs.path'])), + new ExecStatement('git whatchanged %s 2>&1', array($revisions)) + ); + $err = 1; + $trial_threshold = 3; + $output = array(); + for ($trial = 0; $err != 0 && $trial < $trial_threshold; ++$trial) { + SaferExec::execMulti($commands, $output, $err); // if no err, err = 0 + } + if ($err == 0) { + + $delete_stack = $update_stack = $create_stack = array(); + // :100755 000000 e64f1c9... 0000000... D PHPDoE_git_test/en/test.xml + foreach ($output as $string) { + if (preg_match('/^:\d+\s+\d+\s+[a-f0-9]+\.\.\.\s+[a-f0-9]+\.\.\.\s+([DMA])\s+(.*)$/', $string, $matches)) { + if ($matches[1] == 'A') { + $create_stack[] = $matches[2]; + } else if ($matches[1] == 'M') { + $update_stack[] = $matches[2]; + } else { + $delete_stack[] = $matches[2]; + } + } + } + + return array( + 'create' => $create_stack, + 'update' => $update_stack, + 'delete' => $delete_stack + ); + } else { + errlog(json_encode($output)); + return false; + } + } else { + errlog(json_encode($output)); + return false; + } + + + } + + /** + * pull . under DOC_EDITOR_VCS_PATH + * @return True if it does not report any error, false otherwise. + */ + public function update() + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + $commands = array( + new ExecStatement('cd %s', array($appConf[$project]['vcs.path'])), + // we separate pull on fetch and merge, because rcs-keywords work wrong with pull + new ExecStatement('git fetch'), + new ExecStatement('git merge origin/master 2>&1') + ); + + $err = 1; + $trial_threshold = 3; + $output = array(); + for ($trial = 0; $err != 0 && $trial < $trial_threshold; ++$trial) { + array_push($output, "git pull trial #$trial\n"); + SaferExec::execMulti($commands, $output, $err); // if no err, err = 0 + if ($err == 0) array_push($output, "Success.\n"); + } + + if ($err == 0) { + return true; + } else { + errlog(json_encode($output)); + return false; + } + } + + /** + * Get git log of a specified file. + * + * @param $path The path of the file. + * @param $file The name of the file. + * @return An array containing all git log information. + */ + public function log($path, $file) + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + $commands = array( + new ExecStatement('cd %s', array($appConf[$project]['vcs.path'].$path)), + new ExecStatement('git log --format="%%H | %%at | %%an | %%s" -- %s', array($file)) + ); + + $trial_threshold = 3; + while ($trial_threshold-- > 0) { + $output = array(); + SaferExec::execMulti($commands, $output); + if (strlen(trim(implode('', $output))) != 0) break; + } + + $part = $output; + + $final = array(); + for ($i=1; $i < count($part)-1; $i++ ) { + + $o = array(); + + $o['id'] = $i; + $o['raw'] = $part[$i]; + + $contents = trim($part[$i]); + $info = explode(' | ', $contents, 4); + + $o['revision'] = $info[0]; + $o['author'] = $info[2]; + $o['date'] = date('Y/m/d',$info[1]); + + $o['content'] = $info[3]; + + $final[] = $o; + } + + return $final; + } + + /** + * Execute git diff on specific file + * + * @param $path Path to file + * @param $file Filename + * @param $rev1 Diff revision 1 + * @param $rev2 Diff revision 2 + * @return Array of stdout of git diff + */ + public function diff($path, $file, $rev1, $rev2) + { + if ($rev1 == 0) return ''; + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + $commands = array( + new ExecStatement('cd %s', array($appConf[$project]['vcs.path'].$path)), + new ExecStatement('git diff %s %s -- %s', array($rev1, $rev2, $file)) + ); + + $trial_threshold = 3; + while ($trial_threshold-- > 0) { + $output = array(); + SaferExec::execMulti($commands, $output); + if (strlen(trim(implode('', $output))) != 0) break; + } + + return $output; + } + + public function createCommitLogFile($log) + { + $path = tempnam(sys_get_temp_dir(), 'Doc_Editor_Commit_Log_Message'); + + $handle = fopen($path, "w"); + fwrite($handle, $log); + fclose($handle); + + return $path; + } + + public function deleteCommitLogFile($path) + { + @unlink($path); + } + + public function commitFolders($foldersPath) + { + + return Array(); + } + + /** + * Executes git commit + * + * @param $log Commit log + * @param $create Array of files to be created + * @param $update Array of files to be updated + * @param $delete Array of files to be deleted + * @return Associative array{ 'err': git ci return code, 'output': git ci output contained in an array } + */ + public function commit($log, $create=false, $update=false, $delete=false) + { + $am = AccountManager::getInstance(); + + $appConf = $am->appConf; + $project = $am->project; + $vcsLang = $am->vcsLang; + $vcsLogin = $am->vcsLogin; + $vcsEmail = $am->email; + // Info we must store into DB + $info = array(); + + $pathLogFile = $this->createCommitLogFile($log); + + $create_stack = array(); + for ($i = 0; $create && $i < count($create); $i++) { + $p_to = $create[$i]->full_path; + $p_from = $create[$i]->full_new_path; + $create_stack[] = $p_to; + + // Pre-commit : rename *-new/foo.xml to actual file + @copy($p_from, $p_to); + } + + $update_stack = array(); + for ($i = 0; $update && $i < count($update); $i++) { + $p_to = $update[$i]->full_path; + $p_from = $update[$i]->full_new_path; + $update_stack[] = $p_to; + + // Pre-commit : rename *-new/foo.xml to actual file + @copy($p_from, $p_to); + } + + $delete_stack = array(); + for ($i = 0; $delete && $i < count($delete); $i++) { + $delete_stack[] = $delete[$i]->full_path; + } + + $info['nbFilesCreate'] = count($create_stack); + $info['nbFilesDelete'] = count($delete_stack); + $info['nbFilesUpdate'] = count($update_stack); + + $commands = array( + new ExecStatement('cd %s', array($appConf[$project]['vcs.path'])) + ); + + if ($info['nbFilesDelete']) + { + $commands[] = new ExecStatement('git rm' . str_repeat(' %s', $info['nbFilesDelete']), $delete_stack); + } + if ( $info['nbFilesCreate']) + { + $commands[] = new ExecStatement('git add' . str_repeat(' %s', $info['nbFilesCreate']), $create_stack); + } + if ($info['nbFilesUpdate']) + { + $commands[] = new ExecStatement('git add' . str_repeat(' %s', $info['nbFilesUpdate']), $update_stack); + } + + $args = array_merge( + array($pathLogFile, $vcsLogin.( $vcsEmail ? ' <'.$vcsEmail.'>' : '')), + $update_stack, + $delete_stack, + $create_stack + ); + + $commands[] = new ExecStatement('git commit -F %s --author=%s --' . str_repeat(' %s', $info['nbFilesCreate'] + $info['nbFilesUpdate'] + $info['nbFilesDelete']).' 2>&1', $args); + + $err = 1; + $trial_threshold = 3; + $output = array(); + for ($trial = 0; $err != 0 && $trial < $trial_threshold; ++$trial) { + array_push($output, "git commit trial #$trial\n"); + SaferExec::execMulti($commands, $output, $err); // if no err, err = 0 + if ($err == 0) array_push($output, "Success.\n"); + } + + + // Delete tmp logMessage file + $this->deleteCommitLogFile($pathLogFile); + + + + if ($err == 0) { + + // push changes to server + $err = 1; + $trial_threshold = 3; + $temp_output = array(); + $commands = array( + new ExecStatement('cd %s', array($appConf[$project]['vcs.path'])), + new ExecStatement('git push 2>&1') + ); + for ($trial = 0; $err != 0 && $trial < $trial_threshold; ++$trial) { + array_push($output, "git push trial #$trial\n"); + SaferExec::execMulti($commands, $temp_output, $err); // if no err, err = 0 + if ($err == 0) array_push($output, "Success.\n"); + } + + + + // adding revision + $err = 1; + $trial_threshold = 3; + $temp_output = array(); + $commands = array( + new ExecStatement('cd %s', array($appConf[$project]['vcs.path'])) + ); + if ( $info['nbFilesCreate']) + { + $commands[] = new ExecStatement('rm' . str_repeat(' %s', $info['nbFilesCreate']), $create_stack); + $commands[] = new ExecStatement('git checkout --' . str_repeat(' %s', $info['nbFilesCreate']), $create_stack); + } + if ($info['nbFilesUpdate']) + { + $commands[] = new ExecStatement('rm' . str_repeat(' %s', $info['nbFilesUpdate']), $update_stack); + $commands[] = new ExecStatement('git checkout --' . str_repeat(' %s', $info['nbFilesUpdate']), $update_stack); + } + for ($trial = 0; $err != 0 && $trial < $trial_threshold; ++$trial) { + SaferExec::execMulti($commands, $temp_output, $err); // if no err, err = 0 + } + + // We stock this info into DB + $info['user'] = $vcsLogin; + $info['lang'] = $vcsLang; + RepositoryManager::getInstance()->setStaticValue('info', 'commitFiles', json_encode($info), true); + } else { + $this->revert($create, $update, $delete); + errlog(json_encode($output)); + } + + return array('err' => $err, 'output' => $output); + } + + public function revert($create=false, $update=false, $delete=false) + { + $am = AccountManager::getInstance(); + + $appConf = $am->appConf; + $project = $am->project; + + $create_stack = array(); + for ($i = 0; $create && $i < count($create); $i++) { + $create_stack[] = $create[$i]->full_path; + } + + $update_stack = array(); + for ($i = 0; $update && $i < count($update); $i++) { + $update_stack[] = $update[$i]->full_path; + } + + $delete_stack = array(); + for ($i = 0; $delete && $i < count($delete); $i++) { + $delete_stack[] = $delete[$i]->full_path; + } + + $commands = array( + new ExecStatement('cd %s', array($appConf[$project]['vcs.path'])), + new ExecStatement('git checkout --' . str_repeat(' %s', count($create_stack) + count($update_stack) + count($delete_stack)) . ' 2>&1', array_merge($create_stack, $update_stack, $delete_stack)) + ); + + $err = 1; + $trial_threshold = 3; + $output = array(); + for ($trial = 0; $err != 0 && $trial < $trial_threshold; ++$trial) { + array_push($output, "git revert trial #$trial\n"); + SaferExec::execMulti($commands, $output, $err); // if no err, err = 0 + if ($err == 0) array_push($output, "Success.\n"); + } + + return array('err' => $err, 'output' => $output); + } +} + +?> diff --git a/php/LogManager.php b/php/LogManager.php index 0efbf264..5f3e54b4 100644 --- a/php/LogManager.php +++ b/php/LogManager.php @@ -1,6 +1,5 @@ $original_revision, "en_revision" => $new_en_revision, "maintainer" => $new_maintainer, - "fileModifiedEN" => ( $isModifiedEN ) ? '{"user":"'.$isModifiedEN["user"].'", "anonymousIdent":"'.$isModifiedEN["anonymousIdent"].'"}' : false, + "fileModifiedEN" => false, "fileModifiedLang" => ( $isModifiedLang ) ? '{"user":"'.$isModifiedLang["user"].'", "anonymousIdent":"'.$isModifiedLang["anonymousIdent"].'"}' : false ); } else { @@ -387,7 +384,7 @@ public function getPendingReview() $temp['reviewed'] = $new_reviewed; $temp['maintainer'] = $new_maintainer; - $temp['fileModifiedEN'] = ( $isModifiedEN ) ? '{"user":"'.$isModifiedEN["user"].'", "anonymousIdent":"'.$isModifiedEN["anonymousIdent"].'"}' : false; + $temp['fileModifiedEN'] = false; $temp['fileModifiedLang'] = ( $isModifiedLang ) ? '{"user":"'.$isModifiedLang["user"].'", "anonymousIdent":"'.$isModifiedLang["anonymousIdent"].'"}' : false; } else { $temp['reviewed'] = $a->reviewed; diff --git a/php/RepositoryManager.php b/php/RepositoryManager.php index 7022def0..b4079bf5 100644 --- a/php/RepositoryManager.php +++ b/php/RepositoryManager.php @@ -1,14 +1,5 @@ lock()) { // exec the checkout $rtn = VCSFactory::getInstance()->checkout(); @@ -173,126 +165,7 @@ public function cleanUpBeforeCheckBuild() } - /** - * Update a single folder of the repository to sync our local copy. - */ - public function updateFolder($path) - { - $rf = RepositoryFetcher::getInstance(); - $am = AccountManager::getInstance(); - $project = $am->project; - - // We reset the session var - unset($_SESSION['updateFolder']['newFolders']); - unset($_SESSION['updateFolder']['newFiles']); - - // We search for the first folder ; can be en/ LANG/ or doc-base/ for example - $t = explode("/", $path); - $firstFolder = $t[1]; - - array_shift($t); - array_shift($t); - - $pathWithoutLang = '/' . implode("/", $t).'/'; - - // If we are in the root folder, we have //. We must consider this case. - if( $pathWithoutLang == '//' ) { $pathWithoutLang = '/'; } - - if( $firstFolder == "" ) { - $firstFolder = 'root'; - } - - $lock = new LockFile('project_' . $project . '_' . $firstFolder . '_lock_update_folder'); - - if ($lock->lock()) { - - if( $this->isValidLanguage($firstFolder) ) { - - // This is only for EN and LANG. For others, we don't make any version's comparaison. - // We start be get files & folders in this folder to compare it after the update - $actual = $rf->getFilesByDirectory($path); - $actualFiles = $actualFolders = array(); - - for( $i=0; $i < count($actual); $i++ ) { - // We get files and folders - if( $actual[$i]['type'] === 'folder' ) { - $actualFolders[$actual[$i]['text']] = array( "name"=> $actual[$i]['text'] ); - } else { - $actualFiles[$actual[$i]['text']] = array( "name"=> $actual[$i]['text'], "version"=> "" ); - } - } - // We get versions for this files - while( list($k, $v) = each($actualFiles) ) { - - $file = new File($firstFolder, $pathWithoutLang.$k); - $info = $file->getInfo(); - $actualFiles[$k]['version'] = $info['rev']; - - } - - } - - // We update the repository recursively - VCSFactory::getInstance()->updateSingleFolder($path); - - if( $this->isValidLanguage($firstFolder) ) { - // We throw the revCheck on this folder only if the langue is valide - $this->applyRevCheck($pathWithoutLang, 'update', $firstFolder); - - // We get files under this folder to make comparaison after the update - $now = $rf->getFilesByDirectory($path); - $nowFiles = $nowFolders = array(); - - for( $i=0; $i < count($now); $i++ ) { - // We get all folders & files - if( $now[$i]['type'] === 'folder' ) { - $nowFolders[$now[$i]['text']] = array( "name"=> $now[$i]['text'] ); - } else { - $nowFiles[$now[$i]['text']] = array( "name"=> $now[$i]['text'], "version"=> "" ); - } - } - - // We get versions of this files - while( list($k, $v) = each($nowFiles) ) - { - $file = new File($firstFolder, $pathWithoutLang.$k); - $info = $file->getInfo(); - $nowFiles[$k]['version'] = $info['rev']; - } - - //~ debug(json_encode($nowFiles)); - //~ debug(json_encode($actualFiles)); - - // We search for differences - reset($nowFiles); reset($nowFolders); - while( list($k, $v) = each($nowFiles) ) { - // If the file exist before, and at the same version, we delete it from $nowFiles - if( isset($actualFiles[$k] ) && $actualFiles[$k]['version'] == $v['version'] ) { - unset($nowFiles[$k]); - } - } - while( list($k, $v) = each($nowFolders) ) { - // If the folder exist before, we delete it from $nowFolders - if( isset($actualFolders[$k] ) ) { - unset($nowFolders[$k]); - } - } - - // $nowFolders contains only new folders who don't exist before the update - // and $nowFiles, new files who don't exist before the update or who the version have changed - - // We store this result in session to allow get it if this processus take more than 30 seconds (max execution time) - $_SESSION['updateFolder']['newFolders'] = $nowFolders; - $_SESSION['updateFolder']['newFiles'] = $nowFiles; - } - - } - - $lock->release(); - - return json_encode($_SESSION['updateFolder']); - } /** @@ -823,6 +696,46 @@ public function addPendingDelete($file) ); } + // not tested + public function fastUpdate() + { + if ($changed_files = VCSFactory::getInstance()->fastUpdate()) { + + foreach (array_merge($changed_files['create'], $changed_files['update']) as $path) { + $path = explode('/', $path, 2); + $file = new File($path[0], $path[1]); + + + $tmp = Array($file); + $this->delWork($tmp); + + // We must now insert information into the app for this file + $this->addFileInfo($tmp); + } + foreach ($changed_files['update'] as $path) { + $path = explode('/', $path, 2); + $file = new File($path[0], $path[1]); + + // Delete from work table + $tmp = Array($file); + $this->delWork($tmp); + + // We must now update information into the app for this file + $this->updateFileInfo($tmp); + } + foreach ($changed_files['delete'] as $path) { + $path = explode('/', $path, 2); + $file = new File($path[0], $path[1]); + + // Delete this new file from the fileSystem + @unlink($file->full_new_path); + + // Delete from work table + $this->delWork(array($file)); + } + } + } + /** * Update the VCS for each file we try to commit before start the commit processus. * As it, we ensure all VCS conflict. @@ -833,135 +746,59 @@ public function addPendingDelete($file) */ public function beforeCommitChanges($files, $type) { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - $stack = Array(); - switch($type) { - - case 'new' : - - // For new files, we must ensure that this file is steel non exist into the repository before commit it. - for( $i=0; $i < count($files); $i++ ) { - - VCSFactory::getInstance()->updateSingleFile($files[$i]); + if ($files) { + switch($type) { - if( $files[$i]->exist() ) { - - // This file exist in the repository ! We can't commit it as a new file now. - // We must update this file into the app, and suppress it from this commit process - - // Delete this new file from the fileSystem -//~ @unlink($files[$i]->full_path.'.new'); - - // Delete from work table - $tmp = Array($files[$i]); - - // exclude from commit - $this->delWork($tmp); - - // We must now update information into the app for this new file - $this->updateFileInfo($tmp); - - } else { - // This file still not exist in current respository, we can commit it - $stack[] = $files[$i]; - } - - } + case 'new' : - break; - - case 'update' : - - // For update files, we must ensure that this file haven't been modified since last big update - for( $i=0; $i < count($files); $i++ ) { - - // We get the filemtime for this file to compare with the filemtime after the update. - $oldTime = filemtime($files[$i]->full_path); - - VCSFactory::getInstance()->updateSingleFile($files[$i]); - - if( $files[$i]->exist() ) { - - // If this file haven't been deleted since last update - $newTime = filemtime($files[$i]->full_path); - - - if( $newTime != $oldTime ) { - - // This file have been modified since last update. - // We can't commit our change, otherwise this file will be marked as conflict - // We just update the info for this file and skip it from this commit - - $tmp = array($files[$i]); - - // exclude from commit - $this->delWork($tmp); - - // We must now update information into the app for this file - $this->updateFileInfo($tmp); - - } else { - - // This file haven't been modified since last update. - // We can continue the commit processus for it + // For new files, we must ensure that this file is steel non exist into the repository before commit it. + for( $i=0; $i < count($files); $i++ ) { + if( !$files[$i]->exist() ) { + // This file still not exist in current respository, we can commit it $stack[] = $files[$i]; - } - - } else { - - // Here, we try to update a file which have been deleted since last update - // We delete our .new, and remove all reference for it from the DB - - // Delete this new file from the fileSystem - @unlink($files[$i]->full_new_path); - - // Delete from work table - $this->delWork(array($files[$i])); - } - } - - break; - - case 'delete' : - - // For deleted files, we must ensure that this file is steel exist into the repository before commit it. - for( $i=0; $i < count($files); $i++ ) { + break; - VCSFactory::getInstance()->updateSingleFile($files[$i]); + case 'update' : - if( $files[$i]->exist() ) { + // For update files, we must ensure that this file haven't been modified since last big update + for( $i=0; $i < count($files); $i++ ) { - // This file still exists in current respository, we can commit it for delete - $stack[] = $files[$i]; + // We get the filemtime for this file to compare with the filemtime after the update. + $oldTime = filemtime($files[$i]->full_path); + if( $files[$i]->exist() ) { + // If this file haven't been deleted since last update + $newTime = filemtime($files[$i]->full_path); + if( $newTime == $oldTime ) { + // This file haven't been modified since last update. + // We can continue the commit processus for it + $stack[] = $files[$i]; + } + } - } else { + } - // This file don't exist in the repository ! We can't commit it as a deleted file now. - // We must update this file into the app, and suppress it from this commit process + break; - // Delete from work table - $tmp = array($files[$i]); + case 'delete' : - // exclude from commit - $this->delWork($tmp); + // For deleted files, we must ensure that this file is steel exist into the repository before commit it. + for( $i=0; $i < count($files); $i++ ) { - // Remove this files from db - $this->delFiles($tmp); + if( $files[$i]->exist() ) { + // This file still exists in current respository, we can commit it for delete + $stack[] = $files[$i]; + } } - } - - break; - + break; + } } return $stack; @@ -1140,7 +977,8 @@ public function commitChanges($ids, $log) } } - // Before commit, we need to update this file to find if there haven't been modified since last update process + // Before commit, we need to update all files and find if there haven't been modified since last update process + $this->fastUpdate(); $create_stack = $this->beforeCommitChanges($create_stack, 'new'); $update_stack = $this->beforeCommitChanges($update_stack, 'update'); $delete_stack = $this->beforeCommitChanges($delete_stack, 'delete'); @@ -1277,8 +1115,6 @@ public function clearLocalChange($type, $file) $am = AccountManager::getInstance(); $appConf = $am->appConf; $project = $am->project; - $vcsLogin = $am->vcsLogin; - $anonymousIdent = $am->anonymousIdent; $lang = $file->lang; $path = $file->path; @@ -1588,7 +1424,169 @@ public function updateFileInfo($files) } } } + public function addFileInfo($files) + { + $am = AccountManager::getInstance(); + + foreach ($files as $file) { + + $info = $file->getInfo(); + $size = intval(filesize($file->full_path) / 1024); + $date = filemtime($file->full_path); + + if ($file->lang == 'en') { // en file + // update EN file info + $s = 'INSERT INTO `files` + SET + `xmlid` = "%s", + `revision` = "%s", + `size` = "%s", + `mdate` = "%s", + `project` = "%s", + `lang` = "%s", + `path` = "%s", + `name` = "%s"'; + $params = array( + $info['xmlid'], $info['rev'], $size, $date, $am->project, $file->lang, $file->path, $file->name + ); + $this->conn->query($s, $params); + + // update LANG file info + $s = 'UPDATE `files` + SET + `en_revision` = "%s" + WHERE + `project` = "%s" AND + `lang` != "%s" AND + `path` = "%s" AND + `name` = "%s"'; + $params = array( + $info['rev'], $am->project, $file->lang, $file->path, $file->name + ); + $this->conn->query($s, $params); + + } else { // lang file + + // If this file don't exist in EN, we should skip all this proces + $en = new File('en', $file->path.$file->name); + + if( $en->exist() ) { + + $enInfo = $en->getInfo(); + + $sizeEN = intval(filesize($en->full_path) / 1024); + $dateEN = filemtime($en->full_path); + + $size_diff = $sizeEN - $size; + $date_diff = (intval((time() - $dateEN) / 86400)) + - (intval((time() - $date) / 86400)); + + // update LANG file info + $s = 'INSERT INTO `files` + SET + `xmlid` = "%s", + `revision` = "%s", + `en_revision`= "%s", + `reviewed` = "%s", + `reviewed_maintainer` = "%s", + `size` = "%s", + `mdate` = "%s", + `maintainer` = "%s", + `status` = "%s", + `size_diff` = "%s", + `mdate_diff` = "%s", + `project` = "%s", + `lang` = "%s", + `path` = "%s", + `name` = "%s"'; + $params = array( + $info['xmlid'], + $info['en-rev'], + $enInfo['rev'], + trim($info['reviewed']), + trim($info['reviewed_maintainer']), + $size, + $date, + trim($info['maintainer']), + trim($info['status']), + $size_diff, + $date_diff, + $am->project, + $file->lang, + $file->path, + $file->name + ); + $this->conn->query($s, $params); + + // Run the errorTools under this file + $tmpFile[0]['en_content'] = $en->read(true); + $tmpFile[0]['lang_content'] = $file->read(true); + $tmpFile[0]['lang'] = $file->lang; + $tmpFile[0]['path'] = $file->path; + $tmpFile[0]['name'] = $file->name; + $tmpFile[0]['maintainer'] = $info['maintainer']; + + $errorTools = new ToolsError(); + $errorTools->updateFilesError($tmpFile); + + } else // This file exist only in LANG version, like translation.xml, for example + { + + // update LANG file info + $s = 'INSERT INTO `files` + SET + `xmlid` = "%s", + `revision` = "%s", + `en_revision`= "%s", + `reviewed` = "%s", + `reviewed_maintainer` = "%s", + `size` = "%s", + `mdate` = "%s", + `maintainer` = "%s", + `status` = "%s", + `size_diff` = "%s", + `mdate_diff` = "%s", + `project` = "%s", + `lang` = "%s", + `path` = "%s", + `name` = "%s"'; + $params = array( + $info['xmlid'], + $info['en-rev'], + 0, + trim($info['reviewed']), + trim($info['reviewed_maintainer']), + $size, + $date, + trim($info['maintainer']), + trim($info['status']), + 0, + 0, + $am->project, + $file->lang, + $file->path, + $file->name + ); + $this->conn->query($s, $params); + + // Run the errorTools under this file + // If the EN file don't exist, it's because we have a file witch only exist into LANG, for example, translator.xml + // We fake the EN with the LANG content to fake the errorTools ;) + $tmpFile[0]['en_content'] = $file->read(true); + $tmpFile[0]['lang_content'] = $file->read(true); + $tmpFile[0]['lang'] = $file->lang; + $tmpFile[0]['path'] = $file->path; + $tmpFile[0]['name'] = $file->name; + $tmpFile[0]['maintainer'] = $info['maintainer']; + + $errorTools = new ToolsError(); + $errorTools->updateFilesError($tmpFile); + + } + } + } + } /** * Read the translation's file which hold informations about all translators * and put it into database. diff --git a/php/SaferExec.php b/php/SaferExec.php index efd7bb5f..2329f981 100644 --- a/php/SaferExec.php +++ b/php/SaferExec.php @@ -35,51 +35,4 @@ public static function execMulti(array $command_array, &$output = array(), &$ret } } -class ExecStatement -{ - private $command; - private $args; - - /** - * Represents a shell command to be executed. - * - * The first parameter, $command, should be a format string (eg: the kind of string you pass to printf). - * The directives in that string should correspond to the arguments passed as part of the second parameter, the $args array. - * - * The assumptions about security made here only holds when $command is a static string. If $command is - * even partly derived from user input, any assumptions made about safety and security no longer hold. - */ - public function __construct($command, array $args = array()) - { - $this->command = $command; - - // We validate and escape certain types of input. - $this->args = array(); - foreach ($args as $key => $val) - { - if (is_bool($val) || is_float($val) || is_int($val) || is_null($val)) - $this->args[$key] = $val; - else if (is_string($val)) - $this->args[$key] = escapeshellarg($val); - else if (is_object($val)) - $this->args[$key] = escapeshellarg($val->__toString()); - else - trigger_error('Argument with unexpected type used to construct ExecStatement. It has been omitted from the command string.', E_USER_WARNING); - } - } - public function getCommand() - { - return $this->command; - } - - public function getArgs() - { - return $this->args; - } - - public function __toString() - { - return vsprintf($this->getCommand(), $this->getArgs()); - } -} diff --git a/php/SvnClient.php b/php/SvnClient.php index 2ca71692..2dd6cc9d 100644 --- a/php/SvnClient.php +++ b/php/SvnClient.php @@ -1,6 +1,5 @@ conn->query($s, $params); - + $result = array(); while( $r = $res->fetch_array() ) { $result[$r['lang']]['total'] = $r['total']; $result[$r['lang']]['total_size'] = $r['total_size']; @@ -93,7 +89,7 @@ public function getTransFileCount($lang='all') `files` WHERE `revision` = `en_revision` AND - `revision` != 0 AND + `revision` != "0" AND `project` = "%s" GROUP BY `lang`'; $params = array($project); @@ -107,7 +103,7 @@ public function getTransFileCount($lang='all') WHERE `lang` = "%s" AND `revision` = `en_revision` AND - `revision` != 0 AND + `revision` != "0" AND `project` = "%s"'; $params = array($lang, $project); } @@ -273,7 +269,7 @@ public function computeSummary($lang='all') $summary[0]['nbFiles'] = ( isset($uptodate[$lang]['total']) ) ? $uptodate[$lang]['total'] : 0; $summary[0]['percentFiles'] = ( isset($uptodate[$lang]['total']) ) ? round(($uptodate[$lang]['total']*100)/$nbFiles[$lang]['total'], 2) : 0; $summary[0]['sizeFiles'] = ( !isset($uptodate[$lang]['total_size']) ) ? 0 : $uptodate[$lang]['total_size']; - $summary[0]['percentSize'] = (!isset($uptodate[$lang]['total_size'])) ? 0 : round(($uptodate[$lang]['total_size']*100)/$nbFiles[$lang]['total_size'], 2); + $summary[0]['percentSize'] = (!isset($uptodate[$lang]['total_size']) || $uptodate[$lang]['total_size'] == 0 ) ? 0 : round(($uptodate[$lang]['total_size']*100)/$nbFiles[$lang]['total_size'], 2); $summary[1]['id'] = 2; $summary[1]['libel'] = 'Stale files'; diff --git a/php/TranslatorStatistic.php b/php/TranslatorStatistic.php index fd55c69c..da4c5707 100644 --- a/php/TranslatorStatistic.php +++ b/php/TranslatorStatistic.php @@ -1,8 +1,5 @@ appConf; if (!isset(self::$instance)) { + $appConf = AccountManager::getInstance()->appConf; switch ($appConf['GLOBAL_CONFIGURATION']['vcs.type']) { + case 'git': + self::$instance = GitClient::getInstance(); + break; case 'cvs': - require_once dirname(__FILE__) . '/CvsClient.php'; self::$instance = CvsClient::getInstance(); break; case 'svn': - require_once dirname(__FILE__) . '/SvnClient.php'; self::$instance = SvnClient::getInstance(); break; } diff --git a/php/conf/project.php.ini b/php/conf/project.php.ini index f661983a..e7b019c9 100644 --- a/php/conf/project.php.ini +++ b/php/conf/project.php.ini @@ -17,15 +17,13 @@ project.langadmin.de = "nikic" project.langadmin.ar = "visualmind" project.langadmin.pt_BR = "klaussilveira" -vcs.server.host = "svn.php.net" -vcs.server.repos = "repository/" -vcs.server.path = "repository/phpdoc/modules/doc-all/" -vcs.server.port = 443 +; need to change this in local.php.ini +vcs.server = "https://specialLogin:specialPass@git.php.net/push/playground.git/" vcs.anon.login = vcs.anon.passwd = -vcs.module = "phpdoc-all" +vcs.module = "phpdoc" vcs.karma.file = "https://svn.php.net/viewvc/SVNROOT/global_avail?view=co" vcs.path = "{GLOBAL_CONFIGURATION['data.path']}{PHP['vcs.module']}/" diff --git a/php/controller.php b/php/controller.php index 61f391bc..fe5ed422 100755 --- a/php/controller.php +++ b/php/controller.php @@ -7,8 +7,7 @@ error_reporting(E_ALL); set_time_limit(0); -require_once "./ExtJsController.php"; -require_once "./JsonResponseBuilder.php"; +require_once __DIR__.'/loader.php'; $controller = new ExtJsController(array_merge($_GET, $_POST)); diff --git a/php/loader.php b/php/loader.php new file mode 100755 index 00000000..e704f976 --- /dev/null +++ b/php/loader.php @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/php/utility.php b/php/utility.php index 6639bb97..91bf8354 100644 --- a/php/utility.php +++ b/php/utility.php @@ -1,6 +1,5 @@ Date: Thu, 26 Jan 2012 13:48:10 +0400 Subject: [PATCH 2/4] ignore local.*.ini --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 95ab31e9..f780b759 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ data/ -php/conf/localConf.ini \ No newline at end of file +php/conf/localConf.ini +php/conf/local.*.ini \ No newline at end of file From 445f9a3a5335006f04836d5b21c7c1ef25ebff14 Mon Sep 17 00:00:00 2001 From: Alexander Moskaliov Date: Sat, 11 Feb 2012 15:02:48 +0400 Subject: [PATCH 3/4] fix linending --- php/File.php | 1183 +++++++++++++++++++++++++------------------------- 1 file changed, 591 insertions(+), 592 deletions(-) diff --git a/php/File.php b/php/File.php index e4136f1b..a51035d7 100644 --- a/php/File.php +++ b/php/File.php @@ -1,592 +1,591 @@ -appConf; - $project = AccountManager::getInstance()->project; - - // Security - $path = str_replace('..', '', $path); - $path = str_replace('//', '/', $path); - - $this->lang = $lang = trim($lang, '/'); - $path = trim($path, '.'); - $path = trim($path, '/'); - - // Find if the path is a folder or a file. As it, if the path contains an extension, we assume the path is a file. - // Else, it's a folder. - $path_parts = pathinfo($path); - - if( !isset($path_parts['extension']) ) { - $this->isDir = true; - $this->isFile = false; - $this->name = ''; - $path_parts['dirname'] = isset($path_parts['dirname']) ? $path_parts['dirname'] : ''; - $path = $path_parts['dirname'].'/'.$path_parts['basename']; - } else { - $this->isDir = false; - $this->isFile = true; - $this->name = $path_parts['basename']; - $path = $path_parts['dirname']; - } - - $path = trim($path, '.'); - $path = trim($path, '/'); - $path = trim($path, '.'); - - if (strlen($path) > 0) { - $this->path = "/$path/"; - - $this->full_path = $appConf[$project]['vcs.path'].$lang.'/'.$path.'/'.$this->name; - $this->full_new_path = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/'.$lang.'/'.$path.'/'.$this->name; - - $this->full_path_dir = $appConf[$project]['vcs.path'].$lang.'/'.$path.'/'; - $this->full_new_path_dir = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/'.$lang.'/'.$path.'/'; - - // The fallback file : if the file don't exist, we fallback to the EN file witch should always exist - $this->full_path_fallback = $appConf[$project]['vcs.path'].'en/'.$path.'/'.$this->name; - } else { - $this->path = '/'; - - $this->full_path = $appConf[$project]['vcs.path'].$lang.'/'.$this->name; - $this->full_new_path = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/'.$lang.'/'.$this->name; - - $this->full_path_dir = $appConf[$project]['vcs.path'].$lang.'/'; - $this->full_new_path_dir = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/'.$lang.'/'; - - $this->full_path_fallback = $appConf[$project]['vcs.path'].'en/'.$this->name; - } - - $this->conn = DBConnection::getInstance(); - } - - public function exist() - { - if( $this->isDir ) return is_dir($this->full_path_dir); - else return is_file($this->full_path); - } - - - /** - * Translate the content of a file with Google Translate API. - * - * @return The automatic translation. - */ - public function translate() - { - // We must check if the file exist. - // For example, when we start a translation, save it, and then open it from work in progress module, the path don't exist and we must use the fallback path for translation - - $originalContent = ( is_file($this->full_path) ) ? file_get_contents($this->full_path) : file_get_contents($this->full_path_fallback); - - // We search for new line caracters and mark it ! (Google API delete new line) - $originalContent = str_replace("\n", "[@]", $originalContent); - - $lang = AccountManager::getInstance()->vcsLang; - - $translation = false; - $gt = new Gtranslate; - $gt->setRequestType('curl'); - $translation = $gt->translate('en', $lang, $originalContent); - - // Replace new line mark - $translation = str_replace("[@]", "\n", $translation); - - // Few substitutions - $translation = str_replace("&" , "&", $translation); - $translation = str_replace("& ", "&", $translation); - $translation = str_replace("'" , "'", $translation); - $translation = str_replace(""", '"', $translation); - $translation = str_replace("<" , '<', $translation); - $translation = str_replace(">" , '>', $translation); - - // CLeanUp entities. Google return it like this : & Reftitle.parameters;. We convert it like this : &reftitle.parameters; - $translation = preg_replace_callback("/(&)\s(.)(.[^;]*?)(;)/s", - create_function( - '$matches', - 'return $matches[1].strtolower($matches[2]).$matches[3].$matches[4];' - ), - $translation); - - // We remove extra space after :: operator - $translation = preg_replace("/(\w+)(::)(\s)(\w+)/s", "$1$2$4", $translation); - - // We delete space into tab like this - $translation = preg_replace("/(<\/\s(\w+[^>]*)>)/s", "", $translation); - - // We delete space just after an open tag, and just before a close tag, like this foo - $translation = preg_replace("/(<(\w+[^>]*)>)(\s?)(.[^>]*?)(\s?)(<\/(\\2)>)/s", "<$2>$4", $translation); - - return $translation; - } - - /** - * Read the content of a file. - * - * @param $readOriginal true to read the original content of the file, false to read the modified file (if any). By default, false. - * @return The content of the file. - */ - public function read($readOriginal=false) - { - $isModified = $this->isModified(); - $isModified = (bool) $isModified; - - $path = ($readOriginal || !$isModified) - ? $this->full_path - : $this->full_new_path; - - if( is_file($path) ) { - return file_get_contents($path); - } elseif( is_file($this->full_path_fallback) ) { - // usefull for a patch from the FNT module. - return file_get_contents($this->full_path_fallback); - } else { - return false; - } - - } - - /** - * Save a file after modification. - * - * @param $content The new content. - * @return The path to the new file successfully created. - */ - public function save($content) - { - - // Ensure the folder exist. - if( ! is_dir($this->full_new_path_dir) ) { - mkdir( $this->full_new_path_dir, 0777, true ); - } - - // Open in w+ mode - $h = @fopen($this->full_new_path, 'w+'); - if( $h ) { - fwrite($h, $content); - fclose($h); - return $this->full_new_path; - } else { - return array( - 'state' => false - ); - } - } - - /** - * Create a new folder locally & register it to pendingCommit - * If $path is provided, it is used to create the according path. Else, we use the current folder's path. - * - * @param string $path The path to create. By default, we use the current path. - * @return boolean TRUE if the path have been created successfully, FALSE otherwise. - */ - public function createFolder($path=false) - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - if( !$path ) { - $path = $this->path; - } - - $parentFolder = dirname($path); - if(!is_dir($parentFolder)) { - $this->createFolder($parentFolder); - } - - // We create this folder localy - if( ! @mkdir($appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/'.$this->lang.'/'.$path, 0777, true) ) { - return false; - } - - // We register this new folder to be committed - $obj = (object) array('lang' => $this->lang, 'path' => $path, 'name' => '-'); - RepositoryManager::getInstance()->addProgressWork($obj, '-', '-', '-', '-', '-', 'new'); - - return true; - - } - - /** - * Check if the path of this $file exist or not. If not, try to create it - * - * @return true - */ - public function folderExist() - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - if( !is_dir($this->full_new_path_dir) ) { - $this->createFolder(); - } - - return true; - } - - /** - * Parse an array of string to find all attributes in form of (key=value) pairs. - * - * @param $key_value_pairs Array of key-value pair strings to be parsed. - * @return An associated array whos key is the name of the attribute, and value, the value of the attribute. - */ - public function parseAttribute($key_value_pairs) - { - $processed = array(); - - foreach ($key_value_pairs as $pair) { - - // Get attr name and values - $attributes = array(); - preg_match_all('!(.+)=\\s*(["\'])\\s*(.+)\\2!U', $pair, $attributes); - - // Assign all attributes to one associative array - $key_value = array(); - foreach ($attributes[1] as $k => $name) { - $key_value[trim($name)] = trim($attributes[3][$k]); - } - // Collect in order of tags received - $processed[] = $key_value; - } - - return $processed; - } - - /** - * Test if the file is a modified file. - * - * @return Mixed FALSE if the file haven't been modified, otherwise, some information about the user how have modified it. - */ - public function isModified() - { - $am = AccountManager::getInstance(); - $project = $am->project; - - $s = 'SELECT - `id` as fidDB, - `user`, - `anonymousIdent`, - `module` as fromModule, - `type` as ftype - FROM - `work` - WHERE - `project` = "%s" AND - `lang`="%s" AND - `path`="%s" AND - `name`="%s"'; - $params = array( - $project, - $this->lang, - $this->path, - $this->name - ); - - $r = $this->conn->query($s, $params); - - if( $r->num_rows == 0 ) { - return false; - } else { - $a = $r->fetch_assoc(); - $a['isAnonymous'] = $am->anonymous($a['user'], $a['anonymousIdent']); - return json_encode($a); - } - } - - /** - * Get encoding of a file, regarding his XML's header. - * - * @param $content The content of the file - * @return The charset as a string. - */ - public function getEncoding($content=false) - { - if (!$content) { - $content = @file_get_contents($this->full_path); - } - - $content = preg_replace('/\\s+/', ' ', $content); - - $match = array(); - preg_match('!<\?xml(.+)\?>!U', $content, $match); - $xmlinfo = $this->parseAttribute($match); - - $charset = isset($xmlinfo[1]['encoding']) - ? strtolower($xmlinfo[1]['encoding']) - : 'iso-8859-1'; - - return $charset; - } - - /** - * Get the information from the content of a file. - * - * @param $content The content of the file. - * @return An associated array of informations. - */ - public function getInfo($content=false) - { - if (!$content) { - $content = file_get_contents($this->full_path); - } - - $info = array( - 'rev' => 0, - 'en-rev' => 0, - 'maintainer' => 'NULL', - 'reviewed' => 'NULL', - 'reviewed_maintainer' => 'NULL', - 'status' => '-', - 'xmlid' => 'NULL', - 'content' => $content - ); - - // revision tag - $match = array(); - preg_match('//', $content, $match); - if (!empty($match)) { - $info['rev'] = $match[1]; - } - - // Rev tag - $match = array(); - preg_match('//U', $content, $match); - if (!empty($match)) { - $info['en-rev'] = ($match[1] == 'n/a') ? 0 : $match[1]; - $info['maintainer'] = $match[4]; - $info['status'] = $match[5]; - } - - // Reviewed tag - $match = array(); - if (preg_match('//i', $content, $match)) { - $info['reviewed'] = ( isset($match[1]) ) ? trim($match[1]) : NULL; - $info['reviewed_maintainer'] = ( isset($match[3]) ) ? trim($match[3]) : NULL; - } - - // All xmlid - $match = array(); - if (preg_match_all('/xml:id=("|\')(.*?)("|\')/', $content, $match)) { - $info['xmlid'] = implode('|',$match[2]); - } - - return $info; - } - - /** - * Get a raw diff between a file and its modified file. - * - * @param $patchID If set, indicate the ID of the patch from witch we have to retrieve all files diff - * @return The diff of the file with its modified version. - */ - public function rawDiff($patchID=false) - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - if( $patchID ) { - - $return=''; - $output = array(); - - $patchFiles = RepositoryManager::getInstance()->getPatchFilesByID($patchID); - for( $i=0; $i < count($patchFiles); $i++ ) - { - - $pathFileOrigin = $appConf[$project]['vcs.path'] . $patchFiles[$i]->lang . $patchFiles[$i]->path . $patchFiles[$i]->name; - $pathFileModified = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/' . $patchFiles[$i]->lang . $patchFiles[$i]->path . $patchFiles[$i]->name; - - $commands = array( - new ExecStatement('diff -uN %s %s', array($pathFileOrigin, $pathFileModified)) - ); - - $trial_threshold = 3; - while ($trial_threshold-- > 0) - { - $_output = array(); - SaferExec::execMulti($commands, $_output); - if (strlen(trim(implode('', $_output))) != 0) break; - } - - $output = array_merge($output, $_output); - } - - return implode("\r\n", $output); - - } else { - - $pathFileOrigin = $appConf[$project]['vcs.path'] . $this->lang . $this->path . $this->name; - $pathFileModified = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/' . $this->lang . $this->path . $this->name; - - $commands = array( - new ExecStatement('diff -uN %s %s', array($pathFileOrigin, $pathFileModified)) - ); - - $output = array(); - SaferExec::execMulti($commands, $output); - - return implode("\r\n", $output); - } - } - - /** - * Get the diff of a file with his modified version. - * - * @param $rev1 First revison. - * @param $rev2 Second revision. - * @return The diff a the file with his modified version, as HTML, ready to be display. - */ - public function Diff($type, $options) - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - $return = ''; - $output = array(); - - if( $type == 'vcs' ) { - - $output = VCSFactory::getInstance()->diff( - $this->lang.$this->path, - $this->name, $options['rev1'], $options['rev2'] - ); - - $return = $this->DiffGenHTMLOutput($output); - - } elseif( $type == 'file' || $type == 'patch' ) { - - //$ext = ( $options['type'] == 'patch' ) ? '.' . $options['uniqID'] . '.patch' : '.new'; - - // If this patch is for new file, we only display "This is a new file." - if( $type == 'patch' && !is_file($appConf[$project]['vcs.path'].$this->lang.$this->path.$this->name) ) { - return '
This is a new file.
'; - } else { - - if( $options['patchID'] == '' ) - { - - $pathFileOrigin = $appConf[$project]['vcs.path'] . $this->lang . $this->path . $this->name; - $pathFileModified = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/' . $this->lang . $this->path . $this->name; - - $commands = array( - new ExecStatement('diff -uN %s %s', array($pathFileOrigin, $pathFileModified)) - ); - - $trial_threshold = 3; - while ($trial_threshold-- > 0) { - $output = array(); - SaferExec::execMulti($commands, $output); - if (strlen(trim(implode('', $output))) != 0) break; - } - - $return = $this->DiffGenHTMLOutput($output); - - } - else - { - // We get all files from this patch - $patchFiles = RepositoryManager::getInstance()->getPatchFilesByID($options['patchID']); - - for( $i=0; $i < count($patchFiles); $i++ ) - { - - $pathFileOrigin = $appConf[$project]['vcs.path'] . $patchFiles[$i]->lang . $patchFiles[$i]->path . $patchFiles[$i]->name; - $pathFileModified = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/' . $patchFiles[$i]->lang . $patchFiles[$i]->path . $patchFiles[$i]->name; - - $commands = array( - new ExecStatement('diff -uN %s %s', array($pathFileOrigin, $pathFileModified)) - ); - - $trial_threshold = 3; - while ($trial_threshold-- > 0) - { - $output = array(); - SaferExec::execMulti($commands, $output); - if (strlen(trim(implode('', $output))) != 0) break; - } - - $return .= $this->DiffGenHTMLOutput($output); - } - } - } - } - - return $return; - } - - public function DiffGenHTMLOutput($content) { - - $header = array_shift($content)."
".array_shift($content); - $return = ' - - - - '; - - $classes = array( - '+' => 'ins', - '-' => 'del', - ' ' => '', - '@' => 'line' - ); - $first = true; - foreach ($content as $string) { - if ($string[0] == '@' && !$first) $return .= ''; - $first = false; - $return .= ''; - } - $return .= ''; - $return .= '
'.$header.'
 
'.str_replace(' ', ' ', htmlentities($string, ENT_QUOTES, 'UTF-8')).'
 
'; - - return $return; - } - - /** - * Get the image content. - * - * @return An associative array with 'content-type' and 'content' keys - */ - public function getImageContent() - { - $t = explode('.', $this->full_path); - - $return['content-type'] = 'image/'.$t[count($t)-1]; - $return['content'] = file_get_contents($this->full_path); - - return $return; - } -} - -?> +appConf; + $project = AccountManager::getInstance()->project; + + // Security + $path = str_replace('..', '', $path); + $path = str_replace('//', '/', $path); + + $this->lang = $lang = trim($lang, '/'); + $path = trim($path, '.'); + $path = trim($path, '/'); + + // Find if the path is a folder or a file. As it, if the path contains an extension, we assume the path is a file. + // Else, it's a folder. + $path_parts = pathinfo($path); + + if( !isset($path_parts['extension']) ) { + $this->isDir = true; + $this->isFile = false; + $this->name = ''; + $path_parts['dirname'] = isset($path_parts['dirname']) ? $path_parts['dirname'] : ''; + $path = $path_parts['dirname'].'/'.$path_parts['basename']; + } else { + $this->isDir = false; + $this->isFile = true; + $this->name = $path_parts['basename']; + $path = $path_parts['dirname']; + } + + $path = trim($path, '.'); + $path = trim($path, '/'); + $path = trim($path, '.'); + + if (strlen($path) > 0) { + $this->path = "/$path/"; + + $this->full_path = $appConf[$project]['vcs.path'].$lang.'/'.$path.'/'.$this->name; + $this->full_new_path = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/'.$lang.'/'.$path.'/'.$this->name; + + $this->full_path_dir = $appConf[$project]['vcs.path'].$lang.'/'.$path.'/'; + $this->full_new_path_dir = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/'.$lang.'/'.$path.'/'; + + // The fallback file : if the file don't exist, we fallback to the EN file witch should always exist + $this->full_path_fallback = $appConf[$project]['vcs.path'].'en/'.$path.'/'.$this->name; + } else { + $this->path = '/'; + + $this->full_path = $appConf[$project]['vcs.path'].$lang.'/'.$this->name; + $this->full_new_path = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/'.$lang.'/'.$this->name; + + $this->full_path_dir = $appConf[$project]['vcs.path'].$lang.'/'; + $this->full_new_path_dir = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/'.$lang.'/'; + + $this->full_path_fallback = $appConf[$project]['vcs.path'].'en/'.$this->name; + } + + $this->conn = DBConnection::getInstance(); + } + + public function exist() + { + if( $this->isDir ) return is_dir($this->full_path_dir); + else return is_file($this->full_path); + } + + + /** + * Translate the content of a file with Google Translate API. + * + * @return The automatic translation. + */ + public function translate() + { + // We must check if the file exist. + // For example, when we start a translation, save it, and then open it from work in progress module, the path don't exist and we must use the fallback path for translation + + $originalContent = ( is_file($this->full_path) ) ? file_get_contents($this->full_path) : file_get_contents($this->full_path_fallback); + + // We search for new line caracters and mark it ! (Google API delete new line) + $originalContent = str_replace("\n", "[@]", $originalContent); + + $lang = AccountManager::getInstance()->vcsLang; + + $translation = false; + $gt = new Gtranslate; + $gt->setRequestType('curl'); + $translation = $gt->translate('en', $lang, $originalContent); + + // Replace new line mark + $translation = str_replace("[@]", "\n", $translation); + + // Few substitutions + $translation = str_replace("&" , "&", $translation); + $translation = str_replace("& ", "&", $translation); + $translation = str_replace("'" , "'", $translation); + $translation = str_replace(""", '"', $translation); + $translation = str_replace("<" , '<', $translation); + $translation = str_replace(">" , '>', $translation); + + // CLeanUp entities. Google return it like this : & Reftitle.parameters;. We convert it like this : &reftitle.parameters; + $translation = preg_replace_callback("/(&)\s(.)(.[^;]*?)(;)/s", + create_function( + '$matches', + 'return $matches[1].strtolower($matches[2]).$matches[3].$matches[4];' + ), + $translation); + + // We remove extra space after :: operator + $translation = preg_replace("/(\w+)(::)(\s)(\w+)/s", "$1$2$4", $translation); + + // We delete space into tab like this + $translation = preg_replace("/(<\/\s(\w+[^>]*)>)/s", "", $translation); + + // We delete space just after an open tag, and just before a close tag, like this foo + $translation = preg_replace("/(<(\w+[^>]*)>)(\s?)(.[^>]*?)(\s?)(<\/(\\2)>)/s", "<$2>$4", $translation); + + return $translation; + } + + /** + * Read the content of a file. + * + * @param $readOriginal true to read the original content of the file, false to read the modified file (if any). By default, false. + * @return The content of the file. + */ + public function read($readOriginal=false) + { + $isModified = $this->isModified(); + $isModified = (bool) $isModified; + + $path = ($readOriginal || !$isModified) + ? $this->full_path + : $this->full_new_path; + + if( is_file($path) ) { + return file_get_contents($path); + } elseif( is_file($this->full_path_fallback) ) { + // usefull for a patch from the FNT module. + return file_get_contents($this->full_path_fallback); + } else { + return false; + } + + } + + /** + * Save a file after modification. + * + * @param $content The new content. + * @return The path to the new file successfully created. + */ + public function save($content) + { + + // Ensure the folder exist. + if( ! is_dir($this->full_new_path_dir) ) { + mkdir( $this->full_new_path_dir, 0777, true ); + } + + // Open in w+ mode + $h = @fopen($this->full_new_path, 'w+'); + if( $h ) { + fwrite($h, $content); + fclose($h); + return $this->full_new_path; + } else { + return array( + 'state' => false + ); + } + } + + /** + * Create a new folder locally & register it to pendingCommit + * If $path is provided, it is used to create the according path. Else, we use the current folder's path. + * + * @param string $path The path to create. By default, we use the current path. + * @return boolean TRUE if the path have been created successfully, FALSE otherwise. + */ + public function createFolder($path=false) + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + if( !$path ) { + $path = $this->path; + } + + $parentFolder = dirname($path); + if(!is_dir($parentFolder)) { + $this->createFolder($parentFolder); + } + + // We create this folder localy + if( ! @mkdir($appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/'.$this->lang.'/'.$path, 0777, true) ) { + return false; + } + + // We register this new folder to be committed + $obj = (object) array('lang' => $this->lang, 'path' => $path, 'name' => '-'); + RepositoryManager::getInstance()->addProgressWork($obj, '-', '-', '-', '-', '-', 'new'); + + return true; + + } + + /** + * Check if the path of this $file exist or not. If not, try to create it + * + * @return true + */ + public function folderExist() + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + if( !is_dir($this->full_new_path_dir) ) { + $this->createFolder(); + } + + return true; + } + + /** + * Parse an array of string to find all attributes in form of (key=value) pairs. + * + * @param $key_value_pairs Array of key-value pair strings to be parsed. + * @return An associated array whos key is the name of the attribute, and value, the value of the attribute. + */ + public function parseAttribute($key_value_pairs) + { + $processed = array(); + + foreach ($key_value_pairs as $pair) { + + // Get attr name and values + $attributes = array(); + preg_match_all('!(.+)=\\s*(["\'])\\s*(.+)\\2!U', $pair, $attributes); + + // Assign all attributes to one associative array + $key_value = array(); + foreach ($attributes[1] as $k => $name) { + $key_value[trim($name)] = trim($attributes[3][$k]); + } + // Collect in order of tags received + $processed[] = $key_value; + } + + return $processed; + } + + /** + * Test if the file is a modified file. + * + * @return Mixed FALSE if the file haven't been modified, otherwise, some information about the user how have modified it. + */ + public function isModified() + { + $am = AccountManager::getInstance(); + $project = $am->project; + + $s = 'SELECT + `id` as fidDB, + `user`, + `anonymousIdent`, + `module` as fromModule, + `type` as ftype + FROM + `work` + WHERE + `project` = "%s" AND + `lang`="%s" AND + `path`="%s" AND + `name`="%s"'; + $params = array( + $project, + $this->lang, + $this->path, + $this->name + ); + + $r = $this->conn->query($s, $params); + + if( $r->num_rows == 0 ) { + return false; + } else { + $a = $r->fetch_assoc(); + $a['isAnonymous'] = $am->anonymous($a['user'], $a['anonymousIdent']); + return json_encode($a); + } + } + + /** + * Get encoding of a file, regarding his XML's header. + * + * @param $content The content of the file + * @return The charset as a string. + */ + public function getEncoding($content=false) + { + if (!$content) { + $content = @file_get_contents($this->full_path); + } + + $content = preg_replace('/\\s+/', ' ', $content); + + $match = array(); + preg_match('!<\?xml(.+)\?>!U', $content, $match); + $xmlinfo = $this->parseAttribute($match); + + $charset = isset($xmlinfo[1]['encoding']) + ? strtolower($xmlinfo[1]['encoding']) + : 'iso-8859-1'; + + return $charset; + } + + /** + * Get the information from the content of a file. + * + * @param $content The content of the file. + * @return An associated array of informations. + */ + public function getInfo($content=false) + { + if (!$content) { + $content = file_get_contents($this->full_path); + } + + $info = array( + 'rev' => 0, + 'en-rev' => 0, + 'maintainer' => 'NULL', + 'reviewed' => 'NULL', + 'reviewed_maintainer' => 'NULL', + 'status' => '-', + 'xmlid' => 'NULL', + 'content' => $content + ); + + // revision tag + $match = array(); + preg_match('//', $content, $match); + if (!empty($match)) { + $info['rev'] = $match[1]; + } + + // Rev tag + $match = array(); + preg_match('//U', $content, $match); + if (!empty($match)) { + $info['en-rev'] = ($match[1] == 'n/a') ? 0 : $match[1]; + $info['maintainer'] = $match[4]; + $info['status'] = $match[5]; + } + + // Reviewed tag + $match = array(); + if (preg_match('//i', $content, $match)) { + $info['reviewed'] = ( isset($match[1]) ) ? trim($match[1]) : NULL; + $info['reviewed_maintainer'] = ( isset($match[3]) ) ? trim($match[3]) : NULL; + } + + // All xmlid + $match = array(); + if (preg_match_all('/xml:id=("|\')(.*?)("|\')/', $content, $match)) { + $info['xmlid'] = implode('|',$match[2]); + } + + return $info; + } + + /** + * Get a raw diff between a file and its modified file. + * + * @param $patchID If set, indicate the ID of the patch from witch we have to retrieve all files diff + * @return The diff of the file with its modified version. + */ + public function rawDiff($patchID=false) + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + if( $patchID ) { + + $output = array(); + + $patchFiles = RepositoryManager::getInstance()->getPatchFilesByID($patchID); + for( $i=0; $i < count($patchFiles); $i++ ) + { + + $pathFileOrigin = $appConf[$project]['vcs.path'] . $patchFiles[$i]->lang . $patchFiles[$i]->path . $patchFiles[$i]->name; + $pathFileModified = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/' . $patchFiles[$i]->lang . $patchFiles[$i]->path . $patchFiles[$i]->name; + + $commands = array( + new ExecStatement('diff -uN %s %s', array($pathFileOrigin, $pathFileModified)) + ); + + $trial_threshold = 3; + while ($trial_threshold-- > 0) + { + $_output = array(); + SaferExec::execMulti($commands, $_output); + if (strlen(trim(implode('', $_output))) != 0) break; + } + + $output = array_merge($output, $_output); + } + + return implode("\r\n", $output); + + } else { + + $pathFileOrigin = $appConf[$project]['vcs.path'] . $this->lang . $this->path . $this->name; + $pathFileModified = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/' . $this->lang . $this->path . $this->name; + + $commands = array( + new ExecStatement('diff -uN %s %s', array($pathFileOrigin, $pathFileModified)) + ); + + $output = array(); + SaferExec::execMulti($commands, $output); + + return implode("\r\n", $output); + } + } + + /** + * Get the diff of a file with his modified version. + * + * @param $rev1 First revison. + * @param $rev2 Second revision. + * @return The diff a the file with his modified version, as HTML, ready to be display. + */ + public function Diff($type, $options) + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + $return = ''; + $output = array(); + + if( $type == 'vcs' ) { + + $output = VCSFactory::getInstance()->diff( + $this->lang.$this->path, + $this->name, $options['rev1'], $options['rev2'] + ); + + $return = $this->DiffGenHTMLOutput($output); + + } elseif( $type == 'file' || $type == 'patch' ) { + + //$ext = ( $options['type'] == 'patch' ) ? '.' . $options['uniqID'] . '.patch' : '.new'; + + // If this patch is for new file, we only display "This is a new file." + if( $type == 'patch' && !is_file($appConf[$project]['vcs.path'].$this->lang.$this->path.$this->name) ) { + return '
This is a new file.
'; + } else { + + if( $options['patchID'] == '' ) + { + + $pathFileOrigin = $appConf[$project]['vcs.path'] . $this->lang . $this->path . $this->name; + $pathFileModified = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/' . $this->lang . $this->path . $this->name; + + $commands = array( + new ExecStatement('diff -uN %s %s', array($pathFileOrigin, $pathFileModified)) + ); + + $trial_threshold = 3; + while ($trial_threshold-- > 0) { + $output = array(); + SaferExec::execMulti($commands, $output); + if (strlen(trim(implode('', $output))) != 0) break; + } + + $return = $this->DiffGenHTMLOutput($output); + + } + else + { + // We get all files from this patch + $patchFiles = RepositoryManager::getInstance()->getPatchFilesByID($options['patchID']); + + for( $i=0; $i < count($patchFiles); $i++ ) + { + + $pathFileOrigin = $appConf[$project]['vcs.path'] . $patchFiles[$i]->lang . $patchFiles[$i]->path . $patchFiles[$i]->name; + $pathFileModified = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/' . $patchFiles[$i]->lang . $patchFiles[$i]->path . $patchFiles[$i]->name; + + $commands = array( + new ExecStatement('diff -uN %s %s', array($pathFileOrigin, $pathFileModified)) + ); + + $trial_threshold = 3; + while ($trial_threshold-- > 0) + { + $output = array(); + SaferExec::execMulti($commands, $output); + if (strlen(trim(implode('', $output))) != 0) break; + } + + $return .= $this->DiffGenHTMLOutput($output); + } + } + } + } + + return $return; + } + + public function DiffGenHTMLOutput($content) { + + $header = array_shift($content)."
".array_shift($content); + $return = '
+ + + + '; + + $classes = array( + '+' => 'ins', + '-' => 'del', + ' ' => '', + '@' => 'line' + ); + $first = true; + foreach ($content as $string) { + if ($string[0] == '@' && !$first) $return .= ''; + $first = false; + $return .= ''; + } + $return .= ''; + $return .= '
'.$header.'
 
'.str_replace(' ', ' ', htmlentities($string, ENT_QUOTES, 'UTF-8')).'
 
'; + + return $return; + } + + /** + * Get the image content. + * + * @return An associative array with 'content-type' and 'content' keys + */ + public function getImageContent() + { + $t = explode('.', $this->full_path); + + $return['content-type'] = 'image/'.$t[count($t)-1]; + $return['content'] = file_get_contents($this->full_path); + + return $return; + } +} + +?> From 910ba010b75fdb4f5abd910608b67b60ca2606bd Mon Sep 17 00:00:00 2001 From: Alexander Moskaliov Date: Sun, 19 Feb 2012 19:11:38 +0400 Subject: [PATCH 4/4] fix EOL --- js/ExtJs/ext-all-debug-w-comments.js | 10 +- js/ExtJs/ext-all-debug.js | 2 +- js/ExtJs/src/error-checking.js | 714 +-- js/ExtJs/src/locale/ext-lang-am.js | 706 +-- .../widgets/layout/box/ScrollerOverflow.js | 10 +- js/locale/ar.js | 1368 +++--- js/main-all-debug.js | 3942 +++++++-------- js/ui/cmp/EditorConf.js | 2892 +++++------ js/ux/codemirror2/mode/verilog/verilog.js | 388 +- .../main_specific/Ext.ux.Notification.js | 182 +- .../main_specific/Ext.ux.SlidingTabPanel.js | 416 +- .../main_specific/Ext.ux.grid.GridSummary.js | 452 +- php/AccountManager.php | 1442 +++--- php/Config.php | 208 +- php/CvsClient.php | 576 +-- php/DBConnection.php | 148 +- php/ExecStatement.php | 98 +- php/JsonResponseBuilder.php | 102 +- php/LogManager.php | 468 +- php/PreviewFile.php | 292 +- php/RepositoryFetcher.php | 2676 +++++----- php/RepositoryManager.php | 4336 ++++++++--------- php/ToolsXmllint.php | 228 +- php/TranslationStatistic.php | 604 +-- php/TranslatorStatistic.php | 730 +-- php/loader.php | 22 +- php/utility.php | 140 +- 27 files changed, 11576 insertions(+), 11576 deletions(-) diff --git a/js/ExtJs/ext-all-debug-w-comments.js b/js/ExtJs/ext-all-debug-w-comments.js index fde95ef9..bb35cb83 100644 --- a/js/ExtJs/ext-all-debug-w-comments.js +++ b/js/ExtJs/ext-all-debug-w-comments.js @@ -24756,11 +24756,11 @@ Ext.layout.boxOverflow.Scroller = Ext.extend(Ext.layout.boxOverflow.None, { Ext.layout.boxOverflow.scroller = Ext.layout.boxOverflow.Scroller; -/** - * @class Ext.layout.boxOverflow.VerticalScroller - * @extends Ext.layout.boxOverflow.Scroller - * Description - */ +/** + * @class Ext.layout.boxOverflow.VerticalScroller + * @extends Ext.layout.boxOverflow.Scroller + * Description + */ Ext.layout.boxOverflow.VerticalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, { scrollIncrement: 75, wheelIncrement : 2, diff --git a/js/ExtJs/ext-all-debug.js b/js/ExtJs/ext-all-debug.js index 00231c85..7e8fc569 100644 --- a/js/ExtJs/ext-all-debug.js +++ b/js/ExtJs/ext-all-debug.js @@ -15777,7 +15777,7 @@ Ext.layout.boxOverflow.Scroller = Ext.extend(Ext.layout.boxOverflow.None, { Ext.layout.boxOverflow.scroller = Ext.layout.boxOverflow.Scroller; - + Ext.layout.boxOverflow.VerticalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, { scrollIncrement: 75, wheelIncrement : 2, diff --git a/js/ExtJs/src/error-checking.js b/js/ExtJs/src/error-checking.js index 80f65139..f96d3fe8 100644 --- a/js/ExtJs/src/error-checking.js +++ b/js/ExtJs/src/error-checking.js @@ -4,361 +4,361 @@ * licensing@sencha.com * http://www.sencha.com/license */ -Ext.ns('Ext.debug'); -Ext.debug.Assistant = function(){ - var enabled = true; - - return { - enable: function(){ - enabled = true; - }, - - disable: function(){ - enabled = false; - }, - - init : function(classes){ - var klass, - intercept = false, - fn, - method; - Ext.each(classes, function(cls){ - if(this.namespaceExists(cls.name)){ - klass = this.getClass(cls.name); - method = cls.instance ? this.addInstanceCheck : this.addPrototypeCheck; - Ext.each(cls.checks, function(check){ - intercept = check.intercept == true; - fn = method.call(this, klass, check.name, check.fn, check.intercept == true); - if(check.after){ - check.after(fn); - } - }, this); - } - }, this); - }, - - namespaceExists: function(name){ - var parent = window, - exists = true; - - Ext.each(name.split('.'), function(n){ - if(!Ext.isDefined(parent[n])){ - exists = false; - return false; - } - parent = parent[n]; - }); - return exists; - }, - - getClass : function(name){ - var parent = window; - Ext.each(name.split('.'), function(n){ - parent = parent[n]; - }); - return parent; - }, - - warn: function(){ - if(enabled && window.console){ - console.warn.apply(console, arguments); - } - }, - - error: function(){ - if(enabled && window.console){ - console.error.apply(console, arguments); - } - }, - - addPrototypeCheck : function(cls, method, fn, intercept){ - return (cls.prototype[method] = cls.prototype[method][intercept ? 'createInterceptor' : 'createSequence'](fn)); - }, - - addInstanceCheck : function(cls, method, fn, intercept){ - return (cls[method] = cls[method][intercept ? 'createInterceptor' : 'createSequence'](fn)); - } - }; -}(); - -(function(){ - var A = Ext.debug.Assistant, - cls = []; - - cls.push({ - name: 'Ext.util.Observable', - checks: [{ - name: 'addListener', - intercept: true, - fn: function(eventName, fn){ - if(typeof eventName == 'object'){ - var ev, o; - for(ev in eventName){ - if(!this.filterOptRe.test(ev)){ - o = eventName[ev]; - o = o && o.fn ? o.fn : o; - if(!Ext.isFunction(o)){ - A.error('Non function passed to event listener', this, ev); - return false; - } - } - } - }else{ - if(!Ext.isFunction(fn)){ - A.error('Non function passed to event listener', this, eventName); - } - } - }, - after: function(method){ - Ext.util.Observable.prototype.on = method; - } - }] - }); - - cls.push({ - name: 'Ext.Component', - checks: [{ - name: 'render', - intercept: true, - fn: function(container, position){ - if(!container && !this.el){ - A.error('Unable to render to container', this, container); - } - - if(this.contentEl){ - var el = Ext.getDom(this.contentEl); - if(!el){ - A.error('Specified contentEl does not exist', this, this.contentEl); - return false; - } - } - } - }] - }); - - cls.push({ - name: 'Ext.Container', - checks: [{ - name: 'onBeforeAdd', - intercept: true, - fn: function(c){ - if(c.isDestroyed){ - A.warn('Adding destroyed component to container', c, this); - } - if(c.renderTo){ - A.warn('Using renderTo while adding an item to a Container. You should use the add() method or put the item in the items configuration', c, this); - } - if(c.applyTo){ - A.warn('Using applyTo while adding an item to a Container. You should use the add() method or put the item in the items configuration', c, this); - } - - var type = this.layout.type; - if(type == 'container' || type == 'auto'){ - A.warn('A non sizing layout is being used in a container that has child components. This means the child components will not be sized.', this); - } - } - },{ - name: 'lookupComponent', - intercept: true, - fn: function(c){ - var valid = true; - if(Ext.isEmpty(c)){ - valid = false; - } - if(Ext.isString(c)){ - c = Ext.ComponentMgr.get(comp); - valid = !Ext.isEmpty(c); - } - if(!valid){ - A.error('Adding invalid component to container', this, c); - return false; - } - } - }] - }); - - cls.push({ - name: 'Ext.DataView', - checks: [{ - name: 'initComponent', - fn: function(){ - if(!this.itemSelector){ - A.error('No itemSelector specified', this); - } - } - },{ - name: 'afterRender', - fn: function(){ - if(!this.store){ - A.error('No store attached to DataView', this); - } - } - }] - }); - - cls.push({ - name: 'Ext.Window', - checks: [{ - name: 'show', - intercept: true, - fn: function(){ - if(this.isDestroyed){ - A.error('Trying to show a destroyed window. If you want to reuse the window, look at the closeAction configuration.', this); - return false; - } - } - }] - }); - - cls.push({ - name: 'Ext.grid.GridPanel', - checks: [{ - name: 'initComponent', - fn: function(){ - if(!this.colModel){ - A.error('No column model specified for grid', this); - } - if(!this.store){ - A.error('No store specified for grid', this); - } - } - }] - }); - - cls.push({ - name: 'Ext.grid.GridView', - checks: [{ - name: 'autoExpand', - intercept: true, - fn: function(){ - var g = this.grid, - cm = this.cm; - if(!this.userResized && g.autoExpandColumn){ - var tw = cm.getTotalWidth(false), - aw = this.grid.getGridEl().getWidth(true) - this.getScrollOffset(); - if(tw != aw){ - var ci = cm.getIndexById(g.autoExpandColumn); - if(ci == -1){ - A.error('The autoExpandColumn does not exist in the column model', g, g.autoExpandColumn); - return false; - } - } - } - } - }] - }); - - cls.push({ - name: 'Ext.chart.Chart', - checks: [{ - name: 'initComponent', - fn: function(){ - if(!this.store){ - A.error('No store specified for chart', this); - } - } - }] - }); - - cls.push({ - name: 'Ext.tree.TreePanel', - checks: [{ - name: 'afterRender', - intercept: true, - fn: function(){ - if(!this.root){ - A.error('No root node specified for tree', this); - return false; - } - } - }] - }); - - cls.push({ - name: 'Ext', - instance: true, - checks: [{ - name: 'extend', - intercept: true, - fn: function(){ - if(arguments.length == 2 && !arguments[0]){ - A.error('Invalid base class passed to extend', arguments[0]); - return false; - } - if(arguments.length == 3){ - if(!arguments[0]){ - A.error('Invalid class to extend', arguments[0]); - return false; - }else if(!arguments[1]){ - A.error('Invalid base class passed to extend', arguments[1]); - return false; - } - } - } - },{ - name: 'override', - intercept: true, - fn: function(c){ - if(!c){ - A.error('Invalid class passed to override', c); - return false; - } - } - }] - }); - - cls.push({ - name: 'Ext.ComponentMgr', - instance: true, - checks: [{ - name: 'register', - intercept: true, - fn: function(c){ - if(this.all.indexOfKey(c.id) > -1){ - A.warn('A component with this id already exists', c, c.id); - } - } - },{ - name: 'create', - intercept: true, - fn: function(config, defaultType){ - var types = Ext.ComponentMgr.types; - if(!config.render){ - if(config.xtype){ - if(!types[config.xtype]){ - A.error('Unknown xtype specified', config, config.xtype); - return false; - } - }else{ - if(!types[defaultType]){ - A.error('Unknown defaultType specified', config, defaultType); - return false; - } - } - } - } - }] - }); - - cls.push({ - name: 'Ext.layout.FitLayout', - checks: [{ - name: 'onLayout', - intercept: true, - fn: function(){ - var ct = this.container; - if(ct.items.getCount() > 1){ - A.warn('More than 1 item in the container. A fit layout will only display a single item.', ct); - } - } - }] - }); - - if(Ext.BLANK_IMAGE_URL == 'http:/' + '/www.extjs.com/s.gif'){ - A.warn('You should set the Ext.BLANK_IMAGE_URL to reference a local copy.'); - } - - A.init(cls); - - +Ext.ns('Ext.debug'); +Ext.debug.Assistant = function(){ + var enabled = true; + + return { + enable: function(){ + enabled = true; + }, + + disable: function(){ + enabled = false; + }, + + init : function(classes){ + var klass, + intercept = false, + fn, + method; + Ext.each(classes, function(cls){ + if(this.namespaceExists(cls.name)){ + klass = this.getClass(cls.name); + method = cls.instance ? this.addInstanceCheck : this.addPrototypeCheck; + Ext.each(cls.checks, function(check){ + intercept = check.intercept == true; + fn = method.call(this, klass, check.name, check.fn, check.intercept == true); + if(check.after){ + check.after(fn); + } + }, this); + } + }, this); + }, + + namespaceExists: function(name){ + var parent = window, + exists = true; + + Ext.each(name.split('.'), function(n){ + if(!Ext.isDefined(parent[n])){ + exists = false; + return false; + } + parent = parent[n]; + }); + return exists; + }, + + getClass : function(name){ + var parent = window; + Ext.each(name.split('.'), function(n){ + parent = parent[n]; + }); + return parent; + }, + + warn: function(){ + if(enabled && window.console){ + console.warn.apply(console, arguments); + } + }, + + error: function(){ + if(enabled && window.console){ + console.error.apply(console, arguments); + } + }, + + addPrototypeCheck : function(cls, method, fn, intercept){ + return (cls.prototype[method] = cls.prototype[method][intercept ? 'createInterceptor' : 'createSequence'](fn)); + }, + + addInstanceCheck : function(cls, method, fn, intercept){ + return (cls[method] = cls[method][intercept ? 'createInterceptor' : 'createSequence'](fn)); + } + }; +}(); + +(function(){ + var A = Ext.debug.Assistant, + cls = []; + + cls.push({ + name: 'Ext.util.Observable', + checks: [{ + name: 'addListener', + intercept: true, + fn: function(eventName, fn){ + if(typeof eventName == 'object'){ + var ev, o; + for(ev in eventName){ + if(!this.filterOptRe.test(ev)){ + o = eventName[ev]; + o = o && o.fn ? o.fn : o; + if(!Ext.isFunction(o)){ + A.error('Non function passed to event listener', this, ev); + return false; + } + } + } + }else{ + if(!Ext.isFunction(fn)){ + A.error('Non function passed to event listener', this, eventName); + } + } + }, + after: function(method){ + Ext.util.Observable.prototype.on = method; + } + }] + }); + + cls.push({ + name: 'Ext.Component', + checks: [{ + name: 'render', + intercept: true, + fn: function(container, position){ + if(!container && !this.el){ + A.error('Unable to render to container', this, container); + } + + if(this.contentEl){ + var el = Ext.getDom(this.contentEl); + if(!el){ + A.error('Specified contentEl does not exist', this, this.contentEl); + return false; + } + } + } + }] + }); + + cls.push({ + name: 'Ext.Container', + checks: [{ + name: 'onBeforeAdd', + intercept: true, + fn: function(c){ + if(c.isDestroyed){ + A.warn('Adding destroyed component to container', c, this); + } + if(c.renderTo){ + A.warn('Using renderTo while adding an item to a Container. You should use the add() method or put the item in the items configuration', c, this); + } + if(c.applyTo){ + A.warn('Using applyTo while adding an item to a Container. You should use the add() method or put the item in the items configuration', c, this); + } + + var type = this.layout.type; + if(type == 'container' || type == 'auto'){ + A.warn('A non sizing layout is being used in a container that has child components. This means the child components will not be sized.', this); + } + } + },{ + name: 'lookupComponent', + intercept: true, + fn: function(c){ + var valid = true; + if(Ext.isEmpty(c)){ + valid = false; + } + if(Ext.isString(c)){ + c = Ext.ComponentMgr.get(comp); + valid = !Ext.isEmpty(c); + } + if(!valid){ + A.error('Adding invalid component to container', this, c); + return false; + } + } + }] + }); + + cls.push({ + name: 'Ext.DataView', + checks: [{ + name: 'initComponent', + fn: function(){ + if(!this.itemSelector){ + A.error('No itemSelector specified', this); + } + } + },{ + name: 'afterRender', + fn: function(){ + if(!this.store){ + A.error('No store attached to DataView', this); + } + } + }] + }); + + cls.push({ + name: 'Ext.Window', + checks: [{ + name: 'show', + intercept: true, + fn: function(){ + if(this.isDestroyed){ + A.error('Trying to show a destroyed window. If you want to reuse the window, look at the closeAction configuration.', this); + return false; + } + } + }] + }); + + cls.push({ + name: 'Ext.grid.GridPanel', + checks: [{ + name: 'initComponent', + fn: function(){ + if(!this.colModel){ + A.error('No column model specified for grid', this); + } + if(!this.store){ + A.error('No store specified for grid', this); + } + } + }] + }); + + cls.push({ + name: 'Ext.grid.GridView', + checks: [{ + name: 'autoExpand', + intercept: true, + fn: function(){ + var g = this.grid, + cm = this.cm; + if(!this.userResized && g.autoExpandColumn){ + var tw = cm.getTotalWidth(false), + aw = this.grid.getGridEl().getWidth(true) - this.getScrollOffset(); + if(tw != aw){ + var ci = cm.getIndexById(g.autoExpandColumn); + if(ci == -1){ + A.error('The autoExpandColumn does not exist in the column model', g, g.autoExpandColumn); + return false; + } + } + } + } + }] + }); + + cls.push({ + name: 'Ext.chart.Chart', + checks: [{ + name: 'initComponent', + fn: function(){ + if(!this.store){ + A.error('No store specified for chart', this); + } + } + }] + }); + + cls.push({ + name: 'Ext.tree.TreePanel', + checks: [{ + name: 'afterRender', + intercept: true, + fn: function(){ + if(!this.root){ + A.error('No root node specified for tree', this); + return false; + } + } + }] + }); + + cls.push({ + name: 'Ext', + instance: true, + checks: [{ + name: 'extend', + intercept: true, + fn: function(){ + if(arguments.length == 2 && !arguments[0]){ + A.error('Invalid base class passed to extend', arguments[0]); + return false; + } + if(arguments.length == 3){ + if(!arguments[0]){ + A.error('Invalid class to extend', arguments[0]); + return false; + }else if(!arguments[1]){ + A.error('Invalid base class passed to extend', arguments[1]); + return false; + } + } + } + },{ + name: 'override', + intercept: true, + fn: function(c){ + if(!c){ + A.error('Invalid class passed to override', c); + return false; + } + } + }] + }); + + cls.push({ + name: 'Ext.ComponentMgr', + instance: true, + checks: [{ + name: 'register', + intercept: true, + fn: function(c){ + if(this.all.indexOfKey(c.id) > -1){ + A.warn('A component with this id already exists', c, c.id); + } + } + },{ + name: 'create', + intercept: true, + fn: function(config, defaultType){ + var types = Ext.ComponentMgr.types; + if(!config.render){ + if(config.xtype){ + if(!types[config.xtype]){ + A.error('Unknown xtype specified', config, config.xtype); + return false; + } + }else{ + if(!types[defaultType]){ + A.error('Unknown defaultType specified', config, defaultType); + return false; + } + } + } + } + }] + }); + + cls.push({ + name: 'Ext.layout.FitLayout', + checks: [{ + name: 'onLayout', + intercept: true, + fn: function(){ + var ct = this.container; + if(ct.items.getCount() > 1){ + A.warn('More than 1 item in the container. A fit layout will only display a single item.', ct); + } + } + }] + }); + + if(Ext.BLANK_IMAGE_URL == 'http:/' + '/www.extjs.com/s.gif'){ + A.warn('You should set the Ext.BLANK_IMAGE_URL to reference a local copy.'); + } + + A.init(cls); + + })(); \ No newline at end of file diff --git a/js/ExtJs/src/locale/ext-lang-am.js b/js/ExtJs/src/locale/ext-lang-am.js index eb8b5463..15389335 100644 --- a/js/ExtJs/src/locale/ext-lang-am.js +++ b/js/ExtJs/src/locale/ext-lang-am.js @@ -4,356 +4,356 @@ * licensing@sencha.com * http://www.sencha.com/license */ -/** - * List compiled by Tewodros Wondimu on the extjs.com forums Oct 18, 2010. - * - * Amharic Translations - */ - -Ext.UpdateManager.defaults.indicatorText = '
እያስገባ ነዉ...
'; - -if(Ext.DataView){ - Ext.DataView.prototype.emptyText = ""; -} - -if(Ext.grid.GridPanel){ - Ext.grid.GridPanel.prototype.ddText = "{0} ምርጥ ረድፍ {1}"; -} - -if(Ext.LoadMask){ - Ext.LoadMask.prototype.msg = "እያስገባ ነዉ..."; -} - -Date.shortMonthNames = [ - "መስከ", - "ጥቅም", - "ህዳር", - "ታህሳ", - "ጥር", - "የካቲ", - "መጋቢ", - "ሚያዚ", - "ግንቦ", - "ሰኔ", - "ሐምሌ", - "ነሃሴ", - "ጷግሜ" -]; - - -Date.monthNames = [ - "መስከረም", - "ጥቅምት", - "ህዳር", - "ታህሳስ", - "ጥር", - "የካቲት", - "መጋቢት", - "ሚያዚያ", - "ግንቦት", - "ሰኔ", - "ሐምሌ", - "ነሃሴ", - "ጷግሜ" -]; - -Date.getShortMonthName = function(month) { - return Date.monthNames[month].substring(0, 3); -}; - -Date.monthNumbers = { - "መስከረም" : 0, - "ጥቅምት" : 1, - "ህዳር" : 2, - "ታህሳስ" : 3, - "ጥር" : 4, - "የካቲት" : 5, - "መጋቢት" : 6, - "ሚያዚያ" : 7, - "ግንቦት" : 8, - "ሰኔ" : 9, - "ሐምሌ" : 10, - "ነሃሴ" : 11, - "ጷግሜ" : 12 -}; - -Date.getMonthNumber = function(name) { - return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()]; -}; - -Date.dayNames = [ - "እሁድ", - "ሰኞ", - "ማክሰኞ", - "ዓሮብ", - "ሐሙስ", - "አርብ", - "ቅዳሜ" -]; - -Date.getShortDayName = function(day) { - return Date.dayNames[day].substring(0, 3); -}; - -Date.parseCodes.S.s = "(?:st|nd|rd|th)"; - -if(Ext.MessageBox){ - Ext.MessageBox.buttonText = { - ok : "ይሁን", - cancel : "ሰርዝ", - yes : "አዎ", - no : "የለም / አይ" - }; -} - -if(Ext.util.Format){ - Ext.util.Format.date = function(v, format){ - if(!v) return ""; - if(!(v instanceof Date)) v = new Date(Date.parse(v)); - return v.dateFormat(format || "ወ/ቀ/አ"); - }; -} - -if(Ext.DatePicker){ - Ext.apply(Ext.DatePicker.prototype, { - todayText : "ዛሬ", - minText : "ይሄ ቀን ከመጨረሻ ትንሹ ቀን በፊት ነዉ", - maxText : "ይሄ ቀን ከመጨረሻ ትልቁ ቀን በፊት ነዉ", - disabledDaysText : "", - disabledDatesText : "", - monthNames : Date.monthNames, - dayNames : Date.dayNames, - nextText : 'የሚቀጥለዉ ወር(መቆጣጣሪያ ቁምፍ+ቀኝ)', - prevText : 'ያለፈዉ ወር(መቆጣጣሪያ ቁምፍ+ግራ)', - monthYearText : 'ወር ምረጥ (አመት ለመለወጥ መቆጣጣሪያ ቁምፍ+ወደላይ/ወደታች)', - todayTip : "{0} (የቦታ ቁልፍ)", - format : "d/m/Y", - okText : "ይሁን", - cancelText : "ሰርዝ", - startDay : 0 - }); -} - -if(Ext.PagingToolbar){ - Ext.apply(Ext.PagingToolbar.prototype, { - beforePageText : "ገልጽ", - afterPageText : "የ {0}", - firstText : "የመጀመሪያዉ ገልጽ", - prevText : "ያለፈዉ ገልጽ", - nextText : "የሚቀጥለዉ ገልጽ", - lastText : "የመጨረሻዉ ገልጽ", - refreshText : "ከልስ", - displayMsg : "{0} - {1} ሲያሳይ ከ {2}", - emptyMsg : 'የሚታይ ዳታ የለም' - }); -} - -if(Ext.form.BasicForm){ - Ext.form.BasicForm.prototype.waitTitle = "እባክዎን ይጠብቁ..." -} - -if(Ext.form.Field){ - Ext.form.Field.prototype.invalidText = "የዚህ መስክ እሴት የተሳሳተ ነዉ"; -} - -if(Ext.form.TextField){ - Ext.apply(Ext.form.TextField.prototype, { - minLengthText : "የዚህ መስክ የመጨረሻ ትንሽ ርዝመት {0} ነዉ", - maxLengthText : "የዚህ መስክ የመጨረሻ ትልቅ ርዝመት {0} ነዉ", - blankText : "ይሄ መስክ አስፈላጊ ነዉ", - regexText : "", - emptyText : null - }); -} - -if(Ext.form.NumberField){ - Ext.apply(Ext.form.NumberField.prototype, { - decimalSeparator : ".", - decimalPrecision : 2, - minText : "የዚህ መስክ የመጨረሻ ትንሽ እሴት {0} ነዉ", - maxText : "የዚህ መስክ የመጨረሻ ትልቅ እሴት {0} ነዉ", - nanText : "{0} የተሳሳተ ቁጥር ነዉ" - }); -} - -if(Ext.form.DateField){ - Ext.apply(Ext.form.DateField.prototype, { - disabledDaysText : "ቦዝኗል / ስራ አቁሟል", - disabledDatesText : "ቦዝኗል / ስራ አቁሟል", - minText : "እዚ እሴት ዉስጥ ያለዉ ቀን ከ{0} በሑአላ መሆን አለበት", - maxText : "እዚ እሴት ዉስጥ ያለዉ ቀን ከ{0} በፊት መሆን አለበት", - invalidText : "{0} የተሳሳተ ቀን ነዉ - በዚህ ቅርፀት መሆን አለበት {1}", - format : "d/m/y", - altFormats : "d/m/Y|d/m/y|d-m-y|d-m-Y|d/m|d-m|dm|dmy|dmY|d|Y-m-d", - startDay : 0 - }); -} - -if(Ext.form.ComboBox){ - Ext.apply(Ext.form.ComboBox.prototype, { - loadingText : "እያስገባ ነዉ...", - valueNotFoundText : "አልተወሰነም" - }); -} - -if(Ext.form.VTypes){ - Ext.apply(Ext.form.VTypes, { - emailText : 'ይሄ እሴት ኢሜይል መሆን አለበት - በዚህ ቅርፀት መሆን አለበት "user@example.com"', - urlText : 'ይሄ እሴት ዩአርኤን መሆን አለበት - በዚህ ቅርፀት መሆን አለበት "http:/'+'/www.example.com"', - alphaText : 'ይሄ እሴት መያዝ ያለበት ቃላትና _ ብቻ ነዉ', - alphanumText : 'ይሄ እሴት መያዝ ያለበት ቃላት፤ ቁጥርና _ ብቻ ነዉ' - }); -} - -if(Ext.form.HtmlEditor){ - Ext.apply(Ext.form.HtmlEditor.prototype, { - createLinkText : 'እባኮትን ለዚ ዩአርኤን አገናኝ አስገባ:', - buttonTips : { - bold : { - title: 'ደማቅ (መቆጣጣሪያ ቁምፍ+B)', - text: 'የተመረጠዉን ጽሁፍ አድምቅ::', - cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' - }, - italic : { - title: 'ሰያፍ (መቆጣጣሪያ ቁምፍ+I)', - text: 'የተመረጠዉን ጽሁፍ ሰያፍ አድርግ::', - cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' - }, - underline : { - title: 'መስመረግርጌ (መቆጣጣሪያ ቁምፍ+U)', - text: 'የተመረጠዉን ጽሁፍ ከግርጌ አስምር::', - cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' - }, - increasefontsize : { - title: 'ጽሁፉን አሳድግ', - text: 'ቅርጸ ቁምፊ አሳድገግ::', - cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' - }, - decreasefontsize : { - title: 'ጽሁፉን አሳንስ', - text: 'ቅርጸ ቁምፊ አሳንስ::', - cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' - }, - backcolor : { - title: 'ጽሁፍ ምረጥ ቀለም', - text: 'የተመረጠዉን ጽሁፍ ዳራ ቀለም ለዉጥ::', - cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' - }, - forecolor : { - title: 'ቅርጸ ቁምፊ ቀለም', - text: 'የተመረጠዉን ጽሁፍ ቀለም ለዉጥ::', - cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' - }, - justifyleft : { - title: 'ጽሁፍ ግራ አሰልፍ', - text: 'ጽሁፉን ወደግራ አሰልፍ::', - cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' - }, - justifycenter : { - title: 'ጽሁፍ አማክል', - text: 'አርታኢዉ ላይ ጽሁፉን አማክል::', - cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' - }, - justifyright : { - title: 'ጽሁፍ ቀኝ አሰልፍ', - text: 'ጽሁፉን ወደቀኝ አሰልፍ::', - cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' - }, - insertunorderedlist : { - title: 'ነጥበ ምልክት ዝርዝር', - text: 'ነጥበ ምልክት ዝርዝር ጀምር::', - cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' - }, - insertorderedlist : { - title: 'ቁጥራዊ ዝርዝር', - text: 'ቁጥራዊ ዝርዝር ጀምር::', - cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' - }, - createlink : { - title: 'ገፅ አገናኝ', - text: 'የተመረጠዉን ጽሁፍ ገፅ አገናኝ አድርግ::', - cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' - }, - sourceedit : { - title: 'ምንጭ አርትእ', - text: 'ወደ ምንጭ አርትእ ሁነታ ቀይር::', - cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' - } - } - }); -} - -if(Ext.grid.GridView){ - Ext.apply(Ext.grid.GridView.prototype, { - sortAscText : "ሽቅብ ደርድር", - sortDescText : "ቁልቁል ደርድር", - columnsText : "አምዶች" - }); -} - -if(Ext.grid.GroupingView){ - Ext.apply(Ext.grid.GroupingView.prototype, { - emptyGroupText : '(ማንም)', - groupByText : 'በዚ መስክ ቦድን', - showGroupsText : 'በቡድን አሳይ' - }); -} - -if(Ext.grid.PropertyColumnModel){ - Ext.apply(Ext.grid.PropertyColumnModel.prototype, { - nameText : "ስም", - valueText : "እሴት ", - dateFormat : "m/j/Y", - trueText: "እሙን", - falseText: "ሐሰት" - }); -} - -if(Ext.grid.BooleanColumn){ - Ext.apply(Ext.grid.BooleanColumn.prototype, { - trueText : "እሙን", - falseText : "ሐሰት", - undefinedText: ' ' - }); -} - -if(Ext.grid.NumberColumn){ - Ext.apply(Ext.grid.NumberColumn.prototype, { - format : '0,000.00' - }); -} - -if(Ext.grid.DateColumn){ - Ext.apply(Ext.grid.DateColumn.prototype, { - format : 'm/d/Y' - }); -} - -if(Ext.layout.BorderLayout && Ext.layout.BorderLayout.SplitRegion){ - Ext.apply(Ext.layout.BorderLayout.SplitRegion.prototype, { - splitTip : "መጠን ለመቀይር ጎትት::", - collapsibleSplitTip : "መጠን ለመቀይር ጎትት:: ለመደበቅ ሁለቴ ጠቅ አድርግ::" - }); -} - -if(Ext.form.TimeField){ - Ext.apply(Ext.form.TimeField.prototype, { - minText : "እዚህ መስክ ዉስጥ ያለዉ ሰዓት ከ{0} እኩል ወይም በኁላ መሆን አለበት", - maxText : "እዚህ መስክ ዉስጥ ያለዉ ሰዓት ከ{0} እኩል ወይም በፊት መሆን አለበት", - invalidText : "{0} የተሳሳተ ሰዓት ነዉ", - format : "g:i A", - altFormats : "g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H" - }); -} - -if(Ext.form.CheckboxGroup){ - Ext.apply(Ext.form.CheckboxGroup.prototype, { - blankText : "እዚህ ቡድን ዉስጥ ቢያንስ አንድ ዓይነት መምረጥ አለብህ" - }); -} - -if(Ext.form.RadioGroup){ - Ext.apply(Ext.form.RadioGroup.prototype, { - blankText : "እዚህ ቡድን ዉስጥ ቢያንስ አንድ ዓይነት መምረጥ አለብህ" - }); -} +/** + * List compiled by Tewodros Wondimu on the extjs.com forums Oct 18, 2010. + * + * Amharic Translations + */ + +Ext.UpdateManager.defaults.indicatorText = '
እያስገባ ነዉ...
'; + +if(Ext.DataView){ + Ext.DataView.prototype.emptyText = ""; +} + +if(Ext.grid.GridPanel){ + Ext.grid.GridPanel.prototype.ddText = "{0} ምርጥ ረድፍ {1}"; +} + +if(Ext.LoadMask){ + Ext.LoadMask.prototype.msg = "እያስገባ ነዉ..."; +} + +Date.shortMonthNames = [ + "መስከ", + "ጥቅም", + "ህዳር", + "ታህሳ", + "ጥር", + "የካቲ", + "መጋቢ", + "ሚያዚ", + "ግንቦ", + "ሰኔ", + "ሐምሌ", + "ነሃሴ", + "ጷግሜ" +]; + + +Date.monthNames = [ + "መስከረም", + "ጥቅምት", + "ህዳር", + "ታህሳስ", + "ጥር", + "የካቲት", + "መጋቢት", + "ሚያዚያ", + "ግንቦት", + "ሰኔ", + "ሐምሌ", + "ነሃሴ", + "ጷግሜ" +]; + +Date.getShortMonthName = function(month) { + return Date.monthNames[month].substring(0, 3); +}; + +Date.monthNumbers = { + "መስከረም" : 0, + "ጥቅምት" : 1, + "ህዳር" : 2, + "ታህሳስ" : 3, + "ጥር" : 4, + "የካቲት" : 5, + "መጋቢት" : 6, + "ሚያዚያ" : 7, + "ግንቦት" : 8, + "ሰኔ" : 9, + "ሐምሌ" : 10, + "ነሃሴ" : 11, + "ጷግሜ" : 12 +}; + +Date.getMonthNumber = function(name) { + return Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()]; +}; + +Date.dayNames = [ + "እሁድ", + "ሰኞ", + "ማክሰኞ", + "ዓሮብ", + "ሐሙስ", + "አርብ", + "ቅዳሜ" +]; + +Date.getShortDayName = function(day) { + return Date.dayNames[day].substring(0, 3); +}; + +Date.parseCodes.S.s = "(?:st|nd|rd|th)"; + +if(Ext.MessageBox){ + Ext.MessageBox.buttonText = { + ok : "ይሁን", + cancel : "ሰርዝ", + yes : "አዎ", + no : "የለም / አይ" + }; +} + +if(Ext.util.Format){ + Ext.util.Format.date = function(v, format){ + if(!v) return ""; + if(!(v instanceof Date)) v = new Date(Date.parse(v)); + return v.dateFormat(format || "ወ/ቀ/አ"); + }; +} + +if(Ext.DatePicker){ + Ext.apply(Ext.DatePicker.prototype, { + todayText : "ዛሬ", + minText : "ይሄ ቀን ከመጨረሻ ትንሹ ቀን በፊት ነዉ", + maxText : "ይሄ ቀን ከመጨረሻ ትልቁ ቀን በፊት ነዉ", + disabledDaysText : "", + disabledDatesText : "", + monthNames : Date.monthNames, + dayNames : Date.dayNames, + nextText : 'የሚቀጥለዉ ወር(መቆጣጣሪያ ቁምፍ+ቀኝ)', + prevText : 'ያለፈዉ ወር(መቆጣጣሪያ ቁምፍ+ግራ)', + monthYearText : 'ወር ምረጥ (አመት ለመለወጥ መቆጣጣሪያ ቁምፍ+ወደላይ/ወደታች)', + todayTip : "{0} (የቦታ ቁልፍ)", + format : "d/m/Y", + okText : "ይሁን", + cancelText : "ሰርዝ", + startDay : 0 + }); +} + +if(Ext.PagingToolbar){ + Ext.apply(Ext.PagingToolbar.prototype, { + beforePageText : "ገልጽ", + afterPageText : "የ {0}", + firstText : "የመጀመሪያዉ ገልጽ", + prevText : "ያለፈዉ ገልጽ", + nextText : "የሚቀጥለዉ ገልጽ", + lastText : "የመጨረሻዉ ገልጽ", + refreshText : "ከልስ", + displayMsg : "{0} - {1} ሲያሳይ ከ {2}", + emptyMsg : 'የሚታይ ዳታ የለም' + }); +} + +if(Ext.form.BasicForm){ + Ext.form.BasicForm.prototype.waitTitle = "እባክዎን ይጠብቁ..." +} + +if(Ext.form.Field){ + Ext.form.Field.prototype.invalidText = "የዚህ መስክ እሴት የተሳሳተ ነዉ"; +} + +if(Ext.form.TextField){ + Ext.apply(Ext.form.TextField.prototype, { + minLengthText : "የዚህ መስክ የመጨረሻ ትንሽ ርዝመት {0} ነዉ", + maxLengthText : "የዚህ መስክ የመጨረሻ ትልቅ ርዝመት {0} ነዉ", + blankText : "ይሄ መስክ አስፈላጊ ነዉ", + regexText : "", + emptyText : null + }); +} + +if(Ext.form.NumberField){ + Ext.apply(Ext.form.NumberField.prototype, { + decimalSeparator : ".", + decimalPrecision : 2, + minText : "የዚህ መስክ የመጨረሻ ትንሽ እሴት {0} ነዉ", + maxText : "የዚህ መስክ የመጨረሻ ትልቅ እሴት {0} ነዉ", + nanText : "{0} የተሳሳተ ቁጥር ነዉ" + }); +} + +if(Ext.form.DateField){ + Ext.apply(Ext.form.DateField.prototype, { + disabledDaysText : "ቦዝኗል / ስራ አቁሟል", + disabledDatesText : "ቦዝኗል / ስራ አቁሟል", + minText : "እዚ እሴት ዉስጥ ያለዉ ቀን ከ{0} በሑአላ መሆን አለበት", + maxText : "እዚ እሴት ዉስጥ ያለዉ ቀን ከ{0} በፊት መሆን አለበት", + invalidText : "{0} የተሳሳተ ቀን ነዉ - በዚህ ቅርፀት መሆን አለበት {1}", + format : "d/m/y", + altFormats : "d/m/Y|d/m/y|d-m-y|d-m-Y|d/m|d-m|dm|dmy|dmY|d|Y-m-d", + startDay : 0 + }); +} + +if(Ext.form.ComboBox){ + Ext.apply(Ext.form.ComboBox.prototype, { + loadingText : "እያስገባ ነዉ...", + valueNotFoundText : "አልተወሰነም" + }); +} + +if(Ext.form.VTypes){ + Ext.apply(Ext.form.VTypes, { + emailText : 'ይሄ እሴት ኢሜይል መሆን አለበት - በዚህ ቅርፀት መሆን አለበት "user@example.com"', + urlText : 'ይሄ እሴት ዩአርኤን መሆን አለበት - በዚህ ቅርፀት መሆን አለበት "http:/'+'/www.example.com"', + alphaText : 'ይሄ እሴት መያዝ ያለበት ቃላትና _ ብቻ ነዉ', + alphanumText : 'ይሄ እሴት መያዝ ያለበት ቃላት፤ ቁጥርና _ ብቻ ነዉ' + }); +} + +if(Ext.form.HtmlEditor){ + Ext.apply(Ext.form.HtmlEditor.prototype, { + createLinkText : 'እባኮትን ለዚ ዩአርኤን አገናኝ አስገባ:', + buttonTips : { + bold : { + title: 'ደማቅ (መቆጣጣሪያ ቁምፍ+B)', + text: 'የተመረጠዉን ጽሁፍ አድምቅ::', + cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' + }, + italic : { + title: 'ሰያፍ (መቆጣጣሪያ ቁምፍ+I)', + text: 'የተመረጠዉን ጽሁፍ ሰያፍ አድርግ::', + cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' + }, + underline : { + title: 'መስመረግርጌ (መቆጣጣሪያ ቁምፍ+U)', + text: 'የተመረጠዉን ጽሁፍ ከግርጌ አስምር::', + cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' + }, + increasefontsize : { + title: 'ጽሁፉን አሳድግ', + text: 'ቅርጸ ቁምፊ አሳድገግ::', + cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' + }, + decreasefontsize : { + title: 'ጽሁፉን አሳንስ', + text: 'ቅርጸ ቁምፊ አሳንስ::', + cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' + }, + backcolor : { + title: 'ጽሁፍ ምረጥ ቀለም', + text: 'የተመረጠዉን ጽሁፍ ዳራ ቀለም ለዉጥ::', + cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' + }, + forecolor : { + title: 'ቅርጸ ቁምፊ ቀለም', + text: 'የተመረጠዉን ጽሁፍ ቀለም ለዉጥ::', + cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' + }, + justifyleft : { + title: 'ጽሁፍ ግራ አሰልፍ', + text: 'ጽሁፉን ወደግራ አሰልፍ::', + cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' + }, + justifycenter : { + title: 'ጽሁፍ አማክል', + text: 'አርታኢዉ ላይ ጽሁፉን አማክል::', + cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' + }, + justifyright : { + title: 'ጽሁፍ ቀኝ አሰልፍ', + text: 'ጽሁፉን ወደቀኝ አሰልፍ::', + cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' + }, + insertunorderedlist : { + title: 'ነጥበ ምልክት ዝርዝር', + text: 'ነጥበ ምልክት ዝርዝር ጀምር::', + cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' + }, + insertorderedlist : { + title: 'ቁጥራዊ ዝርዝር', + text: 'ቁጥራዊ ዝርዝር ጀምር::', + cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' + }, + createlink : { + title: 'ገፅ አገናኝ', + text: 'የተመረጠዉን ጽሁፍ ገፅ አገናኝ አድርግ::', + cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' + }, + sourceedit : { + title: 'ምንጭ አርትእ', + text: 'ወደ ምንጭ አርትእ ሁነታ ቀይር::', + cls: 'ኤክስ-ኤችቲኤምኤል-አርታኢ-ጠቃሚ ምክር' + } + } + }); +} + +if(Ext.grid.GridView){ + Ext.apply(Ext.grid.GridView.prototype, { + sortAscText : "ሽቅብ ደርድር", + sortDescText : "ቁልቁል ደርድር", + columnsText : "አምዶች" + }); +} + +if(Ext.grid.GroupingView){ + Ext.apply(Ext.grid.GroupingView.prototype, { + emptyGroupText : '(ማንም)', + groupByText : 'በዚ መስክ ቦድን', + showGroupsText : 'በቡድን አሳይ' + }); +} + +if(Ext.grid.PropertyColumnModel){ + Ext.apply(Ext.grid.PropertyColumnModel.prototype, { + nameText : "ስም", + valueText : "እሴት ", + dateFormat : "m/j/Y", + trueText: "እሙን", + falseText: "ሐሰት" + }); +} + +if(Ext.grid.BooleanColumn){ + Ext.apply(Ext.grid.BooleanColumn.prototype, { + trueText : "እሙን", + falseText : "ሐሰት", + undefinedText: ' ' + }); +} + +if(Ext.grid.NumberColumn){ + Ext.apply(Ext.grid.NumberColumn.prototype, { + format : '0,000.00' + }); +} + +if(Ext.grid.DateColumn){ + Ext.apply(Ext.grid.DateColumn.prototype, { + format : 'm/d/Y' + }); +} + +if(Ext.layout.BorderLayout && Ext.layout.BorderLayout.SplitRegion){ + Ext.apply(Ext.layout.BorderLayout.SplitRegion.prototype, { + splitTip : "መጠን ለመቀይር ጎትት::", + collapsibleSplitTip : "መጠን ለመቀይር ጎትት:: ለመደበቅ ሁለቴ ጠቅ አድርግ::" + }); +} + +if(Ext.form.TimeField){ + Ext.apply(Ext.form.TimeField.prototype, { + minText : "እዚህ መስክ ዉስጥ ያለዉ ሰዓት ከ{0} እኩል ወይም በኁላ መሆን አለበት", + maxText : "እዚህ መስክ ዉስጥ ያለዉ ሰዓት ከ{0} እኩል ወይም በፊት መሆን አለበት", + invalidText : "{0} የተሳሳተ ሰዓት ነዉ", + format : "g:i A", + altFormats : "g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H" + }); +} + +if(Ext.form.CheckboxGroup){ + Ext.apply(Ext.form.CheckboxGroup.prototype, { + blankText : "እዚህ ቡድን ዉስጥ ቢያንስ አንድ ዓይነት መምረጥ አለብህ" + }); +} + +if(Ext.form.RadioGroup){ + Ext.apply(Ext.form.RadioGroup.prototype, { + blankText : "እዚህ ቡድን ዉስጥ ቢያንስ አንድ ዓይነት መምረጥ አለብህ" + }); +} diff --git a/js/ExtJs/src/widgets/layout/box/ScrollerOverflow.js b/js/ExtJs/src/widgets/layout/box/ScrollerOverflow.js index 9a1a6080..66ca6089 100644 --- a/js/ExtJs/src/widgets/layout/box/ScrollerOverflow.js +++ b/js/ExtJs/src/widgets/layout/box/ScrollerOverflow.js @@ -324,11 +324,11 @@ Ext.layout.boxOverflow.Scroller = Ext.extend(Ext.layout.boxOverflow.None, { Ext.layout.boxOverflow.scroller = Ext.layout.boxOverflow.Scroller; -/** - * @class Ext.layout.boxOverflow.VerticalScroller - * @extends Ext.layout.boxOverflow.Scroller - * Description - */ +/** + * @class Ext.layout.boxOverflow.VerticalScroller + * @extends Ext.layout.boxOverflow.Scroller + * Description + */ Ext.layout.boxOverflow.VerticalScroller = Ext.extend(Ext.layout.boxOverflow.Scroller, { scrollIncrement: 75, wheelIncrement : 2, diff --git a/js/locale/ar.js b/js/locale/ar.js index 58274a0a..e4388f8b 100644 --- a/js/locale/ar.js +++ b/js/locale/ar.js @@ -1,684 +1,684 @@ -/* -* This file must be encoded in UTF-8 -*/ - -var i18n = new Array(); - -// In file: ../../js/main.js - i18n["Refresh"] = "تحديث"; - i18n["Forbidden"] = "غير مسموح"; - i18n["You can't do this action as anonymous user."] = "لا يمكنك تنفيذ هذا الإجراء كمستخدم غير معرف."; - i18n["Error"] = "خطأ"; - i18n["File system error. Check read/write permission under data folder."] = "خطأ في نظام الملفات. يرجى التأكد من صلاحية القراءة/الكتابة في مجلد البيانات."; - i18n["Main menu"] = "القائمة الرئيسية"; - i18n["Topic:"] = "رسالة:"; - i18n["Defined by {0}, {1}"] = "تم تسجيلها من قبل {0}, {1}"; - i18n["Files need translate"] = "ملفات تحتاج إلى ترجمة"; - i18n["Files need update"] = "ملفات تحتاج إلى تحديث"; - i18n["Error in current translation"] = "خطأ في الترجمة الحالية"; - i18n["Files need reviewed"] = "ملفات تحتاج إلى مراجعة"; - i18n["Not in EN tree"] = "ملفات ليست ضمن النسخة الإجليزية"; - i18n["All files"] = "كل الملفات"; - i18n["Open the Log Message Manager"] = "افتح إدارة سجل الرسائل"; - i18n["Work in progress"] = "قيد العمل والإنجاز"; - i18n["Patches for review"] = "حزم ملفات للمراجعة"; - i18n["Google translation"] = "خدمة جوجل للترجمة"; - i18n["Home"] = "الرئيسية"; - i18n["Connected as"] = "متصل باسم"; - i18n["Connected using"] = "متصل باستخدام"; - i18n["anonymous"] = "غير معروف"; - i18n["Administrator"] = "المدير"; - i18n["You are a global Administrator"] = "لديك صلاحية الإدارة الكلية"; - i18n["You are an administrator for this language"] = "لديك صلاحية الإدارة لهذه اللغة"; - i18n["Project: "] = "المشروع:"; - i18n["Language: "] = "اللغة:"; - i18n["Total number of your files"] = "إجمالي عدد ملفاتك"; - i18n["You have used characters that require the use of UTF-8 despite the XML header.
Please delete these characters or change the header of the XML file in UTF-8 ; i.e.:

<?xml version=\"1.0\" encoding=\"utf-8\"?>
"] = "لقد استخدمت حروفاً تتطلب اعتماد ترميز UTF-8 على غرار معلومات الملف الرأسية.
يرجى إلغاء هذه الحروف أو تغيير الترميز إلى UTF-8 ; على سبيل المثال:

"; - i18n["It seems that you have inserted some tabs caracters into this file. Please, replace each one by one space.
Tip: You can use the \"Re-indent all this file\" button to replace all tabs by spaces."] = "يبدو أنك قد أدخلت بعض الفراغات باستخدم زر الجدولة tabs. يرجى استبدالها بالمسافة.
تلميح: تستطيع استخدام أمر \"إعادة تصفيف هذا الملف\" للقيام بذلك تلقائياً."; - i18n["You can't modify this file as it was modify by another user. Contact an administrator if you want to be able to modify it."] = "لا تستطيع تعديل هذا الملف لأنه معدل من قبل مستخدم آخر. يرجى التواصل مع الإدارة حتى تتمكن من تعديله."; - i18n["The patch you want to delete didn't exist."] = "حزمة الملفات التي ترغب في حذفها غير موجودة."; - i18n["The patch you want to delete isn't own by you. Only the user how create it or a global administrator can delete it."] = "حزمة الملفات التي ترغب في حذفها مسجلة باسم مستخدم آخر. فقط المستخدم صاحب الحزمة أو المدير العام يستطيع حذفها."; - i18n["This action is available only to global administrator."] = "هذا الإجراء متاح فقط للمدير العام."; - i18n["This action is available only to global administrator or to administrator for this lang."] = "هذا الإجراء متاح فقط للمدير العام أو من له صلاحية إدارة هذه اللغة."; - i18n["The file you want to clear local change isn't own by you.
You can only do this action for yours files."] = "الملف الذي تريد إلغاء ترجمته ليس متاحاً لك.
تستطيع تنفيذ هذا الإجراء على ملفاتك فقط."; - -// In file: ../../js/ui/component/CheckDoc.js - i18n["Double-click the cell to open the file selection"] = "اضغط بنقر مزدوج على المربع لفتح تحديد الملف"; - i18n["Extension"] = "التوسعة"; - i18n["Not documented"] = "غير موثقة"; - i18n["Old style"] = "نمط قديم"; - i18n["Bad refsect1 order"] = "ترتيب refsect1 غير صحيح"; - i18n["No parameters"] = "لا توجد مدخلات"; - i18n["No return values"] = "لا توجد قيم معادة"; - i18n["No examples"] = "لا توجد أمثلة"; - i18n["No errors section"] = "لا يوجد قسم للأخطاء"; - i18n["No see also"] = "لا توجد: اقرأ ايضاً"; - i18n["Refsect1 role error"] = "قاعدة Refsect1 غير صحية"; - i18n["Files"] = "ملفات"; - i18n["Open all files"] = "افتح كل الملفات"; - i18n["Open selected files"] = "افتح الملفات المحددة"; - i18n["Please, wait..."] = "الرجاء, انتظر..."; - -// In file: ../../js/ui/component/WorkTreeGrid.js - i18n["Modified by"] = "معدلة بواسطة"; - i18n["Date"] = "التاريخ"; - i18n["Y-m-d, H:i"] = "Y-d-m, H:i"; - i18n["Users"] = "المستخدمين"; - i18n["Last modified"] = "آخر تعديل"; - i18n["Estimated progress"] = "تقدير نسبة الإنجاز"; - i18n["{0}% complete"] = "{0}% منجز"; - i18n["Set the progress..."] = "تحديد نسبة الإنجاز..."; - i18n["View diff"] = "عرض الاختلافات"; - i18n["Download the diff as a patch"] = "تحميل الاختلافات على شكل حزمة"; - i18n["Clear this change"] = "إلغاء هذا التعديل"; - i18n["Cancel this deletion"] = "تراجع عن هذا الحذف"; - i18n["Submit all files for review in patch:"] = "ارسل كل الملفات للمراجعة ضمن حزمة:"; - i18n["Submit all files in this directory in patch:"] = "ارسل كل الملفات في هذا المجلد ضمن حزمة:"; - i18n["Submit as patch for review in:"] = "ارسل للمراجعة ضمن حزمة:"; - i18n["Create a new patch"] = "إنشاء حزمة جديدة"; - i18n["Commit..."] = "اعتمد..."; - i18n["...this file"] = "...هذا الملف"; - i18n["...all files from this folder"] = "...كل الملفات في هذا المجلد"; - i18n["...all files from this patch"] = "...كل الملفات في هذه الحزمة"; - i18n["...all files modified by me"] = "...كل الملفات المعدلة بواسطتي"; - i18n["You have no patch currently. You must create one."] = "ليست لديك حزمة حالياً. يجب أن تنشئ حزمة."; - i18n["Diff for file: {0}"] = "الاختلافات للملف: {0}"; - i18n["Administrator menu"] = "قائمة الإدارة"; - - -// In file: ../../js/ui/component/PatchesTreeGrid.js - i18n["Edit the description of this patch"] = "عدل وصف هذه الحزمة:"; - i18n["Delete this patch"] = "احذف هذه الحزمة"; - i18n["Back all files to work in progress module"] = "إعادة كل الملفات إلى قائمة قيد العمل والإنجاز"; - i18n["Back all this patch to work in progress module"] = "إعادة هذه الحزمة إلى قائمة قيد العمل والإنجاز"; - i18n["Back all this folder to work in progress module"] = "إعادة هذا المجلد إلى قائمة قيد العمل والإنجاز"; - i18n["Back this file to work in progress module"] = "إعادة هذا الملف إلى قائمة قيد العمل والإنجاز"; - i18n["Creation date: "] = "تاريخ الإنشاء:"; - i18n["View unified diff"] = "عرض الاختلافات الموحدة"; - i18n["Download the unified diff as a patch"] = "تحميل الاختلافات الموحدة على شكل حزمة"; - - -// In file: ../../js/ui/component/ManagePatchPrompt.js - i18n["Create"] = "إنشاء"; - i18n["Modify this patch description"] = "عدل وصف هذه الحزمة"; - i18n["Patch name"] = "اسم الحزمة"; - i18n["Patch description"] = "وصف الحزمة"; - i18n["This description will be the default during the validation of the patch by a valid user."] = "هذا الوصف سيكون افتراضياً لهذه الحزمة عند مراجعتها من قبل مستخدم معرف."; - i18n["If provided, an email will be send to you to inform that the patch is commited."] = "إذا تم تسجيل بريد إلكتروني سوف تتم مراسلتك لإبلاغك عند اعتماد هذه الحزمة."; - -// In file: ../../js/ui/task/DeletePatchTask.js - i18n["Patch deleted"] = "تم حذف الحزمة"; - i18n["The patch have been deleted !"] = "الحزمة تم حذفها!"; - -// In file: ../../js/ui/component/ViewVCDiff.js - i18n["Diff From VCS"] = "الاختلافات عن VCS"; - -// In file: ../../js/ui/component/CommitPrompt.js - i18n["VCS commit"] = "اعتماد VCS"; - i18n["Configure this tools"] = "تهيئة هذه الأدوات"; - i18n["Submit"] = "إرسال"; - i18n["Close"] = "إغلاق"; - i18n["Older messages"] = "رسائل قديمة"; - i18n["No log message currently"] = "لا توجد سجلات رسائل حالياً"; - i18n["Log message"] = "رسالة سجل"; - - -// In file: ../../js/ui/component/PortletTranslationGraph.js - i18n["Graphics"] = "رسومات بيانية"; - i18n["Refresh this graph"] = "تحديث هذه الرسمة"; - - -// In file: ../../js/ui/component/PortletInfo.js - i18n["Information"] = "معلومات"; - i18n["Since"] = "منذ"; - i18n["{0} year(s)"] = "{0} سنة/سنوات"; - i18n["{0} month(s)"] = "{0} شهر/شهور"; - i18n["{0} week(s)"] = "{0} اسبوع/اسابيع"; - i18n["{0} day(s)"] = "{0} يوم/أيام"; - i18n["{0} hour(s)"] = "{0} ساعة/ساعات"; - i18n["{0} minute(s)"] = "{0} دقيقة/دقائق"; - i18n["{0} second(s)"] = "{0} ثانية/ثواني"; - i18n["Less than one second"] = "أقل من ثانية واحدة"; - i18n["{0} check all entitites"] = "{0} فحص كل المكونات"; - i18n["{0} updated app's data"] = "{0} حدث بيانات التطبيقات"; - i18n["{0} logged out"] = "{0} قام بتسجيل الخروج"; - i18n["{0} is logged in using the {1} language"] = "{0} قام بتسجيل الدخول ضمن لغة {1}"; - i18n["{0} committed {1} new folder(s) in the {2} language"] = "{0} اعتمد {1} مجلد/مجلدات جديدة ضمن لغة {2} "; - i18n["{0} committed {1} file(s) ({2} new, {3} update, {4} delete) in the language {5}"] = "{0} اعتمد {1} ملف/ملفات ({2} جديدة، {3} معدلة {4} محذوفة) ضمن لغة {5}"; - i18n["{0} changed file\'s owner"] = "{0} غير صلاحية الملف"; - - -// In file: ../../js/ui/component/ErrorFileGrid.js - i18n["Type"] = "النوع"; - i18n["Maintainer"] = "المتعهد"; - i18n["Path"] = "المسار"; - i18n["No Files"] = "لا توجد ملفات"; - i18n["File"] = "ملف"; - i18n["Edit in a new tab"] = "التعديل في تبويب جديد"; - i18n["Diff"] = "الاختلافات"; - i18n["About error type"] = "حول أنواع الخطأ"; - i18n["File with error : in {0}"] = "ملف فيه خطأ : في {0}"; - i18n["Error description"] = "وصف الخطأ"; - i18n["VCS Log"] = "سجل VCS "; - i18n["Tools"] = "أدوات"; - i18n["{0} File: "] = "{0} File: "; - i18n["en File: "] = "en File: "; - i18n["Filter: "] = "تصفية: "; - i18n["Your filter must contain at least 3 characters"] = "عوامل التصفية يجب أن تتضمن 3 حروف على الأقل"; - - -// In file: ../../js/ui/component/PortletTranslationsGraph.js - i18n["Graphics for all languages"] = "الرسومات البيانية لكل اللغات"; - i18n["Lang:"] = "اللغة:"; - i18n["Total:"] = "الإجمالي:"; - i18n["files"] = "ملفات"; - - -// In file: ../../js/ui/component/EntitiesAcronymsPanel.js - i18n["Click on a row to display the content of the entitie.
Double-click on it to insert it at the cursor position."] = "اضغط على أحد الصفوف لعرض المحتويات.
اضغط بشكل مزدوج لإدخالها في الموضع الحالي."; - i18n["Click on a row to display the content of the acronym.
Double-click on it to insert it at the cursor position."] = "اضغط على أحد الصفوف لعرض محتويات المصطلح.
اضغط بشكل مزدوج لإدخالها في الموضع الحالي"; - i18n["Items"] = "عناصر"; - i18n["From"] = "من"; - i18n["Load/Refresh"] = "تحميل/تحديث"; - i18n["Entities & acronyms"] = "عناصر ومصطلحات"; - i18n["Acronyms"] = "مصطلحات"; - - -// In file: ../../js/ui/component/RepositoryTree.js - i18n["Repository"] = "مستودع الملفات"; - i18n["Collapse"] = "إخفاء"; - i18n["Expand"] = "توسعة"; - i18n["Open the same file in {0}"] = "افتح نفس الملف في {0}"; - i18n["Log"] = "Log"; - i18n["{0} Log"] = "{0} Log"; - i18n["File: "] = "ملف: "; - i18n["in {0}"] = "في {0}"; - i18n["Search: "] = "بحث: "; - i18n["Your search must contain at least 3 characters"] = "عبارة البحث يحب أن تحتوي 3 حروف على الأقل"; - i18n["Search result: {0}"] = "نتيجة البحث: {0}"; - i18n["Update this folder"] = "تحديث هذا المجلد"; - - i18n["Add a new folder"] = "إضافة مجلد جديدة"; - i18n["Parent Folder"] = "المجلد الأعلى"; - i18n["Name for the new folder"] = "اسم المجلد الجديد"; - i18n["Folder created"] = "تم إنشاء المجلد"; - i18n["Info: This new folder won't be commited until a new file will be commited into it. If you don't commit any new file into it until 8 days, it will be automatically deleted."] = "معلومات: لن يتم اعتماد المجلد الجديد حتى يتم اعتماد ملف جديد فيه. إذا لم يتم اعتماد أي ملفات فيها خلال 8 أيام فسيتم حذفه تلقائياً"; - i18n["Folder

{0}

was created sucessfully under {1} !"] = "المجلد

{0}

تم إنشاؤه بنجاح في {1} !"; - i18n["This folder already exist in the current folder."] = "هذا المجلد موجود مسبقاً ضمن المجلد الحالي."; - - i18n["Add a new file"] = "إضافة ملف جديد"; - i18n["This file already exist in the current folder."] = "هذا الملف موجود مسبقاً في المجلد الحالي"; - i18n["Name for the new file"] = "اسم الملف الجديد"; - i18n["Chose a skeleton"] = "اختر مخطط"; - i18n["Open the editor"] = "افتح المحرر"; - -// In file: ../../js/ui/component/CheckEntitiesPrompt.js - i18n["Check entities"] = "افحص المكونات"; - i18n["Go !"] = "انطلق !"; - i18n["You're about to check all entities.

This action takes time."] = "أنت على وشك فحص كل المكونات.

هذا الإجراء يتطلب وقتاً."; - - -// In file: ../../js/ui/component/PortletTranslator.js - i18n["{0} Translators"] = "مترجمي {0}"; - i18n["Name"] = "الاسم"; - i18n["Email"] = "بريد إلكتروني"; - i18n["Nick"] = "اسم المستخدم"; - i18n["VCS"] = "VCS"; - i18n["UptoDate"] = "ترجمة حديثة"; - i18n["Stale"] = "غير مكتملة"; - i18n["Sum"] = "مجموع"; - i18n["Send an email to the {0}"] = "أرسل بريد إلكتروني إلى {0}"; - i18n["Send an email to {0}"] = "أرسل بريد إلكتروني إلى {0}"; - i18n["Translators"] = "مترجمون"; - i18n["Refresh this grid"] = "تحديث هذا الجدول"; - - -// In file: ../../js/ui/component/BuildStatus.js - i18n["Last failed build for {0}"] = "آخر بناء لم ينجح {0}"; - i18n["Last failed build for the documentation {0}"] = "آخر بناء لم ينجح لكامل الدليل {0}"; - i18n["This log is too large and have been truncated. Use the following button to download the full content of it."] = "هذا السجل طويل جداً ويجب أن يختصر. استخدم الزر التالي لتحميله كاملاً."; - i18n["Download the full content of this log"] = "تحميل محتويات هذا السجل كاملاً"; - i18n["Language"] = "اللغة"; - - -// In file: ../../js/ui/component/SystemUpdatePrompt.js - i18n["Refresh all data"] = "تحديث كل البيانات"; - i18n["Update all files from VCS"] = "تحديث كل الملفات من VCS"; - i18n["This may take time. Thank you for your patience..."] = "هذا الإجراء يستغرق وقتاً، شكراً لانتظارك..."; - i18n["Apply all tools"] = "استخدم كل الأدومات"; - i18n["Reload data"] = "إعادة تحميل البيانات"; - i18n["Start"] = "إبدأ"; - i18n["update in progress..."] = "التحديث جاري..."; - - -// In file: ../../js/ui/component/PortletBugs.js - i18n["You must manually load this data.
Use the refresh button !"] = "يجب أن تقوم بتحميل هذه البيانات يدوياً.
استخدم زر التحديث !"; - i18n["Open in a new Tab"] = "افتح في تبويب جديد"; - i18n["Open the related file"] = "افتح الملفات ذات العلاقة"; - i18n["Summary"] = "الخلاصة"; - i18n["Error when loading open bugs from Php.net !"] = "حدث خطأ عند تحميل قائمة المشاكل bugs من موقع Php.net !"; - i18n["No open bugs"] = "لا توجد مشاكل bugs مفتوحة"; - i18n["Open bugs for {0}"] = "قائمة المشاكل bugs for {0}"; - - -// In file: ../../js/ui/component/MainPanel.js - i18n["Confirm"] = "تأكيد"; - i18n["This file has been modified without being saved.
Do you really want to close?"] = "هذا الملف تم تعديله ولم يحفظ.
هل تريد فعلاً إغلاقه؟"; - i18n["File: "] = "ملف: "; - i18n["Direct link to this patch"] = "رابط مباشر لهذه الحزمة"; - i18n["Diff for patch: {0}"] = "الاختلافات للحزمة: {0}"; - i18n["Patch Name: "] = "اسم الحزمة:"; - - -// In file: ../../js/ui/component/FilePanel.js - i18n["Undo"] = "تراجع"; - i18n["Redo"] = "إعادة"; - i18n["Close Tab"] = "إغلاق التبويب"; - i18n["Go to previous tab"] = "انتقل للتبويب السابق"; - i18n["Go to next tab"] = "انتقل للتبويب التالي"; - i18n["MarkUp"] = "MarkUp"; - i18n["Reviewed tag"] = "Reviewed tag"; - i18n["Revcheck tag"] = "Revcheck tag"; - i18n["Description section"] = "قسم الوصف"; - i18n["Parameters section"] = "قسم المدخلات"; - i18n["Return section"] = "قسم القيم العائدة"; - i18n["Error section"] = "قسم الأخطاء"; - i18n["Unicode section"] = "قسم Unicode "; - i18n["Changelog section"] = "قسم Changelog "; - i18n["Examples section"] = "قسم الأمثلة"; - i18n["Notes section"] = "قسم الملاحظات"; - i18n["SeeAlso section"] = "قسم SeeAlso"; - i18n["Enable / Disable spellChecking"] = "تفعيل / تعطيل التصحيح الإملائي"; - i18n["Re-indent all this file"] = "إعادة تصفيف هذا الملف"; - i18n["Synchronize scroll bars"] = "مزامنة أشرطة التمرير"; - i18n["Line: "] = "السطر:"; - i18n["Col: "] = "العمود:"; - i18n["Accept this patch and Save the file (CTRL+s)"] = "اعتمد هذه الحزمة واحفظ الملف (CTRL+s)"; - i18n["Reject this patch"] = "رفض هذه الحزمة"; - i18n["Save this file (CTRL+s)"] = "حفظ هذا الملف (CTRL+s)"; - i18n["Do you want to check for errors before saving?"] = "هل تريد فحص الأخطاء قبل الحفظ؟"; - i18n["Save as a patch"] = "الحفظ كـ حزمة"; - i18n["modified"] = "تم التعديل"; - i18n["Check XML with XmlLint"] = "افحص XML بواسطة XmlLint"; - i18n["Expand in a popup"] = "التوسيع في نافذة"; - i18n["Preview in a popup"] = "الاطلاع في نافذة"; - i18n["You must save your file in order to preview the result."] = "يجب أن تحفظ ملفات للاطلاع على النتيجة."; - i18n["Open for editing in a new Tab"] = "افتح للتعديل في تبويب جديد"; - - -// In file: ../../js/ui/component/EditorConf.js - i18n["Main"] = "الإعدادات الرئيسية"; - i18n["Module \"All files\""] = "قائمة \"كل الملفات\""; - i18n["Module \"Files need translate\""] = "قائمة \"الملفات التي تحتاج لترجمة\""; - i18n["Module \"Files need update\""] = "قائمة \"الملفات التي تحتاج لتحديث\""; - i18n["Module \"Files with error\""] = "قائمة \"الملفات التي بها خطأ\""; - i18n["Module \"Files need reviewed\""] = "قائمة \"الملفات التي تحتاج لمراجعة\""; - i18n["Force an UI language"] = "اعتماد لغة الواجهة"; - i18n["Default language, if available"] = "اللغة الافتراضية، إن وجدت"; - i18n["English"] = "English"; - i18n["French"] = "French"; - i18n["Russian"] = "Russian"; - i18n["Spanish"] = "Spanish"; - i18n["Arabic"] = "اللغة العربية"; - i18n["Black"] = "Black"; - i18n["Default"] = "Default"; - i18n["DarkGray"] = "DarkGray"; - i18n["Gray"] = "Gray"; - i18n["Gray Extend"] = "Gray Extend"; - i18n["Indigo"] = "Indigo"; - i18n["Midnight"] = "Midnight"; - i18n["Olive"] = "Olive"; - i18n["Purple"] = "Purple"; - i18n["SilverCherry"] = "SilverCherry"; - i18n["Ubuntu Human"] = "Ubuntu Human"; - i18n["User Interface"] = "واجهة الاستخدام"; - i18n["Main menu width"] = "قياس عرض القائمة الرئيسية"; - i18n["Appearance"] = "المظهر"; - i18n["Choose a theme"] = "اختر سمة المظهر"; - i18n["On save file"] = "عند حفظ الملف"; - i18n["Ask me if I want to check for error before saving the file"] = "اسأل إذا كنت أريد فحص الملف للأخطاء"; - i18n["Always check for error before saving the file"] = "دائما افحص الملف للأخطاء قبل حفظه"; - i18n["Never check for error before saving the file"] = "لا تفحصل الملف للأخطاء قبل الحفظ"; - i18n["External Data"] = "بيانات خارجية"; - i18n["About mails"] = "حول البريد"; - i18n["Load mail at startUp"] = "حمل البريد عند البدء"; - i18n["About bugs"] = "حول المشاكل Bugs"; - i18n["Load bugs at startUp"] = "حمل قائمة المشاكل bugs عند البدء"; - i18n["Menu"] = "القائمة"; - i18n["Nb files to display"] = "عدد الملفات للعرض"; - i18n["files to display"] = "عرض الملفات"; - i18n["0 means no limit"] = "0 يعني بدون حدود"; - i18n["ScrollBars"] = "أشرطة التمرير"; - i18n["Editor"] = "المحرر"; - i18n["SpellChecking"] = "التدقيق الإملائي"; - i18n["Enable spell checking"] = "تفعيل التدقيق الإملائي"; - i18n["Automatically load the log when displaying the file"] = "تحميل سجل الرسائل تلقائياً عند فتح الملف"; - i18n["Start with the panel open"] = "ابدأ باللوحة مفتوحة"; - i18n["Panel width"] = "قياس عرض اللوحة"; - i18n["Diff view"] = "عرض الاختلافات"; - i18n["Panel height"] = "قياس ارتفاح اللوحة"; - i18n["Using ViewVc from php web site"] = "استخدام ViewVc من موقع php"; - i18n["Using diff -u command line"] = "استخدم أمر diff -u command line"; - i18n["Enable spell checking for the {0} file"] = "تفعيل التدقيق الإملائي لملفات {0}"; - i18n["Error type"] = "نوع الخطأ"; - i18n["Skip nbLiteralTag error"] = "تجاهل خطأ nbLiteralTag "; - i18n["Patch content"] = "محتويات الحزمة"; - i18n["Configuration"] = "التهيئة"; - i18n["All changes take effect immediately"] = "اعتماد كل التغييرات مباشرة"; - i18n["Automatically load acronyms data when displaying the file"] = "تحميل قائمة المصطلحات عند فتح الملف"; - i18n["Automatically load entities data when displaying the file"] = "تحميل قائمة المكونات عند فتح الملف"; - i18n["Right panel"] = "اللوحة اليمنى"; - i18n["Display the original file"] = "عرض الملف الأصلي"; - i18n["Do not display a right panel"] = "لا تعرض اللوحة اليمنى"; - i18n["Display the Google Translation Panel"] = "عرض لوحة خدمة ترجمة جوجل"; - i18n["Display EN work in \"Work in progress\" & \"Patches for review\" modules"] = "عرض قائمة ملفات اللغة الإنجليزية ضمن قائمة \"قيد العمل والإنجاز\" و \"قائمة الحزم للمراجعة\" "; - - -// In file: ../../js/ui/component/CheckEntities.js - i18n["Entities"] = "المكونات"; - i18n["Url"] = "Url"; - i18n["Result"] = "النتيجة"; - i18n["Status: "] = "الحالة: "; - i18n["All status"] = "الحالة الإجمالية"; - - -// In file: ../../js/ui/component/PendingTranslateGrid.js - i18n["Need translate: in {0}"] = "تحتاج إلى ترجمة: في {0}"; - i18n["Need file: in {0}"] = "تحتاج إلى ملف: في {0}"; - i18n["New file: "] = "ملف جديد: "; - i18n["Automatic translation: "] = "ترجمة تلقائية: "; - i18n["Dictionary"] = "قاموس"; - i18n["File modified by me"] = "ملف معدل بواسطتي"; - i18n["File modified by {0}"] = "مل معدل من قبل {0}"; - - -// In file: ../../js/ui/component/EmailPrompt.js - i18n["Send an email"] = "أرسل بريد إلكتروني"; - i18n["Send"] = "أرسل"; - i18n["Status"] = "الحالة"; - i18n["Email sent to {0} with success!"] = "تم إرسال رسالة إلى {0} بنجاح!"; - i18n["Cancel"] = "إلغاء"; - i18n["Send To"] = "أرسل إلى"; - i18n["Subject"] = "العنوان"; - - -// In file: ../../js/ui/component/PatchPrompt.js - i18n["Do you want to be alerted ?"] = "هل تريد أن يتم تنبيهك؟"; - i18n["Save"] = "حفظ"; - i18n["If you want to be notified when your patch will be dealt with, thank you to leave an email address below."] = "إذا كنت تريد إعلامك عندما يتم التعامل مع مجموعاتك من الملفات، نرجو ترك عنوانك بريدك الإلكتروني هنا مشكورا"; - - -// In file: ../../js/ui/component/ExecDiff.js - i18n["Loading..."] = "تحميل..."; - - -// In file: ../../js/ui/component/MainMenu.js - i18n["Verify if there is an update in progress. Please, wait..."] = "جاري التأكد من وجود تحديثات. يرجى الانتظار..."; - i18n["Build tools"] = "أدوات البناء"; - i18n["Check build"] = "فحص البناء"; - i18n["Verify if there is a check in progress. Please, wait..."] = "جاري التأكد من وجود عملية فحص. يرجى الانتظار..."; - i18n["Show last failed build"] = "عرض آخر عملية بناء فشلت"; - i18n["Last failed build"] = "آخر عملية بناء فاشلة"; - i18n["EN tools"] = "EN tools"; - i18n["Script check entities"] = "Script check entities"; - i18n["View the last result"] = "عرض النتيجة الأخيرة"; - i18n["Run this script"] = "تنفيذ البرنامج"; - i18n["Verify if there is an entities check in progress. Please, wait..."] = "جاري التأكد من وجود عملية فحص. يرجى الانتظار..."; - i18n["There is currently a check in progress for the entities.
You can't perform a new check now."] = "هناك عملية فحص جارية للمكونات.
لا تستطيع تنفيذ عملية فحص جديدة الآن."; - i18n["There is currently a check in progress for this language.
You can't perform a new check now."] = "توجد عملية فحص جارية لهذه اللغة.
لا تستطيع تنفيذ عملية فحص جديدة الآن."; - i18n["There is currently an update in progress.
You can't perform an update now."] = "هناك عملية تحديث جارية.
لا تستطيع تنفيذ عملية تحديث الآن."; - i18n["Script check document"] = "Script check document"; - i18n["Configure"] = "الإعدادات"; - i18n["Switch to language..."] = "الانتقال إلى لغة..."; - i18n["Erase my personal data"] = "امسح بياناتي الشخصية"; - i18n["This action will erase your personal data. All content about this account will be deleted definitively. Are you sure you want to do that ?"] = "هذا الإجراء سوف يمسح بيانات الشخصية. كل البيانات المتعلقة بهذا الحساب سوف تحذف نهائياً. هل أنت واثق من هذا؟"; - i18n["Thanks !"] = "شكراً لك !"; - i18n["Thank you for using this application !"] = "شكراً لاستخدامك البرنامج !"; - i18n["Log out"] = "تسجيل خروج"; - i18n["Are you sure you want to logout?"] = "هل ترغب فعلاً في تسجيل الخلاوج؟"; - i18n["Report bugs"] = "بلغ عن المشاكل bugs"; - i18n["Documentation"] = "التعليمات"; - i18n["About"] = "حول البرنامج"; - i18n["Chat with us on IRC !"] = "Chat with us on IRC !"; - - -// In file: ../../js/ui/component/VCSLogGrid.js - i18n["Rev."] = "الإصدار."; - i18n["Content"] = "المحتوى"; - i18n["By"] = "بواسطة"; - i18n["(You can change this behavior by setting an option in the configuration window)"] = "(تستطيع تغيير هذا الاسلوب من خلال الإعدادات)"; - i18n["View the diff"] = "عرض الاختلافات"; - i18n["Finding the diff. Please, wait..."] = "جاري البحث عن الاختلافات، يرجى الانتظار..."; - i18n["Diff between {0} & {1}"] = "الاختلافات بين {0} & {1}"; - i18n["Load/Refresh revisions"] = "تحميل/تحديث الإصدارات"; - - -// In file: ../../js/ui/component/DictionnaryGrid.js - i18n["Add a new word"] = "إضافة كلمة جديدة"; - i18n["Delete this word"] = "حذف هذه الكلمة"; - i18n["En word"] = "كلمة إنجليزية"; - i18n["{0} word"] = "{0} كلمة"; - i18n["Last User Update"] = "آخر تحديث من قبل المستخدم"; - i18n["Last Date Update"] = "تاريخ آخر تحديث"; - i18n["Word in dictionnary added/updated"] = "تمت إضافة/تحديث كلمة في القاموس"; - i18n["The word have been added/updated successfully !"] = "تمت إضافة/تحديث كلمة في القاموس بنجاح !"; - i18n["Word deleted"] = "تم حذف الكلمة"; - i18n["The word was deleted successfully !"] = "تم حذف الكلمة بنجاح !"; - - -// In file: ../../js/ui/component/PendingReviewGrid.js - i18n["Reviewed"] = "تمت المراجعة"; - i18n["Open all files about {0} extension"] = "فتح كل الملفات حول توسعة {0} "; - i18n["Need Reviewed in: {0}"] = "تحتاج إلى مراجعة في: {0}"; - - -// In file: ../../js/ui/component/GoogleTranslationPanel.js - i18n["String to translate (en => {0})"] = "النص للترجمة (en => {0})"; - i18n["Translate !"] = "ترجمة !"; - - -// In file: ../../js/ui/component/PortletSummary.js - i18n["Up to date files"] = "ملفات محدثة"; - i18n["Stale files"] = "ملفات غير مكتملة"; - i18n["Files available for translation"] = "ملفات متاحة للترجمة"; - i18n["Total"] = "الإجمالي"; - i18n["File status type"] = "نوع حالة الملفات"; - i18n["Number of files"] = "عدد الملفات"; - i18n["Percent of files"] = "نسبة الملفات"; - i18n["Size of files (kB)"] = "حجم الملفات (kB)"; - i18n["Percent of size"] = "نسبة الحجم"; - - -// In file: ../../js/ui/component/PortletLocalMail.js - i18n["Title"] = "العنوان"; - i18n["Error when loading mails from this mailing list !"] = "حدث خطأ عند تحميل البريد من هذه القائمة !"; - i18n["Mail from {0}"] = "رسالة من {0}"; - - -// In file: ../../js/ui/component/CheckBuildPrompt.js - i18n["You're about to check the build via this command:"] = "أنت على وشكل فحص البناء بهذا الأمر:"; - i18n["WARNING !
This option use a lot of server ressource. If you don't know what are the consequence, please, don't use it."] = "تنبيه !
هذا الخيار يستخدم موارد الجهاز بشكل كثيف. إذا لم تكن تعرف العواقب جيدأً يرجى عدم استخدامه."; - i18n["Enable detailed XML error messages"] = "تفعيل رسائل الأخطاء XML-Errors المفصلة "; - - -// In file: ../../js/ui/component/About.js - i18n["About {0}"] = "حول {0}"; - i18n["Author:"] = "المؤلف:"; - i18n["and others"] = "و آخرون"; - i18n["Credits"] = "مساهمون"; - i18n["Javascript FrameWork"] = "Javascript FrameWork"; - i18n["Code editor"] = "Code editor"; - i18n["Icon pack"] = "Icon pack"; - i18n["License"] = "License"; - i18n["Help and support"] = "Help and support"; - i18n["Mailing list:"] = "Mailing list:"; - i18n["IRC:"] = "IRC:"; - i18n["Web IRC Chat"] = "Web IRC Chat"; - - -// In file: ../../js/ui/component/NotInENGrid.js - i18n["View in a new tab"] = "العرض في تبويب جديد"; - i18n["Remove this file"] = "حذف هذا الملف"; - i18n["File removed by me"] = "تم حذف الملف بواسطتي"; - i18n["File removed by {0}"] = "تم حذف الملف من قبل {0}"; - i18n["Not In EN: in {0}"] = "ملفات ليست ضمن اللغة الإنجليزية: في {0}"; - - -// In file: ../../js/ui/component/CommitLogManager.js - i18n["Update"] = "تحديث"; - i18n["Message updated"] = "تم تحديث الرسالة"; - i18n["Log Message was updated successfully !"] = "تم تحديث الرسالة بنجاح !"; - i18n["Delete this Log Message"] = "احذف هذه الرسالة"; - i18n["Message deleted"] = "تم حذف الرسالة"; - i18n["Log Message was deleted successfully !"] = "تم حذف الرسالة بنجاح !"; - i18n["Manage Log Message"] = "معالجة رسائل السجلات"; - - -// In file: ../../js/ui/component/StaleFileGrid.js - i18n["EN revision"] = "EN revision"; - i18n["View diff..."] = "عرض الاختلافات..."; - i18n["... of the {0} file"] = "... لملف {0} "; - i18n["Need Update: in {0}"] = "تحتاج لتحديث: في {0}"; - i18n["{0} revision"] = "{0} revision"; - - i18n["File EN modified by me"] = "File EN modified by me"; - i18n["File EN modified by {0}"] = "File EN modified by {0}"; - - i18n["File {0} modified by me"] = "ملف {0} معدل بواسطتي"; - i18n["File {0} modified by {1}"] = "ملف {0} معدل من قبل {1}"; - i18n["{0} mine"] = "{0} تؤول إلي"; - - -// In file: ../../js/ui/task/PingTask.js - i18n["check in progress..."] = "جاري الفحص..."; - - -// In file: ../../js/ui/task/SaveTransFileTask.js - i18n["Saving data..."] = "حفظ البيانات..."; - i18n["Document saved"] = "تم حفظ الوثيقة"; - i18n["Document

{0}

was saved successfully !"] = "تم حفظ الوثيقة

{0}

بنجاح !"; - i18n["There is somes XML's errors.

You must fix it before saving this file.

Valid this window to show this errors."] = "هناك بعض الأخطاء XML's errors.

يجب أن تعالج قبل الحفظ.

تابع هذه النافذة لعرض الخطأ."; - - -// In file: ../../js/ui/task/GetGGTranslation.js - - -// In file: ../../js/ui/task/SystemUpdateTask.js - i18n["Finish !"] = "انتهى !"; - - -// In file: ../../js/ui/task/SavePatchTask.js - i18n["Saving data as a patch..."] = "حفظ البيانات على شكل حزمة..."; - i18n["Patch saved"] = "تم حفظ الحزمة"; - i18n["Patch saved successfully !"] = "تم حفظ الحزمة بنجاح !"; - - -// In file: ../../js/ui/task/CheckEntitiesTask.js - i18n["Please, wait until entities are checked..."] = "يرجى الانتظار حتى تتم مراجعة المكونات..."; - - -// In file: ../../js/ui/task/VCSCommitTask.js - i18n["Please, wait until commit..."] = "يرجى الانتظار حتى يتم الاعتماد..."; - i18n["The log message is required."] = "رسالة السجل مطلوبة."; - i18n["You must choose at least one file."] = "يجب أن تختار ملفاً واحداً على الأقل."; - i18n["There are {0} files to close before commit.

{1}

Would you like me to close them for you ?"] = "هناك عدد {0} ملفات يجب أن تغلق قبل الاعتماد.

{1}

هل تريد إغلاقها ?"; - i18n["There is {0} file to close before commit.

{1}

Would you like me to close it for you ?"] = "هناك عدد {0} ملفات يجب أن تغلق قبل الاعتماد.

{1}

هل تريد إغلاقها ?"; - - -// In file: ../../js/ui/task/MarkDeleteTask.js - i18n["This action will mark this file as need deleted.

You need commit this change to take it effect.

Please, confirm this action."] = "هذا الإجراء سيضع علامة مطلوب الحذف على الملف.

يجب أن تعتمد هذا التغيير ليتم تطبيقه.

الرجاء التأكيد."; - - -// In file: ../../js/ui/task/ClearLocalChangeTask.js - i18n["This action will clear your local modification and take back this file from his original stats.
You need confirm."] = "هذا الإجراء سوف يلغي التعديلات ويعيده إلى حالته الأصلية..
الرجاء التأكيد."; - - -// In file: ../../js/ui/task/GetFileTask.js - i18n["Permanent link to this page"] = "رابط دائم لهذه الصفحة"; - i18n["Warning"] = "تحذير"; - i18n["The editor have modified automatically the file {0} into UTF-8 encoding."] = "قام المحرر بتغيير الملف {0} تتلقائياً إلى ترميز UTF-8 ."; - i18n["The file {0} contains some tab characters.
The editor have replace it with space characters."] = "الملف {0} يحتوي على رموز الجدولة TAB.
قام المحرر باستبدالها إلى مسافة."; - i18n["File modified by {0} (anonymous user) but you are an authenticated user, so you can modify it."] = "هذا الملف معدل من قبل {0} (مستخدم غير معرف) ولكن أنت مستخدم معرف لك الصلاحية لتعديله."; - i18n["File modified by {0}."] = "هذا الملف معدل من قبل {0}."; - - -// In file: ../../js/ui/task/UpdateConfTask.js - i18n["Option saved"] = "تم حفظ الإعداد"; - i18n["Option has been saved successfully !"] = "تم حفظ الإعداد بنجاح !"; - - -// In file: ../../js/ui/task/RejectPatchTask.js - i18n["This action will reject this patch, send an email to his author and close this tab."] = "سوف يقوم هذا الإجراء برفض هذه الحزمة، وإرسال رسالة إلى صاحبها وإغلاق هذا التبويب."; - i18n["Patch rejected successfully"] = "تم رفض الحزمة بنجاح"; - i18n["The Patch was rejected successfully !"] = "تم رفض الحزمة بنجاح !"; - - -// In file: ../../js/ui/task/CheckBuildTask.js - i18n["Check build result for {0}"] = "فحص نتيجة البناء في {0}"; - i18n["Check build result for the documentation {0}"] = "فحص نتيجة البناء للتوثيق {0}"; - i18n["Please, wait until the build is checked..."] = "يرجى الانتظار حتى يتم فحص البناء..."; - - -// In file: ../../js/ui/task/CheckFileTask.js - i18n["Checking for error. Please, wait..."] = "البحث عن الأخطاء. يرجى الانتظار..."; - i18n["Check for errors"] = "البحث عن الأهطاء"; - i18n["There is no error."] = "لا توجد أخطاء."; - - -// In file: ../../js/ui/task/AcceptPatchTask.js - i18n["This action will accept this patch, send an email to his author, save the file and close this tab."] = "هذا الإجراء سيعتمد هذه الحزمة، ويرسل رسالة لصاحبها ثم حفظها وإغلاق التبويب."; - i18n["Patch accepted successfully"] = "تم اعتماد الحزمة بنجاح"; - i18n["The Patch was accepted successfully !"] = "تم اعتماد الحزمة بنجاح !"; - - -// In file: ../../ux/extjsPowered/TabCloseMenu.js - i18n["Close Other Tabs"] = "إغلاق التبويبات الأخرى"; - i18n["Close All Tabs"] = "إغلاق كل التبويبات"; - - -// In file: ../../ux/others/main_specific/Ext.ux.UserNotes.js - i18n["Notes ({0})"] = "الملاحظات ({0})"; - i18n["Add a new note"] = "إضافة ملاحظة جديدة"; - i18n["Add"] = "إضافة"; - i18n["Delete this note"] = "حذف هذه الملاحظة"; - i18n["No user notes"] = "لا توجد ملاحظات"; - i18n["Right click to add a new note"] = "اضغط بالزر الأيمن لإضافة ملاحظة"; - i18n["Note added"] = "تمت إضافة الملاحظة"; - i18n["The note was added successfully !"] = "تمت إضافة الملاحظة بنجاح !"; - i18n["Note deleted"] = "تم حذف الملاحظة"; - i18n["The note was deleted successfully !"] = "تم حذف الملاحظة بنجاح !"; - - -// In file: ../../js/ui/task/CheckXml.js - i18n["XML check. Please, wait..."] = "فحص XML. يرجى الانتظار..."; - i18n["XML check"] = "فحص XML"; - - -// In file: ../../js/ui/cmp/CheckXmlWin.js - i18n["Line"] = "سطر"; - i18n["Libel"] = "صياغة"; - i18n["XML Errors"] = "XML Errors"; - -// In file: ../../js/ui/cmp/ChangeFileOwner.js - i18n["Current owner"] = "مالك الملف حالياً"; - i18n["Action"] = "إجراء"; - i18n["New owner"] = "مالك جديد"; - i18n["Change file's owner"] = "تغيير مالك الملف"; - -// In file: ../../js/ui/task/ChangeFileOwner.js - i18n["Owner changed"] = "تم تغيير مالك الملف"; - i18n["The owner for this file have been changed successfully !"] = "تم تغيير مالك الملف بنجاح !"; - -// In file: ../../js/ui/cmp/AnonymousPatchWin.js - i18n["Next"] = "التالي"; - i18n["Anonymous patch manager"] = "مدير حزم ملفات المستخدمين غير المعرفين"; - i18n["You have opened a modified file from the \"Patch for review\" module.
This file has been modified by an anonymous user.

Please choose one of the following actions:"] = "لقد فتحت ملفاً معدلاً ضمن قائمة \"حزم تحتاج لمراجعة\" .
هذا الملف تم تعديلها من قبل مستخدم غير معرف.

الرجاء اختيار أحد الإجراءات التالية:"; - i18n["Continue to modify this file"] = "الاستمرار في تعديل الملف"; - i18n["This action will open this file for modification. Once your modification finish, just save it and this file will be own by you."] = "هذا الإجراء سيفتح الملف للتعديل. عندما تنتهي من التعديل قم بحفظ الملف وسيتم تغيير ملكية الملف إليك."; - i18n["Reject this patch"] = "رفض هذه الحزمة"; - i18n["This action will close this file, and clear the local change. This file will return into his original version, as it is on VCS server."] = "هذا الإجراء سيغلق الملف، ويلغي التعديلات التي تمت عليه. وسيعيد الملف إلى حالته الأصلية المحفوظة على خادم VCS."; - i18n["Validate this patch"] = "مراجعة الملف"; - i18n["This action changes the owner of the modification and register it under your name. The file will appear under your name and you can then commit it."] = "هذا الإجراء سيغير ملكية الملف إليك. سوف يظهر الملف تحت اسمك وسيمكنك اعتماده."; - -// In file: ../../js/ui/cmp/PreviewFile.js - i18n["Preview"] = "استعراض"; +/* +* This file must be encoded in UTF-8 +*/ + +var i18n = new Array(); + +// In file: ../../js/main.js + i18n["Refresh"] = "تحديث"; + i18n["Forbidden"] = "غير مسموح"; + i18n["You can't do this action as anonymous user."] = "لا يمكنك تنفيذ هذا الإجراء كمستخدم غير معرف."; + i18n["Error"] = "خطأ"; + i18n["File system error. Check read/write permission under data folder."] = "خطأ في نظام الملفات. يرجى التأكد من صلاحية القراءة/الكتابة في مجلد البيانات."; + i18n["Main menu"] = "القائمة الرئيسية"; + i18n["Topic:"] = "رسالة:"; + i18n["Defined by {0}, {1}"] = "تم تسجيلها من قبل {0}, {1}"; + i18n["Files need translate"] = "ملفات تحتاج إلى ترجمة"; + i18n["Files need update"] = "ملفات تحتاج إلى تحديث"; + i18n["Error in current translation"] = "خطأ في الترجمة الحالية"; + i18n["Files need reviewed"] = "ملفات تحتاج إلى مراجعة"; + i18n["Not in EN tree"] = "ملفات ليست ضمن النسخة الإجليزية"; + i18n["All files"] = "كل الملفات"; + i18n["Open the Log Message Manager"] = "افتح إدارة سجل الرسائل"; + i18n["Work in progress"] = "قيد العمل والإنجاز"; + i18n["Patches for review"] = "حزم ملفات للمراجعة"; + i18n["Google translation"] = "خدمة جوجل للترجمة"; + i18n["Home"] = "الرئيسية"; + i18n["Connected as"] = "متصل باسم"; + i18n["Connected using"] = "متصل باستخدام"; + i18n["anonymous"] = "غير معروف"; + i18n["Administrator"] = "المدير"; + i18n["You are a global Administrator"] = "لديك صلاحية الإدارة الكلية"; + i18n["You are an administrator for this language"] = "لديك صلاحية الإدارة لهذه اللغة"; + i18n["Project: "] = "المشروع:"; + i18n["Language: "] = "اللغة:"; + i18n["Total number of your files"] = "إجمالي عدد ملفاتك"; + i18n["You have used characters that require the use of UTF-8 despite the XML header.
Please delete these characters or change the header of the XML file in UTF-8 ; i.e.:

<?xml version=\"1.0\" encoding=\"utf-8\"?>
"] = "لقد استخدمت حروفاً تتطلب اعتماد ترميز UTF-8 على غرار معلومات الملف الرأسية.
يرجى إلغاء هذه الحروف أو تغيير الترميز إلى UTF-8 ; على سبيل المثال:

"; + i18n["It seems that you have inserted some tabs caracters into this file. Please, replace each one by one space.
Tip: You can use the \"Re-indent all this file\" button to replace all tabs by spaces."] = "يبدو أنك قد أدخلت بعض الفراغات باستخدم زر الجدولة tabs. يرجى استبدالها بالمسافة.
تلميح: تستطيع استخدام أمر \"إعادة تصفيف هذا الملف\" للقيام بذلك تلقائياً."; + i18n["You can't modify this file as it was modify by another user. Contact an administrator if you want to be able to modify it."] = "لا تستطيع تعديل هذا الملف لأنه معدل من قبل مستخدم آخر. يرجى التواصل مع الإدارة حتى تتمكن من تعديله."; + i18n["The patch you want to delete didn't exist."] = "حزمة الملفات التي ترغب في حذفها غير موجودة."; + i18n["The patch you want to delete isn't own by you. Only the user how create it or a global administrator can delete it."] = "حزمة الملفات التي ترغب في حذفها مسجلة باسم مستخدم آخر. فقط المستخدم صاحب الحزمة أو المدير العام يستطيع حذفها."; + i18n["This action is available only to global administrator."] = "هذا الإجراء متاح فقط للمدير العام."; + i18n["This action is available only to global administrator or to administrator for this lang."] = "هذا الإجراء متاح فقط للمدير العام أو من له صلاحية إدارة هذه اللغة."; + i18n["The file you want to clear local change isn't own by you.
You can only do this action for yours files."] = "الملف الذي تريد إلغاء ترجمته ليس متاحاً لك.
تستطيع تنفيذ هذا الإجراء على ملفاتك فقط."; + +// In file: ../../js/ui/component/CheckDoc.js + i18n["Double-click the cell to open the file selection"] = "اضغط بنقر مزدوج على المربع لفتح تحديد الملف"; + i18n["Extension"] = "التوسعة"; + i18n["Not documented"] = "غير موثقة"; + i18n["Old style"] = "نمط قديم"; + i18n["Bad refsect1 order"] = "ترتيب refsect1 غير صحيح"; + i18n["No parameters"] = "لا توجد مدخلات"; + i18n["No return values"] = "لا توجد قيم معادة"; + i18n["No examples"] = "لا توجد أمثلة"; + i18n["No errors section"] = "لا يوجد قسم للأخطاء"; + i18n["No see also"] = "لا توجد: اقرأ ايضاً"; + i18n["Refsect1 role error"] = "قاعدة Refsect1 غير صحية"; + i18n["Files"] = "ملفات"; + i18n["Open all files"] = "افتح كل الملفات"; + i18n["Open selected files"] = "افتح الملفات المحددة"; + i18n["Please, wait..."] = "الرجاء, انتظر..."; + +// In file: ../../js/ui/component/WorkTreeGrid.js + i18n["Modified by"] = "معدلة بواسطة"; + i18n["Date"] = "التاريخ"; + i18n["Y-m-d, H:i"] = "Y-d-m, H:i"; + i18n["Users"] = "المستخدمين"; + i18n["Last modified"] = "آخر تعديل"; + i18n["Estimated progress"] = "تقدير نسبة الإنجاز"; + i18n["{0}% complete"] = "{0}% منجز"; + i18n["Set the progress..."] = "تحديد نسبة الإنجاز..."; + i18n["View diff"] = "عرض الاختلافات"; + i18n["Download the diff as a patch"] = "تحميل الاختلافات على شكل حزمة"; + i18n["Clear this change"] = "إلغاء هذا التعديل"; + i18n["Cancel this deletion"] = "تراجع عن هذا الحذف"; + i18n["Submit all files for review in patch:"] = "ارسل كل الملفات للمراجعة ضمن حزمة:"; + i18n["Submit all files in this directory in patch:"] = "ارسل كل الملفات في هذا المجلد ضمن حزمة:"; + i18n["Submit as patch for review in:"] = "ارسل للمراجعة ضمن حزمة:"; + i18n["Create a new patch"] = "إنشاء حزمة جديدة"; + i18n["Commit..."] = "اعتمد..."; + i18n["...this file"] = "...هذا الملف"; + i18n["...all files from this folder"] = "...كل الملفات في هذا المجلد"; + i18n["...all files from this patch"] = "...كل الملفات في هذه الحزمة"; + i18n["...all files modified by me"] = "...كل الملفات المعدلة بواسطتي"; + i18n["You have no patch currently. You must create one."] = "ليست لديك حزمة حالياً. يجب أن تنشئ حزمة."; + i18n["Diff for file: {0}"] = "الاختلافات للملف: {0}"; + i18n["Administrator menu"] = "قائمة الإدارة"; + + +// In file: ../../js/ui/component/PatchesTreeGrid.js + i18n["Edit the description of this patch"] = "عدل وصف هذه الحزمة:"; + i18n["Delete this patch"] = "احذف هذه الحزمة"; + i18n["Back all files to work in progress module"] = "إعادة كل الملفات إلى قائمة قيد العمل والإنجاز"; + i18n["Back all this patch to work in progress module"] = "إعادة هذه الحزمة إلى قائمة قيد العمل والإنجاز"; + i18n["Back all this folder to work in progress module"] = "إعادة هذا المجلد إلى قائمة قيد العمل والإنجاز"; + i18n["Back this file to work in progress module"] = "إعادة هذا الملف إلى قائمة قيد العمل والإنجاز"; + i18n["Creation date: "] = "تاريخ الإنشاء:"; + i18n["View unified diff"] = "عرض الاختلافات الموحدة"; + i18n["Download the unified diff as a patch"] = "تحميل الاختلافات الموحدة على شكل حزمة"; + + +// In file: ../../js/ui/component/ManagePatchPrompt.js + i18n["Create"] = "إنشاء"; + i18n["Modify this patch description"] = "عدل وصف هذه الحزمة"; + i18n["Patch name"] = "اسم الحزمة"; + i18n["Patch description"] = "وصف الحزمة"; + i18n["This description will be the default during the validation of the patch by a valid user."] = "هذا الوصف سيكون افتراضياً لهذه الحزمة عند مراجعتها من قبل مستخدم معرف."; + i18n["If provided, an email will be send to you to inform that the patch is commited."] = "إذا تم تسجيل بريد إلكتروني سوف تتم مراسلتك لإبلاغك عند اعتماد هذه الحزمة."; + +// In file: ../../js/ui/task/DeletePatchTask.js + i18n["Patch deleted"] = "تم حذف الحزمة"; + i18n["The patch have been deleted !"] = "الحزمة تم حذفها!"; + +// In file: ../../js/ui/component/ViewVCDiff.js + i18n["Diff From VCS"] = "الاختلافات عن VCS"; + +// In file: ../../js/ui/component/CommitPrompt.js + i18n["VCS commit"] = "اعتماد VCS"; + i18n["Configure this tools"] = "تهيئة هذه الأدوات"; + i18n["Submit"] = "إرسال"; + i18n["Close"] = "إغلاق"; + i18n["Older messages"] = "رسائل قديمة"; + i18n["No log message currently"] = "لا توجد سجلات رسائل حالياً"; + i18n["Log message"] = "رسالة سجل"; + + +// In file: ../../js/ui/component/PortletTranslationGraph.js + i18n["Graphics"] = "رسومات بيانية"; + i18n["Refresh this graph"] = "تحديث هذه الرسمة"; + + +// In file: ../../js/ui/component/PortletInfo.js + i18n["Information"] = "معلومات"; + i18n["Since"] = "منذ"; + i18n["{0} year(s)"] = "{0} سنة/سنوات"; + i18n["{0} month(s)"] = "{0} شهر/شهور"; + i18n["{0} week(s)"] = "{0} اسبوع/اسابيع"; + i18n["{0} day(s)"] = "{0} يوم/أيام"; + i18n["{0} hour(s)"] = "{0} ساعة/ساعات"; + i18n["{0} minute(s)"] = "{0} دقيقة/دقائق"; + i18n["{0} second(s)"] = "{0} ثانية/ثواني"; + i18n["Less than one second"] = "أقل من ثانية واحدة"; + i18n["{0} check all entitites"] = "{0} فحص كل المكونات"; + i18n["{0} updated app's data"] = "{0} حدث بيانات التطبيقات"; + i18n["{0} logged out"] = "{0} قام بتسجيل الخروج"; + i18n["{0} is logged in using the {1} language"] = "{0} قام بتسجيل الدخول ضمن لغة {1}"; + i18n["{0} committed {1} new folder(s) in the {2} language"] = "{0} اعتمد {1} مجلد/مجلدات جديدة ضمن لغة {2} "; + i18n["{0} committed {1} file(s) ({2} new, {3} update, {4} delete) in the language {5}"] = "{0} اعتمد {1} ملف/ملفات ({2} جديدة، {3} معدلة {4} محذوفة) ضمن لغة {5}"; + i18n["{0} changed file\'s owner"] = "{0} غير صلاحية الملف"; + + +// In file: ../../js/ui/component/ErrorFileGrid.js + i18n["Type"] = "النوع"; + i18n["Maintainer"] = "المتعهد"; + i18n["Path"] = "المسار"; + i18n["No Files"] = "لا توجد ملفات"; + i18n["File"] = "ملف"; + i18n["Edit in a new tab"] = "التعديل في تبويب جديد"; + i18n["Diff"] = "الاختلافات"; + i18n["About error type"] = "حول أنواع الخطأ"; + i18n["File with error : in {0}"] = "ملف فيه خطأ : في {0}"; + i18n["Error description"] = "وصف الخطأ"; + i18n["VCS Log"] = "سجل VCS "; + i18n["Tools"] = "أدوات"; + i18n["{0} File: "] = "{0} File: "; + i18n["en File: "] = "en File: "; + i18n["Filter: "] = "تصفية: "; + i18n["Your filter must contain at least 3 characters"] = "عوامل التصفية يجب أن تتضمن 3 حروف على الأقل"; + + +// In file: ../../js/ui/component/PortletTranslationsGraph.js + i18n["Graphics for all languages"] = "الرسومات البيانية لكل اللغات"; + i18n["Lang:"] = "اللغة:"; + i18n["Total:"] = "الإجمالي:"; + i18n["files"] = "ملفات"; + + +// In file: ../../js/ui/component/EntitiesAcronymsPanel.js + i18n["Click on a row to display the content of the entitie.
Double-click on it to insert it at the cursor position."] = "اضغط على أحد الصفوف لعرض المحتويات.
اضغط بشكل مزدوج لإدخالها في الموضع الحالي."; + i18n["Click on a row to display the content of the acronym.
Double-click on it to insert it at the cursor position."] = "اضغط على أحد الصفوف لعرض محتويات المصطلح.
اضغط بشكل مزدوج لإدخالها في الموضع الحالي"; + i18n["Items"] = "عناصر"; + i18n["From"] = "من"; + i18n["Load/Refresh"] = "تحميل/تحديث"; + i18n["Entities & acronyms"] = "عناصر ومصطلحات"; + i18n["Acronyms"] = "مصطلحات"; + + +// In file: ../../js/ui/component/RepositoryTree.js + i18n["Repository"] = "مستودع الملفات"; + i18n["Collapse"] = "إخفاء"; + i18n["Expand"] = "توسعة"; + i18n["Open the same file in {0}"] = "افتح نفس الملف في {0}"; + i18n["Log"] = "Log"; + i18n["{0} Log"] = "{0} Log"; + i18n["File: "] = "ملف: "; + i18n["in {0}"] = "في {0}"; + i18n["Search: "] = "بحث: "; + i18n["Your search must contain at least 3 characters"] = "عبارة البحث يحب أن تحتوي 3 حروف على الأقل"; + i18n["Search result: {0}"] = "نتيجة البحث: {0}"; + i18n["Update this folder"] = "تحديث هذا المجلد"; + + i18n["Add a new folder"] = "إضافة مجلد جديدة"; + i18n["Parent Folder"] = "المجلد الأعلى"; + i18n["Name for the new folder"] = "اسم المجلد الجديد"; + i18n["Folder created"] = "تم إنشاء المجلد"; + i18n["Info: This new folder won't be commited until a new file will be commited into it. If you don't commit any new file into it until 8 days, it will be automatically deleted."] = "معلومات: لن يتم اعتماد المجلد الجديد حتى يتم اعتماد ملف جديد فيه. إذا لم يتم اعتماد أي ملفات فيها خلال 8 أيام فسيتم حذفه تلقائياً"; + i18n["Folder

{0}

was created sucessfully under {1} !"] = "المجلد

{0}

تم إنشاؤه بنجاح في {1} !"; + i18n["This folder already exist in the current folder."] = "هذا المجلد موجود مسبقاً ضمن المجلد الحالي."; + + i18n["Add a new file"] = "إضافة ملف جديد"; + i18n["This file already exist in the current folder."] = "هذا الملف موجود مسبقاً في المجلد الحالي"; + i18n["Name for the new file"] = "اسم الملف الجديد"; + i18n["Chose a skeleton"] = "اختر مخطط"; + i18n["Open the editor"] = "افتح المحرر"; + +// In file: ../../js/ui/component/CheckEntitiesPrompt.js + i18n["Check entities"] = "افحص المكونات"; + i18n["Go !"] = "انطلق !"; + i18n["You're about to check all entities.

This action takes time."] = "أنت على وشك فحص كل المكونات.

هذا الإجراء يتطلب وقتاً."; + + +// In file: ../../js/ui/component/PortletTranslator.js + i18n["{0} Translators"] = "مترجمي {0}"; + i18n["Name"] = "الاسم"; + i18n["Email"] = "بريد إلكتروني"; + i18n["Nick"] = "اسم المستخدم"; + i18n["VCS"] = "VCS"; + i18n["UptoDate"] = "ترجمة حديثة"; + i18n["Stale"] = "غير مكتملة"; + i18n["Sum"] = "مجموع"; + i18n["Send an email to the {0}"] = "أرسل بريد إلكتروني إلى {0}"; + i18n["Send an email to {0}"] = "أرسل بريد إلكتروني إلى {0}"; + i18n["Translators"] = "مترجمون"; + i18n["Refresh this grid"] = "تحديث هذا الجدول"; + + +// In file: ../../js/ui/component/BuildStatus.js + i18n["Last failed build for {0}"] = "آخر بناء لم ينجح {0}"; + i18n["Last failed build for the documentation {0}"] = "آخر بناء لم ينجح لكامل الدليل {0}"; + i18n["This log is too large and have been truncated. Use the following button to download the full content of it."] = "هذا السجل طويل جداً ويجب أن يختصر. استخدم الزر التالي لتحميله كاملاً."; + i18n["Download the full content of this log"] = "تحميل محتويات هذا السجل كاملاً"; + i18n["Language"] = "اللغة"; + + +// In file: ../../js/ui/component/SystemUpdatePrompt.js + i18n["Refresh all data"] = "تحديث كل البيانات"; + i18n["Update all files from VCS"] = "تحديث كل الملفات من VCS"; + i18n["This may take time. Thank you for your patience..."] = "هذا الإجراء يستغرق وقتاً، شكراً لانتظارك..."; + i18n["Apply all tools"] = "استخدم كل الأدومات"; + i18n["Reload data"] = "إعادة تحميل البيانات"; + i18n["Start"] = "إبدأ"; + i18n["update in progress..."] = "التحديث جاري..."; + + +// In file: ../../js/ui/component/PortletBugs.js + i18n["You must manually load this data.
Use the refresh button !"] = "يجب أن تقوم بتحميل هذه البيانات يدوياً.
استخدم زر التحديث !"; + i18n["Open in a new Tab"] = "افتح في تبويب جديد"; + i18n["Open the related file"] = "افتح الملفات ذات العلاقة"; + i18n["Summary"] = "الخلاصة"; + i18n["Error when loading open bugs from Php.net !"] = "حدث خطأ عند تحميل قائمة المشاكل bugs من موقع Php.net !"; + i18n["No open bugs"] = "لا توجد مشاكل bugs مفتوحة"; + i18n["Open bugs for {0}"] = "قائمة المشاكل bugs for {0}"; + + +// In file: ../../js/ui/component/MainPanel.js + i18n["Confirm"] = "تأكيد"; + i18n["This file has been modified without being saved.
Do you really want to close?"] = "هذا الملف تم تعديله ولم يحفظ.
هل تريد فعلاً إغلاقه؟"; + i18n["File: "] = "ملف: "; + i18n["Direct link to this patch"] = "رابط مباشر لهذه الحزمة"; + i18n["Diff for patch: {0}"] = "الاختلافات للحزمة: {0}"; + i18n["Patch Name: "] = "اسم الحزمة:"; + + +// In file: ../../js/ui/component/FilePanel.js + i18n["Undo"] = "تراجع"; + i18n["Redo"] = "إعادة"; + i18n["Close Tab"] = "إغلاق التبويب"; + i18n["Go to previous tab"] = "انتقل للتبويب السابق"; + i18n["Go to next tab"] = "انتقل للتبويب التالي"; + i18n["MarkUp"] = "MarkUp"; + i18n["Reviewed tag"] = "Reviewed tag"; + i18n["Revcheck tag"] = "Revcheck tag"; + i18n["Description section"] = "قسم الوصف"; + i18n["Parameters section"] = "قسم المدخلات"; + i18n["Return section"] = "قسم القيم العائدة"; + i18n["Error section"] = "قسم الأخطاء"; + i18n["Unicode section"] = "قسم Unicode "; + i18n["Changelog section"] = "قسم Changelog "; + i18n["Examples section"] = "قسم الأمثلة"; + i18n["Notes section"] = "قسم الملاحظات"; + i18n["SeeAlso section"] = "قسم SeeAlso"; + i18n["Enable / Disable spellChecking"] = "تفعيل / تعطيل التصحيح الإملائي"; + i18n["Re-indent all this file"] = "إعادة تصفيف هذا الملف"; + i18n["Synchronize scroll bars"] = "مزامنة أشرطة التمرير"; + i18n["Line: "] = "السطر:"; + i18n["Col: "] = "العمود:"; + i18n["Accept this patch and Save the file (CTRL+s)"] = "اعتمد هذه الحزمة واحفظ الملف (CTRL+s)"; + i18n["Reject this patch"] = "رفض هذه الحزمة"; + i18n["Save this file (CTRL+s)"] = "حفظ هذا الملف (CTRL+s)"; + i18n["Do you want to check for errors before saving?"] = "هل تريد فحص الأخطاء قبل الحفظ؟"; + i18n["Save as a patch"] = "الحفظ كـ حزمة"; + i18n["modified"] = "تم التعديل"; + i18n["Check XML with XmlLint"] = "افحص XML بواسطة XmlLint"; + i18n["Expand in a popup"] = "التوسيع في نافذة"; + i18n["Preview in a popup"] = "الاطلاع في نافذة"; + i18n["You must save your file in order to preview the result."] = "يجب أن تحفظ ملفات للاطلاع على النتيجة."; + i18n["Open for editing in a new Tab"] = "افتح للتعديل في تبويب جديد"; + + +// In file: ../../js/ui/component/EditorConf.js + i18n["Main"] = "الإعدادات الرئيسية"; + i18n["Module \"All files\""] = "قائمة \"كل الملفات\""; + i18n["Module \"Files need translate\""] = "قائمة \"الملفات التي تحتاج لترجمة\""; + i18n["Module \"Files need update\""] = "قائمة \"الملفات التي تحتاج لتحديث\""; + i18n["Module \"Files with error\""] = "قائمة \"الملفات التي بها خطأ\""; + i18n["Module \"Files need reviewed\""] = "قائمة \"الملفات التي تحتاج لمراجعة\""; + i18n["Force an UI language"] = "اعتماد لغة الواجهة"; + i18n["Default language, if available"] = "اللغة الافتراضية، إن وجدت"; + i18n["English"] = "English"; + i18n["French"] = "French"; + i18n["Russian"] = "Russian"; + i18n["Spanish"] = "Spanish"; + i18n["Arabic"] = "اللغة العربية"; + i18n["Black"] = "Black"; + i18n["Default"] = "Default"; + i18n["DarkGray"] = "DarkGray"; + i18n["Gray"] = "Gray"; + i18n["Gray Extend"] = "Gray Extend"; + i18n["Indigo"] = "Indigo"; + i18n["Midnight"] = "Midnight"; + i18n["Olive"] = "Olive"; + i18n["Purple"] = "Purple"; + i18n["SilverCherry"] = "SilverCherry"; + i18n["Ubuntu Human"] = "Ubuntu Human"; + i18n["User Interface"] = "واجهة الاستخدام"; + i18n["Main menu width"] = "قياس عرض القائمة الرئيسية"; + i18n["Appearance"] = "المظهر"; + i18n["Choose a theme"] = "اختر سمة المظهر"; + i18n["On save file"] = "عند حفظ الملف"; + i18n["Ask me if I want to check for error before saving the file"] = "اسأل إذا كنت أريد فحص الملف للأخطاء"; + i18n["Always check for error before saving the file"] = "دائما افحص الملف للأخطاء قبل حفظه"; + i18n["Never check for error before saving the file"] = "لا تفحصل الملف للأخطاء قبل الحفظ"; + i18n["External Data"] = "بيانات خارجية"; + i18n["About mails"] = "حول البريد"; + i18n["Load mail at startUp"] = "حمل البريد عند البدء"; + i18n["About bugs"] = "حول المشاكل Bugs"; + i18n["Load bugs at startUp"] = "حمل قائمة المشاكل bugs عند البدء"; + i18n["Menu"] = "القائمة"; + i18n["Nb files to display"] = "عدد الملفات للعرض"; + i18n["files to display"] = "عرض الملفات"; + i18n["0 means no limit"] = "0 يعني بدون حدود"; + i18n["ScrollBars"] = "أشرطة التمرير"; + i18n["Editor"] = "المحرر"; + i18n["SpellChecking"] = "التدقيق الإملائي"; + i18n["Enable spell checking"] = "تفعيل التدقيق الإملائي"; + i18n["Automatically load the log when displaying the file"] = "تحميل سجل الرسائل تلقائياً عند فتح الملف"; + i18n["Start with the panel open"] = "ابدأ باللوحة مفتوحة"; + i18n["Panel width"] = "قياس عرض اللوحة"; + i18n["Diff view"] = "عرض الاختلافات"; + i18n["Panel height"] = "قياس ارتفاح اللوحة"; + i18n["Using ViewVc from php web site"] = "استخدام ViewVc من موقع php"; + i18n["Using diff -u command line"] = "استخدم أمر diff -u command line"; + i18n["Enable spell checking for the {0} file"] = "تفعيل التدقيق الإملائي لملفات {0}"; + i18n["Error type"] = "نوع الخطأ"; + i18n["Skip nbLiteralTag error"] = "تجاهل خطأ nbLiteralTag "; + i18n["Patch content"] = "محتويات الحزمة"; + i18n["Configuration"] = "التهيئة"; + i18n["All changes take effect immediately"] = "اعتماد كل التغييرات مباشرة"; + i18n["Automatically load acronyms data when displaying the file"] = "تحميل قائمة المصطلحات عند فتح الملف"; + i18n["Automatically load entities data when displaying the file"] = "تحميل قائمة المكونات عند فتح الملف"; + i18n["Right panel"] = "اللوحة اليمنى"; + i18n["Display the original file"] = "عرض الملف الأصلي"; + i18n["Do not display a right panel"] = "لا تعرض اللوحة اليمنى"; + i18n["Display the Google Translation Panel"] = "عرض لوحة خدمة ترجمة جوجل"; + i18n["Display EN work in \"Work in progress\" & \"Patches for review\" modules"] = "عرض قائمة ملفات اللغة الإنجليزية ضمن قائمة \"قيد العمل والإنجاز\" و \"قائمة الحزم للمراجعة\" "; + + +// In file: ../../js/ui/component/CheckEntities.js + i18n["Entities"] = "المكونات"; + i18n["Url"] = "Url"; + i18n["Result"] = "النتيجة"; + i18n["Status: "] = "الحالة: "; + i18n["All status"] = "الحالة الإجمالية"; + + +// In file: ../../js/ui/component/PendingTranslateGrid.js + i18n["Need translate: in {0}"] = "تحتاج إلى ترجمة: في {0}"; + i18n["Need file: in {0}"] = "تحتاج إلى ملف: في {0}"; + i18n["New file: "] = "ملف جديد: "; + i18n["Automatic translation: "] = "ترجمة تلقائية: "; + i18n["Dictionary"] = "قاموس"; + i18n["File modified by me"] = "ملف معدل بواسطتي"; + i18n["File modified by {0}"] = "مل معدل من قبل {0}"; + + +// In file: ../../js/ui/component/EmailPrompt.js + i18n["Send an email"] = "أرسل بريد إلكتروني"; + i18n["Send"] = "أرسل"; + i18n["Status"] = "الحالة"; + i18n["Email sent to {0} with success!"] = "تم إرسال رسالة إلى {0} بنجاح!"; + i18n["Cancel"] = "إلغاء"; + i18n["Send To"] = "أرسل إلى"; + i18n["Subject"] = "العنوان"; + + +// In file: ../../js/ui/component/PatchPrompt.js + i18n["Do you want to be alerted ?"] = "هل تريد أن يتم تنبيهك؟"; + i18n["Save"] = "حفظ"; + i18n["If you want to be notified when your patch will be dealt with, thank you to leave an email address below."] = "إذا كنت تريد إعلامك عندما يتم التعامل مع مجموعاتك من الملفات، نرجو ترك عنوانك بريدك الإلكتروني هنا مشكورا"; + + +// In file: ../../js/ui/component/ExecDiff.js + i18n["Loading..."] = "تحميل..."; + + +// In file: ../../js/ui/component/MainMenu.js + i18n["Verify if there is an update in progress. Please, wait..."] = "جاري التأكد من وجود تحديثات. يرجى الانتظار..."; + i18n["Build tools"] = "أدوات البناء"; + i18n["Check build"] = "فحص البناء"; + i18n["Verify if there is a check in progress. Please, wait..."] = "جاري التأكد من وجود عملية فحص. يرجى الانتظار..."; + i18n["Show last failed build"] = "عرض آخر عملية بناء فشلت"; + i18n["Last failed build"] = "آخر عملية بناء فاشلة"; + i18n["EN tools"] = "EN tools"; + i18n["Script check entities"] = "Script check entities"; + i18n["View the last result"] = "عرض النتيجة الأخيرة"; + i18n["Run this script"] = "تنفيذ البرنامج"; + i18n["Verify if there is an entities check in progress. Please, wait..."] = "جاري التأكد من وجود عملية فحص. يرجى الانتظار..."; + i18n["There is currently a check in progress for the entities.
You can't perform a new check now."] = "هناك عملية فحص جارية للمكونات.
لا تستطيع تنفيذ عملية فحص جديدة الآن."; + i18n["There is currently a check in progress for this language.
You can't perform a new check now."] = "توجد عملية فحص جارية لهذه اللغة.
لا تستطيع تنفيذ عملية فحص جديدة الآن."; + i18n["There is currently an update in progress.
You can't perform an update now."] = "هناك عملية تحديث جارية.
لا تستطيع تنفيذ عملية تحديث الآن."; + i18n["Script check document"] = "Script check document"; + i18n["Configure"] = "الإعدادات"; + i18n["Switch to language..."] = "الانتقال إلى لغة..."; + i18n["Erase my personal data"] = "امسح بياناتي الشخصية"; + i18n["This action will erase your personal data. All content about this account will be deleted definitively. Are you sure you want to do that ?"] = "هذا الإجراء سوف يمسح بيانات الشخصية. كل البيانات المتعلقة بهذا الحساب سوف تحذف نهائياً. هل أنت واثق من هذا؟"; + i18n["Thanks !"] = "شكراً لك !"; + i18n["Thank you for using this application !"] = "شكراً لاستخدامك البرنامج !"; + i18n["Log out"] = "تسجيل خروج"; + i18n["Are you sure you want to logout?"] = "هل ترغب فعلاً في تسجيل الخلاوج؟"; + i18n["Report bugs"] = "بلغ عن المشاكل bugs"; + i18n["Documentation"] = "التعليمات"; + i18n["About"] = "حول البرنامج"; + i18n["Chat with us on IRC !"] = "Chat with us on IRC !"; + + +// In file: ../../js/ui/component/VCSLogGrid.js + i18n["Rev."] = "الإصدار."; + i18n["Content"] = "المحتوى"; + i18n["By"] = "بواسطة"; + i18n["(You can change this behavior by setting an option in the configuration window)"] = "(تستطيع تغيير هذا الاسلوب من خلال الإعدادات)"; + i18n["View the diff"] = "عرض الاختلافات"; + i18n["Finding the diff. Please, wait..."] = "جاري البحث عن الاختلافات، يرجى الانتظار..."; + i18n["Diff between {0} & {1}"] = "الاختلافات بين {0} & {1}"; + i18n["Load/Refresh revisions"] = "تحميل/تحديث الإصدارات"; + + +// In file: ../../js/ui/component/DictionnaryGrid.js + i18n["Add a new word"] = "إضافة كلمة جديدة"; + i18n["Delete this word"] = "حذف هذه الكلمة"; + i18n["En word"] = "كلمة إنجليزية"; + i18n["{0} word"] = "{0} كلمة"; + i18n["Last User Update"] = "آخر تحديث من قبل المستخدم"; + i18n["Last Date Update"] = "تاريخ آخر تحديث"; + i18n["Word in dictionnary added/updated"] = "تمت إضافة/تحديث كلمة في القاموس"; + i18n["The word have been added/updated successfully !"] = "تمت إضافة/تحديث كلمة في القاموس بنجاح !"; + i18n["Word deleted"] = "تم حذف الكلمة"; + i18n["The word was deleted successfully !"] = "تم حذف الكلمة بنجاح !"; + + +// In file: ../../js/ui/component/PendingReviewGrid.js + i18n["Reviewed"] = "تمت المراجعة"; + i18n["Open all files about {0} extension"] = "فتح كل الملفات حول توسعة {0} "; + i18n["Need Reviewed in: {0}"] = "تحتاج إلى مراجعة في: {0}"; + + +// In file: ../../js/ui/component/GoogleTranslationPanel.js + i18n["String to translate (en => {0})"] = "النص للترجمة (en => {0})"; + i18n["Translate !"] = "ترجمة !"; + + +// In file: ../../js/ui/component/PortletSummary.js + i18n["Up to date files"] = "ملفات محدثة"; + i18n["Stale files"] = "ملفات غير مكتملة"; + i18n["Files available for translation"] = "ملفات متاحة للترجمة"; + i18n["Total"] = "الإجمالي"; + i18n["File status type"] = "نوع حالة الملفات"; + i18n["Number of files"] = "عدد الملفات"; + i18n["Percent of files"] = "نسبة الملفات"; + i18n["Size of files (kB)"] = "حجم الملفات (kB)"; + i18n["Percent of size"] = "نسبة الحجم"; + + +// In file: ../../js/ui/component/PortletLocalMail.js + i18n["Title"] = "العنوان"; + i18n["Error when loading mails from this mailing list !"] = "حدث خطأ عند تحميل البريد من هذه القائمة !"; + i18n["Mail from {0}"] = "رسالة من {0}"; + + +// In file: ../../js/ui/component/CheckBuildPrompt.js + i18n["You're about to check the build via this command:"] = "أنت على وشكل فحص البناء بهذا الأمر:"; + i18n["WARNING !
This option use a lot of server ressource. If you don't know what are the consequence, please, don't use it."] = "تنبيه !
هذا الخيار يستخدم موارد الجهاز بشكل كثيف. إذا لم تكن تعرف العواقب جيدأً يرجى عدم استخدامه."; + i18n["Enable detailed XML error messages"] = "تفعيل رسائل الأخطاء XML-Errors المفصلة "; + + +// In file: ../../js/ui/component/About.js + i18n["About {0}"] = "حول {0}"; + i18n["Author:"] = "المؤلف:"; + i18n["and others"] = "و آخرون"; + i18n["Credits"] = "مساهمون"; + i18n["Javascript FrameWork"] = "Javascript FrameWork"; + i18n["Code editor"] = "Code editor"; + i18n["Icon pack"] = "Icon pack"; + i18n["License"] = "License"; + i18n["Help and support"] = "Help and support"; + i18n["Mailing list:"] = "Mailing list:"; + i18n["IRC:"] = "IRC:"; + i18n["Web IRC Chat"] = "Web IRC Chat"; + + +// In file: ../../js/ui/component/NotInENGrid.js + i18n["View in a new tab"] = "العرض في تبويب جديد"; + i18n["Remove this file"] = "حذف هذا الملف"; + i18n["File removed by me"] = "تم حذف الملف بواسطتي"; + i18n["File removed by {0}"] = "تم حذف الملف من قبل {0}"; + i18n["Not In EN: in {0}"] = "ملفات ليست ضمن اللغة الإنجليزية: في {0}"; + + +// In file: ../../js/ui/component/CommitLogManager.js + i18n["Update"] = "تحديث"; + i18n["Message updated"] = "تم تحديث الرسالة"; + i18n["Log Message was updated successfully !"] = "تم تحديث الرسالة بنجاح !"; + i18n["Delete this Log Message"] = "احذف هذه الرسالة"; + i18n["Message deleted"] = "تم حذف الرسالة"; + i18n["Log Message was deleted successfully !"] = "تم حذف الرسالة بنجاح !"; + i18n["Manage Log Message"] = "معالجة رسائل السجلات"; + + +// In file: ../../js/ui/component/StaleFileGrid.js + i18n["EN revision"] = "EN revision"; + i18n["View diff..."] = "عرض الاختلافات..."; + i18n["... of the {0} file"] = "... لملف {0} "; + i18n["Need Update: in {0}"] = "تحتاج لتحديث: في {0}"; + i18n["{0} revision"] = "{0} revision"; + + i18n["File EN modified by me"] = "File EN modified by me"; + i18n["File EN modified by {0}"] = "File EN modified by {0}"; + + i18n["File {0} modified by me"] = "ملف {0} معدل بواسطتي"; + i18n["File {0} modified by {1}"] = "ملف {0} معدل من قبل {1}"; + i18n["{0} mine"] = "{0} تؤول إلي"; + + +// In file: ../../js/ui/task/PingTask.js + i18n["check in progress..."] = "جاري الفحص..."; + + +// In file: ../../js/ui/task/SaveTransFileTask.js + i18n["Saving data..."] = "حفظ البيانات..."; + i18n["Document saved"] = "تم حفظ الوثيقة"; + i18n["Document

{0}

was saved successfully !"] = "تم حفظ الوثيقة

{0}

بنجاح !"; + i18n["There is somes XML's errors.

You must fix it before saving this file.

Valid this window to show this errors."] = "هناك بعض الأخطاء XML's errors.

يجب أن تعالج قبل الحفظ.

تابع هذه النافذة لعرض الخطأ."; + + +// In file: ../../js/ui/task/GetGGTranslation.js + + +// In file: ../../js/ui/task/SystemUpdateTask.js + i18n["Finish !"] = "انتهى !"; + + +// In file: ../../js/ui/task/SavePatchTask.js + i18n["Saving data as a patch..."] = "حفظ البيانات على شكل حزمة..."; + i18n["Patch saved"] = "تم حفظ الحزمة"; + i18n["Patch saved successfully !"] = "تم حفظ الحزمة بنجاح !"; + + +// In file: ../../js/ui/task/CheckEntitiesTask.js + i18n["Please, wait until entities are checked..."] = "يرجى الانتظار حتى تتم مراجعة المكونات..."; + + +// In file: ../../js/ui/task/VCSCommitTask.js + i18n["Please, wait until commit..."] = "يرجى الانتظار حتى يتم الاعتماد..."; + i18n["The log message is required."] = "رسالة السجل مطلوبة."; + i18n["You must choose at least one file."] = "يجب أن تختار ملفاً واحداً على الأقل."; + i18n["There are {0} files to close before commit.

{1}

Would you like me to close them for you ?"] = "هناك عدد {0} ملفات يجب أن تغلق قبل الاعتماد.

{1}

هل تريد إغلاقها ?"; + i18n["There is {0} file to close before commit.

{1}

Would you like me to close it for you ?"] = "هناك عدد {0} ملفات يجب أن تغلق قبل الاعتماد.

{1}

هل تريد إغلاقها ?"; + + +// In file: ../../js/ui/task/MarkDeleteTask.js + i18n["This action will mark this file as need deleted.

You need commit this change to take it effect.

Please, confirm this action."] = "هذا الإجراء سيضع علامة مطلوب الحذف على الملف.

يجب أن تعتمد هذا التغيير ليتم تطبيقه.

الرجاء التأكيد."; + + +// In file: ../../js/ui/task/ClearLocalChangeTask.js + i18n["This action will clear your local modification and take back this file from his original stats.
You need confirm."] = "هذا الإجراء سوف يلغي التعديلات ويعيده إلى حالته الأصلية..
الرجاء التأكيد."; + + +// In file: ../../js/ui/task/GetFileTask.js + i18n["Permanent link to this page"] = "رابط دائم لهذه الصفحة"; + i18n["Warning"] = "تحذير"; + i18n["The editor have modified automatically the file {0} into UTF-8 encoding."] = "قام المحرر بتغيير الملف {0} تتلقائياً إلى ترميز UTF-8 ."; + i18n["The file {0} contains some tab characters.
The editor have replace it with space characters."] = "الملف {0} يحتوي على رموز الجدولة TAB.
قام المحرر باستبدالها إلى مسافة."; + i18n["File modified by {0} (anonymous user) but you are an authenticated user, so you can modify it."] = "هذا الملف معدل من قبل {0} (مستخدم غير معرف) ولكن أنت مستخدم معرف لك الصلاحية لتعديله."; + i18n["File modified by {0}."] = "هذا الملف معدل من قبل {0}."; + + +// In file: ../../js/ui/task/UpdateConfTask.js + i18n["Option saved"] = "تم حفظ الإعداد"; + i18n["Option has been saved successfully !"] = "تم حفظ الإعداد بنجاح !"; + + +// In file: ../../js/ui/task/RejectPatchTask.js + i18n["This action will reject this patch, send an email to his author and close this tab."] = "سوف يقوم هذا الإجراء برفض هذه الحزمة، وإرسال رسالة إلى صاحبها وإغلاق هذا التبويب."; + i18n["Patch rejected successfully"] = "تم رفض الحزمة بنجاح"; + i18n["The Patch was rejected successfully !"] = "تم رفض الحزمة بنجاح !"; + + +// In file: ../../js/ui/task/CheckBuildTask.js + i18n["Check build result for {0}"] = "فحص نتيجة البناء في {0}"; + i18n["Check build result for the documentation {0}"] = "فحص نتيجة البناء للتوثيق {0}"; + i18n["Please, wait until the build is checked..."] = "يرجى الانتظار حتى يتم فحص البناء..."; + + +// In file: ../../js/ui/task/CheckFileTask.js + i18n["Checking for error. Please, wait..."] = "البحث عن الأخطاء. يرجى الانتظار..."; + i18n["Check for errors"] = "البحث عن الأهطاء"; + i18n["There is no error."] = "لا توجد أخطاء."; + + +// In file: ../../js/ui/task/AcceptPatchTask.js + i18n["This action will accept this patch, send an email to his author, save the file and close this tab."] = "هذا الإجراء سيعتمد هذه الحزمة، ويرسل رسالة لصاحبها ثم حفظها وإغلاق التبويب."; + i18n["Patch accepted successfully"] = "تم اعتماد الحزمة بنجاح"; + i18n["The Patch was accepted successfully !"] = "تم اعتماد الحزمة بنجاح !"; + + +// In file: ../../ux/extjsPowered/TabCloseMenu.js + i18n["Close Other Tabs"] = "إغلاق التبويبات الأخرى"; + i18n["Close All Tabs"] = "إغلاق كل التبويبات"; + + +// In file: ../../ux/others/main_specific/Ext.ux.UserNotes.js + i18n["Notes ({0})"] = "الملاحظات ({0})"; + i18n["Add a new note"] = "إضافة ملاحظة جديدة"; + i18n["Add"] = "إضافة"; + i18n["Delete this note"] = "حذف هذه الملاحظة"; + i18n["No user notes"] = "لا توجد ملاحظات"; + i18n["Right click to add a new note"] = "اضغط بالزر الأيمن لإضافة ملاحظة"; + i18n["Note added"] = "تمت إضافة الملاحظة"; + i18n["The note was added successfully !"] = "تمت إضافة الملاحظة بنجاح !"; + i18n["Note deleted"] = "تم حذف الملاحظة"; + i18n["The note was deleted successfully !"] = "تم حذف الملاحظة بنجاح !"; + + +// In file: ../../js/ui/task/CheckXml.js + i18n["XML check. Please, wait..."] = "فحص XML. يرجى الانتظار..."; + i18n["XML check"] = "فحص XML"; + + +// In file: ../../js/ui/cmp/CheckXmlWin.js + i18n["Line"] = "سطر"; + i18n["Libel"] = "صياغة"; + i18n["XML Errors"] = "XML Errors"; + +// In file: ../../js/ui/cmp/ChangeFileOwner.js + i18n["Current owner"] = "مالك الملف حالياً"; + i18n["Action"] = "إجراء"; + i18n["New owner"] = "مالك جديد"; + i18n["Change file's owner"] = "تغيير مالك الملف"; + +// In file: ../../js/ui/task/ChangeFileOwner.js + i18n["Owner changed"] = "تم تغيير مالك الملف"; + i18n["The owner for this file have been changed successfully !"] = "تم تغيير مالك الملف بنجاح !"; + +// In file: ../../js/ui/cmp/AnonymousPatchWin.js + i18n["Next"] = "التالي"; + i18n["Anonymous patch manager"] = "مدير حزم ملفات المستخدمين غير المعرفين"; + i18n["You have opened a modified file from the \"Patch for review\" module.
This file has been modified by an anonymous user.

Please choose one of the following actions:"] = "لقد فتحت ملفاً معدلاً ضمن قائمة \"حزم تحتاج لمراجعة\" .
هذا الملف تم تعديلها من قبل مستخدم غير معرف.

الرجاء اختيار أحد الإجراءات التالية:"; + i18n["Continue to modify this file"] = "الاستمرار في تعديل الملف"; + i18n["This action will open this file for modification. Once your modification finish, just save it and this file will be own by you."] = "هذا الإجراء سيفتح الملف للتعديل. عندما تنتهي من التعديل قم بحفظ الملف وسيتم تغيير ملكية الملف إليك."; + i18n["Reject this patch"] = "رفض هذه الحزمة"; + i18n["This action will close this file, and clear the local change. This file will return into his original version, as it is on VCS server."] = "هذا الإجراء سيغلق الملف، ويلغي التعديلات التي تمت عليه. وسيعيد الملف إلى حالته الأصلية المحفوظة على خادم VCS."; + i18n["Validate this patch"] = "مراجعة الملف"; + i18n["This action changes the owner of the modification and register it under your name. The file will appear under your name and you can then commit it."] = "هذا الإجراء سيغير ملكية الملف إليك. سوف يظهر الملف تحت اسمك وسيمكنك اعتماده."; + +// In file: ../../js/ui/cmp/PreviewFile.js + i18n["Preview"] = "استعراض"; diff --git a/js/main-all-debug.js b/js/main-all-debug.js index d34dcc34..438625db 100644 --- a/js/main-all-debug.js +++ b/js/main-all-debug.js @@ -8328,232 +8328,232 @@ Ext.util.md5 = function(s, r, hexcase, chrsz) } }); -Ext.reg('codemirror', Ext.ux.CodeMirror);Ext.ns('Ext.ux.grid'); - -Ext.ux.grid.GridSummary = function(config) { - Ext.apply(this, config); -}; - -Ext.extend(Ext.ux.grid.GridSummary, Ext.util.Observable, { - init : function(grid) { - this.grid = grid; - this.cm = grid.getColumnModel(); - this.view = grid.getView(); - - var v = this.view; - - // override GridView's onLayout() method - v.onLayout = this.onLayout; - - v.afterMethod('render', this.refreshSummary, this); - v.afterMethod('refresh', this.refreshSummary, this); - v.afterMethod('syncScroll', this.syncSummaryScroll, this); - v.afterMethod('onColumnWidthUpdated', this.doWidth, this); - v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this); - v.afterMethod('onColumnHiddenUpdated', this.doHidden, this); - - // update summary row on store's add/remove/clear/update events - grid.store.on({ - add: this.refreshSummary, - remove: this.refreshSummary, - clear: this.refreshSummary, - update: this.refreshSummary, - scope: this - }); - - if (!this.rowTpl) { - this.rowTpl = new Ext.Template( - '
', - '
', - '{cells}', - '
', - '
' - ); - this.rowTpl.disableFormats = true; - } - this.rowTpl.compile(); - - if (!this.cellTpl) { - this.cellTpl = new Ext.Template( - '', - '
{value}
', - "" - ); - this.cellTpl.disableFormats = true; - } - this.cellTpl.compile(); - }, - - calculate : function(rs, cm) { - var data = {}, - cfg = cm.config, - i, cf, cname, j, r, len, jlen; - - for (i = 0, len = cfg.length; i < len; i++) { // loop through all columns in ColumnModel - cf = cfg[i]; // get column's configuration - cname = cf.dataIndex; // get column dataIndex - - // initialise grid summary row data for - // the current column being worked on - data[cname] = 0; - - if (cf.summaryType) { - for (j = 0, jlen = rs.length; j < jlen; j++) { - r = rs[j]; // get a single Record - data[cname] = Ext.ux.grid.GridSummary.Calculations[cf.summaryType](r.get(cname), r, cname, data, j); - } - } - } - - return data; - }, - - onLayout : function(vw, vh) { - if (Ext.type(vh) !== 'number') { // handles grid's height:'auto' config - return; - } - // note: this method is scoped to the GridView - if (!this.grid.getGridEl().hasClass('x-grid-hide-gridsummary')) { - // readjust gridview's height only if grid summary row is visible - this.scroller.setHeight(vh - this.summary.getHeight()); - } - }, - - syncSummaryScroll : function() { - var mb = this.view.scroller.dom; - - this.view.summaryWrap.dom.scrollLeft = mb.scrollLeft; - this.view.summaryWrap.dom.scrollLeft = mb.scrollLeft; // second time for IE (1/2 time first fails, other browsers ignore) - }, - - doWidth : function(col, w, tw) { - var s = this.view.summary.dom; - - s.firstChild.style.width = tw; - s.firstChild.rows[0].childNodes[col].style.width = w; - }, - - doAllWidths : function(ws, tw) { - var s = this.view.summary.dom, - wlen = ws.length, - cells, j; - - s.firstChild.style.width = tw; - cells = s.firstChild.rows[0].childNodes; - - for (j = 0; j < wlen; j++) { - cells[j].style.width = ws[j]; - } - }, - - doHidden : function(col, hidden, tw) { - var s = this.view.summary.dom, - display = hidden ? 'none' : ''; - - s.firstChild.style.width = tw; - s.firstChild.rows[0].childNodes[col].style.display = display; - }, - - renderSummary : function(o, cs, cm) { - cs = cs || this.view.getColumnData(); - var cfg = cm.config, - buf = [], - last = cs.length - 1, - c, cf, p, i, len; - - for (i = 0, len = cs.length; i < len; i++) { - c = cs[i]; - cf = cfg[i]; - p = {}; - - p.id = c.id; - p.style = c.style; - p.css = i === 0 ? 'x-grid3-cell-first ' : (i === last ? 'x-grid3-cell-last ' : ''); - - if (cf.summaryType || cf.summaryRenderer) { - p.value = (cf.summaryRenderer || c.renderer)(o.data[c.name], p, o); - } else { - p.value = ''; - } - if (p.value === undefined || p.value === "") { - p.value = " "; - } - buf[buf.length] = this.cellTpl.apply(p); - } - - return this.rowTpl.apply({ - tstyle: 'width:' + this.view.getTotalWidth() + ';', - cells: buf.join('') - }); - }, - - refreshSummary : function() { - var g = this.grid, ds = g.store, - cs = this.view.getColumnData(), - cm = this.cm, - rs = ds.getRange(), - data = this.calculate(rs, cm), - buf = this.renderSummary({data: data}, cs, cm); - - if (!this.view.summaryWrap) { - this.view.summaryWrap = Ext.DomHelper.insertAfter(this.view.scroller, { - tag: 'div', - cls: 'x-grid3-gridsummary-row-inner' - }, true); - } - this.view.summary = this.view.summaryWrap.update(buf).first(); - }, - - toggleSummary : function(visible) { // true to display summary row - var el = this.grid.getGridEl(); - - if (el) { - if (visible === undefined) { - visible = el.hasClass('x-grid-hide-gridsummary'); - } - el[visible ? 'removeClass' : 'addClass']('x-grid-hide-gridsummary'); - - this.view.layout(); // readjust gridview height - } - }, - - getSummaryNode : function() { - return this.view.summary; - } -}); -Ext.reg('gridsummary', Ext.ux.grid.GridSummary); - -/* - * all Calculation methods are called on each Record in the Store - * with the following 5 parameters: - * - * v - cell value - * record - reference to the current Record - * colName - column name (i.e. the ColumnModel's dataIndex) - * data - the cumulative data for the current column + summaryType up to the current Record - * rowIdx - current row index - */ -Ext.ux.grid.GridSummary.Calculations = { - sum : function(v, record, colName, data, rowIdx) { - return data[colName] + Ext.num(v, 0); - }, - - count : function(v, record, colName, data, rowIdx) { - return rowIdx + 1; - }, - - max : function(v, record, colName, data, rowIdx) { - return Math.max(Ext.num(v, 0), data[colName]); - }, - - min : function(v, record, colName, data, rowIdx) { - return Math.min(Ext.num(v, 0), data[colName]); - }, - - average : function(v, record, colName, data, rowIdx) { - var t = data[colName] + Ext.num(v, 0), count = record.store.getCount(); - return rowIdx === count - 1 ? (t / count) : t; - } +Ext.reg('codemirror', Ext.ux.CodeMirror);Ext.ns('Ext.ux.grid'); + +Ext.ux.grid.GridSummary = function(config) { + Ext.apply(this, config); +}; + +Ext.extend(Ext.ux.grid.GridSummary, Ext.util.Observable, { + init : function(grid) { + this.grid = grid; + this.cm = grid.getColumnModel(); + this.view = grid.getView(); + + var v = this.view; + + // override GridView's onLayout() method + v.onLayout = this.onLayout; + + v.afterMethod('render', this.refreshSummary, this); + v.afterMethod('refresh', this.refreshSummary, this); + v.afterMethod('syncScroll', this.syncSummaryScroll, this); + v.afterMethod('onColumnWidthUpdated', this.doWidth, this); + v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this); + v.afterMethod('onColumnHiddenUpdated', this.doHidden, this); + + // update summary row on store's add/remove/clear/update events + grid.store.on({ + add: this.refreshSummary, + remove: this.refreshSummary, + clear: this.refreshSummary, + update: this.refreshSummary, + scope: this + }); + + if (!this.rowTpl) { + this.rowTpl = new Ext.Template( + '
', + '', + '{cells}', + '
', + '
' + ); + this.rowTpl.disableFormats = true; + } + this.rowTpl.compile(); + + if (!this.cellTpl) { + this.cellTpl = new Ext.Template( + '', + '
{value}
', + "" + ); + this.cellTpl.disableFormats = true; + } + this.cellTpl.compile(); + }, + + calculate : function(rs, cm) { + var data = {}, + cfg = cm.config, + i, cf, cname, j, r, len, jlen; + + for (i = 0, len = cfg.length; i < len; i++) { // loop through all columns in ColumnModel + cf = cfg[i]; // get column's configuration + cname = cf.dataIndex; // get column dataIndex + + // initialise grid summary row data for + // the current column being worked on + data[cname] = 0; + + if (cf.summaryType) { + for (j = 0, jlen = rs.length; j < jlen; j++) { + r = rs[j]; // get a single Record + data[cname] = Ext.ux.grid.GridSummary.Calculations[cf.summaryType](r.get(cname), r, cname, data, j); + } + } + } + + return data; + }, + + onLayout : function(vw, vh) { + if (Ext.type(vh) !== 'number') { // handles grid's height:'auto' config + return; + } + // note: this method is scoped to the GridView + if (!this.grid.getGridEl().hasClass('x-grid-hide-gridsummary')) { + // readjust gridview's height only if grid summary row is visible + this.scroller.setHeight(vh - this.summary.getHeight()); + } + }, + + syncSummaryScroll : function() { + var mb = this.view.scroller.dom; + + this.view.summaryWrap.dom.scrollLeft = mb.scrollLeft; + this.view.summaryWrap.dom.scrollLeft = mb.scrollLeft; // second time for IE (1/2 time first fails, other browsers ignore) + }, + + doWidth : function(col, w, tw) { + var s = this.view.summary.dom; + + s.firstChild.style.width = tw; + s.firstChild.rows[0].childNodes[col].style.width = w; + }, + + doAllWidths : function(ws, tw) { + var s = this.view.summary.dom, + wlen = ws.length, + cells, j; + + s.firstChild.style.width = tw; + cells = s.firstChild.rows[0].childNodes; + + for (j = 0; j < wlen; j++) { + cells[j].style.width = ws[j]; + } + }, + + doHidden : function(col, hidden, tw) { + var s = this.view.summary.dom, + display = hidden ? 'none' : ''; + + s.firstChild.style.width = tw; + s.firstChild.rows[0].childNodes[col].style.display = display; + }, + + renderSummary : function(o, cs, cm) { + cs = cs || this.view.getColumnData(); + var cfg = cm.config, + buf = [], + last = cs.length - 1, + c, cf, p, i, len; + + for (i = 0, len = cs.length; i < len; i++) { + c = cs[i]; + cf = cfg[i]; + p = {}; + + p.id = c.id; + p.style = c.style; + p.css = i === 0 ? 'x-grid3-cell-first ' : (i === last ? 'x-grid3-cell-last ' : ''); + + if (cf.summaryType || cf.summaryRenderer) { + p.value = (cf.summaryRenderer || c.renderer)(o.data[c.name], p, o); + } else { + p.value = ''; + } + if (p.value === undefined || p.value === "") { + p.value = " "; + } + buf[buf.length] = this.cellTpl.apply(p); + } + + return this.rowTpl.apply({ + tstyle: 'width:' + this.view.getTotalWidth() + ';', + cells: buf.join('') + }); + }, + + refreshSummary : function() { + var g = this.grid, ds = g.store, + cs = this.view.getColumnData(), + cm = this.cm, + rs = ds.getRange(), + data = this.calculate(rs, cm), + buf = this.renderSummary({data: data}, cs, cm); + + if (!this.view.summaryWrap) { + this.view.summaryWrap = Ext.DomHelper.insertAfter(this.view.scroller, { + tag: 'div', + cls: 'x-grid3-gridsummary-row-inner' + }, true); + } + this.view.summary = this.view.summaryWrap.update(buf).first(); + }, + + toggleSummary : function(visible) { // true to display summary row + var el = this.grid.getGridEl(); + + if (el) { + if (visible === undefined) { + visible = el.hasClass('x-grid-hide-gridsummary'); + } + el[visible ? 'removeClass' : 'addClass']('x-grid-hide-gridsummary'); + + this.view.layout(); // readjust gridview height + } + }, + + getSummaryNode : function() { + return this.view.summary; + } +}); +Ext.reg('gridsummary', Ext.ux.grid.GridSummary); + +/* + * all Calculation methods are called on each Record in the Store + * with the following 5 parameters: + * + * v - cell value + * record - reference to the current Record + * colName - column name (i.e. the ColumnModel's dataIndex) + * data - the cumulative data for the current column + summaryType up to the current Record + * rowIdx - current row index + */ +Ext.ux.grid.GridSummary.Calculations = { + sum : function(v, record, colName, data, rowIdx) { + return data[colName] + Ext.num(v, 0); + }, + + count : function(v, record, colName, data, rowIdx) { + return rowIdx + 1; + }, + + max : function(v, record, colName, data, rowIdx) { + return Math.max(Ext.num(v, 0), data[colName]); + }, + + min : function(v, record, colName, data, rowIdx) { + return Math.min(Ext.num(v, 0), data[colName]); + }, + + average : function(v, record, colName, data, rowIdx) { + var t = data[colName] + Ext.num(v, 0), count = record.store.getCount(); + return rowIdx === count - 1 ? (t / count) : t; + } };Ext.ux.IFrameComponent = Ext.extend(Ext.BoxComponent, { onRender : function(ct, position){ @@ -9397,97 +9397,97 @@ Ext.ux.MultiSelectTreePanel = Ext.extend(Ext.tree.TreePanel, { }); Ext.reg('multiselecttreepanel', Ext.ux.MultiSelectTreePanel); -/** - * Ext.ux.ToastWindow - * - * @author Edouard Fattal - * @date March 14, 2008 - * - * @class Ext.ux.ToastWindow - * @extends Ext.Window - */ - -Ext.namespace("Ext.ux"); - - -Ext.ux.NotificationMgr = { - positions: [] -}; - -Ext.ux.Notification = Ext.extend(Ext.Window, { - initComponent: function(){ - Ext.apply(this, { - iconCls: this.iconCls || 'x-icon-information', - cls: 'x-notification', - width: 250, - autoHeight: true, - draggable: false, - bodyStyle: 'text-align:center; padding: 10px;' - }); - if(this.autoDestroy) { - this.task = new Ext.util.DelayedTask(this.close, this); - } else { - this.closable = true; - } - Ext.ux.Notification.superclass.initComponent.call(this); - }, - setMessage: function(msg){ - this.body.update(msg); - }, - setTitle: function(title, iconCls){ - Ext.ux.Notification.superclass.setTitle.call(this, title, iconCls||this.iconCls); - }, - onRender:function(ct, position) { - Ext.ux.Notification.superclass.onRender.call(this, ct, position); - }, - onDestroy: function(){ - Ext.ux.NotificationMgr.positions.remove(this.pos); - Ext.ux.Notification.superclass.onDestroy.call(this); - }, - cancelHiding: function(){ - this.addClass('fixed'); - if(this.autoDestroy) { - this.task.cancel(); - } - }, - afterShow: function(){ - Ext.ux.Notification.superclass.afterShow.call(this); - Ext.fly(this.body.dom).on('click', this.cancelHiding, this); - if(this.autoDestroy) { - this.task.delay(this.hideDelay || 5000); - } - }, - animShow: function(){ - this.pos = 0; - while(Ext.ux.NotificationMgr.positions.indexOf(this.pos)>-1) { - this.pos++; - } - Ext.ux.NotificationMgr.positions.push(this.pos); - this.setSize(200,100); - this.el.alignTo(document, "br-br", [ -20, -20-((this.getSize().height+10)*this.pos) ]); - this.el.slideIn('b', { - duration: 1, - callback: this.afterShow, - scope: this - }); - }, - animHide: function(){ - Ext.ux.NotificationMgr.positions.remove(this.pos); - this.el.shadow.hide(); - this.el.ghost("b", { - duration: 1, - remove: false, - callback : function () { - Ext.ux.NotificationMgr.positions.remove(this.pos); - this.destroy(); - }.createDelegate(this) - - }); - }, - - focus: Ext.emptyFn - -}); +/** + * Ext.ux.ToastWindow + * + * @author Edouard Fattal + * @date March 14, 2008 + * + * @class Ext.ux.ToastWindow + * @extends Ext.Window + */ + +Ext.namespace("Ext.ux"); + + +Ext.ux.NotificationMgr = { + positions: [] +}; + +Ext.ux.Notification = Ext.extend(Ext.Window, { + initComponent: function(){ + Ext.apply(this, { + iconCls: this.iconCls || 'x-icon-information', + cls: 'x-notification', + width: 250, + autoHeight: true, + draggable: false, + bodyStyle: 'text-align:center; padding: 10px;' + }); + if(this.autoDestroy) { + this.task = new Ext.util.DelayedTask(this.close, this); + } else { + this.closable = true; + } + Ext.ux.Notification.superclass.initComponent.call(this); + }, + setMessage: function(msg){ + this.body.update(msg); + }, + setTitle: function(title, iconCls){ + Ext.ux.Notification.superclass.setTitle.call(this, title, iconCls||this.iconCls); + }, + onRender:function(ct, position) { + Ext.ux.Notification.superclass.onRender.call(this, ct, position); + }, + onDestroy: function(){ + Ext.ux.NotificationMgr.positions.remove(this.pos); + Ext.ux.Notification.superclass.onDestroy.call(this); + }, + cancelHiding: function(){ + this.addClass('fixed'); + if(this.autoDestroy) { + this.task.cancel(); + } + }, + afterShow: function(){ + Ext.ux.Notification.superclass.afterShow.call(this); + Ext.fly(this.body.dom).on('click', this.cancelHiding, this); + if(this.autoDestroy) { + this.task.delay(this.hideDelay || 5000); + } + }, + animShow: function(){ + this.pos = 0; + while(Ext.ux.NotificationMgr.positions.indexOf(this.pos)>-1) { + this.pos++; + } + Ext.ux.NotificationMgr.positions.push(this.pos); + this.setSize(200,100); + this.el.alignTo(document, "br-br", [ -20, -20-((this.getSize().height+10)*this.pos) ]); + this.el.slideIn('b', { + duration: 1, + callback: this.afterShow, + scope: this + }); + }, + animHide: function(){ + Ext.ux.NotificationMgr.positions.remove(this.pos); + this.el.shadow.hide(); + this.el.ghost("b", { + duration: 1, + remove: false, + callback : function () { + Ext.ux.NotificationMgr.positions.remove(this.pos); + this.destroy(); + }.createDelegate(this) + + }); + }, + + focus: Ext.emptyFn + +}); /** * Plugin for the Ext.Panel class to support a collapsed header title * Also implements vertical rotation for east and west border panels @@ -9606,214 +9606,214 @@ Ext.ux.PanelCollapsedTitle = (function() { } }; return this; -})();/* - * By Jake Knerr - Copyright 2010 - supersonicecho@gmail.com - * - * Version 1.0 - * - * LICENSE - * GPL v3 - * - */ - -Ext.ux.SlidingTabPanel = Ext.extend(Ext.TabPanel, { - - initTab: function(item, index){ - Ext.ux.SlidingTabPanel.superclass.initTab.call(this, item, index); - - this.addEvents({ - startDrag : true, - endDrag : true - }); - - var p = this.getTemplateArgs(item); - if(!this.slidingTabsID) this.slidingTabsID = Ext.id(); // Create a unique ID for this tabpanel - new Ext.ux.DDSlidingTab(p, this.slidingTabsID, { - tabpanel:this // Pass a reference to the tabpanel for each dragObject - }); - } - -}); - -Ext.ux.DDSlidingTab = Ext.extend(Ext.dd.DDProxy, { - - // Constructor - constructor: function() { - Ext.ux.DDSlidingTab.superclass.constructor.apply(this, arguments); - this.setYConstraint(0,0,0); // Lock the proxy to its initial Y coordinate - - // Create a convenient reference to the tab's tabpanel - this.tabpanel = this.config.tabpanel; - - // Set the slide duration - this.slideDuration = this.tabpanel.slideDuration; - if(!this.slideDuration) this.slideDuration = .1; - } - - // Pseudo Private Methods - ,handleMouseDown: function(e, oDD){ - if(this.primaryButtonOnly && e.button != 0) return; - if(this.isLocked()) return; - this.DDM.refreshCache(this.groups); - var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e)); - if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) { - } else { - if (this.clickValidator(e)) { - this.setStartPosition(); // Set the initial element position - this.b4MouseDown(e); - this.onMouseDown(e); - this.DDM.handleMouseDown(e, this); - // this.DDM.stopEvent(e); // Must remove this event swallower for the tabpanel to work - } - } - } - ,startDrag: function(x, y) { - - // Fire the startDrag event - this.tabpanel.fireEvent('startDrag', this.tabpanel, this.tabpanel.getActiveTab()); - - Ext.dd.DDM.useCache = false; // Disable caching of element location - Ext.dd.DDM.mode = 1; // Point mode - - this.proxyWrapper = Ext.get(this.getDragEl()); // Grab a reference to the proxy element we are creating - this.proxyWrapper.update(); // Clear out the proxy's nodes - this.proxyWrapper.applyStyles('z-index:1001;border:0 none;'); - this.proxyWrapper.addClass('tab-proxy'); - - // Use 2 nested divs to mimic the default tab styling - // You may need to customize the proxy to get it to look like your custom tabpanel if you use a bunch of custom css classes and styles - this.stripWrap = this.proxyWrapper.insertHtml('afterBegin', '
', true); - this.dragEl = this.stripWrap.insertHtml('afterBegin','
', true); - - this.tab = Ext.get(this.getEl()); // Grab a reference to the tab being dragged - this.tab.applyStyles('visibility:hidden;'); // Hide the tab being dragged - - // Insert the html and css classes for the dragged tab into the proxy - this.dragEl.insertHtml('afterBegin', this.tab.dom.innerHTML, false); - this.dragEl.dom.className = this.tab.dom.className; - - // Constrain the proxy drag in the X coordinate to the tabpanel - var panelWidth = this.tabpanel.el.getWidth(); - var panelX = this.tabpanel.el.getX(); - var tabX = this.tab.getX(); - var tabWidth = this.tab.getWidth(); - var left = tabX - panelX; - var right = panelX + panelWidth - tabX - tabWidth; - this.resetConstraints(); - this.setXConstraint(left, right); - } - ,onDragOver: function(e, targetArr) { - e.stopEvent(); - - // Grab the tab you have dragged the proxy over - var target = Ext.get(targetArr[0].id); - var targetWidth = target.getWidth(); - var targetX = target.getX(); - var targetMiddle = targetX + (targetWidth / 2); - var elX = this.tab.getX(); - var dragX = this.proxyWrapper.getX(); - var dragW = this.proxyWrapper.getWidth(); - if(dragX < targetX && ((dragX + dragW) > targetMiddle) ) { - if(target.next() != this.tab) { - target.applyStyles('visibility:hidden;'); - this.tab.insertAfter(target); - this.targetProxy = this.createSliderProxy(targetX, target); - if(!this.targetProxy.hasActiveFx()) this.animateSliderProxy(target, this.targetProxy, elX); - } - } - if(dragX > targetX && (dragX < targetMiddle) ) { - if(this.tab.next() != target) { - target.applyStyles('visibility:hidden;'); - this.tab.insertBefore(target); - this.targetProxy = this.createSliderProxy(targetX, target); - if(!this.targetProxy.hasActiveFx()) this.animateSliderProxy(target, this.targetProxy, elX); - } - } - } - ,animateSliderProxy: function(target, targetProxy, elX){ - targetProxy.shift({ - x: elX - ,easing: 'easeOut' - ,duration: this.slideDuration - ,callback: function() { - targetProxy.remove(); - target.applyStyles('visibility:visible;'); - } - ,scope:this - }); - } - ,createSliderProxy: function(targetX, target) { - var sliderWrapperEl = Ext.getBody().insertHtml('afterBegin', '
', true); - sliderWrapperEl.stripWrapper = sliderWrapperEl.insertHtml('afterBegin', '
', true); - sliderWrapperEl.dragEl = sliderWrapperEl.stripWrapper.insertHtml('afterBegin', '
', true); - sliderWrapperEl.dragEl.update(target.dom.innerHTML); - sliderWrapperEl.dragEl.dom.className = target.dom.className; - var h = parseInt(target.getTop(false)); - sliderWrapperEl.setTop(h) - return sliderWrapperEl; - } - ,onDragDrop: function(e, targetId) { - e.stopEvent(); - } - ,endDrag: function(e){ - var elX = this.tab.getX(); - this.proxyWrapper.applyStyles('visibility:visible;'); - - // Animate the dragProxy to the proper position - this.proxyWrapper.shift({ - x: elX - ,easing: 'easeOut' - ,duration: this.slideDuration - ,callback: function() { - this.proxyWrapper.applyStyles('visibility:hidden;'); - this.tab.applyStyles('visibility:visible;'); - - // Cleanup - this.stripWrap.remove(); - this.dragEl.remove(); - if(!this.targetProxy) return; - this.targetProxy.stripWrapper.remove(); - this.targetProxy.dragEl.remove(); - } - ,scope:this - }); - - Ext.dd.DDM.useCache = true; - - this.reorderTab(); - - // Fire the startDrag event - this.tabpanel.fireEvent('endDrag', this.tabpanel, this.tabpanel.getActiveTab()); - - }, - reorderTab: function() { - - var tabsEl = this.tabpanel.header.child('ul').dom.children, - tabsId = [], - tabsOrigin = []; - - for ( var i=0; i < tabsEl.length; i++ ) { - if( tabsEl[i].id.substr(0, this.tabpanel.id.length) == this.tabpanel.id ) { - tabsId.push( tabsEl[i].id.substr((this.tabpanel.id.length+2), tabsEl[i].id.length ) ); - } - } - - // Now, tabsId is the real list ordered of the tab's id - // We put this order into parent element - - // We get the original reference of this tabs - for( var i=0; i < this.tabpanel.items.items.length; i++ ) { - tabsOrigin[this.tabpanel.items.items[i].id] = this.tabpanel.items.items[i]; - } - - for( var i=0; i < tabsId.length; i++ ) { - // the keys - this.tabpanel.items.keys[i] = tabsId[i]; - // the elements - this.tabpanel.items.items[i] = tabsOrigin[tabsId[i]]; - } - - } +})();/* + * By Jake Knerr - Copyright 2010 - supersonicecho@gmail.com + * + * Version 1.0 + * + * LICENSE + * GPL v3 + * + */ + +Ext.ux.SlidingTabPanel = Ext.extend(Ext.TabPanel, { + + initTab: function(item, index){ + Ext.ux.SlidingTabPanel.superclass.initTab.call(this, item, index); + + this.addEvents({ + startDrag : true, + endDrag : true + }); + + var p = this.getTemplateArgs(item); + if(!this.slidingTabsID) this.slidingTabsID = Ext.id(); // Create a unique ID for this tabpanel + new Ext.ux.DDSlidingTab(p, this.slidingTabsID, { + tabpanel:this // Pass a reference to the tabpanel for each dragObject + }); + } + +}); + +Ext.ux.DDSlidingTab = Ext.extend(Ext.dd.DDProxy, { + + // Constructor + constructor: function() { + Ext.ux.DDSlidingTab.superclass.constructor.apply(this, arguments); + this.setYConstraint(0,0,0); // Lock the proxy to its initial Y coordinate + + // Create a convenient reference to the tab's tabpanel + this.tabpanel = this.config.tabpanel; + + // Set the slide duration + this.slideDuration = this.tabpanel.slideDuration; + if(!this.slideDuration) this.slideDuration = .1; + } + + // Pseudo Private Methods + ,handleMouseDown: function(e, oDD){ + if(this.primaryButtonOnly && e.button != 0) return; + if(this.isLocked()) return; + this.DDM.refreshCache(this.groups); + var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e)); + if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) { + } else { + if (this.clickValidator(e)) { + this.setStartPosition(); // Set the initial element position + this.b4MouseDown(e); + this.onMouseDown(e); + this.DDM.handleMouseDown(e, this); + // this.DDM.stopEvent(e); // Must remove this event swallower for the tabpanel to work + } + } + } + ,startDrag: function(x, y) { + + // Fire the startDrag event + this.tabpanel.fireEvent('startDrag', this.tabpanel, this.tabpanel.getActiveTab()); + + Ext.dd.DDM.useCache = false; // Disable caching of element location + Ext.dd.DDM.mode = 1; // Point mode + + this.proxyWrapper = Ext.get(this.getDragEl()); // Grab a reference to the proxy element we are creating + this.proxyWrapper.update(); // Clear out the proxy's nodes + this.proxyWrapper.applyStyles('z-index:1001;border:0 none;'); + this.proxyWrapper.addClass('tab-proxy'); + + // Use 2 nested divs to mimic the default tab styling + // You may need to customize the proxy to get it to look like your custom tabpanel if you use a bunch of custom css classes and styles + this.stripWrap = this.proxyWrapper.insertHtml('afterBegin', '
', true); + this.dragEl = this.stripWrap.insertHtml('afterBegin','
', true); + + this.tab = Ext.get(this.getEl()); // Grab a reference to the tab being dragged + this.tab.applyStyles('visibility:hidden;'); // Hide the tab being dragged + + // Insert the html and css classes for the dragged tab into the proxy + this.dragEl.insertHtml('afterBegin', this.tab.dom.innerHTML, false); + this.dragEl.dom.className = this.tab.dom.className; + + // Constrain the proxy drag in the X coordinate to the tabpanel + var panelWidth = this.tabpanel.el.getWidth(); + var panelX = this.tabpanel.el.getX(); + var tabX = this.tab.getX(); + var tabWidth = this.tab.getWidth(); + var left = tabX - panelX; + var right = panelX + panelWidth - tabX - tabWidth; + this.resetConstraints(); + this.setXConstraint(left, right); + } + ,onDragOver: function(e, targetArr) { + e.stopEvent(); + + // Grab the tab you have dragged the proxy over + var target = Ext.get(targetArr[0].id); + var targetWidth = target.getWidth(); + var targetX = target.getX(); + var targetMiddle = targetX + (targetWidth / 2); + var elX = this.tab.getX(); + var dragX = this.proxyWrapper.getX(); + var dragW = this.proxyWrapper.getWidth(); + if(dragX < targetX && ((dragX + dragW) > targetMiddle) ) { + if(target.next() != this.tab) { + target.applyStyles('visibility:hidden;'); + this.tab.insertAfter(target); + this.targetProxy = this.createSliderProxy(targetX, target); + if(!this.targetProxy.hasActiveFx()) this.animateSliderProxy(target, this.targetProxy, elX); + } + } + if(dragX > targetX && (dragX < targetMiddle) ) { + if(this.tab.next() != target) { + target.applyStyles('visibility:hidden;'); + this.tab.insertBefore(target); + this.targetProxy = this.createSliderProxy(targetX, target); + if(!this.targetProxy.hasActiveFx()) this.animateSliderProxy(target, this.targetProxy, elX); + } + } + } + ,animateSliderProxy: function(target, targetProxy, elX){ + targetProxy.shift({ + x: elX + ,easing: 'easeOut' + ,duration: this.slideDuration + ,callback: function() { + targetProxy.remove(); + target.applyStyles('visibility:visible;'); + } + ,scope:this + }); + } + ,createSliderProxy: function(targetX, target) { + var sliderWrapperEl = Ext.getBody().insertHtml('afterBegin', '
', true); + sliderWrapperEl.stripWrapper = sliderWrapperEl.insertHtml('afterBegin', '
', true); + sliderWrapperEl.dragEl = sliderWrapperEl.stripWrapper.insertHtml('afterBegin', '
', true); + sliderWrapperEl.dragEl.update(target.dom.innerHTML); + sliderWrapperEl.dragEl.dom.className = target.dom.className; + var h = parseInt(target.getTop(false)); + sliderWrapperEl.setTop(h) + return sliderWrapperEl; + } + ,onDragDrop: function(e, targetId) { + e.stopEvent(); + } + ,endDrag: function(e){ + var elX = this.tab.getX(); + this.proxyWrapper.applyStyles('visibility:visible;'); + + // Animate the dragProxy to the proper position + this.proxyWrapper.shift({ + x: elX + ,easing: 'easeOut' + ,duration: this.slideDuration + ,callback: function() { + this.proxyWrapper.applyStyles('visibility:hidden;'); + this.tab.applyStyles('visibility:visible;'); + + // Cleanup + this.stripWrap.remove(); + this.dragEl.remove(); + if(!this.targetProxy) return; + this.targetProxy.stripWrapper.remove(); + this.targetProxy.dragEl.remove(); + } + ,scope:this + }); + + Ext.dd.DDM.useCache = true; + + this.reorderTab(); + + // Fire the startDrag event + this.tabpanel.fireEvent('endDrag', this.tabpanel, this.tabpanel.getActiveTab()); + + }, + reorderTab: function() { + + var tabsEl = this.tabpanel.header.child('ul').dom.children, + tabsId = [], + tabsOrigin = []; + + for ( var i=0; i < tabsEl.length; i++ ) { + if( tabsEl[i].id.substr(0, this.tabpanel.id.length) == this.tabpanel.id ) { + tabsId.push( tabsEl[i].id.substr((this.tabpanel.id.length+2), tabsEl[i].id.length ) ); + } + } + + // Now, tabsId is the real list ordered of the tab's id + // We put this order into parent element + + // We get the original reference of this tabs + for( var i=0; i < this.tabpanel.items.items.length; i++ ) { + tabsOrigin[this.tabpanel.items.items[i].id] = this.tabpanel.items.items[i]; + } + + for( var i=0; i < tabsId.length; i++ ) { + // the keys + this.tabpanel.items.keys[i] = tabsId[i]; + // the elements + this.tabpanel.items.items[i] = tabsOrigin[tabsId[i]]; + } + + } });Ext.ux.UserNotes = Ext.extend(Ext.Button, { originalTitle : _('Notes ({0})'), @@ -13933,1452 +13933,1452 @@ ui.cmp.DictionaryGrid = Ext.extend(Ext.Panel, }); ui.cmp.DictionaryGrid.superclass.initComponent.call(this); } -});Ext.namespace('ui','ui.cmp','ui.cmp._EditorConf','ui.cmp._EditorCmd2Conf'); - -//------------------------------------------------------------------------------ -// EditorConf Win internals - -// EditorConf Win-Menu template -ui.cmp._EditorConf.tplMenu = new Ext.XTemplate( - '', - '', - '' -); -ui.cmp._EditorConf.tplMenu.compile(); - -// EditorConf Win-Menu items definition for EN -ui.cmp._EditorConf.menuDefEn = [ - ['1', 'card1', _('Main')], - ['4', 'card4', _('Module "Files with error"')], - ['6', 'card6', _('Module "All files"')] -]; - -// EditorConf Win-Menu items definition for Non-EN -ui.cmp._EditorConf.menuDefNonEn = [ - ['1', 'card1', _('Main')], - ['2', 'card2', _('Module "Files need translate"')], - ['3', 'card3', _('Module "Files need update"')], - ['4', 'card4', _('Module "Files with error"')], - ['5', 'card5', _('Module "Files need reviewed"')], - ['6', 'card6', _('Module "All files"')] -]; - -// EditorConf Win-Menu items store -ui.cmp._EditorConf.menuStore = new Ext.data.SimpleStore({ - id : 0, - fields : [ - { name : 'id'}, - { name : 'card'}, - { name : 'label'} - ] -}); - -// EditorConf Win-Menu view -ui.cmp._EditorConf.viewMenu = Ext.extend(Ext.DataView, -{ - id : 'conf-menu-view', - tpl : ui.cmp._EditorConf.tplMenu, - singleSelect : true, - overClass : 'x-view-over', - itemSelector : 'div.menu-wrap', - store : ui.cmp._EditorConf.menuStore, - listeners : { - selectionchange : function(view) - { - var r = view.getSelectedRecords(); - Ext.getCmp('confCard').layout.setActiveItem('conf-card-' + r[0].data.id); - } - } -}); - -// CodeMirror2 Theme datastore -ui.cmp._EditorCmd2Conf.themeStore = new Ext.data.SimpleStore({ - fields : ['themeFile', { - name : 'themeName', - type : 'string' - }], - data : [ - [false, _('No theme')], - ['default', _('Default theme')], - ['cobalt', _('Cobalt')], - ['eclipse', _('Eclipse')], - ['elegant', _('Elegant')], - ['monokai', _('Monokai')], - ['neat', _('Neat')], - ['night', _('Night')], - ['rubyblue', _('RubyBlue')] - ] -}); - -// doc-editor Theme datastore -ui.cmp._EditorConf.themeStore = new Ext.data.SimpleStore({ - fields : ['themeFile', { - name : 'themeName', - type : 'string' - }], - data : [ - ['themes/ExtJsThemes/black/css/xtheme-black.css', _('Black')], - ['themes/empty.css', _('Default')], - ['themes/ExtJsThemes/darkgray/css/xtheme-darkgray.css', _('DarkGray')], - ['js/ExtJs/resources/css/xtheme-gray.css', _('Gray')], - ['themes/ExtJsThemes/gray-extend/css/xtheme-gray-extend.css', _('Gray Extend')], - ['themes/ExtJsThemes/indigo/css/xtheme-indigo.css', _('Indigo')], - ['themes/ExtJsThemes/midnight/css/xtheme-midnight.css', _('Midnight')], - ['themes/ExtJsThemes/olive/css/xtheme-olive.css', _('Olive')], - ['themes/ExtJsThemes/purple/css/xtheme-purple.css', _('Purple')], - ['themes/ExtJsThemes/silverCherry/css/xtheme-silverCherry.css', _('SilverCherry')], - ['themes/ExtJsThemes/ubuntu_human/css/xtheme-human.css', _('Ubuntu Human')] - ] -}); - -// doc-editor UI Lang datastore -ui.cmp._EditorConf.uiLangStore = new Ext.data.SimpleStore({ - fields : ['uiLang', { - name : 'uiLangName', - type : 'string' - }], - data : [ - ['default', _('Default language, if available')], - ['en', _('English')], - ['fr', _('French')], - ['ru', _('Russian')], - ['es', _('Spanish')], - ['ar', _('Arabic')] - ] -}); - -ui.cmp._EditorConf.CommitChange = new Ext.util.DelayedTask(function() -{ - new ui.task.UpdateConfTask({ - module : this.module, - itemName : this.itemName, - value : this.getValue() - }); -}); - -// EditorConf card1 - mainApp -ui.cmp._EditorConf.card1 = Ext.extend(Ext.TabPanel, -{ - id : 'conf-card-1', - autoScroll : true, - activeTab : 0, - defaults : { bodyStyle: 'padding: 5px;', autoHeight : true, autoScroll : true }, - - initComponent : function() - { - Ext.apply(this, - { - items : [{ - title : _('User Interface'), - iconCls : 'iconUI', - labelAlign: 'top', - layout:'form', - items : [{ - xtype : 'fieldset', - title : _('Main menu'), - iconCls : 'iconMenu', - items : [{ - xtype : 'spinnerfield', - width : 60, - name : 'PhDOE.user.conf.main.mainMenuWidth', - module : 'main', - itemName : 'mainMenuWidth', - value : PhDOE.user.conf.main.mainMenuWidth || 300, - fieldLabel : _('Main menu width'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - var cmp = Ext.getCmp('main-menu-panel'), - val = this.getValue(); - PhDOE.user.conf.main.mainMenuWidth = val; - cmp.setWidth(val); - cmp.ownerCt.doLayout(); - - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - var cmp = Ext.getCmp('main-menu-panel'), - val = this.getValue(); - PhDOE.user.conf.main.mainMenuWidth = val; - cmp.setWidth(val); - cmp.ownerCt.doLayout(); - - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }] - }, { - xtype : 'fieldset', - iconCls : 'iconThemes', - title : _('Appearance'), - items : [{ - xtype : 'combo', - fieldLabel : _('Choose a theme'), - id : 'conf-combo-theme', - valueField : 'themeFile', - displayField : 'themeName', - triggerAction : 'all', - mode : 'local', - forceSelection : true, - editable : false, - value : PhDOE.user.conf.main.theme, - store : ui.cmp._EditorConf.themeStore, - listeners : { - render : function() - { - Ext.getCmp('conf-combo-theme').store.sort('themeName'); - }, - select : function(c) - { - var hrefTheme = c.getValue(); - - Ext.get('appTheme').dom.href = hrefTheme; - - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'theme', - value : hrefTheme - }); - } - } - },{ - xtype : 'combo', - fieldLabel : _('Force an UI language'), - id : 'conf-combo-ui-lang', - valueField : 'uiLang', - displayField : 'uiLangName', - triggerAction : 'all', - mode : 'local', - forceSelection : true, - editable : false, - value : PhDOE.user.conf.main.uiLang || 'default', - store : ui.cmp._EditorConf.uiLangStore, - listeners : { - select : function(c) - { - var uiLang = c.getValue(); - - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'uiLang', - value : uiLang - }); - } - } - }] - }, { - xtype : 'fieldset', - title : _('On save file'), - iconCls : 'iconSaveFile', - autoHeight : true, - defaults : { hideLabel: true }, - defaultType: 'radio', - items : [{ - autoHeight : true, - name : 'PhDOE.user.conf.main.onSaveFile', - module : 'main', - itemName : 'onSaveFile', - checked : (PhDOE.user.conf.main.onSaveFile === "ask-me") ? true : false, - boxLabel : _('Ask me if I want to check for error before saving the file'), - inputValue : 'ask-me', - listeners : { - check : function(field) - { - if (field.checked) { - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'onSaveFile', - value : field.getRawValue() - }); - } - } - } - }, { - autoHeight : true, - name : 'PhDOE.user.conf.main.onSaveFile', - module : 'main', - itemName : 'onSaveFile', - checked : (PhDOE.user.conf.main.onSaveFile === "always") ? true : false, - boxLabel : _('Always check for error before saving the file'), - inputValue : 'always', - listeners : { - check : function(field) - { - if (field.checked) { - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'onSaveFile', - value : field.getRawValue() - }); - } - } - } - }, { - autoHeight : true, - name : 'PhDOE.user.conf.main.onSaveFile', - module : 'main', - itemName : 'onSaveFile', - checked : (PhDOE.user.conf.main.onSaveFile === "never") ? true : false, - boxLabel : _('Never check for error before saving the file'), - inputValue : 'never', - listeners : { - check : function(field) - { - if (field.checked) { - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'onSaveFile', - value : field.getRawValue() - }); - } - } - } - }] - },{ - xtype : 'checkbox', - name : 'PhDOE.user.conf.main.displayENWork', - checked : PhDOE.user.conf.main.displayENWork, - boxLabel : _('Display EN work in "Work in progress" & "Patches for review" modules'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'displayENWork', - value : field.getValue() - }); - } - } - }] - }, { - title : _('External Data'), - iconCls : 'iconExternalData', - items : [{ - xtype : 'fieldset', - title : _('About mails'), - iconCls : 'iconMailing', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - autoHeight : true, - name : 'PhDOE.user.conf.main.loadMailsAtStartUp', - checked : PhDOE.user.conf.main.loadMailsAtStartUp, - boxLabel : _('Load mail at startUp'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'loadMailsAtStartUp', - value : field.getValue() - }); - } - } - }] - }, { - xtype : 'fieldset', - title : _('About bugs'), - iconCls : 'iconBugs', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - autoHeight : true, - name : 'PhDOE.user.conf.main.loadBugsAtStartUp', - checked : PhDOE.user.conf.main.loadBugsAtStartUp, - boxLabel : _('Load bugs at startUp'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'loadBugsAtStartUp', - value : field.getValue() - }); - } - } - }] - }] - }, { - title : _('Editor'), - iconCls : 'iconEditor', - items : [{ - xtype : 'fieldset', - title : _('Editor theme'), - iconCls : 'iconThemes', - items : [{ - xtype : 'combo', - fieldLabel : _('Choose a theme'), - id : 'conf-combo-cm2-theme', - valueField : 'themeFile', - displayField : 'themeName', - triggerAction : 'all', - mode : 'local', - forceSelection : true, - editable : false, - value : (PhDOE.user.conf.main.editorTheme || 'default'), - store : ui.cmp._EditorCmd2Conf.themeStore, - listeners : { - select : function(c) - { - var themeValue = c.getValue(); - - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'editorTheme', - value : themeValue - }); - } - } - }] - }] - }] - }); - ui.cmp._EditorConf.card1.superclass.initComponent.call(this); - } -}); - -// EditorConf card2 - Module "Files Need Translate" Config -ui.cmp._EditorConf.card2 = Ext.extend(Ext.TabPanel, -{ - id : 'conf-card-2', - autoScroll : true, - activeTab : 0, - defaults : { - bodyStyle : 'padding: 5px;', - autoHeight : true, - autoScroll : true - }, - - initComponent : function() - { - Ext.apply(this, - { - items : [{ - title : _('Menu'), - iconCls : 'iconMenu', - items : [{ - xtype : 'fieldset', - title : _('Nb files to display'), - iconCls : 'iconFilesToDisplay', - defaults : { hideLabel: true }, - items : [{ - xtype : 'spinnerfield', - width : 60, - name : 'PhDOE.user.conf.newFile.nbDisplay', - module : 'newFile', - itemName : 'nbDisplay', - value : PhDOE.user.conf.newFile.nbDisplay || 0, - boxLabel : _('files to display'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }, { - xtype : 'displayfield', - value : _('0 means no limit'), - style : { fontStyle: 'italic'} - }] - }] - }, { - title : _('User Interface'), - iconCls : 'iconUI', - items : [{ - xtype : 'fieldset', - title : _('ScrollBars'), - iconCls : 'iconScrollBar', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'PhDOE.user.conf.newFile.syncScrollbars', - checked : PhDOE.user.conf.newFile.syncScrollbars, - boxLabel : _('Synchronize scroll bars'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'newFile', - itemName : 'syncScrollbars', - value : field.getValue() - }); - } - } - }] - },{ - xtype : 'fieldset', - title : _('Tools'), - iconCls : 'iconConf', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - xtype : 'fieldset', - checkboxToggle : true, - collapsed : !PhDOE.user.conf.newFile.toolsPanelDisplay, - title : _('Start with the panel open'), - listeners : { - collapse : function() - { - new ui.task.UpdateConfTask({ - module : 'newFile', - itemName : 'toolsPanelDisplay', - value : false - }); - }, - expand : function() - { - new ui.task.UpdateConfTask({ - module : 'newFile', - itemName : 'toolsPanelDisplay', - value : true - }); - } - }, - items : [{ - xtype : 'spinnerfield', - width : 60, - name : 'newFile.toolsPanelWidth', - module : 'newFile', - itemName : 'toolsPanelWidth', - value : PhDOE.user.conf.newFile.toolsPanelWidth || 375, - fieldLabel : _('Panel width'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }] - }] - }, { - xtype : 'fieldset', - title : _('Right panel'), - iconCls : 'iconUI', - defaults : { hideLabel: true }, - defaultType : 'radio', - items : [ - /*{ - name: 'PhDOE.user.conf.newFile.secondPanel', - boxLabel: _('Display the Google Translation Panel'), - inputValue: 'google', - checked: (PhDOE.user.conf.newFile.secondPanel === 'google') ? true : false, - listeners: { - check : function(field) - { - if (field.checked) { - new ui.task.UpdateConfTask({ - module : 'newFile', - itemName : 'secondPanel', - value : field.getRawValue() - }); - } - } - } - },*/ - { - name : 'PhDOE.user.conf.newFile.secondPanel', - boxLabel : _('Display the original file'), - inputValue: 'originalFile', - checked: (PhDOE.user.conf.newFile.secondPanel === 'originalFile') ? true : false, - listeners : { - check : function(field) - { - if (field.checked) { - new ui.task.UpdateConfTask({ - module : 'newFile', - itemName : 'secondPanel', - value : field.getRawValue() - }); - } - } - } - },{ - name : 'PhDOE.user.conf.newFile.secondPanel', - boxLabel : _('Do not display a right panel'), - inputValue: 'none', - checked: (!Ext.isDefined(PhDOE.user.conf.newFile.secondPanel) || PhDOE.user.conf.newFile.secondPanel === 'none') ? true : false, - listeners : { - check : function(field) - { - if (field.checked) { - new ui.task.UpdateConfTask({ - module : 'newFile', - itemName : 'secondPanel', - value : field.getRawValue() - }); - } - } - } - }] - }] - }] - }); - ui.cmp._EditorConf.card2.superclass.initComponent.call(this); - } -}); - -// EditorConf card3 - Module "Files Need Update" Config -ui.cmp._EditorConf.card3 = Ext.extend(Ext.TabPanel, -{ - id : 'conf-card-3', - autoScroll : true, - activeTab : 0, - defaults : { - bodyStyle : 'padding: 5px;', - autoHeight : true, - autoScroll : true - }, - - initComponent : function() - { - Ext.apply(this, - { - items : [{ - title : _('Menu'), - iconCls : 'iconMenu', - items : [{ - xtype : 'fieldset', - title : _('Nb files to display'), - iconCls : 'iconFilesToDisplay', - defaults : { hideLabel: true }, - defaultType : 'spinnerfield', - items : [{ - width : 60, - name : 'PhDOE.user.conf.needUpdate.nbDisplay', - module : 'needUpdate', - itemName : 'nbDisplay', - value : PhDOE.user.conf.needUpdate.nbDisplay || 0, - boxLabel : _('files to display'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - - }, { - xtype : 'displayfield', - value : _('0 means no limit'), - style : { fontStyle: 'italic'} - }] - }] - }, { - title : _('User Interface'), - iconCls : 'iconUI', - items : [{ - xtype : 'fieldset', - title : _('ScrollBars'), - iconCls : 'iconScrollBar', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'needUpdate.syncScrollbars', - checked : PhDOE.user.conf.needUpdate.syncScrollbars, - boxLabel : _('Synchronize scroll bars'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'needUpdate', - itemName : 'syncScrollbars', - value : field.getValue() - }); - } - } - }] - }, { - xtype : 'fieldset', - title : _('Tools'), - iconCls : 'iconConf', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'needUpdate.toolsPanelLogLoad', - checked : PhDOE.user.conf.needUpdate.toolsPanelLogLoad, - boxLabel : _('Automatically load the log when displaying the file'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'needUpdate', - itemName : 'toolsPanelLogLoad', - value : field.getValue() - }); - } - } - }, { - xtype : 'fieldset', - checkboxToggle : true, - collapsed : !PhDOE.user.conf.needUpdate.toolsPanelDisplay, - title : _('Start with the panel open'), - listeners : { - collapse : function() - { - new ui.task.UpdateConfTask({ - module : 'needUpdate', - itemName : 'toolsPanelDisplay', - value : false - }); - }, - expand : function() - { - new ui.task.UpdateConfTask({ - module : 'needUpdate', - itemName : 'toolsPanelDisplay', - value : true - }); - } - }, - items : [{ - xtype : 'spinnerfield', - width : 60, - name : 'needUpdate.toolsPanelWidth', - module : 'needUpdate', - itemName : 'toolsPanelWidth', - value : PhDOE.user.conf.needUpdate.toolsPanelWidth || 375, - fieldLabel : _('Panel width'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }] - }] - }, { - xtype : 'fieldset', - title : _('Diff view'), - iconCls : 'iconDiffView', - defaults : { hideLabel: true }, - defaultType : 'radio', - items : [{ - xtype : 'fieldset', - checkboxToggle : true, - collapsed : !PhDOE.user.conf.needUpdate.diffPanelDisplay, - title : _('Start with the panel open'), - listeners : { - collapse : function() - { - new ui.task.UpdateConfTask({ - module : 'needUpdate', - itemName : 'diffPanelDisplay', - value : false - }); - }, - expand : function() - { - new ui.task.UpdateConfTask({ - module : 'needUpdate', - itemName : 'diffPanelDisplay', - value : true - }); - } - }, - items : [{ - xtype : 'spinnerfield', - width : 60, - name : 'needUpdate.diffPanelHeight', - module : 'needUpdate', - itemName : 'diffPanelHeight', - value : PhDOE.user.conf.needUpdate.diffPanelHeight || 150, - fieldLabel : _('Panel height'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }] - }, { - name : 'needUpdate.diffMethod', - checked : (PhDOE.user.conf.needUpdate.diffMethod === "using-viewvc") ? true : false, - boxLabel : _('Using ViewVc from php web site'), - inputValue : 'using-viewvc', - listeners : { - check : function(field) - { - if (field.checked) { - new ui.task.UpdateConfTask({ - module : 'needUpdate', - itemName : 'diffMethod', - value : field.getRawValue() - }); - } - } - } - }, { - name : 'needUpdate.diffMethod', - checked : (PhDOE.user.conf.needUpdate.diffMethod === "using-exec") ? true : false, - boxLabel : _('Using diff -u command line'), - inputValue : 'using-exec', - listeners : { - check : function(field) - { - if (field.checked) { - new ui.task.UpdateConfTask({ - module : 'needUpdate', - itemName : 'diffMethod', - value : field.getRawValue() - }); - } - } - } - }] - }] - }] - }); - ui.cmp._EditorConf.card3.superclass.initComponent.call(this); - } -}); - -// EditorConf card4 - Module "Files with Error" Config -ui.cmp._EditorConf.card4 = Ext.extend(Ext.TabPanel, -{ - id : 'conf-card-4', - autoScroll : true, - activeTab : 0, - defaults : { - bodyStyle : 'padding: 5px;', - autoHeight : true, - autoScroll : true - }, - - initComponent : function() - { - Ext.apply(this, - { - items : [{ - title : _('Menu'), - iconCls : 'iconMenu', - items : [{ - xtype : 'fieldset', - title : _('Nb files to display'), - iconCls : 'iconFilesToDisplay', - defaults : { hideLabel: true }, - defaultType : 'spinnerfield', - items : [{ - width : 60, - name : 'PhDOE.user.conf.error.nbDisplay', - module : 'error', - itemName : 'nbDisplay', - value : PhDOE.user.conf.error.nbDisplay || 0, - boxLabel : _('files to display'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - - }, { - xtype : 'displayfield', - value : _('0 means no limit'), - style : { fontStyle: 'italic'} - }] - }, { - hidden : ( PhDOE.user.lang === 'en' ), - xtype : 'fieldset', - title : _('Error type'), - iconCls : 'iconFilesError', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'error.skipNbLiteralTag', - checked : PhDOE.user.conf.error.skipNbLiteralTag, - boxLabel : _('Skip nbLiteralTag error'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'skipNbLiteralTag', - value : field.getValue() - }); - } - } - }] - }] - }, { - title : _('User Interface'), - iconCls : 'iconUI', - items : [{ - xtype : 'fieldset', - title : _('ScrollBars'), - iconCls : 'iconScrollBar', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'error.syncScrollbars', - checked : PhDOE.user.conf.error.syncScrollbars, - boxLabel : _('Synchronize scroll bars'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'syncScrollbars', - value : field.getValue() - }); - } - } - }] - }, { - xtype : 'fieldset', - title : _('Tools'), - iconCls : 'iconConf', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'error.toolsPanelLogLoad', - checked : PhDOE.user.conf.error.toolsPanelLogLoad, - boxLabel : _('Automatically load the log when displaying the file'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'toolsPanelLogLoad', - value : field.getValue() - }); - } - } - }, { - name : 'error.toolsPanelEntitiesLoad', - checked : PhDOE.user.conf.error.toolsPanelEntitiesLoad, - boxLabel : _('Automatically load entities data when displaying the file'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'toolsPanelEntitiesLoad', - value : field.getValue() - }); - } - } - }, { - name : 'error.toolsPanelAcronymsLoad', - checked : PhDOE.user.conf.error.toolsPanelAcronymsLoad, - boxLabel : _('Automatically load acronyms data when displaying the file'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'toolsPanelAcronymsLoad', - value : field.getValue() - }); - } - } - }, { - xtype : 'fieldset', - checkboxToggle : true, - collapsed : !PhDOE.user.conf.error.toolsPanelDisplay, - title : _('Start with the panel open'), - listeners : { - collapse : function() - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'toolsPanelDisplay', - value : false - }); - }, - expand : function() - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'toolsPanelDisplay', - value : true - }); - } - }, - items: [{ - xtype : 'spinnerfield', - width : 60, - name : 'error.toolsPanelWidth', - module : 'error', - itemName : 'toolsPanelWidth', - value : PhDOE.user.conf.error.toolsPanelWidth || 375, - fieldLabel : _('Panel width'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }] - }] - }, { - xtype : 'fieldset', - title : _('Error description'), - iconCls : 'iconFilesError', - defaults : { hideLabel: true }, - defaultType : 'radio', - items : [{ - xtype : 'fieldset', - checkboxToggle : true, - collapsed : !PhDOE.user.conf.error.descPanelDisplay, - title : _('Start with the panel open'), - listeners : { - collapse : function() - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'descPanelDisplay', - value : false - }); - }, - expand : function() - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'descPanelDisplay', - value : true - }); - } - }, - items : [{ - xtype : 'spinnerfield', - width : 60, - name : 'error.descPanelHeight', - module : 'error', - itemName : 'descPanelHeight', - value : PhDOE.user.conf.error.descPanelHeight || 150, - fieldLabel : _('Panel height'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }] - }] - }] - }] - }); - ui.cmp._EditorConf.card4.superclass.initComponent.call(this); - } -}); - -// EditorConf card5 - Module "Files need Reviewed" Config -ui.cmp._EditorConf.card5 = Ext.extend(Ext.TabPanel, -{ - id : 'conf-card-5', - autoScroll : true, - activeTab : 0, - defaults : { - bodyStyle : 'padding: 5px;', - autoHeight : true, - autoScroll : true - }, - - initComponent : function() - { - Ext.apply(this, - { - items : [{ - title : _('Menu'), - iconCls : 'iconMenu', - items : [{ - xtype : 'fieldset', - title : _('Nb files to display'), - iconCls : 'iconFilesToDisplay', - defaults : { hideLabel: true }, - defaultType : 'spinnerfield', - items : [{ - width : 60, - name : 'reviewed.nbDisplay', - module : 'reviewed', - itemName : 'nbDisplay', - value : PhDOE.user.conf.reviewed.nbDisplay || 0, - boxLabel : _('files to display'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - - }, { - xtype: 'displayfield', - value: _('0 means no limit'), - style: { fontStyle: 'italic'} - }] - }] - }, { - title : _('User Interface'), - iconCls : 'iconUI', - items : [{ - xtype : 'fieldset', - title : _('ScrollBars'), - iconCls : 'iconScrollBar', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'reviewed.syncScrollbars', - checked : PhDOE.user.conf.reviewed.syncScrollbars, - boxLabel : _('Synchronize scroll bars'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'reviewed', - itemName : 'syncScrollbars', - value : field.getValue() - }); - } - } - }] - }, { - xtype : 'fieldset', - title : _('Tools'), - iconCls : 'iconConf', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'reviewed.toolsPanelLogLoad', - checked : PhDOE.user.conf.reviewed.toolsPanelLogLoad, - boxLabel : _('Automatically load the log when displaying the file'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'reviewed', - itemName : 'toolsPanelLogLoad', - value : field.getValue() - }); - } - } - }, { - xtype : 'fieldset', - checkboxToggle : true, - collapsed : !PhDOE.user.conf.reviewed.toolsPanelDisplay, - title : _('Start with the panel open'), - listeners : { - collapse : function() - { - new ui.task.UpdateConfTask({ - module : 'reviewed', - itemName : 'toolsPanelDisplay', - value : false - }); - }, - expand : function() - { - new ui.task.UpdateConfTask({ - module : 'reviewed', - itemName : 'toolsPanelDisplay', - value : true - }); - } - }, - items : [{ - xtype : 'spinnerfield', - width : 60, - name : 'reviewed.toolsPanelWidth', - module : 'reviewed', - itemName : 'toolsPanelWidth', - value : PhDOE.user.conf.reviewed.toolsPanelWidth || 375, - fieldLabel : _('Panel width'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }] - }] - }] - }] - }); - ui.cmp._EditorConf.card5.superclass.initComponent.call(this); - } -}); - -// EditorConf card6 - Module "All files" Config -ui.cmp._EditorConf.card6 = Ext.extend(Ext.TabPanel, -{ - id : 'conf-card-6', - autoScroll : true, - activeTab : 0, - defaults : { - bodyStyle : 'padding: 5px;', - autoHeight : true, - autoScroll : true - }, - - initComponent : function() - { - Ext.apply(this, - { - items : [{ - title : _('User Interface'), - iconCls : 'iconUI', - items : [{ - xtype : 'fieldset', - title : _('Tools'), - iconCls : 'iconConf', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'allFiles.toolsPanelLogLoad', - checked : PhDOE.user.conf.allFiles.toolsPanelLogLoad, - boxLabel : _('Automatically load the log when displaying the file'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'allFiles', - itemName : 'toolsPanelLogLoad', - value : field.getValue() - }); - } - } - }, { - name : 'allFiles.toolsPanelEntitiesLoad', - checked : PhDOE.user.conf.allFiles.toolsPanelEntitiesLoad, - boxLabel : _('Automatically load entities data when displaying the file'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'allFiles', - itemName : 'toolsPanelEntitiesLoad', - value : field.getValue() - }); - } - } - },{ - name : 'allFiles.toolsPanelAcronymsLoad', - checked : PhDOE.user.conf.allFiles.toolsPanelAcronymsLoad, - boxLabel : _('Automatically load acronyms data when displaying the file'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'allFiles', - itemName : 'toolsPanelAcronymsLoad', - value : field.getValue() - }); - } - } - }, { - xtype : 'fieldset', - checkboxToggle : true, - collapsed : !PhDOE.user.conf.allFiles.toolsPanelDisplay, - title : _('Start with the panel open'), - listeners : { - collapse : function() - { - new ui.task.UpdateConfTask({ - module : 'allFiles', - itemName : 'toolsPanelDisplay', - value : false - }); - }, - expand : function() - { - new ui.task.UpdateConfTask({ - module : 'allFiles', - itemName : 'toolsPanelDisplay', - value : true - }); - } - }, - items: [{ - xtype : 'spinnerfield', - width : 60, - name : 'allFiles.toolsPanelWidth', - module : 'allFiles', - itemName : 'toolsPanelWidth', - value : PhDOE.user.conf.allFiles.toolsPanelWidth || 375, - fieldLabel : _('Panel width'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }] - }] - }] - }] - }); - ui.cmp._EditorConf.card6.superclass.initComponent.call(this); - } -}); - -//------------------------------------------------------------------------------ -// EditorConf Win -ui.cmp.EditorConf = Ext.extend(Ext.Window, -{ - id : 'win-conf', - layout : 'border', - width : 700, - height : 470, - iconCls : 'iconConf', - title : _('Configuration'), - modal : true, - plain : true, - bodyBorder : false, - closeAction : 'hide', - buttons : [{ - text : _('Close'), - handler: function() - { - Ext.getCmp('win-conf').hide(); - } - }], - - listeners : { - show : function() - { - var view = Ext.getCmp('conf-menu-view'); - view.select(view.getNode(0)); - } - }, - - initComponent : function() - { - if (PhDOE.user.lang === 'en') { - ui.cmp._EditorConf.menuStore.loadData(ui.cmp._EditorConf.menuDefEn); - } else { - ui.cmp._EditorConf.menuStore.loadData(ui.cmp._EditorConf.menuDefNonEn); - } - - Ext.apply(this, - { - items : [{ - id : 'confMenu', - region : 'west', - border : false, - width : 190, - autoScroll : true, - items : [new ui.cmp._EditorConf.viewMenu()] - }, { - id : 'confCard', - region : 'center', - border : false, - layout : 'card', - width : 375, - frame : true, - activeItem : 0, - - bbar : new Ext.ux.StatusBar({ - defaultText : _('All changes take effect immediately'), - defaultIconCls : 'confStatusBar' - }), - - items : [ - new ui.cmp._EditorConf.card1(), - new ui.cmp._EditorConf.card2(), - new ui.cmp._EditorConf.card3(), - new ui.cmp._EditorConf.card4(), - new ui.cmp._EditorConf.card5(), - new ui.cmp._EditorConf.card6() - ] - }] - }); - ui.cmp.EditorConf.superclass.initComponent.call(this); - } -}); +});Ext.namespace('ui','ui.cmp','ui.cmp._EditorConf','ui.cmp._EditorCmd2Conf'); + +//------------------------------------------------------------------------------ +// EditorConf Win internals + +// EditorConf Win-Menu template +ui.cmp._EditorConf.tplMenu = new Ext.XTemplate( + '', + '', + '' +); +ui.cmp._EditorConf.tplMenu.compile(); + +// EditorConf Win-Menu items definition for EN +ui.cmp._EditorConf.menuDefEn = [ + ['1', 'card1', _('Main')], + ['4', 'card4', _('Module "Files with error"')], + ['6', 'card6', _('Module "All files"')] +]; + +// EditorConf Win-Menu items definition for Non-EN +ui.cmp._EditorConf.menuDefNonEn = [ + ['1', 'card1', _('Main')], + ['2', 'card2', _('Module "Files need translate"')], + ['3', 'card3', _('Module "Files need update"')], + ['4', 'card4', _('Module "Files with error"')], + ['5', 'card5', _('Module "Files need reviewed"')], + ['6', 'card6', _('Module "All files"')] +]; + +// EditorConf Win-Menu items store +ui.cmp._EditorConf.menuStore = new Ext.data.SimpleStore({ + id : 0, + fields : [ + { name : 'id'}, + { name : 'card'}, + { name : 'label'} + ] +}); + +// EditorConf Win-Menu view +ui.cmp._EditorConf.viewMenu = Ext.extend(Ext.DataView, +{ + id : 'conf-menu-view', + tpl : ui.cmp._EditorConf.tplMenu, + singleSelect : true, + overClass : 'x-view-over', + itemSelector : 'div.menu-wrap', + store : ui.cmp._EditorConf.menuStore, + listeners : { + selectionchange : function(view) + { + var r = view.getSelectedRecords(); + Ext.getCmp('confCard').layout.setActiveItem('conf-card-' + r[0].data.id); + } + } +}); + +// CodeMirror2 Theme datastore +ui.cmp._EditorCmd2Conf.themeStore = new Ext.data.SimpleStore({ + fields : ['themeFile', { + name : 'themeName', + type : 'string' + }], + data : [ + [false, _('No theme')], + ['default', _('Default theme')], + ['cobalt', _('Cobalt')], + ['eclipse', _('Eclipse')], + ['elegant', _('Elegant')], + ['monokai', _('Monokai')], + ['neat', _('Neat')], + ['night', _('Night')], + ['rubyblue', _('RubyBlue')] + ] +}); + +// doc-editor Theme datastore +ui.cmp._EditorConf.themeStore = new Ext.data.SimpleStore({ + fields : ['themeFile', { + name : 'themeName', + type : 'string' + }], + data : [ + ['themes/ExtJsThemes/black/css/xtheme-black.css', _('Black')], + ['themes/empty.css', _('Default')], + ['themes/ExtJsThemes/darkgray/css/xtheme-darkgray.css', _('DarkGray')], + ['js/ExtJs/resources/css/xtheme-gray.css', _('Gray')], + ['themes/ExtJsThemes/gray-extend/css/xtheme-gray-extend.css', _('Gray Extend')], + ['themes/ExtJsThemes/indigo/css/xtheme-indigo.css', _('Indigo')], + ['themes/ExtJsThemes/midnight/css/xtheme-midnight.css', _('Midnight')], + ['themes/ExtJsThemes/olive/css/xtheme-olive.css', _('Olive')], + ['themes/ExtJsThemes/purple/css/xtheme-purple.css', _('Purple')], + ['themes/ExtJsThemes/silverCherry/css/xtheme-silverCherry.css', _('SilverCherry')], + ['themes/ExtJsThemes/ubuntu_human/css/xtheme-human.css', _('Ubuntu Human')] + ] +}); + +// doc-editor UI Lang datastore +ui.cmp._EditorConf.uiLangStore = new Ext.data.SimpleStore({ + fields : ['uiLang', { + name : 'uiLangName', + type : 'string' + }], + data : [ + ['default', _('Default language, if available')], + ['en', _('English')], + ['fr', _('French')], + ['ru', _('Russian')], + ['es', _('Spanish')], + ['ar', _('Arabic')] + ] +}); + +ui.cmp._EditorConf.CommitChange = new Ext.util.DelayedTask(function() +{ + new ui.task.UpdateConfTask({ + module : this.module, + itemName : this.itemName, + value : this.getValue() + }); +}); + +// EditorConf card1 - mainApp +ui.cmp._EditorConf.card1 = Ext.extend(Ext.TabPanel, +{ + id : 'conf-card-1', + autoScroll : true, + activeTab : 0, + defaults : { bodyStyle: 'padding: 5px;', autoHeight : true, autoScroll : true }, + + initComponent : function() + { + Ext.apply(this, + { + items : [{ + title : _('User Interface'), + iconCls : 'iconUI', + labelAlign: 'top', + layout:'form', + items : [{ + xtype : 'fieldset', + title : _('Main menu'), + iconCls : 'iconMenu', + items : [{ + xtype : 'spinnerfield', + width : 60, + name : 'PhDOE.user.conf.main.mainMenuWidth', + module : 'main', + itemName : 'mainMenuWidth', + value : PhDOE.user.conf.main.mainMenuWidth || 300, + fieldLabel : _('Main menu width'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + var cmp = Ext.getCmp('main-menu-panel'), + val = this.getValue(); + PhDOE.user.conf.main.mainMenuWidth = val; + cmp.setWidth(val); + cmp.ownerCt.doLayout(); + + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + var cmp = Ext.getCmp('main-menu-panel'), + val = this.getValue(); + PhDOE.user.conf.main.mainMenuWidth = val; + cmp.setWidth(val); + cmp.ownerCt.doLayout(); + + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }] + }, { + xtype : 'fieldset', + iconCls : 'iconThemes', + title : _('Appearance'), + items : [{ + xtype : 'combo', + fieldLabel : _('Choose a theme'), + id : 'conf-combo-theme', + valueField : 'themeFile', + displayField : 'themeName', + triggerAction : 'all', + mode : 'local', + forceSelection : true, + editable : false, + value : PhDOE.user.conf.main.theme, + store : ui.cmp._EditorConf.themeStore, + listeners : { + render : function() + { + Ext.getCmp('conf-combo-theme').store.sort('themeName'); + }, + select : function(c) + { + var hrefTheme = c.getValue(); + + Ext.get('appTheme').dom.href = hrefTheme; + + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'theme', + value : hrefTheme + }); + } + } + },{ + xtype : 'combo', + fieldLabel : _('Force an UI language'), + id : 'conf-combo-ui-lang', + valueField : 'uiLang', + displayField : 'uiLangName', + triggerAction : 'all', + mode : 'local', + forceSelection : true, + editable : false, + value : PhDOE.user.conf.main.uiLang || 'default', + store : ui.cmp._EditorConf.uiLangStore, + listeners : { + select : function(c) + { + var uiLang = c.getValue(); + + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'uiLang', + value : uiLang + }); + } + } + }] + }, { + xtype : 'fieldset', + title : _('On save file'), + iconCls : 'iconSaveFile', + autoHeight : true, + defaults : { hideLabel: true }, + defaultType: 'radio', + items : [{ + autoHeight : true, + name : 'PhDOE.user.conf.main.onSaveFile', + module : 'main', + itemName : 'onSaveFile', + checked : (PhDOE.user.conf.main.onSaveFile === "ask-me") ? true : false, + boxLabel : _('Ask me if I want to check for error before saving the file'), + inputValue : 'ask-me', + listeners : { + check : function(field) + { + if (field.checked) { + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'onSaveFile', + value : field.getRawValue() + }); + } + } + } + }, { + autoHeight : true, + name : 'PhDOE.user.conf.main.onSaveFile', + module : 'main', + itemName : 'onSaveFile', + checked : (PhDOE.user.conf.main.onSaveFile === "always") ? true : false, + boxLabel : _('Always check for error before saving the file'), + inputValue : 'always', + listeners : { + check : function(field) + { + if (field.checked) { + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'onSaveFile', + value : field.getRawValue() + }); + } + } + } + }, { + autoHeight : true, + name : 'PhDOE.user.conf.main.onSaveFile', + module : 'main', + itemName : 'onSaveFile', + checked : (PhDOE.user.conf.main.onSaveFile === "never") ? true : false, + boxLabel : _('Never check for error before saving the file'), + inputValue : 'never', + listeners : { + check : function(field) + { + if (field.checked) { + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'onSaveFile', + value : field.getRawValue() + }); + } + } + } + }] + },{ + xtype : 'checkbox', + name : 'PhDOE.user.conf.main.displayENWork', + checked : PhDOE.user.conf.main.displayENWork, + boxLabel : _('Display EN work in "Work in progress" & "Patches for review" modules'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'displayENWork', + value : field.getValue() + }); + } + } + }] + }, { + title : _('External Data'), + iconCls : 'iconExternalData', + items : [{ + xtype : 'fieldset', + title : _('About mails'), + iconCls : 'iconMailing', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + autoHeight : true, + name : 'PhDOE.user.conf.main.loadMailsAtStartUp', + checked : PhDOE.user.conf.main.loadMailsAtStartUp, + boxLabel : _('Load mail at startUp'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'loadMailsAtStartUp', + value : field.getValue() + }); + } + } + }] + }, { + xtype : 'fieldset', + title : _('About bugs'), + iconCls : 'iconBugs', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + autoHeight : true, + name : 'PhDOE.user.conf.main.loadBugsAtStartUp', + checked : PhDOE.user.conf.main.loadBugsAtStartUp, + boxLabel : _('Load bugs at startUp'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'loadBugsAtStartUp', + value : field.getValue() + }); + } + } + }] + }] + }, { + title : _('Editor'), + iconCls : 'iconEditor', + items : [{ + xtype : 'fieldset', + title : _('Editor theme'), + iconCls : 'iconThemes', + items : [{ + xtype : 'combo', + fieldLabel : _('Choose a theme'), + id : 'conf-combo-cm2-theme', + valueField : 'themeFile', + displayField : 'themeName', + triggerAction : 'all', + mode : 'local', + forceSelection : true, + editable : false, + value : (PhDOE.user.conf.main.editorTheme || 'default'), + store : ui.cmp._EditorCmd2Conf.themeStore, + listeners : { + select : function(c) + { + var themeValue = c.getValue(); + + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'editorTheme', + value : themeValue + }); + } + } + }] + }] + }] + }); + ui.cmp._EditorConf.card1.superclass.initComponent.call(this); + } +}); + +// EditorConf card2 - Module "Files Need Translate" Config +ui.cmp._EditorConf.card2 = Ext.extend(Ext.TabPanel, +{ + id : 'conf-card-2', + autoScroll : true, + activeTab : 0, + defaults : { + bodyStyle : 'padding: 5px;', + autoHeight : true, + autoScroll : true + }, + + initComponent : function() + { + Ext.apply(this, + { + items : [{ + title : _('Menu'), + iconCls : 'iconMenu', + items : [{ + xtype : 'fieldset', + title : _('Nb files to display'), + iconCls : 'iconFilesToDisplay', + defaults : { hideLabel: true }, + items : [{ + xtype : 'spinnerfield', + width : 60, + name : 'PhDOE.user.conf.newFile.nbDisplay', + module : 'newFile', + itemName : 'nbDisplay', + value : PhDOE.user.conf.newFile.nbDisplay || 0, + boxLabel : _('files to display'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }, { + xtype : 'displayfield', + value : _('0 means no limit'), + style : { fontStyle: 'italic'} + }] + }] + }, { + title : _('User Interface'), + iconCls : 'iconUI', + items : [{ + xtype : 'fieldset', + title : _('ScrollBars'), + iconCls : 'iconScrollBar', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'PhDOE.user.conf.newFile.syncScrollbars', + checked : PhDOE.user.conf.newFile.syncScrollbars, + boxLabel : _('Synchronize scroll bars'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'newFile', + itemName : 'syncScrollbars', + value : field.getValue() + }); + } + } + }] + },{ + xtype : 'fieldset', + title : _('Tools'), + iconCls : 'iconConf', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + xtype : 'fieldset', + checkboxToggle : true, + collapsed : !PhDOE.user.conf.newFile.toolsPanelDisplay, + title : _('Start with the panel open'), + listeners : { + collapse : function() + { + new ui.task.UpdateConfTask({ + module : 'newFile', + itemName : 'toolsPanelDisplay', + value : false + }); + }, + expand : function() + { + new ui.task.UpdateConfTask({ + module : 'newFile', + itemName : 'toolsPanelDisplay', + value : true + }); + } + }, + items : [{ + xtype : 'spinnerfield', + width : 60, + name : 'newFile.toolsPanelWidth', + module : 'newFile', + itemName : 'toolsPanelWidth', + value : PhDOE.user.conf.newFile.toolsPanelWidth || 375, + fieldLabel : _('Panel width'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }] + }] + }, { + xtype : 'fieldset', + title : _('Right panel'), + iconCls : 'iconUI', + defaults : { hideLabel: true }, + defaultType : 'radio', + items : [ + /*{ + name: 'PhDOE.user.conf.newFile.secondPanel', + boxLabel: _('Display the Google Translation Panel'), + inputValue: 'google', + checked: (PhDOE.user.conf.newFile.secondPanel === 'google') ? true : false, + listeners: { + check : function(field) + { + if (field.checked) { + new ui.task.UpdateConfTask({ + module : 'newFile', + itemName : 'secondPanel', + value : field.getRawValue() + }); + } + } + } + },*/ + { + name : 'PhDOE.user.conf.newFile.secondPanel', + boxLabel : _('Display the original file'), + inputValue: 'originalFile', + checked: (PhDOE.user.conf.newFile.secondPanel === 'originalFile') ? true : false, + listeners : { + check : function(field) + { + if (field.checked) { + new ui.task.UpdateConfTask({ + module : 'newFile', + itemName : 'secondPanel', + value : field.getRawValue() + }); + } + } + } + },{ + name : 'PhDOE.user.conf.newFile.secondPanel', + boxLabel : _('Do not display a right panel'), + inputValue: 'none', + checked: (!Ext.isDefined(PhDOE.user.conf.newFile.secondPanel) || PhDOE.user.conf.newFile.secondPanel === 'none') ? true : false, + listeners : { + check : function(field) + { + if (field.checked) { + new ui.task.UpdateConfTask({ + module : 'newFile', + itemName : 'secondPanel', + value : field.getRawValue() + }); + } + } + } + }] + }] + }] + }); + ui.cmp._EditorConf.card2.superclass.initComponent.call(this); + } +}); + +// EditorConf card3 - Module "Files Need Update" Config +ui.cmp._EditorConf.card3 = Ext.extend(Ext.TabPanel, +{ + id : 'conf-card-3', + autoScroll : true, + activeTab : 0, + defaults : { + bodyStyle : 'padding: 5px;', + autoHeight : true, + autoScroll : true + }, + + initComponent : function() + { + Ext.apply(this, + { + items : [{ + title : _('Menu'), + iconCls : 'iconMenu', + items : [{ + xtype : 'fieldset', + title : _('Nb files to display'), + iconCls : 'iconFilesToDisplay', + defaults : { hideLabel: true }, + defaultType : 'spinnerfield', + items : [{ + width : 60, + name : 'PhDOE.user.conf.needUpdate.nbDisplay', + module : 'needUpdate', + itemName : 'nbDisplay', + value : PhDOE.user.conf.needUpdate.nbDisplay || 0, + boxLabel : _('files to display'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + + }, { + xtype : 'displayfield', + value : _('0 means no limit'), + style : { fontStyle: 'italic'} + }] + }] + }, { + title : _('User Interface'), + iconCls : 'iconUI', + items : [{ + xtype : 'fieldset', + title : _('ScrollBars'), + iconCls : 'iconScrollBar', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'needUpdate.syncScrollbars', + checked : PhDOE.user.conf.needUpdate.syncScrollbars, + boxLabel : _('Synchronize scroll bars'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'needUpdate', + itemName : 'syncScrollbars', + value : field.getValue() + }); + } + } + }] + }, { + xtype : 'fieldset', + title : _('Tools'), + iconCls : 'iconConf', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'needUpdate.toolsPanelLogLoad', + checked : PhDOE.user.conf.needUpdate.toolsPanelLogLoad, + boxLabel : _('Automatically load the log when displaying the file'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'needUpdate', + itemName : 'toolsPanelLogLoad', + value : field.getValue() + }); + } + } + }, { + xtype : 'fieldset', + checkboxToggle : true, + collapsed : !PhDOE.user.conf.needUpdate.toolsPanelDisplay, + title : _('Start with the panel open'), + listeners : { + collapse : function() + { + new ui.task.UpdateConfTask({ + module : 'needUpdate', + itemName : 'toolsPanelDisplay', + value : false + }); + }, + expand : function() + { + new ui.task.UpdateConfTask({ + module : 'needUpdate', + itemName : 'toolsPanelDisplay', + value : true + }); + } + }, + items : [{ + xtype : 'spinnerfield', + width : 60, + name : 'needUpdate.toolsPanelWidth', + module : 'needUpdate', + itemName : 'toolsPanelWidth', + value : PhDOE.user.conf.needUpdate.toolsPanelWidth || 375, + fieldLabel : _('Panel width'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }] + }] + }, { + xtype : 'fieldset', + title : _('Diff view'), + iconCls : 'iconDiffView', + defaults : { hideLabel: true }, + defaultType : 'radio', + items : [{ + xtype : 'fieldset', + checkboxToggle : true, + collapsed : !PhDOE.user.conf.needUpdate.diffPanelDisplay, + title : _('Start with the panel open'), + listeners : { + collapse : function() + { + new ui.task.UpdateConfTask({ + module : 'needUpdate', + itemName : 'diffPanelDisplay', + value : false + }); + }, + expand : function() + { + new ui.task.UpdateConfTask({ + module : 'needUpdate', + itemName : 'diffPanelDisplay', + value : true + }); + } + }, + items : [{ + xtype : 'spinnerfield', + width : 60, + name : 'needUpdate.diffPanelHeight', + module : 'needUpdate', + itemName : 'diffPanelHeight', + value : PhDOE.user.conf.needUpdate.diffPanelHeight || 150, + fieldLabel : _('Panel height'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }] + }, { + name : 'needUpdate.diffMethod', + checked : (PhDOE.user.conf.needUpdate.diffMethod === "using-viewvc") ? true : false, + boxLabel : _('Using ViewVc from php web site'), + inputValue : 'using-viewvc', + listeners : { + check : function(field) + { + if (field.checked) { + new ui.task.UpdateConfTask({ + module : 'needUpdate', + itemName : 'diffMethod', + value : field.getRawValue() + }); + } + } + } + }, { + name : 'needUpdate.diffMethod', + checked : (PhDOE.user.conf.needUpdate.diffMethod === "using-exec") ? true : false, + boxLabel : _('Using diff -u command line'), + inputValue : 'using-exec', + listeners : { + check : function(field) + { + if (field.checked) { + new ui.task.UpdateConfTask({ + module : 'needUpdate', + itemName : 'diffMethod', + value : field.getRawValue() + }); + } + } + } + }] + }] + }] + }); + ui.cmp._EditorConf.card3.superclass.initComponent.call(this); + } +}); + +// EditorConf card4 - Module "Files with Error" Config +ui.cmp._EditorConf.card4 = Ext.extend(Ext.TabPanel, +{ + id : 'conf-card-4', + autoScroll : true, + activeTab : 0, + defaults : { + bodyStyle : 'padding: 5px;', + autoHeight : true, + autoScroll : true + }, + + initComponent : function() + { + Ext.apply(this, + { + items : [{ + title : _('Menu'), + iconCls : 'iconMenu', + items : [{ + xtype : 'fieldset', + title : _('Nb files to display'), + iconCls : 'iconFilesToDisplay', + defaults : { hideLabel: true }, + defaultType : 'spinnerfield', + items : [{ + width : 60, + name : 'PhDOE.user.conf.error.nbDisplay', + module : 'error', + itemName : 'nbDisplay', + value : PhDOE.user.conf.error.nbDisplay || 0, + boxLabel : _('files to display'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + + }, { + xtype : 'displayfield', + value : _('0 means no limit'), + style : { fontStyle: 'italic'} + }] + }, { + hidden : ( PhDOE.user.lang === 'en' ), + xtype : 'fieldset', + title : _('Error type'), + iconCls : 'iconFilesError', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'error.skipNbLiteralTag', + checked : PhDOE.user.conf.error.skipNbLiteralTag, + boxLabel : _('Skip nbLiteralTag error'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'skipNbLiteralTag', + value : field.getValue() + }); + } + } + }] + }] + }, { + title : _('User Interface'), + iconCls : 'iconUI', + items : [{ + xtype : 'fieldset', + title : _('ScrollBars'), + iconCls : 'iconScrollBar', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'error.syncScrollbars', + checked : PhDOE.user.conf.error.syncScrollbars, + boxLabel : _('Synchronize scroll bars'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'syncScrollbars', + value : field.getValue() + }); + } + } + }] + }, { + xtype : 'fieldset', + title : _('Tools'), + iconCls : 'iconConf', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'error.toolsPanelLogLoad', + checked : PhDOE.user.conf.error.toolsPanelLogLoad, + boxLabel : _('Automatically load the log when displaying the file'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'toolsPanelLogLoad', + value : field.getValue() + }); + } + } + }, { + name : 'error.toolsPanelEntitiesLoad', + checked : PhDOE.user.conf.error.toolsPanelEntitiesLoad, + boxLabel : _('Automatically load entities data when displaying the file'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'toolsPanelEntitiesLoad', + value : field.getValue() + }); + } + } + }, { + name : 'error.toolsPanelAcronymsLoad', + checked : PhDOE.user.conf.error.toolsPanelAcronymsLoad, + boxLabel : _('Automatically load acronyms data when displaying the file'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'toolsPanelAcronymsLoad', + value : field.getValue() + }); + } + } + }, { + xtype : 'fieldset', + checkboxToggle : true, + collapsed : !PhDOE.user.conf.error.toolsPanelDisplay, + title : _('Start with the panel open'), + listeners : { + collapse : function() + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'toolsPanelDisplay', + value : false + }); + }, + expand : function() + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'toolsPanelDisplay', + value : true + }); + } + }, + items: [{ + xtype : 'spinnerfield', + width : 60, + name : 'error.toolsPanelWidth', + module : 'error', + itemName : 'toolsPanelWidth', + value : PhDOE.user.conf.error.toolsPanelWidth || 375, + fieldLabel : _('Panel width'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }] + }] + }, { + xtype : 'fieldset', + title : _('Error description'), + iconCls : 'iconFilesError', + defaults : { hideLabel: true }, + defaultType : 'radio', + items : [{ + xtype : 'fieldset', + checkboxToggle : true, + collapsed : !PhDOE.user.conf.error.descPanelDisplay, + title : _('Start with the panel open'), + listeners : { + collapse : function() + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'descPanelDisplay', + value : false + }); + }, + expand : function() + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'descPanelDisplay', + value : true + }); + } + }, + items : [{ + xtype : 'spinnerfield', + width : 60, + name : 'error.descPanelHeight', + module : 'error', + itemName : 'descPanelHeight', + value : PhDOE.user.conf.error.descPanelHeight || 150, + fieldLabel : _('Panel height'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }] + }] + }] + }] + }); + ui.cmp._EditorConf.card4.superclass.initComponent.call(this); + } +}); + +// EditorConf card5 - Module "Files need Reviewed" Config +ui.cmp._EditorConf.card5 = Ext.extend(Ext.TabPanel, +{ + id : 'conf-card-5', + autoScroll : true, + activeTab : 0, + defaults : { + bodyStyle : 'padding: 5px;', + autoHeight : true, + autoScroll : true + }, + + initComponent : function() + { + Ext.apply(this, + { + items : [{ + title : _('Menu'), + iconCls : 'iconMenu', + items : [{ + xtype : 'fieldset', + title : _('Nb files to display'), + iconCls : 'iconFilesToDisplay', + defaults : { hideLabel: true }, + defaultType : 'spinnerfield', + items : [{ + width : 60, + name : 'reviewed.nbDisplay', + module : 'reviewed', + itemName : 'nbDisplay', + value : PhDOE.user.conf.reviewed.nbDisplay || 0, + boxLabel : _('files to display'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + + }, { + xtype: 'displayfield', + value: _('0 means no limit'), + style: { fontStyle: 'italic'} + }] + }] + }, { + title : _('User Interface'), + iconCls : 'iconUI', + items : [{ + xtype : 'fieldset', + title : _('ScrollBars'), + iconCls : 'iconScrollBar', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'reviewed.syncScrollbars', + checked : PhDOE.user.conf.reviewed.syncScrollbars, + boxLabel : _('Synchronize scroll bars'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'reviewed', + itemName : 'syncScrollbars', + value : field.getValue() + }); + } + } + }] + }, { + xtype : 'fieldset', + title : _('Tools'), + iconCls : 'iconConf', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'reviewed.toolsPanelLogLoad', + checked : PhDOE.user.conf.reviewed.toolsPanelLogLoad, + boxLabel : _('Automatically load the log when displaying the file'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'reviewed', + itemName : 'toolsPanelLogLoad', + value : field.getValue() + }); + } + } + }, { + xtype : 'fieldset', + checkboxToggle : true, + collapsed : !PhDOE.user.conf.reviewed.toolsPanelDisplay, + title : _('Start with the panel open'), + listeners : { + collapse : function() + { + new ui.task.UpdateConfTask({ + module : 'reviewed', + itemName : 'toolsPanelDisplay', + value : false + }); + }, + expand : function() + { + new ui.task.UpdateConfTask({ + module : 'reviewed', + itemName : 'toolsPanelDisplay', + value : true + }); + } + }, + items : [{ + xtype : 'spinnerfield', + width : 60, + name : 'reviewed.toolsPanelWidth', + module : 'reviewed', + itemName : 'toolsPanelWidth', + value : PhDOE.user.conf.reviewed.toolsPanelWidth || 375, + fieldLabel : _('Panel width'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }] + }] + }] + }] + }); + ui.cmp._EditorConf.card5.superclass.initComponent.call(this); + } +}); + +// EditorConf card6 - Module "All files" Config +ui.cmp._EditorConf.card6 = Ext.extend(Ext.TabPanel, +{ + id : 'conf-card-6', + autoScroll : true, + activeTab : 0, + defaults : { + bodyStyle : 'padding: 5px;', + autoHeight : true, + autoScroll : true + }, + + initComponent : function() + { + Ext.apply(this, + { + items : [{ + title : _('User Interface'), + iconCls : 'iconUI', + items : [{ + xtype : 'fieldset', + title : _('Tools'), + iconCls : 'iconConf', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'allFiles.toolsPanelLogLoad', + checked : PhDOE.user.conf.allFiles.toolsPanelLogLoad, + boxLabel : _('Automatically load the log when displaying the file'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'allFiles', + itemName : 'toolsPanelLogLoad', + value : field.getValue() + }); + } + } + }, { + name : 'allFiles.toolsPanelEntitiesLoad', + checked : PhDOE.user.conf.allFiles.toolsPanelEntitiesLoad, + boxLabel : _('Automatically load entities data when displaying the file'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'allFiles', + itemName : 'toolsPanelEntitiesLoad', + value : field.getValue() + }); + } + } + },{ + name : 'allFiles.toolsPanelAcronymsLoad', + checked : PhDOE.user.conf.allFiles.toolsPanelAcronymsLoad, + boxLabel : _('Automatically load acronyms data when displaying the file'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'allFiles', + itemName : 'toolsPanelAcronymsLoad', + value : field.getValue() + }); + } + } + }, { + xtype : 'fieldset', + checkboxToggle : true, + collapsed : !PhDOE.user.conf.allFiles.toolsPanelDisplay, + title : _('Start with the panel open'), + listeners : { + collapse : function() + { + new ui.task.UpdateConfTask({ + module : 'allFiles', + itemName : 'toolsPanelDisplay', + value : false + }); + }, + expand : function() + { + new ui.task.UpdateConfTask({ + module : 'allFiles', + itemName : 'toolsPanelDisplay', + value : true + }); + } + }, + items: [{ + xtype : 'spinnerfield', + width : 60, + name : 'allFiles.toolsPanelWidth', + module : 'allFiles', + itemName : 'toolsPanelWidth', + value : PhDOE.user.conf.allFiles.toolsPanelWidth || 375, + fieldLabel : _('Panel width'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }] + }] + }] + }] + }); + ui.cmp._EditorConf.card6.superclass.initComponent.call(this); + } +}); + +//------------------------------------------------------------------------------ +// EditorConf Win +ui.cmp.EditorConf = Ext.extend(Ext.Window, +{ + id : 'win-conf', + layout : 'border', + width : 700, + height : 470, + iconCls : 'iconConf', + title : _('Configuration'), + modal : true, + plain : true, + bodyBorder : false, + closeAction : 'hide', + buttons : [{ + text : _('Close'), + handler: function() + { + Ext.getCmp('win-conf').hide(); + } + }], + + listeners : { + show : function() + { + var view = Ext.getCmp('conf-menu-view'); + view.select(view.getNode(0)); + } + }, + + initComponent : function() + { + if (PhDOE.user.lang === 'en') { + ui.cmp._EditorConf.menuStore.loadData(ui.cmp._EditorConf.menuDefEn); + } else { + ui.cmp._EditorConf.menuStore.loadData(ui.cmp._EditorConf.menuDefNonEn); + } + + Ext.apply(this, + { + items : [{ + id : 'confMenu', + region : 'west', + border : false, + width : 190, + autoScroll : true, + items : [new ui.cmp._EditorConf.viewMenu()] + }, { + id : 'confCard', + region : 'center', + border : false, + layout : 'card', + width : 375, + frame : true, + activeItem : 0, + + bbar : new Ext.ux.StatusBar({ + defaultText : _('All changes take effect immediately'), + defaultIconCls : 'confStatusBar' + }), + + items : [ + new ui.cmp._EditorConf.card1(), + new ui.cmp._EditorConf.card2(), + new ui.cmp._EditorConf.card3(), + new ui.cmp._EditorConf.card4(), + new ui.cmp._EditorConf.card5(), + new ui.cmp._EditorConf.card6() + ] + }] + }); + ui.cmp.EditorConf.superclass.initComponent.call(this); + } +}); Ext.namespace('ui','ui.cmp','ui.cmp._EmailPrompt'); // config - { name, email } diff --git a/js/ui/cmp/EditorConf.js b/js/ui/cmp/EditorConf.js index f5fa533a..016aa008 100644 --- a/js/ui/cmp/EditorConf.js +++ b/js/ui/cmp/EditorConf.js @@ -1,1446 +1,1446 @@ -Ext.namespace('ui','ui.cmp','ui.cmp._EditorConf','ui.cmp._EditorCmd2Conf'); - -//------------------------------------------------------------------------------ -// EditorConf Win internals - -// EditorConf Win-Menu template -ui.cmp._EditorConf.tplMenu = new Ext.XTemplate( - '', - '', - '' -); -ui.cmp._EditorConf.tplMenu.compile(); - -// EditorConf Win-Menu items definition for EN -ui.cmp._EditorConf.menuDefEn = [ - ['1', 'card1', _('Main')], - ['4', 'card4', _('Module "Files with error"')], - ['6', 'card6', _('Module "All files"')] -]; - -// EditorConf Win-Menu items definition for Non-EN -ui.cmp._EditorConf.menuDefNonEn = [ - ['1', 'card1', _('Main')], - ['2', 'card2', _('Module "Files need translate"')], - ['3', 'card3', _('Module "Files need update"')], - ['4', 'card4', _('Module "Files with error"')], - ['5', 'card5', _('Module "Files need reviewed"')], - ['6', 'card6', _('Module "All files"')] -]; - -// EditorConf Win-Menu items store -ui.cmp._EditorConf.menuStore = new Ext.data.SimpleStore({ - id : 0, - fields : [ - { name : 'id'}, - { name : 'card'}, - { name : 'label'} - ] -}); - -// EditorConf Win-Menu view -ui.cmp._EditorConf.viewMenu = Ext.extend(Ext.DataView, -{ - id : 'conf-menu-view', - tpl : ui.cmp._EditorConf.tplMenu, - singleSelect : true, - overClass : 'x-view-over', - itemSelector : 'div.menu-wrap', - store : ui.cmp._EditorConf.menuStore, - listeners : { - selectionchange : function(view) - { - var r = view.getSelectedRecords(); - Ext.getCmp('confCard').layout.setActiveItem('conf-card-' + r[0].data.id); - } - } -}); - -// CodeMirror2 Theme datastore -ui.cmp._EditorCmd2Conf.themeStore = new Ext.data.SimpleStore({ - fields : ['themeFile', { - name : 'themeName', - type : 'string' - }], - data : [ - [false, _('No theme')], - ['default', _('Default theme')], - ['cobalt', _('Cobalt')], - ['eclipse', _('Eclipse')], - ['elegant', _('Elegant')], - ['monokai', _('Monokai')], - ['neat', _('Neat')], - ['night', _('Night')], - ['rubyblue', _('RubyBlue')] - ] -}); - -// doc-editor Theme datastore -ui.cmp._EditorConf.themeStore = new Ext.data.SimpleStore({ - fields : ['themeFile', { - name : 'themeName', - type : 'string' - }], - data : [ - ['themes/ExtJsThemes/black/css/xtheme-black.css', _('Black')], - ['themes/empty.css', _('Default')], - ['themes/ExtJsThemes/darkgray/css/xtheme-darkgray.css', _('DarkGray')], - ['js/ExtJs/resources/css/xtheme-gray.css', _('Gray')], - ['themes/ExtJsThemes/gray-extend/css/xtheme-gray-extend.css', _('Gray Extend')], - ['themes/ExtJsThemes/indigo/css/xtheme-indigo.css', _('Indigo')], - ['themes/ExtJsThemes/midnight/css/xtheme-midnight.css', _('Midnight')], - ['themes/ExtJsThemes/olive/css/xtheme-olive.css', _('Olive')], - ['themes/ExtJsThemes/purple/css/xtheme-purple.css', _('Purple')], - ['themes/ExtJsThemes/silverCherry/css/xtheme-silverCherry.css', _('SilverCherry')], - ['themes/ExtJsThemes/ubuntu_human/css/xtheme-human.css', _('Ubuntu Human')] - ] -}); - -// doc-editor UI Lang datastore -ui.cmp._EditorConf.uiLangStore = new Ext.data.SimpleStore({ - fields : ['uiLang', { - name : 'uiLangName', - type : 'string' - }], - data : [ - ['default', _('Default language, if available')], - ['en', _('English')], - ['fr', _('French')], - ['ru', _('Russian')], - ['es', _('Spanish')], - ['ar', _('Arabic')] - ] -}); - -ui.cmp._EditorConf.CommitChange = new Ext.util.DelayedTask(function() -{ - new ui.task.UpdateConfTask({ - module : this.module, - itemName : this.itemName, - value : this.getValue() - }); -}); - -// EditorConf card1 - mainApp -ui.cmp._EditorConf.card1 = Ext.extend(Ext.TabPanel, -{ - id : 'conf-card-1', - autoScroll : true, - activeTab : 0, - defaults : { bodyStyle: 'padding: 5px;', autoHeight : true, autoScroll : true }, - - initComponent : function() - { - Ext.apply(this, - { - items : [{ - title : _('User Interface'), - iconCls : 'iconUI', - labelAlign: 'top', - layout:'form', - items : [{ - xtype : 'fieldset', - title : _('Main menu'), - iconCls : 'iconMenu', - items : [{ - xtype : 'spinnerfield', - width : 60, - name : 'PhDOE.user.conf.main.mainMenuWidth', - module : 'main', - itemName : 'mainMenuWidth', - value : PhDOE.user.conf.main.mainMenuWidth || 300, - fieldLabel : _('Main menu width'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - var cmp = Ext.getCmp('main-menu-panel'), - val = this.getValue(); - PhDOE.user.conf.main.mainMenuWidth = val; - cmp.setWidth(val); - cmp.ownerCt.doLayout(); - - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - var cmp = Ext.getCmp('main-menu-panel'), - val = this.getValue(); - PhDOE.user.conf.main.mainMenuWidth = val; - cmp.setWidth(val); - cmp.ownerCt.doLayout(); - - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }] - }, { - xtype : 'fieldset', - iconCls : 'iconThemes', - title : _('Appearance'), - items : [{ - xtype : 'combo', - fieldLabel : _('Choose a theme'), - id : 'conf-combo-theme', - valueField : 'themeFile', - displayField : 'themeName', - triggerAction : 'all', - mode : 'local', - forceSelection : true, - editable : false, - value : PhDOE.user.conf.main.theme, - store : ui.cmp._EditorConf.themeStore, - listeners : { - render : function() - { - Ext.getCmp('conf-combo-theme').store.sort('themeName'); - }, - select : function(c) - { - var hrefTheme = c.getValue(); - - Ext.get('appTheme').dom.href = hrefTheme; - - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'theme', - value : hrefTheme - }); - } - } - },{ - xtype : 'combo', - fieldLabel : _('Force an UI language'), - id : 'conf-combo-ui-lang', - valueField : 'uiLang', - displayField : 'uiLangName', - triggerAction : 'all', - mode : 'local', - forceSelection : true, - editable : false, - value : PhDOE.user.conf.main.uiLang || 'default', - store : ui.cmp._EditorConf.uiLangStore, - listeners : { - select : function(c) - { - var uiLang = c.getValue(); - - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'uiLang', - value : uiLang - }); - } - } - }] - }, { - xtype : 'fieldset', - title : _('On save file'), - iconCls : 'iconSaveFile', - autoHeight : true, - defaults : { hideLabel: true }, - defaultType: 'radio', - items : [{ - autoHeight : true, - name : 'PhDOE.user.conf.main.onSaveFile', - module : 'main', - itemName : 'onSaveFile', - checked : (PhDOE.user.conf.main.onSaveFile === "ask-me") ? true : false, - boxLabel : _('Ask me if I want to check for error before saving the file'), - inputValue : 'ask-me', - listeners : { - check : function(field) - { - if (field.checked) { - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'onSaveFile', - value : field.getRawValue() - }); - } - } - } - }, { - autoHeight : true, - name : 'PhDOE.user.conf.main.onSaveFile', - module : 'main', - itemName : 'onSaveFile', - checked : (PhDOE.user.conf.main.onSaveFile === "always") ? true : false, - boxLabel : _('Always check for error before saving the file'), - inputValue : 'always', - listeners : { - check : function(field) - { - if (field.checked) { - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'onSaveFile', - value : field.getRawValue() - }); - } - } - } - }, { - autoHeight : true, - name : 'PhDOE.user.conf.main.onSaveFile', - module : 'main', - itemName : 'onSaveFile', - checked : (PhDOE.user.conf.main.onSaveFile === "never") ? true : false, - boxLabel : _('Never check for error before saving the file'), - inputValue : 'never', - listeners : { - check : function(field) - { - if (field.checked) { - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'onSaveFile', - value : field.getRawValue() - }); - } - } - } - }] - },{ - xtype : 'checkbox', - name : 'PhDOE.user.conf.main.displayENWork', - checked : PhDOE.user.conf.main.displayENWork, - boxLabel : _('Display EN work in "Work in progress" & "Patches for review" modules'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'displayENWork', - value : field.getValue() - }); - } - } - }] - }, { - title : _('External Data'), - iconCls : 'iconExternalData', - items : [{ - xtype : 'fieldset', - title : _('About mails'), - iconCls : 'iconMailing', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - autoHeight : true, - name : 'PhDOE.user.conf.main.loadMailsAtStartUp', - checked : PhDOE.user.conf.main.loadMailsAtStartUp, - boxLabel : _('Load mail at startUp'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'loadMailsAtStartUp', - value : field.getValue() - }); - } - } - }] - }, { - xtype : 'fieldset', - title : _('About bugs'), - iconCls : 'iconBugs', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - autoHeight : true, - name : 'PhDOE.user.conf.main.loadBugsAtStartUp', - checked : PhDOE.user.conf.main.loadBugsAtStartUp, - boxLabel : _('Load bugs at startUp'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'loadBugsAtStartUp', - value : field.getValue() - }); - } - } - }] - }] - }, { - title : _('Editor'), - iconCls : 'iconEditor', - items : [{ - xtype : 'fieldset', - title : _('Editor theme'), - iconCls : 'iconThemes', - items : [{ - xtype : 'combo', - fieldLabel : _('Choose a theme'), - id : 'conf-combo-cm2-theme', - valueField : 'themeFile', - displayField : 'themeName', - triggerAction : 'all', - mode : 'local', - forceSelection : true, - editable : false, - value : (PhDOE.user.conf.main.editorTheme || 'default'), - store : ui.cmp._EditorCmd2Conf.themeStore, - listeners : { - select : function(c) - { - var themeValue = c.getValue(); - - new ui.task.UpdateConfTask({ - module : 'main', - itemName : 'editorTheme', - value : themeValue - }); - } - } - }] - }] - }] - }); - ui.cmp._EditorConf.card1.superclass.initComponent.call(this); - } -}); - -// EditorConf card2 - Module "Files Need Translate" Config -ui.cmp._EditorConf.card2 = Ext.extend(Ext.TabPanel, -{ - id : 'conf-card-2', - autoScroll : true, - activeTab : 0, - defaults : { - bodyStyle : 'padding: 5px;', - autoHeight : true, - autoScroll : true - }, - - initComponent : function() - { - Ext.apply(this, - { - items : [{ - title : _('Menu'), - iconCls : 'iconMenu', - items : [{ - xtype : 'fieldset', - title : _('Nb files to display'), - iconCls : 'iconFilesToDisplay', - defaults : { hideLabel: true }, - items : [{ - xtype : 'spinnerfield', - width : 60, - name : 'PhDOE.user.conf.newFile.nbDisplay', - module : 'newFile', - itemName : 'nbDisplay', - value : PhDOE.user.conf.newFile.nbDisplay || 0, - boxLabel : _('files to display'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }, { - xtype : 'displayfield', - value : _('0 means no limit'), - style : { fontStyle: 'italic'} - }] - }] - }, { - title : _('User Interface'), - iconCls : 'iconUI', - items : [{ - xtype : 'fieldset', - title : _('ScrollBars'), - iconCls : 'iconScrollBar', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'PhDOE.user.conf.newFile.syncScrollbars', - checked : PhDOE.user.conf.newFile.syncScrollbars, - boxLabel : _('Synchronize scroll bars'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'newFile', - itemName : 'syncScrollbars', - value : field.getValue() - }); - } - } - }] - },{ - xtype : 'fieldset', - title : _('Tools'), - iconCls : 'iconConf', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - xtype : 'fieldset', - checkboxToggle : true, - collapsed : !PhDOE.user.conf.newFile.toolsPanelDisplay, - title : _('Start with the panel open'), - listeners : { - collapse : function() - { - new ui.task.UpdateConfTask({ - module : 'newFile', - itemName : 'toolsPanelDisplay', - value : false - }); - }, - expand : function() - { - new ui.task.UpdateConfTask({ - module : 'newFile', - itemName : 'toolsPanelDisplay', - value : true - }); - } - }, - items : [{ - xtype : 'spinnerfield', - width : 60, - name : 'newFile.toolsPanelWidth', - module : 'newFile', - itemName : 'toolsPanelWidth', - value : PhDOE.user.conf.newFile.toolsPanelWidth || 375, - fieldLabel : _('Panel width'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }] - }] - }, { - xtype : 'fieldset', - title : _('Right panel'), - iconCls : 'iconUI', - defaults : { hideLabel: true }, - defaultType : 'radio', - items : [ - /*{ - name: 'PhDOE.user.conf.newFile.secondPanel', - boxLabel: _('Display the Google Translation Panel'), - inputValue: 'google', - checked: (PhDOE.user.conf.newFile.secondPanel === 'google') ? true : false, - listeners: { - check : function(field) - { - if (field.checked) { - new ui.task.UpdateConfTask({ - module : 'newFile', - itemName : 'secondPanel', - value : field.getRawValue() - }); - } - } - } - },*/ - { - name : 'PhDOE.user.conf.newFile.secondPanel', - boxLabel : _('Display the original file'), - inputValue: 'originalFile', - checked: (PhDOE.user.conf.newFile.secondPanel === 'originalFile') ? true : false, - listeners : { - check : function(field) - { - if (field.checked) { - new ui.task.UpdateConfTask({ - module : 'newFile', - itemName : 'secondPanel', - value : field.getRawValue() - }); - } - } - } - },{ - name : 'PhDOE.user.conf.newFile.secondPanel', - boxLabel : _('Do not display a right panel'), - inputValue: 'none', - checked: (!Ext.isDefined(PhDOE.user.conf.newFile.secondPanel) || PhDOE.user.conf.newFile.secondPanel === 'none') ? true : false, - listeners : { - check : function(field) - { - if (field.checked) { - new ui.task.UpdateConfTask({ - module : 'newFile', - itemName : 'secondPanel', - value : field.getRawValue() - }); - } - } - } - }] - }] - }] - }); - ui.cmp._EditorConf.card2.superclass.initComponent.call(this); - } -}); - -// EditorConf card3 - Module "Files Need Update" Config -ui.cmp._EditorConf.card3 = Ext.extend(Ext.TabPanel, -{ - id : 'conf-card-3', - autoScroll : true, - activeTab : 0, - defaults : { - bodyStyle : 'padding: 5px;', - autoHeight : true, - autoScroll : true - }, - - initComponent : function() - { - Ext.apply(this, - { - items : [{ - title : _('Menu'), - iconCls : 'iconMenu', - items : [{ - xtype : 'fieldset', - title : _('Nb files to display'), - iconCls : 'iconFilesToDisplay', - defaults : { hideLabel: true }, - defaultType : 'spinnerfield', - items : [{ - width : 60, - name : 'PhDOE.user.conf.needUpdate.nbDisplay', - module : 'needUpdate', - itemName : 'nbDisplay', - value : PhDOE.user.conf.needUpdate.nbDisplay || 0, - boxLabel : _('files to display'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - - }, { - xtype : 'displayfield', - value : _('0 means no limit'), - style : { fontStyle: 'italic'} - }] - }] - }, { - title : _('User Interface'), - iconCls : 'iconUI', - items : [{ - xtype : 'fieldset', - title : _('ScrollBars'), - iconCls : 'iconScrollBar', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'needUpdate.syncScrollbars', - checked : PhDOE.user.conf.needUpdate.syncScrollbars, - boxLabel : _('Synchronize scroll bars'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'needUpdate', - itemName : 'syncScrollbars', - value : field.getValue() - }); - } - } - }] - }, { - xtype : 'fieldset', - title : _('Tools'), - iconCls : 'iconConf', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'needUpdate.toolsPanelLogLoad', - checked : PhDOE.user.conf.needUpdate.toolsPanelLogLoad, - boxLabel : _('Automatically load the log when displaying the file'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'needUpdate', - itemName : 'toolsPanelLogLoad', - value : field.getValue() - }); - } - } - }, { - xtype : 'fieldset', - checkboxToggle : true, - collapsed : !PhDOE.user.conf.needUpdate.toolsPanelDisplay, - title : _('Start with the panel open'), - listeners : { - collapse : function() - { - new ui.task.UpdateConfTask({ - module : 'needUpdate', - itemName : 'toolsPanelDisplay', - value : false - }); - }, - expand : function() - { - new ui.task.UpdateConfTask({ - module : 'needUpdate', - itemName : 'toolsPanelDisplay', - value : true - }); - } - }, - items : [{ - xtype : 'spinnerfield', - width : 60, - name : 'needUpdate.toolsPanelWidth', - module : 'needUpdate', - itemName : 'toolsPanelWidth', - value : PhDOE.user.conf.needUpdate.toolsPanelWidth || 375, - fieldLabel : _('Panel width'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }] - }] - }, { - xtype : 'fieldset', - title : _('Diff view'), - iconCls : 'iconDiffView', - defaults : { hideLabel: true }, - defaultType : 'radio', - items : [{ - xtype : 'fieldset', - checkboxToggle : true, - collapsed : !PhDOE.user.conf.needUpdate.diffPanelDisplay, - title : _('Start with the panel open'), - listeners : { - collapse : function() - { - new ui.task.UpdateConfTask({ - module : 'needUpdate', - itemName : 'diffPanelDisplay', - value : false - }); - }, - expand : function() - { - new ui.task.UpdateConfTask({ - module : 'needUpdate', - itemName : 'diffPanelDisplay', - value : true - }); - } - }, - items : [{ - xtype : 'spinnerfield', - width : 60, - name : 'needUpdate.diffPanelHeight', - module : 'needUpdate', - itemName : 'diffPanelHeight', - value : PhDOE.user.conf.needUpdate.diffPanelHeight || 150, - fieldLabel : _('Panel height'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }] - }, { - name : 'needUpdate.diffMethod', - checked : (PhDOE.user.conf.needUpdate.diffMethod === "using-viewvc") ? true : false, - boxLabel : _('Using ViewVc from php web site'), - inputValue : 'using-viewvc', - listeners : { - check : function(field) - { - if (field.checked) { - new ui.task.UpdateConfTask({ - module : 'needUpdate', - itemName : 'diffMethod', - value : field.getRawValue() - }); - } - } - } - }, { - name : 'needUpdate.diffMethod', - checked : (PhDOE.user.conf.needUpdate.diffMethod === "using-exec") ? true : false, - boxLabel : _('Using diff -u command line'), - inputValue : 'using-exec', - listeners : { - check : function(field) - { - if (field.checked) { - new ui.task.UpdateConfTask({ - module : 'needUpdate', - itemName : 'diffMethod', - value : field.getRawValue() - }); - } - } - } - }] - }] - }] - }); - ui.cmp._EditorConf.card3.superclass.initComponent.call(this); - } -}); - -// EditorConf card4 - Module "Files with Error" Config -ui.cmp._EditorConf.card4 = Ext.extend(Ext.TabPanel, -{ - id : 'conf-card-4', - autoScroll : true, - activeTab : 0, - defaults : { - bodyStyle : 'padding: 5px;', - autoHeight : true, - autoScroll : true - }, - - initComponent : function() - { - Ext.apply(this, - { - items : [{ - title : _('Menu'), - iconCls : 'iconMenu', - items : [{ - xtype : 'fieldset', - title : _('Nb files to display'), - iconCls : 'iconFilesToDisplay', - defaults : { hideLabel: true }, - defaultType : 'spinnerfield', - items : [{ - width : 60, - name : 'PhDOE.user.conf.error.nbDisplay', - module : 'error', - itemName : 'nbDisplay', - value : PhDOE.user.conf.error.nbDisplay || 0, - boxLabel : _('files to display'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - - }, { - xtype : 'displayfield', - value : _('0 means no limit'), - style : { fontStyle: 'italic'} - }] - }, { - hidden : ( PhDOE.user.lang === 'en' ), - xtype : 'fieldset', - title : _('Error type'), - iconCls : 'iconFilesError', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'error.skipNbLiteralTag', - checked : PhDOE.user.conf.error.skipNbLiteralTag, - boxLabel : _('Skip nbLiteralTag error'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'skipNbLiteralTag', - value : field.getValue() - }); - } - } - }] - }] - }, { - title : _('User Interface'), - iconCls : 'iconUI', - items : [{ - xtype : 'fieldset', - title : _('ScrollBars'), - iconCls : 'iconScrollBar', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'error.syncScrollbars', - checked : PhDOE.user.conf.error.syncScrollbars, - boxLabel : _('Synchronize scroll bars'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'syncScrollbars', - value : field.getValue() - }); - } - } - }] - }, { - xtype : 'fieldset', - title : _('Tools'), - iconCls : 'iconConf', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'error.toolsPanelLogLoad', - checked : PhDOE.user.conf.error.toolsPanelLogLoad, - boxLabel : _('Automatically load the log when displaying the file'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'toolsPanelLogLoad', - value : field.getValue() - }); - } - } - }, { - name : 'error.toolsPanelEntitiesLoad', - checked : PhDOE.user.conf.error.toolsPanelEntitiesLoad, - boxLabel : _('Automatically load entities data when displaying the file'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'toolsPanelEntitiesLoad', - value : field.getValue() - }); - } - } - }, { - name : 'error.toolsPanelAcronymsLoad', - checked : PhDOE.user.conf.error.toolsPanelAcronymsLoad, - boxLabel : _('Automatically load acronyms data when displaying the file'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'toolsPanelAcronymsLoad', - value : field.getValue() - }); - } - } - }, { - xtype : 'fieldset', - checkboxToggle : true, - collapsed : !PhDOE.user.conf.error.toolsPanelDisplay, - title : _('Start with the panel open'), - listeners : { - collapse : function() - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'toolsPanelDisplay', - value : false - }); - }, - expand : function() - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'toolsPanelDisplay', - value : true - }); - } - }, - items: [{ - xtype : 'spinnerfield', - width : 60, - name : 'error.toolsPanelWidth', - module : 'error', - itemName : 'toolsPanelWidth', - value : PhDOE.user.conf.error.toolsPanelWidth || 375, - fieldLabel : _('Panel width'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }] - }] - }, { - xtype : 'fieldset', - title : _('Error description'), - iconCls : 'iconFilesError', - defaults : { hideLabel: true }, - defaultType : 'radio', - items : [{ - xtype : 'fieldset', - checkboxToggle : true, - collapsed : !PhDOE.user.conf.error.descPanelDisplay, - title : _('Start with the panel open'), - listeners : { - collapse : function() - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'descPanelDisplay', - value : false - }); - }, - expand : function() - { - new ui.task.UpdateConfTask({ - module : 'error', - itemName : 'descPanelDisplay', - value : true - }); - } - }, - items : [{ - xtype : 'spinnerfield', - width : 60, - name : 'error.descPanelHeight', - module : 'error', - itemName : 'descPanelHeight', - value : PhDOE.user.conf.error.descPanelHeight || 150, - fieldLabel : _('Panel height'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }] - }] - }] - }] - }); - ui.cmp._EditorConf.card4.superclass.initComponent.call(this); - } -}); - -// EditorConf card5 - Module "Files need Reviewed" Config -ui.cmp._EditorConf.card5 = Ext.extend(Ext.TabPanel, -{ - id : 'conf-card-5', - autoScroll : true, - activeTab : 0, - defaults : { - bodyStyle : 'padding: 5px;', - autoHeight : true, - autoScroll : true - }, - - initComponent : function() - { - Ext.apply(this, - { - items : [{ - title : _('Menu'), - iconCls : 'iconMenu', - items : [{ - xtype : 'fieldset', - title : _('Nb files to display'), - iconCls : 'iconFilesToDisplay', - defaults : { hideLabel: true }, - defaultType : 'spinnerfield', - items : [{ - width : 60, - name : 'reviewed.nbDisplay', - module : 'reviewed', - itemName : 'nbDisplay', - value : PhDOE.user.conf.reviewed.nbDisplay || 0, - boxLabel : _('files to display'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - - }, { - xtype: 'displayfield', - value: _('0 means no limit'), - style: { fontStyle: 'italic'} - }] - }] - }, { - title : _('User Interface'), - iconCls : 'iconUI', - items : [{ - xtype : 'fieldset', - title : _('ScrollBars'), - iconCls : 'iconScrollBar', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'reviewed.syncScrollbars', - checked : PhDOE.user.conf.reviewed.syncScrollbars, - boxLabel : _('Synchronize scroll bars'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'reviewed', - itemName : 'syncScrollbars', - value : field.getValue() - }); - } - } - }] - }, { - xtype : 'fieldset', - title : _('Tools'), - iconCls : 'iconConf', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'reviewed.toolsPanelLogLoad', - checked : PhDOE.user.conf.reviewed.toolsPanelLogLoad, - boxLabel : _('Automatically load the log when displaying the file'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'reviewed', - itemName : 'toolsPanelLogLoad', - value : field.getValue() - }); - } - } - }, { - xtype : 'fieldset', - checkboxToggle : true, - collapsed : !PhDOE.user.conf.reviewed.toolsPanelDisplay, - title : _('Start with the panel open'), - listeners : { - collapse : function() - { - new ui.task.UpdateConfTask({ - module : 'reviewed', - itemName : 'toolsPanelDisplay', - value : false - }); - }, - expand : function() - { - new ui.task.UpdateConfTask({ - module : 'reviewed', - itemName : 'toolsPanelDisplay', - value : true - }); - } - }, - items : [{ - xtype : 'spinnerfield', - width : 60, - name : 'reviewed.toolsPanelWidth', - module : 'reviewed', - itemName : 'toolsPanelWidth', - value : PhDOE.user.conf.reviewed.toolsPanelWidth || 375, - fieldLabel : _('Panel width'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }] - }] - }] - }] - }); - ui.cmp._EditorConf.card5.superclass.initComponent.call(this); - } -}); - -// EditorConf card6 - Module "All files" Config -ui.cmp._EditorConf.card6 = Ext.extend(Ext.TabPanel, -{ - id : 'conf-card-6', - autoScroll : true, - activeTab : 0, - defaults : { - bodyStyle : 'padding: 5px;', - autoHeight : true, - autoScroll : true - }, - - initComponent : function() - { - Ext.apply(this, - { - items : [{ - title : _('User Interface'), - iconCls : 'iconUI', - items : [{ - xtype : 'fieldset', - title : _('Tools'), - iconCls : 'iconConf', - defaults : { hideLabel: true }, - defaultType : 'checkbox', - items : [{ - name : 'allFiles.toolsPanelLogLoad', - checked : PhDOE.user.conf.allFiles.toolsPanelLogLoad, - boxLabel : _('Automatically load the log when displaying the file'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'allFiles', - itemName : 'toolsPanelLogLoad', - value : field.getValue() - }); - } - } - }, { - name : 'allFiles.toolsPanelEntitiesLoad', - checked : PhDOE.user.conf.allFiles.toolsPanelEntitiesLoad, - boxLabel : _('Automatically load entities data when displaying the file'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'allFiles', - itemName : 'toolsPanelEntitiesLoad', - value : field.getValue() - }); - } - } - },{ - name : 'allFiles.toolsPanelAcronymsLoad', - checked : PhDOE.user.conf.allFiles.toolsPanelAcronymsLoad, - boxLabel : _('Automatically load acronyms data when displaying the file'), - listeners : { - check : function(field) - { - new ui.task.UpdateConfTask({ - module : 'allFiles', - itemName : 'toolsPanelAcronymsLoad', - value : field.getValue() - }); - } - } - }, { - xtype : 'fieldset', - checkboxToggle : true, - collapsed : !PhDOE.user.conf.allFiles.toolsPanelDisplay, - title : _('Start with the panel open'), - listeners : { - collapse : function() - { - new ui.task.UpdateConfTask({ - module : 'allFiles', - itemName : 'toolsPanelDisplay', - value : false - }); - }, - expand : function() - { - new ui.task.UpdateConfTask({ - module : 'allFiles', - itemName : 'toolsPanelDisplay', - value : true - }); - } - }, - items: [{ - xtype : 'spinnerfield', - width : 60, - name : 'allFiles.toolsPanelWidth', - module : 'allFiles', - itemName : 'toolsPanelWidth', - value : PhDOE.user.conf.allFiles.toolsPanelWidth || 375, - fieldLabel : _('Panel width'), - minValue : 0, - maxValue : 10000, - accelerate : true, - enableKeyEvents : true, - listeners : { - keyup : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - }, - spin : function() - { - ui.cmp._EditorConf.CommitChange.delay(1000, null, this); - } - } - }] - }] - }] - }] - }); - ui.cmp._EditorConf.card6.superclass.initComponent.call(this); - } -}); - -//------------------------------------------------------------------------------ -// EditorConf Win -ui.cmp.EditorConf = Ext.extend(Ext.Window, -{ - id : 'win-conf', - layout : 'border', - width : 700, - height : 470, - iconCls : 'iconConf', - title : _('Configuration'), - modal : true, - plain : true, - bodyBorder : false, - closeAction : 'hide', - buttons : [{ - text : _('Close'), - handler: function() - { - Ext.getCmp('win-conf').hide(); - } - }], - - listeners : { - show : function() - { - var view = Ext.getCmp('conf-menu-view'); - view.select(view.getNode(0)); - } - }, - - initComponent : function() - { - if (PhDOE.user.lang === 'en') { - ui.cmp._EditorConf.menuStore.loadData(ui.cmp._EditorConf.menuDefEn); - } else { - ui.cmp._EditorConf.menuStore.loadData(ui.cmp._EditorConf.menuDefNonEn); - } - - Ext.apply(this, - { - items : [{ - id : 'confMenu', - region : 'west', - border : false, - width : 190, - autoScroll : true, - items : [new ui.cmp._EditorConf.viewMenu()] - }, { - id : 'confCard', - region : 'center', - border : false, - layout : 'card', - width : 375, - frame : true, - activeItem : 0, - - bbar : new Ext.ux.StatusBar({ - defaultText : _('All changes take effect immediately'), - defaultIconCls : 'confStatusBar' - }), - - items : [ - new ui.cmp._EditorConf.card1(), - new ui.cmp._EditorConf.card2(), - new ui.cmp._EditorConf.card3(), - new ui.cmp._EditorConf.card4(), - new ui.cmp._EditorConf.card5(), - new ui.cmp._EditorConf.card6() - ] - }] - }); - ui.cmp.EditorConf.superclass.initComponent.call(this); - } -}); +Ext.namespace('ui','ui.cmp','ui.cmp._EditorConf','ui.cmp._EditorCmd2Conf'); + +//------------------------------------------------------------------------------ +// EditorConf Win internals + +// EditorConf Win-Menu template +ui.cmp._EditorConf.tplMenu = new Ext.XTemplate( + '', + '', + '' +); +ui.cmp._EditorConf.tplMenu.compile(); + +// EditorConf Win-Menu items definition for EN +ui.cmp._EditorConf.menuDefEn = [ + ['1', 'card1', _('Main')], + ['4', 'card4', _('Module "Files with error"')], + ['6', 'card6', _('Module "All files"')] +]; + +// EditorConf Win-Menu items definition for Non-EN +ui.cmp._EditorConf.menuDefNonEn = [ + ['1', 'card1', _('Main')], + ['2', 'card2', _('Module "Files need translate"')], + ['3', 'card3', _('Module "Files need update"')], + ['4', 'card4', _('Module "Files with error"')], + ['5', 'card5', _('Module "Files need reviewed"')], + ['6', 'card6', _('Module "All files"')] +]; + +// EditorConf Win-Menu items store +ui.cmp._EditorConf.menuStore = new Ext.data.SimpleStore({ + id : 0, + fields : [ + { name : 'id'}, + { name : 'card'}, + { name : 'label'} + ] +}); + +// EditorConf Win-Menu view +ui.cmp._EditorConf.viewMenu = Ext.extend(Ext.DataView, +{ + id : 'conf-menu-view', + tpl : ui.cmp._EditorConf.tplMenu, + singleSelect : true, + overClass : 'x-view-over', + itemSelector : 'div.menu-wrap', + store : ui.cmp._EditorConf.menuStore, + listeners : { + selectionchange : function(view) + { + var r = view.getSelectedRecords(); + Ext.getCmp('confCard').layout.setActiveItem('conf-card-' + r[0].data.id); + } + } +}); + +// CodeMirror2 Theme datastore +ui.cmp._EditorCmd2Conf.themeStore = new Ext.data.SimpleStore({ + fields : ['themeFile', { + name : 'themeName', + type : 'string' + }], + data : [ + [false, _('No theme')], + ['default', _('Default theme')], + ['cobalt', _('Cobalt')], + ['eclipse', _('Eclipse')], + ['elegant', _('Elegant')], + ['monokai', _('Monokai')], + ['neat', _('Neat')], + ['night', _('Night')], + ['rubyblue', _('RubyBlue')] + ] +}); + +// doc-editor Theme datastore +ui.cmp._EditorConf.themeStore = new Ext.data.SimpleStore({ + fields : ['themeFile', { + name : 'themeName', + type : 'string' + }], + data : [ + ['themes/ExtJsThemes/black/css/xtheme-black.css', _('Black')], + ['themes/empty.css', _('Default')], + ['themes/ExtJsThemes/darkgray/css/xtheme-darkgray.css', _('DarkGray')], + ['js/ExtJs/resources/css/xtheme-gray.css', _('Gray')], + ['themes/ExtJsThemes/gray-extend/css/xtheme-gray-extend.css', _('Gray Extend')], + ['themes/ExtJsThemes/indigo/css/xtheme-indigo.css', _('Indigo')], + ['themes/ExtJsThemes/midnight/css/xtheme-midnight.css', _('Midnight')], + ['themes/ExtJsThemes/olive/css/xtheme-olive.css', _('Olive')], + ['themes/ExtJsThemes/purple/css/xtheme-purple.css', _('Purple')], + ['themes/ExtJsThemes/silverCherry/css/xtheme-silverCherry.css', _('SilverCherry')], + ['themes/ExtJsThemes/ubuntu_human/css/xtheme-human.css', _('Ubuntu Human')] + ] +}); + +// doc-editor UI Lang datastore +ui.cmp._EditorConf.uiLangStore = new Ext.data.SimpleStore({ + fields : ['uiLang', { + name : 'uiLangName', + type : 'string' + }], + data : [ + ['default', _('Default language, if available')], + ['en', _('English')], + ['fr', _('French')], + ['ru', _('Russian')], + ['es', _('Spanish')], + ['ar', _('Arabic')] + ] +}); + +ui.cmp._EditorConf.CommitChange = new Ext.util.DelayedTask(function() +{ + new ui.task.UpdateConfTask({ + module : this.module, + itemName : this.itemName, + value : this.getValue() + }); +}); + +// EditorConf card1 - mainApp +ui.cmp._EditorConf.card1 = Ext.extend(Ext.TabPanel, +{ + id : 'conf-card-1', + autoScroll : true, + activeTab : 0, + defaults : { bodyStyle: 'padding: 5px;', autoHeight : true, autoScroll : true }, + + initComponent : function() + { + Ext.apply(this, + { + items : [{ + title : _('User Interface'), + iconCls : 'iconUI', + labelAlign: 'top', + layout:'form', + items : [{ + xtype : 'fieldset', + title : _('Main menu'), + iconCls : 'iconMenu', + items : [{ + xtype : 'spinnerfield', + width : 60, + name : 'PhDOE.user.conf.main.mainMenuWidth', + module : 'main', + itemName : 'mainMenuWidth', + value : PhDOE.user.conf.main.mainMenuWidth || 300, + fieldLabel : _('Main menu width'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + var cmp = Ext.getCmp('main-menu-panel'), + val = this.getValue(); + PhDOE.user.conf.main.mainMenuWidth = val; + cmp.setWidth(val); + cmp.ownerCt.doLayout(); + + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + var cmp = Ext.getCmp('main-menu-panel'), + val = this.getValue(); + PhDOE.user.conf.main.mainMenuWidth = val; + cmp.setWidth(val); + cmp.ownerCt.doLayout(); + + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }] + }, { + xtype : 'fieldset', + iconCls : 'iconThemes', + title : _('Appearance'), + items : [{ + xtype : 'combo', + fieldLabel : _('Choose a theme'), + id : 'conf-combo-theme', + valueField : 'themeFile', + displayField : 'themeName', + triggerAction : 'all', + mode : 'local', + forceSelection : true, + editable : false, + value : PhDOE.user.conf.main.theme, + store : ui.cmp._EditorConf.themeStore, + listeners : { + render : function() + { + Ext.getCmp('conf-combo-theme').store.sort('themeName'); + }, + select : function(c) + { + var hrefTheme = c.getValue(); + + Ext.get('appTheme').dom.href = hrefTheme; + + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'theme', + value : hrefTheme + }); + } + } + },{ + xtype : 'combo', + fieldLabel : _('Force an UI language'), + id : 'conf-combo-ui-lang', + valueField : 'uiLang', + displayField : 'uiLangName', + triggerAction : 'all', + mode : 'local', + forceSelection : true, + editable : false, + value : PhDOE.user.conf.main.uiLang || 'default', + store : ui.cmp._EditorConf.uiLangStore, + listeners : { + select : function(c) + { + var uiLang = c.getValue(); + + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'uiLang', + value : uiLang + }); + } + } + }] + }, { + xtype : 'fieldset', + title : _('On save file'), + iconCls : 'iconSaveFile', + autoHeight : true, + defaults : { hideLabel: true }, + defaultType: 'radio', + items : [{ + autoHeight : true, + name : 'PhDOE.user.conf.main.onSaveFile', + module : 'main', + itemName : 'onSaveFile', + checked : (PhDOE.user.conf.main.onSaveFile === "ask-me") ? true : false, + boxLabel : _('Ask me if I want to check for error before saving the file'), + inputValue : 'ask-me', + listeners : { + check : function(field) + { + if (field.checked) { + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'onSaveFile', + value : field.getRawValue() + }); + } + } + } + }, { + autoHeight : true, + name : 'PhDOE.user.conf.main.onSaveFile', + module : 'main', + itemName : 'onSaveFile', + checked : (PhDOE.user.conf.main.onSaveFile === "always") ? true : false, + boxLabel : _('Always check for error before saving the file'), + inputValue : 'always', + listeners : { + check : function(field) + { + if (field.checked) { + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'onSaveFile', + value : field.getRawValue() + }); + } + } + } + }, { + autoHeight : true, + name : 'PhDOE.user.conf.main.onSaveFile', + module : 'main', + itemName : 'onSaveFile', + checked : (PhDOE.user.conf.main.onSaveFile === "never") ? true : false, + boxLabel : _('Never check for error before saving the file'), + inputValue : 'never', + listeners : { + check : function(field) + { + if (field.checked) { + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'onSaveFile', + value : field.getRawValue() + }); + } + } + } + }] + },{ + xtype : 'checkbox', + name : 'PhDOE.user.conf.main.displayENWork', + checked : PhDOE.user.conf.main.displayENWork, + boxLabel : _('Display EN work in "Work in progress" & "Patches for review" modules'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'displayENWork', + value : field.getValue() + }); + } + } + }] + }, { + title : _('External Data'), + iconCls : 'iconExternalData', + items : [{ + xtype : 'fieldset', + title : _('About mails'), + iconCls : 'iconMailing', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + autoHeight : true, + name : 'PhDOE.user.conf.main.loadMailsAtStartUp', + checked : PhDOE.user.conf.main.loadMailsAtStartUp, + boxLabel : _('Load mail at startUp'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'loadMailsAtStartUp', + value : field.getValue() + }); + } + } + }] + }, { + xtype : 'fieldset', + title : _('About bugs'), + iconCls : 'iconBugs', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + autoHeight : true, + name : 'PhDOE.user.conf.main.loadBugsAtStartUp', + checked : PhDOE.user.conf.main.loadBugsAtStartUp, + boxLabel : _('Load bugs at startUp'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'loadBugsAtStartUp', + value : field.getValue() + }); + } + } + }] + }] + }, { + title : _('Editor'), + iconCls : 'iconEditor', + items : [{ + xtype : 'fieldset', + title : _('Editor theme'), + iconCls : 'iconThemes', + items : [{ + xtype : 'combo', + fieldLabel : _('Choose a theme'), + id : 'conf-combo-cm2-theme', + valueField : 'themeFile', + displayField : 'themeName', + triggerAction : 'all', + mode : 'local', + forceSelection : true, + editable : false, + value : (PhDOE.user.conf.main.editorTheme || 'default'), + store : ui.cmp._EditorCmd2Conf.themeStore, + listeners : { + select : function(c) + { + var themeValue = c.getValue(); + + new ui.task.UpdateConfTask({ + module : 'main', + itemName : 'editorTheme', + value : themeValue + }); + } + } + }] + }] + }] + }); + ui.cmp._EditorConf.card1.superclass.initComponent.call(this); + } +}); + +// EditorConf card2 - Module "Files Need Translate" Config +ui.cmp._EditorConf.card2 = Ext.extend(Ext.TabPanel, +{ + id : 'conf-card-2', + autoScroll : true, + activeTab : 0, + defaults : { + bodyStyle : 'padding: 5px;', + autoHeight : true, + autoScroll : true + }, + + initComponent : function() + { + Ext.apply(this, + { + items : [{ + title : _('Menu'), + iconCls : 'iconMenu', + items : [{ + xtype : 'fieldset', + title : _('Nb files to display'), + iconCls : 'iconFilesToDisplay', + defaults : { hideLabel: true }, + items : [{ + xtype : 'spinnerfield', + width : 60, + name : 'PhDOE.user.conf.newFile.nbDisplay', + module : 'newFile', + itemName : 'nbDisplay', + value : PhDOE.user.conf.newFile.nbDisplay || 0, + boxLabel : _('files to display'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }, { + xtype : 'displayfield', + value : _('0 means no limit'), + style : { fontStyle: 'italic'} + }] + }] + }, { + title : _('User Interface'), + iconCls : 'iconUI', + items : [{ + xtype : 'fieldset', + title : _('ScrollBars'), + iconCls : 'iconScrollBar', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'PhDOE.user.conf.newFile.syncScrollbars', + checked : PhDOE.user.conf.newFile.syncScrollbars, + boxLabel : _('Synchronize scroll bars'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'newFile', + itemName : 'syncScrollbars', + value : field.getValue() + }); + } + } + }] + },{ + xtype : 'fieldset', + title : _('Tools'), + iconCls : 'iconConf', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + xtype : 'fieldset', + checkboxToggle : true, + collapsed : !PhDOE.user.conf.newFile.toolsPanelDisplay, + title : _('Start with the panel open'), + listeners : { + collapse : function() + { + new ui.task.UpdateConfTask({ + module : 'newFile', + itemName : 'toolsPanelDisplay', + value : false + }); + }, + expand : function() + { + new ui.task.UpdateConfTask({ + module : 'newFile', + itemName : 'toolsPanelDisplay', + value : true + }); + } + }, + items : [{ + xtype : 'spinnerfield', + width : 60, + name : 'newFile.toolsPanelWidth', + module : 'newFile', + itemName : 'toolsPanelWidth', + value : PhDOE.user.conf.newFile.toolsPanelWidth || 375, + fieldLabel : _('Panel width'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }] + }] + }, { + xtype : 'fieldset', + title : _('Right panel'), + iconCls : 'iconUI', + defaults : { hideLabel: true }, + defaultType : 'radio', + items : [ + /*{ + name: 'PhDOE.user.conf.newFile.secondPanel', + boxLabel: _('Display the Google Translation Panel'), + inputValue: 'google', + checked: (PhDOE.user.conf.newFile.secondPanel === 'google') ? true : false, + listeners: { + check : function(field) + { + if (field.checked) { + new ui.task.UpdateConfTask({ + module : 'newFile', + itemName : 'secondPanel', + value : field.getRawValue() + }); + } + } + } + },*/ + { + name : 'PhDOE.user.conf.newFile.secondPanel', + boxLabel : _('Display the original file'), + inputValue: 'originalFile', + checked: (PhDOE.user.conf.newFile.secondPanel === 'originalFile') ? true : false, + listeners : { + check : function(field) + { + if (field.checked) { + new ui.task.UpdateConfTask({ + module : 'newFile', + itemName : 'secondPanel', + value : field.getRawValue() + }); + } + } + } + },{ + name : 'PhDOE.user.conf.newFile.secondPanel', + boxLabel : _('Do not display a right panel'), + inputValue: 'none', + checked: (!Ext.isDefined(PhDOE.user.conf.newFile.secondPanel) || PhDOE.user.conf.newFile.secondPanel === 'none') ? true : false, + listeners : { + check : function(field) + { + if (field.checked) { + new ui.task.UpdateConfTask({ + module : 'newFile', + itemName : 'secondPanel', + value : field.getRawValue() + }); + } + } + } + }] + }] + }] + }); + ui.cmp._EditorConf.card2.superclass.initComponent.call(this); + } +}); + +// EditorConf card3 - Module "Files Need Update" Config +ui.cmp._EditorConf.card3 = Ext.extend(Ext.TabPanel, +{ + id : 'conf-card-3', + autoScroll : true, + activeTab : 0, + defaults : { + bodyStyle : 'padding: 5px;', + autoHeight : true, + autoScroll : true + }, + + initComponent : function() + { + Ext.apply(this, + { + items : [{ + title : _('Menu'), + iconCls : 'iconMenu', + items : [{ + xtype : 'fieldset', + title : _('Nb files to display'), + iconCls : 'iconFilesToDisplay', + defaults : { hideLabel: true }, + defaultType : 'spinnerfield', + items : [{ + width : 60, + name : 'PhDOE.user.conf.needUpdate.nbDisplay', + module : 'needUpdate', + itemName : 'nbDisplay', + value : PhDOE.user.conf.needUpdate.nbDisplay || 0, + boxLabel : _('files to display'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + + }, { + xtype : 'displayfield', + value : _('0 means no limit'), + style : { fontStyle: 'italic'} + }] + }] + }, { + title : _('User Interface'), + iconCls : 'iconUI', + items : [{ + xtype : 'fieldset', + title : _('ScrollBars'), + iconCls : 'iconScrollBar', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'needUpdate.syncScrollbars', + checked : PhDOE.user.conf.needUpdate.syncScrollbars, + boxLabel : _('Synchronize scroll bars'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'needUpdate', + itemName : 'syncScrollbars', + value : field.getValue() + }); + } + } + }] + }, { + xtype : 'fieldset', + title : _('Tools'), + iconCls : 'iconConf', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'needUpdate.toolsPanelLogLoad', + checked : PhDOE.user.conf.needUpdate.toolsPanelLogLoad, + boxLabel : _('Automatically load the log when displaying the file'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'needUpdate', + itemName : 'toolsPanelLogLoad', + value : field.getValue() + }); + } + } + }, { + xtype : 'fieldset', + checkboxToggle : true, + collapsed : !PhDOE.user.conf.needUpdate.toolsPanelDisplay, + title : _('Start with the panel open'), + listeners : { + collapse : function() + { + new ui.task.UpdateConfTask({ + module : 'needUpdate', + itemName : 'toolsPanelDisplay', + value : false + }); + }, + expand : function() + { + new ui.task.UpdateConfTask({ + module : 'needUpdate', + itemName : 'toolsPanelDisplay', + value : true + }); + } + }, + items : [{ + xtype : 'spinnerfield', + width : 60, + name : 'needUpdate.toolsPanelWidth', + module : 'needUpdate', + itemName : 'toolsPanelWidth', + value : PhDOE.user.conf.needUpdate.toolsPanelWidth || 375, + fieldLabel : _('Panel width'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }] + }] + }, { + xtype : 'fieldset', + title : _('Diff view'), + iconCls : 'iconDiffView', + defaults : { hideLabel: true }, + defaultType : 'radio', + items : [{ + xtype : 'fieldset', + checkboxToggle : true, + collapsed : !PhDOE.user.conf.needUpdate.diffPanelDisplay, + title : _('Start with the panel open'), + listeners : { + collapse : function() + { + new ui.task.UpdateConfTask({ + module : 'needUpdate', + itemName : 'diffPanelDisplay', + value : false + }); + }, + expand : function() + { + new ui.task.UpdateConfTask({ + module : 'needUpdate', + itemName : 'diffPanelDisplay', + value : true + }); + } + }, + items : [{ + xtype : 'spinnerfield', + width : 60, + name : 'needUpdate.diffPanelHeight', + module : 'needUpdate', + itemName : 'diffPanelHeight', + value : PhDOE.user.conf.needUpdate.diffPanelHeight || 150, + fieldLabel : _('Panel height'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }] + }, { + name : 'needUpdate.diffMethod', + checked : (PhDOE.user.conf.needUpdate.diffMethod === "using-viewvc") ? true : false, + boxLabel : _('Using ViewVc from php web site'), + inputValue : 'using-viewvc', + listeners : { + check : function(field) + { + if (field.checked) { + new ui.task.UpdateConfTask({ + module : 'needUpdate', + itemName : 'diffMethod', + value : field.getRawValue() + }); + } + } + } + }, { + name : 'needUpdate.diffMethod', + checked : (PhDOE.user.conf.needUpdate.diffMethod === "using-exec") ? true : false, + boxLabel : _('Using diff -u command line'), + inputValue : 'using-exec', + listeners : { + check : function(field) + { + if (field.checked) { + new ui.task.UpdateConfTask({ + module : 'needUpdate', + itemName : 'diffMethod', + value : field.getRawValue() + }); + } + } + } + }] + }] + }] + }); + ui.cmp._EditorConf.card3.superclass.initComponent.call(this); + } +}); + +// EditorConf card4 - Module "Files with Error" Config +ui.cmp._EditorConf.card4 = Ext.extend(Ext.TabPanel, +{ + id : 'conf-card-4', + autoScroll : true, + activeTab : 0, + defaults : { + bodyStyle : 'padding: 5px;', + autoHeight : true, + autoScroll : true + }, + + initComponent : function() + { + Ext.apply(this, + { + items : [{ + title : _('Menu'), + iconCls : 'iconMenu', + items : [{ + xtype : 'fieldset', + title : _('Nb files to display'), + iconCls : 'iconFilesToDisplay', + defaults : { hideLabel: true }, + defaultType : 'spinnerfield', + items : [{ + width : 60, + name : 'PhDOE.user.conf.error.nbDisplay', + module : 'error', + itemName : 'nbDisplay', + value : PhDOE.user.conf.error.nbDisplay || 0, + boxLabel : _('files to display'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + + }, { + xtype : 'displayfield', + value : _('0 means no limit'), + style : { fontStyle: 'italic'} + }] + }, { + hidden : ( PhDOE.user.lang === 'en' ), + xtype : 'fieldset', + title : _('Error type'), + iconCls : 'iconFilesError', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'error.skipNbLiteralTag', + checked : PhDOE.user.conf.error.skipNbLiteralTag, + boxLabel : _('Skip nbLiteralTag error'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'skipNbLiteralTag', + value : field.getValue() + }); + } + } + }] + }] + }, { + title : _('User Interface'), + iconCls : 'iconUI', + items : [{ + xtype : 'fieldset', + title : _('ScrollBars'), + iconCls : 'iconScrollBar', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'error.syncScrollbars', + checked : PhDOE.user.conf.error.syncScrollbars, + boxLabel : _('Synchronize scroll bars'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'syncScrollbars', + value : field.getValue() + }); + } + } + }] + }, { + xtype : 'fieldset', + title : _('Tools'), + iconCls : 'iconConf', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'error.toolsPanelLogLoad', + checked : PhDOE.user.conf.error.toolsPanelLogLoad, + boxLabel : _('Automatically load the log when displaying the file'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'toolsPanelLogLoad', + value : field.getValue() + }); + } + } + }, { + name : 'error.toolsPanelEntitiesLoad', + checked : PhDOE.user.conf.error.toolsPanelEntitiesLoad, + boxLabel : _('Automatically load entities data when displaying the file'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'toolsPanelEntitiesLoad', + value : field.getValue() + }); + } + } + }, { + name : 'error.toolsPanelAcronymsLoad', + checked : PhDOE.user.conf.error.toolsPanelAcronymsLoad, + boxLabel : _('Automatically load acronyms data when displaying the file'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'toolsPanelAcronymsLoad', + value : field.getValue() + }); + } + } + }, { + xtype : 'fieldset', + checkboxToggle : true, + collapsed : !PhDOE.user.conf.error.toolsPanelDisplay, + title : _('Start with the panel open'), + listeners : { + collapse : function() + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'toolsPanelDisplay', + value : false + }); + }, + expand : function() + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'toolsPanelDisplay', + value : true + }); + } + }, + items: [{ + xtype : 'spinnerfield', + width : 60, + name : 'error.toolsPanelWidth', + module : 'error', + itemName : 'toolsPanelWidth', + value : PhDOE.user.conf.error.toolsPanelWidth || 375, + fieldLabel : _('Panel width'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }] + }] + }, { + xtype : 'fieldset', + title : _('Error description'), + iconCls : 'iconFilesError', + defaults : { hideLabel: true }, + defaultType : 'radio', + items : [{ + xtype : 'fieldset', + checkboxToggle : true, + collapsed : !PhDOE.user.conf.error.descPanelDisplay, + title : _('Start with the panel open'), + listeners : { + collapse : function() + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'descPanelDisplay', + value : false + }); + }, + expand : function() + { + new ui.task.UpdateConfTask({ + module : 'error', + itemName : 'descPanelDisplay', + value : true + }); + } + }, + items : [{ + xtype : 'spinnerfield', + width : 60, + name : 'error.descPanelHeight', + module : 'error', + itemName : 'descPanelHeight', + value : PhDOE.user.conf.error.descPanelHeight || 150, + fieldLabel : _('Panel height'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }] + }] + }] + }] + }); + ui.cmp._EditorConf.card4.superclass.initComponent.call(this); + } +}); + +// EditorConf card5 - Module "Files need Reviewed" Config +ui.cmp._EditorConf.card5 = Ext.extend(Ext.TabPanel, +{ + id : 'conf-card-5', + autoScroll : true, + activeTab : 0, + defaults : { + bodyStyle : 'padding: 5px;', + autoHeight : true, + autoScroll : true + }, + + initComponent : function() + { + Ext.apply(this, + { + items : [{ + title : _('Menu'), + iconCls : 'iconMenu', + items : [{ + xtype : 'fieldset', + title : _('Nb files to display'), + iconCls : 'iconFilesToDisplay', + defaults : { hideLabel: true }, + defaultType : 'spinnerfield', + items : [{ + width : 60, + name : 'reviewed.nbDisplay', + module : 'reviewed', + itemName : 'nbDisplay', + value : PhDOE.user.conf.reviewed.nbDisplay || 0, + boxLabel : _('files to display'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + + }, { + xtype: 'displayfield', + value: _('0 means no limit'), + style: { fontStyle: 'italic'} + }] + }] + }, { + title : _('User Interface'), + iconCls : 'iconUI', + items : [{ + xtype : 'fieldset', + title : _('ScrollBars'), + iconCls : 'iconScrollBar', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'reviewed.syncScrollbars', + checked : PhDOE.user.conf.reviewed.syncScrollbars, + boxLabel : _('Synchronize scroll bars'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'reviewed', + itemName : 'syncScrollbars', + value : field.getValue() + }); + } + } + }] + }, { + xtype : 'fieldset', + title : _('Tools'), + iconCls : 'iconConf', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'reviewed.toolsPanelLogLoad', + checked : PhDOE.user.conf.reviewed.toolsPanelLogLoad, + boxLabel : _('Automatically load the log when displaying the file'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'reviewed', + itemName : 'toolsPanelLogLoad', + value : field.getValue() + }); + } + } + }, { + xtype : 'fieldset', + checkboxToggle : true, + collapsed : !PhDOE.user.conf.reviewed.toolsPanelDisplay, + title : _('Start with the panel open'), + listeners : { + collapse : function() + { + new ui.task.UpdateConfTask({ + module : 'reviewed', + itemName : 'toolsPanelDisplay', + value : false + }); + }, + expand : function() + { + new ui.task.UpdateConfTask({ + module : 'reviewed', + itemName : 'toolsPanelDisplay', + value : true + }); + } + }, + items : [{ + xtype : 'spinnerfield', + width : 60, + name : 'reviewed.toolsPanelWidth', + module : 'reviewed', + itemName : 'toolsPanelWidth', + value : PhDOE.user.conf.reviewed.toolsPanelWidth || 375, + fieldLabel : _('Panel width'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }] + }] + }] + }] + }); + ui.cmp._EditorConf.card5.superclass.initComponent.call(this); + } +}); + +// EditorConf card6 - Module "All files" Config +ui.cmp._EditorConf.card6 = Ext.extend(Ext.TabPanel, +{ + id : 'conf-card-6', + autoScroll : true, + activeTab : 0, + defaults : { + bodyStyle : 'padding: 5px;', + autoHeight : true, + autoScroll : true + }, + + initComponent : function() + { + Ext.apply(this, + { + items : [{ + title : _('User Interface'), + iconCls : 'iconUI', + items : [{ + xtype : 'fieldset', + title : _('Tools'), + iconCls : 'iconConf', + defaults : { hideLabel: true }, + defaultType : 'checkbox', + items : [{ + name : 'allFiles.toolsPanelLogLoad', + checked : PhDOE.user.conf.allFiles.toolsPanelLogLoad, + boxLabel : _('Automatically load the log when displaying the file'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'allFiles', + itemName : 'toolsPanelLogLoad', + value : field.getValue() + }); + } + } + }, { + name : 'allFiles.toolsPanelEntitiesLoad', + checked : PhDOE.user.conf.allFiles.toolsPanelEntitiesLoad, + boxLabel : _('Automatically load entities data when displaying the file'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'allFiles', + itemName : 'toolsPanelEntitiesLoad', + value : field.getValue() + }); + } + } + },{ + name : 'allFiles.toolsPanelAcronymsLoad', + checked : PhDOE.user.conf.allFiles.toolsPanelAcronymsLoad, + boxLabel : _('Automatically load acronyms data when displaying the file'), + listeners : { + check : function(field) + { + new ui.task.UpdateConfTask({ + module : 'allFiles', + itemName : 'toolsPanelAcronymsLoad', + value : field.getValue() + }); + } + } + }, { + xtype : 'fieldset', + checkboxToggle : true, + collapsed : !PhDOE.user.conf.allFiles.toolsPanelDisplay, + title : _('Start with the panel open'), + listeners : { + collapse : function() + { + new ui.task.UpdateConfTask({ + module : 'allFiles', + itemName : 'toolsPanelDisplay', + value : false + }); + }, + expand : function() + { + new ui.task.UpdateConfTask({ + module : 'allFiles', + itemName : 'toolsPanelDisplay', + value : true + }); + } + }, + items: [{ + xtype : 'spinnerfield', + width : 60, + name : 'allFiles.toolsPanelWidth', + module : 'allFiles', + itemName : 'toolsPanelWidth', + value : PhDOE.user.conf.allFiles.toolsPanelWidth || 375, + fieldLabel : _('Panel width'), + minValue : 0, + maxValue : 10000, + accelerate : true, + enableKeyEvents : true, + listeners : { + keyup : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + }, + spin : function() + { + ui.cmp._EditorConf.CommitChange.delay(1000, null, this); + } + } + }] + }] + }] + }] + }); + ui.cmp._EditorConf.card6.superclass.initComponent.call(this); + } +}); + +//------------------------------------------------------------------------------ +// EditorConf Win +ui.cmp.EditorConf = Ext.extend(Ext.Window, +{ + id : 'win-conf', + layout : 'border', + width : 700, + height : 470, + iconCls : 'iconConf', + title : _('Configuration'), + modal : true, + plain : true, + bodyBorder : false, + closeAction : 'hide', + buttons : [{ + text : _('Close'), + handler: function() + { + Ext.getCmp('win-conf').hide(); + } + }], + + listeners : { + show : function() + { + var view = Ext.getCmp('conf-menu-view'); + view.select(view.getNode(0)); + } + }, + + initComponent : function() + { + if (PhDOE.user.lang === 'en') { + ui.cmp._EditorConf.menuStore.loadData(ui.cmp._EditorConf.menuDefEn); + } else { + ui.cmp._EditorConf.menuStore.loadData(ui.cmp._EditorConf.menuDefNonEn); + } + + Ext.apply(this, + { + items : [{ + id : 'confMenu', + region : 'west', + border : false, + width : 190, + autoScroll : true, + items : [new ui.cmp._EditorConf.viewMenu()] + }, { + id : 'confCard', + region : 'center', + border : false, + layout : 'card', + width : 375, + frame : true, + activeItem : 0, + + bbar : new Ext.ux.StatusBar({ + defaultText : _('All changes take effect immediately'), + defaultIconCls : 'confStatusBar' + }), + + items : [ + new ui.cmp._EditorConf.card1(), + new ui.cmp._EditorConf.card2(), + new ui.cmp._EditorConf.card3(), + new ui.cmp._EditorConf.card4(), + new ui.cmp._EditorConf.card5(), + new ui.cmp._EditorConf.card6() + ] + }] + }); + ui.cmp.EditorConf.superclass.initComponent.call(this); + } +}); diff --git a/js/ux/codemirror2/mode/verilog/verilog.js b/js/ux/codemirror2/mode/verilog/verilog.js index 736d16ad..65a6cf71 100644 --- a/js/ux/codemirror2/mode/verilog/verilog.js +++ b/js/ux/codemirror2/mode/verilog/verilog.js @@ -1,194 +1,194 @@ -CodeMirror.defineMode("verilog", function(config, parserConfig) { - var indentUnit = config.indentUnit, - keywords = parserConfig.keywords || {}, - blockKeywords = parserConfig.blockKeywords || {}, - atoms = parserConfig.atoms || {}, - hooks = parserConfig.hooks || {}, - multiLineStrings = parserConfig.multiLineStrings; - var isOperatorChar = /[&|~>-1) { - this.pos++; - } - Ext.ux.NotificationMgr.positions.push(this.pos); - this.setSize(200,100); - this.el.alignTo(document, "br-br", [ -20, -20-((this.getSize().height+10)*this.pos) ]); - this.el.slideIn('b', { - duration: 1, - callback: this.afterShow, - scope: this - }); - }, - animHide: function(){ - Ext.ux.NotificationMgr.positions.remove(this.pos); - this.el.shadow.hide(); - this.el.ghost("b", { - duration: 1, - remove: false, - callback : function () { - Ext.ux.NotificationMgr.positions.remove(this.pos); - this.destroy(); - }.createDelegate(this) - - }); - }, - - focus: Ext.emptyFn - -}); +/** + * Ext.ux.ToastWindow + * + * @author Edouard Fattal + * @date March 14, 2008 + * + * @class Ext.ux.ToastWindow + * @extends Ext.Window + */ + +Ext.namespace("Ext.ux"); + + +Ext.ux.NotificationMgr = { + positions: [] +}; + +Ext.ux.Notification = Ext.extend(Ext.Window, { + initComponent: function(){ + Ext.apply(this, { + iconCls: this.iconCls || 'x-icon-information', + cls: 'x-notification', + width: 250, + autoHeight: true, + draggable: false, + bodyStyle: 'text-align:center; padding: 10px;' + }); + if(this.autoDestroy) { + this.task = new Ext.util.DelayedTask(this.close, this); + } else { + this.closable = true; + } + Ext.ux.Notification.superclass.initComponent.call(this); + }, + setMessage: function(msg){ + this.body.update(msg); + }, + setTitle: function(title, iconCls){ + Ext.ux.Notification.superclass.setTitle.call(this, title, iconCls||this.iconCls); + }, + onRender:function(ct, position) { + Ext.ux.Notification.superclass.onRender.call(this, ct, position); + }, + onDestroy: function(){ + Ext.ux.NotificationMgr.positions.remove(this.pos); + Ext.ux.Notification.superclass.onDestroy.call(this); + }, + cancelHiding: function(){ + this.addClass('fixed'); + if(this.autoDestroy) { + this.task.cancel(); + } + }, + afterShow: function(){ + Ext.ux.Notification.superclass.afterShow.call(this); + Ext.fly(this.body.dom).on('click', this.cancelHiding, this); + if(this.autoDestroy) { + this.task.delay(this.hideDelay || 5000); + } + }, + animShow: function(){ + this.pos = 0; + while(Ext.ux.NotificationMgr.positions.indexOf(this.pos)>-1) { + this.pos++; + } + Ext.ux.NotificationMgr.positions.push(this.pos); + this.setSize(200,100); + this.el.alignTo(document, "br-br", [ -20, -20-((this.getSize().height+10)*this.pos) ]); + this.el.slideIn('b', { + duration: 1, + callback: this.afterShow, + scope: this + }); + }, + animHide: function(){ + Ext.ux.NotificationMgr.positions.remove(this.pos); + this.el.shadow.hide(); + this.el.ghost("b", { + duration: 1, + remove: false, + callback : function () { + Ext.ux.NotificationMgr.positions.remove(this.pos); + this.destroy(); + }.createDelegate(this) + + }); + }, + + focus: Ext.emptyFn + +}); diff --git a/js/ux/others/main_specific/Ext.ux.SlidingTabPanel.js b/js/ux/others/main_specific/Ext.ux.SlidingTabPanel.js index 5a1fc539..7b922fd7 100644 --- a/js/ux/others/main_specific/Ext.ux.SlidingTabPanel.js +++ b/js/ux/others/main_specific/Ext.ux.SlidingTabPanel.js @@ -1,209 +1,209 @@ -/* - * By Jake Knerr - Copyright 2010 - supersonicecho@gmail.com - * - * Version 1.0 - * - * LICENSE - * GPL v3 - * - */ - -Ext.ux.SlidingTabPanel = Ext.extend(Ext.TabPanel, { - - initTab: function(item, index){ - Ext.ux.SlidingTabPanel.superclass.initTab.call(this, item, index); - - this.addEvents({ - startDrag : true, - endDrag : true - }); - - var p = this.getTemplateArgs(item); - if(!this.slidingTabsID) this.slidingTabsID = Ext.id(); // Create a unique ID for this tabpanel - new Ext.ux.DDSlidingTab(p, this.slidingTabsID, { - tabpanel:this // Pass a reference to the tabpanel for each dragObject - }); - } - -}); - -Ext.ux.DDSlidingTab = Ext.extend(Ext.dd.DDProxy, { - - // Constructor - constructor: function() { - Ext.ux.DDSlidingTab.superclass.constructor.apply(this, arguments); - this.setYConstraint(0,0,0); // Lock the proxy to its initial Y coordinate - - // Create a convenient reference to the tab's tabpanel - this.tabpanel = this.config.tabpanel; - - // Set the slide duration - this.slideDuration = this.tabpanel.slideDuration; - if(!this.slideDuration) this.slideDuration = .1; - } - - // Pseudo Private Methods - ,handleMouseDown: function(e, oDD){ - if(this.primaryButtonOnly && e.button != 0) return; - if(this.isLocked()) return; - this.DDM.refreshCache(this.groups); - var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e)); - if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) { - } else { - if (this.clickValidator(e)) { - this.setStartPosition(); // Set the initial element position - this.b4MouseDown(e); - this.onMouseDown(e); - this.DDM.handleMouseDown(e, this); - // this.DDM.stopEvent(e); // Must remove this event swallower for the tabpanel to work - } - } - } - ,startDrag: function(x, y) { - - // Fire the startDrag event - this.tabpanel.fireEvent('startDrag', this.tabpanel, this.tabpanel.getActiveTab()); - - Ext.dd.DDM.useCache = false; // Disable caching of element location - Ext.dd.DDM.mode = 1; // Point mode - - this.proxyWrapper = Ext.get(this.getDragEl()); // Grab a reference to the proxy element we are creating - this.proxyWrapper.update(); // Clear out the proxy's nodes - this.proxyWrapper.applyStyles('z-index:1001;border:0 none;'); - this.proxyWrapper.addClass('tab-proxy'); - - // Use 2 nested divs to mimic the default tab styling - // You may need to customize the proxy to get it to look like your custom tabpanel if you use a bunch of custom css classes and styles - this.stripWrap = this.proxyWrapper.insertHtml('afterBegin', '
', true); - this.dragEl = this.stripWrap.insertHtml('afterBegin','
', true); - - this.tab = Ext.get(this.getEl()); // Grab a reference to the tab being dragged - this.tab.applyStyles('visibility:hidden;'); // Hide the tab being dragged - - // Insert the html and css classes for the dragged tab into the proxy - this.dragEl.insertHtml('afterBegin', this.tab.dom.innerHTML, false); - this.dragEl.dom.className = this.tab.dom.className; - - // Constrain the proxy drag in the X coordinate to the tabpanel - var panelWidth = this.tabpanel.el.getWidth(); - var panelX = this.tabpanel.el.getX(); - var tabX = this.tab.getX(); - var tabWidth = this.tab.getWidth(); - var left = tabX - panelX; - var right = panelX + panelWidth - tabX - tabWidth; - this.resetConstraints(); - this.setXConstraint(left, right); - } - ,onDragOver: function(e, targetArr) { - e.stopEvent(); - - // Grab the tab you have dragged the proxy over - var target = Ext.get(targetArr[0].id); - var targetWidth = target.getWidth(); - var targetX = target.getX(); - var targetMiddle = targetX + (targetWidth / 2); - var elX = this.tab.getX(); - var dragX = this.proxyWrapper.getX(); - var dragW = this.proxyWrapper.getWidth(); - if(dragX < targetX && ((dragX + dragW) > targetMiddle) ) { - if(target.next() != this.tab) { - target.applyStyles('visibility:hidden;'); - this.tab.insertAfter(target); - this.targetProxy = this.createSliderProxy(targetX, target); - if(!this.targetProxy.hasActiveFx()) this.animateSliderProxy(target, this.targetProxy, elX); - } - } - if(dragX > targetX && (dragX < targetMiddle) ) { - if(this.tab.next() != target) { - target.applyStyles('visibility:hidden;'); - this.tab.insertBefore(target); - this.targetProxy = this.createSliderProxy(targetX, target); - if(!this.targetProxy.hasActiveFx()) this.animateSliderProxy(target, this.targetProxy, elX); - } - } - } - ,animateSliderProxy: function(target, targetProxy, elX){ - targetProxy.shift({ - x: elX - ,easing: 'easeOut' - ,duration: this.slideDuration - ,callback: function() { - targetProxy.remove(); - target.applyStyles('visibility:visible;'); - } - ,scope:this - }); - } - ,createSliderProxy: function(targetX, target) { - var sliderWrapperEl = Ext.getBody().insertHtml('afterBegin', '
', true); - sliderWrapperEl.stripWrapper = sliderWrapperEl.insertHtml('afterBegin', '
', true); - sliderWrapperEl.dragEl = sliderWrapperEl.stripWrapper.insertHtml('afterBegin', '
', true); - sliderWrapperEl.dragEl.update(target.dom.innerHTML); - sliderWrapperEl.dragEl.dom.className = target.dom.className; - var h = parseInt(target.getTop(false)); - sliderWrapperEl.setTop(h) - return sliderWrapperEl; - } - ,onDragDrop: function(e, targetId) { - e.stopEvent(); - } - ,endDrag: function(e){ - var elX = this.tab.getX(); - this.proxyWrapper.applyStyles('visibility:visible;'); - - // Animate the dragProxy to the proper position - this.proxyWrapper.shift({ - x: elX - ,easing: 'easeOut' - ,duration: this.slideDuration - ,callback: function() { - this.proxyWrapper.applyStyles('visibility:hidden;'); - this.tab.applyStyles('visibility:visible;'); - - // Cleanup - this.stripWrap.remove(); - this.dragEl.remove(); - if(!this.targetProxy) return; - this.targetProxy.stripWrapper.remove(); - this.targetProxy.dragEl.remove(); - } - ,scope:this - }); - - Ext.dd.DDM.useCache = true; - - this.reorderTab(); - - // Fire the startDrag event - this.tabpanel.fireEvent('endDrag', this.tabpanel, this.tabpanel.getActiveTab()); - - }, - reorderTab: function() { - - var tabsEl = this.tabpanel.header.child('ul').dom.children, - tabsId = [], - tabsOrigin = []; - - for ( var i=0; i < tabsEl.length; i++ ) { - if( tabsEl[i].id.substr(0, this.tabpanel.id.length) == this.tabpanel.id ) { - tabsId.push( tabsEl[i].id.substr((this.tabpanel.id.length+2), tabsEl[i].id.length ) ); - } - } - - // Now, tabsId is the real list ordered of the tab's id - // We put this order into parent element - - // We get the original reference of this tabs - for( var i=0; i < this.tabpanel.items.items.length; i++ ) { - tabsOrigin[this.tabpanel.items.items[i].id] = this.tabpanel.items.items[i]; - } - - for( var i=0; i < tabsId.length; i++ ) { - // the keys - this.tabpanel.items.keys[i] = tabsId[i]; - // the elements - this.tabpanel.items.items[i] = tabsOrigin[tabsId[i]]; - } - - } +/* + * By Jake Knerr - Copyright 2010 - supersonicecho@gmail.com + * + * Version 1.0 + * + * LICENSE + * GPL v3 + * + */ + +Ext.ux.SlidingTabPanel = Ext.extend(Ext.TabPanel, { + + initTab: function(item, index){ + Ext.ux.SlidingTabPanel.superclass.initTab.call(this, item, index); + + this.addEvents({ + startDrag : true, + endDrag : true + }); + + var p = this.getTemplateArgs(item); + if(!this.slidingTabsID) this.slidingTabsID = Ext.id(); // Create a unique ID for this tabpanel + new Ext.ux.DDSlidingTab(p, this.slidingTabsID, { + tabpanel:this // Pass a reference to the tabpanel for each dragObject + }); + } + +}); + +Ext.ux.DDSlidingTab = Ext.extend(Ext.dd.DDProxy, { + + // Constructor + constructor: function() { + Ext.ux.DDSlidingTab.superclass.constructor.apply(this, arguments); + this.setYConstraint(0,0,0); // Lock the proxy to its initial Y coordinate + + // Create a convenient reference to the tab's tabpanel + this.tabpanel = this.config.tabpanel; + + // Set the slide duration + this.slideDuration = this.tabpanel.slideDuration; + if(!this.slideDuration) this.slideDuration = .1; + } + + // Pseudo Private Methods + ,handleMouseDown: function(e, oDD){ + if(this.primaryButtonOnly && e.button != 0) return; + if(this.isLocked()) return; + this.DDM.refreshCache(this.groups); + var pt = new Ext.lib.Point(Ext.lib.Event.getPageX(e), Ext.lib.Event.getPageY(e)); + if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) { + } else { + if (this.clickValidator(e)) { + this.setStartPosition(); // Set the initial element position + this.b4MouseDown(e); + this.onMouseDown(e); + this.DDM.handleMouseDown(e, this); + // this.DDM.stopEvent(e); // Must remove this event swallower for the tabpanel to work + } + } + } + ,startDrag: function(x, y) { + + // Fire the startDrag event + this.tabpanel.fireEvent('startDrag', this.tabpanel, this.tabpanel.getActiveTab()); + + Ext.dd.DDM.useCache = false; // Disable caching of element location + Ext.dd.DDM.mode = 1; // Point mode + + this.proxyWrapper = Ext.get(this.getDragEl()); // Grab a reference to the proxy element we are creating + this.proxyWrapper.update(); // Clear out the proxy's nodes + this.proxyWrapper.applyStyles('z-index:1001;border:0 none;'); + this.proxyWrapper.addClass('tab-proxy'); + + // Use 2 nested divs to mimic the default tab styling + // You may need to customize the proxy to get it to look like your custom tabpanel if you use a bunch of custom css classes and styles + this.stripWrap = this.proxyWrapper.insertHtml('afterBegin', '
', true); + this.dragEl = this.stripWrap.insertHtml('afterBegin','
', true); + + this.tab = Ext.get(this.getEl()); // Grab a reference to the tab being dragged + this.tab.applyStyles('visibility:hidden;'); // Hide the tab being dragged + + // Insert the html and css classes for the dragged tab into the proxy + this.dragEl.insertHtml('afterBegin', this.tab.dom.innerHTML, false); + this.dragEl.dom.className = this.tab.dom.className; + + // Constrain the proxy drag in the X coordinate to the tabpanel + var panelWidth = this.tabpanel.el.getWidth(); + var panelX = this.tabpanel.el.getX(); + var tabX = this.tab.getX(); + var tabWidth = this.tab.getWidth(); + var left = tabX - panelX; + var right = panelX + panelWidth - tabX - tabWidth; + this.resetConstraints(); + this.setXConstraint(left, right); + } + ,onDragOver: function(e, targetArr) { + e.stopEvent(); + + // Grab the tab you have dragged the proxy over + var target = Ext.get(targetArr[0].id); + var targetWidth = target.getWidth(); + var targetX = target.getX(); + var targetMiddle = targetX + (targetWidth / 2); + var elX = this.tab.getX(); + var dragX = this.proxyWrapper.getX(); + var dragW = this.proxyWrapper.getWidth(); + if(dragX < targetX && ((dragX + dragW) > targetMiddle) ) { + if(target.next() != this.tab) { + target.applyStyles('visibility:hidden;'); + this.tab.insertAfter(target); + this.targetProxy = this.createSliderProxy(targetX, target); + if(!this.targetProxy.hasActiveFx()) this.animateSliderProxy(target, this.targetProxy, elX); + } + } + if(dragX > targetX && (dragX < targetMiddle) ) { + if(this.tab.next() != target) { + target.applyStyles('visibility:hidden;'); + this.tab.insertBefore(target); + this.targetProxy = this.createSliderProxy(targetX, target); + if(!this.targetProxy.hasActiveFx()) this.animateSliderProxy(target, this.targetProxy, elX); + } + } + } + ,animateSliderProxy: function(target, targetProxy, elX){ + targetProxy.shift({ + x: elX + ,easing: 'easeOut' + ,duration: this.slideDuration + ,callback: function() { + targetProxy.remove(); + target.applyStyles('visibility:visible;'); + } + ,scope:this + }); + } + ,createSliderProxy: function(targetX, target) { + var sliderWrapperEl = Ext.getBody().insertHtml('afterBegin', '
', true); + sliderWrapperEl.stripWrapper = sliderWrapperEl.insertHtml('afterBegin', '
', true); + sliderWrapperEl.dragEl = sliderWrapperEl.stripWrapper.insertHtml('afterBegin', '
', true); + sliderWrapperEl.dragEl.update(target.dom.innerHTML); + sliderWrapperEl.dragEl.dom.className = target.dom.className; + var h = parseInt(target.getTop(false)); + sliderWrapperEl.setTop(h) + return sliderWrapperEl; + } + ,onDragDrop: function(e, targetId) { + e.stopEvent(); + } + ,endDrag: function(e){ + var elX = this.tab.getX(); + this.proxyWrapper.applyStyles('visibility:visible;'); + + // Animate the dragProxy to the proper position + this.proxyWrapper.shift({ + x: elX + ,easing: 'easeOut' + ,duration: this.slideDuration + ,callback: function() { + this.proxyWrapper.applyStyles('visibility:hidden;'); + this.tab.applyStyles('visibility:visible;'); + + // Cleanup + this.stripWrap.remove(); + this.dragEl.remove(); + if(!this.targetProxy) return; + this.targetProxy.stripWrapper.remove(); + this.targetProxy.dragEl.remove(); + } + ,scope:this + }); + + Ext.dd.DDM.useCache = true; + + this.reorderTab(); + + // Fire the startDrag event + this.tabpanel.fireEvent('endDrag', this.tabpanel, this.tabpanel.getActiveTab()); + + }, + reorderTab: function() { + + var tabsEl = this.tabpanel.header.child('ul').dom.children, + tabsId = [], + tabsOrigin = []; + + for ( var i=0; i < tabsEl.length; i++ ) { + if( tabsEl[i].id.substr(0, this.tabpanel.id.length) == this.tabpanel.id ) { + tabsId.push( tabsEl[i].id.substr((this.tabpanel.id.length+2), tabsEl[i].id.length ) ); + } + } + + // Now, tabsId is the real list ordered of the tab's id + // We put this order into parent element + + // We get the original reference of this tabs + for( var i=0; i < this.tabpanel.items.items.length; i++ ) { + tabsOrigin[this.tabpanel.items.items[i].id] = this.tabpanel.items.items[i]; + } + + for( var i=0; i < tabsId.length; i++ ) { + // the keys + this.tabpanel.items.keys[i] = tabsId[i]; + // the elements + this.tabpanel.items.items[i] = tabsOrigin[tabsId[i]]; + } + + } }); \ No newline at end of file diff --git a/js/ux/others/main_specific/Ext.ux.grid.GridSummary.js b/js/ux/others/main_specific/Ext.ux.grid.GridSummary.js index 08f9d4ac..38450300 100755 --- a/js/ux/others/main_specific/Ext.ux.grid.GridSummary.js +++ b/js/ux/others/main_specific/Ext.ux.grid.GridSummary.js @@ -1,227 +1,227 @@ -Ext.ns('Ext.ux.grid'); - -Ext.ux.grid.GridSummary = function(config) { - Ext.apply(this, config); -}; - -Ext.extend(Ext.ux.grid.GridSummary, Ext.util.Observable, { - init : function(grid) { - this.grid = grid; - this.cm = grid.getColumnModel(); - this.view = grid.getView(); - - var v = this.view; - - // override GridView's onLayout() method - v.onLayout = this.onLayout; - - v.afterMethod('render', this.refreshSummary, this); - v.afterMethod('refresh', this.refreshSummary, this); - v.afterMethod('syncScroll', this.syncSummaryScroll, this); - v.afterMethod('onColumnWidthUpdated', this.doWidth, this); - v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this); - v.afterMethod('onColumnHiddenUpdated', this.doHidden, this); - - // update summary row on store's add/remove/clear/update events - grid.store.on({ - add: this.refreshSummary, - remove: this.refreshSummary, - clear: this.refreshSummary, - update: this.refreshSummary, - scope: this - }); - - if (!this.rowTpl) { - this.rowTpl = new Ext.Template( - '
', - '', - '{cells}', - '
', - '
' - ); - this.rowTpl.disableFormats = true; - } - this.rowTpl.compile(); - - if (!this.cellTpl) { - this.cellTpl = new Ext.Template( - '', - '
{value}
', - "" - ); - this.cellTpl.disableFormats = true; - } - this.cellTpl.compile(); - }, - - calculate : function(rs, cm) { - var data = {}, - cfg = cm.config, - i, cf, cname, j, r, len, jlen; - - for (i = 0, len = cfg.length; i < len; i++) { // loop through all columns in ColumnModel - cf = cfg[i]; // get column's configuration - cname = cf.dataIndex; // get column dataIndex - - // initialise grid summary row data for - // the current column being worked on - data[cname] = 0; - - if (cf.summaryType) { - for (j = 0, jlen = rs.length; j < jlen; j++) { - r = rs[j]; // get a single Record - data[cname] = Ext.ux.grid.GridSummary.Calculations[cf.summaryType](r.get(cname), r, cname, data, j); - } - } - } - - return data; - }, - - onLayout : function(vw, vh) { - if (Ext.type(vh) !== 'number') { // handles grid's height:'auto' config - return; - } - // note: this method is scoped to the GridView - if (!this.grid.getGridEl().hasClass('x-grid-hide-gridsummary')) { - // readjust gridview's height only if grid summary row is visible - this.scroller.setHeight(vh - this.summary.getHeight()); - } - }, - - syncSummaryScroll : function() { - var mb = this.view.scroller.dom; - - this.view.summaryWrap.dom.scrollLeft = mb.scrollLeft; - this.view.summaryWrap.dom.scrollLeft = mb.scrollLeft; // second time for IE (1/2 time first fails, other browsers ignore) - }, - - doWidth : function(col, w, tw) { - var s = this.view.summary.dom; - - s.firstChild.style.width = tw; - s.firstChild.rows[0].childNodes[col].style.width = w; - }, - - doAllWidths : function(ws, tw) { - var s = this.view.summary.dom, - wlen = ws.length, - cells, j; - - s.firstChild.style.width = tw; - cells = s.firstChild.rows[0].childNodes; - - for (j = 0; j < wlen; j++) { - cells[j].style.width = ws[j]; - } - }, - - doHidden : function(col, hidden, tw) { - var s = this.view.summary.dom, - display = hidden ? 'none' : ''; - - s.firstChild.style.width = tw; - s.firstChild.rows[0].childNodes[col].style.display = display; - }, - - renderSummary : function(o, cs, cm) { - cs = cs || this.view.getColumnData(); - var cfg = cm.config, - buf = [], - last = cs.length - 1, - c, cf, p, i, len; - - for (i = 0, len = cs.length; i < len; i++) { - c = cs[i]; - cf = cfg[i]; - p = {}; - - p.id = c.id; - p.style = c.style; - p.css = i === 0 ? 'x-grid3-cell-first ' : (i === last ? 'x-grid3-cell-last ' : ''); - - if (cf.summaryType || cf.summaryRenderer) { - p.value = (cf.summaryRenderer || c.renderer)(o.data[c.name], p, o); - } else { - p.value = ''; - } - if (p.value === undefined || p.value === "") { - p.value = " "; - } - buf[buf.length] = this.cellTpl.apply(p); - } - - return this.rowTpl.apply({ - tstyle: 'width:' + this.view.getTotalWidth() + ';', - cells: buf.join('') - }); - }, - - refreshSummary : function() { - var g = this.grid, ds = g.store, - cs = this.view.getColumnData(), - cm = this.cm, - rs = ds.getRange(), - data = this.calculate(rs, cm), - buf = this.renderSummary({data: data}, cs, cm); - - if (!this.view.summaryWrap) { - this.view.summaryWrap = Ext.DomHelper.insertAfter(this.view.scroller, { - tag: 'div', - cls: 'x-grid3-gridsummary-row-inner' - }, true); - } - this.view.summary = this.view.summaryWrap.update(buf).first(); - }, - - toggleSummary : function(visible) { // true to display summary row - var el = this.grid.getGridEl(); - - if (el) { - if (visible === undefined) { - visible = el.hasClass('x-grid-hide-gridsummary'); - } - el[visible ? 'removeClass' : 'addClass']('x-grid-hide-gridsummary'); - - this.view.layout(); // readjust gridview height - } - }, - - getSummaryNode : function() { - return this.view.summary; - } -}); -Ext.reg('gridsummary', Ext.ux.grid.GridSummary); - -/* - * all Calculation methods are called on each Record in the Store - * with the following 5 parameters: - * - * v - cell value - * record - reference to the current Record - * colName - column name (i.e. the ColumnModel's dataIndex) - * data - the cumulative data for the current column + summaryType up to the current Record - * rowIdx - current row index - */ -Ext.ux.grid.GridSummary.Calculations = { - sum : function(v, record, colName, data, rowIdx) { - return data[colName] + Ext.num(v, 0); - }, - - count : function(v, record, colName, data, rowIdx) { - return rowIdx + 1; - }, - - max : function(v, record, colName, data, rowIdx) { - return Math.max(Ext.num(v, 0), data[colName]); - }, - - min : function(v, record, colName, data, rowIdx) { - return Math.min(Ext.num(v, 0), data[colName]); - }, - - average : function(v, record, colName, data, rowIdx) { - var t = data[colName] + Ext.num(v, 0), count = record.store.getCount(); - return rowIdx === count - 1 ? (t / count) : t; - } +Ext.ns('Ext.ux.grid'); + +Ext.ux.grid.GridSummary = function(config) { + Ext.apply(this, config); +}; + +Ext.extend(Ext.ux.grid.GridSummary, Ext.util.Observable, { + init : function(grid) { + this.grid = grid; + this.cm = grid.getColumnModel(); + this.view = grid.getView(); + + var v = this.view; + + // override GridView's onLayout() method + v.onLayout = this.onLayout; + + v.afterMethod('render', this.refreshSummary, this); + v.afterMethod('refresh', this.refreshSummary, this); + v.afterMethod('syncScroll', this.syncSummaryScroll, this); + v.afterMethod('onColumnWidthUpdated', this.doWidth, this); + v.afterMethod('onAllColumnWidthsUpdated', this.doAllWidths, this); + v.afterMethod('onColumnHiddenUpdated', this.doHidden, this); + + // update summary row on store's add/remove/clear/update events + grid.store.on({ + add: this.refreshSummary, + remove: this.refreshSummary, + clear: this.refreshSummary, + update: this.refreshSummary, + scope: this + }); + + if (!this.rowTpl) { + this.rowTpl = new Ext.Template( + '
', + '', + '{cells}', + '
', + '
' + ); + this.rowTpl.disableFormats = true; + } + this.rowTpl.compile(); + + if (!this.cellTpl) { + this.cellTpl = new Ext.Template( + '', + '
{value}
', + "" + ); + this.cellTpl.disableFormats = true; + } + this.cellTpl.compile(); + }, + + calculate : function(rs, cm) { + var data = {}, + cfg = cm.config, + i, cf, cname, j, r, len, jlen; + + for (i = 0, len = cfg.length; i < len; i++) { // loop through all columns in ColumnModel + cf = cfg[i]; // get column's configuration + cname = cf.dataIndex; // get column dataIndex + + // initialise grid summary row data for + // the current column being worked on + data[cname] = 0; + + if (cf.summaryType) { + for (j = 0, jlen = rs.length; j < jlen; j++) { + r = rs[j]; // get a single Record + data[cname] = Ext.ux.grid.GridSummary.Calculations[cf.summaryType](r.get(cname), r, cname, data, j); + } + } + } + + return data; + }, + + onLayout : function(vw, vh) { + if (Ext.type(vh) !== 'number') { // handles grid's height:'auto' config + return; + } + // note: this method is scoped to the GridView + if (!this.grid.getGridEl().hasClass('x-grid-hide-gridsummary')) { + // readjust gridview's height only if grid summary row is visible + this.scroller.setHeight(vh - this.summary.getHeight()); + } + }, + + syncSummaryScroll : function() { + var mb = this.view.scroller.dom; + + this.view.summaryWrap.dom.scrollLeft = mb.scrollLeft; + this.view.summaryWrap.dom.scrollLeft = mb.scrollLeft; // second time for IE (1/2 time first fails, other browsers ignore) + }, + + doWidth : function(col, w, tw) { + var s = this.view.summary.dom; + + s.firstChild.style.width = tw; + s.firstChild.rows[0].childNodes[col].style.width = w; + }, + + doAllWidths : function(ws, tw) { + var s = this.view.summary.dom, + wlen = ws.length, + cells, j; + + s.firstChild.style.width = tw; + cells = s.firstChild.rows[0].childNodes; + + for (j = 0; j < wlen; j++) { + cells[j].style.width = ws[j]; + } + }, + + doHidden : function(col, hidden, tw) { + var s = this.view.summary.dom, + display = hidden ? 'none' : ''; + + s.firstChild.style.width = tw; + s.firstChild.rows[0].childNodes[col].style.display = display; + }, + + renderSummary : function(o, cs, cm) { + cs = cs || this.view.getColumnData(); + var cfg = cm.config, + buf = [], + last = cs.length - 1, + c, cf, p, i, len; + + for (i = 0, len = cs.length; i < len; i++) { + c = cs[i]; + cf = cfg[i]; + p = {}; + + p.id = c.id; + p.style = c.style; + p.css = i === 0 ? 'x-grid3-cell-first ' : (i === last ? 'x-grid3-cell-last ' : ''); + + if (cf.summaryType || cf.summaryRenderer) { + p.value = (cf.summaryRenderer || c.renderer)(o.data[c.name], p, o); + } else { + p.value = ''; + } + if (p.value === undefined || p.value === "") { + p.value = " "; + } + buf[buf.length] = this.cellTpl.apply(p); + } + + return this.rowTpl.apply({ + tstyle: 'width:' + this.view.getTotalWidth() + ';', + cells: buf.join('') + }); + }, + + refreshSummary : function() { + var g = this.grid, ds = g.store, + cs = this.view.getColumnData(), + cm = this.cm, + rs = ds.getRange(), + data = this.calculate(rs, cm), + buf = this.renderSummary({data: data}, cs, cm); + + if (!this.view.summaryWrap) { + this.view.summaryWrap = Ext.DomHelper.insertAfter(this.view.scroller, { + tag: 'div', + cls: 'x-grid3-gridsummary-row-inner' + }, true); + } + this.view.summary = this.view.summaryWrap.update(buf).first(); + }, + + toggleSummary : function(visible) { // true to display summary row + var el = this.grid.getGridEl(); + + if (el) { + if (visible === undefined) { + visible = el.hasClass('x-grid-hide-gridsummary'); + } + el[visible ? 'removeClass' : 'addClass']('x-grid-hide-gridsummary'); + + this.view.layout(); // readjust gridview height + } + }, + + getSummaryNode : function() { + return this.view.summary; + } +}); +Ext.reg('gridsummary', Ext.ux.grid.GridSummary); + +/* + * all Calculation methods are called on each Record in the Store + * with the following 5 parameters: + * + * v - cell value + * record - reference to the current Record + * colName - column name (i.e. the ColumnModel's dataIndex) + * data - the cumulative data for the current column + summaryType up to the current Record + * rowIdx - current row index + */ +Ext.ux.grid.GridSummary.Calculations = { + sum : function(v, record, colName, data, rowIdx) { + return data[colName] + Ext.num(v, 0); + }, + + count : function(v, record, colName, data, rowIdx) { + return rowIdx + 1; + }, + + max : function(v, record, colName, data, rowIdx) { + return Math.max(Ext.num(v, 0), data[colName]); + }, + + min : function(v, record, colName, data, rowIdx) { + return Math.min(Ext.num(v, 0), data[colName]); + }, + + average : function(v, record, colName, data, rowIdx) { + var t = data[colName] + Ext.num(v, 0), count = record.store.getCount(); + return rowIdx === count - 1 ? (t / count) : t; + } }; \ No newline at end of file diff --git a/php/AccountManager.php b/php/AccountManager.php index f72fe732..ebae9537 100644 --- a/php/AccountManager.php +++ b/php/AccountManager.php @@ -1,721 +1,721 @@ -defaultConf = (object) Array( - 'allFiles' => (object) Array( - 'enableSpellCheck' => false, - 'toolsPanelAcronymsLoad' => false, - 'toolsPanelDisplay' => false, - 'toolsPanelEntitiesLoad' => false, - 'toolsPanelLogLoad' => false, - 'toolsPanelWidth' => 375 - ), - 'error' => (object) Array( - 'descPanelDisplay' => true, - 'descPanelHeight' => 150, - 'enableSpellCheckEn' => false, - 'enableSpellCheckLang' => false, - 'nbDisplay' => 0, - 'skipNbLiteralTag' => true, - 'syncScrollbars' => true, - 'toolsPanelAcronymsLoad' => false, - 'toolsPanelDisplay' => false, - 'toolsPanelEntitiesLoad' => false, - 'toolsPanelLogLoad' => false, - 'toolsPanelWidth' => 375 - ), - 'main' => (object) Array( - 'loadBugsAtStartUp' => false, - 'loadMailsAtStartUp' => false, - 'mainMenuWidth' => 300, - 'onSaveFile' => 'ask-me', - 'theme' => 'themes/empty.css', - 'uiLang' => 'default', - 'portalSortEN'=> '{"col1":["portletLocalMail","portletBugs"],"col2":["portletInfo","portletTranslationsGraph"]}', - 'portalSortLANG'=> '{"col1":["portletSummary","portletTranslator","portletLocalMail","portletBugs"],"col2":["portletInfo","portletTranslationGraph","portletTranslationsGraph"]}', - 'displayENWork'=>true, - 'lineWrapping'=>true, - 'editorTheme'=>'default' - ), - 'needUpdate' => (object) Array( - 'diffMethod' => 'using-exec', - 'diffPanelDisplay' => true, - 'diffPanelHeight' => 150, - 'enableSpellCheckEn' => false, - 'enableSpellCheckLang' => false, - 'nbDisplay' => 0, - 'syncScrollbars' => true, - 'toolsPanelDisplay' => false, - 'toolsPanelLogLoad' => false, - 'toolsPanelWidth' => 375 - ), - 'newFile' => (object) Array( - 'enableSpellCheck' => false, - 'googlePanelDisplay' => false, - 'nbDisplay' => 0, - 'toolsPanelDisplay' => false, - 'toolsPanelWidth' => 375, - 'secondPanel' => 'googleTranslate', // can be 'none', 'googleTranslate' or 'originalFile' - 'syncScrollbars' => true - ), - 'reviewed' => (object) Array( - 'enableSpellCheckEn' => false, - 'enableSpellCheckLang' => false, - 'nbDisplay' => 0, - 'syncScrollbars' => true, - 'toolsPanelDisplay' => false, - 'toolsPanelLogLoad' => false, - 'toolsPanelWidth' => 375 - ) - ); - - $this->appConf = Config::getInstance()->getConf(); - - $this->conn = DBConnection::getInstance(); - } - - /** - * Change the current language - * @param $lang string The new language we want to change to - */ - public function switchLang($lang) { - $_SESSION['lang'] = $lang; - $this->vcsLang = $lang; - } - - /** - * Update the date/time about the lastConnexion for this user, in DB - */ - public function updateLastConnect() - { - $s = 'UPDATE `users` SET `last_connect`=now() WHERE `userID`=%d'; - $params = array($this->userID); - $this->conn->query($s, $params); - } - - /** - * Check if there is an authentificated session or not - * Update the last connexion's date in DB for this user - * - * @return TRUE if there is an authentificated session, FALSE otherwise. - */ - public function isLogged() - { - if (!isset($_SESSION['userID'])) { - return false; - } - $this->userID = $_SESSION['userID']; - $this->vcsLogin = $_SESSION['vcsLogin']; - $this->vcsPasswd = $_SESSION['vcsPasswd']; - $this->vcsLang = $_SESSION['lang']; - $this->project = $_SESSION['project']; - $this->anonymousIdent = $_SESSION['anonymousIdent']; - $this->isAnonymous = $_SESSION['isAnonymous']; - $this->email = $_SESSION['email']; - - $this->authService = ( isset($_SESSION['authService']) ) ? $_SESSION['authService'] : false; - $this->authServiceID = ( isset($_SESSION['authServiceID']) ) ? $_SESSION['authServiceID'] : false; - - ProjectManager::getInstance()->setProject($this->project); - - $this->userConf = isset($_SESSION['userConf']) - ? $_SESSION['userConf'] - : $this->defaultConf; - - $this->updateLastConnect(); - - return true; - } - - /** - * Log into this application. - * - * @param $project The project we want to work on. - * @param $vcsLogin The login use to identify this user into PHP VCS server. - * @param $vcsPasswd The password, in plain text, to identify this user into PHP VCS server. - * @param $email The email for this user. Need to contact him via the application. - * @param $lang The language we want to access. - * @return An associated array. - */ - public function login($project, $vcsLogin, $vcsPasswd, $email, $lang='en', $authService='VCS', $authServiceID = null) - { - // Var to return into ExtJs - $return = array(); - - // We manage the project - if( ProjectManager::getInstance()->setProject($project) ) { - $this->project = strtoupper($project); - } else { - $return['state'] = false; - $return['msg'] = 'Bad project'; - $return['authMethod'] = '-'; - return $return; - } - - $this->authService = $authService; - $this->authServiceID = $authServiceID; - - /* - * VCS AUTH SYSTEM - * - */ - - if( $this->authService == 'VCS' ) { - - /* - * ANONYMOUS VCS - * - */ - - // Anonymous's user can logging into this app by providing this login/pass => anonymous/(empty) ou (empty)/(empty) - // The result is the same. $this->vcsLogin will be "anonymous" and $this->vcsPasswd, (empty) - if( ($vcsLogin == "anonymous" && $vcsPasswd == "") - || ($vcsLogin == "" && $vcsPasswd == "") ) { - - $this->isAnonymous = true; - - // Even if the user provide an empty login, we force it to be 'anonymous' - $vcsLogin = 'anonymous'; - - $this->anonymousIdent = ( isset($_COOKIE['anonymousIdent']) ) ? $_COOKIE['anonymousIdent'] : uniqid('', true); - - setcookie("anonymousIdent", $this->anonymousIdent, time() + 3600*24*365, "/"); // One year ;) - - // Register var - $this->vcsLogin = $vcsLogin; - $this->vcsPasswd = ''; - $this->vcsLang = $lang; - $this->email = $email; - - // Check DB - $s = 'SELECT * FROM `users` WHERE `project` = "%s" AND `authService` = "VCS" AND `vcs_login` = "%s" AND `anonymousIdent` = "%s"'; - $params = array($project, $this->vcsLogin, $this->anonymousIdent); - - $r = $this->conn->query($s, $params); - - - if ($r->num_rows == 1) { - - //This anonymous user exist into DB. We store his configuration into ... - $a = $r->fetch_object(); - - // ... object's property ... - $this->userConf = json_decode($a->conf); - - $this->userID = $a->userID; - - // ... and into the php's session (only specific var) - $_SESSION['userConf'] = $this->userConf; - - // We update the email if this user have decided to change it. - $this->updateEmail(); - - } else { - - // We register this new valid user - $userID = $this->register(); - $this->userID = $userID; - - // Store in session only specific var - $_SESSION['userConf'] = $this->defaultConf; - - } - - // Generic session var for VALID & ANONYMOUS VCS user - $_SESSION['userID'] = $this->userID; - $_SESSION['project'] = $this->project; - $_SESSION['vcsLogin'] = $this->vcsLogin = $this->vcsLogin.' #'.$this->userID; - $_SESSION['vcsPasswd'] = $this->vcsPasswd; - $_SESSION['isAnonymous'] = $this->isAnonymous; - $_SESSION['anonymousIdent'] = $this->anonymousIdent; - $_SESSION['lang'] = $this->vcsLang; - $_SESSION['email'] = $this->email; - $_SESSION['authService'] = $this->authService; - $_SESSION['authServiceID'] = $this->authServiceID; - - // We set up the CSRF token - $_SESSION['csrfToken'] = sha1(uniqid(rand(), true)); - - // Store some user info in cookies: we can use this to pre-fill the - // login page if the user's session expires. - setcookie("loginApp", 'anonymous', time() + 3600*24*365, "/"); // One year ;) - setcookie("email", $this->email, time() + 3600*24*365, "/"); - setcookie("lang", $this->vcsLang, time() + 3600*24*365, "/"); - - - // We construct the return's var for ExtJs - $return['state'] = true; - $return['msg'] = 'Welcome !'; - return $return; - - } - - /* - * VALID VCS USER - * - */ - - - else { - - $this->isAnonymous = false; - $this->anonymousIdent = ''; - - // If this app is installed into Php's server, we use the standad way to verify login/password - if( $_SERVER["SERVER_NAME"] == "doc.php.net" ) { - // We try to authenticate this user to master php server. - $AuthReturn = VCSFactory::getInstance()->masterPhpAuthenticate($vcsLogin, $vcsPasswd); - $return['authMethod'] = 'masterPhp'; - } - - - if( $AuthReturn !== true ) { - $return['state'] = false; - $return['msg'] = $AuthReturn; - return $return; - } else { - - // Check the karma - $karma = VCSFactory::getInstance()->checkKarma($vcsLogin, $lang); - - if( $karma !== true ) { - $return['state'] = false; - $return['msg'] = $karma; - return $return; - } - - // Register var - $this->vcsLogin = $vcsLogin; - $this->vcsPasswd = $vcsPasswd; - $this->vcsLang = $lang; - $this->email = $email; - - // Check DB - $s = 'SELECT * FROM `users` WHERE `project` = "%s" AND `authService` = "VCS" AND `vcs_login` = "%s"'; - $params = array($project, $this->vcsLogin); - - $r = $this->conn->query($s, $params); - - if ($r->num_rows == 1) { - - //This user exist into DB. We store his configuration into ... - $a = $r->fetch_object(); - - // ... object's property ... - $this->userConf = json_decode($a->conf); - - $this->userID = $a->userID; - - // ... and into the php's session (only specific var) - $_SESSION['userConf'] = $this->userConf; - - // We update the email if this user have decided to change it. - $this->updateEmail(); - - } else { - - // We register this new valid user - $userID = $this->register(); - $this->userID = $userID; - - // Store in session only specific var - $_SESSION['userConf'] = $this->defaultConf; - - } - - // Generic session var for VALID & ANONYMOUS VCS user - $_SESSION['userID'] = $this->userID; - $_SESSION['project'] = $this->project; - $_SESSION['vcsLogin'] = $this->vcsLogin; - $_SESSION['vcsPasswd'] = $this->vcsPasswd; - $_SESSION['isAnonymous'] = $this->isAnonymous; - $_SESSION['anonymousIdent'] = $this->anonymousIdent; - $_SESSION['lang'] = $this->vcsLang; - $_SESSION['email'] = $this->email; - $_SESSION['authService'] = $this->authService; - $_SESSION['authServiceID'] = $this->authServiceID; - - // We set up the CSRF token - $_SESSION['csrfToken'] = sha1(uniqid(rand(), true)); - - // Store some user info in cookies: we can use this to pre-fill the - // login page if the user's session expires. - setcookie("loginApp", utf8_encode($this->vcsLogin), time() + 3600*24*365, "/"); // One year ;) - setcookie("email", $this->email, time() + 3600*24*365, "/"); - setcookie("lang", $this->vcsLang, time() + 3600*24*365, "/"); - - - // We construct the return's var for ExtJs - $return['state'] = true; - $return['msg'] = 'Welcome !'; - return $return; - } - - } - - } - - /* - * EXTERNAL AUTH SYSTEM - * - */ - - else if( $this->authService == 'google' || $this->authService == 'facebook' ) { - - $this->isAnonymous = true; - $this->anonymousIdent = $this->authService.'-'.$this->authServiceID; - - // Register var - $this->vcsLogin = $vcsLogin; - $this->vcsPasswd = ''; - $this->vcsLang = $lang; - $this->email = $email; - - // Check DB - $s = 'SELECT * FROM `users` WHERE `project` = "%s" AND `authService` = "%s" AND `authServiceID` = "%s" AND `vcs_login` = "%s" AND `anonymousIdent` = "%s"'; - $params = array($project, $this->authService, $this->authServiceID, $this->vcsLogin, $this->anonymousIdent); - - $r = $this->conn->query($s, $params); - - if ($r->num_rows == 1) { - //This anonymous user exist into DB. We store his configuration into ... - $a = $r->fetch_object(); - - // ... object's property ... - $this->userConf = json_decode($a->conf); - - $this->userID = $a->userID; - - // ... and into the php's session (only specific var) - $_SESSION['userConf'] = $this->userConf; - - // We update the email if this user have decided to change it. - $this->updateEmail(); - - } else { - - // We register this new valid user - $userID = $this->register(); - $this->userID = $userID; - - // Store in session only specific var - $_SESSION['userConf'] = $this->defaultConf; - - } - - // Generic session var for VALID & ANONYMOUS VCS user - $_SESSION['userID'] = $this->userID; - $_SESSION['project'] = $this->project; - $_SESSION['vcsLogin'] = $this->vcsLogin; - $_SESSION['vcsPasswd'] = $this->vcsPasswd; - $_SESSION['isAnonymous'] = $this->isAnonymous; - $_SESSION['anonymousIdent'] = $this->anonymousIdent; - $_SESSION['lang'] = $this->vcsLang; - $_SESSION['email'] = $this->email; - $_SESSION['authService'] = $this->authService; - $_SESSION['authServiceID'] = $this->authServiceID; - - // We set up the CSRF token - $_SESSION['csrfToken'] = sha1(uniqid(rand(), true)); - - // Store some user info in cookies: we can use this to pre-fill the - // login page if the user's session expires. - setcookie("loginApp", utf8_encode($this->vcsLogin), time() + 3600*24*365, "/"); // One year ;) - setcookie("email", $this->email, time() + 3600*24*365, "/"); - setcookie("lang", $this->vcsLang, time() + 3600*24*365, "/"); - - // We construct the return's var for ExtJs - $return['state'] = true; - $return['msg'] = 'Welcome !'; - return $return; - - } else { - $return['state'] = false; - $return['msg'] = 'Bad authService'; - $return['authMethod'] = '-'; - return $return; - } - - } - - /** - * Check if a user is an anonymous or not based only on his name. - * @param string The user name to check - * @return boolean TRUE if the given user is an anonymous, FALSE otherwise. - */ - public function anonymous($userLogin, $anonymousIdent) - { - // A valid user is a user who have a "VCS" authService, without anonymousIdent - $s = 'SELECT authService, anonymousIdent FROM `users` WHERE project="%s" AND vcs_login = "%s" AND anonymousIdent = "%s"'; - - $params = array($this->project, $userLogin, $anonymousIdent); - $r = $this->conn->query($s, $params); - $a = $r->fetch_object(); - - // An anonymous have is #xxx at the end of his login. So, the sql "failed" - if( !is_object($a) ) { - return true; - } - - return ( $a->authService == 'VCS' && $a->anonymousIdent == '' ) ? false : true; - } - - public function isGlobalAdmin() - { - // Anonymous can't be a globalAdmin - if( $this->isAnonymous ) return false; - - $admin = explode(",", $this->appConf[$this->project]['project.globaladmin']); - return ( in_array($this->vcsLogin, $admin) ) ? true : false; - } - - public function isLangAdmin() - { - // Anonymous can't be a langAdmin - if( $this->isAnonymous ) return false; - - if( !isset($this->appConf[$this->project]['project.langadmin.'.$this->vcsLang]) ) { - return false; - } - - $admin = explode(",", $this->appConf[$this->project]['project.langadmin.'.$this->vcsLang]); - return ( in_array($this->vcsLogin, $admin) ) ? true : false; - } - - public function isAdmin($lang=false) - { - if( $this->isAnonymous ) return false; - - // If lang is true, this method must return true if current user is either a global admin, or a lang admin - if( $lang ) { - return ( $this->isGlobalAdmin() || $this->isLangAdmin() ) ? true : false; - } else { - // If lang is false, this method must return true if current user is ONLY a global admin - return ( $this->isGlobalAdmin() ) ? true : false; - } - - return false; - } - - public function updateEmail() - { - $s = 'UPDATE `users` SET `email`="%s" WHERE `userID`=%d'; - $params = array($this->email, $this->userID); - $this->conn->query($s, $params); - } - - public function getVCSUsers() - { - $s = 'SELECT `userID`, `vcs_login`, `anonymousIdent`, `authService` FROM `users` WHERE project="%s" AND vcs_login != "anonymous" ORDER BY authService, vcs_login'; - $params = array($this->project); - $r = $this->conn->query($s, $params); - - $result = array(); - $i=0; - - while( $a = $r->fetch_object() ) { - $result[$i]['userID'] = $a->userID; - $result[$i]['userName'] = $a->vcs_login; - $result[$i]['authService'] = $a->authService; - $i++; - } - return $result; - } - - public function setFileOwner($fileIdDB, $newOwnerID) - { - // Get newUser information - $s = 'SELECT * FROM `users` WHERE `userID` = %d'; - $params = array($newOwnerID); - - $r = $this->conn->query($s, $params); - $userInfo = $r->fetch_object(); - - // We update the file - $s = 'UPDATE `work` SET `user` = "%s", `anonymousIdent` = "%s", `module`="workInProgress", patchID=NULL WHERE `id` = %d'; - $params = array($userInfo->vcs_login, $userInfo->anonymousIdent, $fileIdDB); - - $this->conn->query($s, $params); - } - - /** - * Get user's details - * - * @return An object containing all details for this user - */ - public function getUserDetails($user, $anonymousIdent) - { - $am = AccountManager::getInstance(); - $project = $am->project; - - $s = 'SELECT `userID`, `authService`, `email` FROM `users` WHERE `project` = "%s" AND `vcs_login` = "%s" AND `anonymousIdent` = "%s"'; - $params = array($project, $user, $anonymousIdent); - - $r = $this->conn->query($s, $params); - $nb = $r->num_rows; - - // We have found the user - if( $nb != 0 ) { - $a = $r->fetch_object(); - return $a; - } else { - return false; - } - - } - - - /** - * Get the email for a user - * - * @return The email or false if we haven't found it. - */ - public function getUserEmail($user, $anonymousIdent) - { - $am = AccountManager::getInstance(); - $project = $am->project; - - $s = 'SELECT `email` FROM `users` WHERE `project` = "%s" AND `vcs_login` = "%s" AND `anonymousIdent` = "%s"'; - $params = array($project, $user, $anonymousIdent); - - $r = $this->conn->query($s, $params); - $nb = $r->num_rows; - - // We have found an email - if( $nb != 0 ) { - $a = $r->fetch_object(); - return $a->email; - } else { - return false; - } - - } - - /** - * Register a new valid user on the application. - * - * @return int The database insert id - */ - private function register() - { - $s = 'INSERT INTO `users` (`project`, `authService`, `authServiceID`, `vcs_login`, `email`, `anonymousIdent`, `conf`) VALUES ("%s","%s","%s","%s","%s","%s","%s")'; - $params = array($this->project, $this->authService, $this->authServiceID, $this->vcsLogin, $this->email, $this->anonymousIdent, json_encode($this->defaultConf)); - - $this->conn->query($s, $params); - return $this->conn->insert_id(); - } - - /** - * Update an option in user configuration database - * - * @param $item The name of the option. - * @param $value The value of the option. - */ - public function updateConf($module, $itemName, $value) - { - if( $value == "false" ) { - $value = false; - } - - if( $value == "true" ) { - $value = true; - } - - // @todo determine why this is called when these are empty - if (empty($module) || empty($itemName)) { - return false; - } - - $this->userConf->{$module}->{$itemName} = ( is_numeric($value) ) ? (int) $value : $value; - - // In session - unset($_SESSION['userConf']->{$module}->{$itemName}); - $_SESSION['userConf']->{$module}->{$itemName} = ( is_numeric($value) ) ? (int) $value : $value; - - // In DB - if( $this->isAnonymous ) { - $s = 'UPDATE `users` SET `conf`="%s" WHERE `vcs_login`="anonymous" AND `anonymousIdent`="%s"'; - $params = array(json_encode($this->userConf), $this->anonymousIdent); - } else { - $s = 'UPDATE `users` SET `conf`="%s" WHERE `vcs_login`="%s"'; - $params = array(json_encode($this->userConf), $this->vcsLogin); - } - $this->conn->query($s, $params); - } - - /** - * Erase personal data for the current user. - * Delete all reference from `users` & `commitMessage` DB tables. - */ - public function eraseData() - { - $s = 'DELETE FROM `commitMessage` WHERE `user`="%s"'; - $params = array($this->vcsLogin); - $this->conn->query($s, $params); - - $s = 'DELETE FROM `users` WHERE `userID`=%d'; - $params = array($this->userID); - $this->conn->query($s, $params); - } - - /** - * Send an email - * - * @param $to The Receiver. - * @param $subject The subject of the email. - * @param $msg The content of the email. Don't use HTML here ; only plain text. - * @param $from The email we place into From header. - * @param $fromType Either "user" or "list". Default to user - */ - public function email($to, $subject, $msg, $from='', $fromType='user') - { - if( $fromType == 'user' ) { - $from = $this->vcsLogin."@php.net"; - } - - $headers = 'From: '.$from . "\r\n" . - 'X-Mailer: Php Docbook Online Editor' ."\r\n" . - 'Content-Type: text/plain; charset="utf-8"'."\n"; - - mail($to, stripslashes($subject), stripslashes(trim($msg)), $headers, "-fnoreply@php.net"); - } -} - -?> +defaultConf = (object) Array( + 'allFiles' => (object) Array( + 'enableSpellCheck' => false, + 'toolsPanelAcronymsLoad' => false, + 'toolsPanelDisplay' => false, + 'toolsPanelEntitiesLoad' => false, + 'toolsPanelLogLoad' => false, + 'toolsPanelWidth' => 375 + ), + 'error' => (object) Array( + 'descPanelDisplay' => true, + 'descPanelHeight' => 150, + 'enableSpellCheckEn' => false, + 'enableSpellCheckLang' => false, + 'nbDisplay' => 0, + 'skipNbLiteralTag' => true, + 'syncScrollbars' => true, + 'toolsPanelAcronymsLoad' => false, + 'toolsPanelDisplay' => false, + 'toolsPanelEntitiesLoad' => false, + 'toolsPanelLogLoad' => false, + 'toolsPanelWidth' => 375 + ), + 'main' => (object) Array( + 'loadBugsAtStartUp' => false, + 'loadMailsAtStartUp' => false, + 'mainMenuWidth' => 300, + 'onSaveFile' => 'ask-me', + 'theme' => 'themes/empty.css', + 'uiLang' => 'default', + 'portalSortEN'=> '{"col1":["portletLocalMail","portletBugs"],"col2":["portletInfo","portletTranslationsGraph"]}', + 'portalSortLANG'=> '{"col1":["portletSummary","portletTranslator","portletLocalMail","portletBugs"],"col2":["portletInfo","portletTranslationGraph","portletTranslationsGraph"]}', + 'displayENWork'=>true, + 'lineWrapping'=>true, + 'editorTheme'=>'default' + ), + 'needUpdate' => (object) Array( + 'diffMethod' => 'using-exec', + 'diffPanelDisplay' => true, + 'diffPanelHeight' => 150, + 'enableSpellCheckEn' => false, + 'enableSpellCheckLang' => false, + 'nbDisplay' => 0, + 'syncScrollbars' => true, + 'toolsPanelDisplay' => false, + 'toolsPanelLogLoad' => false, + 'toolsPanelWidth' => 375 + ), + 'newFile' => (object) Array( + 'enableSpellCheck' => false, + 'googlePanelDisplay' => false, + 'nbDisplay' => 0, + 'toolsPanelDisplay' => false, + 'toolsPanelWidth' => 375, + 'secondPanel' => 'googleTranslate', // can be 'none', 'googleTranslate' or 'originalFile' + 'syncScrollbars' => true + ), + 'reviewed' => (object) Array( + 'enableSpellCheckEn' => false, + 'enableSpellCheckLang' => false, + 'nbDisplay' => 0, + 'syncScrollbars' => true, + 'toolsPanelDisplay' => false, + 'toolsPanelLogLoad' => false, + 'toolsPanelWidth' => 375 + ) + ); + + $this->appConf = Config::getInstance()->getConf(); + + $this->conn = DBConnection::getInstance(); + } + + /** + * Change the current language + * @param $lang string The new language we want to change to + */ + public function switchLang($lang) { + $_SESSION['lang'] = $lang; + $this->vcsLang = $lang; + } + + /** + * Update the date/time about the lastConnexion for this user, in DB + */ + public function updateLastConnect() + { + $s = 'UPDATE `users` SET `last_connect`=now() WHERE `userID`=%d'; + $params = array($this->userID); + $this->conn->query($s, $params); + } + + /** + * Check if there is an authentificated session or not + * Update the last connexion's date in DB for this user + * + * @return TRUE if there is an authentificated session, FALSE otherwise. + */ + public function isLogged() + { + if (!isset($_SESSION['userID'])) { + return false; + } + $this->userID = $_SESSION['userID']; + $this->vcsLogin = $_SESSION['vcsLogin']; + $this->vcsPasswd = $_SESSION['vcsPasswd']; + $this->vcsLang = $_SESSION['lang']; + $this->project = $_SESSION['project']; + $this->anonymousIdent = $_SESSION['anonymousIdent']; + $this->isAnonymous = $_SESSION['isAnonymous']; + $this->email = $_SESSION['email']; + + $this->authService = ( isset($_SESSION['authService']) ) ? $_SESSION['authService'] : false; + $this->authServiceID = ( isset($_SESSION['authServiceID']) ) ? $_SESSION['authServiceID'] : false; + + ProjectManager::getInstance()->setProject($this->project); + + $this->userConf = isset($_SESSION['userConf']) + ? $_SESSION['userConf'] + : $this->defaultConf; + + $this->updateLastConnect(); + + return true; + } + + /** + * Log into this application. + * + * @param $project The project we want to work on. + * @param $vcsLogin The login use to identify this user into PHP VCS server. + * @param $vcsPasswd The password, in plain text, to identify this user into PHP VCS server. + * @param $email The email for this user. Need to contact him via the application. + * @param $lang The language we want to access. + * @return An associated array. + */ + public function login($project, $vcsLogin, $vcsPasswd, $email, $lang='en', $authService='VCS', $authServiceID = null) + { + // Var to return into ExtJs + $return = array(); + + // We manage the project + if( ProjectManager::getInstance()->setProject($project) ) { + $this->project = strtoupper($project); + } else { + $return['state'] = false; + $return['msg'] = 'Bad project'; + $return['authMethod'] = '-'; + return $return; + } + + $this->authService = $authService; + $this->authServiceID = $authServiceID; + + /* + * VCS AUTH SYSTEM + * + */ + + if( $this->authService == 'VCS' ) { + + /* + * ANONYMOUS VCS + * + */ + + // Anonymous's user can logging into this app by providing this login/pass => anonymous/(empty) ou (empty)/(empty) + // The result is the same. $this->vcsLogin will be "anonymous" and $this->vcsPasswd, (empty) + if( ($vcsLogin == "anonymous" && $vcsPasswd == "") + || ($vcsLogin == "" && $vcsPasswd == "") ) { + + $this->isAnonymous = true; + + // Even if the user provide an empty login, we force it to be 'anonymous' + $vcsLogin = 'anonymous'; + + $this->anonymousIdent = ( isset($_COOKIE['anonymousIdent']) ) ? $_COOKIE['anonymousIdent'] : uniqid('', true); + + setcookie("anonymousIdent", $this->anonymousIdent, time() + 3600*24*365, "/"); // One year ;) + + // Register var + $this->vcsLogin = $vcsLogin; + $this->vcsPasswd = ''; + $this->vcsLang = $lang; + $this->email = $email; + + // Check DB + $s = 'SELECT * FROM `users` WHERE `project` = "%s" AND `authService` = "VCS" AND `vcs_login` = "%s" AND `anonymousIdent` = "%s"'; + $params = array($project, $this->vcsLogin, $this->anonymousIdent); + + $r = $this->conn->query($s, $params); + + + if ($r->num_rows == 1) { + + //This anonymous user exist into DB. We store his configuration into ... + $a = $r->fetch_object(); + + // ... object's property ... + $this->userConf = json_decode($a->conf); + + $this->userID = $a->userID; + + // ... and into the php's session (only specific var) + $_SESSION['userConf'] = $this->userConf; + + // We update the email if this user have decided to change it. + $this->updateEmail(); + + } else { + + // We register this new valid user + $userID = $this->register(); + $this->userID = $userID; + + // Store in session only specific var + $_SESSION['userConf'] = $this->defaultConf; + + } + + // Generic session var for VALID & ANONYMOUS VCS user + $_SESSION['userID'] = $this->userID; + $_SESSION['project'] = $this->project; + $_SESSION['vcsLogin'] = $this->vcsLogin = $this->vcsLogin.' #'.$this->userID; + $_SESSION['vcsPasswd'] = $this->vcsPasswd; + $_SESSION['isAnonymous'] = $this->isAnonymous; + $_SESSION['anonymousIdent'] = $this->anonymousIdent; + $_SESSION['lang'] = $this->vcsLang; + $_SESSION['email'] = $this->email; + $_SESSION['authService'] = $this->authService; + $_SESSION['authServiceID'] = $this->authServiceID; + + // We set up the CSRF token + $_SESSION['csrfToken'] = sha1(uniqid(rand(), true)); + + // Store some user info in cookies: we can use this to pre-fill the + // login page if the user's session expires. + setcookie("loginApp", 'anonymous', time() + 3600*24*365, "/"); // One year ;) + setcookie("email", $this->email, time() + 3600*24*365, "/"); + setcookie("lang", $this->vcsLang, time() + 3600*24*365, "/"); + + + // We construct the return's var for ExtJs + $return['state'] = true; + $return['msg'] = 'Welcome !'; + return $return; + + } + + /* + * VALID VCS USER + * + */ + + + else { + + $this->isAnonymous = false; + $this->anonymousIdent = ''; + + // If this app is installed into Php's server, we use the standad way to verify login/password + if( $_SERVER["SERVER_NAME"] == "doc.php.net" ) { + // We try to authenticate this user to master php server. + $AuthReturn = VCSFactory::getInstance()->masterPhpAuthenticate($vcsLogin, $vcsPasswd); + $return['authMethod'] = 'masterPhp'; + } + + + if( $AuthReturn !== true ) { + $return['state'] = false; + $return['msg'] = $AuthReturn; + return $return; + } else { + + // Check the karma + $karma = VCSFactory::getInstance()->checkKarma($vcsLogin, $lang); + + if( $karma !== true ) { + $return['state'] = false; + $return['msg'] = $karma; + return $return; + } + + // Register var + $this->vcsLogin = $vcsLogin; + $this->vcsPasswd = $vcsPasswd; + $this->vcsLang = $lang; + $this->email = $email; + + // Check DB + $s = 'SELECT * FROM `users` WHERE `project` = "%s" AND `authService` = "VCS" AND `vcs_login` = "%s"'; + $params = array($project, $this->vcsLogin); + + $r = $this->conn->query($s, $params); + + if ($r->num_rows == 1) { + + //This user exist into DB. We store his configuration into ... + $a = $r->fetch_object(); + + // ... object's property ... + $this->userConf = json_decode($a->conf); + + $this->userID = $a->userID; + + // ... and into the php's session (only specific var) + $_SESSION['userConf'] = $this->userConf; + + // We update the email if this user have decided to change it. + $this->updateEmail(); + + } else { + + // We register this new valid user + $userID = $this->register(); + $this->userID = $userID; + + // Store in session only specific var + $_SESSION['userConf'] = $this->defaultConf; + + } + + // Generic session var for VALID & ANONYMOUS VCS user + $_SESSION['userID'] = $this->userID; + $_SESSION['project'] = $this->project; + $_SESSION['vcsLogin'] = $this->vcsLogin; + $_SESSION['vcsPasswd'] = $this->vcsPasswd; + $_SESSION['isAnonymous'] = $this->isAnonymous; + $_SESSION['anonymousIdent'] = $this->anonymousIdent; + $_SESSION['lang'] = $this->vcsLang; + $_SESSION['email'] = $this->email; + $_SESSION['authService'] = $this->authService; + $_SESSION['authServiceID'] = $this->authServiceID; + + // We set up the CSRF token + $_SESSION['csrfToken'] = sha1(uniqid(rand(), true)); + + // Store some user info in cookies: we can use this to pre-fill the + // login page if the user's session expires. + setcookie("loginApp", utf8_encode($this->vcsLogin), time() + 3600*24*365, "/"); // One year ;) + setcookie("email", $this->email, time() + 3600*24*365, "/"); + setcookie("lang", $this->vcsLang, time() + 3600*24*365, "/"); + + + // We construct the return's var for ExtJs + $return['state'] = true; + $return['msg'] = 'Welcome !'; + return $return; + } + + } + + } + + /* + * EXTERNAL AUTH SYSTEM + * + */ + + else if( $this->authService == 'google' || $this->authService == 'facebook' ) { + + $this->isAnonymous = true; + $this->anonymousIdent = $this->authService.'-'.$this->authServiceID; + + // Register var + $this->vcsLogin = $vcsLogin; + $this->vcsPasswd = ''; + $this->vcsLang = $lang; + $this->email = $email; + + // Check DB + $s = 'SELECT * FROM `users` WHERE `project` = "%s" AND `authService` = "%s" AND `authServiceID` = "%s" AND `vcs_login` = "%s" AND `anonymousIdent` = "%s"'; + $params = array($project, $this->authService, $this->authServiceID, $this->vcsLogin, $this->anonymousIdent); + + $r = $this->conn->query($s, $params); + + if ($r->num_rows == 1) { + //This anonymous user exist into DB. We store his configuration into ... + $a = $r->fetch_object(); + + // ... object's property ... + $this->userConf = json_decode($a->conf); + + $this->userID = $a->userID; + + // ... and into the php's session (only specific var) + $_SESSION['userConf'] = $this->userConf; + + // We update the email if this user have decided to change it. + $this->updateEmail(); + + } else { + + // We register this new valid user + $userID = $this->register(); + $this->userID = $userID; + + // Store in session only specific var + $_SESSION['userConf'] = $this->defaultConf; + + } + + // Generic session var for VALID & ANONYMOUS VCS user + $_SESSION['userID'] = $this->userID; + $_SESSION['project'] = $this->project; + $_SESSION['vcsLogin'] = $this->vcsLogin; + $_SESSION['vcsPasswd'] = $this->vcsPasswd; + $_SESSION['isAnonymous'] = $this->isAnonymous; + $_SESSION['anonymousIdent'] = $this->anonymousIdent; + $_SESSION['lang'] = $this->vcsLang; + $_SESSION['email'] = $this->email; + $_SESSION['authService'] = $this->authService; + $_SESSION['authServiceID'] = $this->authServiceID; + + // We set up the CSRF token + $_SESSION['csrfToken'] = sha1(uniqid(rand(), true)); + + // Store some user info in cookies: we can use this to pre-fill the + // login page if the user's session expires. + setcookie("loginApp", utf8_encode($this->vcsLogin), time() + 3600*24*365, "/"); // One year ;) + setcookie("email", $this->email, time() + 3600*24*365, "/"); + setcookie("lang", $this->vcsLang, time() + 3600*24*365, "/"); + + // We construct the return's var for ExtJs + $return['state'] = true; + $return['msg'] = 'Welcome !'; + return $return; + + } else { + $return['state'] = false; + $return['msg'] = 'Bad authService'; + $return['authMethod'] = '-'; + return $return; + } + + } + + /** + * Check if a user is an anonymous or not based only on his name. + * @param string The user name to check + * @return boolean TRUE if the given user is an anonymous, FALSE otherwise. + */ + public function anonymous($userLogin, $anonymousIdent) + { + // A valid user is a user who have a "VCS" authService, without anonymousIdent + $s = 'SELECT authService, anonymousIdent FROM `users` WHERE project="%s" AND vcs_login = "%s" AND anonymousIdent = "%s"'; + + $params = array($this->project, $userLogin, $anonymousIdent); + $r = $this->conn->query($s, $params); + $a = $r->fetch_object(); + + // An anonymous have is #xxx at the end of his login. So, the sql "failed" + if( !is_object($a) ) { + return true; + } + + return ( $a->authService == 'VCS' && $a->anonymousIdent == '' ) ? false : true; + } + + public function isGlobalAdmin() + { + // Anonymous can't be a globalAdmin + if( $this->isAnonymous ) return false; + + $admin = explode(",", $this->appConf[$this->project]['project.globaladmin']); + return ( in_array($this->vcsLogin, $admin) ) ? true : false; + } + + public function isLangAdmin() + { + // Anonymous can't be a langAdmin + if( $this->isAnonymous ) return false; + + if( !isset($this->appConf[$this->project]['project.langadmin.'.$this->vcsLang]) ) { + return false; + } + + $admin = explode(",", $this->appConf[$this->project]['project.langadmin.'.$this->vcsLang]); + return ( in_array($this->vcsLogin, $admin) ) ? true : false; + } + + public function isAdmin($lang=false) + { + if( $this->isAnonymous ) return false; + + // If lang is true, this method must return true if current user is either a global admin, or a lang admin + if( $lang ) { + return ( $this->isGlobalAdmin() || $this->isLangAdmin() ) ? true : false; + } else { + // If lang is false, this method must return true if current user is ONLY a global admin + return ( $this->isGlobalAdmin() ) ? true : false; + } + + return false; + } + + public function updateEmail() + { + $s = 'UPDATE `users` SET `email`="%s" WHERE `userID`=%d'; + $params = array($this->email, $this->userID); + $this->conn->query($s, $params); + } + + public function getVCSUsers() + { + $s = 'SELECT `userID`, `vcs_login`, `anonymousIdent`, `authService` FROM `users` WHERE project="%s" AND vcs_login != "anonymous" ORDER BY authService, vcs_login'; + $params = array($this->project); + $r = $this->conn->query($s, $params); + + $result = array(); + $i=0; + + while( $a = $r->fetch_object() ) { + $result[$i]['userID'] = $a->userID; + $result[$i]['userName'] = $a->vcs_login; + $result[$i]['authService'] = $a->authService; + $i++; + } + return $result; + } + + public function setFileOwner($fileIdDB, $newOwnerID) + { + // Get newUser information + $s = 'SELECT * FROM `users` WHERE `userID` = %d'; + $params = array($newOwnerID); + + $r = $this->conn->query($s, $params); + $userInfo = $r->fetch_object(); + + // We update the file + $s = 'UPDATE `work` SET `user` = "%s", `anonymousIdent` = "%s", `module`="workInProgress", patchID=NULL WHERE `id` = %d'; + $params = array($userInfo->vcs_login, $userInfo->anonymousIdent, $fileIdDB); + + $this->conn->query($s, $params); + } + + /** + * Get user's details + * + * @return An object containing all details for this user + */ + public function getUserDetails($user, $anonymousIdent) + { + $am = AccountManager::getInstance(); + $project = $am->project; + + $s = 'SELECT `userID`, `authService`, `email` FROM `users` WHERE `project` = "%s" AND `vcs_login` = "%s" AND `anonymousIdent` = "%s"'; + $params = array($project, $user, $anonymousIdent); + + $r = $this->conn->query($s, $params); + $nb = $r->num_rows; + + // We have found the user + if( $nb != 0 ) { + $a = $r->fetch_object(); + return $a; + } else { + return false; + } + + } + + + /** + * Get the email for a user + * + * @return The email or false if we haven't found it. + */ + public function getUserEmail($user, $anonymousIdent) + { + $am = AccountManager::getInstance(); + $project = $am->project; + + $s = 'SELECT `email` FROM `users` WHERE `project` = "%s" AND `vcs_login` = "%s" AND `anonymousIdent` = "%s"'; + $params = array($project, $user, $anonymousIdent); + + $r = $this->conn->query($s, $params); + $nb = $r->num_rows; + + // We have found an email + if( $nb != 0 ) { + $a = $r->fetch_object(); + return $a->email; + } else { + return false; + } + + } + + /** + * Register a new valid user on the application. + * + * @return int The database insert id + */ + private function register() + { + $s = 'INSERT INTO `users` (`project`, `authService`, `authServiceID`, `vcs_login`, `email`, `anonymousIdent`, `conf`) VALUES ("%s","%s","%s","%s","%s","%s","%s")'; + $params = array($this->project, $this->authService, $this->authServiceID, $this->vcsLogin, $this->email, $this->anonymousIdent, json_encode($this->defaultConf)); + + $this->conn->query($s, $params); + return $this->conn->insert_id(); + } + + /** + * Update an option in user configuration database + * + * @param $item The name of the option. + * @param $value The value of the option. + */ + public function updateConf($module, $itemName, $value) + { + if( $value == "false" ) { + $value = false; + } + + if( $value == "true" ) { + $value = true; + } + + // @todo determine why this is called when these are empty + if (empty($module) || empty($itemName)) { + return false; + } + + $this->userConf->{$module}->{$itemName} = ( is_numeric($value) ) ? (int) $value : $value; + + // In session + unset($_SESSION['userConf']->{$module}->{$itemName}); + $_SESSION['userConf']->{$module}->{$itemName} = ( is_numeric($value) ) ? (int) $value : $value; + + // In DB + if( $this->isAnonymous ) { + $s = 'UPDATE `users` SET `conf`="%s" WHERE `vcs_login`="anonymous" AND `anonymousIdent`="%s"'; + $params = array(json_encode($this->userConf), $this->anonymousIdent); + } else { + $s = 'UPDATE `users` SET `conf`="%s" WHERE `vcs_login`="%s"'; + $params = array(json_encode($this->userConf), $this->vcsLogin); + } + $this->conn->query($s, $params); + } + + /** + * Erase personal data for the current user. + * Delete all reference from `users` & `commitMessage` DB tables. + */ + public function eraseData() + { + $s = 'DELETE FROM `commitMessage` WHERE `user`="%s"'; + $params = array($this->vcsLogin); + $this->conn->query($s, $params); + + $s = 'DELETE FROM `users` WHERE `userID`=%d'; + $params = array($this->userID); + $this->conn->query($s, $params); + } + + /** + * Send an email + * + * @param $to The Receiver. + * @param $subject The subject of the email. + * @param $msg The content of the email. Don't use HTML here ; only plain text. + * @param $from The email we place into From header. + * @param $fromType Either "user" or "list". Default to user + */ + public function email($to, $subject, $msg, $from='', $fromType='user') + { + if( $fromType == 'user' ) { + $from = $this->vcsLogin."@php.net"; + } + + $headers = 'From: '.$from . "\r\n" . + 'X-Mailer: Php Docbook Online Editor' ."\r\n" . + 'Content-Type: text/plain; charset="utf-8"'."\n"; + + mail($to, stripslashes($subject), stripslashes(trim($msg)), $headers, "-fnoreply@php.net"); + } +} + +?> diff --git a/php/Config.php b/php/Config.php index ad0ea8f4..2970136a 100755 --- a/php/Config.php +++ b/php/Config.php @@ -1,104 +1,104 @@ -buildConf(); - } - - public function buildConf() - { - $p = dirname(__FILE__).'/conf/'; - - // First, we load the global configuration file - $this->conf['GLOBAL_CONFIGURATION'] = parse_ini_file($p."conf.ini"); - - if( is_file($p."localConf.ini") ) { - $this->conf['GLOBAL_CONFIGURATION'] = array_merge( $this->conf['GLOBAL_CONFIGURATION'], parse_ini_file($p."localConf.ini") ); - } - - // We fix the data path here - $this->conf['GLOBAL_CONFIGURATION']['data.path'] = realpath(dirname(__FILE__).'/../'.$this->conf['GLOBAL_CONFIGURATION']['data.path']).'/'; - - // Second, we load all config project file - foreach (glob($p."project.*.ini") as $entry) { - $entry = basename($entry); - if( is_file($p.$entry)) { - - // Get the name of the project directly into the filename - $t = explode(".", $entry); - - $this->conf[strtoupper($t[1])] = parse_ini_file($p.$entry); - } - } - - // End, we load all local config project file - foreach (glob($p."local.*.ini") as $entry) { - $entry = basename($entry); - if( is_file($p.$entry)) { - - // Get the name of the project directly into the filename - $t = explode(".", $entry); - - $this->conf[strtoupper($t[1])] = array_merge( $this->conf[strtoupper($t[1])], parse_ini_file($p.$entry) ); - } - } - - - // Third, we find all marks to be replace by a var from global_configuration array or current project - while( list($project, $value) = each($this->conf) ) { - - if( $project == "GLOBAL_CONFIGURATION" ) { continue; } - - while( list($keys, $v ) = each($value) ) { - - $match = false; - - if( preg_match_all("/\{(.[^}]*?)\['(.*?)'\]\}/", $v,$match) ) { - - $new_val = $v; - for( $i=0; $i < count($match[0]); $i++ ) { - - $new_val = str_replace( $match[0][$i], - $this->conf[$match[1][$i]][$match[2][$i]], - $new_val - ); - - $this->conf[$project][$keys]= $new_val; - } - } - } - } - - reset($this->conf); - return $this->conf; - - } - - public function getConf() { - return $this->conf; - } - - -} - -?> +buildConf(); + } + + public function buildConf() + { + $p = dirname(__FILE__).'/conf/'; + + // First, we load the global configuration file + $this->conf['GLOBAL_CONFIGURATION'] = parse_ini_file($p."conf.ini"); + + if( is_file($p."localConf.ini") ) { + $this->conf['GLOBAL_CONFIGURATION'] = array_merge( $this->conf['GLOBAL_CONFIGURATION'], parse_ini_file($p."localConf.ini") ); + } + + // We fix the data path here + $this->conf['GLOBAL_CONFIGURATION']['data.path'] = realpath(dirname(__FILE__).'/../'.$this->conf['GLOBAL_CONFIGURATION']['data.path']).'/'; + + // Second, we load all config project file + foreach (glob($p."project.*.ini") as $entry) { + $entry = basename($entry); + if( is_file($p.$entry)) { + + // Get the name of the project directly into the filename + $t = explode(".", $entry); + + $this->conf[strtoupper($t[1])] = parse_ini_file($p.$entry); + } + } + + // End, we load all local config project file + foreach (glob($p."local.*.ini") as $entry) { + $entry = basename($entry); + if( is_file($p.$entry)) { + + // Get the name of the project directly into the filename + $t = explode(".", $entry); + + $this->conf[strtoupper($t[1])] = array_merge( $this->conf[strtoupper($t[1])], parse_ini_file($p.$entry) ); + } + } + + + // Third, we find all marks to be replace by a var from global_configuration array or current project + while( list($project, $value) = each($this->conf) ) { + + if( $project == "GLOBAL_CONFIGURATION" ) { continue; } + + while( list($keys, $v ) = each($value) ) { + + $match = false; + + if( preg_match_all("/\{(.[^}]*?)\['(.*?)'\]\}/", $v,$match) ) { + + $new_val = $v; + for( $i=0; $i < count($match[0]); $i++ ) { + + $new_val = str_replace( $match[0][$i], + $this->conf[$match[1][$i]][$match[2][$i]], + $new_val + ); + + $this->conf[$project][$keys]= $new_val; + } + } + } + } + + reset($this->conf); + return $this->conf; + + } + + public function getConf() { + return $this->conf; + } + + +} + +?> diff --git a/php/CvsClient.php b/php/CvsClient.php index 4094220a..10557095 100644 --- a/php/CvsClient.php +++ b/php/CvsClient.php @@ -1,288 +1,288 @@ -appConf; - $project = AccountManager::getInstance()->project; - - $fp = fsockopen($appConf[$project]['vcs.server.host'], $appConf[$project]['vcs.server.port']); - fwrite($fp, - implode("\n", array( - 'BEGIN AUTH REQUEST', - $appConf[$project]['vcs.server.path'], - $cvsLogin, - $this->passwdEncode($cvsPasswd, 'A'), - 'END AUTH REQUEST'."\n" - )) - ); - - $r = trim(fread($fp, 1024)); - fclose($fp); - - if ($r != 'I LOVE YOU') { - if ($r == 'I HATE YOU') { - return 'Bad password'; - } else { - return $r; - } - } else { - return true; - } - } - - /** - * cvs -d :pserver:cvsread:phpfi@cvs.php.net:/repository checkout phpdoc-all under DOC_EDITOR_DATA_PATH - */ - public function checkout() - { - $appConf = AccountManager::getInstance()->appConf; - - $commands = array( - new ExecStatement('cd %s', array($appConf['GLOBAL_CONFIGURATION']['data.path'])), - new ExecStatement('cvs -d :pserver:cvsread:phpfi@cvs.php.net:/repository login'), - new ExecStatement('cvs -d :pserver:cvsread:phpfi@cvs.php.net:/repository checkout phpdoc-all') - ); - SaferExec::execMulti($commands); - } - - /** - * cvs -f -q update -d -P . under DOC_EDITOR_VCS_PATH - */ - public function update() - { - $appConf = AccountManager::getInstance()->appConf; - $project = AccountManager::getInstance()->project; - - $commands = array( - new ExecStatement('cd %s', array($appConf[$project]['vcs.path'])), - new ExecStatement('cvs -f -q update -d -P .') - ); - SaferExec::execMulti($commands); - } - - /** - * Get Cvs log of a specified file. - * - * @param $path The path of the file. - * @param $file The name of the file. - * @return An array containing all Cvs log informations. - */ - public function log($path, $file) - { - $appConf = AccountManager::getInstance()->appConf; - $project = AccountManager::getInstance()->project; - - $commands = array( - new ExecStatement('cd %s', array($appConf[$project]['vcs.path'] . $path)), - new ExecStatement('cvs log %s', array($file)) - ); - - $output = array(); - SaferExec::execMulti($commands, $output); - - $output = implode("\n", $output); - - $output = str_replace('=============================================================================', '', $output); - - $part = explode('----------------------------', $output); - - $final = array(); - for ($i=1; $i < count($part); $i++ ) { - - $o = array(); - - $o['id'] = $i; - $o['raw'] = $part[$i]; - - // Get revision - $out = array(); - preg_match('/revision (.*?)\n/e', $part[$i], $out); - $o['revision'] = $out[1]; - - // Get date - $out = array(); - preg_match('/date: (.*?);/e', $part[$i], $out); - $o['date'] = $out[1]; - - // Get user - $out = array(); - preg_match('/author: (.*?);/e', $part[$i], $out); - $o['author'] = $out[1]; - - //Get content - $content = explode("\n", $part[$i]); - - if (substr($content[3], 0, 9) == 'branches:' ) { $j=4; } - else { $j=3; } - - $o['content'] = ''; - - for ($h=$j; $h < count($content); $h++) { - $o['content'] .= $content[$h]."\n"; - } - $o['content'] = str_replace("\n", '
', trim($o['content'])); - - $final[] = $o; - } - - return $final; - } - - /** - * Execute cvs diff on specific file - * - * @param $path Path to file - * @param $file Filename - * @param $rev1 Diff revision 1 - * @param $rev2 Diff revision 2 - * @return Array of stdout of cvs diff - */ - public function diff($path, $file, $rev1, $rev2) - { - $appConf = AccountManager::getInstance()->appConf; - $project = AccountManager::getInstance()->project; - - $commands = array( - new ExecStatement('cd %s', array($appConf[$project]['vcs.path'] . $path)), - new ExecStatement('cvs diff -kk -u -r %d -r %d %s', array((int)$rev2, (int)$rev1, $file)) - ); - - $output = array(); - SaferExec::execMulti($commands, $output); - - return $output; - } - - /** - * Executes cvs commit - * - * @param $log Commit log - * @param $create Array of files to be created - * @param $update Array of files to be updated - * @param $delete Array of files to be deleted - * @return Array of stdout of cvs commit - */ - public function commit($log, $create=false, $update=false, $delete=false) - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - $create_stack = array(); - for ($i = 0; $create && $i < count($create); $i++) { - $create_stack[] = $create[$i]->lang.'/'.$create[$i]->path.'/'.$create[$i]->name; - } - - $update_stack = array(); - for ($i = 0; $update && $i < count($update); $i++) { - $p = $update[$i]->lang.'/'.$update[$i]->path.'/'.$update[$i]->name; - $update_stack[] = $p; - - @copy( $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/'.$p, $appConf[$project]['vcs.path'].$p); - - @unlink( $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/'.$p ); - } - - $delete_stack = array(); - for ($i = 0; $delete && $i < count($delete); $i++) { - $delete_stack[] = $delete[$i]->lang.'/'.$delete[$i]->path.'/'.$delete[$i]->name; - } - - // Buil the command line - $cvsLogin = AccountManager::getInstance()->vcsLogin; - $cvsPasswd = AccountManager::getInstance()->vcsPasswd; - - $commands = array( - new ExecStatement('export CVS_PASSFILE=%s', array(realpath($appConf['GLOBAL_CONFIGURATION']['data.path']) . '/.cvspass')), - new ExecStatement('cd %s', array($appConf[$project]['vcs.path'])), - new ExecStatement('cvs -d :pserver:' . $cvsLogin . ':' . $cvsPasswd . '@cvs.php.net:/repository login') - ); - - if (!empty($delete_stack)) - { - $commands[] = new ExecStatement('cvs -d :pserver:' . $cvsLogin . ':' . $cvsPasswd . '@cvs.php.net:/repository -f remove -f' . str_repeat(' %s', count($delete_stack)), array($delete_stack)); - } - - if (!empty($create_stack)) - { - $commands[] = new ExecStatement('cvs -d :pserver:' . $cvsLogin . ':' . $cvsPasswd . '@cvs.php.net:/repository -f add' . str_repeat(' %s', count($create_stack)), array($create_stack)); - } - - $args = array_merge(array($log), $create_stack, $update_stack, $delete_stack); - $commands[] = new ExecStatement('cvs -d :pserver:' . $cvsLogin . ':' . $cvsPasswd . '@cvs.php.net:/repository -f commit -l -m %s' . str_repeat(' %s', count($create_stack) + count($update_stack) + count($delete_stack)), $args); - - $output = array(); - SaferExec::execMulti($commands, $output); - - return $output; - } -} - -?> +appConf; + $project = AccountManager::getInstance()->project; + + $fp = fsockopen($appConf[$project]['vcs.server.host'], $appConf[$project]['vcs.server.port']); + fwrite($fp, + implode("\n", array( + 'BEGIN AUTH REQUEST', + $appConf[$project]['vcs.server.path'], + $cvsLogin, + $this->passwdEncode($cvsPasswd, 'A'), + 'END AUTH REQUEST'."\n" + )) + ); + + $r = trim(fread($fp, 1024)); + fclose($fp); + + if ($r != 'I LOVE YOU') { + if ($r == 'I HATE YOU') { + return 'Bad password'; + } else { + return $r; + } + } else { + return true; + } + } + + /** + * cvs -d :pserver:cvsread:phpfi@cvs.php.net:/repository checkout phpdoc-all under DOC_EDITOR_DATA_PATH + */ + public function checkout() + { + $appConf = AccountManager::getInstance()->appConf; + + $commands = array( + new ExecStatement('cd %s', array($appConf['GLOBAL_CONFIGURATION']['data.path'])), + new ExecStatement('cvs -d :pserver:cvsread:phpfi@cvs.php.net:/repository login'), + new ExecStatement('cvs -d :pserver:cvsread:phpfi@cvs.php.net:/repository checkout phpdoc-all') + ); + SaferExec::execMulti($commands); + } + + /** + * cvs -f -q update -d -P . under DOC_EDITOR_VCS_PATH + */ + public function update() + { + $appConf = AccountManager::getInstance()->appConf; + $project = AccountManager::getInstance()->project; + + $commands = array( + new ExecStatement('cd %s', array($appConf[$project]['vcs.path'])), + new ExecStatement('cvs -f -q update -d -P .') + ); + SaferExec::execMulti($commands); + } + + /** + * Get Cvs log of a specified file. + * + * @param $path The path of the file. + * @param $file The name of the file. + * @return An array containing all Cvs log informations. + */ + public function log($path, $file) + { + $appConf = AccountManager::getInstance()->appConf; + $project = AccountManager::getInstance()->project; + + $commands = array( + new ExecStatement('cd %s', array($appConf[$project]['vcs.path'] . $path)), + new ExecStatement('cvs log %s', array($file)) + ); + + $output = array(); + SaferExec::execMulti($commands, $output); + + $output = implode("\n", $output); + + $output = str_replace('=============================================================================', '', $output); + + $part = explode('----------------------------', $output); + + $final = array(); + for ($i=1; $i < count($part); $i++ ) { + + $o = array(); + + $o['id'] = $i; + $o['raw'] = $part[$i]; + + // Get revision + $out = array(); + preg_match('/revision (.*?)\n/e', $part[$i], $out); + $o['revision'] = $out[1]; + + // Get date + $out = array(); + preg_match('/date: (.*?);/e', $part[$i], $out); + $o['date'] = $out[1]; + + // Get user + $out = array(); + preg_match('/author: (.*?);/e', $part[$i], $out); + $o['author'] = $out[1]; + + //Get content + $content = explode("\n", $part[$i]); + + if (substr($content[3], 0, 9) == 'branches:' ) { $j=4; } + else { $j=3; } + + $o['content'] = ''; + + for ($h=$j; $h < count($content); $h++) { + $o['content'] .= $content[$h]."\n"; + } + $o['content'] = str_replace("\n", '
', trim($o['content'])); + + $final[] = $o; + } + + return $final; + } + + /** + * Execute cvs diff on specific file + * + * @param $path Path to file + * @param $file Filename + * @param $rev1 Diff revision 1 + * @param $rev2 Diff revision 2 + * @return Array of stdout of cvs diff + */ + public function diff($path, $file, $rev1, $rev2) + { + $appConf = AccountManager::getInstance()->appConf; + $project = AccountManager::getInstance()->project; + + $commands = array( + new ExecStatement('cd %s', array($appConf[$project]['vcs.path'] . $path)), + new ExecStatement('cvs diff -kk -u -r %d -r %d %s', array((int)$rev2, (int)$rev1, $file)) + ); + + $output = array(); + SaferExec::execMulti($commands, $output); + + return $output; + } + + /** + * Executes cvs commit + * + * @param $log Commit log + * @param $create Array of files to be created + * @param $update Array of files to be updated + * @param $delete Array of files to be deleted + * @return Array of stdout of cvs commit + */ + public function commit($log, $create=false, $update=false, $delete=false) + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + $create_stack = array(); + for ($i = 0; $create && $i < count($create); $i++) { + $create_stack[] = $create[$i]->lang.'/'.$create[$i]->path.'/'.$create[$i]->name; + } + + $update_stack = array(); + for ($i = 0; $update && $i < count($update); $i++) { + $p = $update[$i]->lang.'/'.$update[$i]->path.'/'.$update[$i]->name; + $update_stack[] = $p; + + @copy( $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/'.$p, $appConf[$project]['vcs.path'].$p); + + @unlink( $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/'.$p ); + } + + $delete_stack = array(); + for ($i = 0; $delete && $i < count($delete); $i++) { + $delete_stack[] = $delete[$i]->lang.'/'.$delete[$i]->path.'/'.$delete[$i]->name; + } + + // Buil the command line + $cvsLogin = AccountManager::getInstance()->vcsLogin; + $cvsPasswd = AccountManager::getInstance()->vcsPasswd; + + $commands = array( + new ExecStatement('export CVS_PASSFILE=%s', array(realpath($appConf['GLOBAL_CONFIGURATION']['data.path']) . '/.cvspass')), + new ExecStatement('cd %s', array($appConf[$project]['vcs.path'])), + new ExecStatement('cvs -d :pserver:' . $cvsLogin . ':' . $cvsPasswd . '@cvs.php.net:/repository login') + ); + + if (!empty($delete_stack)) + { + $commands[] = new ExecStatement('cvs -d :pserver:' . $cvsLogin . ':' . $cvsPasswd . '@cvs.php.net:/repository -f remove -f' . str_repeat(' %s', count($delete_stack)), array($delete_stack)); + } + + if (!empty($create_stack)) + { + $commands[] = new ExecStatement('cvs -d :pserver:' . $cvsLogin . ':' . $cvsPasswd . '@cvs.php.net:/repository -f add' . str_repeat(' %s', count($create_stack)), array($create_stack)); + } + + $args = array_merge(array($log), $create_stack, $update_stack, $delete_stack); + $commands[] = new ExecStatement('cvs -d :pserver:' . $cvsLogin . ':' . $cvsPasswd . '@cvs.php.net:/repository -f commit -l -m %s' . str_repeat(' %s', count($create_stack) + count($update_stack) + count($delete_stack)), $args); + + $output = array(); + SaferExec::execMulti($commands, $output); + + return $output; + } +} + +?> diff --git a/php/DBConnection.php b/php/DBConnection.php index 84691680..f0d2ffa6 100644 --- a/php/DBConnection.php +++ b/php/DBConnection.php @@ -1,74 +1,74 @@ -getConf(); - - try { - $this->conn = new mysqli( - $appConf['GLOBAL_CONFIGURATION']['sql.host'], - $appConf['GLOBAL_CONFIGURATION']['sql.user'], - $appConf['GLOBAL_CONFIGURATION']['sql.passwd'], - $appConf['GLOBAL_CONFIGURATION']['sql.database'] - ); - if (mysqli_connect_errno()) { - throw new Exception('connect databases failed!'); - } - } catch (Exception $e) { - echo $e->getMessage(); - exit; - } - } - - public function query($s, array $params) - { - $params = array_map(array($this, 'real_escape_string'), $params); - $query = vsprintf($s, $params); - $r = $this->conn->query($query) or die('Error: '.$this->conn->error.'|'.$query); - return $r; - } - - public function insert_id() - { - return $this->conn->insert_id; - } - - public function num_rows() - { - return $this->conn->num_rows; - } - - public function affected_rows() - { - return $this->conn->affected_rows; - } - - public function real_escape_string($escape_str) - { - return $this->conn->real_escape_string($escape_str); - } -} - -?> +getConf(); + + try { + $this->conn = new mysqli( + $appConf['GLOBAL_CONFIGURATION']['sql.host'], + $appConf['GLOBAL_CONFIGURATION']['sql.user'], + $appConf['GLOBAL_CONFIGURATION']['sql.passwd'], + $appConf['GLOBAL_CONFIGURATION']['sql.database'] + ); + if (mysqli_connect_errno()) { + throw new Exception('connect databases failed!'); + } + } catch (Exception $e) { + echo $e->getMessage(); + exit; + } + } + + public function query($s, array $params) + { + $params = array_map(array($this, 'real_escape_string'), $params); + $query = vsprintf($s, $params); + $r = $this->conn->query($query) or die('Error: '.$this->conn->error.'|'.$query); + return $r; + } + + public function insert_id() + { + return $this->conn->insert_id; + } + + public function num_rows() + { + return $this->conn->num_rows; + } + + public function affected_rows() + { + return $this->conn->affected_rows; + } + + public function real_escape_string($escape_str) + { + return $this->conn->real_escape_string($escape_str); + } +} + +?> diff --git a/php/ExecStatement.php b/php/ExecStatement.php index 60b0371d..0a2901f7 100755 --- a/php/ExecStatement.php +++ b/php/ExecStatement.php @@ -1,50 +1,50 @@ -command = $command; - - // We validate and escape certain types of input. - $this->args = array(); - foreach ($args as $key => $val) - { - if (is_bool($val) || is_float($val) || is_int($val) || is_null($val)) - $this->args[$key] = $val; - else if (is_string($val)) - $this->args[$key] = escapeshellarg($val); - else if (is_object($val)) - $this->args[$key] = escapeshellarg($val->__toString()); - else - trigger_error('Argument with unexpected type used to construct ExecStatement. It has been omitted from the command string.', E_USER_WARNING); - } - } - - public function getCommand() - { - return $this->command; - } - - public function getArgs() - { - return $this->args; - } - - public function __toString() - { - return vsprintf($this->getCommand(), $this->getArgs()); - } -} +command = $command; + + // We validate and escape certain types of input. + $this->args = array(); + foreach ($args as $key => $val) + { + if (is_bool($val) || is_float($val) || is_int($val) || is_null($val)) + $this->args[$key] = $val; + else if (is_string($val)) + $this->args[$key] = escapeshellarg($val); + else if (is_object($val)) + $this->args[$key] = escapeshellarg($val->__toString()); + else + trigger_error('Argument with unexpected type used to construct ExecStatement. It has been omitted from the command string.', E_USER_WARNING); + } + } + + public function getCommand() + { + return $this->command; + } + + public function getArgs() + { + return $this->args; + } + + public function __toString() + { + return vsprintf($this->getCommand(), $this->getArgs()); + } +} ?> \ No newline at end of file diff --git a/php/JsonResponseBuilder.php b/php/JsonResponseBuilder.php index dcc9547c..4b39d570 100644 --- a/php/JsonResponseBuilder.php +++ b/php/JsonResponseBuilder.php @@ -1,51 +1,51 @@ - true); - } - - return json_encode($value); - } - - /** - * Gets the failure response - * @param mixed $value The value being encoded. Can be any type except a resource. - * - * @return string The failure json string. - */ - public static function failure($value = false) - { - if ($value) { - $value['success'] = false; - } else { - $value = array('success' => false); - } - - return json_encode($value); - } -} - -?> + true); + } + + return json_encode($value); + } + + /** + * Gets the failure response + * @param mixed $value The value being encoded. Can be any type except a resource. + * + * @return string The failure json string. + */ + public static function failure($value = false) + { + if ($value) { + $value['success'] = false; + } else { + $value = array('success' => false); + } + + return json_encode($value); + } +} + +?> diff --git a/php/LogManager.php b/php/LogManager.php index 5f3e54b4..10d3bd10 100644 --- a/php/LogManager.php +++ b/php/LogManager.php @@ -1,234 +1,234 @@ -conn = DBConnection::getInstance(); - } - - /** - * Get all commit message. - * - * Each time we commit, we store in DB the commit message to be use later. This method get all this message from DB. - * - * @return An indexed array of commit message. - */ - public function getCommitLog() - { - $am = AccountManager::getInstance(); - $project = $am->project; - $vcsLogin = $am->vcsLogin; - - $result = array(); - - $s = 'SELECT `id`, `text` FROM `commitMessage` WHERE `project`="%s" AND `user`="%s" ORDER BY used DESC'; - $params = array($project, $vcsLogin); - $r = $this->conn->query($s, $params); - while ($a = $r->fetch_assoc()) { - $result[] = $a; - } - - return $result; - } - - /** - * Add a commit log to the DB (if not exist). - * - * @param $log The commit log message to be added if it don't exist yet. - * @return Nothing. - */ - public function addCommitLog($log) - { - $am = AccountManager::getInstance(); - $project = $am->project; - $vcsLogin = $am->vcsLogin; - - $s = 'SELECT id, used FROM `commitMessage` WHERE `project`="%s" AND `text`="%s" AND `user`="%s"'; - $params = array($project, $log, $vcsLogin); - $r = $this->conn->query($s, $params); - - if ($r->num_rows == 0 ) { - $s = 'INSERT INTO `commitMessage` (`project`, `text`,`user`) VALUES ("%s", "%s", "%s")'; - $params = array($project, $log, $vcsLogin); - $this->conn->query($s, $params); - } else { - $a = $r->fetch_object(); - $s = 'UPDATE `commitMessage` SET `used` = %d WHERE id=%d'; - $newUsed = $a->used + 1; - $params = array($newUsed, $a->id); - $this->conn->query($s, $params); - } - } - - /** - * Save an existing log message into DB. - * - * @param $logID The ID of the log message. - * @param $log The message. - */ - public function updateCommitLog($logID, $log) - { - $s = 'UPDATE `commitMessage` SET `text`="%s" WHERE `id`=%d'; - $params = array($log, $logID); - $this->conn->query($s, $params); - } - - /** - * Delete a log message into DB. - * - * @param $logID The ID of the log message. - */ - public function delCommitLog($logID) - { - $s = 'DELETE FROM `commitMessage` WHERE `id`=%d'; - $params = array($logID); - $this->conn->query($s, $params); - } - - /** - * Save Output message into a log file. - * - * @param $file The name of the file. - * @param $output The output message. - * @return Nothing. - */ - public function saveOutputLog($file, $output) - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - $fp = fopen($appConf[$project]['vcs.path'] . '../.' . basename($file), 'w'); - fwrite($fp, implode("
",$output)); - fclose($fp); - } - - /** - * Get the content of a log file. - * - * @param $file The name of the file. - * @return The content of the log file. - */ - public function readOutputLog($file) - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - return $this->highlightBuildLog(file_get_contents($appConf[$project]['vcs.path'] . '../.' . basename($file))); - } - - /** - * Save failed build log. - * - * @param $lang The lang checked - * @param $log The content of the log - */ - public function saveFailedBuild($lang, $log) - { - $project = AccountManager::getInstance()->project; - - $s = 'INSERT INTO `failedBuildLog` (`project`, `lang`, `log`, `date`) - VALUES ("%s","%s", "%s", now())'; - $params = array($project, $lang, json_encode($log)); - $this->conn->query($s, $params); - } - - /** - * Highlight buildLog with some colors. - * - * @param $content The content of the log we want to highlight - * @return The log highlighted - */ - public function highlightBuildLog($content) - { - - $reg_red = array( - '/(Warning: )/', - '/(Notice: )/', - '/(Eyh man. No worries. Happ shittens. Try again after fixing the errors above.)/' - ); - - $reg_blue = array( - '/(Loading and parsing manual.xml...)/', - '/(Checking )/', - '/(Saving it...)/', - '/(Generating )/', - '/( on line )/', - '/(line: )/', - '/(Creating file )/' - ); - - $content = preg_replace( - $reg_red, - '$1', - $content - ); - - $content = preg_replace( - $reg_blue, - '$1', - $content - ); - - return $content; - } - - /** - * Get the list of failed build. - */ - public function getFailedBuild() - { - $project = AccountManager::getInstance()->project; - - $s = 'SELECT `id`, `lang`, `date` FROM `failedBuildLog` WHERE `project` = "%s"'; - $params = array($project); - $r = $this->conn->query($s, $params); - - $node = array(); - while ($a = $r->fetch_assoc()) { - $node[] = $a; - } - - return array('nb' => $r->num_rows, 'node' => $node); - } - - /** - * Get the data about a failed build. - * - * @param $id The id of the failed build into DB we want to retrieve - * @param $highlight If set to true (default), some elements of the content is html-highlighted. - * @return The content of this failed build - */ - public function getFailedBuildData($id, $highlight=true) - { - $s = 'SELECT `log` FROM `failedBuildLog` WHERE `id`=%d'; - $params = array($id); - $r = $this->conn->query($s, $params); - - $a = $r->fetch_object(); - - return ($highlight) ? $this->highlightBuildLog(json_decode($a->log)) : json_decode($a->log); - } -} - -?> +conn = DBConnection::getInstance(); + } + + /** + * Get all commit message. + * + * Each time we commit, we store in DB the commit message to be use later. This method get all this message from DB. + * + * @return An indexed array of commit message. + */ + public function getCommitLog() + { + $am = AccountManager::getInstance(); + $project = $am->project; + $vcsLogin = $am->vcsLogin; + + $result = array(); + + $s = 'SELECT `id`, `text` FROM `commitMessage` WHERE `project`="%s" AND `user`="%s" ORDER BY used DESC'; + $params = array($project, $vcsLogin); + $r = $this->conn->query($s, $params); + while ($a = $r->fetch_assoc()) { + $result[] = $a; + } + + return $result; + } + + /** + * Add a commit log to the DB (if not exist). + * + * @param $log The commit log message to be added if it don't exist yet. + * @return Nothing. + */ + public function addCommitLog($log) + { + $am = AccountManager::getInstance(); + $project = $am->project; + $vcsLogin = $am->vcsLogin; + + $s = 'SELECT id, used FROM `commitMessage` WHERE `project`="%s" AND `text`="%s" AND `user`="%s"'; + $params = array($project, $log, $vcsLogin); + $r = $this->conn->query($s, $params); + + if ($r->num_rows == 0 ) { + $s = 'INSERT INTO `commitMessage` (`project`, `text`,`user`) VALUES ("%s", "%s", "%s")'; + $params = array($project, $log, $vcsLogin); + $this->conn->query($s, $params); + } else { + $a = $r->fetch_object(); + $s = 'UPDATE `commitMessage` SET `used` = %d WHERE id=%d'; + $newUsed = $a->used + 1; + $params = array($newUsed, $a->id); + $this->conn->query($s, $params); + } + } + + /** + * Save an existing log message into DB. + * + * @param $logID The ID of the log message. + * @param $log The message. + */ + public function updateCommitLog($logID, $log) + { + $s = 'UPDATE `commitMessage` SET `text`="%s" WHERE `id`=%d'; + $params = array($log, $logID); + $this->conn->query($s, $params); + } + + /** + * Delete a log message into DB. + * + * @param $logID The ID of the log message. + */ + public function delCommitLog($logID) + { + $s = 'DELETE FROM `commitMessage` WHERE `id`=%d'; + $params = array($logID); + $this->conn->query($s, $params); + } + + /** + * Save Output message into a log file. + * + * @param $file The name of the file. + * @param $output The output message. + * @return Nothing. + */ + public function saveOutputLog($file, $output) + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + $fp = fopen($appConf[$project]['vcs.path'] . '../.' . basename($file), 'w'); + fwrite($fp, implode("
",$output)); + fclose($fp); + } + + /** + * Get the content of a log file. + * + * @param $file The name of the file. + * @return The content of the log file. + */ + public function readOutputLog($file) + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + return $this->highlightBuildLog(file_get_contents($appConf[$project]['vcs.path'] . '../.' . basename($file))); + } + + /** + * Save failed build log. + * + * @param $lang The lang checked + * @param $log The content of the log + */ + public function saveFailedBuild($lang, $log) + { + $project = AccountManager::getInstance()->project; + + $s = 'INSERT INTO `failedBuildLog` (`project`, `lang`, `log`, `date`) + VALUES ("%s","%s", "%s", now())'; + $params = array($project, $lang, json_encode($log)); + $this->conn->query($s, $params); + } + + /** + * Highlight buildLog with some colors. + * + * @param $content The content of the log we want to highlight + * @return The log highlighted + */ + public function highlightBuildLog($content) + { + + $reg_red = array( + '/(Warning: )/', + '/(Notice: )/', + '/(Eyh man. No worries. Happ shittens. Try again after fixing the errors above.)/' + ); + + $reg_blue = array( + '/(Loading and parsing manual.xml...)/', + '/(Checking )/', + '/(Saving it...)/', + '/(Generating )/', + '/( on line )/', + '/(line: )/', + '/(Creating file )/' + ); + + $content = preg_replace( + $reg_red, + '$1', + $content + ); + + $content = preg_replace( + $reg_blue, + '$1', + $content + ); + + return $content; + } + + /** + * Get the list of failed build. + */ + public function getFailedBuild() + { + $project = AccountManager::getInstance()->project; + + $s = 'SELECT `id`, `lang`, `date` FROM `failedBuildLog` WHERE `project` = "%s"'; + $params = array($project); + $r = $this->conn->query($s, $params); + + $node = array(); + while ($a = $r->fetch_assoc()) { + $node[] = $a; + } + + return array('nb' => $r->num_rows, 'node' => $node); + } + + /** + * Get the data about a failed build. + * + * @param $id The id of the failed build into DB we want to retrieve + * @param $highlight If set to true (default), some elements of the content is html-highlighted. + * @return The content of this failed build + */ + public function getFailedBuildData($id, $highlight=true) + { + $s = 'SELECT `log` FROM `failedBuildLog` WHERE `id`=%d'; + $params = array($id); + $r = $this->conn->query($s, $params); + + $a = $r->fetch_object(); + + return ($highlight) ? $this->highlightBuildLog(json_decode($a->log)) : json_decode($a->log); + } +} + +?> diff --git a/php/PreviewFile.php b/php/PreviewFile.php index 5b152b0c..81be7db9 100644 --- a/php/PreviewFile.php +++ b/php/PreviewFile.php @@ -1,146 +1,146 @@ -am = AccountManager::getInstance(); - - // Only available for PHP project - if( $this->am->project != 'PHP' ) { - return false; - } - - $this->path = str_replace('..', '', $path); - - $this->checkPath(); - $this->makePreview(); - - } - - private function checkPath() - { - $appConf = $this->am->appConf; - $project = $this->am->project; - - $this->fullPath = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'/'.$this->path; - $this->fullNewPath = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/'.$this->path; - - } - - private function checkDir() - { - // Output - $this->outputDir = $this->am->appConf['GLOBAL_CONFIGURATION']['data.path'].$this->am->appConf[$this->am->project]['vcs.module'].'/output-'.$this->am->vcsLogin.'/'; - if( !is_dir($this->outputDir) ) { - mkdir($this->outputDir); - } - - // Input - $this->inputDir = $this->am->appConf[$this->am->project]['preview.baseURI.path'].'manual/en/'; - if( !is_dir($this->inputDir) ) { - mkdir($this->am->appConf[$this->am->project]['preview.baseURI.path'].'manual'); - mkdir($this->inputDir); - } - } - - /** - */ - private function makePreview() - { - $appConf = $this->am->appConf; - $project = $this->am->project; - - $this->checkDir(); - - // We clean the input output directory - $commands = array( - new ExecStatement('cd %s', array($this->outputDir)), - new ExecStatement('rm -R *') - ); - SaferExec::execMulti($commands, $output); - $this->cleanCmd = implode('; ', $commands); - $this->cleanLog = $output; - - $rename = 0; - $t = time(); - // We are editing temporary file - if( file_exists($this->fullNewPath) ) { - $rename = 1; - rename($this->fullPath, $this->fullPath . $t); - rename($this->fullNewPath, $this->fullPath); - } - - // We start the build for this file - $commands = array( - new ExecStatement('cd %s', array($appConf[$project]['vcs.path'])), - new ExecStatement($appConf['GLOBAL_CONFIGURATION']['php.bin'] . ' doc-base/configure.php --with-php=%s --generate=%s', array($appConf['GLOBAL_CONFIGURATION']['php.bin'], $this->path)), - new ExecStatement($appConf['GLOBAL_CONFIGURATION']['php.bin'] . ' ../phd/render.php --package PHP --format php --memoryindex -d doc-base/.manual.xml --output %s', array($this->outputDir)) - ); - - SaferExec::execMulti($commands, $output); - $this->buildCmd = implode('; ', $commands); - $this->buildLog = $output; - - // Rename it back - if ($rename) { - rename($this->fullPath, $this->fullNewPath); - rename($this->fullPath . $t, $this->fullPath); - } - - - // Only move the specific file we are generating - $xmlID = $this->getOutputId(); - $filename = 'phdoe-' . time() . '-' . $xmlID. '.php'; - $cmd = new ExecStatement('mv %s %s', array($this->outputDir . 'php-web/' . $xmlID . '.php', $this->inputDir . $filename)); - SaferExec::exec($cmd, $output); - $this->moveCmd = $cmd->__toString(); - $this->moveLog = $output; - - - $this->previewUrl = $this->am->appConf[$this->am->project]['preview.baseURI'].'manual/en/' . $filename; - - } - - private function getOutputId() - { - // The output file name is the first ID of the file - $file = explode('/', $this->path); - $lang = $file[0]; - array_shift($file); - $path = implode('/',$file); - - $fileInfo = new File($lang, $path); - $info = $fileInfo->getInfo(); - - $xmlIDs = explode('|',$info['xmlid']); - $xmlID = $xmlIDs[0]; - return $xmlID; - } - - public function getPreviewUrl() { - return $this->previewUrl; - } - - public function getBuildCmd() { - return $this->buildCmd; - } - -} - -?> +am = AccountManager::getInstance(); + + // Only available for PHP project + if( $this->am->project != 'PHP' ) { + return false; + } + + $this->path = str_replace('..', '', $path); + + $this->checkPath(); + $this->makePreview(); + + } + + private function checkPath() + { + $appConf = $this->am->appConf; + $project = $this->am->project; + + $this->fullPath = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'/'.$this->path; + $this->fullNewPath = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new/'.$this->path; + + } + + private function checkDir() + { + // Output + $this->outputDir = $this->am->appConf['GLOBAL_CONFIGURATION']['data.path'].$this->am->appConf[$this->am->project]['vcs.module'].'/output-'.$this->am->vcsLogin.'/'; + if( !is_dir($this->outputDir) ) { + mkdir($this->outputDir); + } + + // Input + $this->inputDir = $this->am->appConf[$this->am->project]['preview.baseURI.path'].'manual/en/'; + if( !is_dir($this->inputDir) ) { + mkdir($this->am->appConf[$this->am->project]['preview.baseURI.path'].'manual'); + mkdir($this->inputDir); + } + } + + /** + */ + private function makePreview() + { + $appConf = $this->am->appConf; + $project = $this->am->project; + + $this->checkDir(); + + // We clean the input output directory + $commands = array( + new ExecStatement('cd %s', array($this->outputDir)), + new ExecStatement('rm -R *') + ); + SaferExec::execMulti($commands, $output); + $this->cleanCmd = implode('; ', $commands); + $this->cleanLog = $output; + + $rename = 0; + $t = time(); + // We are editing temporary file + if( file_exists($this->fullNewPath) ) { + $rename = 1; + rename($this->fullPath, $this->fullPath . $t); + rename($this->fullNewPath, $this->fullPath); + } + + // We start the build for this file + $commands = array( + new ExecStatement('cd %s', array($appConf[$project]['vcs.path'])), + new ExecStatement($appConf['GLOBAL_CONFIGURATION']['php.bin'] . ' doc-base/configure.php --with-php=%s --generate=%s', array($appConf['GLOBAL_CONFIGURATION']['php.bin'], $this->path)), + new ExecStatement($appConf['GLOBAL_CONFIGURATION']['php.bin'] . ' ../phd/render.php --package PHP --format php --memoryindex -d doc-base/.manual.xml --output %s', array($this->outputDir)) + ); + + SaferExec::execMulti($commands, $output); + $this->buildCmd = implode('; ', $commands); + $this->buildLog = $output; + + // Rename it back + if ($rename) { + rename($this->fullPath, $this->fullNewPath); + rename($this->fullPath . $t, $this->fullPath); + } + + + // Only move the specific file we are generating + $xmlID = $this->getOutputId(); + $filename = 'phdoe-' . time() . '-' . $xmlID. '.php'; + $cmd = new ExecStatement('mv %s %s', array($this->outputDir . 'php-web/' . $xmlID . '.php', $this->inputDir . $filename)); + SaferExec::exec($cmd, $output); + $this->moveCmd = $cmd->__toString(); + $this->moveLog = $output; + + + $this->previewUrl = $this->am->appConf[$this->am->project]['preview.baseURI'].'manual/en/' . $filename; + + } + + private function getOutputId() + { + // The output file name is the first ID of the file + $file = explode('/', $this->path); + $lang = $file[0]; + array_shift($file); + $path = implode('/',$file); + + $fileInfo = new File($lang, $path); + $info = $fileInfo->getInfo(); + + $xmlIDs = explode('|',$info['xmlid']); + $xmlID = $xmlIDs[0]; + return $xmlID; + } + + public function getPreviewUrl() { + return $this->previewUrl; + } + + public function getBuildCmd() { + return $this->buildCmd; + } + +} + +?> diff --git a/php/RepositoryFetcher.php b/php/RepositoryFetcher.php index 69bd1786..114893a9 100644 --- a/php/RepositoryFetcher.php +++ b/php/RepositoryFetcher.php @@ -1,1338 +1,1338 @@ -conn = DBConnection::getInstance(); - } - - - /** - * Get lst info dateTime about this apps - * - * @return The date/time of the last Info - */ - public function getLastInfoDate() - { - $am = AccountManager::getInstance(); - $project = $am->project; - - $s = 'SELECT - `date` - FROM - `staticValue` - WHERE - `project` = "%s" AND - `type`="info" - ORDER BY `date` DESC - LIMIT 0, 1'; - $params = array($am->project); - - $r = $this->conn->query($s, $params); - - $a = $r->fetch_assoc(); - - return $a['date']; - } - - /** - * Get infos about this apps - * - * @return Array - */ - public function getInfos($start, $limit) - { - $am = AccountManager::getInstance(); - $project = $am->project; - - $infos = array(); - - $s = 'SELECT - count(*) as total - FROM - `staticValue` - WHERE - `project` = "%s" AND - `type`="info"'; - $params = array($am->project); - - $r = $this->conn->query($s, $params); - - $a = $r->fetch_assoc(); - $infos['total'] = $a['total']; - - $s = 'SELECT - `field`, `value`, `date` - FROM - `staticValue` - WHERE - `project` = "%s" AND - `type`="info" - ORDER BY `date` DESC - LIMIT %d, %d'; - $params = array($am->project, (int)$start, (int)$limit); - - $r = $this->conn->query($s, $params); - - $i=0; - while ($a = $r->fetch_assoc()) { - $infos['value'][$i]['id'] = $i; - $infos['value'][$i]['field'] = $a['field']; - $infos['value'][$i]['value'] = json_decode($a['value']); - $infos['value'][$i]['date'] = $a['date']; - $infos['value'][$i]['elapsedTime'] = elapsedTime($a['date'], @date("Y-m-d H:i:s")); - $i++; - } - - return $infos; - } - - public function getSkeletonsNames() - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - $return = array(); - - if( !isset($appConf[$project]['skeletons.folder']) ) { - return $return; - } - - $dir = realpath($appConf[$project]['skeletons.folder']); - $d = dir($dir); - while (false !== ($entry = $d->read())) { - if( is_file($dir."/".$entry) && substr($entry, 0, 1) != "." ) { - $return[] = Array("name" => $entry, "path" => $dir."/".$entry); - } - } - $d->close(); - - sort($return); - return $return; - } - - /** - * Get all modified files with user lang or en. - * - * @return An associated array containing informations about modified files. - */ - public function getModifies() - { - $am = AccountManager::getInstance(); - - $s = 'SELECT - * - FROM - `work` - WHERE - `project` = "%s" AND - ( `lang`="%s" OR `lang`="en" ) '; - $params = array( - $am->project, - $am->vcsLang - ); - - $r = $this->conn->query($s, $params); - - $infos = array(); - while ($a = $r->fetch_assoc()) { - $infos[$a['lang'].$a['path'].$a['name']] = $a; - } - - return $infos; - } - - /** - * Get modified files by id. - * - * @param $id Can be a single id or an array of id - * @return An associated array containing informations about modified files specified by param id. - */ - public function getModifiesById($id) - { - $am = AccountManager::getInstance(); - $infos = array(); - - $ids = is_array($id) ? implode(array_map('intval', $id), ',') : (int)$id; - - if( empty( $ids ) ) { - return $infos; - } - - $s = 'SELECT - * - FROM - `work` - WHERE - `project` = "%s" AND - (`lang`="%s" OR `lang`="en" OR `lang`="doc-base") AND `id` IN (%s)'; - - $params = array( - $am->project, - $am->vcsLang, - $ids - ); - - $r = $this->conn->query($s, $params); - - while ($a = $r->fetch_assoc()) { - $infos[] = $a; - } - - return $infos; - } - - - public function getNbPendingUpdate() - { - $am = AccountManager::getInstance(); - - $vcsLang = $am->vcsLang; - $project = $am->project; - - $s = 'SELECT - count(*) as total - FROM - `files` - WHERE - `project` = "%s" AND - `lang` = "%s" AND - `revision` != `en_revision` AND - `status` is not null'; - $params = array( - $project, - $vcsLang - ); - $r = $this->conn->query($s, $params); - $a = $r->fetch_object(); - - return ( $a->total > $am->userConf->needUpdate->nbDisplay && $am->userConf->needUpdate->nbDisplay != 0 ) ? $am->userConf->needUpdate->nbDisplay : $a->total; - - } - /** - * Get all files witch need to be updated. - * - * @return An associated array containing information about files which need to be updated. - */ - public function getPendingUpdate() - { - $am = AccountManager::getInstance(); - - $vcsLang = $am->vcsLang; - $project = $am->project; - - $limit = ( $am->userConf->needUpdate->nbDisplay ) ? 'LIMIT '.(int)$am->userConf->needUpdate->nbDisplay : ''; - - $m = $this->getModifies(); - - $s = 'SELECT - * - FROM - `files` - WHERE - `project`="%s" AND - `lang` = "%s" AND - `revision` != `en_revision` AND - `status` is not NULL - %s'; - $params = array( - $project, - $vcsLang, - $limit - ); - $r = $this->conn->query($s, $params); - - $node = array(); - while ($a = $r->fetch_object()) { - - if ( isset($m[$vcsLang.$a->path.$a->name]) - ) { - - $isModifiedLang = ( isset($m[$vcsLang.$a->path.$a->name]) ) ? $m[$vcsLang.$a->path.$a->name] : false ; - - if ( $isModifiedLang ) { - $new_en_revision = $a->en_revision; - $new_revision = $isModifiedLang['en_revision']; - $original_revision = $a->revision; - $new_maintainer = $isModifiedLang['maintainer']; - } - - $node[] = array( - "id" => $a->id, - "path" => $a->path, - "name" => $a->name, - "revision" => $new_revision, - "original_revision" => $original_revision, - "en_revision" => $new_en_revision, - "maintainer" => $new_maintainer, - "fileModifiedEN" => false, - "fileModifiedLang" => ( $isModifiedLang ) ? '{"user":"'.$isModifiedLang["user"].'", "anonymousIdent":"'.$isModifiedLang["anonymousIdent"].'"}' : false - ); - } else { - $node[] = array( - "id" => $a->id, - "path" => $a->path, - "name" => $a->name, - "revision" => $a->revision, - "original_revision" => NULL, - "en_revision" => $a->en_revision, - "maintainer" => $a->maintainer, - "fileModifiedEN" => false, - "fileModifiedLang" => false - ); - } - } - return array('nb' => $r->num_rows, 'node' => $node); - } - - public function getNbPendingReview() - { - $am = AccountManager::getInstance(); - - $vcsLang = $am->vcsLang; - $project = $am->project; - - $m = $this->getModifies(); - $s = 'SELECT - count(*) as total - FROM - `files` - WHERE - `project`="%s" AND - `lang` = "%s" AND - reviewed != \'yes\''; - $params = array( - $project, - $vcsLang - ); - $r = $this->conn->query($s, $params); - $a = $r->fetch_object(); - - return ( $a->total > $am->userConf->reviewed->nbDisplay && $am->userConf->reviewed->nbDisplay != 0 ) ? $am->userConf->reviewed->nbDisplay : $a->total; - } - /** - * Get all files witch need to be reviewed. - * - * @return An associated array containing informations about files which need to be reviewed. - */ - public function getPendingReview() - { - $am = AccountManager::getInstance(); - - $vcsLang = $am->vcsLang; - $project = $am->project; - - $limit = ( $am->userConf->reviewed->nbDisplay ) ? 'LIMIT '.(int)$am->userConf->reviewed->nbDisplay : ''; - - $m = $this->getModifies(); - $s = 'SELECT - * - FROM - `files` - WHERE - `project`="%s" AND - `lang` = "%s" AND - reviewed != \'yes\' - ORDER BY - `path`, - `name` - %s'; - $params = array( - $project, - $vcsLang, - $limit - ); - $r = $this->conn->query($s, $params); - - $node = array(); - while ($a = $r->fetch_object()) { - - - $isModifiedLang = ( isset($m[$vcsLang.$a->path.$a->name]) ) ? $m[$vcsLang.$a->path.$a->name] : false ; - - $temp = array( - "id" => $a->id, - "path" => $a->path, - "name" => $a->name, - ); - - if ( $isModifiedLang ) - { - $new_reviewed = $isModifiedLang['reviewed']; - $new_maintainer = $isModifiedLang['reviewed_maintainer']; - - $temp['reviewed'] = $new_reviewed; - $temp['maintainer'] = $new_maintainer; - $temp['fileModifiedEN'] = false; - $temp['fileModifiedLang'] = ( $isModifiedLang ) ? '{"user":"'.$isModifiedLang["user"].'", "anonymousIdent":"'.$isModifiedLang["anonymousIdent"].'"}' : false; - } else { - $temp['reviewed'] = $a->reviewed; - $temp['maintainer'] = $a->reviewed_maintainer; - $temp['fileModifiedEN'] = false; - $temp['fileModifiedLang'] = false; - } - $node[] = $temp; - } - return array('nb' => $r->num_rows, 'node' => $node); - } - - public function getNbNotInEn() - { - $am = AccountManager::getInstance(); - $vcsLang = $am->vcsLang; - $project = $am->project; - - $s = 'SELECT - count(*) as total - FROM - `files` - WHERE - `project`="%s" AND - `lang`="%s" AND - `status`="NotInEN"'; - $params = array( - $project, - $vcsLang - ); - - $r = $this->conn->query($s, $params); - $a = $r->fetch_object(); - - return $a->total; - } - /** - * Get all files which are not in EN tree. - * - * @return An associated array containing informations about files which are not in EN tree - */ - public function getNotInEn() - { - $am = AccountManager::getInstance(); - $vcsLang = $am->vcsLang; - $project = $am->project; - - $m = $this->getModifies(); - - $s = 'SELECT - `id`, - `path`, - `name` - FROM - `files` - WHERE - `project`="%s" AND - `lang`="%s" AND - `status`="NotInEN"'; - $params = array( - $project, - $vcsLang - ); - - $r = $this->conn->query($s, $params); - - $node = array(); - while ($a = $r->fetch_object()) { - - $isModified = ( isset($m[$vcsLang.$a->path.$a->name]) ) ? $m[$vcsLang.$a->path.$a->name] : false ; - - $node[] = array( - "id" => $a->id, - "path" => $a->path, - "name" => $a->name, - "fileModified" => ( $isModified ) ? '{"user":"'.$isModified["user"].'", "anonymousIdent":"'.$isModified["anonymousIdent"].'"}' : false - ); - } - - return array('nb' => $r->num_rows, 'node' => $node); - } - - public function getNbPendingTranslate() - { - $am = AccountManager::getInstance(); - $vcsLang = $am->vcsLang; - $project = $am->project; - - $s = 'SELECT - count(*) as total - FROM - `files` - WHERE - `project`="%s" AND - `lang`="%s" AND - `status` is NULL AND - `revision` is NULL'; - $params = array( - $project, - $vcsLang - ); - - $r = $this->conn->query($s, $params); - $a = $r->fetch_object(); - - return ( $a->total > $am->userConf->newFile->nbDisplay && $am->userConf->newFile->nbDisplay != 0 ) ? $am->userConf->newFile->nbDisplay : $a->total; - } - - /** - * Get all files which need to be translated - * - * @return An associated array containing informations about files which need to be translated - */ - public function getPendingTranslate() - { - $am = AccountManager::getInstance(); - - $vcsLang = $am->vcsLang; - $project = $am->project; - - $limit = ( $am->userConf->newFile->nbDisplay ) ? 'LIMIT '.(int)$am->userConf->newFile->nbDisplay : ''; - - $m = $this->getModifies(); - $s = 'SELECT - `id`, `path`, `name` - FROM - `files` - WHERE - `project`="%s" AND - `lang`="%s" AND - `status` is NULL AND - `revision` is NULL - %s'; - - $params = array( - $project, - $vcsLang, - $limit - ); - - $r = $this->conn->query($s, $params); - - $node = array(); - while ($a = $r->fetch_object()) { - - $isModified = ( isset($m[$vcsLang.$a->path.$a->name]) ) ? $m[$vcsLang.$a->path.$a->name] : false ; - - $node[] = array( - "id" => $a->id, - "path" => $a->path, - "name" => $a->name, - "fileModified" => ( $isModified ) ? '{"user":"'.$isModified["user"].'", "anonymousIdent":"'.$isModified["anonymousIdent"].'"}' : false - ); - } - - return array('nb' => $r->num_rows, 'node' => $node); - } - - - // TODO : Deprecated - public function getNbPendingPatch() - { - $am = AccountManager::getInstance(); - $vcsLang = $am->vcsLang; - $project = $am->project; - - $s = 'SELECT - count(*) as total - FROM - `pendingPatch` - WHERE - `project`="%s" AND - (`lang`="%s" OR `lang`=\'en\')'; - $params = array( - $project, - $vcsLang - ); - - $r = $this->conn->query($s, $params); - $a = $r->fetch_object(); - - return $a->total; - } - - /** - * TODO : deprecated - * - * Get all pending patch. - * - * @return An associated array containing informations about pending patch. - */ - public function getPendingPatch() - { - $am = AccountManager::getInstance(); - $vcsLang = $am->vcsLang; - $project = $am->project; - - $s = 'SELECT `id`, CONCAT(`lang`, `path`) AS `path`, `name`, `posted_by` AS \'by\', `uniqID`, `date` FROM `pendingPatch` WHERE `project`="%s" AND (`lang`="%s" OR `lang`=\'en\')'; - $params = array( - $project, - $vcsLang - ); - $r = $this->conn->query($s, $params); - - $node = array(); - while ($row = $r->fetch_assoc()) { - $node[] = $row; - } - - return array('nb' => $r->num_rows, 'node' => $node); - } - - - /** - * Get all folders pending for commit. - * - * @return An associated array containing paths of folders pending for commit, or FALSE if there is no folder to commit. - */ - public function getPendingFoldersCommit() - { - $am = AccountManager::getInstance(); - $vcsLang = $am->vcsLang; - $project = $am->project; - - $s = 'SELECT * FROM `work` WHERE `project`="%s" AND (`lang`="%s" OR `lang`=\'en\') AND `name`=\'-\' ORDER BY id ASC'; - $params = array( - $project, - $vcsLang - ); - - $r = $this->conn->query($s, $params); - - if( $r->num_rows == 0 ) { - return false; - } - - $paths = array(); - while ($a = $r->fetch_object()) { - - $obj = (object) array('lang' => $a->lang, 'path' => $a->path, 'name'=> '-'); - - $paths[$a->lang.$a->path] = $obj; - } - - return $paths; - } - - // TODO : deprecated - public function getNbPendingCommit() - { - $am = AccountManager::getInstance(); - $vcsLang = $am->vcsLang; - $project = $am->project; - - // We exclude item witch name == '-' ; this is new folder ; We don't display it. - $s = 'SELECT count(*) as total FROM `pendingCommit` WHERE `project`="%s" AND (`lang`="%s" OR `lang`=\'en\') AND `name` != \'-\''; - $params = array( - $project, - $vcsLang - ); - - $r = $this->conn->query($s, $params); - $a = $r->fetch_object(); - - return $a->total; - } - - - /** - * Get all files in Work module (progress work and patches for review). - * Actually only used in scripts/cron/send_work_to_list.php - * - * @return An associated array containing informations about files in work - */ - public function getRawWork($lang) - { - $am = AccountManager::getInstance(); - $project = $am->project; - - /**** We start by the work in progress module ****/ - - // We exclude item witch name == '-' ; this is new folder ; We don't display it. - $s = 'SELECT - CONCAT(`lang`, `path`, `name`) as filePath, - `user`, - `date`, - `type` - FROM - `work` - WHERE - `module` = "workInProgress" AND - `lang` = "%s" AND - `project` = "%s" - ORDER BY - type, date'; - $params = array( - $lang, - $project - ); - $r = $this->conn->query($s, $params); - - $workInProgress = Array('nb'=>0,'data'=>Array()); - - if( $r->num_rows != 0 ) - { - $workInProgress['nb'] = $r->num_rows; - while ($a = $r->fetch_array(MYSQLI_ASSOC)) { - $workInProgress['data'][] = $a; - } - } - - /**** then, by the patches for review module ****/ - - // We exclude item witch name == '-' ; this is new folder ; We don't display it. - $s = 'SELECT - CONCAT(`lang`, `path`, `name`) as filePath, - `user`, - `date`, - `type` - FROM - `work` - WHERE - `module` = "PatchesForReview" AND - `lang` = "%s" AND - `project` = "%s" - ORDER BY - type, date'; - $params = array( - $lang, - $project - ); - $r = $this->conn->query($s, $params); - - $PatchesForReview = Array('nb'=>0,'data'=>Array()); - - if( $r->num_rows != 0 ) - { - $PatchesForReview['nb'] = $r->num_rows; - while ($a = $r->fetch_array(MYSQLI_ASSOC)) { - $PatchesForReview['data'][] = $a; - } - } - - // We return the result now - return Array( - "total" => ($workInProgress['nb'] + $PatchesForReview['nb']), - "workInProgress" => $workInProgress, - "PatchesForReview" => $PatchesForReview - ); - } - - /** - * Check is a patch don't contain any files - * - * - * @return TRUE if this patch is empty, FALSE either. - * @see RepositoryFetcher::getWork - */ - private function _isEmptyPatch($patchs) - { - $isEmpty = true; - - while( list($patch, $dataPatch) = each($patchs)) - { - while( list($folder, $dataFiles) = each($dataPatch['folders'])) - { - $isEmpty = false; - } - } - return $isEmpty; - } - - - /** - * Get all files in Work module (progress work or patches for review). - * - * @return An associated array containing informations about files in work - */ - public function getWork($module) - { - $am = AccountManager::getInstance(); - $vcsLang = $am->vcsLang; - $project = $am->project; - $vcsLogin = $am->vcsLogin; - $anonymousIdent = $am->anonymousIdent; - - $node = array(); - - if( $module == 'PatchesForReview' ) { - - // We exclude item witch name == '-' ; this is new folder ; We don't display it. - $s = 'SELECT - `id`, - `name` as patchName, - `description` as patchDescription, - `email` as patchEmail, - `user`, - `anonymousIdent`, - `date` - FROM - `patches` - WHERE - `project` = "%s"'; - $params = array( - $project - ); - $r = $this->conn->query($s, $params); - - $patches = Array(); - - while ($a = $r->fetch_object()) { - - $desc = $a->patchDescription; - $desc = str_replace("\n", '\n', $desc); - $desc = str_replace("\r", '\r', $desc); - $desc = str_replace("\t", '\t', $desc); - $desc = str_replace("'", "\'", $desc); - - $a->patchName = str_replace("'", "\'", $a->patchName); - - $patches[$a->id] = Array( - "user" => $a->user, - "patchName" => $a->patchName, - "patchDescription" => $desc, - "patchEmail" => $a->patchEmail - ); - - $node[$a->user.'@|@'.$a->anonymousIdent][$a->patchName]['idDB'] = $a->id; - $node[$a->user.'@|@'.$a->anonymousIdent][$a->patchName]['date'] = $a->date; - $node[$a->user.'@|@'.$a->anonymousIdent][$a->patchName]['folders'] = array(); - } - - // Bugfix: if we don't have any patches, the query below will fail. - // So we return immediately if that's the case. - if (empty($patches)) - return '[]'; - - // Do we need to display EN Work ? - if( isset($am->userConf->main->displayENWork) && $am->userConf->main->displayENWork === true ) { - $langFilter = '(`lang` = "%s" OR `lang`="en" OR `lang`="doc-base")'; - } else { - $langFilter = '(`lang` = "%s" OR `lang`="doc-base")'; - } - - // We exclude item witch name == '-' ; this is new folder ; We don't display it. - $s = 'SELECT - * - FROM - `work` - WHERE - `project` = "%s" AND - '.$langFilter.' AND - `name` != "-" AND - `module` = "%s" AND - `patchID` IN (%s)'; - $params = array( - $project, - $vcsLang, - $module, - implode(",", array_map('intval', array_keys($patches))) - ); - - $r = $this->conn->query($s, $params); - - while ($a = $r->fetch_object()) { - - $node[$a->user.'@|@'.$a->anonymousIdent][$patches[$a->patchID]["patchName"]]['idDB'] = $a->patchID; - $node[$a->user.'@|@'.$a->anonymousIdent][$patches[$a->patchID]["patchName"]]['folders'][$a->lang.$a->path][] = Array( - "name" => $a->name, - "last_modified" => $a->date, - "type" => $a->type, - "idDB" => $a->id - ); - - } - - $result = '['; - - // We format the result node to pass to ExtJs TreeGrid component - while( list($user, $patchs) = each($node)) { - - // $userInfo[0] => login - // $userInfo[1] => anonymousIdent - $userInfo = explode('@|@',$user); - $userDetails = $am->getUserDetails($userInfo[0], $userInfo[1]); - - // If the current user is not me and if all of his patch are empty, we don't send it - feature request ##60299 - if( $this->_isEmptyPatch($patchs) && !( $userInfo[0] == $vcsLogin && $userInfo[1] == $anonymousIdent ) ) { continue; } - - // Get authService from anonymousIdent - $tmp = explode('-', $userInfo[1]); - if( isset($tmp[1]) ) $authService = $tmp[0]; - else $authService = false; - - if( $authService == 'google' ) { - $iconUser = 'iconGoogle'; - } else if( $authService == 'facebook' ) { - $iconUser = 'iconFacebook'; - } else { - $iconUser = 'iconUser'; - } - - if( $userInfo[0] == $vcsLogin && $userInfo[1] == $anonymousIdent ) { - $expanded = 'true'; - } else { - $expanded = 'false'; - } - - $email = $am->getUserEmail($userInfo[0], $userInfo[1]); - $email = ($email) ? $email : 'false'; - - // We start by users - $result .= "{task:'".$userInfo[0]."',type:'user',userID:'".$userDetails->userID."',isAnonymous:".(($am->anonymous($userInfo[0], $userInfo[1])) ? 'true' : 'false').",email:'".$email."', iconCls:'".$iconUser."',expanded:".$expanded.",children:["; - - // We now walk into patches for this users. - while( list($patch, $dataPatch) = each($patchs)) { - - // If the current user is not me and if all of his patch are empty, we don't send it - feature request ##60299 - if( empty($dataPatch['folders']) && !( $userInfo[0] == $vcsLogin && $userInfo[1] == $anonymousIdent )) { continue; } - - $result .= "{task:'".$patch."',type:'patch',iconCls:'iconPatch',patchDescription:'".((isset($patches[$dataPatch["idDB"]]["patchDescription"])) ? $patches[$dataPatch["idDB"]]["patchDescription"] : '' )."',patchEmail:'".((isset($patches[$dataPatch["idDB"]]["patchEmail"])) ? $patches[$dataPatch["idDB"]]["patchEmail"] : '' )."',expanded:true,creationDate:'".( (isset($dataPatch["date"])) ? $dataPatch["date"] : '' )."',draggable: false, idDB:".$dataPatch["idDB"].", children:["; - - // We now walk into the folders for this patch - while( list($folder, $dataFiles) = each($dataPatch['folders'])) { - $result .= "{task:'".$folder."',type:'folder',iconCls:'iconFolderOpen',expanded:true,children:["; - - // We now walk into the files for this folder - while( list($file, $data) = each($dataFiles)) { - - // Witch iconCls do we need to use ? - switch ($data["type"]) { - case 'delete': - $iconCls = 'iconTrash'; - - break; - case 'new': - $iconCls = 'iconNewFiles'; - - break; - case 'update': - $iconCls = 'iconRefresh'; - - break; - - default: - $iconCls = 'task'; - break; - } - - $result .= "{task:'".$data["name"]."',type:'".$data["type"]."',last_modified:'".$data["last_modified"]."',leaf:true,iconCls:'".$iconCls."', idDB:".$data["idDB"]."},"; - - } - - $result .= ']},'; - - } - - $result .= ']},'; - } - - $result .= ']},'; - } - $result .= ']'; - - // We skip trailing comma - $result = str_replace("},]", "}]", $result); - - return $result; - - } // End if module == PatchesForReview - - - if( $module == 'workInProgress' ) { - - // Do we need to display EN Work ? - if( $am->userConf->main->displayENWork ) { - $langFilter = '(`lang` = "%s" OR `lang`="en" OR `lang`="doc-base")'; - } else { - $langFilter = '(`lang` = "%s" OR `lang`="doc-base")'; - } - - - // We exclude item witch name == '-' ; this is new folder ; We don't display it. - $s = 'SELECT - * - FROM - `work` - WHERE - `project` = "%s" AND - '.$langFilter.' AND - `name` != "-" AND - `module` = "%s" AND - `patchID` IS NULL'; - $params = array( - $project, - $vcsLang, - $module - ); - $r = $this->conn->query($s, $params); - - while ($a = $r->fetch_object()) { - - $node[$a->user.'@|@'.$a->anonymousIdent][$a->lang.$a->path][] = Array( - "name" => $a->name, - "last_modified" => $a->date, - "progress" => $a->progress, - "type" => $a->type, - "idDB" => $a->id - ); - } - - $result = '['; - // We format the result node to pass to ExtJs TreeGrid component - while( list($user, $dataFolders) = each($node)) { - - // $userInfo[0] => login - // $userInfo[1] => anonymousIdent - $userInfo = explode('@|@',$user); - $userDetails = $am->getUserDetails($userInfo[0], $userInfo[1]); - - // Get authService from anonymousIdent - $tmp = explode('-', $userInfo[1]); - if( isset($tmp[1]) ) $authService = $tmp[0]; - else $authService = false; - - if( $authService == 'google' ) { - $iconUser = 'iconGoogle'; - } else if( $authService == 'facebook' ) { - $iconUser = 'iconFacebook'; - } else { - $iconUser = 'iconUser'; - } - - if( $userInfo[0] == $vcsLogin && $userInfo[1] == $anonymousIdent ) { - $expanded = 'true'; - } else { - $expanded = 'false'; - } - - $email = $am->getUserEmail($userInfo[0], $userInfo[1]); - $email = ($email) ? $email : 'false'; - - // We put nbFiles into user's nodes to not have to count it by the client - $result .= "{task:'".$userInfo[0]."',type:'user',userID:'".$userDetails->userID."',isAnonymous:".(($am->anonymous($userInfo[0], $userInfo[1])) ? 'true' : 'false').",email:'".$email."', iconCls:'".$iconUser."',expanded:".$expanded.",children:["; - - // We now walk into the folders for this users - while( list($folder, $dataFiles) = each($dataFolders)) { - $result .= "{task:'".$folder."',type:'folder',iconCls:'iconFolderOpen',expanded:true,children:["; - - // We now walk into the files for this folder - while( list($file, $data) = each($dataFiles)) { - - // Witch iconCls do we need to use ? - switch ($data["type"]) { - case 'delete': - $iconCls = 'iconTrash'; - - break; - case 'new': - $iconCls = 'iconNewFiles'; - - break; - case 'update': - $iconCls = 'iconRefresh'; - - break; - - default: - $iconCls = 'task'; - break; - } - - $result .= "{task:'".$data["name"]."',type:'".$data["type"]."',last_modified:'".$data["last_modified"]."',leaf:true,iconCls:'".$iconCls."',progress:".$data["progress"].", idDB:".$data["idDB"]."},"; - } - - $result .= ']},'; - } - - - $result .= ']},'; - - } - $result .= ']'; - - // We skip trailing comma - $result = str_replace("},]", "}]", $result); - - return $result; - - } // End if module == workInProgress - } - - /** - * Get all files for a given php's extension. Can be exclusive for php project -TODO: Handle project here - * - * @param $ext The name of the extension. - * @return An array of files - */ - public function getFilesByExtension($ext) - { - $am = AccountManager::getInstance(); - $vcsLang = $am->vcsLang; - $project = $am->project; - - $s = 'SELECT `path`, `name` FROM `files` WHERE `path` - LIKE \'/reference/%s/%%\' AND `lang`="%s" AND `project`="%s" ORDER BY `path`, `name`'; - $params = array( - $ext, $vcsLang, $project - ); - $r = $this->conn->query($s, $params); - - $node = array(); $i=0; - while ($a = $r->fetch_object()) { - $node[$i]['path'] = $a->path; - $node[$i]['name'] = $a->name; - - $i++; - } - return $node; - } - - /** - * Get a file regarding its xml ID. - * - * @param $lang The lang of the searched file. - * @param $id The ID of the searched file. - * @return file info include lang, path, name - */ - public function getFileByXmlID($lang, $id) - { - $project = AccountManager::getInstance()->project; - - // If user forget ".php" at this end of the permlink, this is "function" how is search into DB. - // We don't allow it, neither blank ID - if( $id == 'function' || empty($id) ) { - return false; - } - - // We start by searching file witch only this ID - $s = 'SELECT - `lang`, `path`, `name` - FROM - `files` - WHERE - `project`="%s" AND - `lang` = "%s" AND - `xmlid` = "%s"'; - $params = array( - $project, - $lang, - $id - ); - $r = $this->conn->query($s, $params); - $nb = $r->num_rows; - - if( $nb >= 1 ) { - return $r->fetch_object(); - } else { - - // We now search file which contain this ID - $s = 'SELECT - `lang`, `path`, `name` - FROM - `files` - WHERE - `project`="%s" AND - `lang` = "%s" AND - `xmlid` LIKE "%%%s%%"'; - $params = array( - $project, - $lang, - $id - ); - $r = $this->conn->query($s, $params); - $nb = $r->num_rows; - - if( $nb == 0 ) { - return false; - } else { - return $r->fetch_object(); - } - - } - } - - /** - * Perform searching on filepath under the repository tree - * - * @param $key Keyword for search - * @return Array of file info (TODO: remove extjs dependent info) - */ - public function getFileByKeyword($key) - { - $am = AccountManager::getInstance(); - $vcsLang = $am->vcsLang; - $project = $am->project; - - $s = 'SELECT `lang`, `path`, `name` FROM `files` WHERE `project`="%s" AND (`lang`="%s" OR `lang`=\'en\') - AND ( `name` LIKE \'%%%s%%\' OR `xmlid` LIKE \'%%%s%%\' ) ORDER BY `lang`, `path`, `name`'; - $params = array( - $project, - $vcsLang, - $key, - $key - ); - $r = $this->conn->query($s, $params); - - $files = array(); - while ($a = $r->fetch_object()) { - $ext = array_pop(explode('.', $a->name)); - $files[] = array( - 'text' => $a->lang.$a->path.$a->name, - 'id' => '/'.$a->lang.$a->path.$a->name, - 'leaf' => true, - 'cls' => 'file', - 'extension' => $ext, - 'type' => 'file', - 'from' => 'search' - ); - } - return $files; - } - - /** - * Get all files from the local copy. - * - * @param $dir The root folder to retrieve files/folders from. - * @return Array of file info (TODO: remove extjs dependent info) - */ - public function getFilesByDirectory($dir) - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - $vcsLogin = $am->vcsLogin; - $anonymousIdent = $am->anonymousIdent; - - // Security - $dir = str_replace('..', '', $dir); - if (substr($dir, -1) != '/') $dir .= '/'; - - $m = $this->getModifies(); - - // Test if this dir exist - if( !is_dir($appConf[$project]['vcs.path'].$dir) ) { - return; - } - - $d = dir($appConf[$project]['vcs.path'].$dir); - - $files = array(); - - while ($f = $d->read()) - { - // We display only 'en', 'LANG' tree - if ( $dir == '/' - && $f != 'en' - && $f != $appConf[$project]['entities.folder'] - && $f != $am->vcsLang - ) { - continue; // skip non-en and non-user-lang - } - - if ( $f == '.' - || $f == '..' - || substr($f, 0, 1) == '.' // skip hidden files - || substr($f, -4) == '.new' // skip work files - || $f == 'CVS' - ) continue; - - if (is_dir($appConf[$project]['vcs.path'].$dir.$f)) { - - $files[] = array( - 'text' => $f, - 'id' => $dir.$f, - 'cls' => 'folder', - 'type' => 'folder', - 'allowDrag' => false - ); - - } else { - - $testedPath = ltrim($dir.$f, "/"); - - //echo $testedPath."\n"; - - $isModified = ( isset($m[$testedPath]) ) ? $m[$testedPath] : false ; - - if ( $isModified ) { - - if( $isModified['user'] == $vcsLogin && $isModified['anonymousIdent'] == $anonymousIdent ) { - $cls = 'file fileModifiedByMe'; - } else { - $cls = 'file fileModifiedByAnother'; - } - - - } else { - $cls = 'file'; - } - - $ext = array_pop(explode('.',$f)); - $files[] = array( - 'text' => $f, - 'id' => $dir.$f, - 'leaf' => true, - 'cls' => $cls, - 'extension' => $ext, - 'type' => 'file' - ); - } - } - $d->close(); - - return $files; - } - - /** - * Get a static value from DB - * - * @param $type The type of this value - * @param $field The name of the field for this value - * @return The value. - */ - public static function getStaticValue($type, $field) - { - - // Save in DB - $s = 'SELECT id, value FROM staticValue WHERE - `project` = "%s" AND - `type` = "%s" AND - `field`= "%s"'; - $params = array( - AccountManager::getInstance()->project, - $type, - $field - ); - - $r = DBConnection::getInstance()->query($s, $params); - - if( $r->num_rows == 0 ) { - return false; - } else { - $a = $r->fetch_object(); - return json_decode($a->value); - } - } -} - -?> +conn = DBConnection::getInstance(); + } + + + /** + * Get lst info dateTime about this apps + * + * @return The date/time of the last Info + */ + public function getLastInfoDate() + { + $am = AccountManager::getInstance(); + $project = $am->project; + + $s = 'SELECT + `date` + FROM + `staticValue` + WHERE + `project` = "%s" AND + `type`="info" + ORDER BY `date` DESC + LIMIT 0, 1'; + $params = array($am->project); + + $r = $this->conn->query($s, $params); + + $a = $r->fetch_assoc(); + + return $a['date']; + } + + /** + * Get infos about this apps + * + * @return Array + */ + public function getInfos($start, $limit) + { + $am = AccountManager::getInstance(); + $project = $am->project; + + $infos = array(); + + $s = 'SELECT + count(*) as total + FROM + `staticValue` + WHERE + `project` = "%s" AND + `type`="info"'; + $params = array($am->project); + + $r = $this->conn->query($s, $params); + + $a = $r->fetch_assoc(); + $infos['total'] = $a['total']; + + $s = 'SELECT + `field`, `value`, `date` + FROM + `staticValue` + WHERE + `project` = "%s" AND + `type`="info" + ORDER BY `date` DESC + LIMIT %d, %d'; + $params = array($am->project, (int)$start, (int)$limit); + + $r = $this->conn->query($s, $params); + + $i=0; + while ($a = $r->fetch_assoc()) { + $infos['value'][$i]['id'] = $i; + $infos['value'][$i]['field'] = $a['field']; + $infos['value'][$i]['value'] = json_decode($a['value']); + $infos['value'][$i]['date'] = $a['date']; + $infos['value'][$i]['elapsedTime'] = elapsedTime($a['date'], @date("Y-m-d H:i:s")); + $i++; + } + + return $infos; + } + + public function getSkeletonsNames() + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + $return = array(); + + if( !isset($appConf[$project]['skeletons.folder']) ) { + return $return; + } + + $dir = realpath($appConf[$project]['skeletons.folder']); + $d = dir($dir); + while (false !== ($entry = $d->read())) { + if( is_file($dir."/".$entry) && substr($entry, 0, 1) != "." ) { + $return[] = Array("name" => $entry, "path" => $dir."/".$entry); + } + } + $d->close(); + + sort($return); + return $return; + } + + /** + * Get all modified files with user lang or en. + * + * @return An associated array containing informations about modified files. + */ + public function getModifies() + { + $am = AccountManager::getInstance(); + + $s = 'SELECT + * + FROM + `work` + WHERE + `project` = "%s" AND + ( `lang`="%s" OR `lang`="en" ) '; + $params = array( + $am->project, + $am->vcsLang + ); + + $r = $this->conn->query($s, $params); + + $infos = array(); + while ($a = $r->fetch_assoc()) { + $infos[$a['lang'].$a['path'].$a['name']] = $a; + } + + return $infos; + } + + /** + * Get modified files by id. + * + * @param $id Can be a single id or an array of id + * @return An associated array containing informations about modified files specified by param id. + */ + public function getModifiesById($id) + { + $am = AccountManager::getInstance(); + $infos = array(); + + $ids = is_array($id) ? implode(array_map('intval', $id), ',') : (int)$id; + + if( empty( $ids ) ) { + return $infos; + } + + $s = 'SELECT + * + FROM + `work` + WHERE + `project` = "%s" AND + (`lang`="%s" OR `lang`="en" OR `lang`="doc-base") AND `id` IN (%s)'; + + $params = array( + $am->project, + $am->vcsLang, + $ids + ); + + $r = $this->conn->query($s, $params); + + while ($a = $r->fetch_assoc()) { + $infos[] = $a; + } + + return $infos; + } + + + public function getNbPendingUpdate() + { + $am = AccountManager::getInstance(); + + $vcsLang = $am->vcsLang; + $project = $am->project; + + $s = 'SELECT + count(*) as total + FROM + `files` + WHERE + `project` = "%s" AND + `lang` = "%s" AND + `revision` != `en_revision` AND + `status` is not null'; + $params = array( + $project, + $vcsLang + ); + $r = $this->conn->query($s, $params); + $a = $r->fetch_object(); + + return ( $a->total > $am->userConf->needUpdate->nbDisplay && $am->userConf->needUpdate->nbDisplay != 0 ) ? $am->userConf->needUpdate->nbDisplay : $a->total; + + } + /** + * Get all files witch need to be updated. + * + * @return An associated array containing information about files which need to be updated. + */ + public function getPendingUpdate() + { + $am = AccountManager::getInstance(); + + $vcsLang = $am->vcsLang; + $project = $am->project; + + $limit = ( $am->userConf->needUpdate->nbDisplay ) ? 'LIMIT '.(int)$am->userConf->needUpdate->nbDisplay : ''; + + $m = $this->getModifies(); + + $s = 'SELECT + * + FROM + `files` + WHERE + `project`="%s" AND + `lang` = "%s" AND + `revision` != `en_revision` AND + `status` is not NULL + %s'; + $params = array( + $project, + $vcsLang, + $limit + ); + $r = $this->conn->query($s, $params); + + $node = array(); + while ($a = $r->fetch_object()) { + + if ( isset($m[$vcsLang.$a->path.$a->name]) + ) { + + $isModifiedLang = ( isset($m[$vcsLang.$a->path.$a->name]) ) ? $m[$vcsLang.$a->path.$a->name] : false ; + + if ( $isModifiedLang ) { + $new_en_revision = $a->en_revision; + $new_revision = $isModifiedLang['en_revision']; + $original_revision = $a->revision; + $new_maintainer = $isModifiedLang['maintainer']; + } + + $node[] = array( + "id" => $a->id, + "path" => $a->path, + "name" => $a->name, + "revision" => $new_revision, + "original_revision" => $original_revision, + "en_revision" => $new_en_revision, + "maintainer" => $new_maintainer, + "fileModifiedEN" => false, + "fileModifiedLang" => ( $isModifiedLang ) ? '{"user":"'.$isModifiedLang["user"].'", "anonymousIdent":"'.$isModifiedLang["anonymousIdent"].'"}' : false + ); + } else { + $node[] = array( + "id" => $a->id, + "path" => $a->path, + "name" => $a->name, + "revision" => $a->revision, + "original_revision" => NULL, + "en_revision" => $a->en_revision, + "maintainer" => $a->maintainer, + "fileModifiedEN" => false, + "fileModifiedLang" => false + ); + } + } + return array('nb' => $r->num_rows, 'node' => $node); + } + + public function getNbPendingReview() + { + $am = AccountManager::getInstance(); + + $vcsLang = $am->vcsLang; + $project = $am->project; + + $m = $this->getModifies(); + $s = 'SELECT + count(*) as total + FROM + `files` + WHERE + `project`="%s" AND + `lang` = "%s" AND + reviewed != \'yes\''; + $params = array( + $project, + $vcsLang + ); + $r = $this->conn->query($s, $params); + $a = $r->fetch_object(); + + return ( $a->total > $am->userConf->reviewed->nbDisplay && $am->userConf->reviewed->nbDisplay != 0 ) ? $am->userConf->reviewed->nbDisplay : $a->total; + } + /** + * Get all files witch need to be reviewed. + * + * @return An associated array containing informations about files which need to be reviewed. + */ + public function getPendingReview() + { + $am = AccountManager::getInstance(); + + $vcsLang = $am->vcsLang; + $project = $am->project; + + $limit = ( $am->userConf->reviewed->nbDisplay ) ? 'LIMIT '.(int)$am->userConf->reviewed->nbDisplay : ''; + + $m = $this->getModifies(); + $s = 'SELECT + * + FROM + `files` + WHERE + `project`="%s" AND + `lang` = "%s" AND + reviewed != \'yes\' + ORDER BY + `path`, + `name` + %s'; + $params = array( + $project, + $vcsLang, + $limit + ); + $r = $this->conn->query($s, $params); + + $node = array(); + while ($a = $r->fetch_object()) { + + + $isModifiedLang = ( isset($m[$vcsLang.$a->path.$a->name]) ) ? $m[$vcsLang.$a->path.$a->name] : false ; + + $temp = array( + "id" => $a->id, + "path" => $a->path, + "name" => $a->name, + ); + + if ( $isModifiedLang ) + { + $new_reviewed = $isModifiedLang['reviewed']; + $new_maintainer = $isModifiedLang['reviewed_maintainer']; + + $temp['reviewed'] = $new_reviewed; + $temp['maintainer'] = $new_maintainer; + $temp['fileModifiedEN'] = false; + $temp['fileModifiedLang'] = ( $isModifiedLang ) ? '{"user":"'.$isModifiedLang["user"].'", "anonymousIdent":"'.$isModifiedLang["anonymousIdent"].'"}' : false; + } else { + $temp['reviewed'] = $a->reviewed; + $temp['maintainer'] = $a->reviewed_maintainer; + $temp['fileModifiedEN'] = false; + $temp['fileModifiedLang'] = false; + } + $node[] = $temp; + } + return array('nb' => $r->num_rows, 'node' => $node); + } + + public function getNbNotInEn() + { + $am = AccountManager::getInstance(); + $vcsLang = $am->vcsLang; + $project = $am->project; + + $s = 'SELECT + count(*) as total + FROM + `files` + WHERE + `project`="%s" AND + `lang`="%s" AND + `status`="NotInEN"'; + $params = array( + $project, + $vcsLang + ); + + $r = $this->conn->query($s, $params); + $a = $r->fetch_object(); + + return $a->total; + } + /** + * Get all files which are not in EN tree. + * + * @return An associated array containing informations about files which are not in EN tree + */ + public function getNotInEn() + { + $am = AccountManager::getInstance(); + $vcsLang = $am->vcsLang; + $project = $am->project; + + $m = $this->getModifies(); + + $s = 'SELECT + `id`, + `path`, + `name` + FROM + `files` + WHERE + `project`="%s" AND + `lang`="%s" AND + `status`="NotInEN"'; + $params = array( + $project, + $vcsLang + ); + + $r = $this->conn->query($s, $params); + + $node = array(); + while ($a = $r->fetch_object()) { + + $isModified = ( isset($m[$vcsLang.$a->path.$a->name]) ) ? $m[$vcsLang.$a->path.$a->name] : false ; + + $node[] = array( + "id" => $a->id, + "path" => $a->path, + "name" => $a->name, + "fileModified" => ( $isModified ) ? '{"user":"'.$isModified["user"].'", "anonymousIdent":"'.$isModified["anonymousIdent"].'"}' : false + ); + } + + return array('nb' => $r->num_rows, 'node' => $node); + } + + public function getNbPendingTranslate() + { + $am = AccountManager::getInstance(); + $vcsLang = $am->vcsLang; + $project = $am->project; + + $s = 'SELECT + count(*) as total + FROM + `files` + WHERE + `project`="%s" AND + `lang`="%s" AND + `status` is NULL AND + `revision` is NULL'; + $params = array( + $project, + $vcsLang + ); + + $r = $this->conn->query($s, $params); + $a = $r->fetch_object(); + + return ( $a->total > $am->userConf->newFile->nbDisplay && $am->userConf->newFile->nbDisplay != 0 ) ? $am->userConf->newFile->nbDisplay : $a->total; + } + + /** + * Get all files which need to be translated + * + * @return An associated array containing informations about files which need to be translated + */ + public function getPendingTranslate() + { + $am = AccountManager::getInstance(); + + $vcsLang = $am->vcsLang; + $project = $am->project; + + $limit = ( $am->userConf->newFile->nbDisplay ) ? 'LIMIT '.(int)$am->userConf->newFile->nbDisplay : ''; + + $m = $this->getModifies(); + $s = 'SELECT + `id`, `path`, `name` + FROM + `files` + WHERE + `project`="%s" AND + `lang`="%s" AND + `status` is NULL AND + `revision` is NULL + %s'; + + $params = array( + $project, + $vcsLang, + $limit + ); + + $r = $this->conn->query($s, $params); + + $node = array(); + while ($a = $r->fetch_object()) { + + $isModified = ( isset($m[$vcsLang.$a->path.$a->name]) ) ? $m[$vcsLang.$a->path.$a->name] : false ; + + $node[] = array( + "id" => $a->id, + "path" => $a->path, + "name" => $a->name, + "fileModified" => ( $isModified ) ? '{"user":"'.$isModified["user"].'", "anonymousIdent":"'.$isModified["anonymousIdent"].'"}' : false + ); + } + + return array('nb' => $r->num_rows, 'node' => $node); + } + + + // TODO : Deprecated + public function getNbPendingPatch() + { + $am = AccountManager::getInstance(); + $vcsLang = $am->vcsLang; + $project = $am->project; + + $s = 'SELECT + count(*) as total + FROM + `pendingPatch` + WHERE + `project`="%s" AND + (`lang`="%s" OR `lang`=\'en\')'; + $params = array( + $project, + $vcsLang + ); + + $r = $this->conn->query($s, $params); + $a = $r->fetch_object(); + + return $a->total; + } + + /** + * TODO : deprecated + * + * Get all pending patch. + * + * @return An associated array containing informations about pending patch. + */ + public function getPendingPatch() + { + $am = AccountManager::getInstance(); + $vcsLang = $am->vcsLang; + $project = $am->project; + + $s = 'SELECT `id`, CONCAT(`lang`, `path`) AS `path`, `name`, `posted_by` AS \'by\', `uniqID`, `date` FROM `pendingPatch` WHERE `project`="%s" AND (`lang`="%s" OR `lang`=\'en\')'; + $params = array( + $project, + $vcsLang + ); + $r = $this->conn->query($s, $params); + + $node = array(); + while ($row = $r->fetch_assoc()) { + $node[] = $row; + } + + return array('nb' => $r->num_rows, 'node' => $node); + } + + + /** + * Get all folders pending for commit. + * + * @return An associated array containing paths of folders pending for commit, or FALSE if there is no folder to commit. + */ + public function getPendingFoldersCommit() + { + $am = AccountManager::getInstance(); + $vcsLang = $am->vcsLang; + $project = $am->project; + + $s = 'SELECT * FROM `work` WHERE `project`="%s" AND (`lang`="%s" OR `lang`=\'en\') AND `name`=\'-\' ORDER BY id ASC'; + $params = array( + $project, + $vcsLang + ); + + $r = $this->conn->query($s, $params); + + if( $r->num_rows == 0 ) { + return false; + } + + $paths = array(); + while ($a = $r->fetch_object()) { + + $obj = (object) array('lang' => $a->lang, 'path' => $a->path, 'name'=> '-'); + + $paths[$a->lang.$a->path] = $obj; + } + + return $paths; + } + + // TODO : deprecated + public function getNbPendingCommit() + { + $am = AccountManager::getInstance(); + $vcsLang = $am->vcsLang; + $project = $am->project; + + // We exclude item witch name == '-' ; this is new folder ; We don't display it. + $s = 'SELECT count(*) as total FROM `pendingCommit` WHERE `project`="%s" AND (`lang`="%s" OR `lang`=\'en\') AND `name` != \'-\''; + $params = array( + $project, + $vcsLang + ); + + $r = $this->conn->query($s, $params); + $a = $r->fetch_object(); + + return $a->total; + } + + + /** + * Get all files in Work module (progress work and patches for review). + * Actually only used in scripts/cron/send_work_to_list.php + * + * @return An associated array containing informations about files in work + */ + public function getRawWork($lang) + { + $am = AccountManager::getInstance(); + $project = $am->project; + + /**** We start by the work in progress module ****/ + + // We exclude item witch name == '-' ; this is new folder ; We don't display it. + $s = 'SELECT + CONCAT(`lang`, `path`, `name`) as filePath, + `user`, + `date`, + `type` + FROM + `work` + WHERE + `module` = "workInProgress" AND + `lang` = "%s" AND + `project` = "%s" + ORDER BY + type, date'; + $params = array( + $lang, + $project + ); + $r = $this->conn->query($s, $params); + + $workInProgress = Array('nb'=>0,'data'=>Array()); + + if( $r->num_rows != 0 ) + { + $workInProgress['nb'] = $r->num_rows; + while ($a = $r->fetch_array(MYSQLI_ASSOC)) { + $workInProgress['data'][] = $a; + } + } + + /**** then, by the patches for review module ****/ + + // We exclude item witch name == '-' ; this is new folder ; We don't display it. + $s = 'SELECT + CONCAT(`lang`, `path`, `name`) as filePath, + `user`, + `date`, + `type` + FROM + `work` + WHERE + `module` = "PatchesForReview" AND + `lang` = "%s" AND + `project` = "%s" + ORDER BY + type, date'; + $params = array( + $lang, + $project + ); + $r = $this->conn->query($s, $params); + + $PatchesForReview = Array('nb'=>0,'data'=>Array()); + + if( $r->num_rows != 0 ) + { + $PatchesForReview['nb'] = $r->num_rows; + while ($a = $r->fetch_array(MYSQLI_ASSOC)) { + $PatchesForReview['data'][] = $a; + } + } + + // We return the result now + return Array( + "total" => ($workInProgress['nb'] + $PatchesForReview['nb']), + "workInProgress" => $workInProgress, + "PatchesForReview" => $PatchesForReview + ); + } + + /** + * Check is a patch don't contain any files + * + * + * @return TRUE if this patch is empty, FALSE either. + * @see RepositoryFetcher::getWork + */ + private function _isEmptyPatch($patchs) + { + $isEmpty = true; + + while( list($patch, $dataPatch) = each($patchs)) + { + while( list($folder, $dataFiles) = each($dataPatch['folders'])) + { + $isEmpty = false; + } + } + return $isEmpty; + } + + + /** + * Get all files in Work module (progress work or patches for review). + * + * @return An associated array containing informations about files in work + */ + public function getWork($module) + { + $am = AccountManager::getInstance(); + $vcsLang = $am->vcsLang; + $project = $am->project; + $vcsLogin = $am->vcsLogin; + $anonymousIdent = $am->anonymousIdent; + + $node = array(); + + if( $module == 'PatchesForReview' ) { + + // We exclude item witch name == '-' ; this is new folder ; We don't display it. + $s = 'SELECT + `id`, + `name` as patchName, + `description` as patchDescription, + `email` as patchEmail, + `user`, + `anonymousIdent`, + `date` + FROM + `patches` + WHERE + `project` = "%s"'; + $params = array( + $project + ); + $r = $this->conn->query($s, $params); + + $patches = Array(); + + while ($a = $r->fetch_object()) { + + $desc = $a->patchDescription; + $desc = str_replace("\n", '\n', $desc); + $desc = str_replace("\r", '\r', $desc); + $desc = str_replace("\t", '\t', $desc); + $desc = str_replace("'", "\'", $desc); + + $a->patchName = str_replace("'", "\'", $a->patchName); + + $patches[$a->id] = Array( + "user" => $a->user, + "patchName" => $a->patchName, + "patchDescription" => $desc, + "patchEmail" => $a->patchEmail + ); + + $node[$a->user.'@|@'.$a->anonymousIdent][$a->patchName]['idDB'] = $a->id; + $node[$a->user.'@|@'.$a->anonymousIdent][$a->patchName]['date'] = $a->date; + $node[$a->user.'@|@'.$a->anonymousIdent][$a->patchName]['folders'] = array(); + } + + // Bugfix: if we don't have any patches, the query below will fail. + // So we return immediately if that's the case. + if (empty($patches)) + return '[]'; + + // Do we need to display EN Work ? + if( isset($am->userConf->main->displayENWork) && $am->userConf->main->displayENWork === true ) { + $langFilter = '(`lang` = "%s" OR `lang`="en" OR `lang`="doc-base")'; + } else { + $langFilter = '(`lang` = "%s" OR `lang`="doc-base")'; + } + + // We exclude item witch name == '-' ; this is new folder ; We don't display it. + $s = 'SELECT + * + FROM + `work` + WHERE + `project` = "%s" AND + '.$langFilter.' AND + `name` != "-" AND + `module` = "%s" AND + `patchID` IN (%s)'; + $params = array( + $project, + $vcsLang, + $module, + implode(",", array_map('intval', array_keys($patches))) + ); + + $r = $this->conn->query($s, $params); + + while ($a = $r->fetch_object()) { + + $node[$a->user.'@|@'.$a->anonymousIdent][$patches[$a->patchID]["patchName"]]['idDB'] = $a->patchID; + $node[$a->user.'@|@'.$a->anonymousIdent][$patches[$a->patchID]["patchName"]]['folders'][$a->lang.$a->path][] = Array( + "name" => $a->name, + "last_modified" => $a->date, + "type" => $a->type, + "idDB" => $a->id + ); + + } + + $result = '['; + + // We format the result node to pass to ExtJs TreeGrid component + while( list($user, $patchs) = each($node)) { + + // $userInfo[0] => login + // $userInfo[1] => anonymousIdent + $userInfo = explode('@|@',$user); + $userDetails = $am->getUserDetails($userInfo[0], $userInfo[1]); + + // If the current user is not me and if all of his patch are empty, we don't send it - feature request ##60299 + if( $this->_isEmptyPatch($patchs) && !( $userInfo[0] == $vcsLogin && $userInfo[1] == $anonymousIdent ) ) { continue; } + + // Get authService from anonymousIdent + $tmp = explode('-', $userInfo[1]); + if( isset($tmp[1]) ) $authService = $tmp[0]; + else $authService = false; + + if( $authService == 'google' ) { + $iconUser = 'iconGoogle'; + } else if( $authService == 'facebook' ) { + $iconUser = 'iconFacebook'; + } else { + $iconUser = 'iconUser'; + } + + if( $userInfo[0] == $vcsLogin && $userInfo[1] == $anonymousIdent ) { + $expanded = 'true'; + } else { + $expanded = 'false'; + } + + $email = $am->getUserEmail($userInfo[0], $userInfo[1]); + $email = ($email) ? $email : 'false'; + + // We start by users + $result .= "{task:'".$userInfo[0]."',type:'user',userID:'".$userDetails->userID."',isAnonymous:".(($am->anonymous($userInfo[0], $userInfo[1])) ? 'true' : 'false').",email:'".$email."', iconCls:'".$iconUser."',expanded:".$expanded.",children:["; + + // We now walk into patches for this users. + while( list($patch, $dataPatch) = each($patchs)) { + + // If the current user is not me and if all of his patch are empty, we don't send it - feature request ##60299 + if( empty($dataPatch['folders']) && !( $userInfo[0] == $vcsLogin && $userInfo[1] == $anonymousIdent )) { continue; } + + $result .= "{task:'".$patch."',type:'patch',iconCls:'iconPatch',patchDescription:'".((isset($patches[$dataPatch["idDB"]]["patchDescription"])) ? $patches[$dataPatch["idDB"]]["patchDescription"] : '' )."',patchEmail:'".((isset($patches[$dataPatch["idDB"]]["patchEmail"])) ? $patches[$dataPatch["idDB"]]["patchEmail"] : '' )."',expanded:true,creationDate:'".( (isset($dataPatch["date"])) ? $dataPatch["date"] : '' )."',draggable: false, idDB:".$dataPatch["idDB"].", children:["; + + // We now walk into the folders for this patch + while( list($folder, $dataFiles) = each($dataPatch['folders'])) { + $result .= "{task:'".$folder."',type:'folder',iconCls:'iconFolderOpen',expanded:true,children:["; + + // We now walk into the files for this folder + while( list($file, $data) = each($dataFiles)) { + + // Witch iconCls do we need to use ? + switch ($data["type"]) { + case 'delete': + $iconCls = 'iconTrash'; + + break; + case 'new': + $iconCls = 'iconNewFiles'; + + break; + case 'update': + $iconCls = 'iconRefresh'; + + break; + + default: + $iconCls = 'task'; + break; + } + + $result .= "{task:'".$data["name"]."',type:'".$data["type"]."',last_modified:'".$data["last_modified"]."',leaf:true,iconCls:'".$iconCls."', idDB:".$data["idDB"]."},"; + + } + + $result .= ']},'; + + } + + $result .= ']},'; + } + + $result .= ']},'; + } + $result .= ']'; + + // We skip trailing comma + $result = str_replace("},]", "}]", $result); + + return $result; + + } // End if module == PatchesForReview + + + if( $module == 'workInProgress' ) { + + // Do we need to display EN Work ? + if( $am->userConf->main->displayENWork ) { + $langFilter = '(`lang` = "%s" OR `lang`="en" OR `lang`="doc-base")'; + } else { + $langFilter = '(`lang` = "%s" OR `lang`="doc-base")'; + } + + + // We exclude item witch name == '-' ; this is new folder ; We don't display it. + $s = 'SELECT + * + FROM + `work` + WHERE + `project` = "%s" AND + '.$langFilter.' AND + `name` != "-" AND + `module` = "%s" AND + `patchID` IS NULL'; + $params = array( + $project, + $vcsLang, + $module + ); + $r = $this->conn->query($s, $params); + + while ($a = $r->fetch_object()) { + + $node[$a->user.'@|@'.$a->anonymousIdent][$a->lang.$a->path][] = Array( + "name" => $a->name, + "last_modified" => $a->date, + "progress" => $a->progress, + "type" => $a->type, + "idDB" => $a->id + ); + } + + $result = '['; + // We format the result node to pass to ExtJs TreeGrid component + while( list($user, $dataFolders) = each($node)) { + + // $userInfo[0] => login + // $userInfo[1] => anonymousIdent + $userInfo = explode('@|@',$user); + $userDetails = $am->getUserDetails($userInfo[0], $userInfo[1]); + + // Get authService from anonymousIdent + $tmp = explode('-', $userInfo[1]); + if( isset($tmp[1]) ) $authService = $tmp[0]; + else $authService = false; + + if( $authService == 'google' ) { + $iconUser = 'iconGoogle'; + } else if( $authService == 'facebook' ) { + $iconUser = 'iconFacebook'; + } else { + $iconUser = 'iconUser'; + } + + if( $userInfo[0] == $vcsLogin && $userInfo[1] == $anonymousIdent ) { + $expanded = 'true'; + } else { + $expanded = 'false'; + } + + $email = $am->getUserEmail($userInfo[0], $userInfo[1]); + $email = ($email) ? $email : 'false'; + + // We put nbFiles into user's nodes to not have to count it by the client + $result .= "{task:'".$userInfo[0]."',type:'user',userID:'".$userDetails->userID."',isAnonymous:".(($am->anonymous($userInfo[0], $userInfo[1])) ? 'true' : 'false').",email:'".$email."', iconCls:'".$iconUser."',expanded:".$expanded.",children:["; + + // We now walk into the folders for this users + while( list($folder, $dataFiles) = each($dataFolders)) { + $result .= "{task:'".$folder."',type:'folder',iconCls:'iconFolderOpen',expanded:true,children:["; + + // We now walk into the files for this folder + while( list($file, $data) = each($dataFiles)) { + + // Witch iconCls do we need to use ? + switch ($data["type"]) { + case 'delete': + $iconCls = 'iconTrash'; + + break; + case 'new': + $iconCls = 'iconNewFiles'; + + break; + case 'update': + $iconCls = 'iconRefresh'; + + break; + + default: + $iconCls = 'task'; + break; + } + + $result .= "{task:'".$data["name"]."',type:'".$data["type"]."',last_modified:'".$data["last_modified"]."',leaf:true,iconCls:'".$iconCls."',progress:".$data["progress"].", idDB:".$data["idDB"]."},"; + } + + $result .= ']},'; + } + + + $result .= ']},'; + + } + $result .= ']'; + + // We skip trailing comma + $result = str_replace("},]", "}]", $result); + + return $result; + + } // End if module == workInProgress + } + + /** + * Get all files for a given php's extension. Can be exclusive for php project +TODO: Handle project here + * + * @param $ext The name of the extension. + * @return An array of files + */ + public function getFilesByExtension($ext) + { + $am = AccountManager::getInstance(); + $vcsLang = $am->vcsLang; + $project = $am->project; + + $s = 'SELECT `path`, `name` FROM `files` WHERE `path` + LIKE \'/reference/%s/%%\' AND `lang`="%s" AND `project`="%s" ORDER BY `path`, `name`'; + $params = array( + $ext, $vcsLang, $project + ); + $r = $this->conn->query($s, $params); + + $node = array(); $i=0; + while ($a = $r->fetch_object()) { + $node[$i]['path'] = $a->path; + $node[$i]['name'] = $a->name; + + $i++; + } + return $node; + } + + /** + * Get a file regarding its xml ID. + * + * @param $lang The lang of the searched file. + * @param $id The ID of the searched file. + * @return file info include lang, path, name + */ + public function getFileByXmlID($lang, $id) + { + $project = AccountManager::getInstance()->project; + + // If user forget ".php" at this end of the permlink, this is "function" how is search into DB. + // We don't allow it, neither blank ID + if( $id == 'function' || empty($id) ) { + return false; + } + + // We start by searching file witch only this ID + $s = 'SELECT + `lang`, `path`, `name` + FROM + `files` + WHERE + `project`="%s" AND + `lang` = "%s" AND + `xmlid` = "%s"'; + $params = array( + $project, + $lang, + $id + ); + $r = $this->conn->query($s, $params); + $nb = $r->num_rows; + + if( $nb >= 1 ) { + return $r->fetch_object(); + } else { + + // We now search file which contain this ID + $s = 'SELECT + `lang`, `path`, `name` + FROM + `files` + WHERE + `project`="%s" AND + `lang` = "%s" AND + `xmlid` LIKE "%%%s%%"'; + $params = array( + $project, + $lang, + $id + ); + $r = $this->conn->query($s, $params); + $nb = $r->num_rows; + + if( $nb == 0 ) { + return false; + } else { + return $r->fetch_object(); + } + + } + } + + /** + * Perform searching on filepath under the repository tree + * + * @param $key Keyword for search + * @return Array of file info (TODO: remove extjs dependent info) + */ + public function getFileByKeyword($key) + { + $am = AccountManager::getInstance(); + $vcsLang = $am->vcsLang; + $project = $am->project; + + $s = 'SELECT `lang`, `path`, `name` FROM `files` WHERE `project`="%s" AND (`lang`="%s" OR `lang`=\'en\') + AND ( `name` LIKE \'%%%s%%\' OR `xmlid` LIKE \'%%%s%%\' ) ORDER BY `lang`, `path`, `name`'; + $params = array( + $project, + $vcsLang, + $key, + $key + ); + $r = $this->conn->query($s, $params); + + $files = array(); + while ($a = $r->fetch_object()) { + $ext = array_pop(explode('.', $a->name)); + $files[] = array( + 'text' => $a->lang.$a->path.$a->name, + 'id' => '/'.$a->lang.$a->path.$a->name, + 'leaf' => true, + 'cls' => 'file', + 'extension' => $ext, + 'type' => 'file', + 'from' => 'search' + ); + } + return $files; + } + + /** + * Get all files from the local copy. + * + * @param $dir The root folder to retrieve files/folders from. + * @return Array of file info (TODO: remove extjs dependent info) + */ + public function getFilesByDirectory($dir) + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + $vcsLogin = $am->vcsLogin; + $anonymousIdent = $am->anonymousIdent; + + // Security + $dir = str_replace('..', '', $dir); + if (substr($dir, -1) != '/') $dir .= '/'; + + $m = $this->getModifies(); + + // Test if this dir exist + if( !is_dir($appConf[$project]['vcs.path'].$dir) ) { + return; + } + + $d = dir($appConf[$project]['vcs.path'].$dir); + + $files = array(); + + while ($f = $d->read()) + { + // We display only 'en', 'LANG' tree + if ( $dir == '/' + && $f != 'en' + && $f != $appConf[$project]['entities.folder'] + && $f != $am->vcsLang + ) { + continue; // skip non-en and non-user-lang + } + + if ( $f == '.' + || $f == '..' + || substr($f, 0, 1) == '.' // skip hidden files + || substr($f, -4) == '.new' // skip work files + || $f == 'CVS' + ) continue; + + if (is_dir($appConf[$project]['vcs.path'].$dir.$f)) { + + $files[] = array( + 'text' => $f, + 'id' => $dir.$f, + 'cls' => 'folder', + 'type' => 'folder', + 'allowDrag' => false + ); + + } else { + + $testedPath = ltrim($dir.$f, "/"); + + //echo $testedPath."\n"; + + $isModified = ( isset($m[$testedPath]) ) ? $m[$testedPath] : false ; + + if ( $isModified ) { + + if( $isModified['user'] == $vcsLogin && $isModified['anonymousIdent'] == $anonymousIdent ) { + $cls = 'file fileModifiedByMe'; + } else { + $cls = 'file fileModifiedByAnother'; + } + + + } else { + $cls = 'file'; + } + + $ext = array_pop(explode('.',$f)); + $files[] = array( + 'text' => $f, + 'id' => $dir.$f, + 'leaf' => true, + 'cls' => $cls, + 'extension' => $ext, + 'type' => 'file' + ); + } + } + $d->close(); + + return $files; + } + + /** + * Get a static value from DB + * + * @param $type The type of this value + * @param $field The name of the field for this value + * @return The value. + */ + public static function getStaticValue($type, $field) + { + + // Save in DB + $s = 'SELECT id, value FROM staticValue WHERE + `project` = "%s" AND + `type` = "%s" AND + `field`= "%s"'; + $params = array( + AccountManager::getInstance()->project, + $type, + $field + ); + + $r = DBConnection::getInstance()->query($s, $params); + + if( $r->num_rows == 0 ) { + return false; + } else { + $a = $r->fetch_object(); + return json_decode($a->value); + } + } +} + +?> diff --git a/php/RepositoryManager.php b/php/RepositoryManager.php index b4079bf5..792bdf07 100644 --- a/php/RepositoryManager.php +++ b/php/RepositoryManager.php @@ -1,2168 +1,2168 @@ - Array('code' => 'ar', 'iconCls' => 'flags flag-ar', 'name' => 'Arabic'), - 1 => Array('code' => 'pt_BR', 'iconCls' => 'flags flag-pt_BR', 'name' => 'Brazilian Portuguese'), - 2 => Array('code' => 'bg', 'iconCls' => 'flags flag-bg', 'name' => 'Bulgarian'), - 3 => Array('code' => 'zh', 'iconCls' => 'flags flag-zh', 'name' => 'Chinese (Simplified)'), - 4 => Array('code' => 'hk', 'iconCls' => 'flags flag-hk', 'name' => 'Chinese (Hong Kong Cantonese)'), - 5 => Array('code' => 'tw', 'iconCls' => 'flags flag-tw', 'name' => 'Chinese (Traditional)'), - 6 => Array('code' => 'cs', 'iconCls' => 'flags flag-cz', 'name' => 'Czech'), - 7 => Array('code' => 'da', 'iconCls' => 'flags flag-da', 'name' => 'Danish'), - 8 => Array('code' => 'nl', 'iconCls' => 'flags flag-nl', 'name' => 'Dutch'), - 9 => Array('code' => 'en', 'iconCls' => 'flags flag-en', 'name' => 'English'), - 10 => Array('code' => 'fi', 'iconCls' => 'flags flag-fi', 'name' => 'Finnish'), - 11 => Array('code' => 'fr', 'iconCls' => 'flags flag-fr', 'name' => 'French'), - 12 => Array('code' => 'de', 'iconCls' => 'flags flag-de', 'name' => 'German'), - 13 => Array('code' => 'el', 'iconCls' => 'flags flag-el', 'name' => 'Greek'), - 14 => Array('code' => 'he', 'iconCls' => 'flags flag-he', 'name' => 'Hebrew'), - 15 => Array('code' => 'hu', 'iconCls' => 'flags flag-hu', 'name' => 'Hungarian'), - 16 => Array('code' => 'it', 'iconCls' => 'flags flag-it', 'name' => 'Italian'), - 17 => Array('code' => 'ja', 'iconCls' => 'flags flag-ja', 'name' => 'Japanese'), - 18 => Array('code' => 'kr', 'iconCls' => 'flags flag-kr', 'name' => 'Korean'), - 19 => Array('code' => 'no', 'iconCls' => 'flags flag-no', 'name' => 'Norwegian'), - 20 => Array('code' => 'fa', 'iconCls' => 'flags flag-fa', 'name' => 'Persian'), - 21 => Array('code' => 'pl', 'iconCls' => 'flags flag-pl', 'name' => 'Polish'), - 22 => Array('code' => 'pt', 'iconCls' => 'flags flag-pt', 'name' => 'Portuguese'), - 23 => Array('code' => 'ro', 'iconCls' => 'flags flag-ro', 'name' => 'Romanian'), - 24 => Array('code' => 'ru', 'iconCls' => 'flags flag-ru', 'name' => 'Russian'), - 25 => Array('code' => 'sr', 'iconCls' => 'flags flag-rs', 'name' => 'Serbian'), - 26 => Array('code' => 'sk', 'iconCls' => 'flags flag-sk', 'name' => 'Slovak'), - 27 => Array('code' => 'sl', 'iconCls' => 'flags flag-sl', 'name' => 'Slovenian'), - 28 => Array('code' => 'es', 'iconCls' => 'flags flag-es', 'name' => 'Spanish'), - 29 => Array('code' => 'sv', 'iconCls' => 'flags flag-se', 'name' => 'Swedish'), - 30 => Array('code' => 'tr', 'iconCls' => 'flags flag-tr', 'name' => 'Turkish') - ); - - public $existingLanguage = array(); - - private function __construct() - { - $this->conn = DBConnection::getInstance(); - } - - public function getAvailableLanguage() - { - return $this->availableLang; - } - - public function computeExistingLanguage() - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - $this->existingLanguage = array(); - - for( $i=0; $i < count($this->availableLang); $i++ ) { - if( is_dir($appConf[$project]['vcs.path'].$this->availableLang[$i]['code'].'/') ) { - $this->existingLanguage[] = $this->availableLang[$i]; - } - } - - return $this->existingLanguage; - } - - public function getExistingLanguage() - { - if( !isset($this->existingLanguage) || count($this->existingLanguage) == 0 ) { - $this->computeExistingLanguage(); - } - - return $this->existingLanguage; - } - - /** - * Check if a lang is valide or not. - * @param $lang The lang to check - * @return Return true if $lang is a valid language, false otherwise. - */ - public function isValidLanguage($lang) - { - $existLanguage = $this->getExistingLanguage(); - - for( $i=0; $i < count($existLanguage); $i++ ) - { - if( $existLanguage[$i]['code'] == $lang ) { - return true; - } - } - return false; - - } - - - /** - * Checkout the phpdoc-all repository. - * This method must be call ONLY by the /firstRun.php script. - * - * @return An associative array{ 'err': svn co return code, 'output': svn co output contained in an array } - */ - public function checkoutRepository() - { - $project = AccountManager::getInstance()->project; - - $lock = new LockFile('project_' . $project . '_lock_checkout_repository'); - - $rtn = false; - if ($lock->lock()) { - // exec the checkout - $rtn = VCSFactory::getInstance()->checkout(); - } - - $lock->release(); - - return $rtn; - } - - /** - * CleanUp the dataBase before an Update. - * - * @see updateRepository - */ - public function cleanUp() - { - $project = AccountManager::getInstance()->project; - - // We cleanUp the database before update vcs and apply again all tools - foreach (array('files', 'translators', 'errorfiles') as $table) { - $this->conn->query("DELETE FROM `$table` WHERE `project`='%s'", array($project)); - $this->conn->query("OPTIMIZE TABLE `$table` ", array()); - } - } - - /** - * CleanUp the dataBase before check the build. - * We only stock in DB the last failed build on a month. - * - * @see checkBuild - */ - public function cleanUpBeforeCheckBuild() - { - $project = AccountManager::getInstance()->project; - - $this->conn->query("DELETE FROM `failedBuildLog` WHERE `project`= '%s' AND `date` < date_sub(now(),interval 1 month)", array($project)); - } - - - - - - /** - * Update the repository to sync our local copy. - * As this exec command take some time, we start by creating a lock file, then run the command, then delete this lock file. - * As it, we can test if this command has finish, or not. - */ - public function updateRepository() - { - $project = AccountManager::getInstance()->project; - - $lock = new LockFile('project_' . $project . '_lock_update_repository'); - - if ($lock->lock()) { - // exec the update - VCSFactory::getInstance()->update(); - } - - $lock->release(); - } - - /** - * Check the build of the documentation (using configure.php script). - * - * @param $lang The lang of the documentation we want to check the build. We must take out $lang to be able to use this method from cron script on multiple language - * @param $enable_xml_details Indicate whether the check cmd include xml-details option - * @return The output log. - */ - public function checkBuild($lang, $enable_xml_details="false") - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - $return = Array( - "state" => "ok", - "logContent" => "" - ); - - $appConf[$project]['vcs.configure.script.options'] = str_replace("{LangCode}", $lang, $appConf[$project]['vcs.configure.script.options']); - - if ( $enable_xml_details == "true" ) - { - $appConf[$project]['vcs.configure.script.options'] = str_replace("{XmlDetails}", "--enable-xml-details", $appConf[$project]['vcs.configure.script.options']); - } - else - { - $appConf[$project]['vcs.configure.script.options'] = str_replace("{XmlDetails}", "", $appConf[$project]['vcs.configure.script.options']); - } - - $commands = array( - new ExecStatement('cd %s', array(realpath($appConf[$project]['vcs.configure.script.path']))), - new ExecStatement($appConf['GLOBAL_CONFIGURATION']['php.bin'] . ' configure.php --with-php=' . $appConf['GLOBAL_CONFIGURATION']['php.bin'] . ' ' . $appConf[$project]['vcs.configure.script.options']) - ); - - $trial_threshold = 3; - while ($trial_threshold-- > 0) { - $output =array(); - SaferExec::execMulti($commands, $output); - if (strlen(trim(implode('', $output))) != 0) break; - } - - $return["logContent"] = $output; - - // We save the result of this check only if it failed. - if ( strstr(implode(" ", $output), 'Eyh man. No worries. Happ shittens. Try again after fixing the errors above.') || - strstr(implode(" ", $output), 'There were warnings loading the manual') ) - { - $return["state"] = "ko"; - } - - return $return; - } - - /** - * Register a file as a work in progress, into the database. - * - * @param $file The file object to be added into the database. - * @param $revision The revision of this file. - * @param $en_revision The EN revision of this file. - * @param $reviewed The stats of the reviewed tag. - * @param $reviewed_maintainer The maintainer of this reviewed work. - * @param $maintainer The maintainer. - * @param $type The type of work. Can be 'new' for new file, 'update' for an uptaded file, 'delete' for a file marked as delete. - * @return fileID of the file - */ - public function addProgressWork($file, $revision, $en_revision, $reviewed, $reviewed_maintainer, $maintainer, $type='update') - { - $am = AccountManager::getInstance(); - $vcsLogin = $am->vcsLogin; - $anonymousIdent = $am->anonymousIdent; - $project = $am->project; - - $s = 'SELECT - id - FROM - `work` - WHERE - `project`="%s" AND - `lang`="%s" AND - `path`="%s" AND - `name`="%s"'; - $params = array( - $project, - $file->lang, - $file->path, - $file->name - ); - $r = $this->conn->query($s, $params); - - // We insert or update the work table - if ($r->num_rows == 0) { - - $s = 'INSERT into - `work` - (`project`, `lang`, `path`, `name`, `revision`, `en_revision`, `reviewed`, `reviewed_maintainer`, `maintainer`, `user`, `anonymousIdent`, `date`, `type`) - VALUES - ("%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", now(), "%s")'; - $params = array( - $project, - $file->lang, - $file->path, - $file->name, - $revision, - $en_revision, - $reviewed, - $reviewed_maintainer, - $maintainer, - $vcsLogin, - $anonymousIdent, - $type - ); - $this->conn->query($s, $params); - $fileID = $this->conn->insert_id(); - - } else { - - $a = $r->fetch_object(); - - $s = 'UPDATE - `work` - SET - `revision`="%s", - `en_revision`="%s", - `reviewed`="%s", - `reviewed_maintainer`="%s", - `maintainer`="%s", - `user`="%s", - `anonymousIdent`="%s", - `date`=now(), - `module`="workInProgress", - `patchID` = NULL - WHERE - `id`="%s"'; - $params = array( - $revision, - $en_revision, - $reviewed, - $reviewed_maintainer, - $maintainer, - $am->vcsLogin, - $am->anonymousIdent, - $a->id - ); - $this->conn->query($s, $params); - $fileID = $a->id; - } - - return $fileID; - } - - /** - * Delete files from work in progress module. - * - * @param $files An array of File instances. - */ - public function delWork($files) - { - $am = AccountManager::getInstance(); - $project = $am->project; - - while( list($path, $data) = each($files)) - { - $query = 'DELETE FROM `work` - WHERE - `project` = "%s" AND - `lang` = "%s" AND - `path` = "%s" AND - `name` = "%s"'; - $params = array( - $project, - $data->lang, - $data->path, - $data->name - ); - $this->conn->query($query, $params); - } - } - - /** - * Move some files into a specific patch. - * - * @param $patchID The DB Id of the patch - * @param $filesID A comma separated list of files's Id - * @return true - */ - public function moveToPatch($patchID, $filesID) - { - $am = AccountManager::getInstance(); - $vcsLogin = $am->vcsLogin; - $project = $am->project; - - $s = 'SELECT - `name` - FROM - `patches` - WHERE - `project` = "%s" AND - `id` = "%s" AND - `user` = "%s"'; - $params = array( - $project, - $patchID, - $vcsLogin - ); - $r = $this->conn->query($s, $params); - - if( $this->conn->affected_rows() == 0 ) { - return 'Patches unknow for this project or for this user'; - } - - $s = 'UPDATE - `work` - SET - `patchID` = "%s", - `module` = "PatchesForReview" - WHERE - `project` = "%s" AND - `user` = "%s" AND - `id` IN (%s)'; - $params = array( - $patchID, - $project, - $vcsLogin, - implode(',', array_map('intval', explode(',', $filesID))) - ); - $r = $this->conn->query($s, $params); - - if( $this->conn->affected_rows() < 1 ) { - return 'Error. Is this file(s) is(are) own by you ?'; - } else { - return true; - } - - } - - /** - * Move some files into work in progress module. - * - * @param $filesID A comma separated list of files's Id - * @return true - */ - public function moveToWork($filesID) - { - $am = AccountManager::getInstance(); - $vcsLogin = $am->vcsLogin; - $project = $am->project; - - $s = 'UPDATE - `work` - SET - `patchID` = NULL, - `module` = "workInProgress" - WHERE - `project` = "%s" AND - `user` = "%s" AND - `id` IN (%s)'; - - $params = array( - $project, - $vcsLogin, - implode(',', array_map('intval', explode(',', $filesID))) - ); - $r = $this->conn->query($s, $params); - - if( $this->conn->affected_rows() < 1 ) { - return 'Error. Is this file(s) is(are) own by you ?'; - } else { - return true; - } - - } - - /** - * Delete a patch. - * - * @param $patchID The ID of the patch we want to delete - * @return true - */ - public function deletePatch($patchID) - { - $am = AccountManager::getInstance(); - $vcsLogin = $am->vcsLogin; - $project = $am->project; - - // We start by retrieve patch information - $patchInfo = $this->getPatchInfo($patchID); - - if( !$patchInfo ) { - return 'patch_delete_dont_exist'; // the patch don't exist - } else { - - // We must check if we can delete this patch - // Either this patch must be own by the current user or the current user is a global admin for this project - if( $patchInfo->user != $am->vcsLogin || ( $am->isAnonymous && ($patchInfo->anonymousIdent != $am->anonymousIdent) ) ) { - if( ! $am->isAdmin() ) { - return 'patch_delete_isnt_own_by_current_user'; - } - } - } - - // We start by change files for this patch. - $s = 'UPDATE - `work` - SET - `patchID` = NULL, - `module` = "workInProgress" - WHERE - `project` = "%s" AND - `patchID` = %d'; - $params = array( - $project, - $patchID - ); - $this->conn->query($s, $params); - - // We now delete this patch - $s = 'DELETE FROM - `patches` - WHERE - `project` = "%s" AND - `id` = %d'; - $params = array( - $project, - $patchID - ); - $this->conn->query($s, $params); - - return true; - } - - /** - * Get information about a patch by his ID. - * - * @param $patchID The ID of this patch - * @return An associative array containing informations about this patch, or false if no patch exist for this ID - */ - public function getPatchInfo($patchID) - { - $am = AccountManager::getInstance(); - $vcsLogin = $am->vcsLogin; - $project = $am->project; - - $s = 'SELECT - * - FROM - `patches` - WHERE - `id` = "%s"'; - $params = array( - $patchID - ); - $r = $this->conn->query($s, $params); - - if( $r->num_rows == 0 ) { - return false; - } else { - return $r->fetch_object(); - } - } - - /** - * Get all files from a patch by his ID. - * - * @param $patchID The ID of this patch - * @return An associative array containing files about this patch, or false if no patch exist for this ID - */ - public function getPatchFilesByID($patchID) - { - $am = AccountManager::getInstance(); - $vcsLogin = $am->vcsLogin; - $project = $am->project; - - $s = 'SELECT - * - FROM - `work` - WHERE - `module` = \'PatchesForReview\' AND - `patchID` = "%s"'; - - $params = array( - $patchID - ); - $r = $this->conn->query($s, $params); - - if( $r->num_rows == 0 ) { - return false; - } else { - $return = array(); - while( $a = $r->fetch_object() ) { - $return[] = $a; - } - - return $return; - } - } - - /** - * Create a new patch for the current user. - * - * @param $name The name for this new patch - * @param $description The description for this patch - * @param $email Email to be warn when the patch is commited - * @return true - */ - public function createPatch($name, $description, $email) - { - $am = AccountManager::getInstance(); - $vcsLogin = $am->vcsLogin; - $project = $am->project; - - $s = 'INSERT INTO - `patches` - (`project`, `name`, `description`, `email`, `user`, `anonymousIdent`, `date`) - VALUES - ("%s", "%s", "%s", "%s", "%s", "%s", now())'; - $params = array( - $project, - $name, - $description, - $email, - $vcsLogin, - $am->anonymousIdent - ); - $this->conn->query($s, $params); - - return $this->conn->insert_id(); - - } - - /** - * Modify the patch name for the current user. - * @param $patchID The ID of the patch we want to modify - * @param $name The new name for this patch - * @param $description The description for this patch - * @param $email Email to be warn when the patch is commited - * @return true - */ - public function modPatch($patchID, $name, $description, $email) - { - $am = AccountManager::getInstance(); - $vcsLogin = $am->vcsLogin; - $project = $am->project; - - $s = 'UPDATE - `patches` - SET - `name` = "%s", - `description` = "%s", - `email` = "%s" - WHERE - `project` = "%s" AND - `user` = "%s" AND - `id` = %d'; - $params = array( - $name, - $description, - $email, - $project, - $vcsLogin, - $patchID - ); - $this->conn->query($s, $params); - - if( $this->conn->affected_rows() != 1 ) { - return 'Error'; - } else { - return true; - } - } - - /** - * Mark a file as pending delete. - * - * @param $file File instance - * @return Array of info include record_id, request_user, date - */ - public function addPendingDelete($file) - { - $am = AccountManager::getInstance(); - $vcsLogin = $am->vcsLogin; - $project = $am->project; - $anonymousIdent = $am->anonymousIdent; - - $date = @date("Y-m-d H:i:s"); - - $s = 'INSERT INTO - `work` - (`project`, `lang`, `path`, `name`, `revision`, `en_revision`, `reviewed`, `maintainer`, `user`, `anonymousIdent`, `date`, `type`) - VALUES - ("%s", "%s", "%s", "%s", "-", "-", "-", "-", "%s", "%s", "%s", "delete")'; - $params = array( - $project, - $file->lang, - $file->path, - $file->name, - $vcsLogin, - $anonymousIdent, - $date - ); - $this->conn->query($s, $params); - - return array( - 'id' => $this->conn->insert_id(), - 'by' => Array("user"=> $vcsLogin, "anonymousIdent" => $anonymousIdent), - 'date' => $date - ); - } - - // not tested - public function fastUpdate() - { - if ($changed_files = VCSFactory::getInstance()->fastUpdate()) { - - foreach (array_merge($changed_files['create'], $changed_files['update']) as $path) { - $path = explode('/', $path, 2); - $file = new File($path[0], $path[1]); - - - $tmp = Array($file); - $this->delWork($tmp); - - // We must now insert information into the app for this file - $this->addFileInfo($tmp); - } - foreach ($changed_files['update'] as $path) { - $path = explode('/', $path, 2); - $file = new File($path[0], $path[1]); - - // Delete from work table - $tmp = Array($file); - $this->delWork($tmp); - - // We must now update information into the app for this file - $this->updateFileInfo($tmp); - } - foreach ($changed_files['delete'] as $path) { - $path = explode('/', $path, 2); - $file = new File($path[0], $path[1]); - - // Delete this new file from the fileSystem - @unlink($file->full_new_path); - - // Delete from work table - $this->delWork(array($file)); - } - } - } - - /** - * Update the VCS for each file we try to commit before start the commit processus. - * As it, we ensure all VCS conflict. - * - * @param $files All files to check - * @param $type Type of this file. Can be "new", "update", or "delete" - * @return Return the stack of files we must commit. All files which can't be commited have been deleted from this stack. - */ - public function beforeCommitChanges($files, $type) - { - $stack = Array(); - - if ($files) { - switch($type) { - - case 'new' : - - // For new files, we must ensure that this file is steel non exist into the repository before commit it. - for( $i=0; $i < count($files); $i++ ) { - if( !$files[$i]->exist() ) { - // This file still not exist in current respository, we can commit it - $stack[] = $files[$i]; - } - } - - break; - - case 'update' : - - // For update files, we must ensure that this file haven't been modified since last big update - for( $i=0; $i < count($files); $i++ ) { - - // We get the filemtime for this file to compare with the filemtime after the update. - $oldTime = filemtime($files[$i]->full_path); - if( $files[$i]->exist() ) { - // If this file haven't been deleted since last update - $newTime = filemtime($files[$i]->full_path); - if( $newTime == $oldTime ) { - // This file haven't been modified since last update. - // We can continue the commit processus for it - $stack[] = $files[$i]; - } - - } - - } - - break; - - case 'delete' : - - // For deleted files, we must ensure that this file is steel exist into the repository before commit it. - for( $i=0; $i < count($files); $i++ ) { - - if( $files[$i]->exist() ) { - // This file still exists in current respository, we can commit it for delete - $stack[] = $files[$i]; - } - - } - - break; - } - } - - return $stack; - - } - - public function ensureFoldersExists($folders) - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - while( list($folderPath, $data) = each($folders) ) { - - if( ! is_dir($appConf[$project]['vcs.path'].$folderPath) ) { - - mkdir( $appConf[$project]['vcs.path'].$folderPath, 0777, true ); - - } - } - } - - - /** - * Get only Folders we need to commit according to chosen files - * - * @param $folders An array of folders that are in work queue - * @param $l$filesog An array of files chosen to be commited - * @return An associated array similar of $folders params, but contained only folders witch need to be commited for this files - */ - public function getOnlyFoldersForFiles($folders, $files) { - - if( !$folders ) { - return false; - } - - $return = array(); - - function parsePath($path, &$pathInfo) { - - $pathInfo[$path] = 1; - $t = explode("/",$path); - array_pop($t); - - if( count($t) != 0 ) { parsePath(implode("/", $t), $pathInfo); } - - } - - // We walk trow files to find folders to commit - for( $i=0; $i < count($files); $i++) { - - $filePath = $files[$i]['lang'].$files[$i]['path']; - - $pathInfo = array(); - parsePath($filePath, $pathInfo); - - // We walk trow folders pending commit - reset($folders); - while( list($folderPath, $data) = each($folders) ) { - - // We search for path in folder path. If we find it, we add this folder into $return var - - if( isset($pathInfo[$folderPath]) ) { - $return[$folderPath] = $data; - } - - } - - } - return $return; - } - - // file level backup only - private function backupCommit($files, $type) - { - switch ($type) { - case 'new': break; // do nothing for new file - case 'update': - // backup actual file as .bak as .new will replace the actual file soon - for ($i=0; $i < count($files); $i++) { - @copy($files[$i]->full_path, $files[$i]->full_path.'.bak'); - } - break; - case 'delete': break; // do nothing for delete file - } - } - - // file level rollback only - private function rollbackCommit($files, $type) - { - switch ($type) { - case 'new': - // actual file is created in commit process, remove it - for ($i=0; $i < count($files); $i++) { - @unlink($files[$i]->full_path); - } - break; - case 'update': - // rollback actual file from .bak and remove .bak - for ($i=0; $i < count($files); $i++) { - @copy($files[$i]->full_path.'.bak', $files[$i]->full_path); - @unlink($files[$i]->full_path.'.bak'); - } - break; - case 'delete': break; // do nothing for delete file - } - } - - // file level changes only - private function afterCommitChanges($files, $type) - { - switch ($type) { - case 'new': - // remove file in -new folder - for ($i=0; $i < count($files); $i++) { - @unlink($files[$i]->full_new_path); - } - break; - case 'update': - // remove file in -new folder - for ($i=0; $i < count($files); $i++) { - @unlink($files[$i]->full_new_path); - @unlink($files[$i]->full_path.'.bak'); - } - break; - case 'delete': break; // do nothing for delete file - } - } - - /** - * Commit file changes to repository. - * - * @param $ids An array of files' id to be commited. - * @param $log The message log to use with this commit. - * @return An associated array. The key "commitResponse" contains the response from the CVS server after commit (with HTML highlight) and the key "anode", the list of files witch have been really commited. - */ - public function commitChanges($ids, $log) - { - $rf = RepositoryFetcher::getInstance(); - $commitLog = Array(); - - // Get informations about files we need to commit - $fileInfos = $rf->getModifiesById($ids); - - // Task for folders - $foldersInfos = $rf->getPendingFoldersCommit(); - - // We filter this folders to return only this who want to commit according of files array - $foldersInfos = $this->getOnlyFoldersForFiles($foldersInfos, $fileInfos); - - if( $foldersInfos ) { - - // We must create this folder before commit it - $this->ensureFoldersExists($foldersInfos); - - $c = VCSFactory::getInstance()->commitFolders($foldersInfos); - $commitLog = array_merge($commitLog, $c); - $this->delWork($foldersInfos); - } - - // Task for files - // Loop over $fileInfos to find files to be create, update or delete - $create_stack = array(); - $update_stack = array(); - $delete_stack = array(); - - for( $i=0; $i < count($fileInfos); $i++) { - $f = new File( - $fileInfos[$i]['lang'], - $fileInfos[$i]['path'].$fileInfos[$i]['name'] - ); - switch ($fileInfos[$i]['type']) { - case 'new' : $create_stack[] = $f; break; - case 'update' : $update_stack[] = $f; break; - case 'delete' : $delete_stack[] = $f; break; - } - } - - // Before commit, we need to update all files and find if there haven't been modified since last update process - $this->fastUpdate(); - $create_stack = $this->beforeCommitChanges($create_stack, 'new'); - $update_stack = $this->beforeCommitChanges($update_stack, 'update'); - $delete_stack = $this->beforeCommitChanges($delete_stack, 'delete'); - - // keep copy for commit failure recovery - $this->backupCommit($create_stack, 'new'); - $this->backupCommit($update_stack, 'update'); - $this->backupCommit($delete_stack, 'delete'); - - $c = VCSFactory::getInstance()->commit( - $log, $create_stack, $update_stack, $delete_stack - ); - - $commitLog = array_merge($commitLog, $c['output']); - - // html highlight commit log - $reg = array( - '/(Adding )/', - '/(Sending )/', - '/(Deleting )/', - '/(Transmitting file data)/', - '/(Committed revision)/', - '/(A )/', - '/(D )/', - '/(property )/', - '/( set on )/' - ); - - $commitLog = preg_replace( - $reg, - '$1', - $commitLog - ); - - if (0 != $c['err']) { - // error found in commit, rollback commit operation - $this->rollbackCommit($create_stack, 'new'); - $this->rollbackCommit($update_stack, 'update'); - $this->rollbackCommit($delete_stack, 'delete'); - - } else { - // We fetch again the file which have been commited. All file which have been skip from beforeCommitChanges aren't in DB for now. - $fileInfos = $rf->getModifiesById($ids); - - $ids = array(); - // Get all ids which have been really commited - for( $i=0; $i < count($fileInfos); $i ++ ) { - $ids[] = $fileInfos[$i]['id']; - } - - // confirmed commit success. batch delete pending commit, and remove backup - $this->afterCommitChanges($create_stack, 'new'); - $this->afterCommitChanges($update_stack, 'update'); - $this->afterCommitChanges($delete_stack, 'delete'); - } - - return array( - 'err' => $c['err'], - 'commitResponse' => $commitLog, - 'anode' => $ids - ); - } - - /** - * Set the progress for a file in work table. - * - * @param $idDB The type of the file. Can be 'update', 'delete' or 'new' - * @param $progress The File instance of the file. - * @return TRUE if the progress have been saved succesfully, false otherwises - */ - public function SetFileProgress($idDB, $progress) - { - $am = AccountManager::getInstance(); - $project = $am->project; - $vcsLogin = $am->vcsLogin; - $anonymousIdent = $am->anonymousIdent; - - // We start by get the current row - $s = 'SELECT - `user`, - `anonymousIdent` - FROM - `work` - WHERE - `project` = "%s" AND - `id` = %d'; - $params = array( - $project, - $idDB - ); - $r = $this->conn->query($s, $params); - - if( $r->num_rows == 0 ) { - return 'file_dont_exist_in_workInProgress'; - } else { - - $a = $r->fetch_object(); - - if( !($a->user == $vcsLogin && $a->anonymousIdent == $anonymousIdent) ) { - return 'file_isnt_owned_by_current_user'; - } - } - - $s = 'UPDATE - `work` - SET - `progress` = "%s" - WHERE - `project` = "%s" AND - `user` = "%s" AND - `anonymousIdent` = "%s" AND - `id` = %d'; - $params = array( - $progress, - $project, - $vcsLogin, - $anonymousIdent, - $idDB - ); - $this->conn->query($s, $params); - - return true; - } - - /** - * clear local change of a file. - * - * @param $type The type of the file. Can be 'update', 'delete' or 'new' - * @param $file The File instance of the file. - * @return An array which contain informations about this file. - */ - public function clearLocalChange($type, $file) - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - $lang = $file->lang; - $path = $file->path; - $name = $file->name; - - // Initiate return's var - $return = array(); - $return['rev'] = 0; - $return['en-rev'] = 0; - $return['maintainer'] = 0; - $return['reviewed'] = 0; - $return['errorState'] = false; - $return['errorFirst'] = 0; - - // We need select row from work table - $s = "SELECT - `id`, - `user`, - `anonymousIdent` - FROM - `work` - WHERE - `project` = '%s' AND - `lang` = '%s' AND - `path` = '%s' AND - `name` = '%s'"; - $params = array( - $project, - $lang, - $path, - $name - ); - - $r = $this->conn->query($s, $params); - - if( $r->num_rows == 0 ) { - - return 'file_localchange_didnt_exist'; - - } else { - $a = $r->fetch_object(); - - // Rules to allow clearLocalChange or not. - // Either the user who made the modification, either a global admin for this project, either a lang admin - if( $a->user != $am->vcsLogin || ( $am->isAnonymous && ($a->anonymousIdent != $am->anonymousIdent) ) ) { - // This file isn't own by the current user - - // Is the current user is a global admin or a lang admin ? - if( ! $am->isAdmin(true) ) { - if( !(!$am->isAnonymous && $am->anonymous($a->user, $a->anonymousIdent) ) ) { - return 'file_isnt_owned_by_current_user'; - } - } - } - - } - - $return['oldIdDB'] = $a->id; - - // We need delete row from work table - $s = 'DELETE FROM `work` WHERE `id`=%d'; - $params = array($a->id); - $this->conn->query($s, $params); - - // If type == delete, we stop here and return - if ($type == 'delete') { - return $return; - } - - // We need delete file on filesystem (for new & update) - @unlink($file->full_new_path); - - // If type == new, we stop here and return - if ($type == 'new') { - return $return; - } - - // We need check for error in this file - $en_content = file_get_contents($appConf[$project]['vcs.path'].'en' .$path.$name); - $lang_content = file_get_contents($appConf[$project]['vcs.path'].$lang.$path.$name); - - $info = $file->getInfo($lang_content); - $anode[0] = array( - 'lang' => $lang, - 'path' => $path, - 'name' => $name, - 'en_content' => $en_content, - 'lang_content' => $lang_content, - 'maintainer' => $info['maintainer'] - ); - - $errorTools = new ToolsError(); - $error = $errorTools->updateFilesError($anode, 'nocommit'); - - // We need reload original information - $s = "SELECT `revision`, `en_revision`, `maintainer`, `reviewed` FROM `files` - WHERE `project`='%s' AND `lang`='%s' AND `path`='%s' AND `name`='%s'"; - $params = array($project, $lang, $path, $name); - $r = $this->conn->query($s, $params); - $a = $r->fetch_object(); - - $return['rev'] = $a->revision; - $return['en-rev'] = $a->en_revision; - $return['maintainer'] = $a->maintainer; - $return['reviewed'] = $a->reviewed; - - if (isset($error['first'])) { - $return['errorState'] = true; - $return['errorFirst'] = $error['first']; - } else { - $return['errorState'] = false; - $return['errorFirst'] = '-No error-'; - } - - // We return original lang_revision & maintainer - return $return; - } - - /** - * Set the last update datetime into DB - * @param $type Can be "data" or "entities" - */ - public function setLastUpdate($type) - { - $am = AccountManager::getInstance(); - $vcsLogin = $am->vcsLogin; - $project = $am->project; - - $vcsLogin = isset($vcsLogin) - ? $vcsLogin : '-'; - - $value = array(); - $value['date'] = @date("Y-m-d H:i:s"); - $value['by'] = $vcsLogin; - - $this->setStaticValue('last_update_'.$type, '-', json_encode($value)); - } - - /** - * Update information about a file after commit (update informations added with revcheck tools). - * - * @param $files An array of File instances for info update. - */ - public function updateFileInfo($files) - { - - $am = AccountManager::getInstance(); - - foreach ($files as $file) { - - $info = $file->getInfo(); - $size = intval(filesize($file->full_path) / 1024); - $date = filemtime($file->full_path); - - if ($file->lang == 'en') { // en file - // update EN file info - $s = 'UPDATE `files` - SET - `xmlid` = "%s", - `revision` = "%s", - `size` = "%s", - `mdate` = "%s" - WHERE - `project` = "%s" AND - `lang` = "%s" AND - `path` = "%s" AND - `name` = "%s"'; - $params = array( - $info['xmlid'], $info['rev'], $size, $date, $am->project, $file->lang, $file->path, $file->name - ); - $this->conn->query($s, $params); - - // update LANG file info - $s = 'UPDATE `files` - SET - `en_revision` = "%s" - WHERE - `project` = "%s" AND - `lang` != "%s" AND - `path` = "%s" AND - `name` = "%s"'; - $params = array( - $info['rev'], $am->project, $file->lang, $file->path, $file->name - ); - $this->conn->query($s, $params); - - } else { // lang file - - // If this file don't exist in EN, we should skip all this proces - $en = new File('en', $file->path.$file->name); - - if( $en->exist() ) { - - $enInfo = $en->getInfo(); - - $sizeEN = intval(filesize($en->full_path) / 1024); - $dateEN = filemtime($en->full_path); - - $size_diff = $sizeEN - $size; - $date_diff = (intval((time() - $dateEN) / 86400)) - - (intval((time() - $date) / 86400)); - - // update LANG file info - $s = 'UPDATE `files` - SET - `xmlid` = "%s", - `revision` = "%s", - `en_revision`= "%s", - `reviewed` = "%s", - `reviewed_maintainer` = "%s", - `size` = "%s", - `mdate` = "%s", - `maintainer` = "%s", - `status` = "%s", - `size_diff` = "%s", - `mdate_diff` = "%s" - WHERE - `project` = "%s" AND - `lang` = "%s" AND - `path` = "%s" AND - `name` = "%s"'; - $params = array( - $info['xmlid'], - $info['en-rev'], - $enInfo['rev'], - trim($info['reviewed']), - trim($info['reviewed_maintainer']), - $size, - $date, - trim($info['maintainer']), - trim($info['status']), - $size_diff, - $date_diff, - $am->project, - $file->lang, - $file->path, - $file->name - ); - $this->conn->query($s, $params); - - // Run the errorTools under this file - $tmpFile[0]['en_content'] = $en->read(true); - $tmpFile[0]['lang_content'] = $file->read(true); - $tmpFile[0]['lang'] = $file->lang; - $tmpFile[0]['path'] = $file->path; - $tmpFile[0]['name'] = $file->name; - $tmpFile[0]['maintainer'] = $info['maintainer']; - - $errorTools = new ToolsError(); - $errorTools->updateFilesError($tmpFile); - - } else // This file exist only in LANG version, like translation.xml, for example - { - - // update LANG file info - $s = 'UPDATE `files` - SET - `xmlid` = "%s", - `revision` = "%s", - `en_revision`= "%s", - `reviewed` = "%s", - `reviewed_maintainer` = "%s", - `size` = "%s", - `mdate` = "%s", - `maintainer` = "%s", - `status` = "%s", - `size_diff` = "%s", - `mdate_diff` = "%s" - WHERE - `project` = "%s" AND - `lang` = "%s" AND - `path` = "%s" AND - `name` = "%s"'; - $params = array( - $info['xmlid'], - $info['en-rev'], - 0, - trim($info['reviewed']), - trim($info['reviewed_maintainer']), - $size, - $date, - trim($info['maintainer']), - trim($info['status']), - 0, - 0, - $am->project, - $file->lang, - $file->path, - $file->name - ); - $this->conn->query($s, $params); - - // Run the errorTools under this file - // If the EN file don't exist, it's because we have a file witch only exist into LANG, for example, translator.xml - // We fake the EN with the LANG content to fake the errorTools ;) - $tmpFile[0]['en_content'] = $file->read(true); - $tmpFile[0]['lang_content'] = $file->read(true); - $tmpFile[0]['lang'] = $file->lang; - $tmpFile[0]['path'] = $file->path; - $tmpFile[0]['name'] = $file->name; - $tmpFile[0]['maintainer'] = $info['maintainer']; - - $errorTools = new ToolsError(); - $errorTools->updateFilesError($tmpFile); - - } - } - } - } - public function addFileInfo($files) - { - - $am = AccountManager::getInstance(); - - foreach ($files as $file) { - - $info = $file->getInfo(); - $size = intval(filesize($file->full_path) / 1024); - $date = filemtime($file->full_path); - - if ($file->lang == 'en') { // en file - // update EN file info - $s = 'INSERT INTO `files` - SET - `xmlid` = "%s", - `revision` = "%s", - `size` = "%s", - `mdate` = "%s", - `project` = "%s", - `lang` = "%s", - `path` = "%s", - `name` = "%s"'; - $params = array( - $info['xmlid'], $info['rev'], $size, $date, $am->project, $file->lang, $file->path, $file->name - ); - $this->conn->query($s, $params); - - // update LANG file info - $s = 'UPDATE `files` - SET - `en_revision` = "%s" - WHERE - `project` = "%s" AND - `lang` != "%s" AND - `path` = "%s" AND - `name` = "%s"'; - $params = array( - $info['rev'], $am->project, $file->lang, $file->path, $file->name - ); - $this->conn->query($s, $params); - - } else { // lang file - - // If this file don't exist in EN, we should skip all this proces - $en = new File('en', $file->path.$file->name); - - if( $en->exist() ) { - - $enInfo = $en->getInfo(); - - $sizeEN = intval(filesize($en->full_path) / 1024); - $dateEN = filemtime($en->full_path); - - $size_diff = $sizeEN - $size; - $date_diff = (intval((time() - $dateEN) / 86400)) - - (intval((time() - $date) / 86400)); - - // update LANG file info - $s = 'INSERT INTO `files` - SET - `xmlid` = "%s", - `revision` = "%s", - `en_revision`= "%s", - `reviewed` = "%s", - `reviewed_maintainer` = "%s", - `size` = "%s", - `mdate` = "%s", - `maintainer` = "%s", - `status` = "%s", - `size_diff` = "%s", - `mdate_diff` = "%s", - `project` = "%s", - `lang` = "%s", - `path` = "%s", - `name` = "%s"'; - $params = array( - $info['xmlid'], - $info['en-rev'], - $enInfo['rev'], - trim($info['reviewed']), - trim($info['reviewed_maintainer']), - $size, - $date, - trim($info['maintainer']), - trim($info['status']), - $size_diff, - $date_diff, - $am->project, - $file->lang, - $file->path, - $file->name - ); - $this->conn->query($s, $params); - - // Run the errorTools under this file - $tmpFile[0]['en_content'] = $en->read(true); - $tmpFile[0]['lang_content'] = $file->read(true); - $tmpFile[0]['lang'] = $file->lang; - $tmpFile[0]['path'] = $file->path; - $tmpFile[0]['name'] = $file->name; - $tmpFile[0]['maintainer'] = $info['maintainer']; - - $errorTools = new ToolsError(); - $errorTools->updateFilesError($tmpFile); - - } else // This file exist only in LANG version, like translation.xml, for example - { - - // update LANG file info - $s = 'INSERT INTO `files` - SET - `xmlid` = "%s", - `revision` = "%s", - `en_revision`= "%s", - `reviewed` = "%s", - `reviewed_maintainer` = "%s", - `size` = "%s", - `mdate` = "%s", - `maintainer` = "%s", - `status` = "%s", - `size_diff` = "%s", - `mdate_diff` = "%s", - `project` = "%s", - `lang` = "%s", - `path` = "%s", - `name` = "%s"'; - $params = array( - $info['xmlid'], - $info['en-rev'], - 0, - trim($info['reviewed']), - trim($info['reviewed_maintainer']), - $size, - $date, - trim($info['maintainer']), - trim($info['status']), - 0, - 0, - $am->project, - $file->lang, - $file->path, - $file->name - ); - $this->conn->query($s, $params); - - // Run the errorTools under this file - // If the EN file don't exist, it's because we have a file witch only exist into LANG, for example, translator.xml - // We fake the EN with the LANG content to fake the errorTools ;) - $tmpFile[0]['en_content'] = $file->read(true); - $tmpFile[0]['lang_content'] = $file->read(true); - $tmpFile[0]['lang'] = $file->lang; - $tmpFile[0]['path'] = $file->path; - $tmpFile[0]['name'] = $file->name; - $tmpFile[0]['maintainer'] = $info['maintainer']; - - $errorTools = new ToolsError(); - $errorTools->updateFilesError($tmpFile); - - } - } - } - } - /** - * Read the translation's file which hold informations about all translators - * and put it into database. - */ - public function updateTranslatorInfo() - { - $ExistingLanguage = $this->getExistingLanguage(); - $am = AccountManager::getInstance(); - - foreach ($ExistingLanguage as $lang) { - - $lang = $lang["code"]; - $txml = false; - - // Path to find translation.xml file, set default values, - // in case we can't find the translation file - $translation_xml = new File($lang, '/translation.xml'); - - if ( file_exists($translation_xml->full_path) ) { - // Else go on, and load in the file, replacing all - // space type chars with one space - $txml = preg_replace('/\\s+/', ' ', $translation_xml->read(true)); - } - - if ( $txml ) { - // Find all persons matching the pattern - $matches = array(); - if (preg_match_all('!!U', $txml, $matches)) { - $default = array( - 'vcs' => 'n/a', - 'nick' => 'n/a', - 'editor' => 'n/a', - 'email' => 'n/a', - 'name' => 'n/a' - ); - $persons = $translation_xml->parseAttribute($matches[1]); - $charset = $translation_xml->getEncoding($txml); - - foreach ($persons as $person) { - - if ($charset == 'utf-8' ) { - $name = utf8_decode($person['name']); - } else { - $name = $person['name']; - } - - $person = array_merge($default, $person); - - // We try to remove this record if it exist - $query = 'DELETE FROM `translators` WHERE `project`="%s" AND `lang`="%s" AND `nick`="%s"'; - $params = array( - $am->project, - $lang, - $person['nick'] - ); - $this->conn->query($query, $params); - - $query = 'INSERT INTO `translators` (`project`, `lang`, `nick`, `name`, `mail`, `vcs`, `editor`) - VALUES ("%s", "%s", "%s", "%s", "%s", "%s", "%s")'; - $params = array( - $am->project, - $lang, - $person['nick'], - $name, - $person['email'], - $person['vcs'], - $person['editor'] - ); - $this->conn->query($query, $params); - - } - } - } - } - } - - /** - * Check is the File/Folder must be processed or not for certain operation. - * - * @param $file The checked File instance. - * @return True if the File/Folder must be processed, FALSE otherwise. - */ - private function needParsing($file) - { - $name = $file->name; - $path = $file->path; - - if( substr($name, -4) === '.new' ) { - $toDisplay = true; - } else { - $toDisplay = false; - } - - $return = "needParsing : \n"; - $return .= " => name : $name\n"; - $return .= " => path : $path\n"; - - if ( - !$file->exist() - || ( is_file($file->full_path) && !in_array(substr($name, -3), array('xml','ent')) ) - || substr($name, -13) == 'PHPEditBackup' - || strpos($name, 'entities.') === 0 - || $path == '/chmonly/' - || $path == '/internals/' - || $path == '/internals2/' - || $name == 'contributors.ent' - || $name == 'contributors.xml' - || ($path == '/appendices/' && ($name == 'reserved.constants.xml' || $name == 'extensions.xml')) - || $name == 'README' - || $name == 'DO_NOT_TRANSLATE' - || $name == 'rsusi.txt' - || $name == 'translation.xml' - || $name == 'missing-ids.xml' - || $name == 'license.xml' - || $name == 'versions.xml' - ) { - $return .= " FALSE !\n\n\n"; - if( $toDisplay ) echo $return; - return false; - } else { - $return .= " TRUE !\n\n\n"; - if( $toDisplay ) echo $return; - return true; - } - } - - /** - * Run doUpdateNotInEN() on every avaliable language. - * Check all files to see if the LANG files is present into EN tree or not. - */ - public function updateNotInEN() - { - $ExistingLanguage = $this->getExistingLanguage(); - - foreach ($ExistingLanguage as $lang) { - $this->doUpdateNotInEN('/', $lang["code"]); - } - } - /** - * Check all files to see if the LANG files is present into EN tree or not. - * - * @param $path The path to checking directory. - * @param $lang The tested lang. - */ - private function doUpdateNotInEN($path, $lang) - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - if ($dh = @opendir($appConf[$project]['vcs.path'].$lang.$path)) { - - $dirs = array(); - $files = array(); - - while (($name = readdir($dh)) !== false) { - - if( $name == '.' || $name == '..') { - continue; - } - - $file = new File($lang, $path.$name); - if (!$this->needParsing($file)) { - continue; - } - - if ( $file->isDir ) { - $dirs[] = $file; - } elseif ( $file->isFile ) { - $files[] = $file; - } - - } - @closedir($dh); - - foreach($files as $f) { - $en_file = $appConf[$project]['vcs.path'] .'en' .$f->path .$f->name; - $lang_file = $appConf[$project]['vcs.path'] .$lang .$f->path .$f->name; - - if (!@is_file($en_file)) { - $query = 'INSERT INTO `files` (`project`, `lang`, `path`, `name`, `status`) - VALUES ("%s", "%s", "%s", "%s", "%s")'; - $params = array( - $project, - $lang, $f->path, $f->name, 'NotInEN' - ); - $this->conn->query($query, $params); - } - } - - foreach ($dirs as $d) { - $this->doUpdateNotInEN($d->path.'/', $lang); - } - } - } - - /** - * Apply the Revcheck tools recursively on all lang - * - * @param $path The directory from which we start. - * @param $revType Can be 'new' when we start a new revcheck with a clean database or 'update' when we revcheck just one folder (and all is sub-folders). Default to 'new' - * @param $revLang The lang we want to apply the recheck. By default, it's 'all' lang available. - * @return Nothing. - */ - public function applyRevCheck($path = '/', $revType='new', $revLang='all') - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - if ($dh = @opendir($appConf[$project]['vcs.path'].'en'.$path)) { - - $dirs = array(); - $files = array(); - - while (($name = readdir($dh)) !== false) { - - if( $name == '.' || $name == '..') { - continue; - } - - $file = new File('en', $path.$name); - if (!$this->needParsing($file)) { - continue; - } - - if ( $file->isDir ) { - $dirs[] = $file; - } elseif ( $file->isFile ) { - $files[] = $file; - } - } - closedir($dh); - - foreach($files as $f) { - - $en_size = intval(filesize($f->full_path) / 1024); - $en_date = filemtime($f->full_path); - - $infoEN = $f->getInfo(); - $en_revision = ($infoEN['rev'] == 'NULL') ? 'NULL' : $infoEN['rev']; - $xmlid = ($infoEN['xmlid'] == 'NULL') ? 'NULL' : $infoEN['xmlid']; - - $tmp = explode('/', $f->path); - - // Only for Php project - if( $project == 'PHP' ) { - $check_doc = new ToolsCheckDoc(); - $ToolsCheckDocResult = $check_doc->checkDoc($infoEN['content'], $f->path); - } else { - $ToolsCheckDocResult['check_oldstyle'] = 'NULL'; - $ToolsCheckDocResult['check_undoc'] = 'NULL'; - $ToolsCheckDocResult['check_roleerror'] = 'NULL'; - $ToolsCheckDocResult['check_badorder'] = 'NULL'; - $ToolsCheckDocResult['check_noseealso'] = 'NULL'; - $ToolsCheckDocResult['check_noreturnvalues'] = 'NULL'; - $ToolsCheckDocResult['check_noparameters'] = 'NULL'; - $ToolsCheckDocResult['check_noexamples'] = 'NULL'; - $ToolsCheckDocResult['check_noerrors'] = 'NULL'; - } - - // If the type of this revcheck is an update, we start to remove all reference to this file from... - if( $revType == 'update' ) - { - //... table `files` - $query = 'DELETE FROM `files` - WHERE `project`="%s" AND - `lang`="en" AND - `path`="%s" AND - `name`="%s"'; - $params = array( - $am->project, $f->path, $f->name - ); - $this->conn->query($query, $params); - - //... table `errorfiles` - $query = 'DELETE FROM `errorfiles` - WHERE `project`="%s" AND - `lang`="en" AND - `path`="%s" AND - `name`="%s"'; - $params = array( - $am->project, $f->path, $f->name - ); - $this->conn->query($query, $params); - } - - // Sql insert. - $query = 'INSERT INTO `files` (`project`, `lang`, `xmlid`, `path`, `name`, `revision`, `size`, `mdate`, `maintainer`, `status`, `check_oldstyle`, `check_undoc`, `check_roleerror`, `check_badorder`, `check_noseealso`, `check_noreturnvalues`, `check_noparameters`, `check_noexamples`, `check_noerrors`) - VALUES ("%s", "en", "%s", "%s", "%s", "%s", "%s", "%s", NULL, NULL, "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s")'; - $params = array( - $am->project, - $xmlid, $f->path, $f->name, $en_revision, $en_size, $en_date, - $ToolsCheckDocResult['check_oldstyle'], - $ToolsCheckDocResult['check_undoc'], - $ToolsCheckDocResult['check_roleerror'], - $ToolsCheckDocResult['check_badorder'], - $ToolsCheckDocResult['check_noseealso'], - $ToolsCheckDocResult['check_noreturnvalues'], - $ToolsCheckDocResult['check_noparameters'], - $ToolsCheckDocResult['check_noexamples'], - $ToolsCheckDocResult['check_noerrors'] - ); - $this->conn->query($query, $params); - - $error = new ToolsError(); - $error->setParams($infoEN['content'], '', 'en', $f->path, $f->name, ''); - $error->run(); - $error->saveError(); - - - if( $revType == 'update' ) - { - // If we are in update, we have 2 case. $revLang can be en or LANG. - // If revLang is en, we must re-check all available language to reflect changes. - if( $revLang == 'en' ) { - $ExistingLanguage = $this->getExistingLanguage(); - } - // If revLang is LANG, we only re-check this LANG - else { - $ExistingLanguage[] = array("code" => $revLang); - } - } else { - // If this is not an update, we check all languages - $ExistingLanguage = $this->getExistingLanguage(); - } - - foreach($ExistingLanguage as $lang) { - - $lang = $lang["code"]; - - // We skip en language - if( $lang == 'en' ) { - continue; - } - - $lang_file = new File($lang, $f->path.$f->name); - - // If the type of this revcheck is an update, we start be delete all reference to this file in table... - if( $revType == 'update' ) - { - // ... `file` - $query = 'DELETE FROM `files` - WHERE `project`="%s" AND - `lang`="%s" AND - `path`="%s" AND - `name`="%s"'; - $params = array( - $project, $lang, $lang_file->path, $lang_file->name - ); - $this->conn->query($query, $params); - - //... table `errorfiles` - $query = 'DELETE FROM `errorfiles` - WHERE `project`="%s" AND - `lang`="%s" AND - `path`="%s" AND - `name`="%s"'; - $params = array( - $project, $lang, $lang_file->path, $lang_file->name - ); - $this->conn->query($query, $params); - } - - if ( $lang_file->exist() ) { - - // Initial revcheck method - $size = intval(filesize($lang_file->full_path) / 1024); - $date = filemtime($lang_file->full_path); - - $size_diff = $en_size - $size; - $date_diff = (intval((time() - $en_date) / 86400)) - (intval((time() - $date) / 86400)); - - $infoLANG = $lang_file->getInfo(); - $revision = ($infoLANG['en-rev'] == 'NULL') ? 'NULL' : $infoLANG['en-rev']; - $maintainer = ($infoLANG['maintainer'] == 'NULL') ? 'NULL' : $infoLANG['maintainer']; - $status = ($infoLANG['status'] == 'NULL') ? 'NULL' : $infoLANG['status']; - $xmlid = ($infoLANG['xmlid'] == 'NULL') ? 'NULL' : $infoLANG['xmlid']; - $reviewed = ($infoLANG['reviewed'] == 'NULL') ? 'NULL' : $infoLANG['reviewed']; - $reviewed_maintainer = ($infoLANG['reviewed_maintainer'] == 'NULL') ? 'NULL' : $infoLANG['reviewed_maintainer']; - - $query = 'INSERT INTO `files` (`project`, `lang`, `xmlid`, `path`, `name`, `revision`, `en_revision`, `reviewed`, `reviewed_maintainer`, `size`, `size_diff`, `mdate`, `mdate_diff`, `maintainer`, `status`) - VALUES ("%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s")'; - $params = array( - $project, - $lang, - $xmlid, - $lang_file->path, - $lang_file->name, - $revision, - $en_revision, - $reviewed, - $reviewed_maintainer, - $size, - $size_diff, - $date, - $date_diff, - $maintainer, - $status - ); - $this->conn->query($query, $params); - - // Check for error in this file ONLY if this file is uptodate - if ($revision == $en_revision && $revision != 0 ) { - $error = new ToolsError(); - $error->setParams( - $infoEN['content'], $infoLANG['content'], - $lang, $lang_file->path, $lang_file->name, $maintainer - ); - $error->run(); - $error->saveError(); - } - } else { - $query = 'INSERT INTO `files` (`project`, `lang`, `path`, `name`, `size`) - VALUES ("%s", "%s", "%s", "%s", "%s")'; - $params = array( - $project, - $lang, - $lang_file->path, - $lang_file->name, - $en_size - ); - $this->conn->query($query, $params); - } - } - } - - foreach ($dirs as $d) { - $this->applyRevCheck($d->path, $revType, $revLang); - } - } - } - - /** - * Remove a file from DB - * - * @param $files An array of File instances. - * @return Nothing. - */ - public function delFiles($files) - { - - for ($i = 0; $i < count($files); $i++) { - $query = 'DELETE FROM files - WHERE - `project` = "%s" AND - `lang` = "%s" AND - `path` = "%s" AND - `name` = "%s"'; - $params = array( - AccountManager::getInstance()->project, - $files[$i]->lang, $files[$i]->path, $files[$i]->name - ); - $this->conn->query($query, $params); - } - } - - /** - * Set a static value into DB - * - * @param $type The type of this value - * @param $field The name of the field for this value - * @param $value The value. Can be anything who can be store into a SQL TEXT field - * @param $forceNew TRUE to indicate that this value must be added e.g. not updated. By default, the value is updated. - * @return Nothing. - */ - public static function setStaticValue($type, $field, $value, $forceNew=false) - { - $project = AccountManager::getInstance()->project; - - $s = "SELECT id FROM staticValue WHERE - `project` = '%s' AND - `type` = '%s' AND - `field` = '%s' - "; - $params = array( - $project, - $type, - $field - ); - $r = DBConnection::getInstance()->query($s, $params); - - if( $r->num_rows == 0 || $forceNew) { - $s = "INSERT INTO staticValue (`project`, `type`, `field`, `value`, `date`) VALUES ('%s', '%s', '%s', '%s', now())"; - $params = array($project, $type, $field, $value); - DBConnection::getInstance()->query($s, $params); - } else { - $a = $r->fetch_object(); - $s = "UPDATE staticValue SET `value`= '%s', `date`=now() WHERE `id`=%d"; - $params = array($value, $a->id); - DBConnection::getInstance()->query($s, $params); - } - } - - public function applyStaticRevcheck() - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - $ExistingLanguage = $this->getExistingLanguage(); - - foreach( $ExistingLanguage as $lang ) { - - $lang = $lang["code"]; - if( $lang == 'en' ) { continue; } - - $commands = array( - new ExecStatement('cd %s', array($appConf[$project]['vcs.path'])), - new ExecStatement($appConf['GLOBAL_CONFIGURATION']['php.bin'] . ' doc-base/scripts/revcheck.php %s > %s 2>&1', array($lang, $appConf['GLOBAL_CONFIGURATION']['data.path'].'revcheck/'.$lang.'.html')) - ); - SaferExec::execMulti($commands); - } - } - - /** - * All we must do after a patch have been commited. - * - * @param $patchID ID of the patch. - */ - public function postPatchCommit($patchID) - { - $am = AccountManager::getInstance(); - $vcsLogin = $am->vcsLogin; - - // We get patch Information - $patchInfo = $this->getPatchInfo($patchID); - - // We silently return if the patch didn't exist - if( !$patchInfo ) return; - - $to = trim($patchInfo->email); - $subject = '['.$patchInfo->project.'-DOC] - Patch named "'.$patchInfo->name.'" accepted'; - $msg = <<email) && $patchInfo->user != $vcsLogin ) { - $am->email($to, $subject, $msg); - } - } - - /** - * Create the folder how hold all modified files for this project. - * - */ - public function initCreateFolderForModifiedFiles() - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - $folderPath = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new'; - - if( is_dir($folderPath) ) { - return false; // already exist - } else { - if( mkdir($folderPath) ) { - return true; - } else { - return false; - } - } - } -} - -?> + Array('code' => 'ar', 'iconCls' => 'flags flag-ar', 'name' => 'Arabic'), + 1 => Array('code' => 'pt_BR', 'iconCls' => 'flags flag-pt_BR', 'name' => 'Brazilian Portuguese'), + 2 => Array('code' => 'bg', 'iconCls' => 'flags flag-bg', 'name' => 'Bulgarian'), + 3 => Array('code' => 'zh', 'iconCls' => 'flags flag-zh', 'name' => 'Chinese (Simplified)'), + 4 => Array('code' => 'hk', 'iconCls' => 'flags flag-hk', 'name' => 'Chinese (Hong Kong Cantonese)'), + 5 => Array('code' => 'tw', 'iconCls' => 'flags flag-tw', 'name' => 'Chinese (Traditional)'), + 6 => Array('code' => 'cs', 'iconCls' => 'flags flag-cz', 'name' => 'Czech'), + 7 => Array('code' => 'da', 'iconCls' => 'flags flag-da', 'name' => 'Danish'), + 8 => Array('code' => 'nl', 'iconCls' => 'flags flag-nl', 'name' => 'Dutch'), + 9 => Array('code' => 'en', 'iconCls' => 'flags flag-en', 'name' => 'English'), + 10 => Array('code' => 'fi', 'iconCls' => 'flags flag-fi', 'name' => 'Finnish'), + 11 => Array('code' => 'fr', 'iconCls' => 'flags flag-fr', 'name' => 'French'), + 12 => Array('code' => 'de', 'iconCls' => 'flags flag-de', 'name' => 'German'), + 13 => Array('code' => 'el', 'iconCls' => 'flags flag-el', 'name' => 'Greek'), + 14 => Array('code' => 'he', 'iconCls' => 'flags flag-he', 'name' => 'Hebrew'), + 15 => Array('code' => 'hu', 'iconCls' => 'flags flag-hu', 'name' => 'Hungarian'), + 16 => Array('code' => 'it', 'iconCls' => 'flags flag-it', 'name' => 'Italian'), + 17 => Array('code' => 'ja', 'iconCls' => 'flags flag-ja', 'name' => 'Japanese'), + 18 => Array('code' => 'kr', 'iconCls' => 'flags flag-kr', 'name' => 'Korean'), + 19 => Array('code' => 'no', 'iconCls' => 'flags flag-no', 'name' => 'Norwegian'), + 20 => Array('code' => 'fa', 'iconCls' => 'flags flag-fa', 'name' => 'Persian'), + 21 => Array('code' => 'pl', 'iconCls' => 'flags flag-pl', 'name' => 'Polish'), + 22 => Array('code' => 'pt', 'iconCls' => 'flags flag-pt', 'name' => 'Portuguese'), + 23 => Array('code' => 'ro', 'iconCls' => 'flags flag-ro', 'name' => 'Romanian'), + 24 => Array('code' => 'ru', 'iconCls' => 'flags flag-ru', 'name' => 'Russian'), + 25 => Array('code' => 'sr', 'iconCls' => 'flags flag-rs', 'name' => 'Serbian'), + 26 => Array('code' => 'sk', 'iconCls' => 'flags flag-sk', 'name' => 'Slovak'), + 27 => Array('code' => 'sl', 'iconCls' => 'flags flag-sl', 'name' => 'Slovenian'), + 28 => Array('code' => 'es', 'iconCls' => 'flags flag-es', 'name' => 'Spanish'), + 29 => Array('code' => 'sv', 'iconCls' => 'flags flag-se', 'name' => 'Swedish'), + 30 => Array('code' => 'tr', 'iconCls' => 'flags flag-tr', 'name' => 'Turkish') + ); + + public $existingLanguage = array(); + + private function __construct() + { + $this->conn = DBConnection::getInstance(); + } + + public function getAvailableLanguage() + { + return $this->availableLang; + } + + public function computeExistingLanguage() + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + $this->existingLanguage = array(); + + for( $i=0; $i < count($this->availableLang); $i++ ) { + if( is_dir($appConf[$project]['vcs.path'].$this->availableLang[$i]['code'].'/') ) { + $this->existingLanguage[] = $this->availableLang[$i]; + } + } + + return $this->existingLanguage; + } + + public function getExistingLanguage() + { + if( !isset($this->existingLanguage) || count($this->existingLanguage) == 0 ) { + $this->computeExistingLanguage(); + } + + return $this->existingLanguage; + } + + /** + * Check if a lang is valide or not. + * @param $lang The lang to check + * @return Return true if $lang is a valid language, false otherwise. + */ + public function isValidLanguage($lang) + { + $existLanguage = $this->getExistingLanguage(); + + for( $i=0; $i < count($existLanguage); $i++ ) + { + if( $existLanguage[$i]['code'] == $lang ) { + return true; + } + } + return false; + + } + + + /** + * Checkout the phpdoc-all repository. + * This method must be call ONLY by the /firstRun.php script. + * + * @return An associative array{ 'err': svn co return code, 'output': svn co output contained in an array } + */ + public function checkoutRepository() + { + $project = AccountManager::getInstance()->project; + + $lock = new LockFile('project_' . $project . '_lock_checkout_repository'); + + $rtn = false; + if ($lock->lock()) { + // exec the checkout + $rtn = VCSFactory::getInstance()->checkout(); + } + + $lock->release(); + + return $rtn; + } + + /** + * CleanUp the dataBase before an Update. + * + * @see updateRepository + */ + public function cleanUp() + { + $project = AccountManager::getInstance()->project; + + // We cleanUp the database before update vcs and apply again all tools + foreach (array('files', 'translators', 'errorfiles') as $table) { + $this->conn->query("DELETE FROM `$table` WHERE `project`='%s'", array($project)); + $this->conn->query("OPTIMIZE TABLE `$table` ", array()); + } + } + + /** + * CleanUp the dataBase before check the build. + * We only stock in DB the last failed build on a month. + * + * @see checkBuild + */ + public function cleanUpBeforeCheckBuild() + { + $project = AccountManager::getInstance()->project; + + $this->conn->query("DELETE FROM `failedBuildLog` WHERE `project`= '%s' AND `date` < date_sub(now(),interval 1 month)", array($project)); + } + + + + + + /** + * Update the repository to sync our local copy. + * As this exec command take some time, we start by creating a lock file, then run the command, then delete this lock file. + * As it, we can test if this command has finish, or not. + */ + public function updateRepository() + { + $project = AccountManager::getInstance()->project; + + $lock = new LockFile('project_' . $project . '_lock_update_repository'); + + if ($lock->lock()) { + // exec the update + VCSFactory::getInstance()->update(); + } + + $lock->release(); + } + + /** + * Check the build of the documentation (using configure.php script). + * + * @param $lang The lang of the documentation we want to check the build. We must take out $lang to be able to use this method from cron script on multiple language + * @param $enable_xml_details Indicate whether the check cmd include xml-details option + * @return The output log. + */ + public function checkBuild($lang, $enable_xml_details="false") + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + $return = Array( + "state" => "ok", + "logContent" => "" + ); + + $appConf[$project]['vcs.configure.script.options'] = str_replace("{LangCode}", $lang, $appConf[$project]['vcs.configure.script.options']); + + if ( $enable_xml_details == "true" ) + { + $appConf[$project]['vcs.configure.script.options'] = str_replace("{XmlDetails}", "--enable-xml-details", $appConf[$project]['vcs.configure.script.options']); + } + else + { + $appConf[$project]['vcs.configure.script.options'] = str_replace("{XmlDetails}", "", $appConf[$project]['vcs.configure.script.options']); + } + + $commands = array( + new ExecStatement('cd %s', array(realpath($appConf[$project]['vcs.configure.script.path']))), + new ExecStatement($appConf['GLOBAL_CONFIGURATION']['php.bin'] . ' configure.php --with-php=' . $appConf['GLOBAL_CONFIGURATION']['php.bin'] . ' ' . $appConf[$project]['vcs.configure.script.options']) + ); + + $trial_threshold = 3; + while ($trial_threshold-- > 0) { + $output =array(); + SaferExec::execMulti($commands, $output); + if (strlen(trim(implode('', $output))) != 0) break; + } + + $return["logContent"] = $output; + + // We save the result of this check only if it failed. + if ( strstr(implode(" ", $output), 'Eyh man. No worries. Happ shittens. Try again after fixing the errors above.') || + strstr(implode(" ", $output), 'There were warnings loading the manual') ) + { + $return["state"] = "ko"; + } + + return $return; + } + + /** + * Register a file as a work in progress, into the database. + * + * @param $file The file object to be added into the database. + * @param $revision The revision of this file. + * @param $en_revision The EN revision of this file. + * @param $reviewed The stats of the reviewed tag. + * @param $reviewed_maintainer The maintainer of this reviewed work. + * @param $maintainer The maintainer. + * @param $type The type of work. Can be 'new' for new file, 'update' for an uptaded file, 'delete' for a file marked as delete. + * @return fileID of the file + */ + public function addProgressWork($file, $revision, $en_revision, $reviewed, $reviewed_maintainer, $maintainer, $type='update') + { + $am = AccountManager::getInstance(); + $vcsLogin = $am->vcsLogin; + $anonymousIdent = $am->anonymousIdent; + $project = $am->project; + + $s = 'SELECT + id + FROM + `work` + WHERE + `project`="%s" AND + `lang`="%s" AND + `path`="%s" AND + `name`="%s"'; + $params = array( + $project, + $file->lang, + $file->path, + $file->name + ); + $r = $this->conn->query($s, $params); + + // We insert or update the work table + if ($r->num_rows == 0) { + + $s = 'INSERT into + `work` + (`project`, `lang`, `path`, `name`, `revision`, `en_revision`, `reviewed`, `reviewed_maintainer`, `maintainer`, `user`, `anonymousIdent`, `date`, `type`) + VALUES + ("%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", now(), "%s")'; + $params = array( + $project, + $file->lang, + $file->path, + $file->name, + $revision, + $en_revision, + $reviewed, + $reviewed_maintainer, + $maintainer, + $vcsLogin, + $anonymousIdent, + $type + ); + $this->conn->query($s, $params); + $fileID = $this->conn->insert_id(); + + } else { + + $a = $r->fetch_object(); + + $s = 'UPDATE + `work` + SET + `revision`="%s", + `en_revision`="%s", + `reviewed`="%s", + `reviewed_maintainer`="%s", + `maintainer`="%s", + `user`="%s", + `anonymousIdent`="%s", + `date`=now(), + `module`="workInProgress", + `patchID` = NULL + WHERE + `id`="%s"'; + $params = array( + $revision, + $en_revision, + $reviewed, + $reviewed_maintainer, + $maintainer, + $am->vcsLogin, + $am->anonymousIdent, + $a->id + ); + $this->conn->query($s, $params); + $fileID = $a->id; + } + + return $fileID; + } + + /** + * Delete files from work in progress module. + * + * @param $files An array of File instances. + */ + public function delWork($files) + { + $am = AccountManager::getInstance(); + $project = $am->project; + + while( list($path, $data) = each($files)) + { + $query = 'DELETE FROM `work` + WHERE + `project` = "%s" AND + `lang` = "%s" AND + `path` = "%s" AND + `name` = "%s"'; + $params = array( + $project, + $data->lang, + $data->path, + $data->name + ); + $this->conn->query($query, $params); + } + } + + /** + * Move some files into a specific patch. + * + * @param $patchID The DB Id of the patch + * @param $filesID A comma separated list of files's Id + * @return true + */ + public function moveToPatch($patchID, $filesID) + { + $am = AccountManager::getInstance(); + $vcsLogin = $am->vcsLogin; + $project = $am->project; + + $s = 'SELECT + `name` + FROM + `patches` + WHERE + `project` = "%s" AND + `id` = "%s" AND + `user` = "%s"'; + $params = array( + $project, + $patchID, + $vcsLogin + ); + $r = $this->conn->query($s, $params); + + if( $this->conn->affected_rows() == 0 ) { + return 'Patches unknow for this project or for this user'; + } + + $s = 'UPDATE + `work` + SET + `patchID` = "%s", + `module` = "PatchesForReview" + WHERE + `project` = "%s" AND + `user` = "%s" AND + `id` IN (%s)'; + $params = array( + $patchID, + $project, + $vcsLogin, + implode(',', array_map('intval', explode(',', $filesID))) + ); + $r = $this->conn->query($s, $params); + + if( $this->conn->affected_rows() < 1 ) { + return 'Error. Is this file(s) is(are) own by you ?'; + } else { + return true; + } + + } + + /** + * Move some files into work in progress module. + * + * @param $filesID A comma separated list of files's Id + * @return true + */ + public function moveToWork($filesID) + { + $am = AccountManager::getInstance(); + $vcsLogin = $am->vcsLogin; + $project = $am->project; + + $s = 'UPDATE + `work` + SET + `patchID` = NULL, + `module` = "workInProgress" + WHERE + `project` = "%s" AND + `user` = "%s" AND + `id` IN (%s)'; + + $params = array( + $project, + $vcsLogin, + implode(',', array_map('intval', explode(',', $filesID))) + ); + $r = $this->conn->query($s, $params); + + if( $this->conn->affected_rows() < 1 ) { + return 'Error. Is this file(s) is(are) own by you ?'; + } else { + return true; + } + + } + + /** + * Delete a patch. + * + * @param $patchID The ID of the patch we want to delete + * @return true + */ + public function deletePatch($patchID) + { + $am = AccountManager::getInstance(); + $vcsLogin = $am->vcsLogin; + $project = $am->project; + + // We start by retrieve patch information + $patchInfo = $this->getPatchInfo($patchID); + + if( !$patchInfo ) { + return 'patch_delete_dont_exist'; // the patch don't exist + } else { + + // We must check if we can delete this patch + // Either this patch must be own by the current user or the current user is a global admin for this project + if( $patchInfo->user != $am->vcsLogin || ( $am->isAnonymous && ($patchInfo->anonymousIdent != $am->anonymousIdent) ) ) { + if( ! $am->isAdmin() ) { + return 'patch_delete_isnt_own_by_current_user'; + } + } + } + + // We start by change files for this patch. + $s = 'UPDATE + `work` + SET + `patchID` = NULL, + `module` = "workInProgress" + WHERE + `project` = "%s" AND + `patchID` = %d'; + $params = array( + $project, + $patchID + ); + $this->conn->query($s, $params); + + // We now delete this patch + $s = 'DELETE FROM + `patches` + WHERE + `project` = "%s" AND + `id` = %d'; + $params = array( + $project, + $patchID + ); + $this->conn->query($s, $params); + + return true; + } + + /** + * Get information about a patch by his ID. + * + * @param $patchID The ID of this patch + * @return An associative array containing informations about this patch, or false if no patch exist for this ID + */ + public function getPatchInfo($patchID) + { + $am = AccountManager::getInstance(); + $vcsLogin = $am->vcsLogin; + $project = $am->project; + + $s = 'SELECT + * + FROM + `patches` + WHERE + `id` = "%s"'; + $params = array( + $patchID + ); + $r = $this->conn->query($s, $params); + + if( $r->num_rows == 0 ) { + return false; + } else { + return $r->fetch_object(); + } + } + + /** + * Get all files from a patch by his ID. + * + * @param $patchID The ID of this patch + * @return An associative array containing files about this patch, or false if no patch exist for this ID + */ + public function getPatchFilesByID($patchID) + { + $am = AccountManager::getInstance(); + $vcsLogin = $am->vcsLogin; + $project = $am->project; + + $s = 'SELECT + * + FROM + `work` + WHERE + `module` = \'PatchesForReview\' AND + `patchID` = "%s"'; + + $params = array( + $patchID + ); + $r = $this->conn->query($s, $params); + + if( $r->num_rows == 0 ) { + return false; + } else { + $return = array(); + while( $a = $r->fetch_object() ) { + $return[] = $a; + } + + return $return; + } + } + + /** + * Create a new patch for the current user. + * + * @param $name The name for this new patch + * @param $description The description for this patch + * @param $email Email to be warn when the patch is commited + * @return true + */ + public function createPatch($name, $description, $email) + { + $am = AccountManager::getInstance(); + $vcsLogin = $am->vcsLogin; + $project = $am->project; + + $s = 'INSERT INTO + `patches` + (`project`, `name`, `description`, `email`, `user`, `anonymousIdent`, `date`) + VALUES + ("%s", "%s", "%s", "%s", "%s", "%s", now())'; + $params = array( + $project, + $name, + $description, + $email, + $vcsLogin, + $am->anonymousIdent + ); + $this->conn->query($s, $params); + + return $this->conn->insert_id(); + + } + + /** + * Modify the patch name for the current user. + * @param $patchID The ID of the patch we want to modify + * @param $name The new name for this patch + * @param $description The description for this patch + * @param $email Email to be warn when the patch is commited + * @return true + */ + public function modPatch($patchID, $name, $description, $email) + { + $am = AccountManager::getInstance(); + $vcsLogin = $am->vcsLogin; + $project = $am->project; + + $s = 'UPDATE + `patches` + SET + `name` = "%s", + `description` = "%s", + `email` = "%s" + WHERE + `project` = "%s" AND + `user` = "%s" AND + `id` = %d'; + $params = array( + $name, + $description, + $email, + $project, + $vcsLogin, + $patchID + ); + $this->conn->query($s, $params); + + if( $this->conn->affected_rows() != 1 ) { + return 'Error'; + } else { + return true; + } + } + + /** + * Mark a file as pending delete. + * + * @param $file File instance + * @return Array of info include record_id, request_user, date + */ + public function addPendingDelete($file) + { + $am = AccountManager::getInstance(); + $vcsLogin = $am->vcsLogin; + $project = $am->project; + $anonymousIdent = $am->anonymousIdent; + + $date = @date("Y-m-d H:i:s"); + + $s = 'INSERT INTO + `work` + (`project`, `lang`, `path`, `name`, `revision`, `en_revision`, `reviewed`, `maintainer`, `user`, `anonymousIdent`, `date`, `type`) + VALUES + ("%s", "%s", "%s", "%s", "-", "-", "-", "-", "%s", "%s", "%s", "delete")'; + $params = array( + $project, + $file->lang, + $file->path, + $file->name, + $vcsLogin, + $anonymousIdent, + $date + ); + $this->conn->query($s, $params); + + return array( + 'id' => $this->conn->insert_id(), + 'by' => Array("user"=> $vcsLogin, "anonymousIdent" => $anonymousIdent), + 'date' => $date + ); + } + + // not tested + public function fastUpdate() + { + if ($changed_files = VCSFactory::getInstance()->fastUpdate()) { + + foreach (array_merge($changed_files['create'], $changed_files['update']) as $path) { + $path = explode('/', $path, 2); + $file = new File($path[0], $path[1]); + + + $tmp = Array($file); + $this->delWork($tmp); + + // We must now insert information into the app for this file + $this->addFileInfo($tmp); + } + foreach ($changed_files['update'] as $path) { + $path = explode('/', $path, 2); + $file = new File($path[0], $path[1]); + + // Delete from work table + $tmp = Array($file); + $this->delWork($tmp); + + // We must now update information into the app for this file + $this->updateFileInfo($tmp); + } + foreach ($changed_files['delete'] as $path) { + $path = explode('/', $path, 2); + $file = new File($path[0], $path[1]); + + // Delete this new file from the fileSystem + @unlink($file->full_new_path); + + // Delete from work table + $this->delWork(array($file)); + } + } + } + + /** + * Update the VCS for each file we try to commit before start the commit processus. + * As it, we ensure all VCS conflict. + * + * @param $files All files to check + * @param $type Type of this file. Can be "new", "update", or "delete" + * @return Return the stack of files we must commit. All files which can't be commited have been deleted from this stack. + */ + public function beforeCommitChanges($files, $type) + { + $stack = Array(); + + if ($files) { + switch($type) { + + case 'new' : + + // For new files, we must ensure that this file is steel non exist into the repository before commit it. + for( $i=0; $i < count($files); $i++ ) { + if( !$files[$i]->exist() ) { + // This file still not exist in current respository, we can commit it + $stack[] = $files[$i]; + } + } + + break; + + case 'update' : + + // For update files, we must ensure that this file haven't been modified since last big update + for( $i=0; $i < count($files); $i++ ) { + + // We get the filemtime for this file to compare with the filemtime after the update. + $oldTime = filemtime($files[$i]->full_path); + if( $files[$i]->exist() ) { + // If this file haven't been deleted since last update + $newTime = filemtime($files[$i]->full_path); + if( $newTime == $oldTime ) { + // This file haven't been modified since last update. + // We can continue the commit processus for it + $stack[] = $files[$i]; + } + + } + + } + + break; + + case 'delete' : + + // For deleted files, we must ensure that this file is steel exist into the repository before commit it. + for( $i=0; $i < count($files); $i++ ) { + + if( $files[$i]->exist() ) { + // This file still exists in current respository, we can commit it for delete + $stack[] = $files[$i]; + } + + } + + break; + } + } + + return $stack; + + } + + public function ensureFoldersExists($folders) + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + while( list($folderPath, $data) = each($folders) ) { + + if( ! is_dir($appConf[$project]['vcs.path'].$folderPath) ) { + + mkdir( $appConf[$project]['vcs.path'].$folderPath, 0777, true ); + + } + } + } + + + /** + * Get only Folders we need to commit according to chosen files + * + * @param $folders An array of folders that are in work queue + * @param $l$filesog An array of files chosen to be commited + * @return An associated array similar of $folders params, but contained only folders witch need to be commited for this files + */ + public function getOnlyFoldersForFiles($folders, $files) { + + if( !$folders ) { + return false; + } + + $return = array(); + + function parsePath($path, &$pathInfo) { + + $pathInfo[$path] = 1; + $t = explode("/",$path); + array_pop($t); + + if( count($t) != 0 ) { parsePath(implode("/", $t), $pathInfo); } + + } + + // We walk trow files to find folders to commit + for( $i=0; $i < count($files); $i++) { + + $filePath = $files[$i]['lang'].$files[$i]['path']; + + $pathInfo = array(); + parsePath($filePath, $pathInfo); + + // We walk trow folders pending commit + reset($folders); + while( list($folderPath, $data) = each($folders) ) { + + // We search for path in folder path. If we find it, we add this folder into $return var + + if( isset($pathInfo[$folderPath]) ) { + $return[$folderPath] = $data; + } + + } + + } + return $return; + } + + // file level backup only + private function backupCommit($files, $type) + { + switch ($type) { + case 'new': break; // do nothing for new file + case 'update': + // backup actual file as .bak as .new will replace the actual file soon + for ($i=0; $i < count($files); $i++) { + @copy($files[$i]->full_path, $files[$i]->full_path.'.bak'); + } + break; + case 'delete': break; // do nothing for delete file + } + } + + // file level rollback only + private function rollbackCommit($files, $type) + { + switch ($type) { + case 'new': + // actual file is created in commit process, remove it + for ($i=0; $i < count($files); $i++) { + @unlink($files[$i]->full_path); + } + break; + case 'update': + // rollback actual file from .bak and remove .bak + for ($i=0; $i < count($files); $i++) { + @copy($files[$i]->full_path.'.bak', $files[$i]->full_path); + @unlink($files[$i]->full_path.'.bak'); + } + break; + case 'delete': break; // do nothing for delete file + } + } + + // file level changes only + private function afterCommitChanges($files, $type) + { + switch ($type) { + case 'new': + // remove file in -new folder + for ($i=0; $i < count($files); $i++) { + @unlink($files[$i]->full_new_path); + } + break; + case 'update': + // remove file in -new folder + for ($i=0; $i < count($files); $i++) { + @unlink($files[$i]->full_new_path); + @unlink($files[$i]->full_path.'.bak'); + } + break; + case 'delete': break; // do nothing for delete file + } + } + + /** + * Commit file changes to repository. + * + * @param $ids An array of files' id to be commited. + * @param $log The message log to use with this commit. + * @return An associated array. The key "commitResponse" contains the response from the CVS server after commit (with HTML highlight) and the key "anode", the list of files witch have been really commited. + */ + public function commitChanges($ids, $log) + { + $rf = RepositoryFetcher::getInstance(); + $commitLog = Array(); + + // Get informations about files we need to commit + $fileInfos = $rf->getModifiesById($ids); + + // Task for folders + $foldersInfos = $rf->getPendingFoldersCommit(); + + // We filter this folders to return only this who want to commit according of files array + $foldersInfos = $this->getOnlyFoldersForFiles($foldersInfos, $fileInfos); + + if( $foldersInfos ) { + + // We must create this folder before commit it + $this->ensureFoldersExists($foldersInfos); + + $c = VCSFactory::getInstance()->commitFolders($foldersInfos); + $commitLog = array_merge($commitLog, $c); + $this->delWork($foldersInfos); + } + + // Task for files + // Loop over $fileInfos to find files to be create, update or delete + $create_stack = array(); + $update_stack = array(); + $delete_stack = array(); + + for( $i=0; $i < count($fileInfos); $i++) { + $f = new File( + $fileInfos[$i]['lang'], + $fileInfos[$i]['path'].$fileInfos[$i]['name'] + ); + switch ($fileInfos[$i]['type']) { + case 'new' : $create_stack[] = $f; break; + case 'update' : $update_stack[] = $f; break; + case 'delete' : $delete_stack[] = $f; break; + } + } + + // Before commit, we need to update all files and find if there haven't been modified since last update process + $this->fastUpdate(); + $create_stack = $this->beforeCommitChanges($create_stack, 'new'); + $update_stack = $this->beforeCommitChanges($update_stack, 'update'); + $delete_stack = $this->beforeCommitChanges($delete_stack, 'delete'); + + // keep copy for commit failure recovery + $this->backupCommit($create_stack, 'new'); + $this->backupCommit($update_stack, 'update'); + $this->backupCommit($delete_stack, 'delete'); + + $c = VCSFactory::getInstance()->commit( + $log, $create_stack, $update_stack, $delete_stack + ); + + $commitLog = array_merge($commitLog, $c['output']); + + // html highlight commit log + $reg = array( + '/(Adding )/', + '/(Sending )/', + '/(Deleting )/', + '/(Transmitting file data)/', + '/(Committed revision)/', + '/(A )/', + '/(D )/', + '/(property )/', + '/( set on )/' + ); + + $commitLog = preg_replace( + $reg, + '$1', + $commitLog + ); + + if (0 != $c['err']) { + // error found in commit, rollback commit operation + $this->rollbackCommit($create_stack, 'new'); + $this->rollbackCommit($update_stack, 'update'); + $this->rollbackCommit($delete_stack, 'delete'); + + } else { + // We fetch again the file which have been commited. All file which have been skip from beforeCommitChanges aren't in DB for now. + $fileInfos = $rf->getModifiesById($ids); + + $ids = array(); + // Get all ids which have been really commited + for( $i=0; $i < count($fileInfos); $i ++ ) { + $ids[] = $fileInfos[$i]['id']; + } + + // confirmed commit success. batch delete pending commit, and remove backup + $this->afterCommitChanges($create_stack, 'new'); + $this->afterCommitChanges($update_stack, 'update'); + $this->afterCommitChanges($delete_stack, 'delete'); + } + + return array( + 'err' => $c['err'], + 'commitResponse' => $commitLog, + 'anode' => $ids + ); + } + + /** + * Set the progress for a file in work table. + * + * @param $idDB The type of the file. Can be 'update', 'delete' or 'new' + * @param $progress The File instance of the file. + * @return TRUE if the progress have been saved succesfully, false otherwises + */ + public function SetFileProgress($idDB, $progress) + { + $am = AccountManager::getInstance(); + $project = $am->project; + $vcsLogin = $am->vcsLogin; + $anonymousIdent = $am->anonymousIdent; + + // We start by get the current row + $s = 'SELECT + `user`, + `anonymousIdent` + FROM + `work` + WHERE + `project` = "%s" AND + `id` = %d'; + $params = array( + $project, + $idDB + ); + $r = $this->conn->query($s, $params); + + if( $r->num_rows == 0 ) { + return 'file_dont_exist_in_workInProgress'; + } else { + + $a = $r->fetch_object(); + + if( !($a->user == $vcsLogin && $a->anonymousIdent == $anonymousIdent) ) { + return 'file_isnt_owned_by_current_user'; + } + } + + $s = 'UPDATE + `work` + SET + `progress` = "%s" + WHERE + `project` = "%s" AND + `user` = "%s" AND + `anonymousIdent` = "%s" AND + `id` = %d'; + $params = array( + $progress, + $project, + $vcsLogin, + $anonymousIdent, + $idDB + ); + $this->conn->query($s, $params); + + return true; + } + + /** + * clear local change of a file. + * + * @param $type The type of the file. Can be 'update', 'delete' or 'new' + * @param $file The File instance of the file. + * @return An array which contain informations about this file. + */ + public function clearLocalChange($type, $file) + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + $lang = $file->lang; + $path = $file->path; + $name = $file->name; + + // Initiate return's var + $return = array(); + $return['rev'] = 0; + $return['en-rev'] = 0; + $return['maintainer'] = 0; + $return['reviewed'] = 0; + $return['errorState'] = false; + $return['errorFirst'] = 0; + + // We need select row from work table + $s = "SELECT + `id`, + `user`, + `anonymousIdent` + FROM + `work` + WHERE + `project` = '%s' AND + `lang` = '%s' AND + `path` = '%s' AND + `name` = '%s'"; + $params = array( + $project, + $lang, + $path, + $name + ); + + $r = $this->conn->query($s, $params); + + if( $r->num_rows == 0 ) { + + return 'file_localchange_didnt_exist'; + + } else { + $a = $r->fetch_object(); + + // Rules to allow clearLocalChange or not. + // Either the user who made the modification, either a global admin for this project, either a lang admin + if( $a->user != $am->vcsLogin || ( $am->isAnonymous && ($a->anonymousIdent != $am->anonymousIdent) ) ) { + // This file isn't own by the current user + + // Is the current user is a global admin or a lang admin ? + if( ! $am->isAdmin(true) ) { + if( !(!$am->isAnonymous && $am->anonymous($a->user, $a->anonymousIdent) ) ) { + return 'file_isnt_owned_by_current_user'; + } + } + } + + } + + $return['oldIdDB'] = $a->id; + + // We need delete row from work table + $s = 'DELETE FROM `work` WHERE `id`=%d'; + $params = array($a->id); + $this->conn->query($s, $params); + + // If type == delete, we stop here and return + if ($type == 'delete') { + return $return; + } + + // We need delete file on filesystem (for new & update) + @unlink($file->full_new_path); + + // If type == new, we stop here and return + if ($type == 'new') { + return $return; + } + + // We need check for error in this file + $en_content = file_get_contents($appConf[$project]['vcs.path'].'en' .$path.$name); + $lang_content = file_get_contents($appConf[$project]['vcs.path'].$lang.$path.$name); + + $info = $file->getInfo($lang_content); + $anode[0] = array( + 'lang' => $lang, + 'path' => $path, + 'name' => $name, + 'en_content' => $en_content, + 'lang_content' => $lang_content, + 'maintainer' => $info['maintainer'] + ); + + $errorTools = new ToolsError(); + $error = $errorTools->updateFilesError($anode, 'nocommit'); + + // We need reload original information + $s = "SELECT `revision`, `en_revision`, `maintainer`, `reviewed` FROM `files` + WHERE `project`='%s' AND `lang`='%s' AND `path`='%s' AND `name`='%s'"; + $params = array($project, $lang, $path, $name); + $r = $this->conn->query($s, $params); + $a = $r->fetch_object(); + + $return['rev'] = $a->revision; + $return['en-rev'] = $a->en_revision; + $return['maintainer'] = $a->maintainer; + $return['reviewed'] = $a->reviewed; + + if (isset($error['first'])) { + $return['errorState'] = true; + $return['errorFirst'] = $error['first']; + } else { + $return['errorState'] = false; + $return['errorFirst'] = '-No error-'; + } + + // We return original lang_revision & maintainer + return $return; + } + + /** + * Set the last update datetime into DB + * @param $type Can be "data" or "entities" + */ + public function setLastUpdate($type) + { + $am = AccountManager::getInstance(); + $vcsLogin = $am->vcsLogin; + $project = $am->project; + + $vcsLogin = isset($vcsLogin) + ? $vcsLogin : '-'; + + $value = array(); + $value['date'] = @date("Y-m-d H:i:s"); + $value['by'] = $vcsLogin; + + $this->setStaticValue('last_update_'.$type, '-', json_encode($value)); + } + + /** + * Update information about a file after commit (update informations added with revcheck tools). + * + * @param $files An array of File instances for info update. + */ + public function updateFileInfo($files) + { + + $am = AccountManager::getInstance(); + + foreach ($files as $file) { + + $info = $file->getInfo(); + $size = intval(filesize($file->full_path) / 1024); + $date = filemtime($file->full_path); + + if ($file->lang == 'en') { // en file + // update EN file info + $s = 'UPDATE `files` + SET + `xmlid` = "%s", + `revision` = "%s", + `size` = "%s", + `mdate` = "%s" + WHERE + `project` = "%s" AND + `lang` = "%s" AND + `path` = "%s" AND + `name` = "%s"'; + $params = array( + $info['xmlid'], $info['rev'], $size, $date, $am->project, $file->lang, $file->path, $file->name + ); + $this->conn->query($s, $params); + + // update LANG file info + $s = 'UPDATE `files` + SET + `en_revision` = "%s" + WHERE + `project` = "%s" AND + `lang` != "%s" AND + `path` = "%s" AND + `name` = "%s"'; + $params = array( + $info['rev'], $am->project, $file->lang, $file->path, $file->name + ); + $this->conn->query($s, $params); + + } else { // lang file + + // If this file don't exist in EN, we should skip all this proces + $en = new File('en', $file->path.$file->name); + + if( $en->exist() ) { + + $enInfo = $en->getInfo(); + + $sizeEN = intval(filesize($en->full_path) / 1024); + $dateEN = filemtime($en->full_path); + + $size_diff = $sizeEN - $size; + $date_diff = (intval((time() - $dateEN) / 86400)) + - (intval((time() - $date) / 86400)); + + // update LANG file info + $s = 'UPDATE `files` + SET + `xmlid` = "%s", + `revision` = "%s", + `en_revision`= "%s", + `reviewed` = "%s", + `reviewed_maintainer` = "%s", + `size` = "%s", + `mdate` = "%s", + `maintainer` = "%s", + `status` = "%s", + `size_diff` = "%s", + `mdate_diff` = "%s" + WHERE + `project` = "%s" AND + `lang` = "%s" AND + `path` = "%s" AND + `name` = "%s"'; + $params = array( + $info['xmlid'], + $info['en-rev'], + $enInfo['rev'], + trim($info['reviewed']), + trim($info['reviewed_maintainer']), + $size, + $date, + trim($info['maintainer']), + trim($info['status']), + $size_diff, + $date_diff, + $am->project, + $file->lang, + $file->path, + $file->name + ); + $this->conn->query($s, $params); + + // Run the errorTools under this file + $tmpFile[0]['en_content'] = $en->read(true); + $tmpFile[0]['lang_content'] = $file->read(true); + $tmpFile[0]['lang'] = $file->lang; + $tmpFile[0]['path'] = $file->path; + $tmpFile[0]['name'] = $file->name; + $tmpFile[0]['maintainer'] = $info['maintainer']; + + $errorTools = new ToolsError(); + $errorTools->updateFilesError($tmpFile); + + } else // This file exist only in LANG version, like translation.xml, for example + { + + // update LANG file info + $s = 'UPDATE `files` + SET + `xmlid` = "%s", + `revision` = "%s", + `en_revision`= "%s", + `reviewed` = "%s", + `reviewed_maintainer` = "%s", + `size` = "%s", + `mdate` = "%s", + `maintainer` = "%s", + `status` = "%s", + `size_diff` = "%s", + `mdate_diff` = "%s" + WHERE + `project` = "%s" AND + `lang` = "%s" AND + `path` = "%s" AND + `name` = "%s"'; + $params = array( + $info['xmlid'], + $info['en-rev'], + 0, + trim($info['reviewed']), + trim($info['reviewed_maintainer']), + $size, + $date, + trim($info['maintainer']), + trim($info['status']), + 0, + 0, + $am->project, + $file->lang, + $file->path, + $file->name + ); + $this->conn->query($s, $params); + + // Run the errorTools under this file + // If the EN file don't exist, it's because we have a file witch only exist into LANG, for example, translator.xml + // We fake the EN with the LANG content to fake the errorTools ;) + $tmpFile[0]['en_content'] = $file->read(true); + $tmpFile[0]['lang_content'] = $file->read(true); + $tmpFile[0]['lang'] = $file->lang; + $tmpFile[0]['path'] = $file->path; + $tmpFile[0]['name'] = $file->name; + $tmpFile[0]['maintainer'] = $info['maintainer']; + + $errorTools = new ToolsError(); + $errorTools->updateFilesError($tmpFile); + + } + } + } + } + public function addFileInfo($files) + { + + $am = AccountManager::getInstance(); + + foreach ($files as $file) { + + $info = $file->getInfo(); + $size = intval(filesize($file->full_path) / 1024); + $date = filemtime($file->full_path); + + if ($file->lang == 'en') { // en file + // update EN file info + $s = 'INSERT INTO `files` + SET + `xmlid` = "%s", + `revision` = "%s", + `size` = "%s", + `mdate` = "%s", + `project` = "%s", + `lang` = "%s", + `path` = "%s", + `name` = "%s"'; + $params = array( + $info['xmlid'], $info['rev'], $size, $date, $am->project, $file->lang, $file->path, $file->name + ); + $this->conn->query($s, $params); + + // update LANG file info + $s = 'UPDATE `files` + SET + `en_revision` = "%s" + WHERE + `project` = "%s" AND + `lang` != "%s" AND + `path` = "%s" AND + `name` = "%s"'; + $params = array( + $info['rev'], $am->project, $file->lang, $file->path, $file->name + ); + $this->conn->query($s, $params); + + } else { // lang file + + // If this file don't exist in EN, we should skip all this proces + $en = new File('en', $file->path.$file->name); + + if( $en->exist() ) { + + $enInfo = $en->getInfo(); + + $sizeEN = intval(filesize($en->full_path) / 1024); + $dateEN = filemtime($en->full_path); + + $size_diff = $sizeEN - $size; + $date_diff = (intval((time() - $dateEN) / 86400)) + - (intval((time() - $date) / 86400)); + + // update LANG file info + $s = 'INSERT INTO `files` + SET + `xmlid` = "%s", + `revision` = "%s", + `en_revision`= "%s", + `reviewed` = "%s", + `reviewed_maintainer` = "%s", + `size` = "%s", + `mdate` = "%s", + `maintainer` = "%s", + `status` = "%s", + `size_diff` = "%s", + `mdate_diff` = "%s", + `project` = "%s", + `lang` = "%s", + `path` = "%s", + `name` = "%s"'; + $params = array( + $info['xmlid'], + $info['en-rev'], + $enInfo['rev'], + trim($info['reviewed']), + trim($info['reviewed_maintainer']), + $size, + $date, + trim($info['maintainer']), + trim($info['status']), + $size_diff, + $date_diff, + $am->project, + $file->lang, + $file->path, + $file->name + ); + $this->conn->query($s, $params); + + // Run the errorTools under this file + $tmpFile[0]['en_content'] = $en->read(true); + $tmpFile[0]['lang_content'] = $file->read(true); + $tmpFile[0]['lang'] = $file->lang; + $tmpFile[0]['path'] = $file->path; + $tmpFile[0]['name'] = $file->name; + $tmpFile[0]['maintainer'] = $info['maintainer']; + + $errorTools = new ToolsError(); + $errorTools->updateFilesError($tmpFile); + + } else // This file exist only in LANG version, like translation.xml, for example + { + + // update LANG file info + $s = 'INSERT INTO `files` + SET + `xmlid` = "%s", + `revision` = "%s", + `en_revision`= "%s", + `reviewed` = "%s", + `reviewed_maintainer` = "%s", + `size` = "%s", + `mdate` = "%s", + `maintainer` = "%s", + `status` = "%s", + `size_diff` = "%s", + `mdate_diff` = "%s", + `project` = "%s", + `lang` = "%s", + `path` = "%s", + `name` = "%s"'; + $params = array( + $info['xmlid'], + $info['en-rev'], + 0, + trim($info['reviewed']), + trim($info['reviewed_maintainer']), + $size, + $date, + trim($info['maintainer']), + trim($info['status']), + 0, + 0, + $am->project, + $file->lang, + $file->path, + $file->name + ); + $this->conn->query($s, $params); + + // Run the errorTools under this file + // If the EN file don't exist, it's because we have a file witch only exist into LANG, for example, translator.xml + // We fake the EN with the LANG content to fake the errorTools ;) + $tmpFile[0]['en_content'] = $file->read(true); + $tmpFile[0]['lang_content'] = $file->read(true); + $tmpFile[0]['lang'] = $file->lang; + $tmpFile[0]['path'] = $file->path; + $tmpFile[0]['name'] = $file->name; + $tmpFile[0]['maintainer'] = $info['maintainer']; + + $errorTools = new ToolsError(); + $errorTools->updateFilesError($tmpFile); + + } + } + } + } + /** + * Read the translation's file which hold informations about all translators + * and put it into database. + */ + public function updateTranslatorInfo() + { + $ExistingLanguage = $this->getExistingLanguage(); + $am = AccountManager::getInstance(); + + foreach ($ExistingLanguage as $lang) { + + $lang = $lang["code"]; + $txml = false; + + // Path to find translation.xml file, set default values, + // in case we can't find the translation file + $translation_xml = new File($lang, '/translation.xml'); + + if ( file_exists($translation_xml->full_path) ) { + // Else go on, and load in the file, replacing all + // space type chars with one space + $txml = preg_replace('/\\s+/', ' ', $translation_xml->read(true)); + } + + if ( $txml ) { + // Find all persons matching the pattern + $matches = array(); + if (preg_match_all('!!U', $txml, $matches)) { + $default = array( + 'vcs' => 'n/a', + 'nick' => 'n/a', + 'editor' => 'n/a', + 'email' => 'n/a', + 'name' => 'n/a' + ); + $persons = $translation_xml->parseAttribute($matches[1]); + $charset = $translation_xml->getEncoding($txml); + + foreach ($persons as $person) { + + if ($charset == 'utf-8' ) { + $name = utf8_decode($person['name']); + } else { + $name = $person['name']; + } + + $person = array_merge($default, $person); + + // We try to remove this record if it exist + $query = 'DELETE FROM `translators` WHERE `project`="%s" AND `lang`="%s" AND `nick`="%s"'; + $params = array( + $am->project, + $lang, + $person['nick'] + ); + $this->conn->query($query, $params); + + $query = 'INSERT INTO `translators` (`project`, `lang`, `nick`, `name`, `mail`, `vcs`, `editor`) + VALUES ("%s", "%s", "%s", "%s", "%s", "%s", "%s")'; + $params = array( + $am->project, + $lang, + $person['nick'], + $name, + $person['email'], + $person['vcs'], + $person['editor'] + ); + $this->conn->query($query, $params); + + } + } + } + } + } + + /** + * Check is the File/Folder must be processed or not for certain operation. + * + * @param $file The checked File instance. + * @return True if the File/Folder must be processed, FALSE otherwise. + */ + private function needParsing($file) + { + $name = $file->name; + $path = $file->path; + + if( substr($name, -4) === '.new' ) { + $toDisplay = true; + } else { + $toDisplay = false; + } + + $return = "needParsing : \n"; + $return .= " => name : $name\n"; + $return .= " => path : $path\n"; + + if ( + !$file->exist() + || ( is_file($file->full_path) && !in_array(substr($name, -3), array('xml','ent')) ) + || substr($name, -13) == 'PHPEditBackup' + || strpos($name, 'entities.') === 0 + || $path == '/chmonly/' + || $path == '/internals/' + || $path == '/internals2/' + || $name == 'contributors.ent' + || $name == 'contributors.xml' + || ($path == '/appendices/' && ($name == 'reserved.constants.xml' || $name == 'extensions.xml')) + || $name == 'README' + || $name == 'DO_NOT_TRANSLATE' + || $name == 'rsusi.txt' + || $name == 'translation.xml' + || $name == 'missing-ids.xml' + || $name == 'license.xml' + || $name == 'versions.xml' + ) { + $return .= " FALSE !\n\n\n"; + if( $toDisplay ) echo $return; + return false; + } else { + $return .= " TRUE !\n\n\n"; + if( $toDisplay ) echo $return; + return true; + } + } + + /** + * Run doUpdateNotInEN() on every avaliable language. + * Check all files to see if the LANG files is present into EN tree or not. + */ + public function updateNotInEN() + { + $ExistingLanguage = $this->getExistingLanguage(); + + foreach ($ExistingLanguage as $lang) { + $this->doUpdateNotInEN('/', $lang["code"]); + } + } + /** + * Check all files to see if the LANG files is present into EN tree or not. + * + * @param $path The path to checking directory. + * @param $lang The tested lang. + */ + private function doUpdateNotInEN($path, $lang) + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + if ($dh = @opendir($appConf[$project]['vcs.path'].$lang.$path)) { + + $dirs = array(); + $files = array(); + + while (($name = readdir($dh)) !== false) { + + if( $name == '.' || $name == '..') { + continue; + } + + $file = new File($lang, $path.$name); + if (!$this->needParsing($file)) { + continue; + } + + if ( $file->isDir ) { + $dirs[] = $file; + } elseif ( $file->isFile ) { + $files[] = $file; + } + + } + @closedir($dh); + + foreach($files as $f) { + $en_file = $appConf[$project]['vcs.path'] .'en' .$f->path .$f->name; + $lang_file = $appConf[$project]['vcs.path'] .$lang .$f->path .$f->name; + + if (!@is_file($en_file)) { + $query = 'INSERT INTO `files` (`project`, `lang`, `path`, `name`, `status`) + VALUES ("%s", "%s", "%s", "%s", "%s")'; + $params = array( + $project, + $lang, $f->path, $f->name, 'NotInEN' + ); + $this->conn->query($query, $params); + } + } + + foreach ($dirs as $d) { + $this->doUpdateNotInEN($d->path.'/', $lang); + } + } + } + + /** + * Apply the Revcheck tools recursively on all lang + * + * @param $path The directory from which we start. + * @param $revType Can be 'new' when we start a new revcheck with a clean database or 'update' when we revcheck just one folder (and all is sub-folders). Default to 'new' + * @param $revLang The lang we want to apply the recheck. By default, it's 'all' lang available. + * @return Nothing. + */ + public function applyRevCheck($path = '/', $revType='new', $revLang='all') + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + if ($dh = @opendir($appConf[$project]['vcs.path'].'en'.$path)) { + + $dirs = array(); + $files = array(); + + while (($name = readdir($dh)) !== false) { + + if( $name == '.' || $name == '..') { + continue; + } + + $file = new File('en', $path.$name); + if (!$this->needParsing($file)) { + continue; + } + + if ( $file->isDir ) { + $dirs[] = $file; + } elseif ( $file->isFile ) { + $files[] = $file; + } + } + closedir($dh); + + foreach($files as $f) { + + $en_size = intval(filesize($f->full_path) / 1024); + $en_date = filemtime($f->full_path); + + $infoEN = $f->getInfo(); + $en_revision = ($infoEN['rev'] == 'NULL') ? 'NULL' : $infoEN['rev']; + $xmlid = ($infoEN['xmlid'] == 'NULL') ? 'NULL' : $infoEN['xmlid']; + + $tmp = explode('/', $f->path); + + // Only for Php project + if( $project == 'PHP' ) { + $check_doc = new ToolsCheckDoc(); + $ToolsCheckDocResult = $check_doc->checkDoc($infoEN['content'], $f->path); + } else { + $ToolsCheckDocResult['check_oldstyle'] = 'NULL'; + $ToolsCheckDocResult['check_undoc'] = 'NULL'; + $ToolsCheckDocResult['check_roleerror'] = 'NULL'; + $ToolsCheckDocResult['check_badorder'] = 'NULL'; + $ToolsCheckDocResult['check_noseealso'] = 'NULL'; + $ToolsCheckDocResult['check_noreturnvalues'] = 'NULL'; + $ToolsCheckDocResult['check_noparameters'] = 'NULL'; + $ToolsCheckDocResult['check_noexamples'] = 'NULL'; + $ToolsCheckDocResult['check_noerrors'] = 'NULL'; + } + + // If the type of this revcheck is an update, we start to remove all reference to this file from... + if( $revType == 'update' ) + { + //... table `files` + $query = 'DELETE FROM `files` + WHERE `project`="%s" AND + `lang`="en" AND + `path`="%s" AND + `name`="%s"'; + $params = array( + $am->project, $f->path, $f->name + ); + $this->conn->query($query, $params); + + //... table `errorfiles` + $query = 'DELETE FROM `errorfiles` + WHERE `project`="%s" AND + `lang`="en" AND + `path`="%s" AND + `name`="%s"'; + $params = array( + $am->project, $f->path, $f->name + ); + $this->conn->query($query, $params); + } + + // Sql insert. + $query = 'INSERT INTO `files` (`project`, `lang`, `xmlid`, `path`, `name`, `revision`, `size`, `mdate`, `maintainer`, `status`, `check_oldstyle`, `check_undoc`, `check_roleerror`, `check_badorder`, `check_noseealso`, `check_noreturnvalues`, `check_noparameters`, `check_noexamples`, `check_noerrors`) + VALUES ("%s", "en", "%s", "%s", "%s", "%s", "%s", "%s", NULL, NULL, "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s")'; + $params = array( + $am->project, + $xmlid, $f->path, $f->name, $en_revision, $en_size, $en_date, + $ToolsCheckDocResult['check_oldstyle'], + $ToolsCheckDocResult['check_undoc'], + $ToolsCheckDocResult['check_roleerror'], + $ToolsCheckDocResult['check_badorder'], + $ToolsCheckDocResult['check_noseealso'], + $ToolsCheckDocResult['check_noreturnvalues'], + $ToolsCheckDocResult['check_noparameters'], + $ToolsCheckDocResult['check_noexamples'], + $ToolsCheckDocResult['check_noerrors'] + ); + $this->conn->query($query, $params); + + $error = new ToolsError(); + $error->setParams($infoEN['content'], '', 'en', $f->path, $f->name, ''); + $error->run(); + $error->saveError(); + + + if( $revType == 'update' ) + { + // If we are in update, we have 2 case. $revLang can be en or LANG. + // If revLang is en, we must re-check all available language to reflect changes. + if( $revLang == 'en' ) { + $ExistingLanguage = $this->getExistingLanguage(); + } + // If revLang is LANG, we only re-check this LANG + else { + $ExistingLanguage[] = array("code" => $revLang); + } + } else { + // If this is not an update, we check all languages + $ExistingLanguage = $this->getExistingLanguage(); + } + + foreach($ExistingLanguage as $lang) { + + $lang = $lang["code"]; + + // We skip en language + if( $lang == 'en' ) { + continue; + } + + $lang_file = new File($lang, $f->path.$f->name); + + // If the type of this revcheck is an update, we start be delete all reference to this file in table... + if( $revType == 'update' ) + { + // ... `file` + $query = 'DELETE FROM `files` + WHERE `project`="%s" AND + `lang`="%s" AND + `path`="%s" AND + `name`="%s"'; + $params = array( + $project, $lang, $lang_file->path, $lang_file->name + ); + $this->conn->query($query, $params); + + //... table `errorfiles` + $query = 'DELETE FROM `errorfiles` + WHERE `project`="%s" AND + `lang`="%s" AND + `path`="%s" AND + `name`="%s"'; + $params = array( + $project, $lang, $lang_file->path, $lang_file->name + ); + $this->conn->query($query, $params); + } + + if ( $lang_file->exist() ) { + + // Initial revcheck method + $size = intval(filesize($lang_file->full_path) / 1024); + $date = filemtime($lang_file->full_path); + + $size_diff = $en_size - $size; + $date_diff = (intval((time() - $en_date) / 86400)) - (intval((time() - $date) / 86400)); + + $infoLANG = $lang_file->getInfo(); + $revision = ($infoLANG['en-rev'] == 'NULL') ? 'NULL' : $infoLANG['en-rev']; + $maintainer = ($infoLANG['maintainer'] == 'NULL') ? 'NULL' : $infoLANG['maintainer']; + $status = ($infoLANG['status'] == 'NULL') ? 'NULL' : $infoLANG['status']; + $xmlid = ($infoLANG['xmlid'] == 'NULL') ? 'NULL' : $infoLANG['xmlid']; + $reviewed = ($infoLANG['reviewed'] == 'NULL') ? 'NULL' : $infoLANG['reviewed']; + $reviewed_maintainer = ($infoLANG['reviewed_maintainer'] == 'NULL') ? 'NULL' : $infoLANG['reviewed_maintainer']; + + $query = 'INSERT INTO `files` (`project`, `lang`, `xmlid`, `path`, `name`, `revision`, `en_revision`, `reviewed`, `reviewed_maintainer`, `size`, `size_diff`, `mdate`, `mdate_diff`, `maintainer`, `status`) + VALUES ("%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s")'; + $params = array( + $project, + $lang, + $xmlid, + $lang_file->path, + $lang_file->name, + $revision, + $en_revision, + $reviewed, + $reviewed_maintainer, + $size, + $size_diff, + $date, + $date_diff, + $maintainer, + $status + ); + $this->conn->query($query, $params); + + // Check for error in this file ONLY if this file is uptodate + if ($revision == $en_revision && $revision != 0 ) { + $error = new ToolsError(); + $error->setParams( + $infoEN['content'], $infoLANG['content'], + $lang, $lang_file->path, $lang_file->name, $maintainer + ); + $error->run(); + $error->saveError(); + } + } else { + $query = 'INSERT INTO `files` (`project`, `lang`, `path`, `name`, `size`) + VALUES ("%s", "%s", "%s", "%s", "%s")'; + $params = array( + $project, + $lang, + $lang_file->path, + $lang_file->name, + $en_size + ); + $this->conn->query($query, $params); + } + } + } + + foreach ($dirs as $d) { + $this->applyRevCheck($d->path, $revType, $revLang); + } + } + } + + /** + * Remove a file from DB + * + * @param $files An array of File instances. + * @return Nothing. + */ + public function delFiles($files) + { + + for ($i = 0; $i < count($files); $i++) { + $query = 'DELETE FROM files + WHERE + `project` = "%s" AND + `lang` = "%s" AND + `path` = "%s" AND + `name` = "%s"'; + $params = array( + AccountManager::getInstance()->project, + $files[$i]->lang, $files[$i]->path, $files[$i]->name + ); + $this->conn->query($query, $params); + } + } + + /** + * Set a static value into DB + * + * @param $type The type of this value + * @param $field The name of the field for this value + * @param $value The value. Can be anything who can be store into a SQL TEXT field + * @param $forceNew TRUE to indicate that this value must be added e.g. not updated. By default, the value is updated. + * @return Nothing. + */ + public static function setStaticValue($type, $field, $value, $forceNew=false) + { + $project = AccountManager::getInstance()->project; + + $s = "SELECT id FROM staticValue WHERE + `project` = '%s' AND + `type` = '%s' AND + `field` = '%s' + "; + $params = array( + $project, + $type, + $field + ); + $r = DBConnection::getInstance()->query($s, $params); + + if( $r->num_rows == 0 || $forceNew) { + $s = "INSERT INTO staticValue (`project`, `type`, `field`, `value`, `date`) VALUES ('%s', '%s', '%s', '%s', now())"; + $params = array($project, $type, $field, $value); + DBConnection::getInstance()->query($s, $params); + } else { + $a = $r->fetch_object(); + $s = "UPDATE staticValue SET `value`= '%s', `date`=now() WHERE `id`=%d"; + $params = array($value, $a->id); + DBConnection::getInstance()->query($s, $params); + } + } + + public function applyStaticRevcheck() + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + $ExistingLanguage = $this->getExistingLanguage(); + + foreach( $ExistingLanguage as $lang ) { + + $lang = $lang["code"]; + if( $lang == 'en' ) { continue; } + + $commands = array( + new ExecStatement('cd %s', array($appConf[$project]['vcs.path'])), + new ExecStatement($appConf['GLOBAL_CONFIGURATION']['php.bin'] . ' doc-base/scripts/revcheck.php %s > %s 2>&1', array($lang, $appConf['GLOBAL_CONFIGURATION']['data.path'].'revcheck/'.$lang.'.html')) + ); + SaferExec::execMulti($commands); + } + } + + /** + * All we must do after a patch have been commited. + * + * @param $patchID ID of the patch. + */ + public function postPatchCommit($patchID) + { + $am = AccountManager::getInstance(); + $vcsLogin = $am->vcsLogin; + + // We get patch Information + $patchInfo = $this->getPatchInfo($patchID); + + // We silently return if the patch didn't exist + if( !$patchInfo ) return; + + $to = trim($patchInfo->email); + $subject = '['.$patchInfo->project.'-DOC] - Patch named "'.$patchInfo->name.'" accepted'; + $msg = <<email) && $patchInfo->user != $vcsLogin ) { + $am->email($to, $subject, $msg); + } + } + + /** + * Create the folder how hold all modified files for this project. + * + */ + public function initCreateFolderForModifiedFiles() + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + $folderPath = $appConf['GLOBAL_CONFIGURATION']['data.path'].$appConf[$project]['vcs.module'].'-new'; + + if( is_dir($folderPath) ) { + return false; // already exist + } else { + if( mkdir($folderPath) ) { + return true; + } else { + return false; + } + } + } +} + +?> diff --git a/php/ToolsXmllint.php b/php/ToolsXmllint.php index a0ba55ce..6d56dc1c 100644 --- a/php/ToolsXmllint.php +++ b/php/ToolsXmllint.php @@ -1,114 +1,114 @@ -XmlFileName); - @unlink($this->XmlFileResult); - } - - public function saveInTmpFile() - { - $this->XmlFileName = tempnam(sys_get_temp_dir(), 'PhDOE_'.mt_rand()); - $h = fopen($this->XmlFileName, "w"); - fwrite($h, $this->xmlContent); - fclose($h); - } - - public function checkForError($xmlContent) - { - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - $this->xmlContent = $xmlContent; - $this->saveInTmpFile(); - - $this->XmlFileResult = tempnam(sys_get_temp_dir(), 'PhDOE_'.mt_rand()); - - $cmd = new ExecStatement($appConf['GLOBAL_CONFIGURATION']['xmllint.bin'] . ' --noout %s > %s 2>&1', array($this->XmlFileName, $this->XmlFileResult)); - - $trial_threshold = 3; - while ($trial_threshold-- > 0) { - $output = array(); - SaferExec::exec($cmd, $output); - if (strlen(trim(implode('', $output))) != 0) break; - } - - $this->rawErrors = file($this->XmlFileResult); - - $this->Errors = $this->parseResult(); - - return $this->Errors; - - } - - public function parseResult() - { - // Each Error is on 3 lines - $return = array(); - - $tmp = 0; - $numResult = 0; - - for($i=0; $i < count($this->rawErrors); $i++) - { - $return[$numResult][$tmp] = $this->rawErrors[$i]; - - if( $tmp != 2 ) { - $tmp ++; - } else { - $tmp = 0; - $numResult ++; - } - } - - $result = array(); - $numResult = 0; - - // We check all errors - for( $i=0; $i < count($return); $i++) { - - // We skip the filename in the first element of the array - $return[$i][0] = substr($return[$i][0], strlen($this->XmlFileName), strlen($return[$i][0])); - - // We search the line number - $match = array(); - preg_match("/^(:)(\d*)(: )/", $return[$i][0], $match); - $return[$i]['line'] = $match[2]; - - $return[$i][0] = substr($return[$i][0], strlen($match[2])+3, strlen($return[$i][0])); - - // We skip all entity not defined - $match = array(); - preg_match("/^parser error : Entity (.*?) not defined/", $return[$i][0], $match); - - if( count($match) == 0 ) { - $result[$numResult]['libel'] = $return[$i][0]; - $result[$numResult]['ctx1'] = $return[$i][1]; - $result[$numResult]['ctx2'] = $return[$i][2]; - $result[$numResult]['line'] = $return[$i]['line']; - $numResult ++; - } - - - } - - return empty($result) ? 'no_error' : $result; - - } - -} - -?> +XmlFileName); + @unlink($this->XmlFileResult); + } + + public function saveInTmpFile() + { + $this->XmlFileName = tempnam(sys_get_temp_dir(), 'PhDOE_'.mt_rand()); + $h = fopen($this->XmlFileName, "w"); + fwrite($h, $this->xmlContent); + fclose($h); + } + + public function checkForError($xmlContent) + { + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + $this->xmlContent = $xmlContent; + $this->saveInTmpFile(); + + $this->XmlFileResult = tempnam(sys_get_temp_dir(), 'PhDOE_'.mt_rand()); + + $cmd = new ExecStatement($appConf['GLOBAL_CONFIGURATION']['xmllint.bin'] . ' --noout %s > %s 2>&1', array($this->XmlFileName, $this->XmlFileResult)); + + $trial_threshold = 3; + while ($trial_threshold-- > 0) { + $output = array(); + SaferExec::exec($cmd, $output); + if (strlen(trim(implode('', $output))) != 0) break; + } + + $this->rawErrors = file($this->XmlFileResult); + + $this->Errors = $this->parseResult(); + + return $this->Errors; + + } + + public function parseResult() + { + // Each Error is on 3 lines + $return = array(); + + $tmp = 0; + $numResult = 0; + + for($i=0; $i < count($this->rawErrors); $i++) + { + $return[$numResult][$tmp] = $this->rawErrors[$i]; + + if( $tmp != 2 ) { + $tmp ++; + } else { + $tmp = 0; + $numResult ++; + } + } + + $result = array(); + $numResult = 0; + + // We check all errors + for( $i=0; $i < count($return); $i++) { + + // We skip the filename in the first element of the array + $return[$i][0] = substr($return[$i][0], strlen($this->XmlFileName), strlen($return[$i][0])); + + // We search the line number + $match = array(); + preg_match("/^(:)(\d*)(: )/", $return[$i][0], $match); + $return[$i]['line'] = $match[2]; + + $return[$i][0] = substr($return[$i][0], strlen($match[2])+3, strlen($return[$i][0])); + + // We skip all entity not defined + $match = array(); + preg_match("/^parser error : Entity (.*?) not defined/", $return[$i][0], $match); + + if( count($match) == 0 ) { + $result[$numResult]['libel'] = $return[$i][0]; + $result[$numResult]['ctx1'] = $return[$i][1]; + $result[$numResult]['ctx2'] = $return[$i][2]; + $result[$numResult]['line'] = $return[$i]['line']; + $numResult ++; + } + + + } + + return empty($result) ? 'no_error' : $result; + + } + +} + +?> diff --git a/php/TranslationStatistic.php b/php/TranslationStatistic.php index ffe95f81..7c102abb 100644 --- a/php/TranslationStatistic.php +++ b/php/TranslationStatistic.php @@ -1,302 +1,302 @@ -conn = DBConnection::getInstance(); - } - - /** - * Get number/size of all files. - * - * @param $lang Can be either 'all' for all availables languages, or one specific language - * @return An associated array - */ - public function getFileCount($lang='all') - { - $project = AccountManager::getInstance()->project; - - if( $lang == 'all' ) { - $s = 'SELECT - COUNT(*) AS total, - SUM(`size`) AS total_size, - `lang` - FROM - `files` - WHERE - (`status` != "NotInEN" OR `status` IS NULL ) AND - `project` = "%s" - GROUP BY `lang`'; - $params = array($project); - } else { - $s = 'SELECT - COUNT(*) AS total, - SUM(`size`) AS total_size, - `lang` - FROM - `files` - WHERE - `lang` = "%s" AND - (`status` != "NotInEN" OR `status` IS NULL ) AND - `project` = "%s"'; - $params = array($lang, $project); - } - $res = $this->conn->query($s, $params); - $result = array(); - while( $r = $res->fetch_array() ) { - $result[$r['lang']]['total'] = $r['total']; - $result[$r['lang']]['total_size'] = $r['total_size']; - } - return $result; - } - - /** - * Get number of translated files. - * - * @param $lang Can be either 'all' for all availables languages, or one specific language - * @return An associated array - */ - public function getTransFileCount($lang='all') - { - $project = AccountManager::getInstance()->project; - - $result = array(); - - if( $lang == 'all' ) { - $s = 'SELECT - COUNT(`name`) AS total, - SUM(`size`) AS total_size, - `lang` - FROM - `files` - WHERE - `revision` = `en_revision` AND - `revision` != "0" AND - `project` = "%s" - GROUP BY `lang`'; - $params = array($project); - } else { - $s = 'SELECT - COUNT(`name`) AS total, - SUM(`size`) AS total_size, - `lang` - FROM - `files` - WHERE - `lang` = "%s" AND - `revision` = `en_revision` AND - `revision` != "0" AND - `project` = "%s"'; - $params = array($lang, $project); - } - - $res = $this->conn->query($s, $params); - - while( $r = $res->fetch_array() ) { - $result[$r['lang']]['total'] = $r['total']; - $result[$r['lang']]['total_size'] = $r['total_size']; - } - return $result; - } - - /** - * Get statistic about stales files which need to be updated. - * - * @param $lang Can be either 'all' for all availables languages, or one specific language - * @return An associated array - */ - public function getStaleFileCount($lang='all') - { - $project = AccountManager::getInstance()->project; - - $result = array(); - - if( $lang == 'all' ) { - $s = 'SELECT - COUNT(`name`) AS total, - SUM(`size`) AS total_size, - `lang` - FROM - `files` - WHERE - `en_revision` != `revision` AND - `size` is not NULL AND - `project` = "%s" - GROUP BY `lang`'; - $params = array($project); - } else { - $s = 'SELECT - COUNT(`name`) AS total, - SUM(`size`) AS total_size, - `lang` - FROM - `files` - WHERE - `lang` = "%s" AND - `en_revision` != `revision` AND - `size` is not NULL AND - `project` = "%s"'; - $params = array($lang, $project); - } - - $res = $this->conn->query($s, $params); - - while( $r = $res->fetch_array() ) { - $result[$r['lang']]['total'] = $r['total']; - $result[$r['lang']]['total_size'] = $r['total_size']; - } - return $result; - } - - /** - * Get statistic about files which need to be translated. - * - * @param $lang Can be either 'all' for all availables languages, or one specific language - * @return An associated array - */ - public function getNoTransFileCount($lang='all') - { - $project = AccountManager::getInstance()->project; - - $result = $summary = array(); - - // We get EN files - - $s = 'SELECT * FROM files WHERE `lang`="en" AND `project`="%s"'; - $params = array($project); - $r = $this->conn->query($s, $params); - - while( $a = $r->fetch_object() ) { - $resultEN[$a->path.$a->name] = $a->size; - } - - if( $lang == 'all' ) { - $s = 'SELECT - `path`, `name`, `lang` - FROM - `files` - WHERE - `lang` != "en" AND - `revision` is NULL AND - `status` is NULL AND - `project` = "%s" - '; - $params = array($project); - } - else { - $s = 'SELECT - `path`, `name`, `lang` - FROM - `files` - WHERE - `lang` = "%s" AND - `revision` is NULL AND - `status` is NULL AND - `project` = "%s" - '; - $params = array($lang, $project); - } - - $r = $this->conn->query($s, $params); - - while( $a = $r->fetch_object() ) { - $result[$a->lang][$a->path.$a->name] = 'exist'; - } - - while( list($a, $b) = each($result) ) { - $size[$a] = 0; - while( list($k, $v) = each($result[$a]) ) { - $size[$a] += $resultEN[$k]; - } - } - - // - reset($result); - while( list($a, $b) = each($result) ) { - $summary[$a]['total'] = count($result[$a]); - $summary[$a]['total_size'] = $size[$a]; - } - return $summary; - } - - /** - * Compute summary of translation statistic and store it into DB - * - * @param $lang Can be either 'all' for all availables languages, or one specific language - */ - public function computeSummary($lang='all') - { - $rm = RepositoryManager::getInstance(); - $nbFiles = $this->getFileCount($lang); - $uptodate = $this->getTransFileCount($lang); - $stale = $this->getStaleFileCount($lang); - $missFiles = $this->getNoTransFileCount($lang); - - if( $lang == 'all' ) { - $hereLang = $rm->getExistingLanguage(); - } else { - $hereLang = array(0 => Array("code" => $lang)); - } - - foreach( $hereLang as $lang ) { - - $lang = $lang["code"]; - - if( $lang == 'en' ) { continue; } - - $summary = array(); - - $summary[0]['id'] = 1; - $summary[0]['libel'] = 'Up to date files'; - $summary[0]['nbFiles'] = ( isset($uptodate[$lang]['total']) ) ? $uptodate[$lang]['total'] : 0; - $summary[0]['percentFiles'] = ( isset($uptodate[$lang]['total']) ) ? round(($uptodate[$lang]['total']*100)/$nbFiles[$lang]['total'], 2) : 0; - $summary[0]['sizeFiles'] = ( !isset($uptodate[$lang]['total_size']) ) ? 0 : $uptodate[$lang]['total_size']; - $summary[0]['percentSize'] = (!isset($uptodate[$lang]['total_size']) || $uptodate[$lang]['total_size'] == 0 ) ? 0 : round(($uptodate[$lang]['total_size']*100)/$nbFiles[$lang]['total_size'], 2); - - $summary[1]['id'] = 2; - $summary[1]['libel'] = 'Stale files'; - $summary[1]['nbFiles'] = ( isset($stale[$lang]['total']) ) ? $stale[$lang]['total'] : 0; - $summary[1]['percentFiles'] = ( !isset($nbFiles[$lang]['total']) || !isset($stale[$lang]['total']) || $nbFiles[$lang]['total'] == 0 ) ? 0 : round(($stale[$lang]['total']*100)/$nbFiles[$lang]['total'], 2); - $summary[1]['sizeFiles'] = ( !isset($stale[$lang]['total_size']) || $stale[$lang]['total_size'] == '' ) ? 0 : $stale[$lang]['total_size']; - $summary[1]['percentSize'] = (!isset($stale[$lang]['total_size']) || $stale[$lang]['total_size'] == 0 ) ? 0 : round(($stale[$lang]['total_size']*100)/$nbFiles[$lang]['total_size'], 2); - - $summary[2]['id'] = 3; - $summary[2]['libel'] = 'Files available for translation'; - $summary[2]['nbFiles'] = ( isset($missFiles[$lang]['total']) ) ? $missFiles[$lang]['total'] : 0; - $summary[2]['percentFiles'] = ( isset($missFiles[$lang]['total']) ) ? round(($missFiles[$lang]['total']*100)/$nbFiles[$lang]['total'], 2) : 0; - $summary[2]['sizeFiles'] = ( isset($missFiles[$lang]['total_size']) ) ? $missFiles[$lang]['total_size'] : 0; - $summary[2]['percentSize'] = (!isset($missFiles[$lang]['total_size']) || $missFiles[$lang]['total_size'] == 0 || $nbFiles[$lang]['total_size'] == 0 ) ? 0 : round(($missFiles[$lang]['total_size']*100)/$nbFiles[$lang]['total_size'], 2); - - $summary[3]['id'] = 4; - $summary[3]['libel'] = 'Total'; - $summary[3]['nbFiles'] = ( isset($nbFiles[$lang]['total']) ) ? $nbFiles[$lang]['total'] : 0; - $summary[3]['percentFiles'] = '100%'; - $summary[3]['sizeFiles'] = ( isset($nbFiles[$lang]['total_size']) ) ? $nbFiles[$lang]['total_size'] : 0; - $summary[3]['percentSize'] = '100%'; - - // Save $summary into DB - $rm->setStaticValue('translation_summary', $lang, json_encode($summary)); - } - } - -} - -?> +conn = DBConnection::getInstance(); + } + + /** + * Get number/size of all files. + * + * @param $lang Can be either 'all' for all availables languages, or one specific language + * @return An associated array + */ + public function getFileCount($lang='all') + { + $project = AccountManager::getInstance()->project; + + if( $lang == 'all' ) { + $s = 'SELECT + COUNT(*) AS total, + SUM(`size`) AS total_size, + `lang` + FROM + `files` + WHERE + (`status` != "NotInEN" OR `status` IS NULL ) AND + `project` = "%s" + GROUP BY `lang`'; + $params = array($project); + } else { + $s = 'SELECT + COUNT(*) AS total, + SUM(`size`) AS total_size, + `lang` + FROM + `files` + WHERE + `lang` = "%s" AND + (`status` != "NotInEN" OR `status` IS NULL ) AND + `project` = "%s"'; + $params = array($lang, $project); + } + $res = $this->conn->query($s, $params); + $result = array(); + while( $r = $res->fetch_array() ) { + $result[$r['lang']]['total'] = $r['total']; + $result[$r['lang']]['total_size'] = $r['total_size']; + } + return $result; + } + + /** + * Get number of translated files. + * + * @param $lang Can be either 'all' for all availables languages, or one specific language + * @return An associated array + */ + public function getTransFileCount($lang='all') + { + $project = AccountManager::getInstance()->project; + + $result = array(); + + if( $lang == 'all' ) { + $s = 'SELECT + COUNT(`name`) AS total, + SUM(`size`) AS total_size, + `lang` + FROM + `files` + WHERE + `revision` = `en_revision` AND + `revision` != "0" AND + `project` = "%s" + GROUP BY `lang`'; + $params = array($project); + } else { + $s = 'SELECT + COUNT(`name`) AS total, + SUM(`size`) AS total_size, + `lang` + FROM + `files` + WHERE + `lang` = "%s" AND + `revision` = `en_revision` AND + `revision` != "0" AND + `project` = "%s"'; + $params = array($lang, $project); + } + + $res = $this->conn->query($s, $params); + + while( $r = $res->fetch_array() ) { + $result[$r['lang']]['total'] = $r['total']; + $result[$r['lang']]['total_size'] = $r['total_size']; + } + return $result; + } + + /** + * Get statistic about stales files which need to be updated. + * + * @param $lang Can be either 'all' for all availables languages, or one specific language + * @return An associated array + */ + public function getStaleFileCount($lang='all') + { + $project = AccountManager::getInstance()->project; + + $result = array(); + + if( $lang == 'all' ) { + $s = 'SELECT + COUNT(`name`) AS total, + SUM(`size`) AS total_size, + `lang` + FROM + `files` + WHERE + `en_revision` != `revision` AND + `size` is not NULL AND + `project` = "%s" + GROUP BY `lang`'; + $params = array($project); + } else { + $s = 'SELECT + COUNT(`name`) AS total, + SUM(`size`) AS total_size, + `lang` + FROM + `files` + WHERE + `lang` = "%s" AND + `en_revision` != `revision` AND + `size` is not NULL AND + `project` = "%s"'; + $params = array($lang, $project); + } + + $res = $this->conn->query($s, $params); + + while( $r = $res->fetch_array() ) { + $result[$r['lang']]['total'] = $r['total']; + $result[$r['lang']]['total_size'] = $r['total_size']; + } + return $result; + } + + /** + * Get statistic about files which need to be translated. + * + * @param $lang Can be either 'all' for all availables languages, or one specific language + * @return An associated array + */ + public function getNoTransFileCount($lang='all') + { + $project = AccountManager::getInstance()->project; + + $result = $summary = array(); + + // We get EN files + + $s = 'SELECT * FROM files WHERE `lang`="en" AND `project`="%s"'; + $params = array($project); + $r = $this->conn->query($s, $params); + + while( $a = $r->fetch_object() ) { + $resultEN[$a->path.$a->name] = $a->size; + } + + if( $lang == 'all' ) { + $s = 'SELECT + `path`, `name`, `lang` + FROM + `files` + WHERE + `lang` != "en" AND + `revision` is NULL AND + `status` is NULL AND + `project` = "%s" + '; + $params = array($project); + } + else { + $s = 'SELECT + `path`, `name`, `lang` + FROM + `files` + WHERE + `lang` = "%s" AND + `revision` is NULL AND + `status` is NULL AND + `project` = "%s" + '; + $params = array($lang, $project); + } + + $r = $this->conn->query($s, $params); + + while( $a = $r->fetch_object() ) { + $result[$a->lang][$a->path.$a->name] = 'exist'; + } + + while( list($a, $b) = each($result) ) { + $size[$a] = 0; + while( list($k, $v) = each($result[$a]) ) { + $size[$a] += $resultEN[$k]; + } + } + + // + reset($result); + while( list($a, $b) = each($result) ) { + $summary[$a]['total'] = count($result[$a]); + $summary[$a]['total_size'] = $size[$a]; + } + return $summary; + } + + /** + * Compute summary of translation statistic and store it into DB + * + * @param $lang Can be either 'all' for all availables languages, or one specific language + */ + public function computeSummary($lang='all') + { + $rm = RepositoryManager::getInstance(); + $nbFiles = $this->getFileCount($lang); + $uptodate = $this->getTransFileCount($lang); + $stale = $this->getStaleFileCount($lang); + $missFiles = $this->getNoTransFileCount($lang); + + if( $lang == 'all' ) { + $hereLang = $rm->getExistingLanguage(); + } else { + $hereLang = array(0 => Array("code" => $lang)); + } + + foreach( $hereLang as $lang ) { + + $lang = $lang["code"]; + + if( $lang == 'en' ) { continue; } + + $summary = array(); + + $summary[0]['id'] = 1; + $summary[0]['libel'] = 'Up to date files'; + $summary[0]['nbFiles'] = ( isset($uptodate[$lang]['total']) ) ? $uptodate[$lang]['total'] : 0; + $summary[0]['percentFiles'] = ( isset($uptodate[$lang]['total']) ) ? round(($uptodate[$lang]['total']*100)/$nbFiles[$lang]['total'], 2) : 0; + $summary[0]['sizeFiles'] = ( !isset($uptodate[$lang]['total_size']) ) ? 0 : $uptodate[$lang]['total_size']; + $summary[0]['percentSize'] = (!isset($uptodate[$lang]['total_size']) || $uptodate[$lang]['total_size'] == 0 ) ? 0 : round(($uptodate[$lang]['total_size']*100)/$nbFiles[$lang]['total_size'], 2); + + $summary[1]['id'] = 2; + $summary[1]['libel'] = 'Stale files'; + $summary[1]['nbFiles'] = ( isset($stale[$lang]['total']) ) ? $stale[$lang]['total'] : 0; + $summary[1]['percentFiles'] = ( !isset($nbFiles[$lang]['total']) || !isset($stale[$lang]['total']) || $nbFiles[$lang]['total'] == 0 ) ? 0 : round(($stale[$lang]['total']*100)/$nbFiles[$lang]['total'], 2); + $summary[1]['sizeFiles'] = ( !isset($stale[$lang]['total_size']) || $stale[$lang]['total_size'] == '' ) ? 0 : $stale[$lang]['total_size']; + $summary[1]['percentSize'] = (!isset($stale[$lang]['total_size']) || $stale[$lang]['total_size'] == 0 ) ? 0 : round(($stale[$lang]['total_size']*100)/$nbFiles[$lang]['total_size'], 2); + + $summary[2]['id'] = 3; + $summary[2]['libel'] = 'Files available for translation'; + $summary[2]['nbFiles'] = ( isset($missFiles[$lang]['total']) ) ? $missFiles[$lang]['total'] : 0; + $summary[2]['percentFiles'] = ( isset($missFiles[$lang]['total']) ) ? round(($missFiles[$lang]['total']*100)/$nbFiles[$lang]['total'], 2) : 0; + $summary[2]['sizeFiles'] = ( isset($missFiles[$lang]['total_size']) ) ? $missFiles[$lang]['total_size'] : 0; + $summary[2]['percentSize'] = (!isset($missFiles[$lang]['total_size']) || $missFiles[$lang]['total_size'] == 0 || $nbFiles[$lang]['total_size'] == 0 ) ? 0 : round(($missFiles[$lang]['total_size']*100)/$nbFiles[$lang]['total_size'], 2); + + $summary[3]['id'] = 4; + $summary[3]['libel'] = 'Total'; + $summary[3]['nbFiles'] = ( isset($nbFiles[$lang]['total']) ) ? $nbFiles[$lang]['total'] : 0; + $summary[3]['percentFiles'] = '100%'; + $summary[3]['sizeFiles'] = ( isset($nbFiles[$lang]['total_size']) ) ? $nbFiles[$lang]['total_size'] : 0; + $summary[3]['percentSize'] = '100%'; + + // Save $summary into DB + $rm->setStaticValue('translation_summary', $lang, json_encode($summary)); + } + } + +} + +?> diff --git a/php/TranslatorStatistic.php b/php/TranslatorStatistic.php index da4c5707..cf3de00d 100644 --- a/php/TranslatorStatistic.php +++ b/php/TranslatorStatistic.php @@ -1,365 +1,365 @@ -conn = DBConnection::getInstance(); - } - - /** - * Get translators information. - * - * @param $lang Can be either 'all' for all availables languages, or one specific language - * @return An associated array - */ - public function getTranslators($lang='all') - { - $project = AccountManager::getInstance()->project; - - if( $lang == 'all' ) { - $s = 'SELECT - `id`, `nick`, `name`, `mail`, `vcs`, `lang` - FROM - `translators` - WHERE - `project` = "%s" - '; - $params = array($project); - } else { - $s = 'SELECT - `id`, `nick`, `name`, `mail`, `vcs`, `lang` - FROM - `translators` - WHERE - `project` = "%s" AND - `lang` = "%s" - '; - $params = array($project, $lang); - } - - $result = $this->conn->query($s, $params); - - $persons = array(); - - while ($r = $result->fetch_object()) { - $persons[$r->lang][$r->nick] = array( - 'id' => $r->id, - 'name' => utf8_encode($r->name), - 'mail' => $r->mail, - 'vcs' => $r->vcs - ); - } - return $persons; - } - - /** - * Get number of uptodate files per translators. - * - * @param $lang Can be either 'all' for all availables languages, or one specific language - * @return An associated array - */ - public function getUptodateFileCount($lang='all') - { - $project = AccountManager::getInstance()->project; - - if( $lang == 'all' ) { - $s = 'SELECT - COUNT(`name`) AS total, - `maintainer`, - `lang` - FROM - `files` - WHERE - `revision` = `en_revision` AND - `project` = "%s" - GROUP BY - `maintainer` - ORDER BY - `maintainer` - '; - $params = array($project); - } else { - $s = 'SELECT - COUNT(`name`) AS total, - `maintainer`, - `lang` - FROM - `files` - WHERE - `lang` = "%s" AND - `revision` = `en_revision` AND - `project` = "%s" - GROUP BY - `maintainer` - ORDER BY - `maintainer` - '; - $params = array($lang, $project); - } - - $r = $this->conn->query($s, $params); - - $result = array(); - while ($a = $r->fetch_object()) { - $result[$a->lang][$a->maintainer] = $a->total; - } - return $result; - } - - /** - * Get number of uptodate reviewed files per translators. - * - * @param $lang Can be either 'all' for all availables languages, or one specific language - * @return An associated array - */ - public function getReviewedUptodateFileCount($lang='all') - { - $project = AccountManager::getInstance()->project; - - if( $lang == 'all' ) { - $s = 'SELECT - COUNT(`name`) AS total, - `reviewed_maintainer`, - `lang` - FROM - `files` - WHERE - `revision` = `en_revision` AND - `reviewed` = "yes" AND - `project` = "%s" - GROUP BY - `reviewed_maintainer` - ORDER BY - `reviewed_maintainer` - '; - $params = array($project); - } else { - $s = 'SELECT - COUNT(`name`) AS total, - `reviewed_maintainer`, - `lang` - FROM - `files` - WHERE - `lang` = "%s" AND - `revision` = `en_revision` AND - `reviewed` = "yes" AND - `project` = "%s" - GROUP BY - `reviewed_maintainer` - ORDER BY - `reviewed_maintainer` - '; - $params = array($lang, $project); - } - - $r = $this->conn->query($s, $params); - - $result = array(); - while ($a = $r->fetch_object()) { - $result[$a->lang][$a->reviewed_maintainer] = $a->total; - } - return $result; - } - - /** - * Get number of old files per translators. - * - * @param $lang Can be either 'all' for all availables languages, or one specific language - * @return An associated array - */ - public function getStaleFileCount($lang='all') - { - $project = AccountManager::getInstance()->project; - - if( $lang == 'all' ) { - $s = 'SELECT - COUNT(`name`) AS total, - `maintainer`, - `lang` - FROM - `files` - WHERE - `en_revision` != `revision` - AND - `size` is not NULL - AND - `project` = "%s" - GROUP BY - `maintainer` - ORDER BY - `maintainer` - '; - $params = array($project); - } else { - $s = 'SELECT - COUNT(`name`) AS total, - `maintainer`, - `lang` - FROM - `files` - WHERE - `lang` = "%s" - AND - `en_revision` != `revision` - AND - `size` is not NULL - AND - `project` = "%s" - GROUP BY - `maintainer` - ORDER BY - `maintainer` - '; - $params = array($lang, $project); - } - - $r = $this->conn->query($s, $params); - - $result = array(); - while ($a = $r->fetch_object()) { - $result[$a->lang][$a->maintainer] = $a->total; - } - return $result; - } - - /** - * Get number of old reviewed files per translators. - * - * @param $lang Can be either 'all' for all availables languages, or one specific language - * @return An associated array - */ - public function getReviewedStaleFileCount($lang='all') - { - $project = AccountManager::getInstance()->project; - - if( $lang == 'all' ) { - $s = 'SELECT - COUNT(`name`) AS total, - `reviewed_maintainer`, - `lang` - - FROM - `files` - - WHERE - `en_revision` = `revision` AND - `reviewed` != "yes" AND - `size` is not NULL AND - `project` = "%s" - - GROUP BY - `reviewed_maintainer` - - ORDER BY - `reviewed_maintainer` - '; - $params = array($project); - } else { - $s = 'SELECT - COUNT(`name`) AS total, - `reviewed_maintainer`, - `lang` - - FROM - `files` - - WHERE - `lang` = "%s" AND - `en_revision` = `revision` AND - `reviewed` != "yes" AND - `size` is not NULL AND - `project` = "%s" - - GROUP BY - `reviewed_maintainer` - - ORDER BY - `reviewed_maintainer` - '; - $params = array($lang, $project); - } - - $r = $this->conn->query($s, $params); - - $result = array(); - while ($a = $r->fetch_object()) { - $result[$a->lang][$a->reviewed_maintainer] = $a->total; - } - return $result; - } - - /** - * Compute statistics summary about translators and store it into DB - * - * @param $lang Can be either 'all' for all availables languages, or one specific language - */ - public function computeSummary($lang='all') - { - $rm = RepositoryManager::getInstance(); - - $translators = $this->getTranslators($lang); - $uptodate = $this->getUptodateFileCount($lang); - $stale = $this->getStaleFileCount($lang); - - $reviewedUptodate = $this->getReviewedUptodateFileCount($lang); - $reviewedStale = $this->getReviewedStaleFileCount($lang); - - if( $lang == 'all' ) { - $hereLang = $rm->getExistingLanguage(); - } else { - $hereLang = array(0 => Array("code" => $lang)); - } - - foreach( $hereLang as $lang ) { - - $lang = $lang["code"]; - - if( $lang == 'en' ) { continue; } - - $i=0; $persons=array(); - - if( isset($translators[$lang]) ) { - - foreach ($translators[$lang] as $nick => $data) { - $persons[$i] = $data; - $persons[$i]['nick'] = $nick; - - $persons[$i]['uptodate'] = isset($uptodate[$lang][$nick]) ? $uptodate[$lang][$nick] : '0'; - $persons[$i]['stale'] = isset($stale[$lang][$nick]) ? $stale[$lang][$nick] : '0'; - $persons[$i]['sum'] = $persons[$i]['uptodate'] + $persons[$i]['stale']; - - $persons[$i]['reviewedUptodate'] = isset($reviewedUptodate[$lang][$nick]) ? $reviewedUptodate[$lang][$nick] : '0'; - $persons[$i]['reviewedStale'] = isset($reviewedStale[$lang][$nick]) ? $reviewedStale[$lang][$nick] : '0'; - $persons[$i]['reviewedSum'] = $persons[$i]['reviewedUptodate'] + $persons[$i]['reviewedStale']; - - $i++; - } - - // Save $summary into DB - $rm->setStaticValue('translator_summary', $lang, json_encode($persons)); - } - } - } -} - -?> +conn = DBConnection::getInstance(); + } + + /** + * Get translators information. + * + * @param $lang Can be either 'all' for all availables languages, or one specific language + * @return An associated array + */ + public function getTranslators($lang='all') + { + $project = AccountManager::getInstance()->project; + + if( $lang == 'all' ) { + $s = 'SELECT + `id`, `nick`, `name`, `mail`, `vcs`, `lang` + FROM + `translators` + WHERE + `project` = "%s" + '; + $params = array($project); + } else { + $s = 'SELECT + `id`, `nick`, `name`, `mail`, `vcs`, `lang` + FROM + `translators` + WHERE + `project` = "%s" AND + `lang` = "%s" + '; + $params = array($project, $lang); + } + + $result = $this->conn->query($s, $params); + + $persons = array(); + + while ($r = $result->fetch_object()) { + $persons[$r->lang][$r->nick] = array( + 'id' => $r->id, + 'name' => utf8_encode($r->name), + 'mail' => $r->mail, + 'vcs' => $r->vcs + ); + } + return $persons; + } + + /** + * Get number of uptodate files per translators. + * + * @param $lang Can be either 'all' for all availables languages, or one specific language + * @return An associated array + */ + public function getUptodateFileCount($lang='all') + { + $project = AccountManager::getInstance()->project; + + if( $lang == 'all' ) { + $s = 'SELECT + COUNT(`name`) AS total, + `maintainer`, + `lang` + FROM + `files` + WHERE + `revision` = `en_revision` AND + `project` = "%s" + GROUP BY + `maintainer` + ORDER BY + `maintainer` + '; + $params = array($project); + } else { + $s = 'SELECT + COUNT(`name`) AS total, + `maintainer`, + `lang` + FROM + `files` + WHERE + `lang` = "%s" AND + `revision` = `en_revision` AND + `project` = "%s" + GROUP BY + `maintainer` + ORDER BY + `maintainer` + '; + $params = array($lang, $project); + } + + $r = $this->conn->query($s, $params); + + $result = array(); + while ($a = $r->fetch_object()) { + $result[$a->lang][$a->maintainer] = $a->total; + } + return $result; + } + + /** + * Get number of uptodate reviewed files per translators. + * + * @param $lang Can be either 'all' for all availables languages, or one specific language + * @return An associated array + */ + public function getReviewedUptodateFileCount($lang='all') + { + $project = AccountManager::getInstance()->project; + + if( $lang == 'all' ) { + $s = 'SELECT + COUNT(`name`) AS total, + `reviewed_maintainer`, + `lang` + FROM + `files` + WHERE + `revision` = `en_revision` AND + `reviewed` = "yes" AND + `project` = "%s" + GROUP BY + `reviewed_maintainer` + ORDER BY + `reviewed_maintainer` + '; + $params = array($project); + } else { + $s = 'SELECT + COUNT(`name`) AS total, + `reviewed_maintainer`, + `lang` + FROM + `files` + WHERE + `lang` = "%s" AND + `revision` = `en_revision` AND + `reviewed` = "yes" AND + `project` = "%s" + GROUP BY + `reviewed_maintainer` + ORDER BY + `reviewed_maintainer` + '; + $params = array($lang, $project); + } + + $r = $this->conn->query($s, $params); + + $result = array(); + while ($a = $r->fetch_object()) { + $result[$a->lang][$a->reviewed_maintainer] = $a->total; + } + return $result; + } + + /** + * Get number of old files per translators. + * + * @param $lang Can be either 'all' for all availables languages, or one specific language + * @return An associated array + */ + public function getStaleFileCount($lang='all') + { + $project = AccountManager::getInstance()->project; + + if( $lang == 'all' ) { + $s = 'SELECT + COUNT(`name`) AS total, + `maintainer`, + `lang` + FROM + `files` + WHERE + `en_revision` != `revision` + AND + `size` is not NULL + AND + `project` = "%s" + GROUP BY + `maintainer` + ORDER BY + `maintainer` + '; + $params = array($project); + } else { + $s = 'SELECT + COUNT(`name`) AS total, + `maintainer`, + `lang` + FROM + `files` + WHERE + `lang` = "%s" + AND + `en_revision` != `revision` + AND + `size` is not NULL + AND + `project` = "%s" + GROUP BY + `maintainer` + ORDER BY + `maintainer` + '; + $params = array($lang, $project); + } + + $r = $this->conn->query($s, $params); + + $result = array(); + while ($a = $r->fetch_object()) { + $result[$a->lang][$a->maintainer] = $a->total; + } + return $result; + } + + /** + * Get number of old reviewed files per translators. + * + * @param $lang Can be either 'all' for all availables languages, or one specific language + * @return An associated array + */ + public function getReviewedStaleFileCount($lang='all') + { + $project = AccountManager::getInstance()->project; + + if( $lang == 'all' ) { + $s = 'SELECT + COUNT(`name`) AS total, + `reviewed_maintainer`, + `lang` + + FROM + `files` + + WHERE + `en_revision` = `revision` AND + `reviewed` != "yes" AND + `size` is not NULL AND + `project` = "%s" + + GROUP BY + `reviewed_maintainer` + + ORDER BY + `reviewed_maintainer` + '; + $params = array($project); + } else { + $s = 'SELECT + COUNT(`name`) AS total, + `reviewed_maintainer`, + `lang` + + FROM + `files` + + WHERE + `lang` = "%s" AND + `en_revision` = `revision` AND + `reviewed` != "yes" AND + `size` is not NULL AND + `project` = "%s" + + GROUP BY + `reviewed_maintainer` + + ORDER BY + `reviewed_maintainer` + '; + $params = array($lang, $project); + } + + $r = $this->conn->query($s, $params); + + $result = array(); + while ($a = $r->fetch_object()) { + $result[$a->lang][$a->reviewed_maintainer] = $a->total; + } + return $result; + } + + /** + * Compute statistics summary about translators and store it into DB + * + * @param $lang Can be either 'all' for all availables languages, or one specific language + */ + public function computeSummary($lang='all') + { + $rm = RepositoryManager::getInstance(); + + $translators = $this->getTranslators($lang); + $uptodate = $this->getUptodateFileCount($lang); + $stale = $this->getStaleFileCount($lang); + + $reviewedUptodate = $this->getReviewedUptodateFileCount($lang); + $reviewedStale = $this->getReviewedStaleFileCount($lang); + + if( $lang == 'all' ) { + $hereLang = $rm->getExistingLanguage(); + } else { + $hereLang = array(0 => Array("code" => $lang)); + } + + foreach( $hereLang as $lang ) { + + $lang = $lang["code"]; + + if( $lang == 'en' ) { continue; } + + $i=0; $persons=array(); + + if( isset($translators[$lang]) ) { + + foreach ($translators[$lang] as $nick => $data) { + $persons[$i] = $data; + $persons[$i]['nick'] = $nick; + + $persons[$i]['uptodate'] = isset($uptodate[$lang][$nick]) ? $uptodate[$lang][$nick] : '0'; + $persons[$i]['stale'] = isset($stale[$lang][$nick]) ? $stale[$lang][$nick] : '0'; + $persons[$i]['sum'] = $persons[$i]['uptodate'] + $persons[$i]['stale']; + + $persons[$i]['reviewedUptodate'] = isset($reviewedUptodate[$lang][$nick]) ? $reviewedUptodate[$lang][$nick] : '0'; + $persons[$i]['reviewedStale'] = isset($reviewedStale[$lang][$nick]) ? $reviewedStale[$lang][$nick] : '0'; + $persons[$i]['reviewedSum'] = $persons[$i]['reviewedUptodate'] + $persons[$i]['reviewedStale']; + + $i++; + } + + // Save $summary into DB + $rm->setStaticValue('translator_summary', $lang, json_encode($persons)); + } + } + } +} + +?> diff --git a/php/loader.php b/php/loader.php index e704f976..439c71f0 100755 --- a/php/loader.php +++ b/php/loader.php @@ -1,12 +1,12 @@ - \ No newline at end of file diff --git a/php/utility.php b/php/utility.php index 91bf8354..41a7f03c 100644 --- a/php/utility.php +++ b/php/utility.php @@ -1,70 +1,70 @@ -appConf; - $project = $am->project; - - $mess = '['.@date('d/m/Y H:i:s').'] by ' - .$am->vcsLogin.' : '.str_replace("\r\n", " ", $mess)."\n"; - - $fp = fopen($appConf[$project]['vcs.path'].'../.debug', 'a+'); - fwrite($fp, $mess); - fclose($fp); -} - -function errlog($mess) -{ - $am = AccountManager::getInstance(); - $appConf = $am->appConf; - $project = $am->project; - - $mess = '['.@date('d/m/Y H:i:s').'] by ' - .$am->vcsLogin.' : '.str_replace("\r\n", " ", $mess)."\n"; - - $fp = fopen($appConf[$project]['vcs.path'].'../.errlog', 'a+'); - fwrite($fp, $mess); - fclose($fp); -} - -function elapsedTime($startDate, $endDate) { - - $return = array(); - - $units = Array( - 'year(s)' => 12 *4*7*24*60*60, - 'month(s)' => 4 *7*24*60*60, - 'week(s)' => 7 *24*60*60, - 'day(s)' => 24*60*60, - 'hour(s)' => 60*60, - 'minute(s)' => 60, - 'second(s)' => 1 - ); - - $startDate = strtotime($startDate); - $endDate = strtotime($endDate); - - $seconds = floor(($endDate - $startDate)); - - if( $seconds < 1 ) { - return ''; - } - - while( list($k, $v) = each($units) ) { - - if( ($seconds / $v) >= 1 || $k == 'seconds' ) { - $secondsConverted = floor($seconds / $v); - return Array('units' => $k, - 'value' => $secondsConverted); - } - - } -} -?> +appConf; + $project = $am->project; + + $mess = '['.@date('d/m/Y H:i:s').'] by ' + .$am->vcsLogin.' : '.str_replace("\r\n", " ", $mess)."\n"; + + $fp = fopen($appConf[$project]['vcs.path'].'../.debug', 'a+'); + fwrite($fp, $mess); + fclose($fp); +} + +function errlog($mess) +{ + $am = AccountManager::getInstance(); + $appConf = $am->appConf; + $project = $am->project; + + $mess = '['.@date('d/m/Y H:i:s').'] by ' + .$am->vcsLogin.' : '.str_replace("\r\n", " ", $mess)."\n"; + + $fp = fopen($appConf[$project]['vcs.path'].'../.errlog', 'a+'); + fwrite($fp, $mess); + fclose($fp); +} + +function elapsedTime($startDate, $endDate) { + + $return = array(); + + $units = Array( + 'year(s)' => 12 *4*7*24*60*60, + 'month(s)' => 4 *7*24*60*60, + 'week(s)' => 7 *24*60*60, + 'day(s)' => 24*60*60, + 'hour(s)' => 60*60, + 'minute(s)' => 60, + 'second(s)' => 1 + ); + + $startDate = strtotime($startDate); + $endDate = strtotime($endDate); + + $seconds = floor(($endDate - $startDate)); + + if( $seconds < 1 ) { + return ''; + } + + while( list($k, $v) = each($units) ) { + + if( ($seconds / $v) >= 1 || $k == 'seconds' ) { + $secondsConverted = floor($seconds / $v); + return Array('units' => $k, + 'value' => $secondsConverted); + } + + } +} +?>