Merge branch 'master' into 'sprint/master_lanzongjun_fixbug'

# Conflicts:
#   module/project/view/create.html.php
This commit is contained in:
王怡栋
2022-08-10 07:19:51 +00:00
69 changed files with 657 additions and 256 deletions
+8 -1
View File
@@ -28,4 +28,11 @@ UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource`
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackSolution' ORDER BY `id` DESC LIMIT 1) WHERE `module`='feedback' AND `field`='solution';
UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackclosedReason' ORDER BY `id` DESC LIMIT 1), `control`='select' WHERE `module`='feedback' AND `field`='closedReason';
UPDATE `zt_project` SET `closedDate`='' AND `closedBy`='' WHERE `status` != 'closed';
UPDATE `zt_project` SET `closedDate`='' AND `closedBy`='' WHERE `status` != 'closed';
UPDATE `zt_grouppriv` SET `method`='exportTemplate' WHERE `method` = 'exportTemplet';
INSERT IGNORE INTO `zt_workflowaction` (`module`, `action`, `method`, `name`, `type`, `batchMode`, `extensionType`, `open`, `position`, `layout`, `show`, `buildin`, `role`, `createdBy`, `createdDate`) VALUES
('bug', 'batchactivate', 'batchoperate', '批量激活', 'batch', 'different', 'none', 'normal', 'browse', 'normal', 'direct', '1', 'buildin', '', '2022-08-09 15:52');
INSERT INTO `zt_grouppriv` (SELECT `group`,`module`,'reply' FROM `zt_grouppriv` WHERE `module` = 'feedback' AND `method` = 'comment');
INSERT INTO `zt_grouppriv` (SELECT `group`,`module`,'ask' FROM `zt_grouppriv` WHERE `module` = 'feedback' AND `method` = 'comment');
+6 -12
View File
@@ -389,27 +389,21 @@ class control extends baseControl
* inForm=0|1 The fields displayed in a form or not. The default is 1.
* inCell=0|1 The fields displayed in a div with class cell or not. The default is 0.
* @param bool $print
* @param string $moduleName
* @param string $methodName
* @access public
* @return void
*/
public function printExtendFields($object, $type, $extras = '', $print = true)
public function printExtendFields($object, $type, $extras = '', $print = true, $moduleName = '', $methodName = '')
{
if(!isset($this->config->bizVersion)) return false;
$moduleName = $this->app->getModuleName();
$methodName = $this->app->getMethodName();
$moduleName = $moduleName ? $moduleName : $this->app->getModuleName();
$methodName = $methodName ? $methodName : $this->app->getMethodName();
$fields = $this->loadModel('flow')->printFields($moduleName, $methodName, $object, $type, $extras);
if(!$print) return $fields;
$picker = '';
//$jsRoot = $this->config->webRoot . "js/";
//$picker = file_get_contents($this->app->getBasePath() . 'app/sys/common/view/picker.html.php');
//$picker = substr($picker, strpos($picker, '<style>'));
//js::import($jsRoot . 'picker/min.js');
//css::import($jsRoot . 'picker/min.css');
echo $picker . $fields;
echo $fields;
}
/**
+4 -3
View File
@@ -69,7 +69,7 @@ $lang->admin->safe->modeList[0] = 'N/A';
$lang->admin->safe->modeList[1] = 'Medium';
$lang->admin->safe->modeList[2] = 'Stark';
$lang->admin->safe->modeRuleList[1] = 'Beinhaltet Groß und Kleinbuchstaben sowie Ziffern. Länge >= 6';
$lang->admin->safe->modeRuleList[1] = 'Beinhaltet Groß und Kleinbuchstaben sowie Ziffern. Länge >= 6.';
$lang->admin->safe->modeRuleList[2] = 'Beinhaltet Groß und Kleinbuchstaben, Ziffern sowie Sonderzeichen. Länge >= 10.';
$lang->admin->safe->reasonList['weak'] = 'Bekannte Schwache Passwörter';
@@ -87,5 +87,6 @@ $lang->admin->safe->loginCaptchaList[0] = 'Nein';
$lang->admin->safe->resetPWDList[1] = 'ON';
$lang->admin->safe->resetPWDList[0] = 'Off';
$lang->admin->safe->noticeMode = 'Password will be checked when a user logs in, or a user is added or edited.';
$lang->admin->safe->noticeStrong = '';
$lang->admin->safe->noticeMode = 'The password will be checked when creating and modifying user information, and changing passwords.';
$lang->admin->safe->noticeWeakMode = 'The password will be checked when logging into the system, creating and modifying user information, and changing passwords.';
$lang->admin->safe->noticeStrong = 'The longer the password, the more letters, numbers, or special characters it contains, and the less repetitive the password, the more secure it is!';
+4 -3
View File
@@ -69,7 +69,7 @@ $lang->admin->safe->modeList[0] = 'I don\'t care.';
$lang->admin->safe->modeList[1] = 'Medium';
$lang->admin->safe->modeList[2] = 'Strong';
$lang->admin->safe->modeRuleList[1] = ' >= 6 upper and lower case, and numbers';
$lang->admin->safe->modeRuleList[1] = ' >= 6 upper and lower case, and numbers.';
$lang->admin->safe->modeRuleList[2] = ' >= 10 upper and lower case, numbers and special characters.';
$lang->admin->safe->reasonList['weak'] = 'Common Weak Password';
@@ -87,5 +87,6 @@ $lang->admin->safe->loginCaptchaList[0] = 'No';
$lang->admin->safe->resetPWDList[1] = 'ON';
$lang->admin->safe->resetPWDList[0] = 'Off';
$lang->admin->safe->noticeMode = 'Password will be checked when a user logs in, or a user is added or edited.';
$lang->admin->safe->noticeStrong = '';
$lang->admin->safe->noticeMode = 'The password will be checked when creating and modifying user information, and changing passwords.';
$lang->admin->safe->noticeWeakMode = 'The password will be checked when logging into the system, creating and modifying user information, and changing passwords.';
$lang->admin->safe->noticeStrong = 'The longer the password, the more letters, numbers, or special characters it contains, and the less repetitive the password, the more secure it is!';
+5 -4
View File
@@ -69,8 +69,8 @@ $lang->admin->safe->modeList[0] = "Contrôle Modéré";
$lang->admin->safe->modeList[1] = 'Contrôle Moyen';
$lang->admin->safe->modeList[2] = 'Contrôle Fort';
$lang->admin->safe->modeRuleList[1] = ' >= 6 Majuscules, minuscules et chiffres';
$lang->admin->safe->modeRuleList[2] = ' >= 10 Majuscules, minuscules, chiffres et caractères spéciaux';
$lang->admin->safe->modeRuleList[1] = ' >= 6 Majuscules, minuscules et chiffres.';
$lang->admin->safe->modeRuleList[2] = ' >= 10 Majuscules, minuscules, chiffres et caractères spéciaux.';
$lang->admin->safe->reasonList['weak'] = 'Mots de passe faibles courants';
$lang->admin->safe->reasonList['account'] = 'Identique au compte';
@@ -87,5 +87,6 @@ $lang->admin->safe->loginCaptchaList[0] = 'Non';
$lang->admin->safe->resetPWDList[1] = 'ON';
$lang->admin->safe->resetPWDList[0] = 'Off';
$lang->admin->safe->noticeMode = "Le mot de passe sera vérifié quand un utilisateur se connectera ou qu'un utilisateur sera créé ou modifier.";
$lang->admin->safe->noticeStrong = '';
$lang->admin->safe->noticeMode = "Le mot de passe sera vérifié lors de la création et de la modification des coordonnées de l'utilisateur, et du changement de mot de passe.";
$lang->admin->safe->noticeWeakMode = "Le mot de passe sera vérifié lors de la connexion au système, de la création et de la modification des coordonnées de l'utilisateur, et du changement de mot de passe.";
$lang->admin->safe->noticeStrong = "Le mot de passe est d'autant plus sécurisé qu'il est long, qu'il contient plus de lettres, de chiffres ou de caractères spéciaux, et que les lettres du mot de passe sont peu répétitives !";
+3 -2
View File
@@ -87,5 +87,6 @@ $lang->admin->safe->loginCaptchaList[0] = '否';
$lang->admin->safe->resetPWDList[1] = '开启';
$lang->admin->safe->resetPWDList[0] = '关闭';
$lang->admin->safe->noticeMode = '系统会在登录、创建和修改用户、修改密码的时候检查用户口令。';
$lang->admin->safe->noticeStrong = '密码长度越长,含有大写字母或数字或特殊符号越多,密码字母越不重复,安全度越强!';
$lang->admin->safe->noticeMode = '系统会在创建和修改用户、修改密码的时候检查用户口令。';
$lang->admin->safe->noticeWeakMode = '系统会在登录、创建和修改用户、修改密码的时候检查用户口令。';
$lang->admin->safe->noticeStrong = '密码长度越长,含有大写字母或数字或特殊符号越多,密码字母越不重复,安全度越强!';
+1 -1
View File
@@ -40,7 +40,7 @@
<tr>
<th class='thWidth'><?php echo $lang->admin->safe->password?></th>
<td class='w-250px'><?php echo html::radio('mode', $lang->admin->safe->modeList, isset($config->safe->mode) ? $config->safe->mode : 0, "onclick=showModeRule(this.value)")?></td>
<td class='notice'><?php echo $lang->admin->safe->noticeMode?></td>
<td class='notice'><?php echo !empty($config->safe->changeWeak) ? $lang->admin->safe->noticeWeakMode : $lang->admin->safe->noticeMode;?></td>
</tr>
<tr id='mode1Rule' class='hidden'>
<th></th>
+1 -1
View File
@@ -486,7 +486,7 @@ class blockModel extends model
$this->app->loadLang('project');
$params = new stdclass();
$params->type['name'] = $this->lang->block->type;
$params->type['options'] = $this->lang->project->featureBar;
$params->type['options'] = $this->lang->project->featureBar['browse'];
$params->type['control'] = 'select';
$params->orderBy['name'] = $this->lang->block->orderBy;
+2
View File
@@ -340,6 +340,8 @@ $config->bug->datatable->fieldList['resolvedBuild']['title'] = 'resolvedBuild
$config->bug->datatable->fieldList['resolvedBuild']['fixed'] = 'no';
$config->bug->datatable->fieldList['resolvedBuild']['width'] = '120';
$config->bug->datatable->fieldList['resolvedBuild']['required'] = 'no';
$config->bug->datatable->fieldList['resolvedBuild']['control'] = 'select';
$config->bug->datatable->fieldList['resolvedBuild']['dataSource'] = array('module' => 'bug', 'method' =>'getRelatedObjects', 'params' => 'resolvedBuild&id,name');
$config->bug->datatable->fieldList['closedBy']['title'] = 'closedBy';
$config->bug->datatable->fieldList['closedBy']['fixed'] = 'no';
+2 -2
View File
@@ -2090,7 +2090,7 @@ class bug extends control
if(!$this->post->bugIDList) return print(js::locate($this->session->bugList, 'parent'));
$bugIDList = array_unique($this->post->bugIDList);
$bugs = $this->dao->select('id, title, status, resolvedBy, openedBuild')->from(TABLE_BUG)->where('id')->in($bugIDList)->fetchAll('id');
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($bugIDList)->fetchAll('id');
$this->qa->setMenu($this->products, $productID, $branch);
@@ -2293,7 +2293,7 @@ class bug extends control
if($_POST)
{
$this->loadModel('port');
$this->session->set('bugPortParams', array('productID' => $productID, 'executionID' => $executionID));
$this->session->set('bugPortParams', array('productID' => $productID, 'executionID' => $executionID, 'branch' => 'all'));
$this->port->export('bug');
$this->fetch('file', 'export2' . $_POST['fileType'], $_POST);
}
+15 -3
View File
@@ -945,6 +945,7 @@ class bugModel extends model
if(empty($bugIDList)) return $activateBugs;
$extendFields = $this->getFlowExtendFields();
foreach($bugIDList as $bugID)
{
if($data->statusList[$bugID] == 'active') continue;
@@ -967,6 +968,15 @@ class bugModel extends model
$activateBugs[$bugID]['toStory'] = 0;
$activateBugs[$bugID]['lastEditedBy'] = $this->app->user->account;
$activateBugs[$bugID]['lastEditedDate'] = $now;
foreach($extendFields as $extendField)
{
$postFieldData = $this->post->{$extendField->field};
if(is_array($postFieldData[$bugID])) $postFieldData[$bugID] = join(',', $postFieldData[$bugID]);
$activateBugs[$bugID][$extendField->field] = htmlSpecialString($postFieldData[$bugID]);
}
}
/* Update bugs. */
@@ -976,6 +986,8 @@ class bugModel extends model
if(dao::isError()) return print(js::error('bug#' . $bugID . dao::getError(true)));
$this->dao->update(TABLE_BUG)->set('activatedCount = activatedCount + 1')->where('id')->eq((int)$bugID)->exec();
$this->executeHooks($bugID);
}
return $activateBugs;
@@ -3557,13 +3569,13 @@ class bugModel extends model
foreach($bugs as $bug) $relatedObjectIdList[$bug->$object] = $bug->$object;
if($object == 'openedBuild') $object = 'build';
if($object == 'openedBuild' or $object == 'resolvedBuild') $object = 'build';
/* Get related objects title or names. */
$table = $this->config->objectTables[$object];
if($table) $relatedObjects = $this->dao->select($pairs)->from($table) ->where('id')->in($relatedObjectIdList)->fetchPairs();
if($table) $relatedObjects = $this->dao->select($pairs)->from($table)->where('id')->in($relatedObjectIdList)->fetchPairs();
if($object == 'build') $relatedObjects= array('trunk' => $this->lang->trunk) + $relatedObjects;
if(in_array($object, array('build','resolvedBuild'))) $relatedObjects= array('trunk' => $this->lang->trunk) + $relatedObjects;
return $relatedObjects;
}
+23 -1
View File
@@ -11,6 +11,16 @@
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php
if($this->config->edition == 'biz' || $this->config->edition == 'max')
{
$action = $this->loadModel('workflowaction')->getByModuleAndAction('bug', 'batchactivate');
if($action->js) echo "<script>{$action->js}</script>";
if($action->css) echo "<style>{$action->css}</style>";
}
?>
<div id='mainContent' class='main-content'>
<div class='main-header'>
<h2><?php echo $lang->bug->common . $lang->colon . $lang->bug->batchActivate;?></h2>
@@ -24,6 +34,14 @@
<th class='c-assigned'><?php echo $lang->bug->assignedTo;?></th>
<th class='c-build'><?php echo $lang->bug->openedBuild;?></th>
<th><?php echo $lang->bug->legendComment;?></th>
<?php
$extendFields = $this->bug->getFlowExtendFields();
foreach($extendFields as $extendField)
{
$required = strpos(",$extendField->rules,", ',1,') !== false ? 'required' : '';
echo "<th class='c-extend $required'>{$extendField->name}</th>";
}
?>
</tr>
</thead>
<tbody class='text-left'>
@@ -34,11 +52,15 @@
<td style='overflow:visible'><?php echo html::select("assignedToList[$bug->id]", $users, $bug->resolvedBy, "class='form-control chosen'");?></td>
<td style='overflow:visible'><?php echo html::select("openedBuildList[$bug->id]", $builds, $bug->openedBuild, 'size=4 multiple=multiple class="form-control chosen"');?></td>
<td><?php echo html::input("commentList[$bug->id]", '', "class='form-control'");?></td>
<?php
$this->loadModel('flow');
foreach($extendFields as $extendField) echo "<td" . (($extendField->control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, $bug, $extendField->field . "[$bug->id]") . "</td>";
?>
</tr>
<?php endforeach;?>
</tbody>
<tfoot>
<tr><td colspan='5' class='text-center'><?php echo html::submitButton();?></td></tr>
<tr><td colspan="<?php echo count($extendFields) + 5;?>" class='text-center'><?php echo html::submitButton();?></td></tr>
</tfoot>
</table>
</form>
+1
View File
@@ -16,6 +16,7 @@ if($currentLang != 'en') js::import($jsRoot . 'dhtmlxgantt/lang/' . $currentLang
?>
<style>
.gantt_message_area{display:none;}
#ganttPris:hover{background:unset;color:unset;cursor: unset;}
</style>
<script>
gantt.plugins({
+2 -2
View File
@@ -125,7 +125,7 @@ $config->execution->all->search['module'] = 'execution';
$config->execution->all->search['fields']['name'] = $lang->execution->execName;
$config->execution->all->search['fields']['id'] = $lang->execution->execId;
$config->execution->all->search['fields']['status'] = $lang->execution->execStatus;
$config->execution->all->search['fields']['project'] = $lang->execution->project;
if($config->systemMode == 'new') $config->execution->all->search['fields']['project'] = $lang->execution->project;
$config->execution->all->search['fields']['PM'] = $lang->execution->owner;
$config->execution->all->search['fields']['openedBy'] = $lang->execution->openedBy;
$config->execution->all->search['fields']['openedDate'] = $lang->execution->openedDate;
@@ -140,7 +140,7 @@ $config->execution->all->search['fields']['closedDate'] = $lang->execution->
$config->execution->all->search['params']['name'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
$config->execution->all->search['params']['id'] = array('operator' => '=', 'control' => 'input', 'values' => '');
$config->execution->all->search['params']['status'] = array('operator' => '=', 'control' => 'select', 'values' => array('') + $lang->execution->statusList);
$config->execution->all->search['params']['project'] = array('operator' => '=', 'control' => 'select', 'values' => '');
if($config->systemMode == 'new') $config->execution->all->search['params']['project'] = array('operator' => '=', 'control' => 'select', 'values' => '');
$config->execution->all->search['params']['PM'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
$config->execution->all->search['params']['openedBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
$config->execution->all->search['params']['openedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
+1 -1
View File
@@ -28,7 +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}
th.c-status, .c-begin, .c-end, .c-realBegan, .c-realEnd {text-align: center;}
.c-project{text-overflow: unset !important;}
canvas {height: 28px;}
+1 -1
View File
@@ -1,10 +1,10 @@
td.delayed {background: #e84e0f !important; color: white;}
#int-dropdown {margin-left: -8px; border-radius: 4px; border: 1px solid #0c64eb;}
#projectTaskForm table tbody tr td {overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
th.c-deadline {text-align: center;}
.table td.c-estimate, .table td.c-consumed, .table td.c-left {padding-right: 12px;}
.c-estimate {text-align: right;}
.c-consumed {text-align: right;}
.c-deadline {text-align: center;}
.c-left {text-align: right;}
.table-footer {z-index: 1;}
.btn-toolbar > .btn {margin-right: 5px !important;}
+1 -1
View File
@@ -1861,7 +1861,7 @@ function searchCards(value, order = '')
if(hideAll && rdSearchValue != '')
{
if($('.table-empty-tip').length == 0) $('#kanban').append('<div class="table-empty-tip"><p><span class="text-muted">' + kanbanLang.empty + '</span></p></div>');
if($('.table-empty-tip').length == 0) $('#kanban').append('<div class="table-empty-tip"><p><span class="text-muted">' + kanbancardLang.empty + '</span></p></div>');
}
else
{
+13 -1
View File
@@ -174,6 +174,7 @@ $lang->execution->cfdTypeList['bug'] = "View By bug";
$lang->team->account = 'Konto';
$lang->team->role = 'Rolle';
$lang->team->roleAB = 'Meine Rolle';
$lang->team->join = 'Beigetreten';
$lang->team->hours = 'Stunde/Tag';
$lang->team->days = 'Arbeitstage';
@@ -561,11 +562,22 @@ $lang->execution->gantt->color[3] = '#D3F3FD';
$lang->execution->gantt->color[4] = '#DFF5D9';
$lang->execution->gantt->color[5] = '#EBDCF9';
$lang->execution->gantt->textColor[0] = '#2D2D2D';
$lang->execution->gantt->textColor[1] = '#8D0308';
$lang->execution->gantt->textColor[2] = '#9D4200';
$lang->execution->gantt->textColor[3] = '#006D8E';
$lang->execution->gantt->textColor[4] = '#1A8100';
$lang->execution->gantt->textColor[5] = '#660ABC';
$lang->execution->gantt->stage = new stdclass();
$lang->execution->gantt->stage->progressColor = '#70B8FE';
$lang->execution->gantt->stage->color = '#D2E7FC';
$lang->execution->gantt->stage->textColor = '#0050A7';
$lang->execution->gantt->defaultColor = '#EBDCF9';
$lang->execution->gantt->defaultProgressColor = '#9BA8FF';
$lang->execution->gantt->defaultTextColor = '#660ABC';
$lang->execution->gantt->textColor = '000000';
$lang->execution->gantt->bar_height = '24';
$lang->execution->gantt->exportImg = 'Export as Image';
+13 -1
View File
@@ -174,6 +174,7 @@ $lang->execution->cfdTypeList['bug'] = "View By bug";
$lang->team->account = 'User';
$lang->team->role = 'Role';
$lang->team->roleAB = 'My Role';
$lang->team->join = 'Joined';
$lang->team->hours = 'Hours/day';
$lang->team->days = 'Day';
@@ -561,11 +562,22 @@ $lang->execution->gantt->color[3] = '#D3F3FD';
$lang->execution->gantt->color[4] = '#DFF5D9';
$lang->execution->gantt->color[5] = '#EBDCF9';
$lang->execution->gantt->textColor[0] = '#2D2D2D';
$lang->execution->gantt->textColor[1] = '#8D0308';
$lang->execution->gantt->textColor[2] = '#9D4200';
$lang->execution->gantt->textColor[3] = '#006D8E';
$lang->execution->gantt->textColor[4] = '#1A8100';
$lang->execution->gantt->textColor[5] = '#660ABC';
$lang->execution->gantt->stage = new stdclass();
$lang->execution->gantt->stage->progressColor = '#70B8FE';
$lang->execution->gantt->stage->color = '#D2E7FC';
$lang->execution->gantt->stage->textColor = '#0050A7';
$lang->execution->gantt->defaultColor = '#EBDCF9';
$lang->execution->gantt->defaultProgressColor = '#9BA8FF';
$lang->execution->gantt->defaultTextColor = '#660ABC';
$lang->execution->gantt->textColor = '000000';
$lang->execution->gantt->bar_height = '24';
$lang->execution->gantt->exportImg = 'Export as Image';
+13 -1
View File
@@ -174,6 +174,7 @@ $lang->execution->cfdTypeList['bug'] = "View By bug";
$lang->team->account = 'Utilisateur';
$lang->team->role = 'Rôle';
$lang->team->roleAB = 'Mon Rôle';
$lang->team->join = 'Ajouté';
$lang->team->hours = 'Heure/jour';
$lang->team->days = 'Jour';
@@ -561,11 +562,22 @@ $lang->execution->gantt->color[3] = '#D3F3FD';
$lang->execution->gantt->color[4] = '#DFF5D9';
$lang->execution->gantt->color[5] = '#EBDCF9';
$lang->execution->gantt->textColor[0] = '#2D2D2D';
$lang->execution->gantt->textColor[1] = '#8D0308';
$lang->execution->gantt->textColor[2] = '#9D4200';
$lang->execution->gantt->textColor[3] = '#006D8E';
$lang->execution->gantt->textColor[4] = '#1A8100';
$lang->execution->gantt->textColor[5] = '#660ABC';
$lang->execution->gantt->stage = new stdclass();
$lang->execution->gantt->stage->progressColor = '#70B8FE';
$lang->execution->gantt->stage->color = '#D2E7FC';
$lang->execution->gantt->stage->textColor = '#0050A7';
$lang->execution->gantt->defaultColor = '#EBDCF9';
$lang->execution->gantt->defaultProgressColor = '#9BA8FF';
$lang->execution->gantt->defaultTextColor = '#660ABC';
$lang->execution->gantt->textColor = '000000';
$lang->execution->gantt->bar_height = '24';
$lang->execution->gantt->exportImg = 'Export as Image';
+1
View File
@@ -127,6 +127,7 @@ $lang->execution->lifeTimeList['ops'] = "DevOps";
$lang->team = new stdclass();
$lang->team->account = 'Người dùng';
$lang->team->role = 'Vai trò';
$lang->team->roleAB = 'Vai trò của tôi';
$lang->team->join = 'Đã tham gia';
$lang->team->hours = 'Giờ/ngày';
$lang->team->days = 'Ngày';
+13 -1
View File
@@ -174,6 +174,7 @@ $lang->execution->cfdTypeList['bug'] = "按Bug查看";
$lang->team->account = '用户';
$lang->team->role = '角色';
$lang->team->roleAB = '我的角色';
$lang->team->join = '加盟日';
$lang->team->hours = '可用工时/天';
$lang->team->days = '可用工日';
@@ -561,11 +562,22 @@ $lang->execution->gantt->color[3] = '#D3F3FD';
$lang->execution->gantt->color[4] = '#DFF5D9';
$lang->execution->gantt->color[5] = '#EBDCF9';
$lang->execution->gantt->textColor[0] = '#2D2D2D';
$lang->execution->gantt->textColor[1] = '#8D0308';
$lang->execution->gantt->textColor[2] = '#9D4200';
$lang->execution->gantt->textColor[3] = '#006D8E';
$lang->execution->gantt->textColor[4] = '#1A8100';
$lang->execution->gantt->textColor[5] = '#660ABC';
$lang->execution->gantt->stage = new stdclass();
$lang->execution->gantt->stage->progressColor = '#70B8FE';
$lang->execution->gantt->stage->color = '#D2E7FC';
$lang->execution->gantt->stage->textColor = '#0050A7';
$lang->execution->gantt->defaultColor = '#EBDCF9';
$lang->execution->gantt->defaultProgressColor = '#9BA8FF';
$lang->execution->gantt->defaultTextColor = '#660ABC';
$lang->execution->gantt->textColor = '000000';
$lang->execution->gantt->bar_height = '24';
$lang->execution->gantt->exportImg = '导出图片';
+26 -16
View File
@@ -420,6 +420,8 @@ class executionModel extends model
/* Update the path. */
if($this->config->systemMode == 'new') $this->setTreePath($executionID);
$this->updateProducts($executionID);
/* Set team of execution. */
$members = isset($_POST['teamMembers']) ? $_POST['teamMembers'] : array();
array_push($members, $sprint->PO, $sprint->QD, $sprint->PM, $sprint->RD, $sprint->openedBy);
@@ -499,8 +501,8 @@ class executionModel extends model
->setIF(helper::isZeroDate($this->post->begin), 'begin', '')
->setIF(helper::isZeroDate($this->post->end), 'end', '')
->setIF(!isset($_POST['whitelist']), 'whitelist', '')
->setIF($this->post->status == 'closed', 'closedDate', helper::now())
->setIF($this->post->status == 'suspended', 'suspendedDate', helper::today())
->setIF($this->post->status == 'closed' and $oldExecution->status != 'closed', 'closedDate', helper::now())
->setIF($this->post->status == 'suspended' and $oldExecution->status != 'suspended', 'suspendedDate', helper::today())
->setIF($oldExecution->type == 'stage', 'project', $oldExecution->project)
->setDefault('team', $this->post->name)
->join('whitelist', ',')
@@ -698,8 +700,8 @@ class executionModel extends model
if(isset($data->codes)) $executions[$executionID]->code = $executionCode;
if(isset($data->projects)) $executions[$executionID]->project = zget($data->projects, $executionID, 0);
if(isset($data->attributes)) $executions[$executionID]->attribute = zget($data->attributes, $executionID, '');
if($executions[$executionID]->status == 'closed') $executions[$executionID]->closedDate = helper::now();
if($executions[$executionID]->status == 'suspended') $executions[$executionID]->suspendedDate = helper::today();
if($executions[$executionID]->status == 'closed' and $oldExecutions[$executionID]->status != 'closed') $executions[$executionID]->closedDate = helper::now();
if($executions[$executionID]->status == 'suspended' and $oldExecutions[$executionID]->status != 'suspended') $executions[$executionID]->suspendedDate = helper::today();
/* Check unique code for edited executions. */
if($projectModel == 'scrum' and isset($executionCode) and empty($executionCode))
@@ -4368,25 +4370,33 @@ class executionModel extends model
echo "<span class='project-type-label label label-outline $spanClass'>{$this->lang->execution->typeList[$execution->type]}</span> ";
}
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} 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))
if(empty($execution->children))
{
if($execution->status != 'closed')
echo html::a(helper::createLink('execution', 'view', "executionID=$execution->id"), $execution->name);
if(!helper::isZeroDate($execution->end))
{
echo strtotime($today) > strtotime($execution->end) ? '<td class="delayed" title="' . $this->lang->execution->delayed . '">' . $execution->end . '</td>' : '<td>' . $execution->end . '</td>';
}
else
{
echo '<td>' . $execution->end . '</td>';
if($execution->status != 'closed')
{
echo strtotime($today) > strtotime($execution->end) ? '<span class="label label-danger label-badge">' . $this->lang->execution->delayed . '</span>' : '';
}
}
}
else
{
echo '<td></td>';
echo $execution->name;
if(!helper::isZeroDate($execution->end))
{
if($execution->status != 'closed')
{
echo strtotime($today) > strtotime($execution->end) ? '<span class="label label-danger label-badge">' . $this->lang->execution->delayed . '</span>' : '';
}
}
}
echo '<td>' . zget($users, $execution->PM) . '</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 class="c-date"></td>' : '<td class="c-date">' . $execution->begin . '</td>';
echo helper::isZeroDate($execution->end) ? '<td class="c-date"></td>' : '<td class="c-date">' . $execution->end . '</td>';
echo "<td class='hours' title='{$execution->hours->totalEstimate}{$this->lang->execution->workHour}'>" . $execution->hours->totalEstimate . $this->lang->execution->workHourUnit . '</td>';
echo "<td class='hours' title='{$execution->hours->totalConsumed}{$this->lang->execution->workHour}'>" . $execution->hours->totalConsumed . $this->lang->execution->workHourUnit . '</td>';
echo "<td class='hours' title='{$execution->hours->totalLeft}{$this->lang->execution->workHour}'>" . $execution->hours->totalLeft . $this->lang->execution->workHourUnit . '</td>';
+1 -1
View File
@@ -132,7 +132,7 @@
<div id='kanbans'></div>
</div>
<div class='table-empty-tip hidden' id='emptyBox'>
<p><span class="text-muted"><?php echo $lang->kanban->empty?></span></p>
<p><span class="text-muted"><?php echo $lang->kanbancard->empty;?></span></p>
</div>
</div>
+2 -2
View File
@@ -18,14 +18,14 @@
.kanbans .panel {margin: 0 0; border: 1px solid #DCDCDC; border-radius: 4px; box-shadow: none; cursor: pointer; height: 160px; margin-bottom: 5px;}
.kanbans .panel:hover {border-color: #006AF1; box-shadow: 0 0 10px 0 rgba(0,0,100,.25);}
.kanbans .panel-heading {padding: 4px 2px 10px 16px;}
.kanbans .kanban-name {overflow: hidden; white-space:nowrap; width: 78%; float: left; padding-top: 8px;}
.kanbans .kanban-name {overflow: hidden; white-space:nowrap; width: 90%; float: left; padding-top: 8px;}
.kanbans .panel .label-closed {background: #AAA !important; color: #FFF; margin-top:-1px !important;}
.kanbans .kanban-actions {float: right; visibility: hidden;}
.kanbans .kanban-actions .dropdown-menu.pull-right {top:31px; right: -84px; left: auto;}
.kanbans .kanban-actions .dropdown-menu.pull-left {top:31px; right:-1px; left: auto;}
.kanbans .panel .label-closed {background: #AAA !important; color: #FFF; margin-top:-6px;}
.kanbans .panel-body {padding: 0 16px 16px;}
.kanbans .kanban-desc {color: #838a9d; word-break:break-all; height: 70px; overflow: hidden; display: -webkit-box; float:left;}
.kanbans .kanban-desc {color: #838a9d; word-break:break-all; height: 70px; overflow: hidden; float:left;}
.kanbans .kanban-footer {position: absolute; bottom: 10px; right: 10px; left: 15px;}
.kanbans .kanban-members {float: left; height: 24px; line-height: 24px;}
.kanbans .kanban-members > div {display: inline-block; height: 24px;}
+36
View File
@@ -30,3 +30,39 @@ $(function()
window.location.reload();
});
});
(function()
{
/* Expand or collapse text */
function limitText()
{
var fullText;
var limitText;
var $text = $(this);
var options = $.extend({limitSize: 40, suffix: '…'}, $text.data());
var text = $text.text();
if(text.length > options.limitSize)
{
fullText = $text.html();
limitText = text.substring(0, options.limitSize) + options.suffix;
$text.text(limitText).addClass('limit-text-on');
var $toggleBtn = options.toggleBtn ? $(options.toggleBtn) : $text.next('.text-limit-toggle');
$toggleBtn.text($toggleBtn.data('textExpand'));
$toggleBtn.on('click', function()
{
var isLimitOn = $text.toggleClass('limit-text-on').hasClass('limit-text-on');
if(isLimitOn) $text.text(limitText);
else $text.html(fullText);
$toggleBtn.text($toggleBtn.data(isLimitOn ? 'textExpand' : 'textCollapse'));
});
}
else
{
(options.toggleBtn ? $(options.toggleBtn) : $text.next('.text-limit-toggle')).hide();
}
$text.removeClass('hidden');
};
$.fn.textLimit = function(){return this.each(limitText);};
$(function(){$('.text-limit').textLimit();});
})();
+1 -1
View File
@@ -50,7 +50,7 @@
<?php $spaceDescTitle = empty($space->desc) ? $lang->kanban->emptyDesc : str_replace("\n", '', strip_tags($space->desc));?>
<?php $pattern = '/<br[^>]*>|<img[^>]*>/';?>
<?php $spaceDesc = empty($space->desc) ? $lang->kanban->emptyDesc : preg_replace($pattern, '', $space->desc);?>
<p class="spaceDesc text-ellipsis text-primary" title='<?php echo $spaceDescTitle;?>'><?php echo $spaceDesc;?></p>
<p><div><span class="text-limit hidden" data-limit-size="20"><?php echo $spaceDesc;?></span><a class="text-primary text-limit-toggle small" data-text-expand="<?php echo $lang->expand;?>" data-text-collapse="<?php echo $lang->collapse;?>"></a></div></p>
</div>
<div class='spaceActions pull-right'>
<?php $class = $space->status == 'closed' ? 'disabled' : '';?>
+1 -1
View File
@@ -1,2 +1,2 @@
.c-hours, .c-progress {width: 80px !important;}
th.c-status {padding-right: 8px !important;}
.c-status, .c-date {padding-right: 8px !important; text-align: center;}
+6 -6
View File
@@ -21,9 +21,9 @@ td.delayed {background: #e84e0f !important; color: white;}
html[lang="en"] .c-date {width: 80px;}
html[lang="en"] .c-user-short {width: 88px;}
[lang^='de'] .c-user-short, [lang^='fr'] .c-user-short {width: 75px;}
[lang^='de'] .c-date, [lang^='fr'] .c-date {width: 100px;}
[lang^='de'] .c-user, [lang^='fr'] .c-user {width: 118px;}
[lang^='de'] .c-hours.consumed {width: 70px;}
[lang^='de'] .c-hours.estimate {width: 75px;}
[lang^='de'] .c-project {width: 100px;}
[lang^=en] #taskTable .assigned-title{width: 115px !important;}
[lang^=de] #taskTable .assigned-title{width: 145px !important;}
[lang^=de] #taskTable .c-date {width: 80px;}
[lang^=de] #taskTable .c-user {width: 120px;}
[lang^=de] #taskTable .c-hours {width: 88px;}
[lang^=fr] #taskTable .assigned-title{width: 130px !important;}
+6 -6
View File
@@ -39,8 +39,8 @@
<?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 text-center'><?php echo $lang->statusAB;?></th>
<th class='c-user'><?php echo $lang->team->role;?></th>
<th class='c-status'><?php echo $lang->statusAB;?></th>
<th class='c-user' title='<?php echo $lang->team->roleAB;?>'><?php echo $lang->team->roleAB;?></th>
<th class='c-date'><?php echo $lang->team->join;?></th>
<th class='c-hours'><?php echo $lang->my->hours;?></th>
<th class='c-user'><?php echo $lang->execution->myTask;?></th>
@@ -67,9 +67,9 @@
<?php echo isset($execution->projectName) ? html::a($this->createLink('project', 'index', "id=$execution->project", '', '', $execution->project), $execution->projectName, '', "title='$execution->projectName'") : '';?>
</td>
<?php endif;?>
<td><?php echo $execution->begin;?></td>
<td><?php echo $execution->end;?></td>
<td class="c-status text-center">
<td class='c-date'><?php echo $execution->begin;?></td>
<td class='c-date'><?php echo $execution->end;?></td>
<td class="c-status">
<?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:?>
@@ -78,7 +78,7 @@
<?php endif;?>
</td>
<td><?php echo $execution->role;?></td>
<td><?php echo $execution->join;?></td>
<td class='c-date'><?php echo $execution->join;?></td>
<td><?php echo $execution->hours;?></td>
<td><?php echo $execution->assignedToMeTasks;?></td>
<td>
+2 -2
View File
@@ -89,11 +89,11 @@
<?php printf('%03d', $story->id);?>
</td>
<td class='c-pri'><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='c-name nobr <?php if(!empty($story->children)) echo "has-child" ?>'>
<td class='c-name nobr <?php if(!empty($story->children)) echo "has-child" ?>' title='<?php echo $story->title;?>'>
<?php echo html::a($storyLink, $story->title, null, "style='color: $story->color' data-group='product'");?>
<?php if(!empty($story->children)) echo '<a class="story-toggle" data-id="' . $story->id . '"><i class="icon icon-angle-double-right"></i></a>';;?>
</td>
<td class='c-product'><?php echo $story->productTitle;?></td>
<td class='c-product' title='<?php echo $story->productTitle;?>'><?php echo $story->productTitle;?></td>
<td class='c-plan'><?php echo $story->planTitle;?></td>
<td class='c-user'><?php echo zget($users, $story->openedBy);?></td>
<td class='c-hours' title="<?php echo $story->estimate . ' ' . $lang->hourCommon;?>"><?php echo $story->estimate . $config->hourUnit;?></td>
+8 -8
View File
@@ -87,15 +87,15 @@
<?php endif;?>
<?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?>
</th>
<th class="c-date"> <?php common::printOrderLink('date', $orderBy, $vars, $lang->todo->date);?></th>
<th class="c-type"> <?php common::printOrderLink('type', $orderBy, $vars, $lang->todo->type);?></th>
<th class="c-date text-center"><?php common::printOrderLink('date', $orderBy, $vars, $lang->todo->date);?></th>
<th class="c-type"><?php common::printOrderLink('type', $orderBy, $vars, $lang->todo->type);?></th>
<?php $style = $this->app->clientLang == 'en' ? "style='width:80px'" : '';?>
<th class="c-pri" <?php echo $style;?> title=<?php echo $lang->todo->pri;?>> <?php common::printOrderLink('pri', $orderBy, $vars, $lang->priAB);?></th>
<th class="c-name"> <?php common::printOrderLink('name', $orderBy, $vars, $lang->todo->name);?></th>
<th class="c-user"> <?php common::printOrderLink('assignedBy', $orderBy, $vars, $lang->todo->assignedBy);?></th>
<th class="c-begin"> <?php common::printOrderLink('begin', $orderBy, $vars, $lang->todo->beginAB);?></th>
<th class="c-end"> <?php common::printOrderLink('end', $orderBy, $vars, $lang->todo->endAB);?></th>
<th class="c-status"> <?php common::printOrderLink('status', $orderBy, $vars, $lang->todo->status);?></th>
<th class="c-name"> <?php common::printOrderLink('name', $orderBy, $vars, $lang->todo->name);?></th>
<th class="c-user"> <?php common::printOrderLink('assignedBy', $orderBy, $vars, $lang->todo->assignedBy);?></th>
<th class="c-begin"> <?php common::printOrderLink('begin', $orderBy, $vars, $lang->todo->beginAB);?></th>
<th class="c-end"> <?php common::printOrderLink('end', $orderBy, $vars, $lang->todo->endAB);?></th>
<th class="c-status"> <?php common::printOrderLink('status', $orderBy, $vars, $lang->todo->status);?></th>
<th class="c-actions-5"><?php echo $lang->actions;?></th>
</tr>
</thead>
@@ -111,7 +111,7 @@
<?php endif;?>
<?php echo $todo->id?>
</td>
<td class="c-date"><?php echo $todo->date == '2030-01-01' ? $lang->todo->periods['future'] : $todo->date;?></td>
<td class="c-date text-center"><?php echo $todo->date == '2030-01-01' ? $lang->todo->periods['future'] : $todo->date;?></td>
<td class="c-type"><?php echo zget($lang->todo->typeList, $todo->type, '');?></td>
<td class="c-pri"><span title="<?php echo zget($lang->todo->priList, $todo->pri);?>" class='label-pri <?php echo 'label-pri-' . $todo->pri;?>' title='<?php echo zget($lang->todo->priList, $todo->pri, $todo->pri);?>'><?php echo zget($lang->todo->priList, $todo->pri)?></span></td>
<td class="c-name" title="<?php echo $todo->name;?>"><?php echo html::a($this->createLink('todo', 'view', "id=$todo->id&from=my", '', true), $todo->name, '', "data-toggle='modal' data-width='80%' data-type='iframe' data-title='" . $lang->todo->view . "' data-icon='check'");?></td>
+1 -1
View File
@@ -17,7 +17,7 @@ $config->port->datetimeFeilds = '';
$config->port->listFields = '';
$config->port->sysLangFields = ',pri,status,type,mode,severity,os,browser,resolution,confirmed,source,reviewResult,stage,change';
$config->port->sysDataFields = 'execution,product,user';
$config->port->userFields = 'assignedTo,openedBy,finishedBy,canceledBy,closedBy,lastEditedBy,lastRunner,';
$config->port->userFields = 'assignedTo,openedBy,finishedBy,canceledBy,closedBy,lastEditedBy,lastRunner,resolvedBy';
$config->port->import = new stdClass();
+13 -3
View File
@@ -602,15 +602,25 @@ class portModel extends model
{
if(in_array($field, $dataSourceList))
{
$rows[$id]->$field = zget($exportDatas[$field], $value);
if($fieldList[$field]['control'] == 'multiple')
{
$multiple = '';
$multipleLsit = explode(',', $value);
foreach($multipleLsit as $tmpValue) $multiple .= "\n" . zget($exportDatas[$field], $tmpValue);
$rows[$id]->$field = $multiple;
}
else
{
$rows[$id]->$field = zget($exportDatas[$field], $value, '');
}
}
elseif(strpos($this->config->port->userFields, $field) !== false)
{
$rows[$id]->$field = zget($exportDatas['user'], $value);
$rows[$id]->$field = zget($exportDatas['user'], $value, '');
}
/* if value = 0 or value = 0000:00:00 set value = ''*/
if(!$value or helper::isZeroDate($value))
if(helper::isZeroDate($value))
{
$rows[$id]->$field = '';
}
+4
View File
@@ -57,3 +57,7 @@ $config->programplan->customCreateFields = 'PM,percent,attribute,acl,milestone,r
$config->programplan->custom = new stdclass();
$config->programplan->custom->createFields = 'PM,percent,attribute,acl,milestone';
$config->programplan->custom->customGanttFields = 'PM,deadline,status,realBegan,realEnd,progress,taskProgress,estimate,consumed';
$config->programplan->ganttCustom = new stdclass();
$config->programplan->ganttCustom->ganttFields = 'PM,deadline';
+5
View File
@@ -84,6 +84,11 @@ class programplan extends control
if(strpos($selectCustom, 'date') !== false) $dateDetails = 0;
$plans = $this->programplan->getDataForGantt($projectID, $this->productID, $baselineID, $selectCustom, false);
/* Set Custom. */
foreach(explode(',', $this->config->programplan->custom->customGanttFields) as $field) $customFields[$field] = $this->lang->programplan->ganttCustom[$field];
$this->view->customFields = $customFields;
$this->view->showFields = $this->config->programplan->ganttCustom->ganttFields;
}
if($type == 'assignedTo')
+10
View File
@@ -80,6 +80,16 @@ $lang->programplan->stageCustom = new stdClass();
$lang->programplan->stageCustom->date = 'Show Date';
$lang->programplan->stageCustom->task = 'Show Task';
$lang->programplan->ganttCustom['PM'] ='Manager';
$lang->programplan->ganttCustom['deadline'] ='Deadline';
$lang->programplan->ganttCustom['status'] ='Status';
$lang->programplan->ganttCustom['realBegan'] ='Actual Began';
$lang->programplan->ganttCustom['realEnd'] ='Actual End';
$lang->programplan->ganttCustom['progress'] ='Workload Ratio';
$lang->programplan->ganttCustom['taskProgress'] ='Task Progress';
$lang->programplan->ganttCustom['estimate'] ='Estimate';
$lang->programplan->ganttCustom['consumed'] ='Consumed';
$lang->programplan->error = new stdclass();
$lang->programplan->error->percentNumber = '"Workload %" must be digits.';
$lang->programplan->error->planFinishSmall = 'The "End" date must be > the "Begin" date.';
+10
View File
@@ -80,6 +80,16 @@ $lang->programplan->stageCustom = new stdClass();
$lang->programplan->stageCustom->date = 'Show Date';
$lang->programplan->stageCustom->task = 'Show Task';
$lang->programplan->ganttCustom['PM'] ='Manager';
$lang->programplan->ganttCustom['deadline'] ='Deadline';
$lang->programplan->ganttCustom['status'] ='Status';
$lang->programplan->ganttCustom['realBegan'] ='Actual Began';
$lang->programplan->ganttCustom['realEnd'] ='Actual End';
$lang->programplan->ganttCustom['progress'] ='Workload Ratio';
$lang->programplan->ganttCustom['taskProgress'] ='Task Progress';
$lang->programplan->ganttCustom['estimate'] ='Estimate';
$lang->programplan->ganttCustom['consumed'] ='Consumed';
$lang->programplan->error = new stdclass();
$lang->programplan->error->percentNumber = '"Workload %" must be digits.';
$lang->programplan->error->planFinishSmall = 'The "End" date must be > the "Begin" date.';
+10
View File
@@ -80,6 +80,16 @@ $lang->programplan->stageCustom = new stdClass();
$lang->programplan->stageCustom->date = 'Show Date';
$lang->programplan->stageCustom->task = 'Show Task';
$lang->programplan->ganttCustom['PM'] ='Manager';
$lang->programplan->ganttCustom['deadline'] ='Deadline';
$lang->programplan->ganttCustom['status'] ='Status';
$lang->programplan->ganttCustom['realBegan'] ='Actual Began';
$lang->programplan->ganttCustom['realEnd'] ='Actual End';
$lang->programplan->ganttCustom['progress'] ='Workload Ratio';
$lang->programplan->ganttCustom['taskProgress'] ='Task Progress';
$lang->programplan->ganttCustom['estimate'] ='Estimate';
$lang->programplan->ganttCustom['consumed'] ='Consumed';
$lang->programplan->error = new stdclass();
$lang->programplan->error->percentNumber = '"Workload %" must be digits.';
$lang->programplan->error->planFinishSmall = 'The "End" date must be > the "Begin" date.';
+10
View File
@@ -80,6 +80,16 @@ $lang->programplan->stageCustom = new stdClass();
$lang->programplan->stageCustom->date = '显示日期';
$lang->programplan->stageCustom->task = '显示任务';
$lang->programplan->ganttCustom['PM'] ='负责人';
$lang->programplan->ganttCustom['deadline'] ='计划完成';
$lang->programplan->ganttCustom['status'] ='状态';
$lang->programplan->ganttCustom['realBegan'] ='实际开始';
$lang->programplan->ganttCustom['realEnd'] ='实际结束';
$lang->programplan->ganttCustom['progress'] ='工作量占比';
$lang->programplan->ganttCustom['taskProgress'] ='任务进度';
$lang->programplan->ganttCustom['estimate'] ='工时';
$lang->programplan->ganttCustom['consumed'] ='消耗工时';
$lang->programplan->error = new stdclass();
$lang->programplan->error->percentNumber = '"工作量比例"必须为数字';
$lang->programplan->error->planFinishSmall = '"计划完成时间"必须大于"计划开始时间"';
+14 -13
View File
@@ -202,7 +202,7 @@ class programplanModel extends model
$data->duration = 1;
$data->color = $this->lang->execution->gantt->stage->color;
$data->progressColor = $this->lang->execution->gantt->stage->progressColor;
$data->textColor = $this->lang->execution->gantt->textColor;
$data->textColor = $this->lang->execution->gantt->stage->textColor;
$data->bar_height = $this->lang->execution->gantt->bar_height;
if($data->endDate > $data->start_date) $data->duration = helper::diffDate($data->endDate, $data->start_date) + 1;
@@ -213,7 +213,6 @@ class programplanModel extends model
$stageIndex[$plan->id] = array('planID' => $plan->id, 'parent' => $plan->parent, 'progress' => array('totalEstimate' => 0, 'totalConsumed' => 0, 'totalReal' => 0));
}
$taskSign = "<span class='task-label'>[ T ] </span>";
$taskPri = "<span class='label-pri label-pri-%s' title='%s'>%s</span> ";
/* Judge whether to display tasks under the stage. */
@@ -260,7 +259,7 @@ class programplanModel extends model
$data = new stdclass();
$data->id = $task->execution . '-' . $task->id;
$data->type = 'task';
$data->text = $taskSign . $priIcon . $task->name;
$data->text = $priIcon . $task->name;
$data->percent = '';
$data->status = $this->processStatus('task', $task);
$data->owner_id = $task->assignedTo;
@@ -281,9 +280,9 @@ class programplanModel extends model
$data->duration = 1;
$data->estimate = $task->estimate;
$data->consumed = $task->consumed;
$data->color = zget($this->lang->execution->gantt->color, $task->pri);
$data->progressColor = zget($this->lang->execution->gantt->progressColor, $task->pri);
$data->textColor = $this->lang->execution->gantt->textColor;
$data->color = zget($this->lang->execution->gantt->color, $task->pri, $this->lang->execution->gantt->defaultColor);
$data->progressColor = zget($this->lang->execution->gantt->progressColor, $task->pri, $this->lang->execution->gantt->defaultProgressColor);
$data->textColor = zget($this->lang->execution->gantt->textColor, $task->pri, $this->lang->execution->gantt->defaultTextColor);
$data->bar_height = $this->lang->execution->gantt->bar_height;
/* If multi task then show the teams. */
@@ -370,7 +369,6 @@ class programplanModel extends model
foreach($plans as $plan) $planIdList[$plan->id] = $plan->id;
$taskSign = "<span class='task-label'>[ T ] </span>";
$taskPri = "<span class='label-pri label-pri-%s' title='%s'>%s</span> ";
/* Judge whether to display tasks under the stage. */
@@ -432,8 +430,11 @@ class programplanModel extends model
$dataGroup->parent = 0;
$dataGroup->open = true;
$dataGroup->progress = '';
$dataGroup->taskProgress = '';
$dataGroup->bar_height = $this->lang->execution->gantt->bar_height;
$dataGroup->taskProgress = '';
$dataGroup->color = $this->lang->execution->gantt->stage->color;
$dataGroup->progressColor = $this->lang->execution->gantt->stage->progressColor;
$dataGroup->textColor = $this->lang->execution->gantt->stage->textColor;
$dataGroup->bar_height = $this->lang->execution->gantt->bar_height;
$groupKey = $groupID . $group;
$datas['data'][$groupKey] = $dataGroup;
@@ -461,7 +462,7 @@ class programplanModel extends model
$data = new stdclass();
$data->id = $task->id;
$data->type = 'task';
$data->text = $taskSign . $priIcon . $task->name;
$data->text = $priIcon . $task->name;
$data->percent = '';
$data->status = $this->processStatus('task', $task);
$data->owner_id = $task->assignedTo;
@@ -482,9 +483,9 @@ class programplanModel extends model
$data->duration = 1;
$data->estimate = $task->estimate;
$data->consumed = $task->consumed;
$data->color = zget($this->lang->execution->gantt->color, $task->pri);
$data->progressColor = zget($this->lang->execution->gantt->progressColor, $task->pri);
$data->textColor = $this->lang->execution->gantt->textColor;
$data->color = zget($this->lang->execution->gantt->color, $task->pri, $this->lang->execution->gantt->defaultColor);
$data->progressColor = zget($this->lang->execution->gantt->progressColor, $task->pri, $this->lang->execution->gantt->defaultProgressColor);
$data->textColor = zget($this->lang->execution->gantt->textColor, $task->pri, $this->lang->execution->gantt->defaultTextColor);
$data->bar_height = $this->lang->execution->gantt->bar_height;
if($data->endDate > $data->start_date) $data->duration = helper::diffDate($data->endDate, $data->start_date) + 1;
+19 -19
View File
@@ -70,8 +70,13 @@ form {display: block; margin-top: 0em; margin-block-end: 1em;}
<?php js::set('module', $app->rawModule);?>
<?php js::set('method', $app->rawMethod);?>
<?php js::set('ganttType', $ganttType);?>
<?php js::set('showFields', $showFields);?>
<?php js::set('canGanttEdit', common::hasPriv('programplan', 'ganttEdit'));?>
<div id='mainContent' class='main-content load-indicator' data-loading='<?php echo $lang->programplan->exporting;?>'>
<div class="pull-right btn-toolbar">
<?php $customLink = $this->createLink('custom', 'ajaxSaveCustomFields', 'module=programplan&section=ganttCustom&key=ganttFields')?>
<?php include '../../common/view/customfield.html.php';?>
</div>
<form class="main-form form-ajax not-watch">
<div class="example">
<?php echo html::commonButton($lang->programplan->full, 'id="fullScreenBtn"', 'btn btn-primary btn-sm')?>
@@ -498,24 +503,19 @@ $(function()
gantt.config.scale_height = 18 * gantt.config.scales.length;
gantt.config.duration_unit = "day";
gantt.config.columns = [
{name: 'text', width: '*', tree: true, resize: true, width:200},
{name: 'owner_id', align: 'center', resize: true, width: 80, template: function(task){return getByIdForGantt(gantt.serverList('userList'), task.owner_id)}},
{name: 'status', align: 'center', resize: true, width: 80},
{name: 'start_date', align: 'center', resize: true, width: 80},
{name: 'end_date', align: 'center', resize: true, width: 80},
{name: 'duration', align: 'center', resize: true, width: 60},
{name: 'estimate', align: 'center', resize: true, width: 60},
{name: 'percent', align: 'center', resize: true, width:70, template: function(plan)
{
if(plan.percent) return Math.round(plan.percent) + '%';
}
},
{name: 'taskProgress', align: 'center', resize: true, width: 60},
{name: 'realBegan', align: 'center', resize: true, width: 60},
{name: 'realEnd', align: 'center', resize: true, width: 60},
{name: 'consumed', align: 'center', resize: false, width: 60},
];
gantt.config.columns = [];
gantt.config.columns.push({name: 'text', width: '*', tree: true, resize: true, width:200});
if(showFields.indexOf('PM') != -1) gantt.config.columns.push({name: 'owner_id', align: 'center', resize: true, width: 80, template: function(task){return getByIdForGantt(gantt.serverList('userList'), task.owner_id)}})
if(showFields.indexOf('status') != -1) gantt.config.columns.push({name: 'status', align: 'center', resize: true, width: 80});
gantt.config.columns.push({name: 'start_date', align: 'center', resize: true, width: 80});
if(showFields.indexOf('deadline') != -1) gantt.config.columns.push({name: 'end_date', align: 'center', resize: true, width: 80});
gantt.config.columns.push({name: 'duration', align: 'center', resize: true, width: 60});
if(showFields.indexOf('estimate') != -1) gantt.config.columns.push({name: 'estimate', align: 'center', resize: true, width: 60});
if(showFields.indexOf('progress') != -1) gantt.config.columns.push({name: 'percent', align: 'center', resize: true, width:70, template: function(plan){ if(plan.percent) return Math.round(plan.percent) + '%';}});
if(showFields.indexOf('taskProgress') != -1) gantt.config.columns.push({name: 'taskProgress', align: 'center', resize: true, width: 60});
if(showFields.indexOf('realBegan') != -1) gantt.config.columns.push({name: 'realBegan', align: 'center', resize: true, width: 60});
if(showFields.indexOf('realEnd') != -1) gantt.config.columns.push({name: 'realEnd', align: 'center', resize: true, width: 60});
if(showFields.indexOf('consumed') != -1) gantt.config.columns.push({name: 'consumed', align: 'center', resize: false, width: 60});
gantt.locale.labels.column_text = <?php echo json_encode($typeHtml);?>;
gantt.locale.labels.column_owner_id = "<?php echo $lang->programplan->PMAB;?>";
@@ -684,7 +684,7 @@ $(function()
if(task) gantt[task.$open ? 'close' : 'open'](task.id);
});
$(".checkbox-primary").on('click', function()
$(".example .checkbox-primary").on('click', function()
{
var stageCustom = [];
$("input[name='stageCustom[]']:checked").each(function()
+1
View File
@@ -7,3 +7,4 @@
th.table-nest-title-edit {padding-left: 50px !important;}
th.table-nest-title-edit .table-nest-toggle {left: 28px;}
th.table-nest-title .check-all {position: absolute; left: 15px; top: 7px;}
.c-date {text-align: center;}
+1 -1
View File
@@ -1093,7 +1093,7 @@ class projectModel extends model
->stripTags($this->config->project->editor->create['id'], $this->config->allowedTags)
->remove('products,branch,plans,delta,newProduct,productName,future,contactListMenu,teamMembers')
->get();
if(!isset($this->config->setCode) or $this->config->setCode == 1) unset($project->code);
if(isset($this->config->setCode) and $this->config->setCode == 0) unset($project->code);
$linkedProductsCount = 0;
if(isset($_POST['products']))
+3
View File
@@ -64,6 +64,9 @@ $lang->release->mailContent = '<p>Dear users,</p><p style="margin-left: 30px;"
$lang->release->storyList = '<p style="margin-left: 30px;">Story List:%s。</p>';
$lang->release->bugList = '<p style="margin-left: 30px;">Bug List:%s。</p>';
$lang->release->storyTitle = 'Story Name';
$lang->release->bugTitle = 'Bug Name';
$lang->release->filePath = 'Download : ';
$lang->release->scmPath = 'SCM Pfad : ';
+3
View File
@@ -64,6 +64,9 @@ $lang->release->mailContent = '<p>Dear users,</p><p style="margin-left: 30px;"
$lang->release->storyList = '<p style="margin-left: 30px;">Story List:%s。</p>';
$lang->release->bugList = '<p style="margin-left: 30px;">Bug List:%s。</p>';
$lang->release->storyTitle = 'Story Name';
$lang->release->bugTitle = 'Bug Name';
$lang->release->filePath = 'Download : ';
$lang->release->scmPath = 'SCM Path : ';
+3
View File
@@ -64,6 +64,9 @@ $lang->release->mailContent = '<p>Dear users,</p><p style="margin-left: 30px;"
$lang->release->storyList = '<p style="margin-left: 30px;">Story List:%s。</p>';
$lang->release->bugList = '<p style="margin-left: 30px;">Bug List:%s。</p>';
$lang->release->storyTitle = 'Story Name';
$lang->release->bugTitle = 'Bug Name';
$lang->release->filePath = 'Télecharger : ';
$lang->release->scmPath = 'SCM Path : ';
+3
View File
@@ -64,6 +64,9 @@ $lang->release->mailContent = '<p>尊敬的用户,您好!</p><p style="mar
$lang->release->storyList = '<p style="margin-left: 30px;">需求列表:%s。</p>';
$lang->release->bugList = '<p style="margin-left: 30px;">Bug列表:%s。</p>';
$lang->release->storyTitle = '需求名称';
$lang->release->bugTitle = 'Bug名称';
$lang->release->filePath = '下载地址:';
$lang->release->scmPath = '版本库地址:';
+4
View File
@@ -556,6 +556,10 @@ class releaseModel extends model
$suffix = empty($release->product) ? '' : ' - ' . $this->loadModel('product')->getById($release->product)->name;
$subject = 'Release #' . $release->id . ' ' . $release->name . $suffix;
$stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($release->stories)->andWhere('deleted')->eq(0)->fetchAll('id');
$bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($release->bugs)->andWhere('deleted')->eq(0)->fetchAll();
$leftBugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($release->leftBugs)->andWhere('deleted')->eq(0)->fetchAll();
/* Get mail content. */
$modulePath = $this->app->getModulePath($appName = '', 'release');
$oldcwd = getcwd();
+118 -19
View File
@@ -12,24 +12,123 @@
?>
<?php $mailTitle = 'RELEASE #' . $release->id . ' ' . $release->name;?>
<?php $module = $this->app->tab == 'product' ? 'release' : 'projectrelease';?>
<?php include $this->app->getModuleRoot() . 'common/view/mail.header.html.php';?>
<tr>
<td>
<table cellpadding='0' cellspacing='0' width='600' style='border: none; border-collapse: collapse;'>
<?php
$onlybody = isonlybody() ? true : false;
if($onlybody) $_GET['onlybody'] = 'no';
?>
<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
<html xmlns='http://www.w3.org/1999/xhtml'>
 <head>
  <meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
  <title><?php echo $mailTitle ?></title>
  <meta name='viewport' content='width=device-width, initial-scale=1.0'/>
<style>
.content tr {line-height: 30px;}
.content tr:last-child td{border-bottom: 1px solid #D7DBDE;}
.content th, .content td {border-top: 1px solid #D7DBDE; color: #3C4353;}
.content .id {text-align: center; width: 100px;}
.content .title {border-left: 1px solid #D7DBDE; text-align: left; padding-left: 30px;}
.content-icon {width: 16px; height: 16px; vertical-align: middle;}
</style>
 </head>
<body style='background-color: #FFF;'>
 <table border='0' cellpadding='0' cellspacing='0' width='100%' style='font-size: 13px; color: #333; line-height: 20px; font-family: "Helvetica Neue",Helvetica,"Microsoft Yahei","Hiragino Sans GB","WenQuanYi Micro Hei",Tahoma,Arial,sans-serif;'>
<tr>
<td style='padding: 10px; background-color: #F8FAFE; border: none; font-size: 14px; font-weight: 500; border-bottom: 1px solid #e5e5e5;'>
<?php echo html::a(zget($this->config->mail, 'domain', common::getSysURL()) . helper::createLink($module, 'view', "releaseID=$release->id", 'html'), $mailTitle, '', "text-decoration: underline;'");?>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td style='padding: 10px; border: none;'>
<fieldset style='border: 1px solid #e5e5e5'>
<legend style='color: #114f8e'><?php echo $this->lang->release->desc;?></legend>
<div style='padding:5px;'><?php echo $release->desc;?></div>
</fieldset>
</td>
</tr>
<td>
<table align='center' border='0' cellpadding='0' cellspacing='0' width='1080' style='border: none; border-collapse: collapse;'>
<tr>
<td style='padding: 10px 0; border: none; vertical-align: middle;'><strong style='font-size: 18px; color: #1B1F28;'><?php echo $this->app->company->name ?></strong></td>
</tr>
</table>
<table align='center' border='0' cellpadding='0' cellspacing='0' width='1080' style='background-color: #fff; border: 1px solid; border-color: rgba(0, 127, 255, 0.2); margin-bottom: 20px; font-size:13px;'>
<tr>
<td>
<table cellpadding='0' cellspacing='0' width='1080' style='border: none; border-collapse: collapse;'>
<tr>
<td style='padding: 10px; background-color: #F8FAFE; border: none; font-size: 15px; font-weight: 500; border-bottom: 1px solid #e5e5e5;'>
<?php echo html::a(zget($this->config->mail, 'domain', common::getSysURL()) . helper::createLink($module, 'view', "releaseID=$release->id", 'html'), $mailTitle, '', "style='text-decoration: none; color: #007FFF; font-family: PingFang-SC;''");?>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td class='content-head' style='padding: 15px 10px 15px 40px; border: none;'>
<img src='<?php echo common::getSysURL() . '/theme/default/images/release/story.png';?>' class='content-icon' style='width: 16px; height: 16px; vertical-align: middle;'/>
<span style='vertical-align: middle; font-weight: bold; color: #1B1F28;'><?php echo $this->lang->release->stories . '(' . count($stories) . ')';?></span>
</td>
</tr>
<tr>
<td>
<table align='center' cellpadding='0' cellspacing='0' width='1000' class='content' style='background-color: #fff;margin-bottom: 20px; font-size:13px;'>
<thead>
<tr style='background-color: #F4F5F7;'>
<th style='text-align: center; width: 100px;border-top: 1px solid #D7DBDE; color: #3C4353;'><?php echo $this->lang->idAB; ?></th>
<th class='title' style='border-left: 1px solid #D7DBDE; text-align: left; padding-left: 30px;border-top: 1px solid #D7DBDE; color: #3C4353;'><?php echo $this->lang->release->storyTitle; ?></th>
</tr>
</thead>
<tbody>
<?php foreach($stories as $story):?>
<tr>
<td class='id' style='text-align: center; width: 100px;border-top: 1px solid #D7DBDE; color: #3C4353;'><?php echo $story->id;?></td>
<td class='title' style='border-left: 1px solid #D7DBDE; text-align: left; padding-left: 30px;border-top: 1px solid #D7DBDE; color: #3C4353;'><?php echo $story->title;?></td>
</tr>
<?php endforeach;?>
</tbody>
</table>
</td>
</tr>
<tr>
<td class='content-head' style='padding: 15px 10px 15px 40px; border: none;'>
<img src='<?php echo common::getSysURL() . '/theme/default/images/release/bug.png';?>' class='content-icon' style='width: 16px; height: 16px; vertical-align: middle;'/>
<span style='vertical-align: middle; font-weight: bold; color: #1B1F28;'><?php echo $this->lang->release->bugs . '(' . count($bugs) . ')';?></span>
</td>
</tr>
<tr>
<td>
<table align='center' cellpadding='0' cellspacing='0' width='1000' class='content' style='background-color: #fff;margin-bottom: 20px; font-size:13px;'>
<thead>
<tr style='background-color: #F4F5F7;'>
<th class='id' style='text-align: center; width: 100px;border-top: 1px solid #D7DBDE; color: #3C4353;'><?php echo $this->lang->idAB; ?></th>
<th class='title' style='border-left: 1px solid #D7DBDE; text-align: left; padding-left: 30px;border-top: 1px solid #D7DBDE; color: #3C4353;'><?php echo $this->lang->release->bugTitle; ?></th>
</tr>
</thead>
<tbody>
<?php foreach($bugs as $bug):?>
<tr>
<td class='id' style='text-align: center; width: 100px;border-top: 1px solid #D7DBDE; color: #3C4353;'><?php echo $bug->id;?></td>
<td class='title' style='border-left: 1px solid #D7DBDE; text-align: left; padding-left: 30px;border-top: 1px solid #D7DBDE; color: #3C4353;'><?php echo $bug->title;?></td>
</tr>
<?php endforeach;?>
</tbody>
</table>
</td>
</tr>
<tr>
<td class='content-head' style='padding: 15px 10px 15px 40px; border: none;'>
<img src='<?php echo common::getSysURL() . '/theme/default/images/release/leftbug.png';?>' class='content-icon' style='width: 16px; height: 16px; vertical-align: middle;'/>
<span style='vertical-align: middle; font-weight: bold; color: #1B1F28;'><?php echo $this->lang->release->leftBugs . '(' . count($leftBugs) . ')';?></span>
</td>
</tr>
<tr>
<td>
<table align='center' cellpadding='0' cellspacing='0' width='1000' class='content' style='background-color: #fff;margin-bottom: 20px; font-size:13px;'>
<thead>
<tr style='background-color: #F4F5F7;'>
<th class='id' style='text-align: center; width: 100px;border-top: 1px solid #D7DBDE; color: #3C4353;'><?php echo $this->lang->idAB; ?></th>
<th class='title' style='border-left: 1px solid #D7DBDE; text-align: left; padding-left: 30px;border-top: 1px solid #D7DBDE; color: #3C4353;'><?php echo $this->lang->release->bugTitle; ?></th>
</tr>
</thead>
<tbody>
<?php foreach($leftBugs as $bug):?>
<tr>
<td class='id' style='text-align: center; width: 100px;border-top: 1px solid #D7DBDE; color: #3C4353;'><?php echo $bug->id;?></td>
<td class='title' style='border-left: 1px solid #D7DBDE; text-align: left; padding-left: 30px;border-top: 1px solid #D7DBDE; color: #3C4353;'><?php echo $bug->title;?></td>
</tr>
<?php endforeach;?>
</tbody>
</table>
</td>
</tr>
<?php include $this->app->getModuleRoot() . 'common/view/mail.footer.html.php';?>
+7
View File
@@ -75,6 +75,13 @@ $config->search->fields->story->content = 'keywords,spec,verify';
$config->search->fields->story->addedDate = 'openedDate';
$config->search->fields->story->editedDate = 'lastEditedDate';
$config->search->fields->requirement = new stdclass();
$config->search->fields->requirement->id = 'id';
$config->search->fields->requirement->title = 'title';
$config->search->fields->requirement->content = 'keywords,spec,verify';
$config->search->fields->requirement->addedDate = 'openedDate';
$config->search->fields->requirement->editedDate = 'lastEditedDate';
$config->search->fields->task = new stdclass();
$config->search->fields->task->id = 'id';
$config->search->fields->task->title = 'name';
+16 -1
View File
@@ -191,7 +191,7 @@ class search extends control
}
else
{
$type = zget($this->lang->searchObjects, ($result['type'] == 'case' ? 'testcase' : $result['type']), $result['type']);
$type = zget($this->lang->search->modules, ($result['type'] == 'case' ? 'testcase' : $result['type']), $result['type']);
return $this->send(array('result' => 'unfinished', 'message' => sprintf($this->lang->search->buildResult, $type, $type, $result['count']), 'type' => $type, 'count' => $result['count'], 'next' => inlink('buildIndex', "type={$result['type']}&lastID={$result['lastID']}") ));
}
}
@@ -231,6 +231,20 @@ class search extends control
$pager = new pager(0, $this->config->search->recPerPage, $pageID);
$results = $this->search->getList($words, $type, $pager);
if($words)
{
$typeCount = $this->search->getListCount($words);
$typeList = array('all' => $this->lang->search->modules['all']);
foreach($typeCount as $objectType => $count)
{
$typeList[$objectType] = $this->lang->search->modules[$objectType];
}
}
else
{
$typeList = $this->lang->search->modules;
}
/* Set session. */
$uri = inlink('index', "recTotal=$pager->recTotal&pageID=$pager->pageID");
$uri .= strpos($uri, '?') === false ? '?' : '&';
@@ -266,6 +280,7 @@ class search extends control
$this->view->consumed = time() - $begin;
$this->view->title = $this->lang->search->index;
$this->view->type = $type;
$this->view->typeList = $typeList;
$this->view->pager = $pager;
$this->view->words = $words;
$this->view->referer = $this->session->referer;
+2 -1
View File
@@ -95,7 +95,8 @@ $lang->search->modules['productplan'] = 'Plan';
$lang->search->modules['program'] = 'Program';
$lang->search->modules['project'] = 'Project';
$lang->search->modules['execution'] = $lang->executionCommon;
$lang->search->modules['story'] = 'Story';
$lang->search->modules['story'] = $lang->SRCommon;
$lang->search->modules['requirement'] = $lang->URCommon;
$lang->search->objectTypeList['story'] = $lang->SRCommon;
$lang->search->objectTypeList['requirement'] = $lang->URCommon;
+2 -1
View File
@@ -95,7 +95,8 @@ $lang->search->modules['productplan'] = 'Plan';
$lang->search->modules['program'] = 'Program';
$lang->search->modules['project'] = 'Project';
$lang->search->modules['execution'] = $lang->executionCommon;
$lang->search->modules['story'] = 'Story';
$lang->search->modules['story'] = $lang->SRCommon;
$lang->search->modules['requirement'] = $lang->URCommon;
$lang->search->objectTypeList['story'] = $lang->SRCommon;
$lang->search->objectTypeList['requirement'] = $lang->URCommon;
+2 -1
View File
@@ -95,7 +95,8 @@ $lang->search->modules['productplan'] = 'Plan';
$lang->search->modules['program'] = 'Program';
$lang->search->modules['project'] = 'Project';
$lang->search->modules['execution'] = $lang->executionCommon;
$lang->search->modules['story'] = 'Story';
$lang->search->modules['story'] = $lang->SRCommon;
$lang->search->modules['requirement'] = $lang->URCommon;
$lang->search->objectTypeList['story'] = $lang->SRCommon;
$lang->search->objectTypeList['requirement'] = $lang->URCommon;
+3 -2
View File
@@ -90,12 +90,13 @@ $lang->search->modules['product'] = $lang->productCommon;
$lang->search->modules['release'] = '发布';
$lang->search->modules['testtask'] = '测试单';
$lang->search->modules['testsuite'] = '测试套件';
$lang->search->modules['testreport'] = '报告';
$lang->search->modules['testreport'] = '测试报告';
$lang->search->modules['productplan'] = '计划';
$lang->search->modules['program'] = '项目集';
$lang->search->modules['project'] = '项目';
$lang->search->modules['execution'] = $lang->executionCommon;
$lang->search->modules['story'] = '需求';
$lang->search->modules['story'] = $lang->SRCommon;
$lang->search->modules['requirement'] = $lang->URCommon;
$lang->search->objectTypeList['story'] = $lang->SRCommon;
$lang->search->objectTypeList['requirement'] = $lang->URCommon;
+52 -9
View File
@@ -585,15 +585,14 @@ class searchModel extends model
}
/**
* get search results of keywords.
* Get list sql params.
*
* @param string $keywords
* @param string $type
* @param object $pager
* @access public
* @access protected
* @return array
*/
public function getList($keywords, $type, $pager = null)
protected function getSqlParams($keywords, $type)
{
$spliter = $this->app->loadClass('spliter');
$words = explode(' ', self::unify($keywords, ' '));
@@ -637,6 +636,46 @@ class searchModel extends model
}
}
return array($words, $againstCond, $likeCondition, $allowedObject);
}
/**
* Get counts of keyword search results.
*
* @param string $keywords
* @param string $type
* @access public
* @return array
*/
public function getListCount($keywords, $type = 'all')
{
list($words, $againstCond, $likeCondition, $allowedObject) = $this->getSqlParams($keywords, $type);
$typeCount = $this->dao->select("objectType, count(*) as objectCount")
->from(TABLE_SEARCHINDEX)
->where("(MATCH(title,content) AGAINST('{$againstCond}' IN BOOLEAN MODE) >= 1 {$likeCondition})")
->andWhere('vision')->eq($this->config->vision)
->andWhere('objectType')->in($allowedObject)
->andWhere('addedDate')->le(helper::now())
->groupBy('objectType')
->fetchPairs('objectType', 'objectCount');
arsort($typeCount);
return $typeCount;
}
/**
* get search results of keywords.
*
* @param string $keywords
* @param string $type
* @param object $pager
* @access public
* @return array
*/
public function getList($keywords, $type, $pager = null)
{
list($words, $againstCond, $likeCondition, $allowedObject) = $this->getSqlParams($keywords, $type);
$scoreColumn = "(MATCH(title, content) AGAINST('{$againstCond}' IN BOOLEAN MODE))";
$stmt = $this->dao->select("*, {$scoreColumn} as score")
->from(TABLE_SEARCHINDEX)
@@ -685,7 +724,7 @@ class searchModel extends model
if($module == 'issue') $fields = $this->config->edition == 'max' ? 'id,project,owner,lib' : 'id,project,owner';
if($module == 'project') $fields = 'id,model';
if($module == 'execution')$fields = 'id,type,project';
if($module == 'story') $fields = $this->config->edition == 'max' ? 'id,type,lib' : 'id,type';
if($module == 'story' or $module == 'requirement') $fields = $this->config->edition == 'max' ? 'id,type,lib' : 'id,type';
if(($module == 'risk' or $module == 'opportunity') and $this->config->edition == 'max') $fields = 'id,lib';
if($module == 'doc' and $this->config->edition == 'max') $fields = 'id,assetLib,assetLibType';
if(empty($fields)) continue;
@@ -738,9 +777,9 @@ class searchModel extends model
$record->url = helper::createLink('execution', $method, "id={$record->objectID}");
$record->extraType = empty($execution->type) ? '' : $execution->type;
}
elseif($module == 'story')
elseif($module == 'story' or $module == 'requirement')
{
$story = $objectList['story'][$record->objectID];
$story = $objectList[$module][$record->objectID];
if(!empty($story->lib))
{
$module = 'assetlib';
@@ -1127,9 +1166,13 @@ class searchModel extends model
public function buildIndexQuery($type, $testDeleted = true)
{
$table = $this->config->objectTables[$type];
if($type == 'story')
if($type == 'story' or $type == 'requirement')
{
$query = $this->dao->select('DISTINCT t1.*,t2.spec,t2.verify')->from($table)->alias('t1')->leftJoin(TABLE_STORYSPEC)->alias('t2')->on('t1.id=t2.story')->where('t1.deleted')->eq(0)->andWhere('t1.version=t2.version');
$query = $this->dao->select('DISTINCT t1.*,t2.spec,t2.verify')->from($table)->alias('t1')
->leftJoin(TABLE_STORYSPEC)->alias('t2')->on('t1.id=t2.story')
->where('t1.deleted')->eq(0)
->andWhere('type')->eq($type)
->andWhere('t1.version=t2.version');
}
elseif($type == 'doc')
{
+2 -2
View File
@@ -22,7 +22,7 @@ adjustMenuWidth();
<form method='post' action='<?php echo inlink('index')?>' style='margin-bottom:10px;'>
<div class='input-group col-md-8 col-md-offset-2'>
<span class='input-group-btn w-auto'><?php echo html::input('words', $words, "class='form-control'")?></span>
<span class='input-group-btn select'><?php echo html::select('type[]', $lang->search->modules, $type, "class='form-control chosen' multiple")?></span>
<span class='input-group-btn select'><?php echo html::select('type[]', $typeList, $type, "class='form-control chosen' multiple")?></span>
<span class='input-group-btn'><?php echo html::submitButton($lang->search->common, '', 'btn btn-primary')?></span>
</div>
</form>
@@ -41,7 +41,7 @@ adjustMenuWidth();
<?php
$objectType = $object->objectType == 'case' ? 'testcase' : $object->objectType;
echo html::a($object->url, $object->title, '', 'title="' . strip_tags($object->title) . '"');
if(($objectType == 'story' || $objectType == 'execution' || $objectType == 'issue') and !empty($object->extraType))
if(($objectType == 'story' || $objectType == 'requirement' || $objectType == 'execution' || $objectType == 'issue') and !empty($object->extraType))
{
echo "<small class=''>[{$lang->search->objectTypeList[$object->extraType]} #{$object->objectID}]</small> ";
}
+7 -6
View File
@@ -4464,7 +4464,8 @@ class storyModel extends model
}
elseif($id == 'title')
{
$title = $story->title;
$title = $story->title;
$class .= ' text-ellipsis';
if(!empty($story->children)) $class .= ' has-child';
}
elseif($id == 'plan')
@@ -4637,25 +4638,25 @@ class storyModel extends model
echo zget($users, $story->openedBy, $story->openedBy);
break;
case 'openedDate':
echo substr($story->openedDate, 5, 11);
echo helper::isZeroDate($story->openedDate) ? '' : substr($story->openedDate, 5, 11);
break;
case 'assignedTo':
$this->printAssignedHtml($story, $users);
break;
case 'assignedDate':
echo substr($story->assignedDate, 5, 11);
echo helper::isZeroDate($story->assignedDate) ? '' : substr($story->assignedDate, 5, 11);
break;
case 'reviewedBy':
echo $story->reviewedBy;
break;
case 'reviewedDate':
echo substr($story->reviewedDate, 5, 11);
echo helper::isZeroDate($story->reviewedDate) ? '' : substr($story->reviewedDate, 5, 11);
break;
case 'closedBy':
echo zget($users, $story->closedBy, $story->closedBy);
break;
case 'closedDate':
echo substr($story->closedDate, 5, 11);
echo helper::isZeroDate($story->closedDate) ? '' : substr($story->closedDate, 5, 11);
break;
case 'closedReason':
echo zget($this->lang->story->reasonList, $story->closedReason, $story->closedReason);
@@ -4664,7 +4665,7 @@ class storyModel extends model
echo zget($users, $story->lastEditedBy, $story->lastEditedBy);
break;
case 'lastEditedDate':
echo substr($story->lastEditedDate, 5, 11);
echo helper::isZeroDate($story->lastEditedDate) ? '' : substr($story->lastEditedDate, 5, 11);
break;
case 'feedbackBy':
echo $story->feedbackBy;
+8 -15
View File
@@ -3805,26 +3805,19 @@ class taskModel extends model
$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 .= 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>';
$list .= '<td></td>';
$list .= helper::isZeroDate($task->estStarted) ? '<td></td>' : '<td>' . $task->estStarted . '</td>';
if(!helper::isZeroDate($task->deadline))
{
if($task->status != 'done')
if($task->status != done)
{
$list .= strtotime($today) > strtotime($task->deadline) ? '<td class="delayed" ' . 'title="' . $this->lang->execution->delayed . '">' . $task->deadline . '</td>' : '<td>' . $task->deadline . '</td>';
}
else
{
$list .= '<td>' . $task->deadline . '</td>';
$list .= strtotime($today) > strtotime($task->deadline) ? '<span class="label label-danger label-badge">' . $this->lang->execution->delayed . '</span>' : '';
}
}
else
{
$list .= '<td></td>';
}
$list .= '</td>';
$list .= '<td>' . zget($users, $task->assignedTo, '') . '</td>';
$list .= "<td class='status-{$task->status} text-center'>" . $this->processStatus('task', $task) . '</td>';
$list .= '<td></td>';
$list .= helper::isZeroDate($task->estStarted) ? '<td class="c-date"></td>' : '<td class="c-date">' . $task->estStarted . '</td>';
$list .= helper::isZeroDate($task->deadline) ? '<td class="c-date"></td>' : '<td class="c-date">' . $task->deadline . '</td>';
$list .= '<td>' . $task->estimate . $this->lang->execution->workHourUnit . '</td>';
$list .= '<td>' . $task->consumed . $this->lang->execution->workHourUnit . '</td>';
$list .= '<td>' . $task->left . $this->lang->execution->workHourUnit . '</td>';
+2 -2
View File
@@ -70,7 +70,7 @@ $config->testcase->search['params']['stage'] = array('operator' => 'inclu
$config->testcase->search['params']['lib'] = array('operator' => '=', 'control' => 'select', 'values' => '');
$config->testcase->search['params']['lastRunner'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
$config->testcase->search['params']['lastRunResult'] = array('operator' => '=', 'control' => 'select', 'values' => array_diff($lang->testcase->resultList, array('n/a' => $lang->testcase->resultList['n/a'])) + array('' => ''));
$config->testcase->search['params']['lastRunResult'] = array('operator' => '=', 'control' => 'select', 'values' => array_diff($lang->testcase->resultList, array('n/a' => $lang->testcase->resultList['n/a'])) + array('null' => $lang->testcase->unexecuted));
$config->testcase->search['params']['lastRunDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->testcase->search['params']['openedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->testcase->search['params']['lastEditedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
@@ -185,7 +185,7 @@ $config->testcase->datatable->fieldList['status']['required'] = 'no';
$config->testcase->datatable->fieldList['lastEditedBy']['title'] = 'lastEditedBy';
$config->testcase->datatable->fieldList['lastEditedBy']['fixed'] = 'no';
$config->testcase->datatable->fieldList['lastEditedBy']['width'] = '80';
$config->testcase->datatable->fieldList['lastEditedBy']['width'] = '92';
$config->testcase->datatable->fieldList['lastEditedBy']['required'] = 'no';
$config->testcase->datatable->fieldList['lastEditedDate']['title'] = 'lastEditedDate';
+16 -3
View File
@@ -919,8 +919,7 @@ class upgrade extends control
$response['message'] = '';
$response['nextMessage'] = '';
$stmt = $this->dao->query("SHOW TABLE STATUS WHERE `Engine` is not null AND `Engine` = 'MyISAM'");
$stmt = $this->dao->query("SHOW TABLE STATUS WHERE `Engine` is not null AND `Engine` = 'MyISAM'");
$table = $stmt->fetch();
if(empty($table))
{
@@ -939,14 +938,28 @@ class upgrade extends control
$tableName = $table->Name;
$response['table'] = $tableName;
/* Check process this table or not. */
$dbProcesses = $this->dao->query("SHOW PROCESSLIST")->fetchAll();
foreach($dbProcesses as $dbProcess)
{
if($dbProcess->db != $this->config->db->name) continue;
if(strpos($dbProcess->Info, " `{$tableName}` "))
{
$response['message'] = sprintf($this->lang->upgrade->changingTable, $response['table']);
return print(json_encode($response));
}
}
if($nextTable)
{
$response['next'] = $nextTable->Name;
$response['next'] = $nextTable->Name;
if($response['next']) $response['nextMessage'] = sprintf($this->lang->upgrade->changingTable, $response['next']);
}
if(stripos($tableName, 'searchindex') !== false)
{
/* Change fulltext index. */
$stmt = $this->dao->query("show index from `$tableName`");
$indexes = array();
while($index = $stmt->fetch())
+82 -1
View File
@@ -534,6 +534,7 @@ class upgradeModel extends model
$this->processCreatedInfo();
$this->processCreatedBy();
$this->updateApproval();
$this->updateSearchIndex();
break;
}
@@ -679,8 +680,10 @@ class upgradeModel extends model
case 'biz7.0':
$this->processFlowPosition();
break;
case 'biz7.3':
case 'biz7.4':
$this->updateApproval();
$this->addDefaultRuleToWorkflow();
$this->addFlowActions('biz7.3');
break;
}
}
@@ -6880,4 +6883,82 @@ class upgradeModel extends model
return !dao::isError();
}
/**
* Update story search index.
*
* @access public
* @return void
*/
public function updateSearchIndex()
{
$requirementIds = $this->dao->select('t1.id')->from(TABLE_SEARCHINDEX)->alias('t1')
->leftJoin(TABLE_STORY)->alias('t2')->on('t1.objectID = t2.id')
->where('t1.objectType')->eq('story')
->andWhere('t2.type')->eq('requirement')
->fetchPairs('id');
$this->dao->update(TABLE_SEARCHINDEX)->set('objectType')->eq('requirement')->where('id')->in($requirementIds)->exec();
}
/**
* Add required rule to the built-in workflow status field.
*
* @access public
* @return void
*/
public function addDefaultRuleToWorkflow()
{
$notemptyRule = $this->dao->select('id')->from(TABLE_WORKFLOWRULE)->where('rule')->eq('notempty')->fetch();
if(empty($notemptyRule)) return false;
$fields = $this->dao->select('*')->from(TABLE_WORKFLOWFIELD)->where('field')->eq('status')->andWhere('buildin')->eq(1)->fetchAll();
foreach($fields as $field)
{
if(strpos(',' . $field->rules . ',', ',' . $notemptyRule->id . ',') !== false) continue;
$rules = $notemptyRule->id;
if(!empty($field->rules)) $rules = $field->rules . ',' . $rules;
$this->dao->update(TABLE_WORKFLOWFIELD)->set('rules')->eq($rules)->where('id')->eq($field->id)->exec();
}
return !dao::isError();
}
/**
* Add workflow actions.
*
* @param int $version
* @access public
* @return void
*/
public function addFlowActions($version)
{
$this->loadModel('workflow');
$this->loadModel('workflowaction');
$upgradeLang = $this->lang->workflowaction->upgrade[$version];
$upgradeConfig = $this->config->workflowaction->upgrade[$version];
if(empty($upgradeLang) || empty($upgradeConfig)) return true;
$this->lang->workflowaction->upgrade = new stdclass();
$this->config->workflowaction->upgrade = new stdclass();
foreach($upgradeLang as $module => $labels)
{
$this->lang->workflowaction->upgrade->actions = $labels;
foreach($upgradeConfig[$module] as $code => $config) $this->config->workflowaction->upgrade->$code = $config;
$flow = $this->workflow->getByModule($module);
$this->workflow->createActions($flow, 'upgrade');
$this->dao->update(TABLE_WORKFLOWACTION)->set('extensionType')->eq('none')->set('role')->eq('buildin')->where('module')->eq($module)->andWhere('action')->in(array_keys($labels))->exec();
foreach($labels as $method => $label)
{
$workflowAction = $this->dao->select('*')->from(TABLE_WORKFLOWACTION)->where('module')->eq($module)->andWhere('action')->eq($method)->fetch();
unset($workflowAction->id);
$workflowAction->vision = $workflowAction->vision == 'lite' ? 'rnd' : 'lite';
$this->dao->replace(TABLE_WORKFLOWACTION)->data($workflowAction)->exec();
}
}
return !dao::isError();
}
}
-32
View File
@@ -1,32 +0,0 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/weekly.class.php';
su('admin');
/**
title=测试 weeklyModel->getPV();
cid=1
pid=1
测试projectID值为0,date值为2022-05-01 >> 1488
测试projectID值为0,date值为空 >> 4223.02
测试projectID值为11,date值为2022-05-01 >> 24
测试projectID值为11,date值为空 >> 100
测试projectID值为41,date值为2022-05-01 >> 9
测试projectID值为41,date值为空 >> 50.5
*/
$projectIDList = array(0, 11, 41);
$dateList = array('2022-05-01', '');
$weekly = new weeklyTest();
r($weekly->getPVTest($projectIDList[0], $dateList[0])) && p() && e('1488'); //测试projectID值为0,date值为2022-05-01
r($weekly->getPVTest($projectIDList[0], $dateList[1])) && p() && e('4223.02'); //测试projectID值为0,date值为空
r($weekly->getPVTest($projectIDList[1], $dateList[0])) && p() && e('24'); //测试projectID值为11,date值为2022-05-01
r($weekly->getPVTest($projectIDList[1], $dateList[1])) && p() && e('100'); //测试projectID值为11,date值为空
r($weekly->getPVTest($projectIDList[2], $dateList[0])) && p() && e('9'); //测试projectID值为41,date值为2022-05-01
r($weekly->getPVTest($projectIDList[2], $dateList[1])) && p() && e('50.5'); //测试projectID值为41,date值为空
-37
View File
@@ -1,37 +0,0 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/weekly.class.php';
$db->switchDB();
su('admin');
/**
title=测试 weeklyModel->save();
cid=1
pid=1
保存项目为已挂起、日期不为空的数据 >> 11,41
保存项目为已挂起、日期为空的数据 >> 12,41
保存项目为已关闭、日期不为空的数据 >> 13,42
保存项目为已关闭、日期为空的数据 >> 14,42
保存项目为未开始、日期不为空的数据 >> 15,43
保存项目为未开始、日期为空的数据 >> 16,43
保存项目为进行中、日期不为空的数据 >> 17,45
保存项目为进行中、日期为空的数据 >> 18,45
*/
$productID = array('41', '42', '43', '45');
$date = array('2022-04-29', '');
$weekly = new weeklyTest();
r($weekly->saveTest($productID[0], $date[0])) && p('id,project') && e('11,41'); //保存项目为已挂起、日期不为空的数据
r($weekly->saveTest($productID[0], $date[1])) && p('id,project') && e('12,41'); //保存项目为已挂起、日期为空的数据
r($weekly->saveTest($productID[1], $date[0])) && p('id,project') && e('13,42'); //保存项目为已关闭、日期不为空的数据
r($weekly->saveTest($productID[1], $date[1])) && p('id,project') && e('14,42'); //保存项目为已关闭、日期为空的数据
r($weekly->saveTest($productID[2], $date[0])) && p('id,project') && e('15,43'); //保存项目为未开始、日期不为空的数据
r($weekly->saveTest($productID[2], $date[1])) && p('id,project') && e('16,43'); //保存项目为未开始、日期为空的数据
r($weekly->saveTest($productID[3], $date[0])) && p('id,project') && e('17,45'); //保存项目为进行中、日期不为空的数据
r($weekly->saveTest($productID[3], $date[1])) && p('id,project') && e('18,45'); //保存项目为进行中、日期为空的数据
$db->restoreDB();
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

File diff suppressed because one or more lines are too long