Merge branch 'master' of https://gitlab.zcorp.cc/easycorp/zentaopms into tanghucheng_task
This commit is contained in:
@@ -3191,9 +3191,19 @@ class bugModel extends model
|
||||
$class .= ' c-user';
|
||||
$title = "title='" . zget($users, $bug->resolvedBy) . "'";
|
||||
break;
|
||||
case 'openedBy':
|
||||
$class .= ' c-user';
|
||||
$title = "title='" . zget($users, $bug->openedBy) . "'";
|
||||
break;
|
||||
case 'project':
|
||||
$title = "title='" . zget($projectPairs, $bug->project, '') . "'";
|
||||
break;
|
||||
case 'plan':
|
||||
$title = "title='" . zget($plans, $bug->plan) . "'";
|
||||
break;
|
||||
case 'execution':
|
||||
$title = "title='" . zget($executions, $bug->execution) . "'";
|
||||
break;
|
||||
case 'resolvedBuild':
|
||||
$class .= ' text-ellipsis';
|
||||
$title = "title='" . $bug->resolvedBuild . "'";
|
||||
|
||||
@@ -320,7 +320,7 @@ $lang->execution->menu->task = array('link' => "{$lang->task->common}|execut
|
||||
$lang->execution->menu->kanban = array('link' => "$lang->executionKanban|execution|taskkanban|executionID=%s");
|
||||
$lang->execution->menu->burn = array('link' => "$lang->burn|execution|burn|executionID=%s");
|
||||
$lang->execution->menu->view = array('link' => "$lang->view|execution|grouptask|executionID=%s", 'alias' => 'grouptask,tree,taskeffort,gantt,calendar,relation,maintainrelation');
|
||||
$lang->execution->menu->story = array('link' => "$lang->SRCommon|execution|story|executionID=%s", 'subModule' => 'story', 'alias' => 'batchcreate,linkstory,storykanban');
|
||||
$lang->execution->menu->story = array('link' => "$lang->SRCommon|execution|story|executionID=%s", 'subModule' => 'story', 'alias' => 'batchcreate,linkstory,storykanban,batchtotask');
|
||||
$lang->execution->menu->qa = array('link' => "{$lang->qa->common}|execution|bug|executionID=%s", 'subModule' => 'bug,testcase,testtask,testreport', 'alias' => 'qa,bug,testcase,testtask,testreport');
|
||||
$lang->execution->menu->devops = array('link' => "{$lang->repo->common}|repo|browse|repoID=0&branchID=&objectID=%s", 'subModule' => 'repo');
|
||||
$lang->execution->menu->doc = array('link' => "{$lang->doc->common}|doc|tableContents|type=execution&objectID=%s", 'subModule' => 'doc');
|
||||
|
||||
@@ -188,14 +188,14 @@ $config->execution->datatable->fieldList['id']['fixed'] = 'left';
|
||||
$config->execution->datatable->fieldList['id']['width'] = '70';
|
||||
$config->execution->datatable->fieldList['id']['required'] = 'yes';
|
||||
|
||||
$config->execution->datatable->fieldList['name']['title'] = 'name';
|
||||
$config->execution->datatable->fieldList['name']['title'] = 'execName';
|
||||
$config->execution->datatable->fieldList['name']['fixed'] = 'left';
|
||||
$config->execution->datatable->fieldList['name']['width'] = 'auto';
|
||||
$config->execution->datatable->fieldList['name']['required'] = 'yes';
|
||||
|
||||
if(!isset($config->setCode) or $config->setCode == 1)
|
||||
{
|
||||
$config->execution->datatable->fieldList['code']['title'] = 'code';
|
||||
$config->execution->datatable->fieldList['code']['title'] = 'execCode';
|
||||
$config->execution->datatable->fieldList['code']['fixed'] = 'no';
|
||||
$config->execution->datatable->fieldList['code']['width'] = '95';
|
||||
$config->execution->datatable->fieldList['code']['required'] = 'no';
|
||||
@@ -211,7 +211,7 @@ $config->execution->datatable->fieldList['PM']['fixed'] = 'no';
|
||||
$config->execution->datatable->fieldList['PM']['width'] = '70';
|
||||
$config->execution->datatable->fieldList['PM']['required'] = 'no';
|
||||
|
||||
$config->execution->datatable->fieldList['status']['title'] = 'status';
|
||||
$config->execution->datatable->fieldList['status']['title'] = 'execStatus';
|
||||
$config->execution->datatable->fieldList['status']['fixed'] = 'no';
|
||||
$config->execution->datatable->fieldList['status']['width'] = '100';
|
||||
$config->execution->datatable->fieldList['status']['required'] = 'no';
|
||||
|
||||
@@ -1058,7 +1058,7 @@ class execution extends control
|
||||
$this->view->builds = $this->build->getBuildPairs($productID);
|
||||
$this->view->branchOption = $branchOption;
|
||||
$this->view->branchTagOption = $branchTagOption;
|
||||
$this->view->plans = $this->loadModel('productplan')->getPairs($productID);
|
||||
$this->view->plans = $this->loadModel('productplan')->getPairs($productID ? $productID : array_keys($products));
|
||||
$this->view->stories = $storyList;
|
||||
$this->view->tasks = $taskList;
|
||||
$this->view->projectPairs = $this->loadModel('project')->getPairsByProgram();
|
||||
@@ -1384,6 +1384,9 @@ class execution extends control
|
||||
$this->loadModel('kanban');
|
||||
$this->app->loadClass('date');
|
||||
|
||||
$minDate = !helper::isZeroDate($execution->openedDate) ? $execution->openedDate : $execution->begin;
|
||||
$maxDate = !helper::isZeroDate($execution->closedDate) ? $execution->closedDate : helper::today();
|
||||
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$begin = htmlspecialchars($this->post->begin, ENT_QUOTES);
|
||||
@@ -1424,6 +1427,8 @@ class execution extends control
|
||||
$this->view->chartData = $chartData;
|
||||
$this->view->begin = $begin;
|
||||
$this->view->end = $end;
|
||||
$this->view->minDate = $minDate;
|
||||
$this->view->maxDate = $maxDate;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -2290,9 +2295,7 @@ class execution extends control
|
||||
{
|
||||
$this->app->loadClass('date');
|
||||
|
||||
$begin = date('Y-m-d', strtotime('-13 days'));
|
||||
$begin = (helper::isZeroDate($execution->begin) or helper::diffDate($begin, $execution->begin) > 0) ? $begin : $execution->begin;
|
||||
$end = helper::today();
|
||||
list($begin, $end) = $this->execution->getBeginEnd4CFD($execution);
|
||||
$dateList = date::getDateList($begin, $end, 'Y-m-d', 'noweekend');
|
||||
$chartData = $this->execution->buildCFDData($executionID, $dateList, 'task');
|
||||
if(isset($chartData['line'])) $chartData['line'] = array_reverse($chartData['line']);
|
||||
|
||||
@@ -28,6 +28,7 @@ td.flex span.project-type-label {min-width: 40px;}
|
||||
.has-child > span {margin-right: 5px;}
|
||||
.c-name > .text-ellipsis {text-overflow: clip;}
|
||||
.c-code, .c-project {overflow: hidden; white-space: nowrap;}
|
||||
th.c-status {text-align: center}
|
||||
|
||||
.c-project{text-overflow: unset !important;}
|
||||
canvas {height: 28px;}
|
||||
|
||||
@@ -137,7 +137,7 @@ $(function()
|
||||
location.href = createLink('execution', 'cfd', 'executionID=' + executionID + '&type=' + type + '&withWeekend=' + withWeekend + '&begin=' + begin + '&end=' + end);
|
||||
});
|
||||
|
||||
$("#end, #begin").datetimepicker('setEndDate', today);
|
||||
$("#end, #begin").datetimepicker('setStartDate', executionBegin);
|
||||
$("#end, #begin").datetimepicker('setEndDate', maxDate);
|
||||
$("#end, #begin").datetimepicker('setStartDate', minDate);
|
||||
$('.datetimepicker-days table tfoot').append('<tr><th colspan="7">' + dateRangeTip + '</th></tr>');
|
||||
});
|
||||
|
||||
@@ -32,7 +32,7 @@ $(function()
|
||||
})
|
||||
|
||||
/* Get checked stories. */
|
||||
$('#batchToTaskButton').on('click', function()
|
||||
$(document).on('click', '#batchToTaskButton', function()
|
||||
{
|
||||
storyIdList = '';
|
||||
linedTaskIdList = '';
|
||||
@@ -53,6 +53,26 @@ $(function()
|
||||
|
||||
$('#submit').click(function()
|
||||
{
|
||||
var taskType = $('#type').val();
|
||||
var hourPoint = $('#hourPointValue').val();
|
||||
if(taskType.length == 0)
|
||||
{
|
||||
alert(typeNotEmpty);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(hourPoint == 0)
|
||||
{
|
||||
alert(hourPointNotEmpty);
|
||||
return false;
|
||||
}
|
||||
else if(typeof(hourPoint) != 'undefined' && (isNaN(hourPoint) || hourPoint < 0))
|
||||
{
|
||||
alert(hourPointNotError);
|
||||
return false;
|
||||
}
|
||||
hourPoint = typeof(hourPoint) == 'undefined' ? 0 : hourPoint;
|
||||
|
||||
if(linedTaskIdList)
|
||||
{
|
||||
confirmStoryToTask = confirmStoryToTask.replace('%s', linedTaskIdList);
|
||||
|
||||
@@ -154,6 +154,7 @@ $lang->execution->putoff = 'Zurückstellen';
|
||||
$lang->execution->suspend = 'Aussetzen';
|
||||
$lang->execution->close = 'Schließen';
|
||||
$lang->execution->export = 'Export';
|
||||
$lang->execution->next = "Next";
|
||||
|
||||
$lang->execution->endList[7] = '1 Woche';
|
||||
$lang->execution->endList[14] = '2 Wochen';
|
||||
|
||||
@@ -154,6 +154,7 @@ $lang->execution->putoff = 'Delay';
|
||||
$lang->execution->suspend = 'Suspend';
|
||||
$lang->execution->close = 'Close';
|
||||
$lang->execution->export = 'Export';
|
||||
$lang->execution->next = "Next";
|
||||
|
||||
$lang->execution->endList[7] = '1 Week';
|
||||
$lang->execution->endList[14] = '2 Weeks';
|
||||
|
||||
@@ -154,6 +154,7 @@ $lang->execution->putoff = 'Ajourner';
|
||||
$lang->execution->suspend = 'Suspendre';
|
||||
$lang->execution->close = 'Fermer';
|
||||
$lang->execution->export = 'Exporter';
|
||||
$lang->execution->next = "Suivant";
|
||||
|
||||
$lang->execution->endList[7] = '1 Semaine';
|
||||
$lang->execution->endList[14] = '2 Semaines';
|
||||
|
||||
@@ -154,6 +154,7 @@ $lang->execution->putoff = "延期";
|
||||
$lang->execution->suspend = "挂起";
|
||||
$lang->execution->close = "关闭";
|
||||
$lang->execution->export = "导出";
|
||||
$lang->execution->next = "下一步";
|
||||
|
||||
$lang->execution->endList[7] = '一星期';
|
||||
$lang->execution->endList[14] = '两星期';
|
||||
|
||||
@@ -3179,24 +3179,8 @@ class executionModel extends model
|
||||
*/
|
||||
public function getBeginEnd4CFD($execution)
|
||||
{
|
||||
$begin = $execution->begin;
|
||||
$end = $execution->end;
|
||||
if(helper::today() < $execution->begin)
|
||||
{
|
||||
$begin = helper::today();
|
||||
$end = helper::today();
|
||||
}
|
||||
elseif((helper::today() >= $execution->begin) and (helper::today() <= $execution->end))
|
||||
{
|
||||
$begin = (date('Y-m-d', strtotime('-13 days')) < $execution->begin) ? $execution->begin : date('Y-m-d', strtotime('-13 days'));
|
||||
$end = helper::today();
|
||||
}
|
||||
elseif((helper::today() > $execution->end))
|
||||
{
|
||||
$begin = date('Y-m-d', strtotime('-13 days', strtotime($execution->end))) > $execution->begin ? date('Y-m-d', strtotime('-13 days', strtotime($execution->end))) : $execution->begin;
|
||||
$end = $execution->end;
|
||||
}
|
||||
|
||||
$end = (!helper::isZeroDate($execution->closedDate) and date('Y-m-d', strtotime($execution->closedDate)) < helper::today()) ? date('Y-m-d', strtotime($execution->closedDate)) : helper::today();
|
||||
$begin = (!helper::isZeroDate($execution->openedDate) and date('Y-m-d', strtotime($execution->openedDate)) > date('Y-m-d', strtotime('-13 days', strtotime($end)))) ? date('Y-m-d', strtotime($execution->openedDate)) : date('Y-m-d', strtotime('-13 days', strtotime($end)));
|
||||
return array($begin, $end);
|
||||
}
|
||||
|
||||
@@ -4385,7 +4369,7 @@ class executionModel extends model
|
||||
}
|
||||
echo empty($execution->children) ? html::a(helper::createLink('execution', 'view', "executionID=$execution->id"), $execution->name) : $execution->name;
|
||||
echo '<td>' . zget($users, $execution->PM) . '</td>';
|
||||
echo "<td class='status-{$execution->status}'>" . zget($this->lang->project->statusList, $execution->status) . '</td>';
|
||||
echo "<td class='status-{$execution->status} text-center'>" . zget($this->lang->project->statusList, $execution->status) . '</td>';
|
||||
echo '<td>' . html::ring($execution->hours->progress) . '</td>';
|
||||
echo helper::isZeroDate($execution->begin) ? '<td></td>' : '<td>' . $execution->begin . '</td>';
|
||||
if(!helper::isZeroDate($execution->end))
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
<?php js::set('YUnit', $lang->execution->count); ?>
|
||||
<?php js::set('XUnit', $lang->execution->burnXUnit); ?>
|
||||
<?php js::set('dateRangeTip', $lang->execution->charts->cfd->dateRangeTip); ?>
|
||||
<?php js::set('today', date(DT_DATE1)); ?>
|
||||
<?php js::set('executionBegin', $execution->begin); ?>
|
||||
<?php js::set('minDate', $minDate); ?>
|
||||
<?php js::set('maxDate', $maxDate); ?>
|
||||
<div id='mainMenu' class='clearfix'>
|
||||
<div class='btn-toolbar pull-left'>
|
||||
<?php
|
||||
|
||||
@@ -18,8 +18,12 @@
|
||||
<?php js::set('productID', $this->cookie->storyProductParam);?>
|
||||
<?php js::set('branchID', str_replace(',', '_', $this->cookie->storyBranchParam));?>
|
||||
<?php js::set('executionID', $execution->id);?>
|
||||
<?php js::set('projectID', $execution->project);?>
|
||||
<?php js::set('confirmUnlinkStory', $lang->execution->confirmUnlinkStory)?>
|
||||
<?php js::set('typeError', sprintf($this->lang->error->notempty, $this->lang->task->type))?>
|
||||
<?php js::set('typeNotEmpty', sprintf($this->lang->error->notempty, $this->lang->task->type));?>
|
||||
<?php js::set('hourPointNotEmpty', sprintf($this->lang->error->notempty, $this->lang->story->convertRelations));?>
|
||||
<?php js::set('hourPointNotError', sprintf($this->lang->story->float, $this->lang->story->convertRelations));?>
|
||||
<?php js::set('workingHourError', sprintf($this->lang->error->notempty, $this->lang->workingHour))?>
|
||||
<?php js::set('linkedTaskStories', $linkedTaskStories);?>
|
||||
<?php js::set('confirmStoryToTask', $lang->execution->confirmStoryToTask);?>
|
||||
@@ -318,7 +322,7 @@
|
||||
<h4 class="modal-title"><?php echo $lang->story->batchToTask;?></h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method='post' class='form-ajax' action='<?php echo $this->createLink('story', 'batchToTask', "executionID=$execution->id");?>'>
|
||||
<form method='post' class='not-watch' action='<?php echo $this->createLink('story', 'batchToTask', "executionID=$execution->id&projectID=$execution->project");?>'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th class="<?php echo strpos($this->app->getClientLang(), 'zh') === false ? 'w-140px' : 'w-80px';?>"><?php echo $lang->task->type?></th>
|
||||
@@ -328,7 +332,7 @@
|
||||
<?php if($lang->hourCommon !== $lang->workingHour):?>
|
||||
<tr>
|
||||
<th><?php echo $lang->story->one . $lang->hourCommon?></th>
|
||||
<td><div class='input-group'><span class='input-group-addon'><?php echo "=";?></span><?php echo html::input('hourPointValue', '', "class='form-control' required");?> <span class='input-group-addon'><?php echo $lang->workingHour;?></span></div></td>
|
||||
<td><div class='input-group'><span class='input-group-addon'><?php echo "≈";?></span><?php echo html::input('hourPointValue', '', "class='form-control' required");?> <span class='input-group-addon'><?php echo $lang->workingHour;?></span></div></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<?php endif;?>
|
||||
@@ -342,7 +346,7 @@
|
||||
<tr>
|
||||
<td colspan='3' class='text-center'>
|
||||
<?php echo html::hidden('storyIdList', '');?>
|
||||
<?php echo html::submitButton($lang->story->toTask, '', 'btn btn-primary');?>
|
||||
<?php echo html::submitButton($lang->execution->next, '', 'btn btn-primary');?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Regular → Executable
+6
@@ -127,6 +127,12 @@ class file extends control
|
||||
return print("<html><head><meta charset='utf-8'></head><body>{$this->lang->file->fileNotFound}</body></html>");
|
||||
}
|
||||
|
||||
if(!$this->file->checkPriv($file))
|
||||
{
|
||||
echo(js::alert($this->lang->file->accessDenied));
|
||||
return print(js::locate(helper::createLink('my', 'index')));
|
||||
}
|
||||
|
||||
/* Judge the mode, down or open. */
|
||||
$mode = 'down';
|
||||
$fileTypes = 'txt|jpg|jpeg|gif|png|bmp|xml|html';
|
||||
|
||||
Regular → Executable
+1
@@ -56,6 +56,7 @@ $lang->file->uploadImagesExplain = 'Hinweis: Beim Upload von .jpg, .jpeg, .gif,
|
||||
$lang->file->saveAndNext = 'Save and Next';
|
||||
$lang->file->importPager = 'Total: <strong>%s</strong>. Page <strong>%s</strong> of <strong>%s</strong>';
|
||||
$lang->file->importSummary = "Import <strong id='allCount'>%s</strong> items You can <strong>%s</strong> items/page, so you have to import <strong id='times'>%s</strong> times.";
|
||||
$lang->file->accessDenied = 'Access denied to this file!';
|
||||
|
||||
$lang->file->errorNotExists = "<span class='text-red'>'%s' wurde nicht gefunden.</span>";
|
||||
$lang->file->errorCanNotWrite = "<span class='text-red'>'%s' ist nicht beschreibbar. Bitte passen Sie die Berechtigungen an. Befehl <span class='code'>sudo chmod -R 777 '%s'</span></span> in Linux.";
|
||||
|
||||
Regular → Executable
+1
@@ -56,6 +56,7 @@ $lang->file->uploadImagesExplain = 'Note: upload .jpg, .jpeg, .gif, or .png imag
|
||||
$lang->file->saveAndNext = 'Save and Next';
|
||||
$lang->file->importPager = 'Total: <strong>%s</strong>. Page <strong>%s</strong> of <strong>%s</strong>';
|
||||
$lang->file->importSummary = "Import <strong id='allCount'>%s</strong> items You can <strong>%s</strong> items/page, so you have to import <strong id='times'>%s</strong> times.";
|
||||
$lang->file->accessDenied = 'Access denied to this file!';
|
||||
|
||||
$lang->file->errorNotExists = "<span class='text-red'>'%s' is not found.</span>";
|
||||
$lang->file->errorCanNotWrite = "<span class='text-red'>'%s' is not writable. Please change its permission. Enter <span class='code'>sudo chmod -R 777 '%s'</span></span> in Linux.";
|
||||
|
||||
Regular → Executable
+1
@@ -56,6 +56,7 @@ $lang->file->uploadImagesExplain = "Note : Chargez images au format .jpg, .jpeg,
|
||||
$lang->file->saveAndNext = 'Enregistrer et poursuivre';
|
||||
$lang->file->importPager = 'Total: <strong>%s</strong>. Page <strong>%s</strong> de <strong>%s</strong>';
|
||||
$lang->file->importSummary = "Import <strong id='allCount'>%s</strong> items Vous pouvez avoir <strong>%s</strong> items/page, vous devez donc importer <strong id='times'>%s</strong> fois.";
|
||||
$lang->file->accessDenied = 'Access denied to this file!';
|
||||
|
||||
$lang->file->errorNotExists = "<span class='text-red'>'%s' non trouvé.</span>";
|
||||
$lang->file->errorCanNotWrite = "<span class='text-red'>'%s' non inscriptible. Changez les permissions. Entrez la commande <span class='code'>sudo chmod -R 777 '%s'</span></span> sous Linux.";
|
||||
|
||||
Regular → Executable
+1
@@ -51,6 +51,7 @@ $lang->file->uploadImagesExplain = 'Ghi chú: upload .jpg, .jpeg, .gif, or .png
|
||||
$lang->file->saveAndNext = 'Save and Next';
|
||||
$lang->file->importPager = 'Total: <strong>%s</strong>. Page <strong>%s</strong> of <strong>%s</strong>';
|
||||
$lang->file->importSummary = "Import <strong id='allCount'>%s</strong> items You can <strong>%s</strong> items/page, so you have to import <strong id='times'>%s</strong> times.";
|
||||
$lang->file->accessDenied = 'Access denied to this file!';
|
||||
|
||||
$lang->file->errorNotExists = "<span class='text-red'>'%s' không là found.</span>";
|
||||
$lang->file->errorCanNotWrite = "<span class='text-red'>'%s' không thể ghi. Vui lòng change its permission. Enter <span class='code'>sudo chmod -R 777 '%s'</span></span> in Linux.";
|
||||
|
||||
Regular → Executable
+1
@@ -56,6 +56,7 @@ $lang->file->uploadImagesExplain = '注:请上传"jpg, jpeg, gif, png"格式
|
||||
$lang->file->saveAndNext = '保存并跳转下一页';
|
||||
$lang->file->importPager = '共有<strong>%s</strong>条记录,当前第<strong>%s</strong>页,共有<strong>%s</strong>页';
|
||||
$lang->file->importSummary = "本次导入共有<strong id='allCount'>%s</strong>条记录,每页导入%s条,需要导入<strong id='times'>%s</strong>次";
|
||||
$lang->file->accessDenied = '您无权下载该附件!';
|
||||
|
||||
$lang->file->errorNotExists = "<span class='text-red'>文件夹 '%s' 不存在</span>";
|
||||
$lang->file->errorCanNotWrite = "<span class='text-red'>文件夹 '%s' 不可写,请改变文件夹的权限。在linux中输入指令: <span class='code'>sudo chmod -R 777 %s</span></span>";
|
||||
|
||||
Regular → Executable
Regular → Executable
+52
@@ -525,6 +525,58 @@ class fileModel extends model
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check file priv.
|
||||
*
|
||||
* @param int $file
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function checkPriv($file)
|
||||
{
|
||||
if($this->app->user->admin) return true;
|
||||
|
||||
$objectType = $file->objectType;
|
||||
$objectID = $file->objectID;
|
||||
|
||||
$projectObjects = array('design', 'issue', 'risk');
|
||||
$productObjects = array('story', 'bug', 'testcase', 'productplan');
|
||||
$executionObjects = array('task', 'build');
|
||||
|
||||
$table = $this->config->objectTables[$objectType];
|
||||
if(!$table) return true;
|
||||
|
||||
if(in_array($objectType, $projectObjects))
|
||||
{
|
||||
$projectID = $this->dao->findByID($objectID)->from($table)->fetch('project');
|
||||
}
|
||||
elseif(in_array($objectType, $productObjects))
|
||||
{
|
||||
$productID = $this->dao->findByID($objectID)->from($table)->fetch('product');
|
||||
}
|
||||
elseif(in_array($objectType, $executionObjects))
|
||||
{
|
||||
$executionID = $this->dao->findByID($objectID)->from($table)->fetch('execution');
|
||||
}
|
||||
elseif($objectType == 'doc')
|
||||
{
|
||||
$doc = $this->dao->findById($objectID)->from(TABLE_DOC)->fetch();
|
||||
return $this->loadModel('doc')->checkPrivDoc($doc);
|
||||
}
|
||||
elseif($objectType == 'feedback')
|
||||
{
|
||||
$productID = $this->dao->findById($objectID)->from(TABLE_FEEDBACK)->fetch();
|
||||
$grantProducts = $this->loadModel('feedback')->getGrantProducts();
|
||||
return in_array($productID, array_keys($grantProducts));
|
||||
}
|
||||
|
||||
if(isset($projectID) and strpos(",{$this->app->user->view->projects},", ",$projectID,") === false) return false;
|
||||
if(isset($productID) and strpos(",{$this->app->user->view->products},", ",$productID,") === false) return false;
|
||||
if(isset($executionID) and strpos(",{$this->app->user->view->sprints},", ",$executionID,") === false) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress image to config configured size.
|
||||
*
|
||||
|
||||
@@ -1240,9 +1240,9 @@ EOF;
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$this->user->updatePassword($this->app->user->id);
|
||||
if(dao::isError()) return print(js::error(dao::getError()));
|
||||
if(isonlybody()) return print(js::closeModal('parent.parent', 'this'));
|
||||
return print(js::locate($this->createLink('my', 'index'), 'parent.parent'));
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true));
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess,locate => $this->createLink('my', 'index')));
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->changePassword;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#mainContent table > tbody > tr > td > div.text-danger.help-text {word-break: break-all;}
|
||||
@@ -1 +1,2 @@
|
||||
.c-hours, .c-progress {width: 80px !important;}
|
||||
.c-hours, .c-progress {width: 80px !important;}
|
||||
th.c-status {padding-right: 8px !important;}
|
||||
|
||||
@@ -14,6 +14,7 @@ $(document).ready(function()
|
||||
var password1 = $('input#password1').val().trim();
|
||||
var passwordStrength = computePasswordStrength(password1);
|
||||
var rand = $('input#verifyRand').val();
|
||||
if(!password1Encrypted) $("#passwordLength").val(password1.length);
|
||||
|
||||
if($("form input[name=passwordStrength]").length == 0) $('#submit').after("<input type='hidden' name='passwordStrength' value='0' />");
|
||||
$("form input[name=passwordStrength]").val(passwordStrength);
|
||||
|
||||
@@ -13,6 +13,7 @@ $(document).ready(function()
|
||||
var password = $('input#verifyPassword').val();
|
||||
var password1 = $('input#password1').val();
|
||||
var passwordStrength = computePasswordStrength(password1);
|
||||
if(!password1Encrypted) $("#passwordLength").val(password1.length);
|
||||
|
||||
if($("form input[name=passwordStrength]").length == 0) $('#submit').after("<input type='hidden' name='passwordStrength' value='0' />");
|
||||
$("form input[name=passwordStrength]").val(passwordStrength);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<div class='main-header'>
|
||||
<h2><i class='icon-key'></i> <?php echo $lang->my->changePassword;?></h2>
|
||||
</div>
|
||||
<form method='post' target='hiddenwin'>
|
||||
<form method='post' class='form-ajax'>
|
||||
<table align='center' class='table table-form w-320px'>
|
||||
<tr>
|
||||
<th class='rowhead thWidth'><?php echo $lang->user->account;?></th>
|
||||
@@ -35,7 +35,7 @@
|
||||
<th><?php echo $lang->user->newPassword;?></th>
|
||||
<td>
|
||||
<span class='input-group'>
|
||||
<?php echo html::password('password1', '', "class='form-control' onmouseup='checkPassword(this.value)' onkeyup='checkPassword(this.value)' placeholder='" . (!empty($config->safe->mode) ? $lang->user->placeholder->passwordStrength[$config->safe->mode] : '') . "'");?>
|
||||
<?php echo html::password('password1', '', "class='form-control' onmouseup='checkPassword(this.value)' onkeyup='checkPassword(this.value)' placeholder='" . zget($lang->user->placeholder->passwordStrength, $config->safe->mode, '') . "'");?>
|
||||
<span class='input-group-addon' id='passwordStrength'></span>
|
||||
</span>
|
||||
</td>
|
||||
@@ -45,7 +45,10 @@
|
||||
<td><?php echo html::password('password2', '', "class='form-control'");?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='2' class='text-center form-actions'><?php echo html::submitButton();?></td>
|
||||
<td colspan='2' class='text-center form-actions'>
|
||||
<?php echo html::hidden('passwordLength', 0);?>
|
||||
<?php echo html::submitButton();?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php if(!empty($this->app->user->modifyPasswordReason)):?>
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
</tr>
|
||||
</table>
|
||||
<?php echo html::select('visions[]', $this->user->getVisionList(), $user->visions, "class='form-control chosen' multiple");?>
|
||||
<div class='text-center form-actions'><?php echo html::submitButton() . html::backButton();?></div>
|
||||
<div class='text-center form-actions'><?php echo html::hidden('passwordLength', 0) . html::submitButton() . html::backButton();?></div>
|
||||
</form>
|
||||
<?php echo html::hidden('verifyRand', $rand);?>
|
||||
</div>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
<?php endif;?>
|
||||
<th class='c-date'><?php echo $lang->execution->begin;?></th>
|
||||
<th class='c-date'><?php echo $lang->execution->end;?></th>
|
||||
<th class='c-status'><?php echo $lang->statusAB;?></th>
|
||||
<th class='c-status text-center'><?php echo $lang->statusAB;?></th>
|
||||
<th class='c-user'><?php echo $lang->team->role;?></th>
|
||||
<th class='c-date'><?php echo $lang->team->join;?></th>
|
||||
<th class='c-hours'><?php echo $lang->my->hours;?></th>
|
||||
@@ -53,13 +53,13 @@
|
||||
<tr class='text-left'>
|
||||
<td><?php echo html::a($link, sprintf('%03d', $execution->id));?></td>
|
||||
<td class='c-name text-left'>
|
||||
<?php if($config->systemMode == 'new'):?>
|
||||
<?php if($config->systemMode == 'new'):?>
|
||||
<?php
|
||||
if($execution->type === 'stage') echo "<span class='project-type-label label label-outline label-warning'>{$lang->project->stage}</span> ";
|
||||
if($execution->type === 'sprint') echo "<span class='project-type-label label label-outline label-info'>{$lang->executionCommon}</span> ";
|
||||
if($execution->type === 'kanban') echo "<span class='project-type-label label label-outline label-info'>{$lang->execution->kanban}</span> ";
|
||||
?>
|
||||
<?php endif;?>
|
||||
<?php endif;?>
|
||||
<?php echo html::a($link, $execution->name, '', "title='$execution->name'");?>
|
||||
</td>
|
||||
<?php if($config->systemMode == 'new'):?>
|
||||
@@ -69,7 +69,7 @@
|
||||
<?php endif;?>
|
||||
<td><?php echo $execution->begin;?></td>
|
||||
<td><?php echo $execution->end;?></td>
|
||||
<td class="c-status">
|
||||
<td class="c-status text-center">
|
||||
<?php if(isset($execution->delay)):?>
|
||||
<span class="status-project status-delayed" title='<?php echo $lang->execution->delayed;?>'><?php echo $lang->execution->delayed;?></span>
|
||||
<?php else:?>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
$lang->port = new stdclass();
|
||||
|
||||
$lang->port->reservedWord['id'] = 'ID';
|
||||
$lang->port->reservedWord['type'] = 'Type';
|
||||
$lang->port->reservedWord['project'] = 'Project';
|
||||
$lang->port->reservedWord['execution'] = 'Execution';
|
||||
$lang->port->reservedWord['product'] = 'Project';
|
||||
$lang->port->reservedWord['code'] = 'CODE';
|
||||
$lang->port->reservedWord['name'] = 'Name';
|
||||
$lang->port->reservedWord['title'] = 'Title';
|
||||
|
||||
$lang->port->importCase = 'Import EXCEL';
|
||||
$lang->port->importNotice = 'Notice: Importing data is risky! Make sure to complete the following steps in sequence before merging.';
|
||||
$lang->port->noRequire = 'Row %s has“%s ”which is a required field and it should not be blank.';
|
||||
$lang->port->exportTemplate = 'Export Template';
|
||||
$lang->port->import = 'Import';
|
||||
$lang->port->id = 'ID';
|
||||
|
||||
$lang->port->new = 'New';
|
||||
|
||||
$lang->port->num = 'Count:';
|
||||
$lang->port->children = 'Child';
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
$lang->port = new stdclass();
|
||||
|
||||
$lang->port->reservedWord['id'] = 'ID';
|
||||
$lang->port->reservedWord['type'] = 'Type';
|
||||
$lang->port->reservedWord['project'] = 'Project';
|
||||
$lang->port->reservedWord['execution'] = 'Execution';
|
||||
$lang->port->reservedWord['product'] = 'Project';
|
||||
$lang->port->reservedWord['code'] = 'CODE';
|
||||
$lang->port->reservedWord['name'] = 'Name';
|
||||
$lang->port->reservedWord['title'] = 'Title';
|
||||
|
||||
$lang->port->importCase = 'Import EXCEL';
|
||||
$lang->port->importNotice = 'Notice: Importing data is risky! Make sure to complete the following steps in sequence before merging.';
|
||||
$lang->port->noRequire = 'Row %s has“%s ”which is a required field and it should not be blank.';
|
||||
$lang->port->exportTemplate = 'Export Template';
|
||||
$lang->port->import = 'Import';
|
||||
$lang->port->id = 'ID';
|
||||
|
||||
$lang->port->new = 'New';
|
||||
|
||||
$lang->port->num = 'Count:';
|
||||
$lang->port->children = 'Child';
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
$lang->port = new stdclass();
|
||||
|
||||
$lang->port->reservedWord['id'] = 'ID';
|
||||
$lang->port->reservedWord['type'] = 'Type';
|
||||
$lang->port->reservedWord['project'] = 'Project';
|
||||
$lang->port->reservedWord['execution'] = 'Execution';
|
||||
$lang->port->reservedWord['product'] = 'Project';
|
||||
$lang->port->reservedWord['code'] = 'CODE';
|
||||
$lang->port->reservedWord['name'] = 'Name';
|
||||
$lang->port->reservedWord['title'] = 'Title';
|
||||
|
||||
$lang->port->importCase = 'Import EXCEL';
|
||||
$lang->port->importNotice = 'Notice: Importing data is risky! Make sure to complete the following steps in sequence before merging.';
|
||||
$lang->port->noRequire = 'Row %s has“%s ”which is a required field and it should not be blank.';
|
||||
$lang->port->exportTemplate = 'Export Template';
|
||||
$lang->port->import = 'Import';
|
||||
$lang->port->id = 'ID';
|
||||
|
||||
$lang->port->new = 'New';
|
||||
|
||||
$lang->port->num = 'Count:';
|
||||
$lang->port->children = 'Child';
|
||||
@@ -9,7 +9,6 @@ $lang->port->reservedWord['product'] = '所属产品';
|
||||
$lang->port->reservedWord['code'] = '代号';
|
||||
$lang->port->reservedWord['name'] = '名称';
|
||||
$lang->port->reservedWord['title'] = '标题';
|
||||
$lang->port->reservedWord['asdawdadw'] = '测试字段';
|
||||
|
||||
$lang->port->importCase = '导入EXCEL';
|
||||
$lang->port->importNotice = '请先导出模板,按照模板格式填写数据后再导入。';
|
||||
|
||||
@@ -16,3 +16,4 @@ tbody.sortable > tr > td.sort-handler {color: #3c4353 !important;}
|
||||
|
||||
div.checkbox-primary + span.table-nest-icon {margin-left:0px !important;}
|
||||
#checkAll + label.hover:after {border-width: 0px;}
|
||||
.c-budget {padding-right:16px !important;}
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
<?php endif;?>
|
||||
</td>
|
||||
<?php $programBudget = $this->loadModel('project')->getBudgetWithUnit($program->budget);?>
|
||||
<td class='text-right'><?php echo $program->budget != 0 ? zget($lang->project->currencySymbol, $program->budgetUnit) . ' ' . $programBudget : $lang->project->future;?></td>
|
||||
<td class='text-right c-budget'><?php echo $program->budget != 0 ? zget($lang->project->currencySymbol, $program->budgetUnit) . ' ' . $programBudget : $lang->project->future;?></td>
|
||||
<td><?php echo $program->begin;?></td>
|
||||
<td><?php echo $program->end == LONG_TIME ? $lang->program->longTime : $program->end;?></td>
|
||||
<td>
|
||||
|
||||
@@ -1183,7 +1183,7 @@ class project extends control
|
||||
$this->view->branchOption = $branchOption;
|
||||
$this->view->branchTagOption = $branchTagOption;
|
||||
$this->view->executions = $executions;
|
||||
$this->view->plans = $this->loadModel('productplan')->getPairs($productID);
|
||||
$this->view->plans = $this->loadModel('productplan')->getPairs($productID ? $productID : array_keys($products));
|
||||
$this->view->stories = $storyList;
|
||||
$this->view->tasks = $taskList;
|
||||
$this->view->projectPairs = $this->project->getPairsByProgram();
|
||||
|
||||
@@ -2029,7 +2029,7 @@ class projectModel extends model
|
||||
echo $project->end;
|
||||
break;
|
||||
case 'status':
|
||||
echo "<span class='status-task status-{$project->status}'> " . zget($this->lang->project->statusList, $project->status) . "</span>";
|
||||
echo "<span class='status-task text-center status-{$project->status}'> " . zget($this->lang->project->statusList, $project->status) . "</span>";
|
||||
break;
|
||||
case 'budget':
|
||||
echo $budgetTitle;
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
<?php echo $lang->nameAB;?>
|
||||
</th>
|
||||
<th class='c-user'><?php echo $lang->execution->owner;?></th>
|
||||
<th class='c-status'><?php echo $lang->project->status;?></th>
|
||||
<th class='c-status text-center'><?php echo $lang->project->status;?></th>
|
||||
<th class='c-hours'><?php echo $lang->project->progress;?></th>
|
||||
<th class='c-date'><?php echo $lang->programplan->begin;?></th>
|
||||
<th class='c-date'><?php echo $lang->programplan->end;?></th>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
<th class='c-user'><?php echo $lang->openedByAB;?></th>
|
||||
<th class='c-user'><?php echo $lang->assignedToAB;?></th>
|
||||
<th class='c-estimate text-right'><?php echo $lang->story->estimateAB;?></th>
|
||||
<th class='c-status'><?php echo $lang->statusAB;?></th>
|
||||
<th class='c-status text-center'><?php echo $lang->statusAB;?></th>
|
||||
<th class='c-stage'><?php echo $lang->story->stageAB;?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -50,14 +50,14 @@
|
||||
<td><span class='label-pri <?php echo 'label-pri-' . $story->pri;?>' title='<?php echo zget($lang->story->priList, $story->pri)?>'><?php echo zget($lang->story->priList, $story->pri)?></span></td>
|
||||
<td class='text-left nobr c-name' title='<?php echo $story->title?>'>
|
||||
<?php
|
||||
if($story->parent > 0) echo "<span class='label'>{$lang->story->childrenAB}</span>";
|
||||
if($story->parent > 0) echo "<span class='label label-badge label-light' title='{$lang->story->childrenAB}'>{$lang->story->childrenAB}</span>";
|
||||
echo html::a($this->createLink('story', 'view', "storyID=$story->id", '', true), $story->title, '', "data-toggle='modal' data-type='iframe' data-width='90%'");
|
||||
?>
|
||||
</td>
|
||||
<td><?php echo zget($users, $story->openedBy);?></td>
|
||||
<td><?php echo zget($users, $story->assignedTo);?></td>
|
||||
<td class='text-right' title="<?php echo $story->estimate . ' ' . $lang->hourCommon;?>"><?php echo $story->estimate . $config->hourUnit;?></td>
|
||||
<td><span class='status-story status-<?php echo $story->status?>'><?php echo $this->processStatus('story', $story);?></span></td>
|
||||
<td class='text-center'><span class='status-story status-<?php echo $story->status?>'><?php echo $this->processStatus('story', $story);?></span></td>
|
||||
<td><?php echo zget($lang->story->stageList, $story->stage);?></td>
|
||||
</tr>
|
||||
<?php $unlinkedCount++;?>
|
||||
|
||||
@@ -75,7 +75,7 @@
|
||||
<th class="text-left"><?php common::printOrderLink('title', $orderBy, $vars, $lang->story->title);?></th>
|
||||
<th class='c-user'> <?php common::printOrderLink('openedBy', $orderBy, $vars, $lang->openedByAB);?></th>
|
||||
<th class='w-80px text-right'><?php common::printOrderLink('estimate', $orderBy, $vars, $lang->story->estimateAB);?></th>
|
||||
<th class='w-90px'> <?php common::printOrderLink('status', $orderBy, $vars, $lang->statusAB);?></th>
|
||||
<th class='w-90px text-center'> <?php common::printOrderLink('status', $orderBy, $vars, $lang->statusAB);?></th>
|
||||
<th class='w-100px'><?php common::printOrderLink('stage', $orderBy, $vars, $lang->story->stageAB);?></th>
|
||||
<th class='c-actions-1'><?php echo $lang->actions?></th>
|
||||
</tr>
|
||||
@@ -96,13 +96,13 @@
|
||||
<td><span class='label-pri <?php echo 'label-pri-' . $story->pri;?>' title='<?php echo zget($lang->story->priList, $story->pri, $story->pri);?>'><?php echo zget($lang->story->priList, $story->pri, $story->pri);?></span></td>
|
||||
<td class='text-left nobr' title='<?php echo $story->title?>'>
|
||||
<?php
|
||||
if($story->parent > 0) echo "<span class='label'>{$lang->story->childrenAB}</span>";
|
||||
if($story->parent > 0) echo "<span class='label label-badge label-light' title='{$lang->story->childrenAB}'>{$lang->story->childrenAB}</span>";
|
||||
echo html::a($storyLink,$story->title, '', "class='preview'");
|
||||
?>
|
||||
</td>
|
||||
<td><?php echo zget($users, $story->openedBy);?></td>
|
||||
<td class='text-right' title="<?php echo $story->estimate . ' ' . $lang->hourCommon;?>"><?php echo $story->estimate . $config->hourUnit;?></td>
|
||||
<td>
|
||||
<td class='text-center'>
|
||||
<span class='status-story status-<?php echo $story->status;?>'><?php echo $this->processStatus('story', $story);?></span>
|
||||
</td>
|
||||
<td><?php echo $lang->story->stageList[$story->stage];?></td>
|
||||
@@ -196,7 +196,7 @@
|
||||
<td><?php echo zget($users, $bug->openedBy);?></td>
|
||||
<td><?php echo substr($bug->openedDate, 5, 11)?></td>
|
||||
<td><?php echo zget($users, $bug->resolvedBy);?></td>
|
||||
<td><?php echo substr($bug->resolvedDate, 5, 11)?></td>
|
||||
<td><?php echo helper::isZeroDate($bug->resolvedDate) ? '' : substr($bug->resolvedDate, 5, 11);?></td>
|
||||
<td class='c-actions'>
|
||||
<?php
|
||||
if(common::hasPriv('release', 'unlinkBug') and $canBeChanged)
|
||||
|
||||
+30
-12
@@ -1730,29 +1730,47 @@ class story extends control
|
||||
* Batch stories convert to tasks.
|
||||
*
|
||||
* @param int $executionID
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function batchToTask($executionID = 0)
|
||||
public function batchToTask($executionID = 0, $projectID = 0)
|
||||
{
|
||||
if(!empty($_POST))
|
||||
if(!empty($_POST['name']))
|
||||
{
|
||||
$response['result'] = 'success';
|
||||
$response['message'] = $this->lang->story->successToTask;
|
||||
|
||||
$tasks = $this->story->batchToTask($executionID, $this->session->project);
|
||||
|
||||
if(dao::isError())
|
||||
{
|
||||
$response['result'] = 'fail';
|
||||
$response['message'] = dao::getError();
|
||||
return $this->send($response);
|
||||
}
|
||||
$tasks = $this->story->batchToTask($executionID, $projectID);
|
||||
if(dao::isError()) return print(js::error(dao::getError()));
|
||||
|
||||
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'idList' => $tasks));
|
||||
$response['locate'] = $this->createLink('execution', 'task', "executionID=$executionID");
|
||||
return $this->send($response);
|
||||
return print(js::locate($this->createLink('execution', 'task', "executionID=$executionID"), 'parent'));
|
||||
}
|
||||
|
||||
if(!$this->post->storyIdList) return print(js::locate($this->session->storyList, 'parent'));
|
||||
|
||||
$stories = $this->story->getByList($_POST['storyIdList']);
|
||||
$storyGroup = array();
|
||||
foreach($stories as $story)
|
||||
{
|
||||
if(strpos('draft,closed', $story->status) !== false) continue;
|
||||
if(isset($storyGroup[$story->module])) continue;
|
||||
$storyGroup[$story->module] = $this->story->getExecutionStoryPairs($executionID, 0, 'all', $story->module, 'short', 'active');
|
||||
}
|
||||
|
||||
$this->view->title = $this->lang->story->batchToTask;
|
||||
$this->view->executionID = $executionID;
|
||||
$this->view->syncFields = empty($_POST['fields']) ? array() : $_POST['fields'];
|
||||
$this->view->hourPointValue = empty($_POST['hourPointValue']) ? 0 : $_POST['hourPointValue'];
|
||||
$this->view->taskType = empty($_POST['type']) ? '' : $_POST['type'];
|
||||
$this->view->stories = $stories;
|
||||
$this->view->storyGroup = $storyGroup;
|
||||
$this->view->modules = $this->loadModel('tree')->getTaskOptionMenu($executionID, 0, 0, 'allModule');
|
||||
$this->view->members = $this->loadModel('user')->getTeamMemberPairs($executionID, 'execution', 'nodeleted');
|
||||
$this->view->storyTasks = $this->loadModel('task')->getStoryTaskCounts(array_keys($stories), $executionID);
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
.chosen-container[id^="story"] {width: 200px; max-width: 150px;}
|
||||
select[id^="story"] + .picker-single {width: 130px; max-width: 130px;}
|
||||
#mainContent .main-header h2 {max-width: 300px;}
|
||||
|
||||
#batchToTaskForm .input-group,
|
||||
#batchToTaskForm .input-group .form-control {position: static;}
|
||||
#batchToTaskForm .input-group .colorpicker {z-index: 2;}
|
||||
#batchToTaskForm .input-group .colorpicker.open {z-index: 5;}
|
||||
.main-header .pull-left {max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
|
||||
|
||||
.chosen-results > li.has-task,
|
||||
.chosen-results > li.has-new-task {position: relative; color: #388E3C;}
|
||||
.chosen-results > li.has-task.highlighted,
|
||||
.chosen-results > li.has-new-task.highlighted {color: #fff;}
|
||||
|
||||
.c-id {width: 30px;}
|
||||
.c-name, .c-desc {width: 150px;}
|
||||
.c-story {width: 200px;}
|
||||
.c-assigned {width: 130px;}
|
||||
.c-date {width: 120px;}
|
||||
.c-pri {width: 80px;}
|
||||
.c-actions {width: 60px;}
|
||||
Executable
+304
@@ -0,0 +1,304 @@
|
||||
$(document).on('change', "[name^='estStarted'], [name^='deadline']", function()
|
||||
{
|
||||
toggleCheck($(this));
|
||||
});
|
||||
|
||||
/**
|
||||
* Set story related.
|
||||
*
|
||||
* @param int $num
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function setStoryRelated(num)
|
||||
{
|
||||
setPreview(num);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle checkbox.
|
||||
*
|
||||
* @param object $obj
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function toggleCheck(obj)
|
||||
{
|
||||
var $this = $(obj);
|
||||
var date = $this.val();
|
||||
var $ditto = $this.closest('div').find("input[type='checkBox']");
|
||||
if(date == '')
|
||||
{
|
||||
$ditto.attr('checked', true);
|
||||
$ditto.closest('.input-group-addon').show();
|
||||
}
|
||||
else
|
||||
{
|
||||
$ditto.removeAttr('checked');
|
||||
$ditto.closest('.input-group-addon').hide();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set stories.
|
||||
*
|
||||
* @param int $moduleID
|
||||
* @param int $executionID
|
||||
* @param int $num
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function setStories(moduleID, executionID, num)
|
||||
{
|
||||
var link = createLink('story', 'ajaxGetExecutionStories', 'executionID=' + executionID + '&productID=0&branch=all&moduleID=' + moduleID + '&storyID=0&num=' + num + '&type=short');
|
||||
$.get(link, function(stories)
|
||||
{
|
||||
var storyID = $('#story' + num).val();
|
||||
if(!stories) stories = '<select id="story' + num + '" name="story[' + num + ']" class="form-control"></select>';
|
||||
$('#story' + num).replaceWith(stories);
|
||||
if(num != 0 && (moduleID == 0 || moduleID == 'ditto')) $('#story' + num).append("<option value='ditto'>" + ditto + "</option>");
|
||||
$('#story' + num).val(storyID);
|
||||
|
||||
var chosenWidth = $("#story" + num + "_chosen").css('max-width');
|
||||
$("#story" + num + "_chosen").remove();
|
||||
$("#story" + num).next('.picker').remove();
|
||||
$("#story" + num).chosen();
|
||||
$("#story" + num + "_chosen").width(chosenWidth).css('max-width', chosenWidth);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy story title.
|
||||
*
|
||||
* @param int $num
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function copyStoryTitle(num)
|
||||
{
|
||||
var $story = $('#story' + num);
|
||||
var storyTitle = $story.find('option:selected').text();
|
||||
var storyValue = $story.find('option:selected').val();
|
||||
var begin = parseInt($story.closest('tr').children('.c-id').text()) - 2;
|
||||
|
||||
if(storyValue === 'ditto')
|
||||
{
|
||||
for(var i = begin; i >= 0; i--)
|
||||
{
|
||||
var selectedValue = $('#tableBody tbody > tr').eq(i).find('select[name^="story"]').val();
|
||||
var selectedTitle = $('#tableBody tbody > tr').eq(i).find('select[name^="story"]').find('option:selected').text();
|
||||
if(selectedValue !== 'ditto')
|
||||
{
|
||||
storyTitle = selectedTitle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var startPosition = storyTitle.indexOf(':') + 1;
|
||||
var endPosition = storyTitle.lastIndexOf('[');
|
||||
storyTitle = storyTitle.substr(startPosition, endPosition - startPosition);
|
||||
|
||||
$('#name\\[' + num + '\\]').val(storyTitle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set preview.
|
||||
*
|
||||
* @param int $num
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function setPreview(num)
|
||||
{
|
||||
var storyID = $('#story' + num).val();
|
||||
if(storyID != 0 && storyID != 'ditto')
|
||||
{
|
||||
storyLink = createLink('story', 'view', "storyID=" + storyID, '', true);
|
||||
$('#preview' + num).removeAttr('disabled');
|
||||
$('#preview' + num).modalTrigger({type:'iframe'});
|
||||
$('#preview' + num).css('pointer-events', 'auto');
|
||||
$('#preview' + num).attr('href', storyLink);
|
||||
}
|
||||
else
|
||||
{
|
||||
storyLink = '#';
|
||||
$('#preview' + num).attr('disabled', true);
|
||||
$('#preview' + num).css('pointer-events', 'none');
|
||||
$('#preview' + num).attr('href', storyLink);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark story task.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function markStoryTask()
|
||||
{
|
||||
$('select[name^="story"]').each(function()
|
||||
{
|
||||
var $select = $(this);
|
||||
$select.find('option').each(function()
|
||||
{
|
||||
var $option = $(this);
|
||||
var value = $option.attr('value');
|
||||
var tasksCount = storyTasks[value];
|
||||
$option.attr('data-data', value).toggleClass('has-task', !!(tasksCount && tasksCount !== '0'));
|
||||
});
|
||||
$select.trigger("chosen:updated");
|
||||
});
|
||||
|
||||
var getStoriesHasTask = function()
|
||||
{
|
||||
var storiesHasTask = {};
|
||||
$('#tableBody tbody>tr').each(function()
|
||||
{
|
||||
var $tr = $(this);
|
||||
if ($tr.find('input[name^="name"]').val())
|
||||
{
|
||||
storiesHasTask[$tr.find('select[name^="story"]').val()] = true;
|
||||
}
|
||||
});
|
||||
return storiesHasTask;
|
||||
};
|
||||
|
||||
$('#batchToTaskForm').on('chosen:showing_dropdown', 'select[name^="story"],.chosen-with-drop', function()
|
||||
{
|
||||
var storiesHasTask = getStoriesHasTask();
|
||||
var $container = $(this).closest('td').find('.chosen-container');
|
||||
setTimeout(function()
|
||||
{
|
||||
$container.find('.chosen-results>li').each(function()
|
||||
{
|
||||
var $li = $(this);
|
||||
$li.toggleClass('has-new-task', !!storiesHasTask[$li.data('data')]);
|
||||
});
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
$(document).on('chosen:showing_dropdown', 'select[name^="story"],.chosen-with-drop', function()
|
||||
{
|
||||
var select = $(this).closest('td').find('select');
|
||||
if($(select).val() == 'ditto')
|
||||
{
|
||||
var index = $(select).closest('td').index();
|
||||
var row = $(select).closest('tr').index();
|
||||
var table = $(select).closest('tr').parent();
|
||||
var value = '';
|
||||
for(i = row - 1; i >= 0; i--)
|
||||
{
|
||||
value = $(table).find('tr').eq(i).find('td').eq(index).find('select').val();
|
||||
if(value != 'ditto') break;
|
||||
}
|
||||
$(select).val(value);
|
||||
$(select).trigger("chosen:updated");
|
||||
$(select).trigger("change");
|
||||
}
|
||||
})
|
||||
|
||||
$(document).on('mousedown', 'select', function()
|
||||
{
|
||||
if($(this).val() == 'ditto')
|
||||
{
|
||||
var index = $(this).closest('td').index();
|
||||
var row = $(this).closest('tr').index();
|
||||
var table = $(this).closest('tr').parent();
|
||||
var value = '';
|
||||
for(i = row - 1; i >= 0; i--)
|
||||
{
|
||||
value = $(table).find('tr').eq(i).find('td').eq(index).find('select').val();
|
||||
if(value != 'ditto') break;
|
||||
}
|
||||
$(this).val(value);
|
||||
}
|
||||
})
|
||||
|
||||
$(function()
|
||||
{
|
||||
$('.chosen-container[id^=module]').width(chosenWidth);
|
||||
$('.chosen-container[id^=module]').css('max-width', chosenWidth);
|
||||
|
||||
var chosenWidth = $('#story1_chosen').width();
|
||||
$('.chosen-container[id^=story]').width(chosenWidth);
|
||||
$('.chosen-container[id^=story]').css('max-width', chosenWidth);
|
||||
|
||||
markStoryTask();
|
||||
|
||||
$(document).keydown(function(event)
|
||||
{
|
||||
if(event.ctrlKey && event.keyCode == 38)
|
||||
{
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
selectFocusJump('up');
|
||||
}
|
||||
else if(event.ctrlKey && event.keyCode == 40)
|
||||
{
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
selectFocusJump('down');
|
||||
}
|
||||
else if(event.keyCode == 38)
|
||||
{
|
||||
inputFocusJump('up');
|
||||
}
|
||||
else if(event.keyCode == 40)
|
||||
{
|
||||
inputFocusJump('down');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Add row.
|
||||
*
|
||||
* @param object $obj
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function addRow(obj)
|
||||
{
|
||||
var row = $('#addRow').html().replace(/%i%/g, rowIndex + 1);
|
||||
$('<tr class="addedRow">' + row + '</tr>').insertAfter($(obj).closest('tr'));
|
||||
|
||||
var $beginRow = $row = $(obj).closest('tr').next();
|
||||
|
||||
$row.find(".form-date").datepicker();
|
||||
$row.find("input[name^=color]").colorPicker();
|
||||
$row.find('div[id$=_chosen]').remove();
|
||||
$row.find('.picker').remove();
|
||||
$row.find('.chosen').chosen();
|
||||
|
||||
var begin = parseInt($(obj).parent().siblings('.c-id').text()) + 1;
|
||||
var count = $('#tableBody tbody > tr').length;
|
||||
for(var i = begin; i <= count; i++)
|
||||
{
|
||||
$beginRow.children('.c-id').text(i);
|
||||
$beginRow = $beginRow.next();
|
||||
}
|
||||
rowIndex ++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete row.
|
||||
*
|
||||
* @param object $obj
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function deleteRow(obj)
|
||||
{
|
||||
var $beginRow = $(obj).closest('tr').next();
|
||||
var begin = parseInt($(obj).parent().siblings('.c-id').text());
|
||||
var count = $('#tableBody tbody > tr').length;
|
||||
for(var i = begin; i <= count; i++)
|
||||
{
|
||||
$beginRow.children('.c-id').text(i);
|
||||
$beginRow = $beginRow.next();
|
||||
}
|
||||
|
||||
$(obj).closest('tr').remove();
|
||||
}
|
||||
@@ -84,9 +84,10 @@ $lang->story->reportAction = "Story Report";
|
||||
|
||||
$lang->story->skipStory = '%s is a parent story. It cannot be closed.';
|
||||
$lang->story->closedStory = 'Story %s is closed and will not be closed.';
|
||||
$lang->story->batchToTaskTips = "This action will create a task with the same name as the selected {$lang->SRCommon} and link {$lang->SRCommon} to the task. The closed {$lang->SRCommon} will not be converted into tasks.";
|
||||
$lang->story->batchToTaskTips = "The closed {$lang->SRCommon} will not be converted into tasks.";
|
||||
$lang->story->successToTask = "Converted to task.";
|
||||
$lang->story->storyRound = '%s time estimation';
|
||||
$lang->story->float = "『%s』should be positive number, decimals included.";
|
||||
|
||||
$lang->story->id = 'ID';
|
||||
$lang->story->parent = 'Parent';
|
||||
|
||||
@@ -84,9 +84,10 @@ $lang->story->reportAction = "Report";
|
||||
|
||||
$lang->story->skipStory = '%s is a parent story. It cannot be closed.';
|
||||
$lang->story->closedStory = 'Story %s is closed and will not be closed.';
|
||||
$lang->story->batchToTaskTips = "This action will create a task with the same name as the selected {$lang->SRCommon} and link {$lang->SRCommon} to the task. The closed {$lang->SRCommon} will not be converted into tasks.";
|
||||
$lang->story->batchToTaskTips = "The closed {$lang->SRCommon} will not be converted into tasks.";
|
||||
$lang->story->successToTask = "Converted to task.";
|
||||
$lang->story->storyRound = '%s time estimation';
|
||||
$lang->story->float = "『%s』should have positive number, or decimals.";
|
||||
|
||||
$lang->story->id = 'ID';
|
||||
$lang->story->parent = 'Parent';
|
||||
|
||||
@@ -84,9 +84,10 @@ $lang->story->reportAction = "Rapport de Story";
|
||||
|
||||
$lang->story->skipStory = '%s is a parent story. It cannot be closed.';
|
||||
$lang->story->closedStory = 'Story %s is closed and will not be closed.';
|
||||
$lang->story->batchToTaskTips = "This action will create a task with the same name as the selected {$lang->SRCommon} and link {$lang->SRCommon} to the task. The closed {$lang->SRCommon} will not be converted into tasks.";
|
||||
$lang->story->batchToTaskTips = "The closed {$lang->SRCommon} will not be converted into tasks.";
|
||||
$lang->story->successToTask = "Converted to task.";
|
||||
$lang->story->storyRound = '%s time estimation';
|
||||
$lang->story->float = "『 %s 』doit avoir des nombres positifs ou décimaux.";
|
||||
|
||||
$lang->story->id = 'ID';
|
||||
$lang->story->parent = 'Parent';
|
||||
|
||||
@@ -84,9 +84,10 @@ $lang->story->reportAction = "统计报表";
|
||||
|
||||
$lang->story->skipStory = '需求:%s 为父需求,将不会被关闭。';
|
||||
$lang->story->closedStory = '需求:%s 已关闭,将不会被关闭。';
|
||||
$lang->story->batchToTaskTips = "此操作会创建与所选{$lang->SRCommon}同名的任务,并将{$lang->SRCommon}关联到任务中,已关闭的需求不会转为任务。";
|
||||
$lang->story->batchToTaskTips = "已关闭的需求不会转为任务。";
|
||||
$lang->story->successToTask = '批量转任务成功';
|
||||
$lang->story->storyRound = '第 %s 轮估算';
|
||||
$lang->story->float = "『%s』应当是正数,可以是小数。";
|
||||
|
||||
$lang->story->id = '编号';
|
||||
$lang->story->parent = '父需求';
|
||||
|
||||
+138
-46
@@ -2020,72 +2020,159 @@ class storyModel extends model
|
||||
{
|
||||
/* load Module and get the data from the post and get the current time. */
|
||||
$this->loadModel('action');
|
||||
$data = fixer::input('post')->get();
|
||||
$now = helper::now();
|
||||
$this->loadModel('task');
|
||||
|
||||
/* Judgment of required items. */
|
||||
if(empty($data->type))
|
||||
{
|
||||
dao::$errors['type'] = sprintf($this->lang->error->notempty, $this->lang->task->type);
|
||||
}
|
||||
$now = helper::now();
|
||||
$account = $this->app->user->account;
|
||||
$tasks = fixer::input('post')
|
||||
->remove('syncFields')
|
||||
->get();
|
||||
|
||||
if(isset($data->hourPointValue) and empty($data->hourPointValue))
|
||||
{
|
||||
dao::$errors['hourPointValue'] = sprintf($this->lang->error->notempty, $this->lang->story->convertRelations);
|
||||
}
|
||||
elseif(isset($data->hourPointValue) and !is_numeric($data->hourPointValue))
|
||||
{
|
||||
dao::$errors['hourPointValue'] = sprintf($this->lang->error->float, $this->lang->story->convertRelations);
|
||||
}
|
||||
if(dao::isError()) return false;
|
||||
if(!empty($_POST['syncFields'])) $stories = empty($tasks->story) ? array() : $this->getByList($tasks->story);
|
||||
|
||||
/* Create tasks. */
|
||||
$tasks = array();
|
||||
$stories = empty($data->storyIdList) ? array() : $this->getByList($data->storyIdList);
|
||||
foreach($stories as $story)
|
||||
$preStory = 0;
|
||||
$storyIDs = array();
|
||||
$taskNames = array();
|
||||
foreach($tasks->story as $key => $storyID)
|
||||
{
|
||||
if(strpos('draft,closed', $story->status) !== false) continue;
|
||||
$tasks->name[$key] = trim($tasks->name[$key]);
|
||||
if(empty($tasks->name[$key])) continue;
|
||||
if($tasks->type[$key] == 'affair') continue;
|
||||
if($tasks->type[$key] == 'ditto' and isset($tasks->type[$key - 1]) and $tasks->type[$key - 1] == 'affair') continue;
|
||||
|
||||
$task = new stdclass();
|
||||
$task->execution = $executionID;
|
||||
$task->project = $projectID ? $projectID : 0;
|
||||
$task->name = $story->title;
|
||||
$task->story = $story->id;
|
||||
$task->type = $data->type;
|
||||
$task->estimate = isset($data->hourPointValue) ? ($story->estimate * $data->hourPointValue) : $story->estimate;
|
||||
$task->left = $task->estimate;
|
||||
$task->openedBy = $this->app->user->account;
|
||||
$task->openedDate = $now;
|
||||
$task->storyVersion = $story->version;
|
||||
if($storyID == 'ditto') $storyID = $preStory;
|
||||
$preStory = $storyID;
|
||||
|
||||
if(isset($data->fields))
|
||||
if(!isset($tasks->story[$key - 1]) and $key > 1 and !empty($tasks->name[$key - 1]))
|
||||
{
|
||||
foreach($data->fields as $field)
|
||||
{
|
||||
$task->$field = $story->$field;
|
||||
|
||||
if($field == 'assignedTo') $task->assignedDate = $now;
|
||||
if($field == 'spec')
|
||||
{
|
||||
unset($task->$field);
|
||||
$task->desc = $story->$field;
|
||||
}
|
||||
}
|
||||
$storyIDs[] = 0;
|
||||
$taskNames[] = $tasks->name[$key - 1];
|
||||
}
|
||||
|
||||
$inNames = in_array($tasks->name[$key], $taskNames);
|
||||
if(!$inNames or ($inNames && !in_array($storyID, $storyIDs)))
|
||||
{
|
||||
$storyIDs[] = $storyID;
|
||||
$taskNames[] = $tasks->name[$key];
|
||||
}
|
||||
else
|
||||
{
|
||||
dao::$errors['message'][] = sprintf($this->lang->duplicate, $this->lang->task->common) . ' ' . $tasks->name[$key];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$story = 0;
|
||||
$module = 0;
|
||||
$type = '';
|
||||
$assignedTo = '';
|
||||
$estStarted = '0000-00-00';
|
||||
$deadline = '0000-00-00';
|
||||
$data = array();
|
||||
$requiredFields = "," . $this->config->task->create->requiredFields . ",";
|
||||
foreach($tasks->name as $i => $task)
|
||||
{
|
||||
$module = (!isset($tasks->module[$i]) or $tasks->module[$i] == 'ditto') ? $module : $tasks->module[$i];
|
||||
$story = (!isset($tasks->story[$i]) or $tasks->story[$i] == 'ditto') ? $story : $tasks->story[$i];
|
||||
$type = (!isset($tasks->type[$i]) or $tasks->type[$i] == 'ditto') ? $type : $tasks->type[$i];
|
||||
$assignedTo = (!isset($tasks->assignedTo[$i]) or $tasks->assignedTo[$i] == 'ditto') ? $assignedTo : $tasks->assignedTo[$i];
|
||||
$estStarted = (!isset($tasks->estStarted[$i]) or isset($tasks->estStartedDitto[$i])) ? $estStarted : $tasks->estStarted[$i];
|
||||
$deadline = (!isset($tasks->deadline[$i]) or isset($tasks->deadlineDitto[$i])) ? $deadline : $tasks->deadline[$i];
|
||||
|
||||
if(empty($tasks->name[$i])) continue;
|
||||
|
||||
$data[$i] = new stdclass();
|
||||
$data[$i]->story = (int)$story;
|
||||
$data[$i]->type = $type;
|
||||
$data[$i]->module = (int)$module;
|
||||
$data[$i]->assignedTo = $assignedTo;
|
||||
$data[$i]->color = $tasks->color[$i];
|
||||
$data[$i]->name = $tasks->name[$i];
|
||||
$data[$i]->pri = $tasks->pri[$i];
|
||||
$data[$i]->estimate = $tasks->estimate[$i];
|
||||
$data[$i]->left = $tasks->estimate[$i];
|
||||
$data[$i]->project = $this->config->systemMode == 'new' ? $projectID : 0;
|
||||
$data[$i]->execution = $executionID;
|
||||
$data[$i]->estStarted = $estStarted;
|
||||
$data[$i]->deadline = $deadline;
|
||||
$data[$i]->status = 'wait';
|
||||
$data[$i]->openedBy = $account;
|
||||
$data[$i]->openedDate = $now;
|
||||
$data[$i]->vision = 'rnd';
|
||||
if($story)
|
||||
{
|
||||
$data[$i]->storyVersion = $stories[$story]->version;
|
||||
if(strpos(",{$_POST['syncFields']},", ',spec,') !== false) $data[$i]->desc = $stories[$story]->spec;
|
||||
if(strpos(",{$_POST['syncFields']},", 'mailto') !== false) $data[$i]->mailto = $stories[$story]->mailto;
|
||||
}
|
||||
|
||||
if($assignedTo) $data[$i]->assignedDate = $now;
|
||||
if(strpos($requiredFields, ',estStarted,') !== false and empty($estStarted)) $data[$i]->estStarted = '';
|
||||
if(strpos($requiredFields, ',deadline,') !== false and empty($deadline)) $data[$i]->deadline = '';
|
||||
}
|
||||
|
||||
/* check data. */
|
||||
foreach($data as $i => $task)
|
||||
{
|
||||
if(!helper::isZeroDate($task->deadline) and $task->deadline < $task->estStarted)
|
||||
{
|
||||
dao::$errors['message'][] = $this->lang->task->error->deadlineSmall;
|
||||
return false;
|
||||
}
|
||||
|
||||
if($task->estimate and !preg_match("/^[0-9]+(.[0-9]{1,3})?$/", $task->estimate))
|
||||
{
|
||||
dao::$errors['message'][] = $this->lang->task->error->estimateNumber;
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach(explode(',', $requiredFields) as $field)
|
||||
{
|
||||
$field = trim($field);
|
||||
if(empty($field)) continue;
|
||||
|
||||
if(!isset($task->$field)) continue;
|
||||
if(!empty($task->$field)) continue;
|
||||
if($field == 'estimate' and strlen(trim($task->estimate)) != 0) continue;
|
||||
|
||||
dao::$errors['message'][] = sprintf($this->lang->error->notempty, $this->lang->task->$field);
|
||||
return false;
|
||||
}
|
||||
if($task->estimate) $task->estimate = (float)$task->estimate;
|
||||
}
|
||||
|
||||
$taskIdList = array();
|
||||
foreach($data as $i => $task)
|
||||
{
|
||||
$task->version = 1;
|
||||
$this->dao->insert(TABLE_TASK)->data($task)
|
||||
->autoCheck()
|
||||
->checkIF($task->estimate != '', 'estimate', 'float')
|
||||
->exec();
|
||||
|
||||
if(dao::isError()) return false;
|
||||
$taskID = $this->dao->lastInsertID();
|
||||
$tasks[] = $taskID;
|
||||
|
||||
$taskID = $this->dao->lastInsertID();
|
||||
$taskIdList[] = $taskID;
|
||||
|
||||
$taskSpec = new stdClass();
|
||||
$taskSpec->task = $taskID;
|
||||
$taskSpec->version = $task->version;
|
||||
$taskSpec->name = $task->name;
|
||||
$taskSpec->estStarted = $task->estStarted;
|
||||
$taskSpec->deadline = $task->deadline;
|
||||
|
||||
$this->dao->insert(TABLE_TASKSPEC)->data($taskSpec)->autoCheck()->exec();
|
||||
if(dao::isError()) return false;
|
||||
|
||||
if($task->story) $this->setStage($task->story);
|
||||
|
||||
$this->action->create('task', $taskID, 'Opened', '');
|
||||
}
|
||||
|
||||
$this->loadModel('kanban')->updateLane($executionID, 'task');
|
||||
return $tasks;
|
||||
return $taskIdList;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4422,6 +4509,11 @@ class storyModel extends model
|
||||
{
|
||||
$title = $story->feedbackBy;
|
||||
}
|
||||
elseif($id =='version')
|
||||
{
|
||||
$title = $story->version;
|
||||
$class = 'text-center';
|
||||
}
|
||||
elseif($id == 'notifyEmail')
|
||||
{
|
||||
$title = $story->notifyEmail;
|
||||
|
||||
Executable
+202
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
/**
|
||||
* The batch to task view of story module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
|
||||
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author Shujie Tian <tianshujie@easycorp.ltd>
|
||||
* @package story
|
||||
* @version $Id$
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php include '../../common/view/datepicker.html.php';?>
|
||||
<?php js::set('ditto', $lang->task->ditto);?>
|
||||
<?php js::set('storyTasks', $storyTasks);?>
|
||||
<?php js::set('storyType', 'story');?>
|
||||
<?php js::set('storyCount', count($stories));?>
|
||||
<?php
|
||||
$requiredFields = array();
|
||||
foreach(explode(',', $config->task->create->requiredFields) as $field)
|
||||
{
|
||||
if($field) $requiredFields[$field] = '';
|
||||
}
|
||||
?>
|
||||
<div id="mainContent" class="main-content fade">
|
||||
<div class="main-header clearfix">
|
||||
<h2 class="pull-left"><?php echo $lang->story->batchToTask;?></h2>
|
||||
</div>
|
||||
<form method='post' class='batch-actions-form' target='hiddenwin' enctype='multipart/form-data' id="batchToTaskForm">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-form" id="tableBody">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='c-id'><?php echo $lang->idAB;?></th>
|
||||
<th class='c-module<?php echo zget($requiredFields, 'module', '', ' required');?>'><?php echo $lang->task->module?></th>
|
||||
<th class='c-story<?php echo zget($requiredFields, 'story', '', ' required');?>'><?php echo $lang->task->story;?></th>
|
||||
<th class='c-name required has-btn'><?php echo $lang->task->name;?></span></th>
|
||||
<th class='c-type required'><?php echo $lang->typeAB;?></span></th>
|
||||
<th class='c-assigned<?php echo zget($requiredFields, 'assignedTo', '', ' required');?>'><?php echo $lang->task->assignedTo;?></th>
|
||||
<th class='c-estimate<?php echo zget($requiredFields, 'estimate', '', ' required');?>'><?php echo $lang->task->estimateAB;?></th>
|
||||
<th class='c-date<?php echo zget($requiredFields, 'estStarted', '', ' required');?>'><?php echo $lang->task->estStarted;?></th>
|
||||
<th class='c-date<?php echo zget($requiredFields, 'deadline', '', ' required');?>'><?php echo $lang->task->deadline;?></th>
|
||||
<th class='c-pri<?php echo zget($requiredFields, 'pri', '', ' required');?>'><?php echo $lang->task->pri;?></th>
|
||||
<th class='c-actions'><?php echo $lang->actions;?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php $i = 1;?>
|
||||
<?php foreach($stories as $storyID => $story):?>
|
||||
<?php
|
||||
if(strpos('draft,closed', $story->status) !== false) continue;
|
||||
|
||||
$currentStory = $storyID;
|
||||
$pri = 3;
|
||||
$storyPairs = zget($storyGroup, $story->module, array());
|
||||
$estimate = $hourPointValue ? $story->estimate * $hourPointValue : $story->estimate;
|
||||
if($i == 1)
|
||||
{
|
||||
$moduleID = 0;
|
||||
$type = $assignedTo = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$type = $assignedTo = $moduleID = 'ditto';
|
||||
$storyPairs['ditto'] = $lang->task->ditto;
|
||||
$members['ditto'] = $lang->task->ditto;
|
||||
$modules['ditto'] = $lang->task->ditto;
|
||||
$lang->task->typeList['ditto'] = $lang->task->ditto;
|
||||
}
|
||||
|
||||
if(in_array('module', $syncFields)) $moduleID = $story->module;
|
||||
if(in_array('pri', $syncFields)) $pri = $story->pri;
|
||||
if(in_array('assignedTo', $syncFields)) $assignedTo = $story->assignedTo ? $story->assignedTo : $assignedTo;
|
||||
?>
|
||||
<tr>
|
||||
<td class='text-left c-id'><?php echo $i;?></td>
|
||||
<td style='overflow:visible'>
|
||||
<?php echo html::select("module[$i]", $modules, $moduleID, "class='form-control chosen' onchange='setStories(this.value, $executionID, $i)'")?>
|
||||
</td>
|
||||
<td style='overflow: visible'>
|
||||
<div class='input-group'>
|
||||
<?php echo html::select("story[$i]", $storyPairs, $currentStory, "class='form-control chosen' onchange='setStoryRelated($i)'");?>
|
||||
<span class='input-group-btn'>
|
||||
<a id='preview<?php echo $i;?>' href="<?php echo $this->createLink('story', 'view', "storyID=$currentStory", '', true)?>" class='btn iframe btn-link btn-icon btn-copy' data-width='80%' title='<?php echo $lang->preview;?>'><i class='icon-eye'></i></a>
|
||||
<a href='javascript:copyStoryTitle(<?php echo $i;?>)' class='btn btn-link btn-icon btn-copy' title='<?php echo $lang->task->copyStoryTitle; ?>'><i class='icon-arrow-right'></i></a>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td style='overflow:visible'>
|
||||
<div class="input-control has-icon-right">
|
||||
<?php echo html::input("name[$i]", $story->title, "class='form-control title-import'");?>
|
||||
<div class="colorpicker">
|
||||
<button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown"><span class="cp-title"></span><span class="color-bar"></span><i class="ic"></i></button>
|
||||
<ul class="dropdown-menu clearfix pull-right">
|
||||
<li class="heading"><?php echo $lang->task->colorTag;?><i class="icon icon-close"></i></li>
|
||||
</ul>
|
||||
<?php echo html::hidden("color[$i]", '', "data-provide='colorpicker' data-icon='color' data-wrapper='input-control-icon-right' data-update-color='#name\\[$i\\]'");?>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td><?php echo html::select("type[$i]", $lang->task->typeList, $taskType, 'class=form-control');?></td>
|
||||
<td style='overflow:visible'><?php echo html::select("assignedTo[$i]", $members, $assignedTo, "class='form-control chosen'");?></td>
|
||||
<td><?php echo html::input("estimate[$i]", $estimate, "class='form-control text-center'");?></td>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<?php
|
||||
echo html::input("estStarted[$i]", '', "class='form-control text-center form-date' onkeyup='toggleCheck(this)'");
|
||||
if($i != 1) echo "<span class='input-group-addon estStartedBox'><input type='checkbox' name='estStartedDitto[$i]' id='estStartedDitto$i' " . ($i > 1 ? "checked" : '') . " /> {$lang->task->ditto}</span>";
|
||||
?>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<?php
|
||||
echo html::input("deadline[$i]", '', "class='form-control text-center form-date' onkeyup='toggleCheck(this)'");
|
||||
if($i != 1) echo "<span class='input-group-addon deadlineBox'><input type='checkbox' name='deadlineDitto[$i]' id='deadlineDitto$i' " . ($i > 1 ? "checked" : '') . " /> {$lang->task->ditto}</span>";
|
||||
?>
|
||||
</div>
|
||||
</td>
|
||||
<td><?php echo html::select("pri[$i]", (array)$lang->task->priList, $pri, 'class=form-control');?></td>
|
||||
<td class='c-actions text-left'>
|
||||
<a href='javascript:;' onclick='addRow(this)' class='btn btn-link'><i class='icon-plus'></i></a>
|
||||
<?php if($i > 1):?>
|
||||
<a href='javascript:;' onclick='deleteRow(this)' class='btn btn-link'><i class='icon icon-close'></i></a>
|
||||
<?php endif;?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php $i ++;?>
|
||||
<?php endforeach;?>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan='11' class='text-center form-actions'>
|
||||
<?php echo html::hidden('syncFields', implode(',', $syncFields));?>
|
||||
<?php echo html::submitButton();?>
|
||||
<?php echo html::backButton();?>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<?php js::set('rowIndex', -- $i);?>
|
||||
<div>
|
||||
<?php $i = '%i%';?>
|
||||
<table class='hidden'>
|
||||
<tr id='addRow' class='hidden'>
|
||||
<td class='text-left c-id'><?php echo $i;?></td>
|
||||
<td style='overflow:visible'>
|
||||
<?php echo html::select("module[$i]", $modules, 'ditto', "class='form-control chosen' onchange='setStories(this.value, $executionID, $i)'")?>
|
||||
</td>
|
||||
<td style='overflow: visible'>
|
||||
<div class='input-group'>
|
||||
<?php echo html::select("story[$i]", $storyPairs, 'ditto', "class='form-control chosen' onchange='setStoryRelated($i)'");?>
|
||||
<span class='input-group-btn'>
|
||||
<a id='preview<?php echo $i;?>' href='#' class='btn iframe btn-link btn-icon btn-copy' style='pointer-events:none' data-width='80%' disabled='disabled' title='<?php echo $lang->preview; ?>'><i class='icon-eye'></i></a>
|
||||
<a href='javascript:copyStoryTitle(<?php echo $i;?>)' class='btn btn-link btn-icon btn-copy' title='<?php echo $lang->task->copyStoryTitle; ?>'><i class='icon-arrow-right'></i></a>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td style='overflow:visible'>
|
||||
<div class="input-control has-icon-right">
|
||||
<?php echo html::input("name[$i]", '', "class='form-control title-import'");?>
|
||||
<div class="colorpicker">
|
||||
<button type="button" class="btn btn-link dropdown-toggle" data-toggle="dropdown"><span class="cp-title"></span><span class="color-bar"></span><i class="ic"></i></button>
|
||||
<ul class="dropdown-menu clearfix pull-right">
|
||||
<li class="heading"><?php echo $lang->task->colorTag;?><i class="icon icon-close"></i></li>
|
||||
</ul>
|
||||
<?php echo html::hidden("color[$i]", '', "data-provide='colorpicker' data-icon='color' data-wrapper='input-control-icon-right' data-update-color='#name\\[$i\\]'");?>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td><?php echo html::select("type[$i]", $lang->task->typeList, 'ditto', 'class=form-control');?></td>
|
||||
<td style='overflow:visible'><?php echo html::select("assignedTo[$i]", $members, 'ditto', "class='form-control chosen'");?></td>
|
||||
<td><?php echo html::input("estimate[$i]", '', "class='form-control text-center'");?></td>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<?php
|
||||
echo html::input("estStarted[$i]", '', "class='form-control text-center form-date' onkeyup='toggleCheck(this)'");
|
||||
echo "<span class='input-group-addon estStartedBox'><input type='checkbox' name='estStartedDitto[$i]' id='estStartedDitto$i' checked/> {$lang->task->ditto}</span>";
|
||||
?>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<?php
|
||||
echo html::input("deadline[$i]", '', "class='form-control text-center form-date' onkeyup='toggleCheck(this)'");
|
||||
echo "<span class='input-group-addon deadlineBox'><input type='checkbox' name='deadlineDitto[$i]' id='deadlineDitto$i' checked/> {$lang->task->ditto}</span>";
|
||||
?>
|
||||
</div>
|
||||
</td>
|
||||
<td><?php echo html::select("pri[$i]", (array)$lang->task->priList, $pri, 'class=form-control');?></td>
|
||||
<td class='c-actions text-left'>
|
||||
<a href='javascript:;' onclick='addRow(this)' class='btn btn-link'><i class='icon-plus'></i></a>
|
||||
<a href='javascript:;' onclick='deleteRow(this)' class='btn btn-link'><i class='icon icon-close'></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<?php include '../../common/view/footer.html.php';?>
|
||||
@@ -128,7 +128,8 @@ function setStoryRelated(num)
|
||||
*/
|
||||
function setPreview(num)
|
||||
{
|
||||
var storyID = $('#story' + num).val();
|
||||
var storyID = $('#story' + num).val();
|
||||
var storyLink = '#';
|
||||
if(storyID != 0 && storyID != 'ditto')
|
||||
{
|
||||
var link = createLink('story', 'ajaxGetInfo', 'storyID=' + storyID);
|
||||
@@ -148,6 +149,7 @@ function setPreview(num)
|
||||
var concat = storyLink.indexOf('?') >= 0 ? '&' : '?';
|
||||
storyLink = storyLink + concat + 'onlybody=yes';
|
||||
}
|
||||
|
||||
$('#preview' + num).removeAttr('disabled');
|
||||
$('#preview' + num).modalTrigger({type:'iframe'});
|
||||
$('#preview' + num).css('pointer-events', 'auto');
|
||||
@@ -155,7 +157,6 @@ function setPreview(num)
|
||||
}
|
||||
else
|
||||
{
|
||||
storyLink = '#';
|
||||
$('#preview' + num).attr('disabled', true);
|
||||
$('#preview' + num).css('pointer-events', 'none');
|
||||
$('#preview' + num).attr('href', storyLink);
|
||||
|
||||
@@ -3804,7 +3804,7 @@ class taskModel extends model
|
||||
$list = "<tr $trAttrs class='$trClass $showmore'>";
|
||||
$list .= '<td>';
|
||||
if($task->parent > 0) $list .= '<span class="label label-badge label-light" title="' . $this->lang->task->children . '">' . $this->lang->task->childrenAB . '</span> ';
|
||||
$list .= html::a(helper::createLink('task', 'view', "id=$task->id"), $task->name, '', "data-app='project'");
|
||||
$list .= common::hasPriv('task', 'view') ? html::a(helper::createLink('task', 'view', "id=$task->id"), $task->name, '', "style='color: $task->color'", "data-app='project'") : "<span style='color:$task->color'>$task->name</span>";
|
||||
$list .= '</td>';
|
||||
$list .= '<td>' . zget($users, $task->assignedTo, '') . '</td>';
|
||||
$list .= "<td class='status-{$task->status}'>" . $this->processStatus('task', $task) . '</td>';
|
||||
|
||||
@@ -118,7 +118,7 @@ $colspan = count($visibleFields) + 3;
|
||||
<tr>
|
||||
<td class='text-left c-id'><?php echo $i;?></td>
|
||||
<td class="<?php echo zget($visibleFields, 'module', 'hidden')?> moduleBox" style='overflow:visible'>
|
||||
<?php echo html::select("module[$i]", $modules, $moduleID, "class='form-control chosen' onchange='setStories(this.value, $execution->id)'")?>
|
||||
<?php echo html::select("module[$i]", $modules, $moduleID, "class='form-control chosen' onchange='setStories(this.value, $execution->id, $i)'")?>
|
||||
<?php echo html::hidden("parent[$i]", $parent);?>
|
||||
</td>
|
||||
<?php if($execution->lifetime != 'ops' and $execution->attribute != 'request' and $execution->attribute != 'review'):?>
|
||||
|
||||
@@ -1068,15 +1068,14 @@ class user extends control
|
||||
|
||||
if($_POST)
|
||||
{
|
||||
if($needCreateFile) return print(js::reload('parent'));
|
||||
if($needCreateFile) return $this->send(array('result' => 'success', 'locate' => 'reload'));
|
||||
|
||||
$result = $this->user->resetPassword();
|
||||
if(dao::isError()) return print(js::error(dao::getError()));
|
||||
if(!$result) return print(js::alert($this->lang->user->resetFail));
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
if(!$result) return $this->send(array('result' => 'fail', 'message' => $this->lang->user->resetFail));
|
||||
|
||||
echo js::alert($this->lang->user->resetSuccess);
|
||||
$referer = helper::safe64Encode($this->createLink('index', 'index'));
|
||||
return print(js::locate(inlink('logout', 'referer=' . $referer), 'parent'));
|
||||
return $this->send(array('result' => 'success', 'message' => $this->lang->user->resetSuccess, 'locate' => $this->createLink('user', 'logout', 'referer=' . $referer)));
|
||||
}
|
||||
|
||||
/* Remove the real path for security reason. */
|
||||
@@ -1174,6 +1173,7 @@ class user extends control
|
||||
$this->view->title = $this->lang->user->resetPWD;
|
||||
$this->view->expired = $expired;
|
||||
$this->view->user = empty($user) ? '' : $user;
|
||||
$this->view->rand = $this->user->updateSessionRandom();
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
@@ -3,3 +3,5 @@
|
||||
.w-enVerifyPassword {width: 150px !important;}
|
||||
.c-id {width: 70px;}
|
||||
.c-hours {width: 110px;}
|
||||
|
||||
#mainContent table > tbody > tr > td > div.text-danger.help-text {word-break: break-all;}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
.alert-info > h5 > span {color: red;}
|
||||
.btn-back {margin-left: 25px;}
|
||||
.table tbody > tr > td div.text-danger.help-text {word-break: break-all;}
|
||||
|
||||
@@ -13,3 +13,4 @@ body {background: #1183fb linear-gradient(-90deg, #0a48d1 0%, #1183fb 100%); bac
|
||||
#resetPanel .form-group .input-group.required:after {top: 6px;}
|
||||
#resetPanel .form-actions > .btn-wide {min-width: 45%;}
|
||||
#resetPanel .form-actions > a.btn-wide {margin-right: 0px;}
|
||||
#resetForm .form-group div.text-danger.help-text {word-break: break-all;}
|
||||
|
||||
@@ -92,11 +92,12 @@ $(function()
|
||||
$('#password2').change(function(){password2Encrypted = false});
|
||||
$('#submit').click(function()
|
||||
{
|
||||
if(!password1Encrypted && !password2Encrypted)
|
||||
if(!password1Encrypted || !password2Encrypted)
|
||||
{
|
||||
var password1 = $('#password1').val();
|
||||
var password2 = $('#password2').val();
|
||||
var passwordStrength = computePasswordStrength(password1);
|
||||
if(!password1Encrypted) $("#passwordLength").val(password1.length);
|
||||
|
||||
if($("form input[name=passwordStrength]").length == 0) $('#submit').after("<input type='hidden' name='passwordStrength' value='0' />");
|
||||
$("form input[name=passwordStrength]").val(passwordStrength);
|
||||
|
||||
@@ -6,11 +6,12 @@ $(function()
|
||||
$('#password2').change(function(){password2Encrypted = false});
|
||||
$('#submit').click(function()
|
||||
{
|
||||
if(!password1Encrypted && !password2Encrypted)
|
||||
if(!password1Encrypted || !password2Encrypted)
|
||||
{
|
||||
var password1 = $('#password1').val().trim();
|
||||
var password2 = $('#password2').val().trim();
|
||||
var passwordStrength = computePasswordStrength(password1);
|
||||
if(!password1Encrypted) $("#passwordLength").val(password1.length);
|
||||
|
||||
if($("form input[name=passwordStrength]").length == 0) $('#submit').after("<input type='hidden' name='passwordStrength' value='0' />");
|
||||
$("form input[name=passwordStrength]").val(passwordStrength);
|
||||
|
||||
+21
-4
@@ -1,10 +1,27 @@
|
||||
$(document).ready(function()
|
||||
{
|
||||
var password1Encrypted = false
|
||||
var password2Encrypted = false
|
||||
$('#password1').change(function(){password1Encrypted = false});
|
||||
$('#password2').change(function(){password2Encrypted = false});
|
||||
$('form #submit').click(function()
|
||||
{
|
||||
var password = $('#password1').val().trim();
|
||||
var passwordStrength = computePasswordStrength(password);
|
||||
if(!password1Encrypted || !password2Encrypted)
|
||||
{
|
||||
var password1 = $('#password1').val().trim();
|
||||
var password2 = $('#password2').val().trim();
|
||||
var passwordStrength = computePasswordStrength(password1);
|
||||
|
||||
$('form').prepend("<input type='hidden' name='passwordStrength' value=" + passwordStrength + "/>");
|
||||
});
|
||||
if($("form input[name=passwordStrength]").length == 0) $('#submit').after("<input type='hidden' name='passwordStrength' value='0' />");
|
||||
$("form input[name=passwordStrength]").val(passwordStrength);
|
||||
|
||||
var rand = $('input#verifyRand').val();
|
||||
if(password1 && !password1Encrypted) $('#password1').val(md5(password1) + rand);
|
||||
if(password2 && !password2Encrypted) $('#password2').val(md5(password2) + rand);
|
||||
password1Encrypted = true;
|
||||
password2Encrypted = true;
|
||||
$('form').prepend("<input type='hidden' name='passwordStrength' value='" + passwordStrength + "'>");
|
||||
$('form').prepend("<input type='hidden' name='passwordLength' value='" + password1.length + "'>");
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
@@ -10,13 +10,27 @@ $(function()
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
$('#password1').attr('id', 'password');
|
||||
|
||||
var password1Encrypted = false
|
||||
var password2Encrypted = false
|
||||
$('#password1').change(function(){password1Encrypted = false});
|
||||
$('#password2').change(function(){password2Encrypted = false});
|
||||
$('#submit').click(function()
|
||||
{
|
||||
var password1 = $('#password').val();
|
||||
var passwordStrength = computePasswordStrength(password1);
|
||||
if(!password1Encrypted || !password2Encrypted)
|
||||
{
|
||||
var password1 = $('#password1').val().trim();
|
||||
var password2 = $('#password2').val().trim();
|
||||
var passwordStrength = computePasswordStrength(password1);
|
||||
if(!password1Encrypted) $("#passwordLength").val(password1.length);
|
||||
|
||||
$("form input[id=passwordStrength]").val(passwordStrength);
|
||||
if($("form input[name=passwordStrength]").length == 0) $('#submit').after("<input type='hidden' name='passwordStrength' value='0' />");
|
||||
$("form input[name=passwordStrength]").val(passwordStrength);
|
||||
|
||||
var rand = $('input#verifyRand').val();
|
||||
if(password1 && !password1Encrypted) $('#password1').val(md5(password1) + rand);
|
||||
if(password2 && !password2Encrypted) $('#password2').val(md5(password2) + rand);
|
||||
password1Encrypted = true;
|
||||
password2Encrypted = true;
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -224,9 +224,14 @@ $lang->user->placeholder->loginAccount = 'Enter your account';
|
||||
$lang->user->placeholder->loginUrl = 'Enter your ZenTao address';
|
||||
$lang->user->placeholder->email = 'Enter your email';
|
||||
|
||||
$lang->user->placeholder->passwordStrength[0] = '≥6 letters.';
|
||||
$lang->user->placeholder->passwordStrength[1] = 'Buchstaben und Ziffern. Mindestens 6 Zeichen';
|
||||
$lang->user->placeholder->passwordStrength[2] = 'Buchstaben, Ziffern und Sonderzeichen. Mindestens 10 Zeichen';
|
||||
|
||||
$lang->user->placeholder->passwordStrengthCheck[0] = 'The password should be ≥ 6 letters.';
|
||||
$lang->user->placeholder->passwordStrengthCheck[1] = 'The password should be ≥ 6 letters, combination of uppercase, lowercase letters and numbers.';
|
||||
$lang->user->placeholder->passwordStrengthCheck[2] = 'The password should be ≥ 10 letters, combination of uppercase, lowercase letters, numbers, and special symbols.';
|
||||
|
||||
$lang->user->error = new stdclass();
|
||||
$lang->user->error->account = "ID %s,Konto muss Buchstaben, Unterstriche oder Ziffern enthalten. Mindestens 3 Zeichen.";
|
||||
$lang->user->error->accountDupl = "ID %s,Konto wurde genutzt.";
|
||||
|
||||
@@ -224,9 +224,14 @@ $lang->user->placeholder->loginAccount = 'Enter your account';
|
||||
$lang->user->placeholder->loginUrl = 'Enter your ZenTao address';
|
||||
$lang->user->placeholder->email = 'Enter your email';
|
||||
|
||||
$lang->user->placeholder->passwordStrength[0] = '≥6 letters.';
|
||||
$lang->user->placeholder->passwordStrength[1] = '>= 6 letters and numbers';
|
||||
$lang->user->placeholder->passwordStrength[2] = '>= 10 letters, numbers and special characters';
|
||||
|
||||
$lang->user->placeholder->passwordStrengthCheck[0] = 'The password should be ≥ 6 letters.';
|
||||
$lang->user->placeholder->passwordStrengthCheck[1] = 'The password should be ≥ 6 letters, combination of uppercase, lowercase letters and numbers.';
|
||||
$lang->user->placeholder->passwordStrengthCheck[2] = 'The password should be ≥ 10 letters, combination of uppercase, lowercase letters, numbers, and special symbols.';
|
||||
|
||||
$lang->user->error = new stdclass();
|
||||
$lang->user->error->account = "ID %s,account must be >= 3 letters, underline or numbers";
|
||||
$lang->user->error->accountDupl = "ID %s,account is used.";
|
||||
|
||||
@@ -224,9 +224,14 @@ $lang->user->placeholder->loginAccount = 'Enter your account';
|
||||
$lang->user->placeholder->loginUrl = 'Enter your ZenTao address';
|
||||
$lang->user->placeholder->email = 'Enter your email';
|
||||
|
||||
$lang->user->placeholder->passwordStrength[0] = 'Le mot de passe doit ≥ 6 caractè res.';
|
||||
$lang->user->placeholder->passwordStrength[1] = '>= 6 lettres et chiffres';
|
||||
$lang->user->placeholder->passwordStrength[2] = '>= 10 lettres, chiffres et caractères spéciaux';
|
||||
|
||||
$lang->user->placeholder->passwordStrengthCheck[0] = 'Le mot de passe doit ≥ 6 caractères.';
|
||||
$lang->user->placeholder->passwordStrengthCheck[1] = 'Le mot de passe doit ≥ 6 caractères, combinaison de lettres majuscules, minuscules et de chiffres.';
|
||||
$lang->user->placeholder->passwordStrengthCheck[2] = 'Le mot de passe doit ≥ 10 caractères, combinaison de lettres majuscules, minuscules, de chiffres et de symboles spéciaux.';
|
||||
|
||||
$lang->user->error = new stdclass();
|
||||
$lang->user->error->account = "ID %s,compte doit être >= 3 lettres, souligné ou chiffres";
|
||||
$lang->user->error->accountDupl = "ID %s,compte déjà utilisé par quelqu'un d'autre.";
|
||||
|
||||
@@ -224,8 +224,13 @@ $lang->user->placeholder->loginAccount = '请输入用户名';
|
||||
$lang->user->placeholder->loginUrl = '请输入禅道系统网址';
|
||||
$lang->user->placeholder->email = '请输入邮箱';
|
||||
|
||||
$lang->user->placeholder->passwordStrength[1] = '6位以上,包含大小写字母,数字。';
|
||||
$lang->user->placeholder->passwordStrength[2] = '10位以上,包含大小写字母,数字,特殊字符。';
|
||||
$lang->user->placeholder->passwordStrength[0] = '密码必须6位及以上。';
|
||||
$lang->user->placeholder->passwordStrength[1] = '6位及以上,包含大小写字母,数字。';
|
||||
$lang->user->placeholder->passwordStrength[2] = '10位及以上,包含大小写字母,数字,特殊字符。';
|
||||
|
||||
$lang->user->placeholder->passwordStrengthCheck[0] = '密码须6位及以上。';
|
||||
$lang->user->placeholder->passwordStrengthCheck[1] = '密码必须6位及以上,且包含大小写字母、数字。';
|
||||
$lang->user->placeholder->passwordStrengthCheck[2] = '密码必须10位及以上,且包含大小写字母、数字、特殊符号。';
|
||||
|
||||
$lang->user->error = new stdclass();
|
||||
$lang->user->error->account = "【ID %s】的用户名应该为:三位以上的英文、数字或下划线的组合";
|
||||
|
||||
+27
-19
@@ -320,7 +320,7 @@ class userModel extends model
|
||||
->setIF($this->post->password1 == false, 'password', '')
|
||||
->setIF($this->post->email != false, 'email', trim($this->post->email))
|
||||
->join('visions', ',')
|
||||
->remove('new, group, password1, password2, verifyPassword, passwordStrength')
|
||||
->remove('new, group, password1, password2, verifyPassword, passwordStrength,passwordLength')
|
||||
->get();
|
||||
|
||||
if(empty($_POST['verifyPassword']) or $this->post->verifyPassword != md5($this->app->user->password . $this->session->rand))
|
||||
@@ -544,7 +544,7 @@ class userModel extends model
|
||||
->setIF($this->post->password1 != false, 'password', substr($this->post->password1, 0, 32))
|
||||
->setIF($this->post->email != false, 'email', trim($this->post->email))
|
||||
->join('visions', ',')
|
||||
->remove('new, password1, password2, groups,verifyPassword, passwordStrength')
|
||||
->remove('new, password1, password2, groups,verifyPassword, passwordStrength,passwordLength')
|
||||
->get();
|
||||
|
||||
if(empty($_POST['verifyPassword']) or $this->post->verifyPassword != md5($this->app->user->password . $this->session->rand))
|
||||
@@ -786,7 +786,7 @@ class userModel extends model
|
||||
|
||||
$user = fixer::input('post')
|
||||
->setIF($this->post->password1 != false, 'password', substr($this->post->password1, 0, 32))
|
||||
->remove('account, password1, password2, originalPassword, passwordStrength')
|
||||
->remove('account, password1, password2, originalPassword, passwordStrength,passwordLength')
|
||||
->get();
|
||||
|
||||
if(empty($_POST['originalPassword']) or $this->post->originalPassword != md5($this->app->user->password . $this->session->rand))
|
||||
@@ -800,6 +800,7 @@ class userModel extends model
|
||||
$this->app->user->modifyPassword = false;
|
||||
if(!dao::isError())
|
||||
{
|
||||
if(!empty($this->app->user->modifyPasswordReason)) $this->app->user->modifyPasswordReason = '';
|
||||
$this->loadModel('score')->create('user', 'changePassword', $this->computePasswordStrength($this->post->password1));
|
||||
}
|
||||
}
|
||||
@@ -818,7 +819,7 @@ class userModel extends model
|
||||
$user = $this->getById($this->post->account);
|
||||
if(!$user) return false;
|
||||
|
||||
$password = md5($this->post->password1);
|
||||
$password = substr($this->post->password1, 0, 32);
|
||||
$this->dao->update(TABLE_USER)->set('password')->eq($password)->autoCheck()->where('account')->eq($this->post->account)->exec();
|
||||
return !dao::isError();
|
||||
}
|
||||
@@ -833,17 +834,28 @@ class userModel extends model
|
||||
{
|
||||
$_POST['password1'] = trim($_POST['password1']);
|
||||
$_POST['password2'] = trim($_POST['password2']);
|
||||
if(!$canNoPassword and empty($_POST['password1'])) dao::$errors['password'][] = sprintf($this->lang->error->notempty, $this->lang->user->password);
|
||||
if(!$canNoPassword and empty($_POST['password1'])) dao::$errors['password1'][] = sprintf($this->lang->error->notempty, $this->lang->user->password) . '<br/>';
|
||||
if($this->post->password1 != false)
|
||||
{
|
||||
if($this->post->password1 != $this->post->password2) dao::$errors['password'][] = $this->lang->error->passwordsame;
|
||||
if(!validater::checkReg($this->post->password1, '|(.){6,}|')) dao::$errors['password'][] = $this->lang->error->passwordrule;
|
||||
if(isset($this->config->safe->mode) and ($this->post->passwordStrength < $this->config->safe->mode)) dao::$errors['password1'][] = zget($this->lang->user->placeholder->passwordStrengthCheck, $this->config->safe->mode, $this->lang->user->weakPassword) . '<br/>';
|
||||
|
||||
if(isset($_POST['passwordLength']) and $this->post->passwordLength < 6 and empty(dao::$errors['password1'])) dao::$errors['password1'][] = zget($this->lang->user->placeholder->passwordStrengthCheck, 0, $this->lang->user->weakPassword) . '<br/>';
|
||||
|
||||
if($this->post->password1 != $this->post->password2) dao::$errors['password1'][] = $this->lang->error->passwordsame . '<br/>';
|
||||
|
||||
if(isset($this->config->safe->mode) and ($this->post->passwordStrength < $this->config->safe->mode)) dao::$errors['password'] = zget($this->lang->user->placeholder->passwordStrength, $this->config->safe->mode, $this->lang->user->weakPassword);
|
||||
if(!empty($this->config->safe->changeWeak))
|
||||
{
|
||||
if(!isset($this->config->safe->weak)) $this->app->loadConfig('admin');
|
||||
if(strpos(",{$this->config->safe->weak},", ",{$this->post->password1},") !== false) dao::$errors['password1'][] = sprintf($this->lang->user->errorWeak, $this->config->safe->weak);
|
||||
|
||||
if(strpos(",{$this->config->safe->weak},", ",{$this->post->password1},") !== false) dao::$errors['password1'] = sprintf($this->lang->user->errorWeak, $this->config->safe->weak);
|
||||
|
||||
$weaks = array();
|
||||
foreach(explode(',', $this->config->safe->weak) as $weak)
|
||||
{
|
||||
$weak = md5(trim($weak));
|
||||
$weaks[$weak] = $weak;
|
||||
}
|
||||
if(isset($weaks[substr($this->post->password1, 0, 32)])) dao::$errors['password1'] = sprintf($this->lang->user->errorWeak, $this->config->safe->weak);
|
||||
}
|
||||
}
|
||||
return !dao::isError();
|
||||
@@ -1656,7 +1668,6 @@ class userModel extends model
|
||||
$strength = 0;
|
||||
$length = strlen($password);
|
||||
|
||||
$uniqueChars = '';
|
||||
$complexity = array();
|
||||
$chars = str_split($password);
|
||||
foreach($chars as $letter)
|
||||
@@ -1664,7 +1675,7 @@ class userModel extends model
|
||||
$asc = ord($letter);
|
||||
if($asc >= 48 && $asc <= 57)
|
||||
{
|
||||
$complexity[2] = 2;
|
||||
$complexity[0] = 1;
|
||||
}
|
||||
elseif($asc >= 65 && $asc <= 90)
|
||||
{
|
||||
@@ -1672,20 +1683,17 @@ class userModel extends model
|
||||
}
|
||||
elseif($asc >= 97 && $asc <= 122)
|
||||
{
|
||||
$complexity[0] = 1;
|
||||
$complexity[2] = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
$complexity[3] = 3;
|
||||
$complexity[3] = 8;
|
||||
}
|
||||
if(strpos($uniqueChars, $letter) === false) $uniqueChars .= $letter;
|
||||
}
|
||||
if(strlen($uniqueChars) > 4)$strength += strlen($uniqueChars) - 4;
|
||||
$strength += array_sum($complexity) + (2 * (count($complexity) - 1));
|
||||
if($length < 6 and $strength >= 10) $strength = 9;
|
||||
$sumComplexity = array_sum($complexity);
|
||||
|
||||
$strength = $strength > 29 ? 29 : $strength;
|
||||
$strength = floor($strength / 10);
|
||||
if(($sumComplexity == 7 or $sumComplexity == 15) and $length >= 6) $strength = 1;
|
||||
if($sumComplexity == 15 and $length >= 10) $strength = 2;
|
||||
|
||||
return $strength;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php include '../../common/view/datepicker.html.php';?>
|
||||
<?php js::import($jsRoot . 'md5.js');?>
|
||||
<?php if(!empty($config->safe->mode)) $lang->user->placeholder->password1 = $lang->user->placeholder->passwordStrength[$config->safe->mode]?>
|
||||
<?php $lang->user->placeholder->password1 = zget($lang->user->placeholder->passwordStrength, $config->safe->mode, '');?>
|
||||
<?php js::set('holders', $lang->user->placeholder);?>
|
||||
<?php js::set('roleGroup', $roleGroup);?>
|
||||
<?php
|
||||
@@ -110,6 +110,7 @@ $showVisionList = count($visionList) > 1;
|
||||
<th></th>
|
||||
<td class='text-center form-actions'>
|
||||
<?php if(!$showVisionList) echo html::hidden("visions[]", $this->config->vision);?>
|
||||
<?php echo html::hidden('passwordLength', 0);?>
|
||||
<?php echo html::submitButton();?>
|
||||
<?php echo html::a($this->createLink('company', 'browse'), $lang->goback, '', "class='btn btn-wide'")?>
|
||||
</td>
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
<td>
|
||||
<input type='password' style="display:none"> <!-- Disable input password by browser automatically. -->
|
||||
<span class='input-group'>
|
||||
<?php echo html::password('password1', '', "class='form-control disabled-ie-placeholder' onmouseup='checkPassword(this.value)' onkeyup='checkPassword(this.value)' placeholder='" . (!empty($config->safe->mode) ? $lang->user->placeholder->passwordStrength[$config->safe->mode] : '') . "'");?>
|
||||
<?php echo html::password('password1', '', "class='form-control disabled-ie-placeholder' onmouseup='checkPassword(this.value)' onkeyup='checkPassword(this.value)' placeholder='" . zget($lang->user->placeholder->passwordStrength, $config->safe->mode, '') . "'");?>
|
||||
<span class='input-group-addon' id='passwordStrength'></span>
|
||||
</span>
|
||||
</td>
|
||||
@@ -117,6 +117,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='2' class='text-center form-actions'>
|
||||
<?php echo html::hidden('passwordLength', 0);?>
|
||||
<?php echo html::submitButton();?>
|
||||
<?php echo html::backButton();?>
|
||||
</td>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
*/
|
||||
?>
|
||||
<?php include '../../common/view/header.lite.html.php';?>
|
||||
<?php js::import($jsRoot . 'md5.js');?>
|
||||
<?php if($needCreateFile):?>
|
||||
<div class='container mw-700px' style='margin-top:100px;'>
|
||||
<div class='panel panel-default'>
|
||||
@@ -34,7 +35,7 @@
|
||||
<div class='panel-heading'>
|
||||
<strong><?php echo $lang->user->resetPassword?></strong>
|
||||
</div>
|
||||
<form method='post' target='hiddenwin'>
|
||||
<form method='post' class='form-ajax'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th><?php echo $lang->user->account?></th>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
include '../../common/view/header.lite.html.php';
|
||||
?>
|
||||
<?php js::import($jsRoot . 'md5.js');?>
|
||||
<?php js::set('expired', $expired);?>
|
||||
<?php if($expired):?>
|
||||
<style>body {background: none;}</style>
|
||||
@@ -28,7 +29,7 @@ include '../../common/view/header.lite.html.php';
|
||||
<div class='form-group'>
|
||||
<label for='password1'><?php echo $lang->user->password;?></label>
|
||||
<span class='input-group'>
|
||||
<?php echo html::password('password1', '', "class='form-control' required placeholder='{$lang->user->placeholder->loginPassword}' onmouseup='checkPassword(this.value)' onkeyup='checkPassword(this.value)'");?>
|
||||
<?php echo html::password('password1', '', "class='form-control' required placeholder='" . zget($lang->user->placeholder->loginPassword, $config->safe->mode, '') . "' onmouseup='checkPassword(this.value)' onkeyup='checkPassword(this.value)'");?>
|
||||
<span class='input-group-addon' id='passwordStrength'></span>
|
||||
</span>
|
||||
</div>
|
||||
@@ -41,6 +42,7 @@ include '../../common/view/header.lite.html.php';
|
||||
<?php
|
||||
echo html::hidden('account', $user->account);
|
||||
echo html::hidden('passwordStrength', '');
|
||||
echo html::hidden('passwordLength', 0);
|
||||
echo html::submitButton($lang->user->submit);
|
||||
echo html::a(inlink('login'), $lang->goback, '', 'class="btn btn-wide"');
|
||||
?>
|
||||
@@ -49,6 +51,7 @@ include '../../common/view/header.lite.html.php';
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
<?php echo html::hidden('verifyRand', $rand);?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,7 +8,7 @@ INSERT INTO `zt_config` (`id`, `vision`, `owner`, `module`, `section`, `key`, `v
|
||||
(6, 'rnd', 'system', 'project', '', 'unitList', 'CNY,USD'),
|
||||
(7, 'rnd', 'system', 'project', '', 'defaultCurrency', 'CNY'),
|
||||
(8, 'rnd', 'system', 'story', '', 'reviewRules', 'allpass'),
|
||||
(10, 'rnd', 'system', 'common', 'global', 'version', '17.0.beta1'),
|
||||
(10, '', 'system', 'common', 'global', 'version', '17.4'),
|
||||
(11, 'rnd', 'system', 'common', 'global', 'sn', 'c8aa3269e181f2b9258ce96625de1497'),
|
||||
(12, 'rnd', 'system', 'common', 'global', 'flow', 'full'),
|
||||
(13, 'rnd', 'system', 'common', 'safe', 'mode', '1'),
|
||||
|
||||
@@ -81,6 +81,8 @@ class db
|
||||
$dbUsed = $this->getUsedDbList();
|
||||
$lastDB = 0;
|
||||
if(!empty($dbUsed)) $lastDB = max($dbUsed);
|
||||
|
||||
/* If all db is used. */
|
||||
if($lastDB == $this->config->test->dbNum)
|
||||
{
|
||||
shell_exec("> $this->dbLogFile");
|
||||
@@ -139,7 +141,7 @@ class db
|
||||
*/
|
||||
function initDB()
|
||||
{
|
||||
for($i = 1; $i < 11; $i++)
|
||||
for($i = 1; $i <= $this->config->test->dbNum; $i++)
|
||||
{
|
||||
$this->dao->query('DROP DATABASE ' . $this->config->test->dbPrefix . $i);
|
||||
$this->dao->query('CREATE DATABASE ' . $this->config->test->dbPrefix . $i);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/action.class.php';
|
||||
$db->switchDB();
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
@@ -34,4 +35,4 @@ r($action->createTest($objectTypeList[3], $objectIDList[0], $actionTypeList[3]))
|
||||
r($action->createTest($objectTypeList[4], $objectIDList[0], $actionTypeList[4], $comment)) && p('objectType,objectId,action,comment') && e('story,,comments,测试备注'); // 测试创建story 1 comment动态
|
||||
r($action->createTest($objectTypeList[4], $objectIDList[0], $actionTypeList[4])) && p() && e(''); // 测试创建story 1 comment动态 不填写备注
|
||||
r($action->createTest($objectTypeList[2], $objectIDList[0], $actionTypeList[5], '', '', $actor)) && p() && e('0'); // 测试创建游客 logout动态
|
||||
system("./ztest init");
|
||||
$db->restoreDB();
|
||||
@@ -10,10 +10,12 @@ title=测试 actionModel->getTrashes();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
查询type all id desc排序的回收站信息 >> testsuite,,这是测试套件名称87;story,,软件需求48
|
||||
查询type all id desc排序的回收站信息 >> story,,软件需求48;testsuite,,这是测试套件名称87
|
||||
查询type hidden id asc排序的回收站信息 >> testcase,,这个是测试用例9
|
||||
查询type hidden id asc排序的回收站信息 >> testcase,,这个是测试用例9
|
||||
查询objectType all type all id desc排序的回收站信息 >> testsuite,,这是测试套件名称87;story,,软件需求48
|
||||
查询objectType all type all id desc排序的回收站信息 >> story,,软件需求48;testsuite,,这是测试套件名称87
|
||||
查询objectType all type hidden id asc排序的回收站信息 >> testcase,,这个是测试用例9
|
||||
查询objectType all type hidden id asc排序的回收站信息 >> testcase,,这个是测试用例9
|
||||
查询objectType story type all id asc排序的回收站信息 >> story,,软件需求48
|
||||
查询objectType testcase hidden id asc排序的回收站信息 >> testcase,,这个是测试用例9
|
||||
|
||||
*/
|
||||
|
||||
@@ -29,4 +31,4 @@ r($action->getTrashesTest($objectTypeList[0], $typeList[0], $orderBy[1], $pager)
|
||||
r($action->getTrashesTest($objectTypeList[0], $typeList[1], $orderBy[0], $pager)) && p('0:objectType,objectId,objectName') && e('testcase,,这个是测试用例9'); // 查询objectType all type hidden id asc排序的回收站信息
|
||||
r($action->getTrashesTest($objectTypeList[0], $typeList[1], $orderBy[1], $pager)) && p('0:objectType,objectId,objectName') && e('testcase,,这个是测试用例9'); // 查询objectType all type hidden id asc排序的回收站信息
|
||||
r($action->getTrashesTest($objectTypeList[1], $typeList[0], $orderBy[0], $pager)) && p('0:objectType,objectId,objectName') && e('story,,软件需求48'); // 查询objectType story type all id asc排序的回收站信息
|
||||
r($action->getTrashesTest($objectTypeList[2], $typeList[1], $orderBy[0], $pager)) && p('0:objectType,objectId,objectName') && e('testcase,,这个是测试用例9'); // 查询objectType testcase hidden id asc排序的回收站信息
|
||||
r($action->getTrashesTest($objectTypeList[2], $typeList[1], $orderBy[0], $pager)) && p('0:objectType,objectId,objectName') && e('testcase,,这个是测试用例9'); // 查询objectType testcase hidden id asc排序的回收站信息
|
||||
Regular → Executable
+4
-1
@@ -10,6 +10,9 @@ title=测试 actionModel->getTrashObjectTypes();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
查询type all 的对象类型列表 >> story
|
||||
查询type all 的对象类型列表 >> testcase
|
||||
|
||||
*/
|
||||
|
||||
$typeList = array('all', 'hidden');
|
||||
@@ -17,4 +20,4 @@ $typeList = array('all', 'hidden');
|
||||
$action = new actionTest();
|
||||
|
||||
r($action->getTrashObjectTypesTest($typeList[0])) && p('story:objectType') && e('story'); // 查询type all 的对象类型列表
|
||||
r($action->getTrashObjectTypesTest($typeList[1])) && p('testcase:objectType') && e('testcase'); // 查询type all 的对象类型列表
|
||||
r($action->getTrashObjectTypesTest($typeList[1])) && p('testcase:objectType') && e('testcase'); // 查询type all 的对象类型列表
|
||||
@@ -2,6 +2,7 @@
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/action.class.php';
|
||||
$db->switchDB();
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
@@ -17,4 +18,4 @@ pid=1
|
||||
$action = new actionTest();
|
||||
|
||||
r($action->hideAllTest()) && p('0:extra;1:extra;2:extra') && e('2;2;2'); // 隐藏回收站全部信息
|
||||
system("./ztest init");
|
||||
$db->restoreDB();
|
||||
@@ -2,6 +2,7 @@
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/action.class.php';
|
||||
$db->switchDB();
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
@@ -24,4 +25,4 @@ r($action->hideOneTest($actionIDList[0])) && p('extra') && e('2'); // 隐藏acti
|
||||
r($action->hideOneTest($actionIDList[1])) && p('extra') && e('2'); // 隐藏action 87
|
||||
r($action->hideOneTest($actionIDList[2])) && p('extra') && e('2'); // 隐藏已隐藏action 9
|
||||
r($action->hideOneTest($actionIDList[3])) && p('extra') && e('1'); // 隐藏非删除action 1
|
||||
system("./ztest init");
|
||||
$db->restoreDB();
|
||||
@@ -2,6 +2,7 @@
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/action.class.php';
|
||||
$db->switchDB();
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
@@ -34,4 +35,4 @@ r($action->logHistoryTest($actionIDList[1], $changes2)) && p('0:field,old,new')
|
||||
r($action->logHistoryTest($actionIDList[2], $changes3)) && p('0:field,old,new') && e('name,name1,name2'); // 测试新增actionID 10003 历史记录
|
||||
r($action->logHistoryTest($actionIDList[3], $changes4)) && p('0:field,old,new') && e('code,code1,code2'); // 测试新增actionID 10004 历史记录
|
||||
r($action->logHistoryTest($actionIDList[4], $changes5)) && p('0:field,old,new') && e('assignedTo,test2,test1'); // 测试新增actionID 10005 历史记录
|
||||
system("./ztest init");
|
||||
$db->restoreDB();
|
||||
@@ -2,6 +2,7 @@
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/action.class.php';
|
||||
$db->switchDB();
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
@@ -28,4 +29,4 @@ r($action->readTest($objectType[1], $objectID[1])) && p('0:objectType,objectID,r
|
||||
r($action->readTest($objectType[2], $objectID[2])) && p('0:objectType,objectID,read') && e('productplan,3,1'); // 测试对action 3 进行阅读操作
|
||||
r($action->readTest($objectType[3], $objectID[3])) && p('0:objectType,objectID,read') && e('release,4,1'); // 测试对action 4 进行阅读操作
|
||||
r($action->readTest($objectType[4], $objectID[4])) && p('0:objectType,objectID,read') && e('project,5,1'); // 测试对action 5 进行阅读操作
|
||||
system("./ztest init");
|
||||
$db->restoreDB();
|
||||
@@ -2,6 +2,7 @@
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/action.class.php';
|
||||
$db->switchDB();
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
@@ -24,4 +25,4 @@ r($action->undeleteTest($actionIDList[0])) && p('extra') && e('0'); // 测试还
|
||||
r($action->undeleteTest($actionIDList[1])) && p('extra') && e('0'); // 测试还原action 87
|
||||
r($action->undeleteTest($actionIDList[2])) && p('extra') && e('0'); // 测试还原action 9
|
||||
r($action->undeleteTest($actionIDList[3])) && p('extra') && e('1'); // 测试还原未删除action 1
|
||||
system("./ztest init");
|
||||
$db->restoreDB();
|
||||
@@ -2,6 +2,7 @@
|
||||
<?php
|
||||
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
|
||||
include dirname(dirname(dirname(__FILE__))) . '/class/action.class.php';
|
||||
$db->switchDB();
|
||||
su('admin');
|
||||
|
||||
/**
|
||||
@@ -27,4 +28,4 @@ r($action->updateCommentTest($actionIDList[1], $commentList[1])) && p('comment')
|
||||
r($action->updateCommentTest($actionIDList[2], $commentList[2])) && p('comment') && e('备注3'); // 测试更新action 3的备注
|
||||
r($action->updateCommentTest($actionIDList[3], $commentList[3])) && p('comment') && e('备注4'); // 测试更新action 4的备注
|
||||
r($action->updateCommentTest($actionIDList[4], $commentList[4])) && p('comment') && e('备注5'); // 测试更新action 5的备注
|
||||
system("./ztest init");
|
||||
$db->restoreDB();
|
||||
Regular → Executable
+6
-1
@@ -10,6 +10,11 @@ title=测试 apiModel->create();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
测试创建api >> 910
|
||||
测试没有lib创建api >> 『API Library』should not be blank.
|
||||
测试没有title创建api >> 『Name』should not be blank.
|
||||
测试没有path创建api >> 『Request Path』should not be blank.
|
||||
|
||||
*/
|
||||
|
||||
$api = new apiTest();
|
||||
@@ -46,4 +51,4 @@ $emptyPathApi['path'] = '';
|
||||
r($api->createTest($normalApi)) && p('lib') && e('910'); //测试创建api
|
||||
r($api->createTest($emptyLibApi)) && p('lib:0') && e('『API Library』should not be blank.'); //测试没有lib创建api
|
||||
r($api->createTest($emptyTitleApi)) && p('title:0') && e('『Name』should not be blank.'); //测试没有title创建api
|
||||
r($api->createTest($emptyPathApi)) && p('path:0') && e('『Request Path』should not be blank.'); //测试没有path创建api
|
||||
r($api->createTest($emptyPathApi)) && p('path:0') && e('『Request Path』should not be blank.'); //测试没有path创建api
|
||||
Regular → Executable
+4
-1
@@ -10,6 +10,9 @@ title=测试 apiModel->createStruct();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
创建数据结构 >> struct
|
||||
创建没有结构名的数据结构 >> 『Name』should not be blank.
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
@@ -32,4 +35,4 @@ $normalStruct->addedBy = $tester->app->user->account;
|
||||
$normalStruct->addedDate = helper::now();
|
||||
|
||||
r($api->createStructTest($normalStruct)) && p('name') && e('struct'); //创建数据结构
|
||||
r($api->createStructTest($emptyNameStruct)) && p('name:0') && e('『Name』should not be blank.'); //创建没有结构名的数据结构
|
||||
r($api->createStructTest($emptyNameStruct)) && p('name:0') && e('『Name』should not be blank.'); //创建没有结构名的数据结构
|
||||
Regular → Executable
+3
-1
@@ -10,6 +10,8 @@ title=测试 apiModel->deleteRelease();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
删除一个创建的发布 >> 0
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
@@ -24,4 +26,4 @@ $normalRelease->addedDate = helper::now();
|
||||
|
||||
$release = $api->publishLibTest($normalRelease, false);
|
||||
|
||||
r($api->deleteReleaseTest($release->id, $release->lib)) && p('') && e('0'); //删除一个创建的发布
|
||||
r($api->deleteReleaseTest($release->id, $release->lib)) && p('') && e('0'); //删除一个创建的发布
|
||||
Regular → Executable
+3
-1
@@ -10,6 +10,8 @@ title=测试 apiModel->getApiListByRelease();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
创建api后创建发布,使用发布查找api >> 910
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
@@ -44,4 +46,4 @@ $normalRelease->addedDate = helper::now();
|
||||
$apiInfo = $api->createTest($normalApi, false);
|
||||
$release = $api->publishLibTest($normalRelease, false);
|
||||
|
||||
r($api->getApiListByReleaseTest($release)) && p('0:lib') && e('910'); //创建api后创建发布,使用发布查找api
|
||||
r($api->getApiListByReleaseTest($release)) && p('0:lib') && e('910'); //创建api后创建发布,使用发布查找api
|
||||
Regular → Executable
+3
-1
@@ -10,6 +10,8 @@ title=测试 apiModel->getLibById();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
获取刚创建的api >> 910
|
||||
|
||||
*/
|
||||
|
||||
$api = new apiTest();
|
||||
@@ -35,4 +37,4 @@ $data = array(
|
||||
$normalApi = $data;
|
||||
|
||||
$apiInfo = $api->createTest($normalApi, false);
|
||||
r($api->getLibByIdTest($apiInfo->id)) && p('lib') && e('910'); //获取刚创建的api
|
||||
r($api->getLibByIdTest($apiInfo->id)) && p('lib') && e('910'); //获取刚创建的api
|
||||
Regular → Executable
+6
-1
@@ -10,6 +10,11 @@ title=测试 apiModel->getListByModuleId();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
通过正常的libID、moduleID、releaseID查询api信息 >> 获取token
|
||||
通过正常的libID、moduleID,不传releaseID,查询api信息 >> 获取我的个人信息
|
||||
通过正常的libID,不传moduleID、releaseID查询api信息 >> 获取token
|
||||
通过不存在的libID,moduleID,releaseID查询api信息 >> 0
|
||||
|
||||
*/
|
||||
|
||||
$api = new apiTest();
|
||||
@@ -17,4 +22,4 @@ $api = new apiTest();
|
||||
r($api->getListByModuleIdTest(1, 1, 1)) && p('title') && e('获取token'); //通过正常的libID、moduleID、releaseID查询api信息
|
||||
r($api->getListByModuleIdTest(1, 1, 0)) && p('title') && e('获取我的个人信息'); //通过正常的libID、moduleID,不传releaseID,查询api信息
|
||||
r($api->getListByModuleIdTest(1, 0, 0)) && p('title') && e('获取token'); //通过正常的libID,不传moduleID、releaseID查询api信息
|
||||
r($api->getListByModuleIdTest(0, 0, 0)) && p('title') && e('0'); //通过不存在的libID,moduleID,releaseID查询api信息
|
||||
r($api->getListByModuleIdTest(0, 0, 0)) && p('title') && e('0'); //通过不存在的libID,moduleID,releaseID查询api信息
|
||||
Regular → Executable
+3
-1
@@ -10,6 +10,8 @@ title=测试 apiModel->getRelease();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
获取刚创建的发布 >> Version1
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
@@ -23,4 +25,4 @@ $normalRelease->addedBy = $tester->app->user->account;
|
||||
$normalRelease->addedDate = helper::now();
|
||||
|
||||
$release = $api->publishLibTest($normalRelease, false);
|
||||
r($api->getReleaseTest($release->lib)) && p('version') && e('Version1'); //获取刚创建的发布
|
||||
r($api->getReleaseTest($release->lib)) && p('version') && e('Version1'); //获取刚创建的发布
|
||||
Regular → Executable
+3
-1
@@ -10,6 +10,8 @@ title=测试 apiModel->getReleaseListByApi();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
获取刚插入的发布信息 >> 910
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
@@ -23,4 +25,4 @@ $normalRelease->addedBy = $tester->app->user->account;
|
||||
$normalRelease->addedDate = helper::now();
|
||||
|
||||
$release = $api->publishLibTest($normalRelease, false);
|
||||
r($api->getReleaseListByApiTest($release->lib, $release->id)) && p("{$release->id}:lib") && e('910'); //获取刚插入的发布信息
|
||||
r($api->getReleaseListByApiTest($release->lib, $release->id)) && p("{$release->id}:lib") && e('910'); //获取刚插入的发布信息
|
||||
Regular → Executable
+3
-1
@@ -10,6 +10,8 @@ title=测试 apiModel->getStructByID();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
获取刚创建的数据结构 >> struct
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
@@ -24,4 +26,4 @@ $normalStruct->addedBy = $tester->app->user->account;
|
||||
$normalStruct->addedDate = helper::now();
|
||||
|
||||
$struct = $api->createStructTest($normalStruct, false);
|
||||
r($api->getStructByIDTest($struct->id)) && p('name') && e('struct'); //获取刚创建的数据结构
|
||||
r($api->getStructByIDTest($struct->id)) && p('name') && e('struct'); //获取刚创建的数据结构
|
||||
Regular → Executable
+3
-1
@@ -10,6 +10,8 @@ title=测试 apiModel->getStructListByLibID();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
用libID获取刚插入的数据结构 >> 910
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
@@ -26,4 +28,4 @@ $normalStruct->addedDate = helper::now();
|
||||
|
||||
$struct = $api->createStructTest($normalStruct, false);
|
||||
|
||||
r($api->getStructListByLibIDTest($normalStruct->lib)) && p('0:lib') && e('910'); //用libID获取刚插入的数据结构
|
||||
r($api->getStructListByLibIDTest($normalStruct->lib)) && p('0:lib') && e('910'); //用libID获取刚插入的数据结构
|
||||
Regular → Executable
+3
-1
@@ -10,6 +10,8 @@ title=测试 apiModel->getStructListByRelease();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
创建api后创建发布,使用发布查找api >> 910
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
@@ -45,4 +47,4 @@ $apiInfo = $api->createTest($normalApi, false);
|
||||
$release = $api->publishLibTest($normalRelease, false);
|
||||
|
||||
r($api->getStructListByReleaseTest($release->lib)) && p('') && e('');
|
||||
//r($api->getApiListByReleaseTest($release)) && p('0:lib') && e('910'); //创建api后创建发布,使用发布查找api
|
||||
//r($api->getApiListByReleaseTest($release)) && p('0:lib') && e('910'); //创建api后创建发布,使用发布查找api
|
||||
Regular → Executable
+4
-1
@@ -10,6 +10,9 @@ title=测试 apiModel->publishLib();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
没有版本名的发布 >> 『Version』should not be blank.
|
||||
正常的发布 >> Version1
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
@@ -30,4 +33,4 @@ $normalRelease->addedBy = $tester->app->user->account;
|
||||
$normalRelease->addedDate = helper::now();
|
||||
|
||||
r($api->publishLibTest($emptyBuildRelease)) && p('version:0') && e('『Version』should not be blank.'); //没有版本名的发布
|
||||
r($api->publishLibTest($normalRelease)) && p('version') && e('Version1'); //正常的发布
|
||||
r($api->publishLibTest($normalRelease)) && p('version') && e('Version1'); //正常的发布
|
||||
Regular → Executable
+3
-2
@@ -10,6 +10,8 @@ title=测试 apiModel->update();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
修改一个刚创建的api >> edittestapi
|
||||
|
||||
*/
|
||||
|
||||
$api = new apiTest();
|
||||
@@ -50,10 +52,9 @@ $editData = array(
|
||||
'responseExample' => ''
|
||||
);
|
||||
|
||||
|
||||
$normalApi = $data;
|
||||
$editApi = $editData;
|
||||
|
||||
$apiInfo = $api->createTest($normalApi, false);
|
||||
|
||||
r($api->updateTest($apiInfo->id, $editApi)) && p('0:new') && e('edittestapi'); //修改一个刚创建的api
|
||||
r($api->updateTest($apiInfo->id, $editApi)) && p('0:new') && e('edittestapi'); //修改一个刚创建的api
|
||||
Regular → Executable
+4
-1
@@ -10,6 +10,9 @@ title=测试 apiModel->updateStruct();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
正常的修改 >> editStruct
|
||||
没有名称的修改 >> 『Name』should not be blank.
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
@@ -37,4 +40,4 @@ $emptyNameEditStruct['name'] = '';
|
||||
|
||||
$struct = $api->createStructTest($normalStruct, false);
|
||||
r($api->updateStructTest($struct->id, $normalEditStruct, false)) && p('0:new') && e('editStruct'); //正常的修改
|
||||
r($api->updateStructTest($struct->id, $emptyNameEditStruct)) && p('name:0') && e('『Name』should not be blank.'); //没有名称的修改
|
||||
r($api->updateStructTest($struct->id, $emptyNameEditStruct)) && p('name:0') && e('『Name』should not be blank.'); //没有名称的修改
|
||||
@@ -10,11 +10,12 @@ title=测试 blockModel->getQaStatisticParams();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
|
||||
测试name >> 类型
|
||||
测试control >> select
|
||||
|
||||
*/
|
||||
|
||||
$block = new blockTest();
|
||||
|
||||
r($block->getQaStatisticParamsTest()) && p('type:name') && e('类型'); //测试name
|
||||
r($block->getQaStatisticParamsTest()) && p('type:control') && e('select');//测试control
|
||||
r($block->getQaStatisticParamsTest()) && p('type:control') && e('select');//测试control
|
||||
@@ -10,10 +10,10 @@ title=测试 blockModel->getReleaseParams();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
|
||||
测试name >> 数量,20,input
|
||||
|
||||
*/
|
||||
|
||||
$block = new blockTest();
|
||||
|
||||
r($block->getReleaseParamsTest()) && p('name,default,control') && e('数量,20,input'); //测试name
|
||||
r($block->getReleaseParamsTest()) && p('name,default,control') && e('数量,20,input'); //测试name
|
||||
@@ -10,7 +10,11 @@ title=测试 blockModel->getScrumListParams();
|
||||
cid=1
|
||||
pid=1
|
||||
|
||||
|
||||
测试name和select >> 类型,select
|
||||
测试options >> 未完成
|
||||
测试options >> 进行中
|
||||
测试options >> 全部
|
||||
测试options >> 我参与
|
||||
|
||||
*/
|
||||
|
||||
@@ -20,4 +24,4 @@ r($block->getScrumListParamsTest()) && p('name,control') && e('类型,select
|
||||
r($block->getScrumListParamsTest()) && p('options:undone') && e('未完成'); //测试options
|
||||
r($block->getScrumListParamsTest()) && p('options:doing') && e('进行中'); //测试options
|
||||
r($block->getScrumListParamsTest()) && p('options:all') && e('全部'); //测试options
|
||||
r($block->getScrumListParamsTest()) && p('options:involved') && e('我参与'); //测试options
|
||||
r($block->getScrumListParamsTest()) && p('options:involved') && e('我参与'); //测试options
|
||||
@@ -16,4 +16,4 @@ pid=1
|
||||
|
||||
$block = new blockTest();
|
||||
|
||||
r($block->getScrumProductParamsTest()) && p('count:name;count:default;count:control') && e('数量;20;input'); // 测试获取产品区块的参数
|
||||
r($block->getScrumProductParamsTest()) && p('count:name;count:default;count:control') && e('数量;20;input'); // 测试获取产品区块的参数
|
||||
@@ -16,4 +16,4 @@ pid=1
|
||||
|
||||
$block = new blockTest();
|
||||
|
||||
r($block->getScrumRoadMapParamsTest()) && p() && e('0'); // 测试获取产品路线图区块的参数
|
||||
r($block->getScrumRoadMapParamsTest()) && p() && e('0'); // 测试获取产品路线图区块的参数
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user