Merge branch 'master' into 'master_liuhong_63787'
# Conflicts: # module/program/css/browse.css # module/project/css/browse.css
This commit is contained in:
+19
-5
@@ -140,7 +140,8 @@ class userEntry extends Entry
|
||||
break;
|
||||
case 'execution':
|
||||
$info->execution = array('total' => 0, 'executions' => array());
|
||||
if(!common::hasPriv('my', 'execution')) break;
|
||||
if(!common::hasPriv('my', 'work')) break;
|
||||
$this->config->openMethods[] = 'my.execution';
|
||||
|
||||
$control = $this->loadController('my', 'execution');
|
||||
$control->execution($this->param('type', 'undone'), $this->param('order', 'id_desc'), $this->param('total', 0), $this->param('limit', 5), $this->param('page', 1));
|
||||
@@ -193,6 +194,7 @@ class userEntry extends Entry
|
||||
case 'task':
|
||||
$info->task = array('total' => 0, 'tasks' => array());
|
||||
if(!common::hasPriv('my', 'work')) break;
|
||||
$this->config->openMethods[] = 'my.task';
|
||||
|
||||
$control = $this->loadController('my', 'task');
|
||||
$control->task($this->param('type', 'assignedTo'), 0, $this->param('order', 'id_desc'), $this->param('total', 0), $this->param('limit', 5), $this->param('page', 1));
|
||||
@@ -208,6 +210,7 @@ class userEntry extends Entry
|
||||
case 'bug':
|
||||
$info->bug = array('total' => 0, 'bugs' => array());
|
||||
if(!common::hasPriv('my', 'work')) break;
|
||||
$this->config->openMethods[] = 'my.bug';
|
||||
|
||||
$control = $this->loadController('my', 'bug');
|
||||
$control->bug($this->param('type', 'assignedTo'), 0, $this->param('order', 'id_desc'), $this->param('total', 0), $this->param('limit', 5), $this->param('page', 1));
|
||||
@@ -264,6 +267,7 @@ class userEntry extends Entry
|
||||
case 'story':
|
||||
$info->story = array('total' => 0, 'stories' => array());
|
||||
if(!common::hasPriv('my', 'work')) break;
|
||||
$this->config->openMethods[] = 'my.story';
|
||||
|
||||
$control = $this->loadController('my', 'story');
|
||||
$control->story($this->param('type', 'assignedTo'), 0, $this->param('order', 'id_desc'), $this->param('total', 0), $this->param('limit', 5), $this->param('page', 1));
|
||||
@@ -289,6 +293,7 @@ class userEntry extends Entry
|
||||
|
||||
if($this->config->edition == 'max')
|
||||
{
|
||||
$this->config->openMethods[] = 'my.issue';
|
||||
$control = $this->loadController('my', 'issue');
|
||||
$control->issue('createdBy', 0, 'id_desc', 0, $this->param('limit', 5), 1);
|
||||
$data = $this->getData();
|
||||
@@ -306,6 +311,7 @@ class userEntry extends Entry
|
||||
|
||||
if($this->config->edition == 'max')
|
||||
{
|
||||
$this->config->openMethods[] = 'my.risk';
|
||||
$control = $this->loadController('my', 'risk');
|
||||
$control->risk('createdBy', 0, 'id_desc', 0, $this->param('limit', 5), 1);
|
||||
$data = $this->getData();
|
||||
@@ -323,6 +329,7 @@ class userEntry extends Entry
|
||||
|
||||
if($this->config->edition == 'max')
|
||||
{
|
||||
$this->config->openMethods[] = 'my.myMeeting';
|
||||
$control = $this->loadController('my', 'myMeeting');
|
||||
$control->myMeeting('all', '', 'id_desc', 0, $this->param('limit', 5), 1);
|
||||
$data = $this->getData();
|
||||
@@ -375,14 +382,21 @@ class userEntry extends Entry
|
||||
$oldUser = $this->loadModel('user')->getByID($userID, 'id');
|
||||
|
||||
/* Set $_POST variables. */
|
||||
$fields = 'dept,realname,email,commiter,gender,role,mobile,phone,visions,groups';
|
||||
$fields = 'dept,realname,role,join,type,visions,mobile,phone,qq,dingding,weixin,skype,whatsapp,slack,address,address,email,commiter,gender,groups,passwordStrength,locked,fails,birthday';
|
||||
$this->batchSetPost($fields, $oldUser);
|
||||
$this->setPost('account', $oldUser->account);
|
||||
|
||||
if($this->request('gender') and !in_array($this->request('gender'), array('f', 'm'))) return $this->sendError(400, "The value of gendar must be 'f' or 'm'");
|
||||
$userGroups = $this->dao->select('`group`')->from(TABLE_USERGROUP)->where('account')->eq($oldUser->account)->fetchPairs('group', 'group');
|
||||
$this->setPost('groups', $this->request('groups', zget($_POST, 'groups', array_values($userGroups))));
|
||||
|
||||
$this->setPost('password1', $this->request('password', ''));
|
||||
$this->setPost('password2', $this->request('password', ''));
|
||||
$gender = $this->request('gender', zget($_POST, 'gender', 'f'));
|
||||
if(!in_array($gender, array('f', 'm'))) return $this->sendError(400, "The value of gender must be 'f' or 'm'");
|
||||
if($this->request('gender') and !in_array($this->request('gender'), array('f', 'm'))) return $this->sendError(400, "The value of gendar must be 'f' or 'm'");
|
||||
$this->setPost('gender', $gender);
|
||||
|
||||
$password = $this->request('password', zget($_POST, 'password', ''));
|
||||
$this->setPost('password1', md5($password));
|
||||
$this->setPost('password2', md5($password));
|
||||
$this->setPost('verifyPassword', md5($this->app->user->password . $this->app->session->rand));
|
||||
|
||||
$control = $this->loadController('user', 'edit');
|
||||
|
||||
@@ -55,21 +55,23 @@ class usersEntry extends entry
|
||||
*/
|
||||
public function post()
|
||||
{
|
||||
$fields = 'account,dept,realname,email,commiter,gender';
|
||||
$fields = 'type,dept,account,password,visions,realname,join,role,email,commiter,gender,group,passwordStrength';
|
||||
$this->batchSetPost($fields);
|
||||
|
||||
if(!in_array($this->request('gendar', 'f'), array('f', 'm'))) return $this->sendError(400, "The value of gendar must be 'f' or 'm'");
|
||||
if(!in_array($this->request('gendar', zget($_POST, 'gendar', 'f')), array('f', 'm'))) return $this->sendError(400, "The value of gendar must be 'f' or 'm'");
|
||||
|
||||
$password = $this->request('password', '') ? md5($this->request('password')) : '';
|
||||
$password = $this->request('password', zget($_POST, 'password', '')) ? md5($this->request('password', zget($_POST, 'password', ''))) : '';
|
||||
|
||||
$visions = $this->request('visions', array('rnd'));
|
||||
if(!is_array($visions)) $visions = explode(',', $visions);
|
||||
|
||||
if($this->request('group')) $this->setPost('group', explode(',', $this->request('group')));
|
||||
$this->setPost('password1', $password);
|
||||
$this->setPost('password2', $password);
|
||||
$this->setPost('passwordStrength', 3);
|
||||
$this->setPost('visions', $visions);
|
||||
$this->setPost('verifyPassword', md5($this->app->user->password . $this->app->session->rand));
|
||||
unset($_POST['password']);
|
||||
|
||||
$control = $this->loadController('user', 'create');
|
||||
$this->requireFields('account,password1,realname');
|
||||
|
||||
+8
-1
@@ -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');
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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!';
|
||||
|
||||
@@ -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!';
|
||||
|
||||
@@ -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 !";
|
||||
|
||||
@@ -69,8 +69,8 @@ $lang->admin->safe->modeList[0] = '不检查';
|
||||
$lang->admin->safe->modeList[1] = '中';
|
||||
$lang->admin->safe->modeList[2] = '强';
|
||||
|
||||
$lang->admin->safe->modeRuleList[1] = '6位以上,包含大小写字母,数字。';
|
||||
$lang->admin->safe->modeRuleList[2] = '10位以上,包含字母,数字,特殊字符。';
|
||||
$lang->admin->safe->modeRuleList[1] = '6位及以上,包含大小写字母,数字。';
|
||||
$lang->admin->safe->modeRuleList[2] = '10位及以上,包含字母,数字,特殊字符。';
|
||||
|
||||
$lang->admin->safe->reasonList['weak'] = '常用弱口令';
|
||||
$lang->admin->safe->reasonList['account'] = '与帐号相同';
|
||||
@@ -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 = '密码长度越长,含有大写字母或数字或特殊符号越多,密码字母越不重复,安全度越强!';
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+16
-3
@@ -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;
|
||||
@@ -2243,6 +2255,7 @@ class bugModel extends model
|
||||
}
|
||||
}
|
||||
|
||||
$this->app->loadLang('report');
|
||||
foreach($datas as $buildID => $data)
|
||||
{
|
||||
$data->name = isset($builds[$buildID]) ? $builds[$buildID] : $this->lang->report->undefined;
|
||||
@@ -3557,13 +3570,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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -245,14 +245,17 @@ class build extends control
|
||||
|
||||
/* Get stories and stages. */
|
||||
$storyPager = new pager($type == 'story' ? $recTotal : 0, $recPerPage, $type == 'story' ? $pageID : 1);
|
||||
$stories = $this->dao->select('t1.*, t2.stage')->from(TABLE_STORY)->alias('t1')
|
||||
->leftJoin(TABLE_STORYSTAGE)->alias('t2')->on('t1.id = t2.story')
|
||||
->where('t1.id')->in($build->stories)
|
||||
->andWhere('t1.deleted')->eq(0)
|
||||
->beginIF($type == 'story')->orderBy("t1.$orderBy")->fi()
|
||||
$stories = $this->dao->select('*')->from(TABLE_STORY)
|
||||
->where('id')->in($build->stories)
|
||||
->andWhere('deleted')->eq(0)
|
||||
->beginIF($type == 'story')->orderBy($orderBy)->fi()
|
||||
->page($storyPager)
|
||||
->fetchAll('id');
|
||||
|
||||
$stages = $this->dao->select('*')->from(TABLE_STORYSTAGE)->where('story')->in($build->stories)->andWhere('branch')->eq($build->branch)->fetchPairs('story', 'stage');
|
||||
foreach($stages as $storyID => $stage) $stories[$storyID]->stage = $stage;
|
||||
|
||||
|
||||
/* Set menu. */
|
||||
if($this->app->tab == 'project')
|
||||
{
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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,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;}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -49,6 +49,10 @@ $(function()
|
||||
}
|
||||
storyIdList += $(this).val() + ',';
|
||||
});
|
||||
|
||||
$('#type').val('').trigger("chosen:updated");
|
||||
$('#hourPointValue').val('');
|
||||
$('input[name^=fields]').prop('checked', true);
|
||||
});
|
||||
|
||||
$('#submit').click(function()
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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
-17
@@ -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))
|
||||
@@ -4367,26 +4369,33 @@ class executionModel extends model
|
||||
$spanClass = $execution->type == 'stage' ? 'label-warning' : 'label-info';
|
||||
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>';
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
<small><?php echo $lang->arrow . ' ' . $lang->execution->edit;?></small>
|
||||
</h2>
|
||||
</div>
|
||||
<?php echo html::hidden('project', 0);?>
|
||||
<form class='load-indicator main-form form-ajax' method='post' target='hiddenwin' id='dataform'>
|
||||
<table class='table table-form'>
|
||||
<?php if($config->systemMode == 'new' and isset($project)):?>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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;}
|
||||
|
||||
@@ -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();});
|
||||
})();
|
||||
|
||||
@@ -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,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;}
|
||||
|
||||
+15
-6
@@ -21,9 +21,18 @@ 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 .c-project {width: 100px}
|
||||
[lang^=en] #taskTable .assigned-title {width: 120px !important;}
|
||||
[lang^=de] #taskTable .c-name {width: 100px;}
|
||||
[lang^=de] #taskTable .c-project {width: 80px;}
|
||||
[lang^=de] #taskTable .c-date {width: 78px;}
|
||||
[lang^=de] #taskTable .assigned-title {width: 123px !important;}
|
||||
[lang^=de] #taskTable .c-user {width: 118px;}
|
||||
[lang^=de] #taskTable .c-hours {width: 86px;}
|
||||
[lang^=de] #taskTable .c-user-short {width: 75px;}
|
||||
[lang^=fr] #taskTable .c-name {width: 120px;}
|
||||
[lang^=fr] #taskTable .c-project {width: 100px;}
|
||||
[lang^=fr] #taskTable .c-date {width: 91px;}
|
||||
[lang^=fr] #taskTable .assigned-title {width: 130px !important;}
|
||||
[lang^=fr] #taskTable .c-user-short {width: 75px;}
|
||||
[lang^=fr] #taskTable .c-status {width: 71px;}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
<?php endif;?>
|
||||
<td class="text-center <?php echo isset($task->delay) ? 'delayed' : '';?>"><?php if(substr($task->deadline, 0, 4) > 0) echo substr($task->deadline, 5, 6);?></td>
|
||||
<?php if($type != 'assignedTo'): ?>
|
||||
<td class="c-assignedTo has-btn"> <?php $this->task->printAssignedHtml($task, $users);?></td>
|
||||
<td class="c-assignedTo has-btn" title="<?php echo zget($users, $task->assignedTo);?>"> <?php $this->task->printAssignedHtml($task, $users);?></td>
|
||||
<?php endif;?>
|
||||
<?php if($type != 'finishedBy'): ?>
|
||||
<td class='c-user'><?php echo zget($users, $task->finishedBy);?></td>
|
||||
@@ -196,7 +196,7 @@
|
||||
<?php endif;?>
|
||||
<td class="text-center <?php echo isset($child->delay) ? 'delayed' : '';?>"><?php if(substr($child->deadline, 0, 4) > 0) echo substr($child->deadline, 5, 6);?></td>
|
||||
<?php if($type != 'assignedTo'): ?>
|
||||
<td class="c-assignedTo has-btn"> <?php $this->task->printAssignedHtml($child, $users);?></td>
|
||||
<td class="c-assignedTo has-btn" title="<?php echo zget($users, $child->assignedTo);?>"> <?php $this->task->printAssignedHtml($child, $users);?></td>
|
||||
<?php endif;?>
|
||||
<?php if($type != 'finishedBy'): ?>
|
||||
<td class='c-user'><?php echo zget($users, $child->finishedBy);?></td>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
@@ -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 = '';
|
||||
}
|
||||
|
||||
@@ -17,14 +17,16 @@ $insert = $this->session->insert;
|
||||
?>
|
||||
<style>
|
||||
form{overflow-x: scroll}
|
||||
#maxImport:focus {outline: none;}
|
||||
.c-pri{width:100px}
|
||||
.c-estimate, .c-severity, .c-openedBuild, .c-title{width:150px !important;}
|
||||
#showData > thead > tr > th{min-width:150px !important;}
|
||||
.c-story{width:150px;}
|
||||
.c-team {width:100px; padding:0px 0px 8px 0px !important;}
|
||||
.c-estimate-1 {width:50px;padding:0px 0px 8px 8px !important;}
|
||||
</style>
|
||||
<?php if(!empty($suhosinInfo)):?>
|
||||
<div class='alert alert-info'><?php echo $suhosinInfo?></div>
|
||||
<?php die;?>
|
||||
<?php elseif(empty($maxImport) and $allCount > $this->config->file->maxImport):?>
|
||||
<div id="mainContent" class="main-content">
|
||||
<div class="main-header">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php include $app->getModuleRoot() . 'common/view/header.lite.html.php';?>
|
||||
<style>input[type=file]:focus, input[type=checkbox]:focus, input[type=radio]:focus {outline: none;}</style>
|
||||
<main>
|
||||
<div class="container">
|
||||
<div id="mainContent" class='main-content'>
|
||||
|
||||
@@ -704,49 +704,6 @@ class program extends control
|
||||
echo $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax get budget left.
|
||||
*
|
||||
* @param int $programID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetBudgetLeft($programID)
|
||||
{
|
||||
$program = $this->program->getByID($programID);
|
||||
$budgetLeft = $this->program->getBudgetLeft($program);
|
||||
echo number_format($budgetLeft, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax get available budget.
|
||||
*
|
||||
* @param int $programID
|
||||
* @param int $selectedProgramID
|
||||
* @param int $budget
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetAvailableBudget($programID, $selectedProgramID, $budget)
|
||||
{
|
||||
if(!empty($programID))
|
||||
{
|
||||
$program = $this->program->getByID($programID);
|
||||
$selectedProgram = $this->program->getByID($selectedProgramID);
|
||||
$budgetLeft = $this->program->getBudgetLeft($selectedProgram);
|
||||
$availableBudget = $program->parent == $selectedProgramID ? $budgetLeft + $program->budget : $budgetLeft;
|
||||
}
|
||||
else
|
||||
{
|
||||
$selectedProgram = $this->program->getByID($selectedProgramID);
|
||||
$availableBudget = $this->program->getBudgetLeft($selectedProgram);
|
||||
}
|
||||
|
||||
$tips = '';
|
||||
if($budget != 0 && $budget !== null && $budget > $availableBudget) $tips = "<span id='beyondBudgetTip' class='text-remind'>" . $this->lang->program->budgetOverrun . zget($this->lang->project->currencySymbol, $selectedProgram->budgetUnit) . $availableBudget . "</span>";
|
||||
echo json_encode($tips);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update program order.
|
||||
*
|
||||
|
||||
@@ -14,6 +14,7 @@ tbody.sortable > tr > td.sort-handler {color: #3c4353 !important;}
|
||||
|
||||
.has-suffix > a {max-width: calc(100% - 100px); padding-right: 5px; color: #0c60e1; display: inline-block; max-width: calc(100% - 50px);}
|
||||
|
||||
div.checkbox-primary + span.table-nest-icon {margin-left:0px !important;}
|
||||
div.checkbox-primary + span.table-nest-icon {margin-left: 0px !important;}
|
||||
#checkAll + label.hover:after {border-width: 0px;}
|
||||
.c-budget {width:100px; text-align: right; padding-right:16px !important;}
|
||||
.c-status {width: 65px !important;}
|
||||
+118
-4
@@ -93,6 +93,7 @@ function computeWorkDays(currentID)
|
||||
{
|
||||
computeEndDate();
|
||||
}
|
||||
outOfDateTip();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,6 +112,7 @@ function computeEndDate(delta)
|
||||
if(delta == 999)
|
||||
{
|
||||
$('#end').val(longTime);
|
||||
outOfDateTip();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -294,15 +296,18 @@ $(function()
|
||||
*/
|
||||
function setBudgetTipsAndAclList(parentID)
|
||||
{
|
||||
var selectedProgramID = $('#parent').val();
|
||||
|
||||
if(parentID != 0)
|
||||
{
|
||||
$.get(createLink('program', 'ajaxGetBudgetLeft', "ProgramID=" + parentID), function(budgetLeft)
|
||||
$.get(createLink('project', 'ajaxGetObjectInfo', "objectType=program&objectID=" + parentID + "&selectedProgramID=" + selectedProgramID), function(data)
|
||||
{
|
||||
var data = JSON.parse(data);
|
||||
parentProgram = programList[parentID];
|
||||
programBudget = parentProgram.budget;
|
||||
PGMBudgetUnit = currencySymbol[parentProgram.budgetUnit];
|
||||
|
||||
budgetNotes = programBudget != 0 ? (PGMParentBudget + PGMBudgetUnit + budgetLeft) : '';
|
||||
budgetNotes = programBudget != 0 ? (PGMParentBudget + PGMBudgetUnit + data.availableBudget) : '';
|
||||
$('#budget').attr('placeholder', budgetNotes);
|
||||
});
|
||||
$('.aclBox').html($('#subPGMAcl').html());
|
||||
@@ -315,6 +320,113 @@ function setBudgetTipsAndAclList(parentID)
|
||||
|
||||
if(typeof(programID) == 'undefined') programID = 0;
|
||||
budgetOverrunTips();
|
||||
outOfDateTip();
|
||||
}
|
||||
|
||||
/**
|
||||
* compare childlish date.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function compareChildDate()
|
||||
{
|
||||
if(page == 'create') return;
|
||||
|
||||
var end = $('#end').val();
|
||||
var begin = $('#begin').val();
|
||||
var selectedProgramID = $('#parent').val();
|
||||
if($('#dateTip').length > 0) $('#dateTip').remove();
|
||||
|
||||
if(end == longTime) end = LONG_TIME;
|
||||
if(end.length > 0 && begin.length > 0)
|
||||
{
|
||||
var programEnd = new Date(end);
|
||||
var programBegin = new Date(begin);
|
||||
|
||||
$.get(createLink('project', 'ajaxGetObjectInfo', 'objectType=program&objectID=' + programID + '&selectedProgramID=' + selectedProgramID), function(data)
|
||||
{
|
||||
var childInfo = JSON.parse(data);
|
||||
if(childInfo.maxChildEnd == '' || childInfo.minChildBegin == '') return;
|
||||
|
||||
var childBegin = new Date(childInfo.minChildBegin);
|
||||
var childEnd = new Date(childInfo.maxChildEnd);
|
||||
if(programBegin <= childBegin && programEnd >= childEnd) return;
|
||||
|
||||
var dateTip = '';
|
||||
if(programBegin > childBegin && programEnd >= childEnd)
|
||||
{
|
||||
dateTip = "<span id='dateTip' class='text-remind'>" + beginGreateChild + childInfo.minChildBegin + "</span>";
|
||||
}
|
||||
else if(programEnd < childEnd && programBegin <= childBegin)
|
||||
{
|
||||
dateTip = "<span id='dateTip' class='text-remind'>" + endLetterChild + childInfo.maxChildEnd + "</span>";
|
||||
}
|
||||
else
|
||||
{
|
||||
dateTip = "<span id='dateTip' class='text-remind'>" + dateExceedChild + childInfo.minChildBegin + "~" + childInfo.maxChildEnd + "</span>";
|
||||
}
|
||||
|
||||
$('#dateBox').after(dateTip);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The date is out of the range of the parent project set, and a prompt is given.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function outOfDateTip()
|
||||
{
|
||||
var end = $('#end').val();
|
||||
var begin = $('#begin').val();
|
||||
if($('#dateTip').length > 0) $('#dateTip').remove();
|
||||
|
||||
if(end == longTime) end = LONG_TIME;
|
||||
if(end.length > 0 && begin.length > 0)
|
||||
{
|
||||
var selectedProgramID = $('#parent').val();
|
||||
var programEnd = new Date(end);
|
||||
var programBegin = new Date(begin);
|
||||
|
||||
if(selectedProgramID == 0)
|
||||
{
|
||||
compareChildDate();
|
||||
return;
|
||||
}
|
||||
|
||||
if(typeof(programID) == 'undefined') programID = 0;
|
||||
$.get(createLink('project', 'ajaxGetObjectInfo', 'objectType=program&objectID=' + programID + "&selectedProgramID=" + selectedProgramID), function(data)
|
||||
{
|
||||
var dateTip = '';
|
||||
var data = JSON.parse(data);
|
||||
var parentEnd = new Date(data.selectedProgramEnd);
|
||||
var parentBegin = new Date(data.selectedProgramBegin);
|
||||
|
||||
if(programBegin >= parentBegin && programEnd <= parentEnd)
|
||||
{
|
||||
compareChildDate();
|
||||
return;
|
||||
}
|
||||
|
||||
if(programBegin < parentBegin && programEnd <= parentEnd && programEnd >= parentBegin)
|
||||
{
|
||||
dateTip = "<span id='dateTip' class='text-remind'>" + beginLetterParent + data.selectedProgramBegin + "</span>";
|
||||
}
|
||||
else if(programEnd > parentEnd && programBegin >= parentBegin && programBegin <= parentEnd)
|
||||
{
|
||||
dateTip = "<span id='dateTip' class='text-remind'>" + endGreaterParent + data.selectedProgramEnd + "</span>";
|
||||
}
|
||||
else
|
||||
{
|
||||
dateTip = "<span id='dateTip' class='text-remind'>" + dateExceedParent + data.selectedProgramBegin + "~" + data.selectedProgramEnd + "</span>";
|
||||
}
|
||||
|
||||
$('#dateBox').after(dateTip);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,11 +446,13 @@ function budgetOverrunTips()
|
||||
}
|
||||
|
||||
if(typeof(programID) == 'undefined') programID = 0;
|
||||
$.get(createLink('program', 'ajaxGetAvailableBudget', 'programID=' + programID + "&selectedProgramID=" + selectedProgramID + "&budget=" + budget), function(data)
|
||||
$.get(createLink('project', 'ajaxGetObjectInfo', 'objectType=program&objectID=' + programID + "&selectedProgramID=" + selectedProgramID), function(data)
|
||||
{
|
||||
var data = JSON.parse(data);
|
||||
|
||||
var tip = "";
|
||||
if(budget !=0 && budget !== null && budget > data.availableBudget) var tip = "<span id='beyondBudgetTip' class='text-remind'>" + budgetOverrun + currencySymbol[data.budgetUnit] + data.availableBudget + "</span>"
|
||||
if($('#beyondBudgetTip').length > 0) $('#beyondBudgetTip').remove();
|
||||
$('#budgetBox').after(data);
|
||||
$('#budgetBox').after(tip);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -100,10 +100,12 @@ $lang->program->noProgram = 'No program.';
|
||||
$lang->program->showClosed = 'Closed programs.';
|
||||
$lang->program->tips = 'If a parent program is selected, the products under the parent program can be associated. If no program is selected for the project, a product with the same name as the project is created and associated with the project by default.';
|
||||
$lang->program->confirmBatchUnlink = "Do you want to batch unlink these stakeholders?";
|
||||
$lang->program->beginLetterParent = 'The start date of the program should be ≥ the start date of the parent program: %s.';
|
||||
$lang->program->endGreaterParent = 'The finish date of the program should be ≤ the finish date of the parent program: %s.';
|
||||
$lang->program->beginGreateChild = 'The start date of the parent program should be ≤the minimum start time of the %s: %s.';
|
||||
$lang->program->endLetterChild = 'The finish time of the parent program should be ≥ the maximum finish time of the %s: %s.';
|
||||
$lang->program->beginLetterParent = 'The start date of the program was < the start date of the parent program:';
|
||||
$lang->program->endGreaterParent = 'The finish date of the program was > the finish date of the parent program:';
|
||||
$lang->program->dateExceedParent = 'The start and finish date of the program was > the start and finish date of the parent program:';
|
||||
$lang->program->beginGreateChild = 'The start date of the program was > the minimum start date of the subprogram or project:';
|
||||
$lang->program->endLetterChild = 'The finish date of the program was < the maximum finish date of the subprogram or project:';
|
||||
$lang->program->dateLetterChild = 'The start and finish date of the program no longer include the date scope of the subprogram or project:';
|
||||
$lang->program->closeErrorMessage = 'There are subprograms or projects that are not closed';
|
||||
$lang->program->hasChildren = 'It has child programs or projects. You cannot delete it.';
|
||||
$lang->program->hasProduct = 'It has products. You cannot delete it.';
|
||||
|
||||
@@ -100,10 +100,12 @@ $lang->program->noProgram = 'No program.';
|
||||
$lang->program->showClosed = 'Closed';
|
||||
$lang->program->tips = 'If a parent program is selected, the products under the parent program can be associated. If no program is selected for the project, a product with the same name as the project is created and associated with the project by default.';
|
||||
$lang->program->confirmBatchUnlink = "Do you want to batch unlink these stakeholders?";
|
||||
$lang->program->beginLetterParent = 'The start date of the program should be ≥ the start date of the parent program: %s.';
|
||||
$lang->program->endGreaterParent = 'The finish date of the program should be ≤ the finish date of the parent program: %s.';
|
||||
$lang->program->beginGreateChild = 'The start date of the parent program should be ≤the minimum start time of the %s: %s.';
|
||||
$lang->program->endLetterChild = 'The finish time of the parent program should be ≥ the maximum finish time of the %s: %s.';
|
||||
$lang->program->beginLetterParent = 'The start date of the program was < the start date of the parent program:';
|
||||
$lang->program->endGreaterParent = 'The finish date of the program was > the finish date of the parent program:';
|
||||
$lang->program->dateExceedParent = 'The start and finish date of the program was > the start and finish date of the parent program:';
|
||||
$lang->program->beginGreateChild = 'The start date of the program was > the minimum start date of the subprogram or project:';
|
||||
$lang->program->endLetterChild = 'The finish date of the program was < the maximum finish date of the subprogram or project:';
|
||||
$lang->program->dateLetterChild = 'The start and finish date of the program no longer include the date scope of the subprogram or project:';
|
||||
$lang->program->closeErrorMessage = 'There are subprograms or projects that are not closed';
|
||||
$lang->program->hasChildren = 'The program has a child program or the project exists and can not be deleted.';
|
||||
$lang->program->hasProduct = 'The program has products exist and can not be deleted.';
|
||||
|
||||
@@ -100,10 +100,12 @@ $lang->program->noProgram = 'No program.';
|
||||
$lang->program->showClosed = 'Closed programs.';
|
||||
$lang->program->tips = 'If a parent program is selected, the products under the parent program can be associated. If no program is selected for the project, a product with the same name as the project is created and associated with the project by default.';
|
||||
$lang->program->confirmBatchUnlink = "Do you want to batch unlink these stakeholders?";
|
||||
$lang->program->beginLetterParent = 'La date de début du programme doit être ≥ à la date de début du programme parent: %s.';
|
||||
$lang->program->endGreaterParent = 'La date de fin du programme doit être ≤ à la date de fin du programme parent: %s.';
|
||||
$lang->program->beginGreateChild = 'La date de début du programme parent doit être ≤ à la date de début minimum du %s: %s.';
|
||||
$lang->program->endLetterChild = 'Le temps de fin du programme parent doit être ≥ au temps de fin maximum du %s: %s.';
|
||||
$lang->program->beginLetterParent = 'La date de début du programme était < à la date de début du programme parent:';
|
||||
$lang->program->endGreaterParent = 'La date de fin du programme était > à la date de fin du programme parent:';
|
||||
$lang->program->dateExceedParent = 'La date de début et de fin du programme était > à la date de début et de fin du programme parent:';
|
||||
$lang->program->beginGreateChild = 'La date de début du programme était > à la date minimale de début du sous-programme ou du projet:';
|
||||
$lang->program->endLetterChild = 'La date de fin du programme était < à la de fin maximale du sous-programme ou du projet:';
|
||||
$lang->program->dateLetterChild = 'La date de début et de fin du programme ne correspond plus la date du sous-programme ou du projet:';
|
||||
$lang->program->closeErrorMessage = 'There are subprograms or projects that are not closed';
|
||||
$lang->program->hasChildren = 'It has child programs or projects. You cannot delete it.';
|
||||
$lang->program->hasProduct = 'It has products. You cannot delete it.';
|
||||
|
||||
@@ -100,10 +100,12 @@ $lang->program->noProgram = '暂时没有项目集';
|
||||
$lang->program->showClosed = '显示已关闭';
|
||||
$lang->program->tips = '选择了父项目集,则可关联该父项目集下的产品。如果项目未选择任何项目集,则系统会默认创建一个和该项目同名的产品并关联该项目。';
|
||||
$lang->program->confirmBatchUnlink = "您确定要批量移除这些干系人吗?";
|
||||
$lang->program->beginLetterParent = '项目集开始日期应大于等于父项目集的开始日期:%s。';
|
||||
$lang->program->endGreaterParent = '项目集完成日期应小于等于父项目集的完成日期:%s。';
|
||||
$lang->program->beginGreateChild = '父项目集的开始日期应小于等于%s的最小开始时间:%s。';
|
||||
$lang->program->endLetterChild = '父项目集的完成时间应大于等于%s的最大完成时间:%s。';
|
||||
$lang->program->beginLetterParent = '项目集的开始日期已小于父项目集的开始日期:';
|
||||
$lang->program->endGreaterParent = '项目集的完成日期已大于父项目集的完成日期:';
|
||||
$lang->program->dateExceedParent = '项目集的起止日期已超出父项目集的起止日期';
|
||||
$lang->program->beginGreateChild = '项目集的开始日期已大于子项目集或项目的最小开始日期:';
|
||||
$lang->program->endLetterChild = '项目集的完成日期已小于子项目集或项目的最大完成日期:';
|
||||
$lang->program->dateExceedChild = '项目集的起止日期已不包含子项目集或项目的日期范围';
|
||||
$lang->program->closeErrorMessage = '存在子项目集或项目为未关闭状态';
|
||||
$lang->program->hasChildren = '该项目集有子项目集或项目存在,不能删除。';
|
||||
$lang->program->hasProduct = '该项目集有产品存在,不能删除。';
|
||||
|
||||
@@ -35,10 +35,18 @@
|
||||
<?php js::set('holders', $lang->execution->placeholder);?>
|
||||
<?php js::set('errorSameProducts', $lang->project->errorSameProducts);?>
|
||||
<?php js::set('longTime', $lang->program->longTime);?>
|
||||
<?php js::set('LONG_TIME', LONG_TIME);?>
|
||||
<?php js::set('currencySymbol', $lang->project->currencySymbol);?>
|
||||
<?php js::set('PGMParentBudget', $lang->program->parentBudget);?>
|
||||
<?php js::set('future', $lang->project->future);?>
|
||||
<?php js::set('programList', $programList);?>
|
||||
<?php js::set('budgetOverrun', $lang->project->budgetOverrun);?>
|
||||
<?php js::set('currencySymbol', $lang->project->currencySymbol)?>
|
||||
<?php js::set('parentBudget', $lang->program->parentBudget);?>
|
||||
<?php js::set('beginLetterParent', $lang->program->beginLetterParent);?>
|
||||
<?php js::set('endGreaterParent', $lang->program->endGreaterParent);?>
|
||||
<?php js::set('dateExceedParent', $lang->program->dateExceedParent);?>
|
||||
<?php js::set('page', $this->app->getMethodName());?>
|
||||
<?php $aclList = $parentProgram ? $lang->program->subAclList : $lang->program->aclList;?>
|
||||
<?php $requiredFields = $config->program->create->requiredFields;?>
|
||||
<div id='mainContent' class='main-content'>
|
||||
@@ -90,10 +98,10 @@
|
||||
<tr>
|
||||
<th id="dateRange"><?php echo $lang->project->dateRange;?></th>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<div id='dateBox' class='input-group'>
|
||||
<?php echo html::input('begin', date('Y-m-d'), "class='form-control form-date' onchange='computeWorkDays();' placeholder='" . $lang->project->begin . "' required");?>
|
||||
<span class='input-group-addon'><?php echo $lang->project->to;?></span>
|
||||
<?php echo html::input('end', '', "class='form-control form-date' placeholder='" . $lang->project->end . "' required");?>
|
||||
<?php echo html::input('end', '', "class='form-control form-date' onchange='outOfDateTip();' placeholder='" . $lang->project->end . "' required");?>
|
||||
</div>
|
||||
</td>
|
||||
<td id="endList" colspan='2'><?php echo html::radio('delta', $lang->program->endList, '', "onclick='computeEndDate(this.value)'");?></td>
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
?>
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php include '../../common/view/kindeditor.html.php';?>
|
||||
<?php js::set('LONG_TIME', LONG_TIME);?>
|
||||
<?php js::set('page', $this->app->getMethodName());?>
|
||||
<?php js::set('weekend', $config->execution->weekend);?>
|
||||
<?php js::set('longTime', $lang->program->longTime);?>
|
||||
<?php js::set('currencySymbol', $lang->project->currencySymbol);?>
|
||||
@@ -25,6 +27,15 @@
|
||||
<?php js::set('exRateNum', sprintf($lang->error->float, $lang->program->exchangeRate));?>
|
||||
<?php js::set('exRateNotNegative', $lang->program->exRateNotNegative);?>
|
||||
<?php js::set('programID', $program->id);?>
|
||||
<?php js::set('budgetOverrun', $lang->project->budgetOverrun);?>
|
||||
<?php js::set('currencySymbol', $lang->project->currencySymbol)?>
|
||||
<?php js::set('parentBudget', $lang->program->parentBudget);?>
|
||||
<?php js::set('beginLetterParent', $lang->program->beginLetterParent);?>
|
||||
<?php js::set('endGreaterParent', $lang->program->endGreaterParent);?>
|
||||
<?php js::set('dateExceedParent', $lang->program->dateExceedParent);?>
|
||||
<?php js::set('beginGreateChild', $lang->program->beginGreateChild);?>
|
||||
<?php js::set('endLetterChild', $lang->program->endLetterChild);?>
|
||||
<?php js::set('dateExceedChild', $lang->program->dateExceedChild);?>
|
||||
<?php $aclList = $program->parent ? $lang->program->subAclList : $lang->program->aclList;?>
|
||||
<?php $requiredFields = $config->program->edit->requiredFields;?>
|
||||
<div id='mainContent' class='main-content'>
|
||||
@@ -73,12 +84,12 @@
|
||||
<tr>
|
||||
<th id="dateRange"><?php echo $lang->project->dateRange;?></th>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<?php echo html::input('begin', $program->begin, "class='form-control form-date' placeholder='" . $lang->project->begin . "' required");?>
|
||||
<div id='dateBox' class='input-group'>
|
||||
<?php echo html::input('begin', $program->begin, "class='form-control form-date' onchange='outOfDateTip();' placeholder='" . $lang->project->begin . "' required");?>
|
||||
<span class='input-group-addon'><?php echo $lang->project->to;?></span>
|
||||
<?php
|
||||
$end = $program->end == LONG_TIME ? $lang->program->longTime : $program->end;
|
||||
echo html::input('end', $end, "class='form-control form-date' placeholder='" . $lang->project->end . "' required");
|
||||
echo html::input('end', $end, "class='form-control form-date' onchange='outOfDateTip();' placeholder='" . $lang->project->end . "' required");
|
||||
?>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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')
|
||||
@@ -96,6 +101,11 @@ class programplan extends control
|
||||
if(strpos($selectCustom, 'date') !== false) $dateDetails = 0;
|
||||
|
||||
$plans = $this->programplan->getDataForGanttGroupByAssignedTo($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 == 'lists')
|
||||
|
||||
@@ -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.';
|
||||
|
||||
@@ -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.';
|
||||
|
||||
@@ -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.';
|
||||
|
||||
@@ -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 = '"计划完成时间"必须大于"计划开始时间"';
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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§ion=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,23 @@ $(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: 80});
|
||||
if(showFields.indexOf('realEnd') != -1) gantt.config.columns.push({name: 'realEnd', align: 'center', resize: true, width: 80});
|
||||
if(showFields.indexOf('consumed') != -1) gantt.config.columns.push({name: 'consumed', align: 'center', resize: false, width: 60});
|
||||
|
||||
endField = gantt.config.columns.pop();
|
||||
endField.resize = false;
|
||||
gantt.config.columns.push(endField);
|
||||
|
||||
gantt.locale.labels.column_text = <?php echo json_encode($typeHtml);?>;
|
||||
gantt.locale.labels.column_owner_id = "<?php echo $lang->programplan->PMAB;?>";
|
||||
@@ -684,7 +688,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()
|
||||
|
||||
+29
-19
@@ -220,37 +220,47 @@ class project extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax get available budget.
|
||||
* Ajax: Get selected object's information.
|
||||
*
|
||||
* @param int $programID
|
||||
* @param str $objectType
|
||||
* @param int $objectID
|
||||
* @param int $selectedProgramID
|
||||
* @param int $budget
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxGetAvailableBudget($projectID, $selectedProgramID, $budget)
|
||||
public function ajaxGetObjectInfo($objectType, $objectID, $selectedProgramID)
|
||||
{
|
||||
if(!empty($projectID))
|
||||
{
|
||||
$project = $this->project->getByID($projectID);
|
||||
$selectedProgram = $this->loadModel('program')->getByID($selectedProgramID);
|
||||
$budgetLeft = $this->program->getBudgetLeft($selectedProgram);
|
||||
$availableBudget = $project->parent == $selectedProgramID ? $budgetLeft + $project->budget : $budgetLeft;
|
||||
}
|
||||
else
|
||||
if($selectedProgramID)
|
||||
{
|
||||
$selectedProgram = $this->loadModel('program')->getByID($selectedProgramID);
|
||||
$availableBudget = $this->program->getBudgetLeft($selectedProgram);
|
||||
if($selectedProgram->budget) $availableBudget = $this->program->getBudgetLeft($selectedProgram);
|
||||
}
|
||||
|
||||
$tip = '';
|
||||
if($budget != 0 && $budget !== null && $budget > $availableBudget) $tip = "<span id='beyondBudgetTip' class='text-remind'>" . $this->lang->project->budgetOverrun . zget($this->lang->project->currencySymbol, $selectedProgram->budgetUnit) . $availableBudget . "</span>";
|
||||
if(!empty($objectID))
|
||||
{
|
||||
$object = $objectType == 'project' ? $this->project->getByID($objectID) : $this->loadModel('program')->getByID($objectID);
|
||||
|
||||
$placeholder = '';
|
||||
if($selectedProgram and $selectedProgram->budget != 0) $placeholder = $this->lang->project->parentBudget . zget($this->lang->project->currencySymbol, $selectedProgram->budgetUnit) . $availableBudget;
|
||||
if(isset($availableBudget)) $availableBudget = $object->parent == $selectedProgramID ? $availableBudget + $object->budget : $availableBudget;
|
||||
|
||||
$tipList = array('tip' => $tip, 'placeholder' => $placeholder);
|
||||
echo json_encode($tipList);
|
||||
if($objectType == 'program')
|
||||
{
|
||||
$minChildBegin = $this->dao->select('begin as minBegin')->from(TABLE_PROGRAM)->where('id')->ne($objectID)->andWhere('deleted')->eq(0)->andWhere('path')->like("%,{$objectID},%")->orderBy('begin_asc')->fetch('minBegin');
|
||||
$maxChildEnd = $this->dao->select('end as maxEnd')->from(TABLE_PROGRAM)->where('id')->ne($objectID)->andWhere('deleted')->eq(0)->andWhere('path')->like("%,{$objectID},%")->andWhere('end')->ne('0000-00-00')->orderBy('end_desc')->fetch('maxEnd');
|
||||
}
|
||||
}
|
||||
|
||||
$data = array();
|
||||
if(isset($selectedProgram))
|
||||
{
|
||||
$data['selectedProgramBegin'] = $selectedProgram->begin;
|
||||
$data['selectedProgramEnd'] = $selectedProgram->end;
|
||||
$data['budgetUnit'] = $selectedProgram->budgetUnit;
|
||||
}
|
||||
if(isset($availableBudget)) $data['availableBudget'] = $availableBudget;
|
||||
if(isset($minChildBegin)) $data['minChildBegin'] = $minChildBegin;
|
||||
if(isset($maxChildEnd)) $data['maxChildEnd'] = $maxChildEnd;
|
||||
|
||||
echo json_encode($data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;}
|
||||
|
||||
+59
-32
@@ -95,6 +95,7 @@ function computeWorkDays(currentID)
|
||||
{
|
||||
computeEndDate();
|
||||
}
|
||||
outOfDateTip();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,6 +116,7 @@ function computeEndDate(delta)
|
||||
$('#end').val(longTime).trigger('mousedown');
|
||||
$('#daysBox').addClass('hidden');
|
||||
$('#days').val(0).trigger('mousedown');
|
||||
outOfDateTip();
|
||||
return false;
|
||||
}
|
||||
$('#daysBox').removeClass('hidden');
|
||||
@@ -297,35 +299,6 @@ $(function()
|
||||
});
|
||||
})
|
||||
|
||||
/**
|
||||
* Set budget tips and acl list.
|
||||
*
|
||||
* @param int $parentProgramID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function setBudgetTipsAndAclList(programID)
|
||||
{
|
||||
if(programID != 0)
|
||||
{
|
||||
$.get(createLink('project', 'ajaxGetBudgetLeft', "programID=" + programID), function(budgetLeft)
|
||||
{
|
||||
parentProgram = PGMList[programID];
|
||||
projectBudget = parentProgram.budget;
|
||||
PGMBudgetUnit = currencySymbol[parentProgram.budgetUnit];
|
||||
|
||||
budgetNotes = projectBudget != 0 ? (PGMParentBudget + PGMBudgetUnit + budgetLeft) : '';
|
||||
$('#budget').attr('placeholder', budgetNotes);
|
||||
});
|
||||
$('.aclBox').html($('#subPGMAcl').html());
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#budget').removeAttr('placeholder');
|
||||
$('.aclBox').html($('#PGMAcl').html());
|
||||
}
|
||||
}
|
||||
|
||||
$(document).on('change', "#plansBox select[name^='plans']", function()
|
||||
{
|
||||
var $plan = $(this);
|
||||
@@ -365,14 +338,68 @@ function budgetOverrunTips()
|
||||
}
|
||||
|
||||
if(typeof(projectID) == 'undefined') projectID = 0;
|
||||
$.get(createLink('project', 'ajaxGetAvailableBudget', 'projectID=' + projectID + "&selectedProgramID=" + selectedProgramID + "&budget=" + budget), function(data)
|
||||
$.get(createLink('project', 'ajaxGetObjectInfo', 'objectType=project&objectID=' + projectID + "&selectedProgramID=" + selectedProgramID), function(data)
|
||||
{
|
||||
var data = JSON.parse(data);
|
||||
if(typeof(data.availableBudget) == 'undefined') return;
|
||||
|
||||
var tip = "";
|
||||
if(budget != 0 && budget !== null && budget > data.availableBudget) tip = "<span id='beyondBudgetTip' class='text-remind'>" + budgetOverrun + currencySymbol[data.budgetUnit] + data.availableBudget.toFixed(2) + "</span>"
|
||||
if($('#beyondBudgetTip').length > 0) $('#beyondBudgetTip').remove();
|
||||
$('#budgetBox').after(data.tip);
|
||||
$('#budgetBox').after(tip);
|
||||
|
||||
var placeholder = '';
|
||||
if(selectedProgramID) placeholder = parentBudget + currencySymbol[data.budgetUnit] + data.availableBudget.toFixed(2);
|
||||
if($('#budget').attr('placeholder')) $('#budget').removeAttr('placeholder')
|
||||
$('#budget').attr('placeholder', data.placeholder);
|
||||
$('#budget').attr('placeholder', placeholder);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*The date is out of the range of the parent project set, and a prompt is given.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
function outOfDateTip()
|
||||
{
|
||||
var end = $('#end').val();
|
||||
var begin = $('#begin').val();
|
||||
if($('#dateTip').length > 0) $('#dateTip').remove();
|
||||
|
||||
if(end == longTime) end = LONG_TIME;
|
||||
if(end.length > 0 && begin.length > 0)
|
||||
{
|
||||
var selectedProgramID = $('#parent').val();
|
||||
|
||||
if(selectedProgramID == 0) return;
|
||||
|
||||
if(typeof(projectID) == 'undefined') projectID = 0;
|
||||
$.get(createLink('project', 'ajaxGetObjectInfo', 'objectType=project&objectID=' + projectID + '&selectedProgramID=' + selectedProgramID), function(data)
|
||||
{
|
||||
var data = JSON.parse(data);
|
||||
var parentEnd = new Date(data.selectedProgramEnd);
|
||||
var parentBegin = new Date(data.selectedProgramBegin);
|
||||
var projectEnd = new Date(end);
|
||||
var projectBegin = new Date(begin);
|
||||
|
||||
if(projectBegin >= parentBegin && projectEnd <= parentEnd) return;
|
||||
|
||||
var dateTip = "";
|
||||
if(projectBegin < parentBegin && projectEnd <= parentEnd && projectEnd >= parentBegin)
|
||||
{
|
||||
dateTip = "<span id='dateTip' class='text-remind'>" + beginLetterParent + data.selectedProgramBegin + "</span>";
|
||||
}
|
||||
else if(projectEnd > parentEnd && projectBegin >= parentBegin && projectBegin <= parentEnd)
|
||||
{
|
||||
dateTip = "<span id='dateTip' class='text-remind'>" + endGreaterParent + data.selectedProgramEnd + "</span>";
|
||||
}
|
||||
else
|
||||
{
|
||||
dateTip = "<span id='dateTip' class='text-remind'>" + dateExceedParent + data.selectedProgramBegin + "~" + data.selectedProgramEnd + "</span>";
|
||||
}
|
||||
|
||||
$('#dateBox').after(dateTip);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ $(function()
|
||||
{
|
||||
var programID = $(this).val();
|
||||
setAclList(programID);
|
||||
budgetOverrunTips();
|
||||
|
||||
/* Determine whether the project can change the project set. */
|
||||
link = createLink('project', 'ajaxCheckProduct', 'programID=' + programID + '&projectID=' + projectID);
|
||||
@@ -58,6 +57,9 @@ $(function()
|
||||
|
||||
if(!changed) $("#parent").val(oldParent).trigger("chosen:updated");
|
||||
oldParent = $('#parent').val();
|
||||
|
||||
budgetOverrunTips();
|
||||
outOfDateTip();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -320,9 +320,10 @@ $lang->project->confirmDelete = "Do you want to delete [%s]?";
|
||||
$lang->project->cannotChangeToCat = "It is not empty, so you cannot change it to a parent.";
|
||||
$lang->project->cannotCancelCat = "It has child projects, so you cannot unmark the parent.";
|
||||
$lang->project->parentBeginEnd = "Parent begin&end date: %s ~ %s";
|
||||
$lang->project->parentBudget = "The budget of the parent project: ";
|
||||
$lang->project->beginLetterParent = "The begin date of the parent project: %s. It cannot be < the begin date of its parent project.";
|
||||
$lang->project->endGreaterParent = "The end date of the parent project: %s. It cannot be > the end date of its parent project.";
|
||||
$lang->project->parentBudget = "The budget of the parent program: ";
|
||||
$lang->project->beginLetterParent = "The start date of the project was < the minimum start date of the parent program:";
|
||||
$lang->project->endGreaterParent = "The finish date of the project was > the maximum finish date of the parent program:";
|
||||
$lang->project->dateExceedParent = "The start and finish date of the project was > the start and finish date of the parent program:";
|
||||
$lang->project->beginGreateChild = 'The start date of the project should be ≥ the start date of program: %s.';
|
||||
$lang->project->endLetterChild = 'The finish date of the project should be ≤ the finish date of program: %s.';
|
||||
$lang->project->begigLetterExecution = 'The start date of project should be ≤ the minimum start date of the execution: %s.';
|
||||
|
||||
@@ -320,9 +320,10 @@ $lang->project->confirmDelete = 'Do you want to delete \"%s\"?';
|
||||
$lang->project->cannotChangeToCat = "The project has contents, so you cannot it to a parent project.";
|
||||
$lang->project->cannotCancelCat = "There are child projects of this project. You cannot cancel the parent project mark.";
|
||||
$lang->project->parentBeginEnd = "The begin and end date of the parent project: %s ~ %s";
|
||||
$lang->project->parentBudget = "The budget of the parent project: ";
|
||||
$lang->project->beginLetterParent = "The begin date of the parent project: %s. It cannot be < the begin date of its parent project.";
|
||||
$lang->project->endGreaterParent = "The end date of the parent project: %s. It cannot be > the end date of its parent project.";
|
||||
$lang->project->parentBudget = "The budget of the parent program: ";
|
||||
$lang->project->beginLetterParent = "The start date of the project was < the minimum start date of the parent program:";
|
||||
$lang->project->endGreaterParent = "The finish date of the project was > the maximum finish date of the parent program:";
|
||||
$lang->project->dateExceedParent = "The start and finish date of the project was > the start and finish date of the parent program:";
|
||||
$lang->project->beginGreateChild = 'The start date of the project should be ≥ the start date of program: %s.';
|
||||
$lang->project->endLetterChild = 'The finish date of the project should be ≤ the finish date of program: %s.';
|
||||
$lang->project->begigLetterExecution = 'The start date of project should be ≤ the minimum start date of the execution: %s.';
|
||||
|
||||
@@ -321,8 +321,9 @@ $lang->project->cannotChangeToCat = "It is not empty, so you cannot change it
|
||||
$lang->project->cannotCancelCat = "It has child projects, so you cannot unmark the parent.";
|
||||
$lang->project->parentBeginEnd = "Parent begin&end date: %s ~ %s";
|
||||
$lang->project->parentBudget = "The budget of the parent project: ";
|
||||
$lang->project->beginLetterParent = "The begin date of the parent project: %s. It cannot be < the begin date of its parent project.";
|
||||
$lang->project->endGreaterParent = "The end date of the parent project: %s. It cannot be > the end date of its parent project.";
|
||||
$lang->project->beginLetterParent = "La date de début du projet était < à la date minimale de début du programme parent:";
|
||||
$lang->project->endGreaterParent = "La date de fin du projet était > à la date de fin maximale du programme parent:";
|
||||
$lang->project->dateExceedParent = "La date de début et de fin du project était > à la date de début et de fin du programme parent:";
|
||||
$lang->project->beginGreateChild = 'La date de début du projets "%s" doit être ≥ à la date de début du programme "%s" : %s.';
|
||||
$lang->project->endLetterChild = 'La date de fin du projets doit être ≤ à la date de fin du programme: %s.';
|
||||
$lang->project->begigLetterExecution = 'La date de début du projet "%s" doit être ≤ à la date de début minimum d\'excution: %s';
|
||||
|
||||
@@ -320,9 +320,10 @@ $lang->project->confirmDelete = '您确定删除项目“%s”吗?';
|
||||
$lang->project->cannotChangeToCat = "该项目已经有实际的内容,无法修改为父项目";
|
||||
$lang->project->cannotCancelCat = "该项目下已经有子项目,无法取消父项目标记";
|
||||
$lang->project->parentBeginEnd = "父项目起止时间:%s ~ %s";
|
||||
$lang->project->parentBudget = "父项目预算:";
|
||||
$lang->project->beginLetterParent = "父项目的开始日期:%s,开始日期不能小于父项目的开始日期";
|
||||
$lang->project->endGreaterParent = "父项目的完成日期:%s,完成日期不能大于父项目的完成日期";
|
||||
$lang->project->parentBudget = "父项目集预算:";
|
||||
$lang->project->beginLetterParent = "项目的开始日期已小于父项目集的最小开始日期:";
|
||||
$lang->project->endGreaterParent = "项目的完成日期已大于父项目集的最大完成日期:";
|
||||
$lang->project->dateExceedParent = "项目的起止日期已超出父项目集的起止日期:";
|
||||
$lang->project->beginGreateChild = '项目的开始日期应大于等于项目集的最小开始日期:%s';
|
||||
$lang->project->endLetterChild = '项目的完成日期应小于等于项目集的最大完成日期:%s';
|
||||
$lang->project->begigLetterExecution = '项目的开始日期应小于等于执行的最小开始日期:%s';
|
||||
|
||||
@@ -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']))
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<?php include '../../common/view/header.html.php';?>
|
||||
<?php include '../../common/view/kindeditor.html.php';?>
|
||||
<?php js::import($jsRoot . 'misc/date.js');?>
|
||||
<?php js::set('LONG_TIME', LONG_TIME);?>
|
||||
<?php js::set('model', $model);?>
|
||||
<?php js::set('programID', $programID);?>
|
||||
<?php js::set('copyProjectID', $copyProjectID);?>
|
||||
@@ -26,6 +27,12 @@
|
||||
<?php js::set('selectedBranchID', $branchID);?>
|
||||
<?php js::set('productName', $lang->product->name);?>
|
||||
<?php js::set('manageProducts', $lang->project->manageProducts);?>
|
||||
<?php js::set('budgetOverrun', $lang->project->budgetOverrun);?>
|
||||
<?php js::set('currencySymbol', $lang->project->currencySymbol)?>
|
||||
<?php js::set('parentBudget', $lang->project->parentBudget);?>
|
||||
<?php js::set('beginLetterParent', $lang->project->beginLetterParent);?>
|
||||
<?php js::set('endGreaterParent', $lang->project->endGreaterParent);?>
|
||||
<?php js::set('dateExceedParent', $lang->project->dateExceedParent);?>
|
||||
<?php $requiredFields = $config->project->create->requiredFields;?>
|
||||
<?php js::set('requiredFields', $requiredFields);?>
|
||||
<div id='mainContent' class='main-content'>
|
||||
@@ -38,7 +45,7 @@
|
||||
<?php if($config->edition != 'max' || $model == 'kanban'):?>
|
||||
<button type='button' class='btn btn-link' data-toggle='modal' data-target='#copyProjectModal'><?php echo html::icon($lang->icons['copy'], 'muted') . ' ' . $lang->project->copy;?></button>
|
||||
<?php else: ?>
|
||||
<button type='button' class='btn btn-link' data-toggle='modal' data-target='#maxCopyProjectModal'><?php echo html::icon($lang->icons['copy'], 'muted') . ' ' . $lang->project->copy;?></button>
|
||||
<button type='button' class='btn btn-link open-btn' data-toggle='modal' data-target='#maxCopyProjectModal'><?php echo html::icon($lang->icons['copy'], 'muted') . ' ' . $lang->project->copy;?></button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
@@ -93,7 +100,7 @@
|
||||
<tr>
|
||||
<th id="dateRange"><?php echo $lang->project->dateRange;?></th>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<div id='dateBox' class='input-group'>
|
||||
<?php echo html::input('begin', date('Y-m-d'), "class='form-control form-date' onchange='computeWorkDays();' placeholder='" . $lang->project->begin . "' required");?>
|
||||
<span class='input-group-addon'><?php echo $lang->project->to;?></span>
|
||||
<?php echo html::input('end', '', "class='form-control form-date' onchange='computeWorkDays();' placeholder='" . $lang->project->end . "' required");?>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<?php include '../../common/view/kindeditor.html.php';?>
|
||||
<?php js::import($jsRoot . 'misc/date.js');?>
|
||||
<?php js::set('weekend', $config->execution->weekend);?>
|
||||
<?php js::set('LONG_TIME', LONG_TIME);?>
|
||||
<?php js::set('errorSameProducts', $lang->project->errorSameProducts);?>
|
||||
<?php js::set('errorSameBranches', $lang->project->errorSameBranches);?>
|
||||
<?php js::set('errorSamePlans', $lang->project->errorSamePlans);?>
|
||||
@@ -30,6 +31,12 @@
|
||||
<?php $requiredFields = $config->project->edit->requiredFields;?>
|
||||
<?php js::set('requiredFields', $requiredFields);?>
|
||||
<?php js::set('budget', $project->budget);?>
|
||||
<?php js::set('budgetOverrun', $lang->project->budgetOverrun);?>
|
||||
<?php js::set('currencySymbol', $lang->project->currencySymbol)?>
|
||||
<?php js::set('parentBudget', $lang->project->parentBudget);?>
|
||||
<?php js::set('beginLetterParent', $lang->project->beginLetterParent);?>
|
||||
<?php js::set('endGreaterParent', $lang->project->endGreaterParent);?>
|
||||
<?php js::set('dateExceedParent', $lang->project->dateExceedParent);?>
|
||||
<div id='mainContent' class='main-content'>
|
||||
<div class='center-block'>
|
||||
<div class='main-header'>
|
||||
@@ -95,7 +102,7 @@
|
||||
<tr>
|
||||
<th id="dateRange"><?php echo $lang->project->dateRange;?></th>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<div id='dateBox' class='input-group'>
|
||||
<?php echo html::input('begin', $project->begin, "class='form-control form-date' onchange='computeWorkDays();' placeholder='" . $lang->project->begin . "' required");?>
|
||||
<span class='input-group-addon'><?php echo $lang->project->to;?></span>
|
||||
<?php
|
||||
|
||||
@@ -231,14 +231,17 @@ class projectrelease extends control
|
||||
}
|
||||
|
||||
$storyPager = new pager($type == 'story' ? $recTotal : 0, $recPerPage, $type == 'story' ? $pageID : 1);
|
||||
$stories = $this->dao->select('t1.*, t2.stage')->from(TABLE_STORY)->alias('t1')
|
||||
->leftJoin(TABLE_STORYSTAGE)->alias('t2')->on('t1.id = t2.story')
|
||||
->where('t1.id')->in($release->stories)
|
||||
->andWhere('t1.deleted')->eq(0)
|
||||
->beginIF($type == 'story')->orderBy("t1.$orderBy")->fi()
|
||||
$stories = $this->dao->select('*')->from(TABLE_STORY)
|
||||
->where('id')->in($release->stories)
|
||||
->andWhere('deleted')->eq(0)
|
||||
->beginIF($type == 'story')->orderBy($orderBy)->fi()
|
||||
->page($storyPager)
|
||||
->fetchAll('id');
|
||||
|
||||
$stages = $this->dao->select('*')->from(TABLE_STORYSTAGE)->where('story')->in($release->stories)->andWhere('branch')->eq($release->branch)->fetchPairs('story', 'stage');
|
||||
foreach($stages as $storyID => $stage) $stories[$storyID]->stage = $stage;
|
||||
|
||||
|
||||
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story');
|
||||
|
||||
$bugPager = new pager($type == 'bug' ? $recTotal : 0, $recPerPage, $type == 'bug' ? $pageID : 1);
|
||||
|
||||
@@ -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 : ';
|
||||
|
||||
|
||||
@@ -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 : ';
|
||||
|
||||
|
||||
@@ -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 : ';
|
||||
|
||||
|
||||
@@ -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 = '版本库地址:';
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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';?>
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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')
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ include '../../common/view/chosen.html.php';
|
||||
$formId = 'searchForm-' . uniqid('');
|
||||
?>
|
||||
<style>
|
||||
.btn-active-text .text {font-weight: 400; font-size: 14px;}
|
||||
#save-query .text {font-weight: 400; font-size: 14px;}
|
||||
#selectPeriod {padding: 4px 0; height: 197px; min-width: 120px}
|
||||
#selectPeriod > .dropdown-header {background: #f1f1f1; display: block; text-align: center; padding: 4px 0; line-height: 20px; margin: 5px 10px; font-size: 14px; border-radius: 2px; color: #333; font-size: 12px}
|
||||
#groupAndOr {display: inline-block;}
|
||||
|
||||
@@ -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> ";
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ $config->story->datatable->fieldList['estimate']['required'] = 'no';
|
||||
|
||||
$config->story->datatable->fieldList['stage']['title'] = 'stageAB';
|
||||
$config->story->datatable->fieldList['stage']['fixed'] = 'no';
|
||||
$config->story->datatable->fieldList['stage']['width'] = '80';
|
||||
$config->story->datatable->fieldList['stage']['width'] = '85';
|
||||
$config->story->datatable->fieldList['stage']['required'] = 'no';
|
||||
|
||||
$config->story->datatable->fieldList['openedBy']['title'] = 'openedByAB';
|
||||
|
||||
@@ -13,10 +13,13 @@ select[id^="story"] + .picker-single {width: 130px; max-width: 130px;}
|
||||
.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;}
|
||||
#batchToTaskForm .c-id {width: 30px;}
|
||||
#batchToTaskForm .c-name, #batchToTaskForm .c-desc {width: 150px;}
|
||||
#batchToTaskForm .c-story {width: 200px;}
|
||||
#batchToTaskForm .c-assigned {width: 125px;}
|
||||
#batchToTaskForm .c-date {width: 105px;}
|
||||
#batchToTaskForm .c-pri {width: 65px;}
|
||||
#batchToTaskForm .c-actions, #batchToTaskForm .c-estimate {width: 60px;}
|
||||
#batchToTaskForm .input-group-addon {padding: 5px 6px;}
|
||||
[lang^=de] #batchToTaskForm .c-date {width: 120px;}
|
||||
[lang^=de] #batchToTaskForm .c-estimate {width: 65px;}
|
||||
|
||||
@@ -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
@@ -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>';
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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值为空
|
||||
@@ -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
Reference in New Issue
Block a user