From 6f5ec321d1f89befdd4c55de13d07afc2932081f Mon Sep 17 00:00:00 2001 From: wyd621 Date: Fri, 16 Aug 2013 10:50:07 +0800 Subject: [PATCH 01/26] * fix a bug. --- module/common/model.php | 2 +- www/js/jquery/form/zentao.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/module/common/model.php b/module/common/model.php index cbad95c533..e637dc9c92 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -619,7 +619,7 @@ class commonModel extends model } else { - $objects = $this->dbh->query($queryCondition . "OR id=$objectID ORDER BY $orderBy")->fetchAll(); + $objects = $this->dbh->query($queryCondition . " ORDER BY $orderBy")->fetchAll(); } $tmpObjectIDs = array(); diff --git a/www/js/jquery/form/zentao.js b/www/js/jquery/form/zentao.js index d263372581..7f3e23d999 100644 --- a/www/js/jquery/form/zentao.js +++ b/www/js/jquery/form/zentao.js @@ -13,8 +13,11 @@ $.extend( { $.enableForm(formID); + /* try parse to json when response is json's string. */ + try{if(typeof(response) == 'string') response = JSON.parse(response);}catch(e){} + /* The response is not an object, some error occers, alert it. */ - if($.type(response) != 'object') + if(typeof(response) != 'object') { if(response) return alert(response); return alert('No response.'); From 123bb5d8c6a3adda689ff874da7fa26a6d92d6c0 Mon Sep 17 00:00:00 2001 From: wyd621 Date: Mon, 19 Aug 2013 09:23:58 +0800 Subject: [PATCH 02/26] * fix a bug for dropmenu. --- module/common/view/dropmenu.html.php | 7 ++----- tools/minifyfront.php | 2 -- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/module/common/view/dropmenu.html.php b/module/common/view/dropmenu.html.php index 878668155f..4521506b4b 100644 --- a/module/common/view/dropmenu.html.php +++ b/module/common/view/dropmenu.html.php @@ -1,8 +1,5 @@ getExtViewFile(__FILE__)){include $extView; return helper::cd();}?> debug) -{ - css::import($defaultTheme . 'dropmenu.css'); - js::import($jsRoot . 'jquery/dropmenu/dropmenu.js'); -} +css::import($defaultTheme . 'dropmenu.css'); +js::import($jsRoot . 'jquery/dropmenu/dropmenu.js'); ?> diff --git a/tools/minifyfront.php b/tools/minifyfront.php index 8bf7b82796..747ce05f8d 100755 --- a/tools/minifyfront.php +++ b/tools/minifyfront.php @@ -21,7 +21,6 @@ $jsFiles[] = $jqueryRoot . 'datepicker/date.js'; $jsFiles[] = $jqueryRoot . 'datepicker/min.js'; $jsFiles[] = $jqueryRoot . 'alert/min.js'; $jsFiles[] = $jqueryRoot . 'colorize/min.js'; -$jsFiles[] = $jqueryRoot . 'dropmenu/dropmenu.js'; /* Combine these js files. */ $allJSFile = $jsRoot . 'all.js'; @@ -71,7 +70,6 @@ foreach($langs as $lang) $cssCode .= file_get_contents($themeRoot . 'default/treeview.css'); $cssCode .= file_get_contents($themeRoot . 'default/datepicker.css'); $cssCode .= file_get_contents($themeRoot . 'default/alert.css'); - $cssCode .= file_get_contents($themeRoot . 'default/dropmenu.css'); /* Css file for current lang and current them. */ $cssCode .= file_get_contents($themeRoot . "lang/$lang.css"); From ba58f898b47ad535cbdb009dcbd327bb1d918ba2 Mon Sep 17 00:00:00 2001 From: xia0ta0 Date: Mon, 19 Aug 2013 14:50:02 +0800 Subject: [PATCH 03/26] * use ',' between repo accounts. --- module/user/model.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/module/user/model.php b/module/user/model.php index b1cd4077fb..5f740b3970 100644 --- a/module/user/model.php +++ b/module/user/model.php @@ -115,7 +115,14 @@ class userModel extends model if(!$rawCommiters) return array(); $commiters = array(); - foreach($rawCommiters as $commiter) $commiters[$commiter->commiter] = $commiter->realname ? $commiter->realname : $commiter->account; + foreach($rawCommiters as $commiter) + { + $userCommiters = explode(',', $commiter->commiter); + foreach($userCommiters as $userCommiter) + { + $commiters[$userCommiter] = $commiter->realname ? $commiter->realname : $commiter->account; + } + } return $commiters; } From 67a9c68636f2c24152c767f73802697e6c63a4fc Mon Sep 17 00:00:00 2001 From: wyd621 Date: Mon, 19 Aug 2013 15:43:35 +0800 Subject: [PATCH 04/26] * finish task #1396. --- module/testcase/control.php | 13 --- module/testcase/lang/en.php | 3 +- module/testcase/lang/zh-cn.php | 3 +- module/testcase/view/showimport.html.php | 102 ++++++++++------------- 4 files changed, 45 insertions(+), 76 deletions(-) diff --git a/module/testcase/control.php b/module/testcase/control.php index b9cddebc7b..e0b2b321e5 100644 --- a/module/testcase/control.php +++ b/module/testcase/control.php @@ -814,8 +814,6 @@ class testcase extends control $endField = $field; $caseData = array(); $stepData = array(); - $hasEdit = false; - $hasNew = false; while($csv) { $case = new stdclass(); @@ -889,15 +887,6 @@ class testcase extends control $csv = substr($csv, $pos + strlen($delimiter)); } - if(!empty($case->id)) - { - $hasEdit = true; - } - else - { - $hasNew = true; - } - $caseData[$row] = $case; unset($case); $row++; @@ -919,8 +908,6 @@ class testcase extends control $this->view->stepData = $stepData; $this->view->productID = $productID; $this->view->product = $this->products[$productID]; - $this->view->hasEdit = $hasEdit; - $this->view->hasNew = $hasNew; $this->display(); } } diff --git a/module/testcase/lang/en.php b/module/testcase/lang/en.php index 3c943d2679..0b24d72915 100644 --- a/module/testcase/lang/en.php +++ b/module/testcase/lang/en.php @@ -69,8 +69,7 @@ $lang->testcase->export = "Export data"; $lang->testcase->confirmChange = 'Confirm case change'; $lang->testcase->confirmStoryChange = 'Confirm story change'; -$lang->testcase->editHaved = 'Modify existing case'; -$lang->testcase->addNew = 'Add new case'; +$lang->testcase->new = 'New'; $lang->testcase->num = 'The number of cases'; diff --git a/module/testcase/lang/zh-cn.php b/module/testcase/lang/zh-cn.php index 39c17a6ae9..94631b3dec 100644 --- a/module/testcase/lang/zh-cn.php +++ b/module/testcase/lang/zh-cn.php @@ -69,8 +69,7 @@ $lang->testcase->export = "导出数据"; $lang->testcase->confirmChange = '确认用例变动'; $lang->testcase->confirmStoryChange = '确认需求变动'; -$lang->testcase->editHaved = '修改已有用例'; -$lang->testcase->addNew = '添加新用例'; +$lang->testcase->new = '新增'; $lang->testcase->num = '导入用例个数:'; diff --git a/module/testcase/view/showimport.html.php b/module/testcase/view/showimport.html.php index ecd39360ef..0ef4eab98b 100644 --- a/module/testcase/view/showimport.html.php +++ b/module/testcase/view/showimport.html.php @@ -1,8 +1,9 @@ +
- - @@ -24,13 +25,24 @@ $case):?> - id)) continue?> - + - - - + + + @@ -52,58 +64,30 @@
testcase->editHaved?>
testcase->id?> testcase->title?>
id . html::hidden("id[$key]", $case->id) . html::hidden("product[$key]", $productID)?> + id)) + { + echo $case->id . html::hidden("id[$key]", $case->id); + } + else + { + echo $key . " {$lang->testcase->new}"; + } + echo html::hidden("product[$key]", $productID); + ?> + title, "class='text-1' style='margin-top:2px'")?>module) ? $case->module : $cases[$case->id]->module, "class='select-2'")?>story) ? $case->story : $cases[$case->id]->story, "class='select-2'")?>testcase->priList, isset($case->pri) ? $case->pri : $cases[$case->id]->pri)?>module) ? $case->module : (isset($case->id) ? $cases[$case->id]->module : ''), "class='select-2'")?>story) ? $case->story : (isset($case->id) ? $cases[$case->id]->story : ''), "class='select-2'")?>testcase->priList, isset($case->pri) ? $case->pri : (isset($case->id) ? $cases[$case->id]->pri : ''))?> testcase->typeList, $case->type)?> testcase->statusList, isset($case->status) ? $case->status : '')?> frequency) ? $case->frequency : 1, "size='2'")?>
- - - - - - - - - - - - - - - - - - $case):?> - - - - - - - - - - - - - - -
testcase->addNew?>
testcase->importID?>testcase->title?>testcase->module?>testcase->story?>testcase->pri?>testcase->type?>testcase->status?>testcase->frequency?>testcase->stage?>testcase->precondition?>testcase->steps?> - - - - - -
testcase->stepDesc?>testcase->stepExpect?>
-
title, "class='text-1' style='margin-top:2px'")?>module) ? $case->module : '', "class='select-2'") . html::hidden("product[$key]", $productID)?>story) ? $case->story : '', "class='select-2'")?>testcase->priList, isset($case->pri) ? $case->pri : '')?>testcase->typeList, $case->type)?>testcase->statusList, isset($case->status) ? $case->status : 'normal')?>frequency) ? $case->frequency : 1, "size='2'")?>testcase->stageList, isset($case->stage) ? $case->stage : '', "multiple='multiple'")?>precondition) ? $case->precondition : "", "style='margin-top:2px; height:69px'")?> - - - $desc):?> - - - - - -
- -
-

