This commit is contained in:
holan20180123
2021-08-18 17:23:30 +08:00
55 changed files with 175 additions and 161 deletions
+1 -1
View File
@@ -1345,7 +1345,7 @@ INSERT INTO `zt_group` (`id`, `name`, `role`, `desc`) VALUES
(10, 'OTHERS', 'others', 'for others.'),
(11, 'guest', 'guest', 'For guest'),
(12, 'LIMITED', 'limited', 'For limited user'),
(13, '项目管理员', 'projectAdmin', '项目管理员可以维护项目的权限');
(13, 'Project Admin', 'projectAdmin', 'Project Admins manage project privileges');
INSERT INTO `zt_grouppriv` (`group`, `module`, `method`) VALUES
(1,'action','editComment'),
+1 -1
View File
@@ -843,7 +843,7 @@ function getWebRoot($full = false)
/**
* 当数组/对象变量$var存在$key项时,返回存在的对应值或设定值,否则返回$key或不存在的设定值。
* When there is a $key in the array/object $var, it returns it or $valueWhenExists, otherwise returns $key or $valueWhenNone.
* When the $var has the $key, return it, else result one default value.
*
* @param array|object $var
* @param string|int $key
+10 -9
View File
@@ -151,30 +151,32 @@ class gitlab
}
/**
* Get branch
* Get branches.
*
* @access public
* @return array
*/
public function branch()
{
$branches = array();
$api = "branches";
/* Max size of per_page in gitlab API is 100. */
$params = array();
$params['per_page'] = '100';
$branches = array();
for($page = 1; true; $page ++)
{
$params['page'] = $page;
$list = $this->fetch($api, $params);
if(empty($list)) break;
$branchList = $this->fetch("branches", $params);
if(empty($branchList)) break;
foreach($list as $branch)
foreach($branchList as $branch)
{
if(!isset($branch->name)) continue;
$branches[$branch->name] = $branch->name;
}
if(count($list) < $params['per_page']) break;
/* Last page. */
if(count($branchList) < $params['per_page']) break;
}
if(empty($branches)) $branches['master'] = 'master';
@@ -523,7 +525,6 @@ class gitlab
if(!scm::checkRevision($version)) return array();
$api = "commits";
/* TODO Put getCommits into cron job. And check best size of $count. */
if(empty($count)) $count = 10;
$params = array();
+1 -2
View File
@@ -23,8 +23,7 @@ $lang->action->action = 'Action';
$lang->action->actionID = 'Action ID';
$lang->action->date = 'Date';
$lang->action->extra = 'Extra';
$lang->action->system = 'System';
$lang->action->system = 'System';
$lang->action->trash = 'Recycle';
$lang->action->undelete = 'Restore';
+1 -2
View File
@@ -23,8 +23,7 @@ $lang->action->action = '动作';
$lang->action->actionID = '记录ID';
$lang->action->date = '日期';
$lang->action->extra = '附加值';
$lang->action->system = '系统';
$lang->action->system = '系统';
$lang->action->trash = '回收站';
$lang->action->undelete = '还原';
+1 -2
View File
@@ -23,8 +23,7 @@ $lang->action->action = '動作';
$lang->action->actionID = '記錄ID';
$lang->action->date = '日期';
$lang->action->extra = '附加值';
$lang->action->system = '系統';
$lang->action->system = '系統';
$lang->action->trash = '資源回收筒';
$lang->action->undelete = '還原';
+4 -5
View File
@@ -1108,25 +1108,24 @@ class actionModel extends model
$method = $this->config->action->assetViewMethod[$action->objectType];
}
$action->objectLink = helper::createLink('assetlib', $method, sprintf($vars, $action->objectID), '', '', $projectID);
$action->objectLink = helper::createLink('assetlib', $method, sprintf($vars, $action->objectID));
}
else
{
if($action->objectType == 'doclib')
{
$docLib = $this->dao->select('type,product,project,execution,deleted')->from(TABLE_DOCLIB)->where('id')->eq($action->objectID)->fetch();
$docLib->type = $docLib->type == 'execution' ? 'project' : $docLib->type;
$docLib->objectID = strpos('product,project', $docLib->type) !== false ? $docLib->{$docLib->type} : 0;
$docLib->objectID = strpos('product,project,execution', $docLib->type) !== false ? $docLib->{$docLib->type} : 0;
$appendLib = $docLib->deleted == '1' ? $action->objectID : 0;
$action->objectLink = helper::createLink('doc', 'objectLibs', sprintf($vars, $docLib->type, $docLib->objectID, $action->objectID, $appendLib));
}
elseif($action->objectType == 'user')
{
$action->objectLink = !isset($deptUsers[$action->objectID]) ? 'javascript:void(0)' : helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID), '', '', $projectID);
$action->objectLink = !isset($deptUsers[$action->objectID]) ? 'javascript:void(0)' : helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID));
}
else
{
$action->objectLink = helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID), '', '', $projectID);
$action->objectLink = helper::createLink($moduleName, $methodName, sprintf($vars, $action->objectID));
}
}
$action->objectLabel = $objectLabel;
+3 -2
View File
@@ -55,7 +55,7 @@ class bug extends control
if($this->app->openApp == 'project')
{
$objectID = $this->session->project;
$products = $this->loadModel('project')->getProducts($objectID, false);
$products = $this->loadModel('project')->getProducts($objectID, false);
}
elseif($this->app->openApp == 'execution')
{
@@ -735,13 +735,14 @@ class bug extends control
if($this->app->openApp == 'project') $this->loadModel('project')->setMenu($bug->project);
if($this->app->openApp == 'execution') $this->loadModel('execution')->setMenu($bug->execution);
if($this->app->openApp == 'qa') $this->qa->setMenu($this->products, $bug->product, $bug->branch);
if($this->app->openApp == 'devops')
{
session_write_close();
$repos = $this->loadModel('repo')->getRepoPairs($bug->project);
$this->repo->setMenu($repos);
$this->lang->navGroup->bug = 'devops';
}
if($this->app->openApp == 'product')
{
$this->loadModel('product')->setMenu($bug->product);
+5 -2
View File
@@ -285,7 +285,7 @@ class bugModel extends model
public function createBugFromGitlabIssue($bug, $executionID)
{
$bug->openedBy = $this->app->user->account;
$bug->openedDate = helper::now(); // TODO(dingguodong) use from issue->created_at ?
$bug->openedDate = helper::now();
$bug->assignedDate = isset($bug->assignedTo) ? helper::now() : 0;
$bug->openedBuild = 'trunk';
$bug->story = 0;
@@ -1818,7 +1818,10 @@ class bugModel extends model
$bugSteps .= $this->lang->bug->tplExpect;
}
return array('title' => $title, 'steps' => $bugSteps, 'storyID' => $run->case->story, 'moduleID' => $run->case->module, 'version' => $run->case->version);
if(!empty($run->task)) $testtask = $this->loadModel('testtask')->getById($run->task);
$executionID = isset($testtask->execution) ? $testtask->execution : 0;
return array('title' => $title, 'steps' => $bugSteps, 'storyID' => $run->case->story, 'moduleID' => $run->case->module, 'version' => $run->case->version, 'executionID' => $executionID);
}
/**
+4 -1
View File
@@ -123,7 +123,10 @@ class ci extends control
$caseResult = $post->funcResult;
$firstCase = array_shift($caseResult);
$productID = $firstCase->productId;
if(empty($productID) and !empty($firstCase->id)) $productID = $this->dao->select('product')->from(TABLE_CASE)->where('id')->eq((int)$firstCase->id)->fetch('product');
if(empty($productID) and !empty($firstCase->id))
{
$productID = $this->dao->findById($firstCase->id)->from(TABLE_CASE)->fetch('product');
}
}
if(empty($productID)) die(json_encode(array('result' => 'fail', 'message' => 'productID is not found')));
+6 -6
View File
@@ -36,8 +36,8 @@ $lang->help = 'Help';
$lang->aboutZenTao = 'About';
$lang->profile = 'Profile';
$lang->changePassword = 'Password';
$lang->unfoldMenu = 'Unfold Menu';
$lang->collapseMenu = 'Collapse Menu';
$lang->unfoldMenu = 'Unfold';
$lang->collapseMenu = 'Collapse';
$lang->preference = 'Preference';
$lang->runInfo = "<div class='row'><div class='u-1 a-center' id='debugbar'>Time %s MS, Memory %s KB, Query %s. </div></div>";
$lang->agreement = "I have read and agreed to the terms and conditions of <a href='http://zpl.pub/page/zplv12.html' target='_blank'> Z PUBLIC LICENSE 1.2 </a>. <span class='text-danger'>Without authorization, I should not remove, hide or cover any logos/links of ZenTao.</span>";
@@ -86,8 +86,8 @@ $lang->importSuccess = 'Saved';
$lang->fail = 'Fail';
$lang->addFiles = 'Added Files';
$lang->files = 'Files ';
$lang->pasteText = 'Multi-lines Paste';
$lang->uploadImages = 'Multi-images Upload';
$lang->pasteText = 'Multi-line Paste';
$lang->uploadImages = 'Multi-image Upload';
$lang->timeout = 'Timeout. Check your newtwork connections, or try it again!';
$lang->repairTable = 'Database table might be damaged. Run phpmyadmin or myisamchk to fix it.';
$lang->duplicate = '%s has the same title as a file existed.';
@@ -144,7 +144,7 @@ $lang->admin->common = 'Admin';
$lang->task->common = 'Task';
$lang->bug->common = 'Bug';
$lang->testcase->common = 'Testcase';
$lang->testtask->common = 'Testtask';
$lang->testtask->common = 'Request';
$lang->score->common = 'Score';
$lang->build->common = 'Build';
$lang->testreport->common = 'Report';
@@ -185,7 +185,7 @@ $lang->track = 'Track';
$lang->settings = 'Settings';
$lang->overview = 'Overview';
$lang->module = 'Module';
$lang->priv = 'Priv Group';
$lang->priv = 'Privilege';
$lang->design = 'Design';
$lang->other = 'Other';
$lang->estimation = 'Estimation';
+7 -7
View File
@@ -567,9 +567,9 @@ class commonModel extends model
$menuOrder = $lang->mainNav->menuOrder;
ksort($menuOrder);
$items = array();
$lastItem = end($menuOrder);
$divider = false;
$items = array();
$lastItem = end($menuOrder);
$printDivider = false;
foreach($menuOrder as $key => $group)
{
@@ -577,11 +577,11 @@ class commonModel extends model
list($title, $currentModule, $currentMethod, $vars) = explode('|', $nav);
/* When last divider is not used in mainNav, use it next menu. */
$divider = ($divider || ($lastItem != $key) && strpos($lang->dividerMenu, ",{$group},") !== false) ? true : false;
if($divider and !empty($items))
$printDivider = ($printDivider || ($lastItem != $key) && strpos($lang->dividerMenu, ",{$group},") !== false) ? true : false;
if($printDivider and !empty($items))
{
$items[] = 'divider';
$divider = false;
$items[] = 'divider';
$printDivider = false;
}
/**
+1 -1
View File
@@ -1020,7 +1020,7 @@ class doc extends control
{
list($libs, $libID, $object, $objectID) = $this->doc->setMenuByType($type, $objectID, $libID);
$libID = empty($libID) ? 0 : $libID;
$libID = (int)$libID;
$moduleTree = $type == 'book' ? $this->doc->getBookStructure($libID) : $this->doc->getTreeMenu($type, $objectID, $libID);
+2 -2
View File
@@ -98,7 +98,7 @@ $lang->doc->libName = 'Document Library';
$lang->doc->libType = 'Category';
$lang->doc->custom = 'Custom Document Library';
$lang->doc->customAB = 'Custom Doc Lib';
$lang->doc->createLib = 'Create Document Library';
$lang->doc->createLib = 'Document Library';
$lang->doc->allLibs = 'Library List';
$lang->doc->objectLibs = "{$lang->productCommon}/{$lang->executionCommon} Libraries";
$lang->doc->showFiles = 'Attachments';
@@ -108,7 +108,7 @@ $lang->doc->fixedMenu = 'Fix to Menu';
$lang->doc->removeMenu = 'Remove from Menu';
$lang->doc->search = 'Search';
$lang->doc->allCollections = 'All Collections';
$lang->doc->keywordsTips = 'Please use commas to separate multiple keywords.';
$lang->doc->keywordsTips = 'Please use commas to separate keywords.';
global $config;
/* Query condition list. */
+1 -1
View File
@@ -1238,7 +1238,7 @@ class docModel extends model
$orderedExecutions = array();
foreach($executions as $id => $execution)
{
$execution->name = zget($projectPairs, $execution->project) . '/' . $execution->name;
$execution->name = zget($projectPairs, $execution->project) . ' / ' . $execution->name;
if($execution->status != 'done' and $execution->status != 'closed' and $execution->PM == $this->app->user->account)
{
+8 -6
View File
@@ -195,9 +195,13 @@ class entryModel extends model
$detail->url = helper::createLink('user', 'profile', "userID={$user->id}");
if($user->avatar != "")
{
$detail->avatar = common::getSysURL() . $user->avatar;
}
else
{
$detail->avatar = "https://www.gravatar.com/avatar/" . md5($user->account) . "?d=identicon&s=80";
}
return $detail;
}
@@ -212,11 +216,10 @@ class entryModel extends model
*/
public function getAssignees($objectType, $object)
{
$users = $this->dao
->select('account')->from(TABLE_TEAM)
->where('type')->eq($objectType)
->andWhere('root')->eq($object->id)
->fetchAll();
$users = $this->dao->select('account')->from(TABLE_TEAM)
->where('type')->eq($objectType)
->andWhere('root')->eq($object->id)
->fetchAll();
if($users)
{
@@ -230,5 +233,4 @@ class entryModel extends model
return ($object->assignedTo == "" or $object->assignedTo == "closed") ? array() : array($this->getUser($object->assignedTo));
}
}
-2
View File
@@ -25,8 +25,6 @@ $config->execution->customBatchEditFields = 'days,type,teamname,status,desc,PO,Q
$config->execution->custom = new stdclass();
$config->execution->custom->batchEditFields = 'days,status,PM';
$config->execution->skipCreate = array('computeburn', 'ajaxgetdropmenu', 'executionkanban', 'ajaxgetteammembers');
$config->execution->editor = new stdclass();
$config->execution->editor->create = array('id' => 'desc', 'tools' => 'simpleTools');
$config->execution->editor->edit = array('id' => 'desc', 'tools' => 'simpleTools');
+4 -3
View File
@@ -41,7 +41,8 @@ class execution extends control
$this->loadModel('project');
$this->executions = $this->execution->getPairs(0, 'all', 'nocode');
if(!in_array($this->methodName, $this->config->execution->skipCreate) and $this->app->openApp == 'execution')
$skipCreateStep = array('computeburn', 'ajaxgetdropmenu', 'executionkanban', 'ajaxgetteammembers');
if(!in_array($this->methodName, $skipCreateStep) and $this->app->openApp == 'execution')
{
if(!$this->executions and $this->methodName != 'index' and $this->methodName != 'create' and $this->app->getViewType() != 'mhtml') $this->locate($this->createLink('execution', 'create'));
}
@@ -2286,7 +2287,7 @@ class execution extends control
$currentMembers = $this->execution->getTeamMembers($executionID);
$members2Import = $this->execution->getMembers2Import($team2Import, array_keys($currentMembers));
$teams2Import = $this->loadModel('personnel')->getCopyObjects($executionID, 'sprint');
$teams2Import = $this->loadModel('personnel')->getCopiedObjects($executionID, 'sprint');
$teams2Import = array('' => '') + $teams2Import;
/* Append users for get users. */
@@ -2665,7 +2666,7 @@ class execution extends control
if($this->config->systemMode == 'new')
{
$type = $this->dao->findById($objectID)->from(TABLE_PROJECT)->fetch('type');
$type = $type == 'project' ? $type : 'execution';
if($type != 'project') $type = 'execution';
}
$users = $this->loadModel('user')->getPairs('nodeleted|noclosed');
+4
View File
@@ -1 +1,5 @@
#product_chosen .chosen-single {width: 180px;}
td.flex {display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center;}
td.flex span.label-badge {margin-left: 5px; min-width: 50px;}
td.flex span.project-type-label {margin-left: 5px; min-width: 36px;}
+2 -1
View File
@@ -22,7 +22,8 @@
.board-title {padding-right: 20px;}
.board-actions {position: absolute; right: 3px; top: 3px;}
.board-actions.nav > li > a {padding: 3px 3px;}
#kanban {overflow-y: auto; min-height:350px;}
#kanban {overflow-y: auto; min-height: 350px;}
#kanban > .table {min-width: 1100px; table-layout: auto;}
#kanban.dragging .boards.dragging .board {background: #eee; opacity: .35; border-color: #f1f1f1;}
#kanban thead > tr > th {padding-left: 0; padding-right: 0;}
+3 -3
View File
@@ -33,9 +33,9 @@ $(function()
/* Assign value to the manage products by the different request type.*/
var product = $('#products0');
if(copyExecutionID) productID = product.val();
$(product).val(productID);
$(product).trigger("chosen:updated");
loadBranches($(product));
product.val(productID);
product.trigger("chosen:updated");
loadBranches(product);
var adjustMainCol = function()
{
+7 -6
View File
@@ -1299,15 +1299,15 @@ class executionModel extends model
{
$link = helper::createLink('repo', 'browse', "repoID=0&branchID=&executionID=%s");
}
elseif($module == 'doc')
{
$link = helper::createLink('doc', $method, "type=execution&objectID=%s&from=execution");
}
else
{
$link = helper::createLink($module, $method, "executionID=%s");
}
if($module == 'doc')
{
$link = helper::createLink('doc', $method, "type=execution&objectID=%s&from=execution");
}
return $link;
}
@@ -2444,7 +2444,7 @@ class executionModel extends model
}
/**
* Get the project and execution the team through the projectID.
* Get team of the project and its executions by projectID.
*
* @param int $projectID
* @access public
@@ -2454,8 +2454,9 @@ class executionModel extends model
{
$teams = $this->dao->select('id,team,type')->from(TABLE_PROJECT)
->where('deleted')->eq(0)
->andWhere('project')->eq($projectID)
->andWhere('(project')->eq($projectID)
->orWhere('id')->eq($projectID)
->markRight(1)
->fetchAll('id');
if(empty($teams)) return array();
+2 -2
View File
@@ -90,12 +90,12 @@ td.hours {text-align: right; overflow: hidden; text-overflow: ellipsis; white-sp
<?php endif;?>
<?php printf('%03d', $execution->id);?>
</td>
<td class='text-left <?php if(!empty($execution->children)) echo 'has-child';?>' title='<?php echo $execution->name?>'>
<td class='text-left <?php if(!empty($execution->children)) echo 'has-child';?> flex' title='<?php echo $execution->name?>'>
<?php if(isset($this->config->maxVersion)):?>
<span class='project-type-label label label-outline <?php echo $execution->type == 'sprint' ? 'label-info' : 'label-warning';?>'><?php echo $lang->execution->typeList[$execution->type]?></span>
<?php endif;?>
<?php
echo !empty($execution->children) ? $execution->name : html::a($this->createLink('execution', 'task', 'execution=' . $execution->id), $execution->name);
echo !empty($execution->children) ? $execution->name : html::a($this->createLink('execution', 'task', 'execution=' . $execution->id), $execution->name, '', "class='text-ellipsis'");
if(isset($execution->delay)) echo "<span class='label label-danger label-badge'>{$lang->execution->delayed}</span> ";
?>
<?php if(!empty($execution->children)):?>
-1
View File
@@ -623,7 +623,6 @@ class gitlabModel extends model
*/
public function apiGetIssues($gitlabID, $projectID, $options = null)
{
/* TODO(dingguodong) not pagination yet. */
if($options)
{
$url = sprintf($this->getApiRoot($gitlabID), "/projects/{$projectID}/issues") . '&per_page=20' . $options;
+2 -2
View File
@@ -1,7 +1,7 @@
<?php
$lang->index->common = 'Home';
$lang->index->index = 'Home';
$lang->index->pleaseInput = 'Please input';
$lang->index->pleaseInput = 'Enter';
$lang->index->search = 'Search';
$lang->index->app = new stdClass();
@@ -14,4 +14,4 @@ $lang->index->upgradeNow = 'Upgrade now';
$lang->index->upgrade = 'Upgrade';
$lang->index->log = 'Log';
$lang->index->detailed = 'Details';
$lang->index->website = 'Please visit the official website';
$lang->index->website = 'Visit ZenTao official website';
+1 -1
View File
@@ -168,7 +168,7 @@ class messageModel extends model
{
/* Get notifiy persons. */
$notifyPersons = array();
if(!empty($toList->notify)) $notifyPersons = $this->loadModel('release')->getNotifyPersons($object->notify, $object->product, $object->build);
if(!empty($object->notify)) $notifyPersons = $this->loadModel('release')->getNotifyPersons($object->notify, $object->product, $object->build);
foreach($notifyPersons as $account)
{
+2 -2
View File
@@ -19,7 +19,7 @@ $lang->misc->zentao->labels['about'] = 'About ZenTao';
$lang->misc->zentao->labels['support'] = 'Tech Support';
$lang->misc->zentao->labels['cowin'] = 'Help Us';
$lang->misc->zentao->labels['service'] = 'Service';
$lang->misc->zentao->labels['others'] = 'EasyCorp Products';
$lang->misc->zentao->labels['others'] = 'From EasyCorp';
$lang->misc->zentao->icons['about'] = 'group';
$lang->misc->zentao->icons['support'] = 'question-sign';
@@ -69,7 +69,7 @@ $lang->misc->tableName = "Table Name";
$lang->misc->tableStatus = "Status";
$lang->misc->novice = "New to ZenTao? Do you want to start ZenTao Tutorial?";
$lang->misc->showAnnual = 'Add Annual Summary';
$lang->misc->annualDesc = 'After version 12.0, the Annual Summary can be viewed on 『Report->Annual Summary』 page. <a href="%s" target="_blank" id="showAnnual" class="btn btn-mini btn-primary">See now</a>.';
$lang->misc->annualDesc = 'After version 12.0, Annual Summary can be viewed on 『Report->Annual Summary』 page. <a href="%s" target="_blank" id="showAnnual" class="btn btn-mini btn-primary">See now</a>.';
$lang->misc->remind = 'New feature reminders';
$lang->misc->noticeRepair = "<h5>If you are not Administrator, contact your ZenTao Administrator to repair tables.</h5>
+1 -1
View File
@@ -202,7 +202,7 @@ class personnel extends control
$this->view->objectID = $objectID;
$this->view->objectType = $objectType;
$this->view->objectName = $objectName;
$this->view->objects = array('' => '') + $this->personnel->getCopyObjects($objectID, $objectType);
$this->view->objects = array('' => '') + $this->personnel->getCopiedObjects($objectID, $objectType);
$this->view->module = $module;
$this->view->deptID = $deptID;
$this->view->appendUsers = $appendUsers;
+2 -2
View File
@@ -457,14 +457,14 @@ class personnelModel extends model
}
/**
* Get objects to copy whitelist.
* Get objects to copy.
*
* @param int $objectID
* @param int $objectType
* @access public
* @return array
*/
public function getCopyObjects($objectID, $objectType)
public function getCopiedObjects($objectID, $objectType)
{
$objects = array();
Binary file not shown.
+4 -4
View File
@@ -247,7 +247,7 @@ class programModel extends model
{
$totalProgress = array();
$projectCount = array();
$userPrjCount = array();
$userPRJCount = array();
$progressList = array();
$programPairs = $this->getPairs();
$projectStats = $this->getProjectStats(0, 'all', 0, 'id_desc', null, 0, 0, true);
@@ -257,7 +257,7 @@ class programModel extends model
{
$totalProgress[$programID] = 0;
$projectCount[$programID] = 0;
$userPrjCount[$programID] = 0;
$userPRJCount[$programID] = 0;
$progressList[$programID] = 0;
foreach($projectStats as $project)
@@ -265,7 +265,7 @@ class programModel extends model
if(strpos($project->path, ',' . $programID . ',') === false) continue;
/* The number of projects under this program that the user can view. */
if(strpos(',' . $this->app->user->view->projects . ',', ',' . $project->id . ',') !== false) $userPrjCount[$programID] ++;
if(strpos(',' . $this->app->user->view->projects . ',', ',' . $project->id . ',') !== false) $userPRJCount[$programID] ++;
$totalProgress[$programID] += $project->hours->progress;
$projectCount[$programID] ++;
@@ -274,7 +274,7 @@ class programModel extends model
if(empty($projectCount[$programID])) continue;
/* Program progress can't see when this user don't have all projects priv. */
if(!$this->app->user->admin and $userPrjCount[$programID] != $projectCount[$programID])
if(!$this->app->user->admin and $userPRJCount[$programID] != $projectCount[$programID])
{
unset($progressList[$programID]);
continue;
+1 -1
View File
@@ -1257,7 +1257,7 @@ class project extends control
$this->view->depts = array('' => '') + $this->dept->getOptionMenu();
$this->view->currentMembers = $currentMembers;
$this->view->members2Import = $members2Import;
$this->view->teams2Import = array('' => '') + $this->loadModel('personnel')->getCopyObjects($projectID, 'project');
$this->view->teams2Import = array('' => '') + $this->loadModel('personnel')->getCopiedObjects($projectID, 'project');
$this->view->copyProjectID = $copyProjectID;
$this->display();
}
+2 -1
View File
@@ -12,4 +12,5 @@ td.c-actions {overflow: visible;}
.panel-actions {position: relative; padding: 0 0;}
td.flex {display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center;}
td.flex span.label-danger {margin-left: 5px; min-width: 50px;}
td.flex span.label-badge {margin-left: 5px; min-width: 50px;}
td.flex a.text-ellipsis {min-width: 30px;}
-5
View File
@@ -1,8 +1,3 @@
function checkUserDept(userID)
{
alert(noAccess);
}
/**
* Delete memeber of project team.
*
+1 -1
View File
@@ -1627,7 +1627,7 @@ class projectModel extends model
return $this->dao->select('account, role, hours')
->from(TABLE_TEAM)
->where('root')->eq($projectID)
->andWhere('type')->in('project')
->andWhere('type')->eq('project')
->andWhere('account')->notIN($currentMembers)
->fetchAll('account');
}
+1 -1
View File
@@ -97,7 +97,7 @@
<div class='col' data-id='<?php echo $projectID?>'>
<div class='panel'>
<div class='projectStatus'>
<?php $status = ($project->status == 'doing' and isset($project->delay)) ? 'delay' : $project->status;?>
<?php $status = isset($project->delay) ? 'delay' : $project->status;?>
<span class="label label-<?php echo $status;?>"><?php echo $lang->project->statusList[$status];?></span>
</div>
<div class='panel-heading'>
+1 -1
View File
@@ -69,7 +69,7 @@
<?php
if(common::hasPriv('user', 'view'))
{
$link = isset($deptUsers[$member->userID]) ? $this->createLink('user', 'view', "userID={$member->userID}") : "javascript:checkUserDept();";
$link = isset($deptUsers[$member->userID]) ? $this->createLink('user', 'view', "userID={$member->userID}") : "javascript: alert(noAccess);";
echo html::a($link, $member->realname, '', 'data-app="system"');
}
else
+1 -1
View File
@@ -14,7 +14,7 @@ $lang->projectstory->confirm = 'Confirm';
/* Notice. */
$lang->projectstory->whyNoStories = "No story can be linked. Please check whether there is any story in project which is linked to {$lang->productCommon} and make sure it has been reviewed.";
$lang->projectstory->batchUnlinkTip = 'The following requirements are linked to Executions of this project, please remove them from the execution first.';
$lang->projectstory->batchUnlinkTip = 'Other requirements are removed. The following requirements are linked to the execution of this project. Please remove them from the execution first.';
global $app;
$app->loadLang('product');
+1 -1
View File
@@ -14,7 +14,7 @@ $lang->projectstory->confirm = 'Confirm';
/* Notice. */
$lang->projectstory->whyNoStories = "No story can be linked. Please check whether there is any story in project which is linked to {$lang->productCommon} and make sure it has been reviewed.";
$lang->projectstory->batchUnlinkTip = 'The following requirements are linked to Executions of this project, please remove them from the execution first.';
$lang->projectstory->batchUnlinkTip = 'Other requirements are removed. The following requirements are linked to the execution of this project. Please remove them from the execution first.';
global $app;
$app->loadLang('product');
+1 -1
View File
@@ -14,7 +14,7 @@ $lang->projectstory->confirm = 'Confirm';
/* Notice. */
$lang->projectstory->whyNoStories = "No story can be linked. Please check whether there is any story in project which is linked to {$lang->productCommon} and make sure it has been reviewed.";
$lang->projectstory->batchUnlinkTip = 'The following requirements are linked to Executions of this project, please remove them from the execution first.';
$lang->projectstory->batchUnlinkTip = 'Other requirements are removed. The following requirements are linked to the execution of this project. Please remove them from the execution first.';
global $app;
$app->loadLang('product');
+1 -1
View File
@@ -14,7 +14,7 @@ $lang->projectstory->confirm = 'Confirm';
/* Notice. */
$lang->projectstory->whyNoStories = "No story can be linked. Please check whether there is any story in project which is linked to {$lang->productCommon} and make sure it has been reviewed.";
$lang->projectstory->batchUnlinkTip = 'The following requirements are linked to Executions of this project, please remove them from the execution first.';
$lang->projectstory->batchUnlinkTip = 'Other requirements are removed. The following requirements are linked to the execution of this project. Please remove them from the execution first.';
global $app;
$app->loadLang('product');
+1 -1
View File
@@ -14,7 +14,7 @@ $lang->projectstory->confirm = '确定';
/* Notice. */
$lang->projectstory->whyNoStories = "看起来没有{$lang->SRCommon}可以关联。请检查下项目关联的{$lang->productCommon}中有没有{$lang->SRCommon},而且要确保它们已经审核通过。";
$lang->projectstory->batchUnlinkTip = '如下需求已与该项目下执行相关联,请从执行中移除后再操作。';
$lang->projectstory->batchUnlinkTip = '其他需求已经移除,如下需求已与该项目下执行相关联,请从执行中移除后再操作。';
global $app;
$app->loadLang('product');
+1 -1
View File
@@ -272,7 +272,7 @@ class releaseModel extends model
/* Init vars. */
$notifyPersons = array();
$managers = '';
$notifyList = explode($notifyList, ',');
$notifyList = explode(',', $notifyList);
foreach($notifyList as $notify)
{
+1 -1
View File
@@ -2,4 +2,4 @@
#sidebar>.sidebar-toggle>.icon {right: -2px; left: auto;}
.main-row {width: 99%;}
.btn-toolbar > .last-sync-time {display: inline-block; float: left; margin-right: 10px;}
.dropdown-menu>li.selected>a:after {content: '';}
.dropdown-menu > li.selected > a:after {content: '';}
+3 -2
View File
@@ -614,6 +614,7 @@ class repoModel extends model
{
$repo = $this->getRepoByID($repoID);
if(empty($repo)) return array();
return $this->dao->select('id,name')->from(TABLE_PRODUCT)
->where('id')->in($repo->product)
->andWhere('deleted')->eq(0)
@@ -1787,10 +1788,10 @@ class repoModel extends model
*/
public function processGitlab($repo)
{
$gitlab = $this->loadModel('gitlab')->getByID($repo->client); // The $repo->client is gitlabID
$gitlab = $this->loadModel('gitlab')->getByID($repo->client); // The $repo->client is gitlabID.
if(!$gitlab) return $repo;
$repo->gitlab = $gitlab->id;
$repo->project = $repo->path; // The projectID in gitlab
$repo->project = $repo->path; // The projectID in gitlab.
$repo->path = sprintf($this->config->repo->gitlab->apiPath, $gitlab->url, $repo->path);
$repo->client = $gitlab->url;
$repo->password = $gitlab->token;
+1 -1
View File
@@ -13,7 +13,7 @@ $(document).ready(function()
}
else
{
className = response.type + 'count';
className = response.type + 'count';
$typeCount = $('#resultBox .' + className)
if($typeCount.length == 0)
{
+1 -1
View File
@@ -30,7 +30,7 @@ class searchModel extends model
if($module == 'projectStory') $flowModule = 'story';
if($module == 'projectBug') $flowModule = 'bug';
$fields = $this->loadModel('workflowfield')->getList($flowModule);
$fields = $this->loadModel('workflowfield')->getList($flowModule);
$maxCount = $this->config->maxCount;
$this->config->maxCount = 0;
+34 -34
View File
@@ -792,38 +792,39 @@ class storyModel extends model
$_POST['reviewer'] = array_filter($_POST['reviewer']);
$oldReviewer = $this->getReviewerPairs($storyID, $oldStory->version);
$oldStory->reviewers = implode(',', array_keys($oldReviewer));
/* Update story reviewer. */
$this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->andWhere('version')->eq($oldStory->version)->andWhere('reviewer')->notin(implode(',', $_POST['reviewer']))->exec();
foreach($_POST['reviewer'] as $reviewer)
if(array_diff($_POST['reviewer'], array_keys($oldReviewer)) or array_diff(array_keys($oldReviewer), $_POST['reviewer']))
{
if(in_array($reviewer, array_keys($oldReviewer))) continue;
$reviewData = new stdclass();
$reviewData->story = $storyID;
$reviewData->version = $oldStory->version;
$reviewData->reviewer = $reviewer;
$this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec();
}
/* Update the story status by review rules. */
$reviewerList = $this->getReviewerPairs($storyID, $oldStory->version);
$story->reviewers = implode(',', array_keys($reviewerList));
$reviewedBy = explode(',', trim($oldStory->reviewedBy, ','));
if(!array_diff(array_keys($reviewerList), $reviewedBy))
{
$status = $this->setStatusByReviewRules($reviewerList);
$story->status = $status ? $status : $oldStory->status;
if($story->status == 'closed')
/* Update story reviewer. */
$this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->andWhere('version')->eq($oldStory->version)->andWhere('reviewer')->notin(implode(',', $_POST['reviewer']))->exec();
foreach($_POST['reviewer'] as $reviewer)
{
$story->closedBy = $this->app->user->account;
$story->closedDate = $now;
$story->assignedTo = 'closed';
$story->assignedDate = $now;
$story->stage = 'closed';
if($this->post->closedReason == 'done') $story->stage = 'released';
if(in_array($reviewer, array_keys($oldReviewer))) continue;
$reviewData = new stdclass();
$reviewData->story = $storyID;
$reviewData->version = $oldStory->version;
$reviewData->reviewer = $reviewer;
$this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec();
}
/* Update the story status by review rules. */
$reviewerList = $this->getReviewerPairs($storyID, $oldStory->version);
$story->reviewers = implode(',', array_keys($reviewerList));
$reviewedBy = explode(',', trim($oldStory->reviewedBy, ','));
if(!array_diff(array_keys($reviewerList), $reviewedBy))
{
$status = $this->setStatusByReviewRules($reviewerList);
$story->status = $status ? $status : $oldStory->status;
if($story->status == 'closed')
{
$story->closedBy = $this->app->user->account;
$story->closedDate = $now;
$story->assignedTo = 'closed';
$story->assignedDate = $now;
$story->stage = 'closed';
if($this->post->closedReason == 'done') $story->stage = 'released';
}
}
}
}
@@ -3798,11 +3799,11 @@ class storyModel extends model
break;
}
common::printIcon('story', 'change', $vars . "&from=$story->from", $story, 'list', 'alter', '', '', false, "data-group=$story->from");
common::printIcon('story', 'review', $vars . "&from=$story->from", $story, 'list', 'search', '', '', false, "data-group=$story->from");
common::printIcon('story', 'change', $vars . "&from=$story->from", $story, 'list', 'alter', '', '', false, "data-group=$story->from");
common::printIcon('story', 'review', $vars . "&from=$story->from", $story, 'list', 'search', '', '', false, "data-group=$story->from");
if($this->app->openApp != 'project') common::printIcon('story', 'recall', $vars, $story, 'list', 'back', 'hiddenwin', '', '', '', $this->lang->story->recall);
common::printIcon('story', 'close', $vars, $story, 'list', '', '', 'iframe', true);
common::printIcon('story', 'edit', $vars . "&from=$story->from", $story, 'list', '', '', '', false, "data-group=$story->from");
common::printIcon('story', 'close', $vars, $story, 'list', '', '', 'iframe', true);
common::printIcon('story', 'edit', $vars . "&from=$story->from", $story, 'list', '', '', '', false, "data-group=$story->from");
if($story->type != 'requirement') common::printIcon('story', 'createCase', "productID=$story->product&branch=$story->branch&module=0&from=&param=0&$vars", $story, 'list', 'sitemap', '', '', false, "data-app='qa'");
common::printIcon('story', 'batchCreate', "productID=$story->product&branch=$story->branch&module=$story->module&storyID=$story->id", $story, 'list', 'split', '', '', '', '', $this->lang->story->subdivide);
if($this->app->rawModule == 'projectstory') common::printIcon('projectstory', 'unlinkStory', "projectID={$this->session->project}&storyID=$story->id", '', 'list', 'unlink', 'hiddenwin');
@@ -4515,7 +4516,7 @@ class storyModel extends model
$comment = isset($_POST['comment']) ? $this->post->comment : '';
$actionID = !empty($result) ? $this->loadModel('action')->create('story', $story->id, 'Reviewed', $comment, ucfirst($result) . $reasonParam) : '';
if(ucfirst($result) != 'Revert')
if(strtolower($result) != 'revert')
{
if($story->status == 'closed') $this->action->create('story', $story->id, 'ReviewClosed');
if($story->status == 'active') $this->action->create('story', $story->id, 'PassReviewed');
@@ -4524,5 +4525,4 @@ class storyModel extends model
return $actionID;
}
}
+4 -4
View File
@@ -135,7 +135,7 @@ $lang->task->lblTestStory = 'Story Tested';
$lang->task->recordEstimateAction = 'Record Estimate';
$lang->task->ditto = 'Ditto';
$lang->task->dittoNotice = "This Task is not linked to the %s as the previous one is!";
$lang->task->dittoNotice = "This Task is not linked to %s like the last one!";
$lang->task->selectTestStory = 'Select Story Testd';
$lang->task->selectAllUser = 'All Users';
$lang->task->noStory = 'No Story Linked';
@@ -175,8 +175,8 @@ $lang->task->reasonList['done'] = 'Done';
$lang->task->reasonList['cancel'] = 'Cancelled';
$lang->task->afterChoices['continueAdding'] = ' Continue Adding Tasks';
$lang->task->afterChoices['toTaskList'] = 'Go to Task List Page';
$lang->task->afterChoices['toStoryList'] = 'Go to Story List Page';
$lang->task->afterChoices['toTaskList'] = 'Go to Task List';
$lang->task->afterChoices['toStoryList'] = 'Go to Story List';
$lang->task->legendBasic = 'Basic Info';
$lang->task->legendEffort = 'Effort';
@@ -202,7 +202,7 @@ $lang->task->deniedNotice = 'Only the %s can %s the task.';
$lang->task->noTask = 'No tasks yet. ';
$lang->task->createDenied = 'Create Task is denied in this project';
$lang->task->cannotDeleteParent = 'Cannot delete parent task';
$lang->task->addChildTask = 'Because the task has already consumed consumption, to ensure data consistency, we will help you create a subtask with the same name to record the consumption.';
$lang->task->addChildTask = 'Because the task has cost hours, ZenTao will create a child task with the same name to record the cost housrs to ensure data consistency.';
$lang->task->error = new stdclass();
$lang->task->error->totalNumber = '"Total Cost" must be numbers.';
+1 -1
View File
@@ -2143,7 +2143,7 @@ class taskModel extends model
}
$projectList = array();
foreach($tasks as $task) $projectList[] = $task->project;
foreach($tasks as $task) $projectList[$task->project] = $task->project;
$projectPairs = $this->dao->select('id,name')->from(TABLE_PROJECT)->where('id')->in($projectList)->fetchPairs('id');
foreach($tasks as $task) $task->projectName = zget($projectPairs, $task->project);
+1 -1
View File
@@ -201,7 +201,7 @@
<?php endif;?>
<tr>
<th><?php echo $lang->testcase->type;?></th>
<?php unset($lang->testcase->typeList['unit']);?>
<?php if($case->type != 'unit') unset($lang->testcase->typeList['unit']);?>
<td><?php echo html::select('type', (array)$lang->testcase->typeList, $case->type, "class='form-control chosen'");?></td>
</tr>
<tr>
+6 -6
View File
@@ -48,12 +48,12 @@ $lang->testtask->allTasks = 'All Requests';
$lang->testtask->collapseAll = 'Collapse';
$lang->testtask->expandAll = 'Expand';
$lang->testtask->viewAction = "View Testtask";
$lang->testtask->viewAction = "View Request";
$lang->testtask->casesAction = 'View Case';
$lang->testtask->activateAction = "Activate Testtask";
$lang->testtask->blockAction = "Block Testtask";
$lang->testtask->closeAction = "Close Testtask";
$lang->testtask->startAction = "Start Testtask";
$lang->testtask->activateAction = "Activate Request";
$lang->testtask->blockAction = "Block Request";
$lang->testtask->closeAction = "Close Request";
$lang->testtask->startAction = "Start Request";
$lang->testtask->resultsAction = "Case Result";
$lang->testtask->reportAction = 'Report';
@@ -203,7 +203,7 @@ $lang->testtask->unitTag['lastWeek'] = 'Last week';
$lang->testtask->unitTag['thisMonth'] = 'This month';
$lang->testtask->unitTag['lastMonth'] = 'Last month';
$lang->testtask->typeList['integrate'] = 'Integrate';
$lang->testtask->typeList['integrate'] = 'Integration';
$lang->testtask->typeList['system'] = 'System';
$lang->testtask->typeList['acceptance'] = 'Acceptance';
$lang->testtask->typeList['performance'] = 'Performance';
+3 -2
View File
@@ -51,12 +51,13 @@
<td class='w-50px text-center'><i class='collapse-handle icon-angle-down text-muted'></i></td>
</tr>
<?php $executionParam = ($this->app->openApp == 'execution' and isset($testtask)) ? "executionID=$testtask->execution" : "";?>
<?php $params = isset($testtask) ? ",testtask=$testtask->id,buildID=$testtask->build" : "";?>
<?php $params = isset($testtask) ? ",testtask=$testtask->id" : "";?>
<?php $params = $params . ",buildID=" . (isset($testtask->build) ? $testtask->build : $result->build);?>
<?php if($executionParam) $params .= ',' . $executionParam;?>
<tr class='result-detail hide' id='tr-detail_<?php echo $trCount++; ?>'>
<td colspan='7' class='pd-0'>
<?php $projectParam = $this->app->openApp == 'project' ? "projectID={$this->session->project}," : ''?>
<form data-params='<?php echo "product=$case->product&branch=$case->branch&extras={$projectParam}caseID=$case->id,version=$case->version,resultID=$result->id,runID=$runID" . $params?>' method='post'>
<form data-params='<?php echo "product=$case->product&branch=$case->branch&extras={$projectParam}caseID=$case->id,version=$case->version,resultID=$result->id,runID=$result->run" . $params?>' method='post'>
<table class='table table-condensed resultSteps'>
<thead>
<tr>
+6
View File
@@ -4766,6 +4766,12 @@ class upgradeModel extends model
}
}
/**
* Merge repo.
*
* @access public
* @return void
*/
public function mergeRepo()
{
$data = fixer::input('post')
+12 -12
View File
@@ -11,8 +11,8 @@
*/
$lang->user->common = 'User';
$lang->user->id = 'ID';
$lang->user->inside = 'Inside Members';
$lang->user->outside = 'Outside Members';
$lang->user->inside = 'Internal';
$lang->user->outside = 'Outsiders';
$lang->user->company = 'Company';
$lang->user->dept = 'Department';
$lang->user->account = 'Account';
@@ -54,8 +54,8 @@ $lang->user->score = 'Score';
$lang->user->name = 'Name';
$lang->user->type = 'User Type';
$lang->user->cropAvatar = 'Crop Avatar';
$lang->user->cropAvatarTip = 'Drag and drop the box to select the image clipping range.';
$lang->user->cropImageTip = 'The image used is too small, the recommended image size is at least 48x48, the current image size is %s';
$lang->user->cropAvatarTip = 'Drag and drop the box to crop the image.';
$lang->user->cropImageTip = 'The image is too small. The recommended image size is at least 48x48. The current image size is %s';
$lang->user->captcha = 'Captcha';
$lang->user->legendBasic = 'Basic Information';
@@ -89,7 +89,7 @@ $lang->user->else = 'Else';
$lang->user->saveTemplate = 'Save as Template';
$lang->user->setPublic = 'Set as Public Template';
$lang->user->deleteTemplate = 'Delete Template';
$lang->user->setTemplateTitle = 'Please enter the title of template.';
$lang->user->setTemplateTitle = 'Please enter the title of the template.';
$lang->user->applyTemplate = 'Templates';
$lang->user->confirmDeleteTemplate = 'Do you want to delete this template?';
$lang->user->setPublicTemplate = 'Set as Public Template';
@@ -128,7 +128,7 @@ $lang->user->loginFailed = "Login failed. Please check your account and passwor
$lang->user->lockWarning = "You can try %s times.";
$lang->user->loginLocked = "Please contact the administrator to unlock your account or try %s minutes later.";
$lang->user->weakPassword = "Your password does not meet the requirements.";
$lang->user->errorWeak = "Passwords cannot use [%s] these commonly used weak passwords.";
$lang->user->errorWeak = "Passwords cannot use [%s] weak passwords.";
$lang->user->errorCaptcha = "Captcha Error";
$lang->user->roleList[''] = '';
@@ -199,10 +199,10 @@ $lang->user->error->account = "ID %s,account must be >= 3 letters, unde
$lang->user->error->accountDupl = "ID %s,account is used.";
$lang->user->error->realname = "ID %s,must be real name";
$lang->user->error->password = "ID %s,password must be >= 6 characters.";
$lang->user->error->mail = "ID %s,please enter valid Email address";
$lang->user->error->mail = "ID %s,enter valid Email address";
$lang->user->error->reserved = "ID %s,account is reserved.";
$lang->user->error->weakPassword = "ID %s,the password strength is less than the system setting.";
$lang->user->error->dangerPassword = "ID %s,Passwords cannot be used with [%s] these commonly used if-passwords.";
$lang->user->error->dangerPassword = "ID %s,passwords cannot be used with [%s] these commonly used if-passwords.";
$lang->user->error->verifyPassword = "Verification failed. Please enter your Login Password.";
$lang->user->error->originalPassword = "Old password is incorrect.";
@@ -247,13 +247,13 @@ $lang->user->noticeResetFile = "<h5>Contact the Administrator to reset your pas
<li>If the file exists, remove it and create it again.</li>
</ol>";
$lang->user->notice4Safe = "Warning: Weak password of one click package detected";
$lang->user->process4DIR = "It is detected that you may be using the one click installation package environment. Other sites in the environment are still using simple passwords. For security reasons, if you do not use other sites, please handle them in time. Delete or rename the %s directory. Visit: <a href='https://www.zentao.pm/book/zentaomanual/fix-weak-password-564.html' target='_blank'>https://www.zentao.pm/book/zentaomanual/fix-weak-password-564.html</a>";
$lang->user->process4DB = "It is detected that you may be using the one click installation package environment. Other sites in the environment are still using simple passwords. For security reasons, if you do not use other sites, please handle them in time. Please login database and modify password field of zt_user table of %s database. Visit: <a href='https://www.zentao.pm/book/zentaomanual/fix-weak-password-564.html' target='_blank'>https://www.zentao.pm/book/zentaomanual/fix-weak-password-564.html</a>";
$lang->user->process4DIR = "It is detected that you might use the one-click installation package environment. Other sites in the environment are still using weak passwords. For security reasons, if you do not use other sites, please handle them in time. Delete or rename the %s directory. Visit: <a href='https://www.zentao.pm/book/zentaomanual/fix-weak-password-564.html' target='_blank'>https://www.zentao.pm/book/zentaomanual/fix-weak-password-564.html</a>";
$lang->user->process4DB = "It is detected that you might use the one-click installation package environment. Other sites in the environment are still using simple passwords. For security reasons, if you do not use other sites, please handle them in time. Please login database and modify password field of zt_user table of %s database. Visit: <a href='https://www.zentao.pm/book/zentaomanual/fix-weak-password-564.html' target='_blank'>https://www.zentao.pm/book/zentaomanual/fix-weak-password-564.html</a>";
$lang->user->mkdirWin = <<<EOT
<html><head><meta charset='utf-8'></head>
<body><table align='center' style='width:700px; margin-top:100px; border:1px solid gray; font-size:14px;'><tr><td style='padding:8px'>
<div style='margin-bottom:8px;'>不能创建临时目录,请确认目录<strong style='color:#ed980f'>%s</strong>是否存在并有操作权限。</div>
<div>Can't create tmp directory, make sure the directory <strong style='color:#ed980f'>%s</strong> exists and has permission to operate.</div>
<div>A tmp directory cannot be created. Make sure the directory <strong style='color:#ed980f'>%s</strong> exists and you have the right permission.</div>
</td></tr></table></body></html>
EOT;
$lang->user->mkdirLinux = <<<EOT
@@ -261,7 +261,7 @@ $lang->user->mkdirLinux = <<<EOT
<body><table align='center' style='width:700px; margin-top:100px; border:1px solid gray; font-size:14px;'><tr><td style='padding:8px'>
<div style='margin-bottom:8px;'>不能创建临时目录,请确认目录<strong style='color:#ed980f'>%s</strong>是否存在并有操作权限。</div>
<div style='margin-bottom:8px;'>命令为:<strong style='color:#ed980f'>chmod o=rwx -R %s</strong>。</div>
<div>Can't create tmp directory, make sure the directory <strong style='color:#ed980f'>%s</strong> exists and has permission to operate.</div>
<div>A tmp directory cannot be created. Make sure the directory <strong style='color:#ed980f'>%s</strong> exists and you have the right permission.</div>
<div style='margin-bottom:8px;'>Commond: <strong style='color:#ed980f'>chmod o=rwx -R %s</strong>.</div>
</td></tr></table></body></html>
EOT;