+ From 3079ce5fa56362cdfed69d83b50a5d6518d7f773 Mon Sep 17 00:00:00 2001 From: wyd621 Date: Tue, 20 Aug 2013 08:27:10 +0800 Subject: [PATCH 05/26] * fix js error. --- module/testcase/view/exporttemplet.html.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/module/testcase/view/exporttemplet.html.php b/module/testcase/view/exporttemplet.html.php index cd6a6d3da4..b9b12109a1 100644 --- a/module/testcase/view/exporttemplet.html.php +++ b/module/testcase/view/exporttemplet.html.php @@ -11,13 +11,12 @@ function setDownloading() function closeWindow() { - if($.cookie('downloading') == 1 || i >= 30) + if($.cookie('downloading') == 1) { parent.$.fn.colorbox.close(); $.cookie('downloading', null); clearInterval(time); } - i ++; }
From 667110a5ca60cd17130e40f75d26f3890e1d9fbd Mon Sep 17 00:00:00 2001 From: wyd621 Date: Tue, 20 Aug 2013 11:28:27 +0800 Subject: [PATCH 06/26] * finish task #1400. --- module/common/model.php | 3 --- module/story/control.php | 1 + module/task/control.php | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/module/common/model.php b/module/common/model.php index e637dc9c92..2ce01a9975 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -683,9 +683,6 @@ class commonModel extends model $orderBy = explode('limit', $orderBy[1]); $orderBy = str_replace('t1.', '', $orderBy[0]); - /* Fix bug #448. I don't know why too. */ - if($orderBy == 'yes') $orderBy = ''; - $this->session->set($objectType . 'OrderBy', $orderBy); } else diff --git a/module/story/control.php b/module/story/control.php index d35074d55a..8d6438b5c9 100644 --- a/module/story/control.php +++ b/module/story/control.php @@ -1035,6 +1035,7 @@ class story extends control if(isset($storyLang->statusList[$story->status])) $story->status = $storyLang->statusList[$story->status]; if(isset($storyLang->stageList[$story->stage])) $story->stage = $storyLang->stageList[$story->stage]; if(isset($storyLang->reasonList[$story->closedReason])) $story->closedReason = $storyLang->reasonList[$story->closedReason]; + if(isset($storyLang->sourceList[$story->source])) $story->source = $storyLang->sourceList[$story->source]; if(isset($users[$story->openedBy])) $story->openedBy = $users[$story->openedBy]; if(isset($users[$story->assignedTo])) $story->assignedTo = $users[$story->assignedTo]; diff --git a/module/task/control.php b/module/task/control.php index d5f78a1d42..64d4f9bdfe 100644 --- a/module/task/control.php +++ b/module/task/control.php @@ -936,6 +936,7 @@ class task extends control /* Get related objects title or names. */ $relatedStories = $this->dao->select('id,title')->from(TABLE_STORY) ->where('id')->in($relatedStoryIdList)->fetchPairs(); $relatedFiles = $this->dao->select('id, objectID, pathname, title')->from(TABLE_FILE)->where('objectType')->eq('task')->andWhere('objectID')->in(@array_keys($tasks))->fetchGroup('objectID'); + $relatedModules = $this->loadModel('tree')->getTaskOptionMenu($projectID); foreach($tasks as $task) { @@ -954,6 +955,7 @@ class task extends control if(isset($taskLang->priList[$task->pri])) $task->pri = $taskLang->priList[$task->pri]; if(isset($taskLang->statusList[$task->status])) $task->status = $taskLang->statusList[$task->status]; if(isset($taskLang->reasonList[$task->closedReason])) $task->closedReason = $taskLang->reasonList[$task->closedReason]; + if(isset($relatedModules[$task->module])) $task->module = $relatedModules[$task->module]; if(isset($users[$task->openedBy])) $task->openedBy = $users[$task->openedBy]; if(isset($users[$task->assignedTo])) $task->assignedTo = $users[$task->assignedTo]; From 7fd864fcf9e534396053d63f882b5cfb4513e139 Mon Sep 17 00:00:00 2001 From: wyd621 Date: Tue, 20 Aug 2013 16:05:53 +0800 Subject: [PATCH 07/26] * fix a bug for bug tempate when create bug. --- module/common/view/kindeditor.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/common/view/kindeditor.html.php b/module/common/view/kindeditor.html.php index 420585fbcb..918b3bc8e6 100755 --- a/module/common/view/kindeditor.html.php +++ b/module/common/view/kindeditor.html.php @@ -44,7 +44,7 @@ $(document).ready(function() KindEditor.ready(function(K) { - keEditor = K.create('#' + editorID, + editor = K.create('#' + editorID, { items:editorTool, filterMode:true, From 30dd77cfabf16156dd7fe60ca1c2974267775d7a Mon Sep 17 00:00:00 2001 From: wyd621 Date: Tue, 20 Aug 2013 16:06:17 +0800 Subject: [PATCH 08/26] * finish task #1392. --- module/testcase/model.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/module/testcase/model.php b/module/testcase/model.php index 6c50a5abe5..e8317d27b2 100644 --- a/module/testcase/model.php +++ b/module/testcase/model.php @@ -538,5 +538,8 @@ class testcaseModel extends model } } } + + unlink($this->session->importFile); + unset($_SESSION['importFile']); } } From a1e80ec59ce92ed30ed98dd1337e50e1add4ff37 Mon Sep 17 00:00:00 2001 From: azhi Date: Wed, 21 Aug 2013 08:52:22 +0800 Subject: [PATCH 09/26] * finish task#1388. --- module/task/view/create.html.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/module/task/view/create.html.php b/module/task/view/create.html.php index 9173ac73b5..e2025f9e86 100644 --- a/module/task/view/create.html.php +++ b/module/task/view/create.html.php @@ -30,6 +30,10 @@ task->assignedTo;?> assignedTo, 'class=select-3');?> + + task->type;?> + task->typeList, $task->type, 'class=select-3 onchange="setOwners(this.value)"');?> + task->story;?> @@ -65,10 +69,6 @@ task->deadline;?> deadline, "class='text-3 date'");?> - - task->type;?> - task->typeList, $task->type, 'class=select-3 onchange="setOwners(this.value)"');?> - task->mailto;?> From 746cbf28995f6eb07ff31529a640fc2197b83de3 Mon Sep 17 00:00:00 2001 From: azhi Date: Wed, 21 Aug 2013 09:52:20 +0800 Subject: [PATCH 10/26] * finish task#1395. --- module/bug/view/browse.html.php | 2 +- module/product/view/browse.html.php | 2 +- module/project/view/task.html.php | 2 +- module/testcase/view/browse.html.php | 2 +- www/js/my.full.js | 50 ++++++++++++++++++++++------ www/theme/default/style.css | 1 + 6 files changed, 45 insertions(+), 14 deletions(-) diff --git a/module/bug/view/browse.html.php b/module/bug/view/browse.html.php index e7a25d3d58..fafdbb27af 100644 --- a/module/bug/view/browse.html.php +++ b/module/bug/view/browse.html.php @@ -72,7 +72,7 @@ js::set('customed', $customed); } ?> -
 
+
 
diff --git a/module/product/view/browse.html.php b/module/product/view/browse.html.php index c3f600b5c0..870e79b8f8 100644 --- a/module/product/view/browse.html.php +++ b/module/product/view/browse.html.php @@ -52,7 +52,7 @@
'>
-
 
+
 
diff --git a/module/project/view/task.html.php b/module/project/view/task.html.php index 4ab8f9512e..5bb5ee66de 100644 --- a/module/project/view/task.html.php +++ b/module/project/view/task.html.php @@ -21,7 +21,7 @@ var browseType = '';
'>
-
 
+
 
diff --git a/module/testcase/view/browse.html.php b/module/testcase/view/browse.html.php index 27ea34a6a3..743652877d 100644 --- a/module/testcase/view/browse.html.php +++ b/module/testcase/view/browse.html.php @@ -58,7 +58,7 @@ js::set('confirmDelete', $lang->testcase->confirmDelete);
'>
-
 
+
 
diff --git a/www/js/my.full.js b/www/js/my.full.js index 7c102ff032..6503de6644 100644 --- a/www/js/my.full.js +++ b/www/js/my.full.js @@ -285,6 +285,39 @@ function toggleHelpLink() if($.cookie('help') == 'on') return $.cookie('help', 'off', {expires:config.cookieLife, path:config.webRoot}); } +/** + * Hide tree box + * + * @param string $treeType + * @access public + * @return void + */ +function hideTreeBox(treeType) +{ + $.cookie(treeType, 'hide', {expires:config.cookieLife, path:config.webRoot}); + $('.side').hide(); + $('.divider').hide(); + $('.treeSlider span').css("border-right", "0 none"); + $('.treeSlider span').css("border-left", "4px solid #000000"); + +} + +/** + * Show tree box + * + * @param string $treeType + * @access public + * @return void + */ +function showTreeBox(treeType) +{ + $.cookie(treeType, 'show', {expires:config.cookieLife, path:config.webRoot}); + $('.side').show(); + $('.divider').show(); + $('.treeSlider span').css("border-right", "4px solid #000000"); + $('.treeSlider span').css("border-left", "0 none"); +} + /** * Toggle tree menu. @@ -293,23 +326,20 @@ function toggleHelpLink() */ function toggleTreeBox() { - var treeSliderH = 50; - $('.treeSlider').height(treeSliderH); + var treeType = $('.treeSlider').attr('id'); + if($.cookie(treeType) == 'hide') hideTreeBox(treeType); + $('.treeSlider').toggle ( function() { - $('.side').hide() - $('.divider').hide() - $('.treeSlider span').css("border-right", "0 none"); - $('.treeSlider span').css("border-left", "4px solid #000000"); + if($.cookie(treeType) == 'hide') return showTreeBox(treeType); + hideTreeBox(treeType); }, function() { - $('.side').show() - $('.divider').show() - $('.treeSlider span').css("border-right", "4px solid #000000"); - $('.treeSlider span').css("border-left", "0 none"); + if($.cookie(treeType) == 'show') return hideTreeBox(treeType); + showTreeBox(treeType); } ); } diff --git a/www/theme/default/style.css b/www/theme/default/style.css index 61dae982ba..78ba594983 100644 --- a/www/theme/default/style.css +++ b/www/theme/default/style.css @@ -358,6 +358,7 @@ table.tablesorter thead tr .headerSortDown {background-image: url(./images/table border-left:none; cursor: pointer; width: 8px; + height: 50px; left: 16px; border-radius:0px 10px 10px 0px } From 70301377c1fefe10ccb7e74da1823b7532a939dd Mon Sep 17 00:00:00 2001 From: azhi Date: Wed, 21 Aug 2013 10:28:23 +0800 Subject: [PATCH 11/26] * code for task#1395. --- www/js/my.full.js | 1 + 1 file changed, 1 insertion(+) diff --git a/www/js/my.full.js b/www/js/my.full.js index 6503de6644..c7d22655a9 100644 --- a/www/js/my.full.js +++ b/www/js/my.full.js @@ -327,6 +327,7 @@ function showTreeBox(treeType) function toggleTreeBox() { var treeType = $('.treeSlider').attr('id'); + if(typeof treeType == 'undefined') return; if($.cookie(treeType) == 'hide') hideTreeBox(treeType); $('.treeSlider').toggle From e130f43bb871c1645ac5634c266bbdcce32343a4 Mon Sep 17 00:00:00 2001 From: azhi Date: Wed, 21 Aug 2013 10:31:13 +0800 Subject: [PATCH 12/26] * fix bug#482. --- module/bug/view/assignto.html.php | 2 +- module/bug/view/confirmbug.html.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/module/bug/view/assignto.html.php b/module/bug/view/assignto.html.php index 03f598694c..5b74081a7f 100644 --- a/module/bug/view/assignto.html.php +++ b/module/bug/view/assignto.html.php @@ -26,7 +26,7 @@ js::set('page', 'assignedto'); - + diff --git a/module/bug/view/confirmbug.html.php b/module/bug/view/confirmbug.html.php index ca43f7015d..33a0fab85c 100755 --- a/module/bug/view/confirmbug.html.php +++ b/module/bug/view/confirmbug.html.php @@ -30,7 +30,7 @@ js::set('page', 'confirmbug'); - + From b18fb04eda85f4ebab7148b97f5b015a504cbd5c Mon Sep 17 00:00:00 2001 From: azhi Date: Wed, 21 Aug 2013 10:34:28 +0800 Subject: [PATCH 13/26] * adjust the code. --- module/release/model.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/module/release/model.php b/module/release/model.php index 1faf3d84bf..b7a635e4a3 100644 --- a/module/release/model.php +++ b/module/release/model.php @@ -87,14 +87,14 @@ class releaseModel extends model $buildID = $this->dao->lastInsertID(); } - $release = fixer::input('post') - ->stripTags('name') - ->add('product', (int)$productID) - ->join('stories', ',') - ->join('bugs', ',') - ->remove('allchecker') - ->setIF($this->post->build ==false, 'build', $buildID) - ->get(); + $release = fixer::input('post') + ->stripTags('name') + ->add('product', (int)$productID) + ->join('stories', ',') + ->join('bugs', ',') + ->setIF($this->post->build == false, 'build', $buildID) + ->remove('allchecker') + ->get(); $this->dao->insert(TABLE_RELEASE)->data($release)->autoCheck()->batchCheck($this->config->release->create->requiredFields, 'notempty')->check('name','unique')->exec(); $releaseID = $this->dao->lastInsertID(); From b74358ede49181a82d59ba51d307c947850a52c0 Mon Sep 17 00:00:00 2001 From: azhi Date: Wed, 21 Aug 2013 10:43:22 +0800 Subject: [PATCH 14/26] * fix bug#469. --- module/tree/control.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/tree/control.php b/module/tree/control.php index 7a3ed645ef..df1c4bf4c2 100644 --- a/module/tree/control.php +++ b/module/tree/control.php @@ -303,7 +303,7 @@ class tree extends control */ public function ajaxGetOptionMenu($rootID, $viewType = 'story', $rootModuleID = 0, $returnType = 'html', $needManage = false) { - if($viewType = 'task') + if($viewType == 'task') { $optionMenu = $this->tree->getTaskOptionMenu($rootID); } From c51ec3b3794cda1b9fe7f1f47fdd47468d5a4e1c Mon Sep 17 00:00:00 2001 From: azhi Date: Wed, 21 Aug 2013 10:50:41 +0800 Subject: [PATCH 15/26] * fix bug#467. --- module/task/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/task/model.php b/module/task/model.php index 4491733050..ac4e8d86b4 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -387,9 +387,9 @@ class taskModel extends model $now = helper::now(); $task = fixer::input('post') ->setDefault('assignedTo', $this->app->user->account) - ->setDefault('assignedDate', $now) ->setDefault('lastEditedBy', $this->app->user->account) ->setDefault('lastEditedDate', $now) + ->setIF($oldTask->assignedTo != $this->app->user->account, 'assignedDate', $now) ->remove('comment')->get(); if($this->post->left == 0) { From 5bfb46323910f53f55f875a33e27589109e062a8 Mon Sep 17 00:00:00 2001 From: azhi Date: Wed, 21 Aug 2013 11:22:45 +0800 Subject: [PATCH 16/26] * fix bug#461. --- module/product/view/browse.html.php | 2 +- module/story/control.php | 2 +- module/story/model.php | 80 ++++++++++++++--------------- 3 files changed, 41 insertions(+), 43 deletions(-) diff --git a/module/product/view/browse.html.php b/module/product/view/browse.html.php index 870e79b8f8..334c04cc43 100644 --- a/module/product/view/browse.html.php +++ b/module/product/view/browse.html.php @@ -153,7 +153,7 @@ createLink('story', 'batchClose', "productID=$productID&projectID=0"); $misc = $canBatchClose ? "onclick=setFormAction('$actionLink')" : $class; echo "
  • " . html::a('#', $lang->close, '', $misc) . "
  • "; diff --git a/module/story/control.php b/module/story/control.php index 8d6438b5c9..ac7e221813 100644 --- a/module/story/control.php +++ b/module/story/control.php @@ -644,7 +644,7 @@ class story extends control */ public function batchClose($productID = 0, $projectID = 0) { - if($this->post->closedReasons) + if($this->post->comments) { $allChanges = $this->story->batchClose(); diff --git a/module/story/model.php b/module/story/model.php index 79855d7c14..4e12fa005d 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -579,51 +579,49 @@ class storyModel extends model /* Adjust whether the post data is complete, if not, remove the last element of $storyIDList. */ if($this->session->showSuhosinInfo) array_pop($storyIDList); - if(!empty($storyIDList)) + foreach($storyIDList as $storyID) { - foreach($storyIDList as $storyID) + $oldStory = $this->getById($storyID); + if(!$oldStory->status == 'closed') continue; + + $story->lastEditedBy = $this->app->user->account; + $story->lastEditedDate = $now; + $story->closedBy = $this->app->user->account; + $story->closedDate = $now; + $story->assignedTo = 'closed'; + $story->assignedDate = $now; + $story->status = 'closed'; + + $story->closedReason = $this->post->closedReasons[$storyID]; + $story->duplicateStory = $this->post->duplicateStoryIDList[$storyID] ? $this->post->duplicateStoryIDList[$storyID] : $oldStory->duplicateStory; + $story->childStories = $this->post->childStoriesIDList[$storyID] ? $this->post->childStoriesIDList[$storyID] : $oldStory->childStories; + + if($story->closedReason == 'done') $story->stage = 'released'; + if($story->closedReason != 'done') $story->plan = 0; + + $stories[$storyID] = $story; + unset($story); + } + + foreach($stories as $storyID => $story) + { + if(!$story->closedReason) continue; + + $oldStory = $this->getById($storyID); + + $this->dao->update(TABLE_STORY)->data($story) + ->autoCheck() + ->checkIF($story->closedReason == 'duplicate', 'duplicateStory', 'notempty') + ->checkIF($story->closedReason == 'subdivided', 'childStories', 'notempty') + ->where('id')->eq($storyID)->exec(); + + if(!dao::isError()) { - $oldStory = $this->getById($storyID); - - $story->lastEditedBy = $this->app->user->account; - $story->lastEditedDate = $now; - $story->closedBy = $this->app->user->account; - $story->closedDate = $now; - $story->assignedTo = 'closed'; - $story->assignedDate = $now; - $story->status = 'closed'; - - $story->closedReason = $this->post->closedReasons[$storyID]; - $story->duplicateStory = $this->post->duplicateStoryIDList[$storyID] ? $this->post->duplicateStoryIDList[$storyID] : $oldStory->duplicateStory; - $story->childStories = $this->post->childStoriesIDList[$storyID] ? $this->post->childStoriesIDList[$storyID] : $oldStory->childStories; - - if($story->closedReason == 'done') $story->stage = 'released'; - if($story->closedReason != 'done') $story->plan = 0; - - $stories[$storyID] = $story; - unset($story); + $allChanges[$storyID] = common::createChanges($oldStory, $story); } - - foreach($stories as $storyID => $story) + else { - if(!$story->closedReason) continue; - - $oldStory = $this->getById($storyID); - - $this->dao->update(TABLE_STORY)->data($story) - ->autoCheck() - ->checkIF($story->closedReason == 'duplicate', 'duplicateStory', 'notempty') - ->checkIF($story->closedReason == 'subdivided', 'childStories', 'notempty') - ->where('id')->eq($storyID)->exec(); - - if(!dao::isError()) - { - $allChanges[$storyID] = common::createChanges($oldStory, $story); - } - else - { - die(js::error('story#' . $storyID . dao::getError(true))); - } + die(js::error('story#' . $storyID . dao::getError(true))); } } From ca93b742cdbec8e8b638fb14fa30485d79a53fb4 Mon Sep 17 00:00:00 2001 From: azhi Date: Wed, 21 Aug 2013 13:18:38 +0800 Subject: [PATCH 17/26] * fix bug#481. --- module/action/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/action/model.php b/module/action/model.php index db56467676..c110ac5bb0 100644 --- a/module/action/model.php +++ b/module/action/model.php @@ -39,7 +39,7 @@ class actionModel extends model $action->actor = $actor ? $actor : $this->app->user->account; $action->action = strtolower($actionType); $action->date = helper::now(); - $action->comment = $comment; + $action->comment = ltrim($comment, "
    "); $action->extra = $extra; /* Get product and project for this object. */ From faec7a8092b038b52514deab875a5cad10fb205d Mon Sep 17 00:00:00 2001 From: azhi Date: Wed, 21 Aug 2013 13:45:20 +0800 Subject: [PATCH 18/26] * fix bug#483. --- module/bug/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/bug/model.php b/module/bug/model.php index ea6a08c3fb..c629e9782c 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -1312,7 +1312,7 @@ class bugModel extends model { $products = array_keys($this->loadModel('product')->getPrivProducts()); $bugQuery = str_replace($allProduct, '1', $this->session->bugQuery); - $bugQuery = $bugQuery . ' AND `product`' . helper::dbIN(array_keys($products)); + $bugQuery = $bugQuery . ' AND `product`' . helper::dbIN($products); } $bugQuery = $this->loadModel('search')->replaceDynamic($bugQuery); $bugs = $this->dao->select('*')->from(TABLE_BUG)->where($bugQuery) From 5e52c53dd2521232d4cd3cb924f418b6319482dd Mon Sep 17 00:00:00 2001 From: xia0ta0 Date: Wed, 21 Aug 2013 15:59:59 +0800 Subject: [PATCH 19/26] * code for task#1403. --- module/user/lang/zh-cn.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/module/user/lang/zh-cn.php b/module/user/lang/zh-cn.php index 9356ec0495..2b85af5a58 100644 --- a/module/user/lang/zh-cn.php +++ b/module/user/lang/zh-cn.php @@ -16,7 +16,7 @@ $lang->user->dept = '所属部门'; $lang->user->account = '用户名'; $lang->user->password = '密码'; $lang->user->password2 = '请重复密码'; -$lang->user->role = '角色'; +$lang->user->role = '职位'; $lang->user->group = '分组'; $lang->user->realname = '真实姓名'; $lang->user->nickname = '昵称'; @@ -124,7 +124,7 @@ $lang->user->loginWithDemoUser = '使用demo账号登录:'; $lang->user->placeholder = new stdclass(); $lang->user->placeholder->account = '英文、数字和下划线的组合,三位以上'; $lang->user->placeholder->password1 = '六位以上'; -$lang->user->placeholder->role = '角色影响内容和用户列表的顺序。'; +$lang->user->placeholder->role = '职位影响内容和用户列表的顺序。'; $lang->user->placeholder->group = '分组决定用户的权限列表。'; $lang->user->placeholder->join = '入职日期'; $lang->user->placeholder->commiter = '版本控制系统(subversion)中的帐号'; @@ -135,7 +135,7 @@ $lang->user->error->accountDupl = "ID %s,该用户名已经存在"; $lang->user->error->realname = "ID %s,必须填写真实姓名"; $lang->user->error->password = "ID %s,密码必须六位以上"; $lang->user->error->mail = "ID %s,请填写正确的邮箱地址"; -$lang->user->error->role = "ID %s,角色不能为空"; +$lang->user->error->role = "ID %s,职位不能为空"; $lang->user->contacts = new stdclass(); $lang->user->contacts->common = '联系人'; From 967f9cd0e5a76a68a702ef9343d7412f8bbd4350 Mon Sep 17 00:00:00 2001 From: azhi Date: Fri, 23 Aug 2013 11:21:24 +0800 Subject: [PATCH 20/26] + add git module. --- module/git/config.php | 26 ++ module/git/control.php | 98 +++++ module/git/lang/en.php | 17 + module/git/lang/zh-cn.php | 17 + module/git/model.php | 658 ++++++++++++++++++++++++++++++++++ module/git/view/cat.html.php | 16 + module/git/view/diff.html.php | 17 + 7 files changed, 849 insertions(+) create mode 100644 module/git/config.php create mode 100644 module/git/control.php create mode 100644 module/git/lang/en.php create mode 100644 module/git/lang/zh-cn.php create mode 100644 module/git/model.php create mode 100644 module/git/view/cat.html.php create mode 100644 module/git/view/diff.html.php diff --git a/module/git/config.php b/module/git/config.php new file mode 100644 index 0000000000..d1b1c57946 --- /dev/null +++ b/module/git/config.php @@ -0,0 +1,26 @@ +git->client = '/usr/bin/git'; // c:\git\git.exe + * $config->git->repos['pms']['path'] = '/home/user/repo/pms'; // c:\repo\pms + * + */ +$config->git = new stdClass(); +$config->git->encodings = 'utf-8, gbk'; +$config->git->client = '/usr/bin/git'; + +$i = 1; +$config->git->repos[$i]['path'] = '/home/z/pms'; + +/* +$i ++; +$config->git->repos[$i]['path'] = ''; +*/ diff --git a/module/git/control.php b/module/git/control.php new file mode 100644 index 0000000000..16b0885e45 --- /dev/null +++ b/module/git/control.php @@ -0,0 +1,98 @@ + + * @package git + * @version $Id$ + * @link http://www.zentao.net + */ +class git extends control +{ + /** + * Sync git. + * + * @access public + * @return void + */ + public function run() + { + $this->git->run(); + } + + /** + * Diff a file. + * + * @param string $path + * @param int $revision + * @access public + * @return void + */ + public function diff($path, $revision) + { + $url = helper::safe64Decode($path); + $this->view->url = $path; + $this->view->revision = $revision; + $this->view->diff = $this->git->diff($path, $revision); + + $this->display(); + } + + /** + * Cat a file. + * + * @param string $path + * @param int $revision + * @access public + * @return void + */ + public function cat($path, $revision) + { + $url = helper::safe64Decode($url); + $this->view->path = $path; + $this->view->revision = $revision; + $this->view->code = $this->git->cat($path, $revision); + + $this->display(); + } + + /** + * Sync from the syncer by api. + * + * @access public + * @return void + */ + public function apiSync() + { + if($this->post->logs) + { + $repoRoot = $this->post->repoRoot; + $logs = stripslashes($this->post->logs); + $logs = simplexml_load_string($logs); + foreach($logs->logentry as $entry) + { + $parsedLogs[] = $this->git->convertLog($entry); + } + $parsedObjects = array('stories' => array(), 'tasks' => array(), 'bugs' => array()); + foreach($parsedLogs as $log) + { + $objects = $this->git->parseComment($log->msg); + if($objects) + { + $this->git->saveAction2PMS($objects, $log, $repoRoot); + if($objects['stories']) $parsedObjects['stories'] = array_merge($parsedObjects['stories'], $objects['stories']); + if($objects['tasks']) $parsedObjects['tasks' ] = array_merge($parsedObjects['tasks'], $objects['tasks']); + if($objects['bugs']) $parsedObjects['bugs'] = array_merge($parsedObjects['bugs'], $objects['bugs']); + } + } + $parsedObjects['stories'] = array_unique($parsedObjects['stories']); + $parsedObjects['tasks'] = array_unique($parsedObjects['tasks']); + $parsedObjects['bugs'] = array_unique($parsedObjects['bugs']); + $this->view->parsedObjects = $parsedObjects; + $this->display(); + exit; + } + } +} diff --git a/module/git/lang/en.php b/module/git/lang/en.php new file mode 100644 index 0000000000..49a91119ea --- /dev/null +++ b/module/git/lang/en.php @@ -0,0 +1,17 @@ + + * @package git + * @version $Id$ + * @link http://www.zentao.net + */ +/* Methods. */ +$lang->git = new stdclass(); +$lang->git->common = 'Git'; +$lang->git->cat = 'View code'; +$lang->git->diff = 'Diff code'; +$lang->git->apiSync = 'API: sync git log'; diff --git a/module/git/lang/zh-cn.php b/module/git/lang/zh-cn.php new file mode 100644 index 0000000000..5575f0204e --- /dev/null +++ b/module/git/lang/zh-cn.php @@ -0,0 +1,17 @@ + + * @package git + * @version $Id$ + * @link http://www.zentao.net + */ +/* 方法列表。*/ +$lang->git = new stdclass(); +$lang->git->common = 'Git'; +$lang->git->cat = '查看源代码'; +$lang->git->diff = '比较源代码'; +$lang->git->apiSync = '接口:同步git日志'; diff --git a/module/git/model.php b/module/git/model.php new file mode 100644 index 0000000000..88b6d3616a --- /dev/null +++ b/module/git/model.php @@ -0,0 +1,658 @@ + + * @package git + * @version $Id$ + * @link http://www.zentao.net + */ +?> +loadModel('action'); + } + + /** + * Run. + * + * @access public + * @return void + */ + public function run() + { + $this->setRepos(); + $this->setLogRoot(); + $this->setRestartFile(); + + foreach($this->repos as $name => $repo) + { + $this->printLog("begin repo $name"); + $repo = (object)$repo; + $repo->name = $name; + $this->setRepo($repo); + + $savedRevision = $this->getSavedRevision(); + $this->printLog("start from revision $savedRevision"); + $logs = $this->getRepoLogs($repo, $savedRevision); + $this->printLog("get " . count($logs) . " logs"); + + $this->printLog('begin parsing logs'); + foreach($logs as $log) + { + $this->printLog("parsing log {$log->revision}"); + if($log->revision == $savedRevision) + { + $this->printLog("{$log->revision} alread parsed, ommit it"); + continue; + } + + $this->printLog("comment is\n----------\n" . trim($log->msg) . "\n----------"); + $objects = $this->parseComment($log->msg); + if($objects) + { + $this->printLog('extract' . + 'story:' . join(' ', $objects['stories']) . + ' task:' . join(' ', $objects['tasks']) . + ' bug:' . join(',', $objects['bugs'])); + + $this->saveAction2PMS($objects, $log); + } + else + { + $this->printLog('no objects found' . "\n"); + } + if($log->revision > $savedRevision) $savedRevision = $log->revision; + } + $this->saveLastRevision($savedRevision); + $this->printLog("save revision $savedRevision"); + $this->deleteRestartFile(); + $this->printLog("\n\nrepo $name finished"); + } + } + + /** + * Set the log root. + * + * @access public + * @return void + */ + public function setLogRoot() + { + $this->logRoot = $this->app->getTmpRoot() . 'git/'; + if(!is_dir($this->logRoot)) mkdir($this->logRoot); + } + + /** + * Set the restart file. + * + * @access public + * @return void + */ + public function setRestartFile() + { + $this->restartFile = dirname(__FILE__) . '/restart'; + } + + /** + * Delete the restart file. + * + * @access public + * @return void + */ + public function deleteRestartFile() + { + if(is_file($this->restartFile)) unlink($this->restartFile); + } + + /** + * Set the repos. + * + * @access public + * @return void + */ + public function setRepos() + { + if(!$this->config->git->repos) die("You must set one git repo.\n"); + $this->repos = $this->config->git->repos; + } + + /** + * Set repo. + * + * @param object $repo + * @access public + * @return void + */ + public function setRepo($repo) + { + $this->setClient($repo); + $this->setLogFile($repo->name); + $this->setRepoRoot($repo); + } + + /** + * Set the git binary client of a repo. + * + * @param object $repo + * @access public + * @return void + */ + public function setClient($repo) + { + if($this->config->git->client == '') die("You must set the git client file.\n"); + $this->client = $this->config->git->client; + } + + /** + * Set the log file of a repo. + * + * @param string $repoName + * @access public + * @return void + */ + public function setLogFile($repoName) + { + $this->logFile = $this->logRoot . $repoName; + } + + /** + * set the root path of a repo. + * + * @param object $repo + * @access public + * @return void + */ + public function setRepoRoot($repo) + { + $this->repoRoot = $repo->path; + } + + /** + * Get repo logs. + * + * @param object $repo + * @param int $fromRevision + * @access public + * @return array + */ + public function getRepoLogs($repo, $fromRevision) + { + $parsedLogs = array(); + + /* The git log command. */ + if($fromRevision) + { + $cmd = "cd $this->repoRoot; $this->client log --stat -r $fromRevision:HEAD --pretty=format:%an*_*%cd*_*%H*_*%s"; + } + else + { + $cmd = "cd $this->repoRoot; $this->client log --stat --pretty=format:%an*_*%cd*_*%H*_*%s"; + } + exec($cmd, $list); + + if(!$list) die("Some error occers: \nThe command is $cmd\n"); + + /* Process logs. */ + $logs = array(); + $i = 0; + + foreach($list as $line) + { + if(!$line) + { + $i++; + continue; + } + $logs[$i][] = $line; + } + foreach($logs as $log) + { + $parsedLogs[] = $this->convertLog($log); + } + return $parsedLogs; + } + + /** + * Convert log from xml format to object. + * + * @param object $log + * @access public + * @return ojbect + */ + public function convertLog($log) + { + + list($account, $date, $hash, $comment) = explode('*_*', $log[0]); + $parsedLog = new stdClass(); + $parsedLog->author = $account; + $parsedLog->revision = $hash; + $parsedLog->msg = $comment; + $parsedLog->date = date('Y-m-d H:i:s', strtotime($date)); + $parsedLog->files = array(); + + unset($log[0]); + foreach($log as $change) + { + if(strpos($change, '|') === false) continue; + list($entry, $modify) = explode('|', $change); + $entry = trim($entry); + $parsedLog->files['M'][] = $entry; + } + + return $parsedLog; + } + + /** + * Parse the comment of git, extract object id list from it. + * + * @param string $comment + * @access public + * @return array + */ + public function parseComment($comment) + { + $stories = array(); + $tasks = array(); + $bugs = array(); + + // bug|story|task(case insensitive) + some space + #|:|:(Chinese) + id lists(maybe join with space or ,) + // $comment = "bug # 1,2,3,4 Bug:1 2 3 4 5 story:9999,1234566 story:456,1234566"; + $commonReg = "(?:\s){0,}(?:#|:|:){0,}([0-9, ]{1,})"; + $taskReg = '/task' . $commonReg . '/i'; + $storyReg = '/story' . $commonReg . '/i'; + $bugReg = '/bug' . $commonReg . '/i'; + + if(preg_match_all($storyReg, $comment, $result)) $stories = join(' ', $result[1]); + if(preg_match_all($taskReg, $comment, $result)) $tasks = join(' ', $result[1]); + if(preg_match_all($bugReg, $comment, $result)) $bugs = join(' ', $result[1]); + + if($stories) $stories = array_unique(explode(' ', str_replace(',', ' ', $stories))); + if($tasks) $tasks = array_unique(explode(' ', str_replace(',', ' ', $tasks))); + if($bugs) $bugs = array_unique(explode(' ', str_replace(',', ' ', $bugs))); + + if(!$stories and !$tasks and !$bugs) return array(); + return array('stories' => $stories, 'tasks' => $tasks, 'bugs' => $bugs); + } + + /** + * Convert the comment to uft-8. + * + * @param string $comment + * @access public + * @return string + */ + public function iconvComment($comment) + { + /* Get encodings. */ + $encodings = str_replace(' ', '', trim($comment)); + if($encodings == '') return $comment; + $encodings = explode(',', $encodings); + + /* Try convert. */ + foreach($encodings as $encoding) + { + $result = @iconv($encoding, 'utf-8', $comment); + if($result) return $result; + } + + return $comment; + } + + /** + * Diff a url. + * + * @param string $path + * @param int $revision + * @access public + * @return string|bool + */ + public function diff($path, $revision) + { + $repo = $this->getRepoByURL($path); + if(!$repo) return false; + + $this->setClient($repo); + putenv('LC_CTYPE=en_US.UTF-8'); + + $path = str_replace('%2F', '/', urlencode($path)); + $path = str_replace('%3A', ':', $path); + + $cmd = $this->client . " diff $revision^ $revision $url"; + $diff = `$cmd`; + return $diff; + } + + /** + * Cat a url. + * + * @param string $path + * @param int $revision + * @access public + * @return string|bool + */ + public function cat($path, $revision) + { + $repo = $this->getRepoByURL($path); + if(!$repo) return false; + + $this->setClient($repo); + + putenv('LC_CTYPE=en_US.UTF-8'); + + $path = str_replace('%2F', '/', urlencode($path)); + $path = str_replace('%3A', ':', $path); + + $cmd = $this->client . " show -r $revision $path"; + $code = `$cmd`; + return $code; + } + + /** + * Get repo by url. + * + * @param string $url + * @access public + * @return object|bool + */ + public function getRepoByURL($url) + { + foreach($this->config->git->repos as $repo) if(strpos($url, $repo['path']) !== false) return (object)$repo; + return false; + } + + /** + * Save action to pms. + * + * @param array $objects + * @param object $log + * @param string $repoRoot + * @access public + * @return void + */ + public function saveAction2PMS($objects, $log, $repoRoot = '') + { + $action = new stdclass(); + $action->actor = $log->author; + $action->action = 'gitcommited'; + $action->date = $log->date; + $action->comment = $this->iconvComment($log->msg); + $action->extra = $log->revision; + + $changes = $this->createActionChanges($log, $repoRoot); + + if($objects['stories']) + { + $products = $this->getStoryProducts($objects['stories']); + foreach($objects['stories'] as $storyID) + { + $storyID = (int)$storyID; + if(!isset($products[$storyID])) continue; + + $action->objectType = 'story'; + $action->objectID = $storyID; + $action->product = $products[$storyID]; + $action->project = 0; + + $this->saveRecord($action, $changes); + } + } + + if($objects['tasks']) + { + $productsAndProjects = $this->getTaskProductsAndProjects($objects['tasks']); + foreach($objects['tasks'] as $taskID) + { + $taskID = (int)$taskID; + if(!isset($productsAndProjects[$taskID])) continue; + + $action->objectType = 'task'; + $action->objectID = $taskID; + $action->product = $productsAndProjects[$taskID]['product']; + $action->project = $productsAndProjects[$taskID]['project']; + + $this->saveRecord($action, $changes); + } + } + + if($objects['bugs']) + { + $productsAndProjects = $this->getBugProductsAndProjects($objects['bugs']); + + foreach($objects['bugs'] as $bugID) + { + $bugID = (int)$bugID; + if(!isset($productsAndProjects[$bugID])) continue; + + $action->objectType = 'bug'; + $action->objectID = $bugID; + $action->product = $productsAndProjects[$bugID]->product; + $action->project = $productsAndProjects[$bugID]->project; + + $this->saveRecord($action, $changes); + } + } + } + + /** + * Save an action to pms. + * + * @param object $action + * @param object $log + * @access public + * @return bool + */ + public function saveRecord($action, $changes) + { + $record = $this->dao->select('*')->from(TABLE_ACTION) + ->where('objectType')->eq($action->objectType) + ->andWhere('objectID')->eq($action->objectID) + ->andWhere('extra')->eq($action->extra) + ->andWhere('action')->eq('gitcommited') + ->fetch(); + if($record) + { + $this->dao->update(TABLE_ACTION)->data($action)->where('id')->eq($record->id)->exec(); + if($changes) + { + $historyID = $this->dao->findByAction($record->id)->from(TABLE_HISTORY)->fetch('id'); + $this->dao->update(TABLE_HISTORY)->data($changes)->where('id')->eq($historyID)->exec(); + } + } + else + { + $this->dao->insert(TABLE_ACTION)->data($action)->autoCheck()->exec(); + if($changes) + { + $actionID = $this->dao->lastInsertID(); + $this->action->logHistory($actionID, array($changes)); + } + } + } + + /** + * Create changes for action from a log. + * + * @param object $log + * @param string $repoRoot + * @access public + * @return array + */ + public function createActionChanges($log, $repoRoot) + { + if(!$log->files) return array(); + $diff = ''; + + $oldSelf = $this->server->PHP_SELF; + $this->server->set('PHP_SELF', $this->config->webRoot); + + if(!$repoRoot) $repoRoot = $this->repoRoot; + + foreach($log->files as $action => $actionFiles) + { + foreach($actionFiles as $file) + { + $param = array('url' => helper::safe64Encode($repoRoot . $file), 'revision' => $log->revision); + $catLink = trim(html::a(helper::createLink('git', 'cat', $param, 'html'), 'view', '', "class='gitlink'")); + $diffLink = trim(html::a(helper::createLink('git', 'diff', $param, 'html'), 'diff', '', "class='gitlink'")); + $diff .= $action . " " . $file . " $catLink "; + $diff .= $action == 'M' ? "$diffLink\n" : "\n" ; + } + } + $changes->field = 'subversion'; + $changes->old = ''; + $changes->new = ''; + $changes->diff = trim($diff); + + $this->server->set('PHP_SELF', $oldSelf); + return (array)$changes; + } + + /** + * Get products of stories. + * + * @param array $stories + * @access public + * @return array + */ + public function getStoryProducts($stories) + { + return $this->dao->select('id, product')->from(TABLE_STORY)->where('id')->in($stories)->fetchPairs(); + } + + /** + * Get products and projects of tasks. + * + * @param array $tasks + * @access public + * @return array + */ + public function getTaskProductsAndProjects($tasks) + { + $records = array(); + $products = $this->dao->select('t1.id, t2.product') + ->from(TABLE_TASK)->alias('t1') + ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') + ->where('t1.id')->in($tasks)->fetchPairs(); + + $projects = $this->dao->select('id, project')->from(TABLE_TASK)->where('id')->in($tasks)->fetchPairs(); + + foreach($projects as $taskID => $projectID) + { + $record = array(); + $record['project'] = $projectID; + $record['product'] = isset($products[$taskID]) ? $products[$taskID] : 0; + $records[$taskID] = $record; + } + return $records; + } + + /** + * Get products and projects of bugs. + * + * @param array $bugs + * @access public + * @return array + */ + public function getBugProductsAndProjects($bugs) + { + return $this->dao->select('id, project, product')->from(TABLE_BUG)->where('id')->in($bugs)->fetchAll('id'); + } + + /** + * Get the saved revision. + * + * @access public + * @return int + */ + public function getSavedRevision() + { + if(!file_exists($this->logFile)) return 0; + if(file_exists($this->restartFile)) return 0; + return (int)trim(file_get_contents($this->logFile)); + } + + /** + * Save the last revision. + * + * @param int $revision + * @access public + * @return void + */ + public function saveLastRevision($revision) + { + file_put_contents($this->logFile, $revision); + } + + /** + * Pring log. + * + * @param sting $log + * @access public + * @return void + */ + public function printLog($log) + { + echo helper::now() . " $log\n"; + } +} diff --git a/module/git/view/cat.html.php b/module/git/view/cat.html.php new file mode 100644 index 0000000000..15406f134f --- /dev/null +++ b/module/git/view/cat.html.php @@ -0,0 +1,16 @@ + + * @package file + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
    +
    <?php echo $code;?>
    + diff --git a/module/git/view/diff.html.php b/module/git/view/diff.html.php new file mode 100644 index 0000000000..067c43e4de --- /dev/null +++ b/module/git/view/diff.html.php @@ -0,0 +1,17 @@ + + * @package file + * @version $Id$ + * @link http://www.zentao.net + */ +?> + + +
    +
    <?php echo $diff;?>
    + From abd4f18af85a544d1da40b92dda6090fee61bdb1 Mon Sep 17 00:00:00 2001 From: azhi Date: Mon, 26 Aug 2013 10:16:58 +0800 Subject: [PATCH 21/26] * finish task#1406. --- module/productplan/lang/en.php | 1 + module/productplan/lang/zh-cn.php | 1 + 2 files changed, 2 insertions(+) diff --git a/module/productplan/lang/en.php b/module/productplan/lang/en.php index cefdb0e880..d0df597b90 100644 --- a/module/productplan/lang/en.php +++ b/module/productplan/lang/en.php @@ -43,6 +43,7 @@ $lang->productplan->desc = 'Desc'; $lang->productplan->begin = 'Begin'; $lang->productplan->end = 'End'; +$lang->productplan->endList[7] = 'One Weeks'; $lang->productplan->endList[14] = 'Two Weeks'; $lang->productplan->endList[31] = 'One Month'; $lang->productplan->endList[62] = 'Two Months'; diff --git a/module/productplan/lang/zh-cn.php b/module/productplan/lang/zh-cn.php index a7ba98e84b..deeb14dfcb 100644 --- a/module/productplan/lang/zh-cn.php +++ b/module/productplan/lang/zh-cn.php @@ -43,6 +43,7 @@ $lang->productplan->desc = '描述'; $lang->productplan->begin = '开始日期'; $lang->productplan->end = '结束日期'; +$lang->productplan->endList[7] = '一星期'; $lang->productplan->endList[14] = '两星期'; $lang->productplan->endList[31] = '一个月'; $lang->productplan->endList[62] = '两个月'; From 2ddd389a21a04d4cc797e8ec434ec7423979cc1c Mon Sep 17 00:00:00 2001 From: xia0ta0 Date: Mon, 26 Aug 2013 10:39:09 +0800 Subject: [PATCH 22/26] * code for task#1365. --- module/action/lang/en.php | 3 +++ module/action/lang/zh-cn.php | 3 +++ module/action/model.php | 3 ++- module/git/control.php | 24 ++++++++++++++++++------ module/git/model.php | 29 ++++++++++++++++------------- module/group/lang/resource.php | 25 ++++++++++++++++++------- 6 files changed, 60 insertions(+), 27 deletions(-) diff --git a/module/action/lang/en.php b/module/action/lang/en.php index bd3da97934..0b31cec48c 100644 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -89,6 +89,7 @@ $lang->action->desc->editestimate = '$date, $actor edited wor $lang->action->desc->deleteestimate = '$date, $actor deleted working hours'; $lang->action->desc->canceled = '$date, canceled by $actor.'; $lang->action->desc->svncommited = '$date, $actor commited to svn,revision is #$extra.' . "\n"; +$lang->action->desc->gitcommited = '$date, $actor commited to git,revision is #$extra.' . "\n"; $lang->action->desc->finished = '$date, finished by $actor.'; $lang->action->desc->diff1 = 'changed %s, old is "%s", new is "%s".
    '; $lang->action->desc->diff2 = 'changed %s, the diff is:' . "\n" . "
    %s
    " . "\n"; @@ -119,6 +120,7 @@ $lang->action->label->tostory = 'converted to story'; $lang->action->label->frombug = 'converted from bug'; $lang->action->label->totask = 'converted to task'; $lang->action->label->svncommited = 'commited code'; +$lang->action->label->gitcommited = 'commited code'; $lang->action->label->linked2plan = 'link to plan'; $lang->action->label->unlinkedfromplan = 'unlink from plan'; $lang->action->label->marked = 'edited'; @@ -191,6 +193,7 @@ $lang->action->search->label['tostory'] = $lang->action->label->tost $lang->action->search->label['frombug'] = $lang->action->label->frombug; $lang->action->search->label['totask'] = $lang->action->label->totask; $lang->action->search->label['svncommited'] = $lang->action->label->svncommited; +$lang->action->search->label['gitcommited'] = $lang->action->label->gitcommited; $lang->action->search->label['linked2plan'] = $lang->action->label->linked2plan; $lang->action->search->label['unlinkedfromplan'] = $lang->action->label->unlinkedfromplan; $lang->action->search->label['linked2project'] = $lang->action->label->linked2project; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index 4fdb662e10..005c695edf 100644 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -89,6 +89,7 @@ $lang->action->desc->editestimate = '$date, 由 $actor 编辑 $lang->action->desc->deleteestimate = '$date, 由 $actor 删除工时。'; $lang->action->desc->canceled = '$date, 由 $actor 取消。' . "\n"; $lang->action->desc->svncommited = '$date, 由 $actor 提交代码,版本为#$extra。' . "\n"; +$lang->action->desc->gitcommited = '$date, 由 $actor 提交代码,版本为#$extra。' . "\n"; $lang->action->desc->finished = '$date, 由 $actor 完成。' . "\n"; $lang->action->desc->diff1 = '修改了 %s,旧值为 "%s",新值为 "%s"。
    ' . "\n"; $lang->action->desc->diff2 = '修改了 %s,区别为:' . "\n" . "
    %s
    " . "\n"; @@ -119,6 +120,7 @@ $lang->action->label->tostory = '转需求'; $lang->action->label->frombug = '转需求'; $lang->action->label->totask = '转任务'; $lang->action->label->svncommited = '提交代码'; +$lang->action->label->gitcommited = '提交代码'; $lang->action->label->linked2plan = '关联计划'; $lang->action->label->unlinkedfromplan = '移除计划'; $lang->action->label->marked = '编辑了'; @@ -191,6 +193,7 @@ $lang->action->search->label['tostory'] = $lang->action->label->tost $lang->action->search->label['frombug'] = $lang->action->label->frombug; $lang->action->search->label['totask'] = $lang->action->label->totask; $lang->action->search->label['svncommited'] = $lang->action->label->svncommited; +$lang->action->search->label['gitcommited'] = $lang->action->label->gitcommited; $lang->action->search->label['linked2plan'] = $lang->action->label->linked2plan; $lang->action->search->label['unlinkedfromplan'] = $lang->action->label->unlinkedfromplan; $lang->action->search->label['linked2project'] = $lang->action->label->linked2project; diff --git a/module/action/model.php b/module/action/model.php index c110ac5bb0..412afa561e 100644 --- a/module/action/model.php +++ b/module/action/model.php @@ -193,6 +193,7 @@ class actionModel extends model foreach($actions as $actionID => $action) { if(strtolower($action->action) == 'svncommited' and isset($commiters[$action->actor])) $action->actor = $commiters[$action->actor]; + if(strtolower($action->action) == 'gitcommited' and isset($commiters[$action->actor])) $action->actor = $commiters[$action->actor]; $action->history = isset($histories[$actionID]) ? $histories[$actionID] : array(); $actions[$actionID] = $action; } @@ -605,7 +606,7 @@ class actionModel extends model if($history->diff != '') { $history->diff = str_replace(array('', '', '', ''), array('[ins]', '[/ins]', '[del]', '[/del]'), $history->diff); - $history->diff = $history->field != 'subversion' ? htmlspecialchars($history->diff) : $history->diff; // Keep the diff link. + $history->diff = ($history->field != 'subversion' and $history->field != 'git') ? htmlspecialchars($history->diff) : $history->diff; // Keep the diff link. $history->diff = str_replace(array('[ins]', '[/ins]', '[del]', '[/del]'), array('', '', '', ''), $history->diff); $history->diff = nl2br($history->diff); $history->noTagDiff = preg_replace('/<\/?([a-z][a-z0-9]*)[^\/]*\/?>/Ui', '', $history->diff); diff --git a/module/git/control.php b/module/git/control.php index 16b0885e45..55ada5053f 100644 --- a/module/git/control.php +++ b/module/git/control.php @@ -32,7 +32,7 @@ class git extends control */ public function diff($path, $revision) { - $url = helper::safe64Decode($path); + $path = helper::safe64Decode($path); $this->view->url = $path; $this->view->revision = $revision; $this->view->diff = $this->git->diff($path, $revision); @@ -50,7 +50,7 @@ class git extends control */ public function cat($path, $revision) { - $url = helper::safe64Decode($url); + $path = helper::safe64Decode($path); $this->view->path = $path; $this->view->revision = $revision; $this->view->code = $this->git->cat($path, $revision); @@ -69,12 +69,24 @@ class git extends control if($this->post->logs) { $repoRoot = $this->post->repoRoot; - $logs = stripslashes($this->post->logs); - $logs = simplexml_load_string($logs); - foreach($logs->logentry as $entry) + $list = json_decode($this->post->logs); + + $logs = array(); + $i = 0; + foreach($list as $line) { - $parsedLogs[] = $this->git->convertLog($entry); + if(!$line) + { + $i++; + continue; + } + $logs[$i][] = $line; } + foreach($logs as $log) + { + $parsedLogs[] = $this->convertLog($log); + } + $parsedObjects = array('stories' => array(), 'tasks' => array(), 'bugs' => array()); foreach($parsedLogs as $log) { diff --git a/module/git/model.php b/module/git/model.php index 88b6d3616a..f0bdcd2218 100644 --- a/module/git/model.php +++ b/module/git/model.php @@ -98,6 +98,7 @@ class gitModel extends model $this->printLog("get " . count($logs) . " logs"); $this->printLog('begin parsing logs'); + $latestRevision = $logs[0]->revision; foreach($logs as $log) { $this->printLog("parsing log {$log->revision}"); @@ -112,7 +113,7 @@ class gitModel extends model if($objects) { $this->printLog('extract' . - 'story:' . join(' ', $objects['stories']) . + ' story:' . join(' ', $objects['stories']) . ' task:' . join(' ', $objects['tasks']) . ' bug:' . join(',', $objects['bugs'])); @@ -122,10 +123,10 @@ class gitModel extends model { $this->printLog('no objects found' . "\n"); } - if($log->revision > $savedRevision) $savedRevision = $log->revision; } - $this->saveLastRevision($savedRevision); - $this->printLog("save revision $savedRevision"); + + $this->saveLastRevision($latestRevision); + $this->printLog("save revision $latestRevision"); $this->deleteRestartFile(); $this->printLog("\n\nrepo $name finished"); } @@ -243,15 +244,16 @@ class gitModel extends model /* The git log command. */ if($fromRevision) { - $cmd = "cd $this->repoRoot; $this->client log --stat -r $fromRevision:HEAD --pretty=format:%an*_*%cd*_*%H*_*%s"; + $cmd = "cd $this->repoRoot; $this->client log --stat $fromRevision..HEAD --pretty=format:%an*_*%cd*_*%H*_*%s"; } else { $cmd = "cd $this->repoRoot; $this->client log --stat --pretty=format:%an*_*%cd*_*%H*_*%s"; } - exec($cmd, $list); + exec($cmd, $list, $return); - if(!$list) die("Some error occers: \nThe command is $cmd\n"); + if(!$list and $return) die("Some error occers: \nThe command is $cmd\n"); + if(!$list and !$return) exit; /* Process logs. */ $logs = array(); @@ -296,7 +298,7 @@ class gitModel extends model { if(strpos($change, '|') === false) continue; list($entry, $modify) = explode('|', $change); - $entry = trim($entry); + $entry = '/' . trim($entry); $parsedLog->files['M'][] = $entry; } @@ -378,7 +380,7 @@ class gitModel extends model $path = str_replace('%2F', '/', urlencode($path)); $path = str_replace('%3A', ':', $path); - $cmd = $this->client . " diff $revision^ $revision $url"; + $cmd = "cd $repo->path;$this->client diff $revision^ $revision $path"; $diff = `$cmd`; return $diff; } @@ -403,7 +405,8 @@ class gitModel extends model $path = str_replace('%2F', '/', urlencode($path)); $path = str_replace('%3A', ':', $path); - $cmd = $this->client . " show -r $revision $path"; + $subPath = substr($path, strlen($repo->path) + 1); + $cmd = "cd $repo->path;$this->client show $revision:$subPath"; $code = `$cmd`; return $code; } @@ -437,7 +440,7 @@ class gitModel extends model $action->action = 'gitcommited'; $action->date = $log->date; $action->comment = $this->iconvComment($log->msg); - $action->extra = $log->revision; + $action->extra = substr($log->revision, 0, 10); $changes = $this->createActionChanges($log, $repoRoot); @@ -559,7 +562,7 @@ class gitModel extends model $diff .= $action == 'M' ? "$diffLink\n" : "\n" ; } } - $changes->field = 'subversion'; + $changes->field = 'git'; $changes->old = ''; $changes->new = ''; $changes->diff = trim($diff); @@ -629,7 +632,7 @@ class gitModel extends model { if(!file_exists($this->logFile)) return 0; if(file_exists($this->restartFile)) return 0; - return (int)trim(file_get_contents($this->logFile)); + return trim(file_get_contents($this->logFile)); } /** diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index 51e0a689a3..702e0454c6 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -46,13 +46,14 @@ $lang->moduleOrder[125] = 'action'; $lang->moduleOrder[130] = 'mail'; $lang->moduleOrder[135] = 'svn'; -$lang->moduleOrder[140] = 'search'; -$lang->moduleOrder[145] = 'tree'; -$lang->moduleOrder[150] = 'api'; -$lang->moduleOrder[155] = 'file'; -$lang->moduleOrder[160] = 'misc'; -$lang->moduleOrder[165] = 'sso'; -$lang->moduleOrder[170] = 'webapp'; +$lang->moduleOrder[140] = 'git'; +$lang->moduleOrder[145] = 'search'; +$lang->moduleOrder[150] = 'tree'; +$lang->moduleOrder[155] = 'api'; +$lang->moduleOrder[160] = 'file'; +$lang->moduleOrder[165] = 'misc'; +$lang->moduleOrder[170] = 'sso'; +$lang->moduleOrder[175] = 'webapp'; $lang->resource = new stdclass(); @@ -513,6 +514,16 @@ $lang->svn->methodOrder[5] = 'diff'; $lang->svn->methodOrder[10] = 'cat'; $lang->svn->methodOrder[15] = 'apiSync'; +/* Git. */ +$lang->resource->git = new stdclass(); +$lang->resource->git->diff = 'diff'; +$lang->resource->git->cat = 'cat'; +$lang->resource->git->apiSync = 'apiSync'; + +$lang->git->methodOrder[5] = 'diff'; +$lang->git->methodOrder[10] = 'cat'; +$lang->git->methodOrder[15] = 'apiSync'; + /* Company. */ $lang->resource->company = new stdclass(); $lang->resource->company->index = 'index'; From 26ce3673b5cc2b104807964cd71853b130f7ced0 Mon Sep 17 00:00:00 2001 From: xia0ta0 Date: Mon, 26 Aug 2013 14:27:47 +0800 Subject: [PATCH 23/26] * remove draft stories. --- module/story/model.php | 1 + 1 file changed, 1 insertion(+) diff --git a/module/story/model.php b/module/story/model.php index 4e12fa005d..97c6dca8d2 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -989,6 +989,7 @@ class storyModel extends model $queryProductID = 'all'; } $storyQuery = $storyQuery . ' AND `product`' . helper::dbIN(array_keys($products)); + if($projectID != '') $storyQuery .= " AND `status` != 'draft'"; $storyQuery = $this->loadModel('search')->replaceDynamic($storyQuery); return $this->getBySQL($queryProductID, $storyQuery, $orderBy, $pager); From 36024ce40a7377fa9fe97b687254c58073ab9d46 Mon Sep 17 00:00:00 2001 From: xia0ta0 Date: Mon, 26 Aug 2013 15:07:45 +0800 Subject: [PATCH 24/26] * fix bug#457. --- module/testcase/control.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/module/testcase/control.php b/module/testcase/control.php index e0b2b321e5..4ff8029818 100644 --- a/module/testcase/control.php +++ b/module/testcase/control.php @@ -115,7 +115,8 @@ class testcase extends control $queryProductID = $productID; $allProduct = "`product` = 'all'"; - $caseQuery = $this->session->testcaseQuery; + + $caseQuery = '(' . $this->session->testcaseQuery; if(strpos($this->session->testcaseQuery, $allProduct) !== false) { $products = array_keys($this->loadModel('product')->getPrivProducts()); @@ -123,6 +124,7 @@ class testcase extends control $caseQuery = $caseQuery . ' AND `product`' . helper::dbIN(array_keys($products)); $queryProductID = 'all'; } + $caseQuery .= ')'; $caseQuery = $this->loadModel('search')->replaceDynamic($caseQuery); $this->view->cases = $this->dao->select('*')->from(TABLE_CASE)->where($caseQuery) From 588648bb8e60a9e0cc353962f82b19852a93155c Mon Sep 17 00:00:00 2001 From: xia0ta0 Date: Mon, 26 Aug 2013 15:49:39 +0800 Subject: [PATCH 25/26] * code for task#1405. --- module/task/lang/en.php | 1 + module/task/lang/zh-cn.php | 1 + module/task/model.php | 1 + 3 files changed, 3 insertions(+) diff --git a/module/task/lang/en.php b/module/task/lang/en.php index c605ae0175..f25e133a6b 100644 --- a/module/task/lang/en.php +++ b/module/task/lang/en.php @@ -149,6 +149,7 @@ $lang->task->error->consumedNumber = '"Consumed" must be number'; $lang->task->error->consumedSmall = '"Consumed" must be more than consumed before'; $lang->task->error->consumedThisTime = 'Please input "hours"'; $lang->task->error->left = 'Please input "left"'; +$lang->task->error->work = '"Comment" must be less than 255 characters'; /* Report. */ $lang->task->report = new stdclass(); diff --git a/module/task/lang/zh-cn.php b/module/task/lang/zh-cn.php index 07f4ba8d20..7a04edccc0 100644 --- a/module/task/lang/zh-cn.php +++ b/module/task/lang/zh-cn.php @@ -149,6 +149,7 @@ $lang->task->error->consumedNumber = '"已经消耗"必须为数字'; $lang->task->error->consumedSmall = '"已经消耗"必须大于之前消耗'; $lang->task->error->consumedThisTime = '请填写"工时"'; $lang->task->error->left = '请填写"剩余"'; +$lang->task->error->work = '"备注"必须小于255个字符'; /* 统计报表。*/ $lang->task->report = new stdclass(); diff --git a/module/task/model.php b/module/task/model.php index ac4e8d86b4..e64f6397db 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -440,6 +440,7 @@ class taskModel extends model { if(!$record->consumed[$id]) die(js::alert($this->lang->task->error->consumedThisTime)); if($record->left[$id] === '') die(js::alert($this->lang->task->error->left)); + if(strlen($record->work[$id]) > 255) die(js::alert($this->lang->task->error->work)); $estimates[$id] = new stdclass(); $estimates[$id]->date = $record->dates[$id]; $estimates[$id]->task = $taskID; From 27e54f1202fbb2c5c1a4797c05a4364f2af3e1e4 Mon Sep 17 00:00:00 2001 From: xia0ta0 Date: Mon, 26 Aug 2013 16:19:03 +0800 Subject: [PATCH 26/26] * code for task#1408. --- module/testcase/js/common.js | 5 +---- module/testcase/view/create.html.php | 3 +++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/module/testcase/js/common.js b/module/testcase/js/common.js index 95c21548c8..1334b9df1f 100644 --- a/module/testcase/js/common.js +++ b/module/testcase/js/common.js @@ -106,10 +106,7 @@ function createRow() { if(newRowID == 0) newRowID = $('.stepID').size(); newRowID ++; - var lblDelete = 'testcase->deleteStep;?>'; - var lblBefore = 'testcase->insertBefore;?>'; - var lblAfter = 'testcase->insertAfter;?>'; - var newRow = "
    "; + var newRow = ""; newRow += ""; newRow += ""; newRow += ""; diff --git a/module/testcase/view/create.html.php b/module/testcase/view/create.html.php index b4a432dbf0..aab915b3ec 100644 --- a/module/testcase/view/create.html.php +++ b/module/testcase/view/create.html.php @@ -13,6 +13,9 @@ +testcase->deleteStep);?> +testcase->insertBefore);?> +testcase->insertAfter);?>
    bug->mailto;?>mailto), 'class="text-1" multiple');?>mailto), 'class="w-p98" multiple');?>
    comment;?>
    bug->mailto;?>mailto), 'class="text-1" multiple');?>mailto), 'class="w-p98" multiple');?>
    comment;?>
    testcase->create;?>