This commit is contained in:
王怡栋
2021-09-09 10:25:59 +08:00
56 changed files with 400 additions and 106 deletions
-1
View File
@@ -23,4 +23,3 @@ CREATE TABLE `zt_mr` (
`mergeStatus` char(30) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+20
View File
@@ -264,6 +264,10 @@ class baseEntry
global $app;
$app->setModuleName($moduleName);
$app->setMethodName($methodName);
/* Check user permission. */
$this->checkPriv();
$app->setControlFile();
/*
@@ -550,4 +554,20 @@ class baseEntry
$entry = new $entryName();
return call_user_func_array(array($entry, $method), $params);
}
/**
* Check the user has permission to access this method, if not, return 403.
*
* @access public
* @return void
*/
public function checkPriv()
{
$module = $this->app->getModuleName();
$method = $this->app->getMethodName();
if($module and $method and !commonModel::hasPriv($module, $method))
{
$this->send(403, array('error' => 'Access not allowed'));
}
}
}
+10 -7
View File
@@ -234,11 +234,14 @@ class html extends baseHTML
/**
* Create user avatar.
*
* @param string|object|array $user User object or user avatar address or user account
* @param string|int $size Avatar size, can be a number or preset sizes: "xs", "sm", "", "lg", "xl", default is ""
* @param string $className Avatar element class name, default is "avatar-circle"
* @param string $attrib Extra attributes on avatar element
* @param string $tag Avatar element tag name, default is "div"
* @param string|object|array $user User object or user avatar url or user account
* @param string|int $size Avatar size, can be a number or preset sizes: "xs", "sm", "", "lg", "xl", default is ""
* @param string $className Avatar element class name, default is "avatar-circle"
* @param string $attrib Extra attributes on avatar element
* @param string $tag Avatar element tag name, default is "div"
* @param string $hueDistance Hue distance used as background color for default avatar
* @param string $saturation Saturation used as background color for default avatar
* @param string $lightness Lightness used as background color for default avatar
* @static
* @access public
* @return string
@@ -290,7 +293,7 @@ class html extends baseHTML
/**
* Create a small user avatar.
*
* @param string|object $user User object or user avatar address or user account
* @param string|object $user User object or user avatar url or user account
* @param string $className Avatar element class name, default is "avatar-circle"
* @param string $attrib Extra attributes on avatar element
* @param string $tag Avatar element tag name, default is "div"
@@ -306,7 +309,7 @@ class html extends baseHTML
/**
* Create a large user avatar.
*
* @param string|object $user User object or user avatar address or user account
* @param string|object $user User object or user avatar url or user account
* @param string $className Avatar element class name, default is "avatar-circle"
* @param string $attrib Extra attributes on avatar element
* @param string $tag Avatar element tag name, default is "div"
+96
View File
@@ -566,3 +566,99 @@ $lang->action->search->label['paused'] = $lang->action->label->pa
$lang->action->search->label['verified'] = $lang->action->label->verified;
$lang->action->search->label['login'] = $lang->action->label->login;
$lang->action->search->label['logout'] = $lang->action->label->logout;
/* Action language config for API(JIHU) */
$lang->action->apiTitle = new stdclass();
$lang->action->apiTitle->opened = 'Opened.';
$lang->action->apiTitle->created = 'Created.';
$lang->action->apiTitle->added = 'Added.';
$lang->action->apiTitle->changed = 'Changed.';
$lang->action->apiTitle->edited = 'Edited.';
$lang->action->apiTitle->assigned = 'Assigned to <strong>%s</strong>.';
$lang->action->apiTitle->closed = 'Closed.';
$lang->action->apiTitle->deleted = 'Deleted.';
$lang->action->apiTitle->deletedfile = 'Deleted: <strong><i>%s</i></strong>.';
$lang->action->apiTitle->editfile = 'Edited: <strong><i>%s</i></strong>.';
$lang->action->apiTitle->erased = 'Erased.';
$lang->action->apiTitle->undeleted = 'Restored.';
$lang->action->apiTitle->hidden = 'Hidden.';
$lang->action->apiTitle->commented = 'Commented';
$lang->action->apiTitle->activated = 'Activated.';
$lang->action->apiTitle->confirmed = 'Confirmed.';
$lang->action->apiTitle->caseconfirmed = '<strong>$actor</strong> confirmed the case change. The latest build is <strong>#$extra</strong>';
$lang->action->apiTitle->bugconfirmed = '<strong>$actor</strong> confirmed Bug.';
$lang->action->apiTitle->frombug = 'Converted from <strong>$actor</strong>. Its ID was <strong>$extra</strong>.';
$lang->action->apiTitle->started = 'Started by <strong>$actor</strong>.';
$lang->action->apiTitle->restarted = 'Continued by <strong>$actor</strong>.';
$lang->action->apiTitle->delayed = 'Postponed by <strong>$actor</strong>.';
$lang->action->apiTitle->suspended = 'Suspended by <strong>$actor</strong>.';
$lang->action->apiTitle->recordestimate = 'Recorded by <strong>$actor</strong> and it cost <strong>$extra</strong> hours.';
$lang->action->apiTitle->editestimate = '<strong>$actor</strong> edited Hour.';
$lang->action->apiTitle->deleteestimate = '<strong>$actor</strong> deleted Hour.';
$lang->action->apiTitle->canceled = 'Cancelled by <strong>$actor</strong>.';
$lang->action->apiTitle->svncommited = '<strong>$actor</strong> committed and the build is <strong>#$extra</strong>.';
$lang->action->apiTitle->gitcommited = '<strong>$actor</strong> committed and the build is <strong>#$extra</strong>.';
$lang->action->apiTitle->finished = 'Finished by <strong>$actor</strong>.';
$lang->action->apiTitle->paused = 'Paused by <strong>$actor</strong>.';
$lang->action->apiTitle->linked2bug = 'Linked to <strong>$extra</strong> by <strong>$actor</strong>';
$lang->action->apiTitle->linked2testtask = 'Linked to <strong>$extra</strong> by <strong>$actor</strong>';
$lang->action->apiTitle->resolved = 'Resolved by <strong>$actor</strong> ';
$lang->action->apiTitle->managed = 'By <strong>$actor</strong> managed.';
$lang->action->apiTitle->estimated = 'By <strong>$actor</strong> estimated.';
$lang->action->apiTitle->run = 'By <strong>$actor</strong> executed.';
$lang->action->apiTitle->tostory = "To story: {$lang->SRCommon}";
$lang->action->apiTitle->createchildren = 'Create children <strong>%s</strong>.';
$lang->action->apiTitle->linkchildtask = 'Link a child task <strong>%s</strong>.';
$lang->action->apiTitle->unlinkchildrentask = 'Unlink a child task <strong>%s</strong>.';
$lang->action->apiTitle->linkparenttask = 'Link a parent task <strong>%s</strong>.';
$lang->action->apiTitle->unlinkparenttask = 'Unlink a parent task <strong>%s</strong>.';
$lang->action->apiTitle->deletechildrentask = 'Delete a child task<strong>%s</strong>.';
$lang->action->apiTitle->createchildrenstory = 'Create a child story <strong>%s</strong>.';
$lang->action->apiTitle->linkchildstory = 'Link a child story <strong>%s</strong>.';
$lang->action->apiTitle->unlinkchildrenstory = 'Unlink a child story <strong>%s</strong>.';
$lang->action->apiTitle->linkparentstory = 'Link parent story <strong>%s</strong>.';
$lang->action->apiTitle->unlinkparentstory = 'Unlink parent story from <strong>%s</strong>.';
$lang->action->apiTitle->deletechildrenstory = 'Deleted a child story <strong>%s</strong>.';
$lang->action->apiTitle->linkrelatedcase = 'Link related case <strong>%s</strong>.';
$lang->action->apiTitle->unlinkrelatedcase = 'Unlink related case <strong>%s</strong>.';
$lang->action->apiTitle->openedbysystem = 'Opened by system';
$lang->action->apiTitle->closedbysystem = 'Closed by system';
$lang->action->apiTitle->communicated = 'Communicated';
$lang->action->apiTitle->blocked = 'Blocked';
$lang->action->apiTitle->reviewed = 'Reviewed';
$lang->action->apiTitle->recalled = 'Recalled';
$lang->action->apiTitle->moved = 'Moved';
$lang->action->apiTitle->fromlib = 'Import from lib';
$lang->action->apiTitle->totask = 'To task';
$lang->action->apiTitle->linked2plan = "Link to plan";
$lang->action->apiTitle->unlinkedfromplan = "Unlinked from plan";
$lang->action->apiTitle->changestatus = 'Changed status';
$lang->action->apiTitle->marked = 'Marked';
$lang->action->apiTitle->linked2execution = "Linked to {$lang->executionCommon}";
$lang->action->apiTitle->unlinkedfromexecution = "Unlinked from {$lang->executionCommon}";
$lang->action->apiTitle->linked2project = "Linked to project";
$lang->action->apiTitle->unlinkedfromproject = "Unlinked from project";
$lang->action->apiTitle->unlinkedfrombuild = "Unlinked from build";
$lang->action->apiTitle->linked2release = "Linked to release";
$lang->action->apiTitle->unlinkedfromrelease = "Unlinked from release";
$lang->action->apiTitle->linkrelatedbug = "Linked related Bug";
$lang->action->apiTitle->unlinkrelatedbug = "Unlinked related Bug";
$lang->action->apiTitle->linkrelatedstory = "Link related story {$lang->SRCommon}";
$lang->action->apiTitle->unlinkrelatedstory = "Unlink related story {$lang->SRCommon}";
$lang->action->apiTitle->subdividestory = "Subdivided story: {$lang->SRCommon}";
$lang->action->apiTitle->unlinkchildstory = "Unlink child story: {$lang->SRCommon}";
$lang->action->apiTitle->verified = 'Verified';
$lang->action->apiTitle->login = 'Login';
$lang->action->apiTitle->logout = "Logout";
$lang->action->apiTitle->linked2build = "Linked to build";
$lang->action->apiTitle->unlinkedfromtesttask = "Unlinked from test task";
$lang->action->apiTitle->batchcreate = "Batch create";
$lang->action->apiTitle->managedteam = "Managed team";
$lang->action->apiTitle->managedwhitelist = "Managed white list";
$lang->action->apiTitle->tracked = 'Tracked';
$lang->action->apiTitle->hangup = 'Hangup';
$lang->action->apiTitle->reviewpassed = 'Review passed';
$lang->action->apiTitle->reviewrejected = 'Review rejected';
$lang->action->apiTitle->reviewclarified = 'Review clarified';
$lang->action->apiTitle->commitsummary = 'Commit summary';
$lang->action->apiTitle->updatetrainee = 'Update trainee';
+96
View File
@@ -566,3 +566,99 @@ $lang->action->search->label['paused'] = $lang->action->label->pa
$lang->action->search->label['verified'] = $lang->action->label->verified;
$lang->action->search->label['login'] = $lang->action->label->login;
$lang->action->search->label['logout'] = $lang->action->label->logout;
/* Action language config for API(JIHU) */
$lang->action->apiTitle = new stdclass();
$lang->action->apiTitle->opened = '首次创建。';
$lang->action->apiTitle->created = '首次创建。';
$lang->action->apiTitle->added = '添加成功。';
$lang->action->apiTitle->changed = '进行了需求变更。';
$lang->action->apiTitle->edited = '编辑操作。';
$lang->action->apiTitle->assigned = '指派给 <strong>%s</strong>。';
$lang->action->apiTitle->closed = '执行了关闭操作。';
$lang->action->apiTitle->deleted = '执行删除操作。';
$lang->action->apiTitle->deletedfile = '删除了附件:<strong><i>%s</i></strong>。';
$lang->action->apiTitle->editfile = '编辑了附件:<strong><i>%s</i></strong>。';
$lang->action->apiTitle->erased = '执行了删除操作。';
$lang->action->apiTitle->undeleted = '执行还原操作。';
$lang->action->apiTitle->hidden = '进行隐藏操作。';
$lang->action->apiTitle->commented = '添加了备注';
$lang->action->apiTitle->activated = '执行激活操作。';
$lang->action->apiTitle->confirmed = '确认' . $lang->SRCommon . '变动,最新版本为<strong>#%s</strong>。';
$lang->action->apiTitle->caseconfirmed = '确认用例变动,最新版本为<strong>#%s</strong>。';
$lang->action->apiTitle->bugconfirmed = '确认了Bug。';
$lang->action->apiTitle->frombug = 'Bug转化而来,Bug编号为 <strong>%s</strong>。';
$lang->action->apiTitle->started = '启动。';
$lang->action->apiTitle->restarted = '继续。';
$lang->action->apiTitle->delayed = '执行了延期操作。';
$lang->action->apiTitle->suspended = '挂起。';
$lang->action->apiTitle->recordestimate = '记录工时,消耗 <strong>%s</strong> 小时。';
$lang->action->apiTitle->editestimate = '编辑了工时。';
$lang->action->apiTitle->deleteestimate = '删除工时。';
$lang->action->apiTitle->canceled = '执行取消操作。';
$lang->action->apiTitle->svncommited = '提交代码,版本为<strong>#%s</strong>。';
$lang->action->apiTitle->gitcommited = '提交代码,版本为<strong>#%s</strong>。';
$lang->action->apiTitle->finished = '完成。';
$lang->action->apiTitle->paused = '暂停。';
$lang->action->apiTitle->linked2bug = '关联到版本 <strong>%s</strong>';
$lang->action->apiTitle->linked2testtask = '关联到测试单 <strong>%s</strong>';
$lang->action->apiTitle->resolved = '解决。';
$lang->action->apiTitle->managed = '维护。';
$lang->action->apiTitle->estimated = '估算。';
$lang->action->apiTitle->run = '执行。';
$lang->action->apiTitle->tostory = "转{$lang->SRCommon}";
$lang->action->apiTitle->createchildren = '创建子任务 <strong>%s</strong>。';
$lang->action->apiTitle->linkchildtask = '关联子任务 <strong>%s</strong>。';
$lang->action->apiTitle->unlinkchildrentask = '移除子任务 <strong>%s</strong>。';
$lang->action->apiTitle->linkparenttask = '关联到父任务 <strong>%s</strong>。';
$lang->action->apiTitle->unlinkparenttask = '从父任务<strong>%s</strong>取消关联。';
$lang->action->apiTitle->deletechildrentask = '删除子任务<strong>%s</strong>。';
$lang->action->apiTitle->createchildrenstory = '创建子需求 <strong>%s</strong>。';
$lang->action->apiTitle->linkchildstory = '关联子需求 <strong>%s</strong>。';
$lang->action->apiTitle->unlinkchildrenstory = '移除子需求 <strong>%s</strong>。';
$lang->action->apiTitle->linkparentstory = '关联到父需求 <strong>%s</strong>。';
$lang->action->apiTitle->unlinkparentstory = '从父需求<strong>%s</strong>取消关联。';
$lang->action->apiTitle->deletechildrenstory = '删除子需求<strong>%s</strong>。';
$lang->action->apiTitle->linkrelatedcase = '关联相关用例 <strong>%s</strong>。';
$lang->action->apiTitle->unlinkrelatedcase = '移除相关用例 <strong>%s</strong>。';
$lang->action->apiTitle->openedbysystem = '系统创建';
$lang->action->apiTitle->closedbysystem = '系统关闭';
$lang->action->apiTitle->communicated = '沟通';
$lang->action->apiTitle->blocked = '阻塞';
$lang->action->apiTitle->reviewed = '评审';
$lang->action->apiTitle->recalled = '撤销评审';
$lang->action->apiTitle->moved = '移动';
$lang->action->apiTitle->fromlib = '从用例库导入';
$lang->action->apiTitle->totask = '转任务';
$lang->action->apiTitle->linked2plan = "关联计划";
$lang->action->apiTitle->unlinkedfromplan = "移除计划";
$lang->action->apiTitle->changestatus = '修改状态';
$lang->action->apiTitle->marked = '编辑';
$lang->action->apiTitle->linked2execution = "关联{$lang->executionCommon}";
$lang->action->apiTitle->unlinkedfromexecution = "移除{$lang->executionCommon}";
$lang->action->apiTitle->linked2project = "关联项目";
$lang->action->apiTitle->unlinkedfromproject = "移除项目";
$lang->action->apiTitle->unlinkedfrombuild = "移除版本";
$lang->action->apiTitle->linked2release = "关联发布";
$lang->action->apiTitle->unlinkedfromrelease = "移除发布";
$lang->action->apiTitle->linkrelatedbug = "关联了相关Bug";
$lang->action->apiTitle->unlinkrelatedbug = "移除了相关Bug";
$lang->action->apiTitle->linkrelatedstory = "关联了相关{$lang->SRCommon}";
$lang->action->apiTitle->unlinkrelatedstory = "移除了相关{$lang->SRCommon}";
$lang->action->apiTitle->subdividestory = "细分了{$lang->SRCommon}";
$lang->action->apiTitle->unlinkchildstory = "移除了细分{$lang->SRCommon}";
$lang->action->apiTitle->verified = '验收';
$lang->action->apiTitle->login = '登录系统';
$lang->action->apiTitle->logout = "退出登录";
$lang->action->apiTitle->linked2build = "关联";
$lang->action->apiTitle->unlinkedfromtesttask = "移除";
$lang->action->apiTitle->batchcreate = "批量创建任务";
$lang->action->apiTitle->managedteam = "维护";
$lang->action->apiTitle->managedwhitelist = "维护";
$lang->action->apiTitle->tracked = '跟踪';
$lang->action->apiTitle->hangup = '挂起';
$lang->action->apiTitle->reviewpassed = '确认通过';
$lang->action->apiTitle->reviewrejected = '拒绝';
$lang->action->apiTitle->reviewclarified = '有待明确';
$lang->action->apiTitle->commitsummary = '提交培训总结';
$lang->action->apiTitle->updatetrainee = '更新培训人员';
+39
View File
@@ -1513,4 +1513,43 @@ class actionModel extends model
$this->search->saveIndex($objectType, $data);
}
/**
* Print actions of an object for API(JIHU).
*
* @param array $action
* @access public
* @return void
*/
public function printActionAPI($action)
{
if(!isset($action->objectType) or !isset($action->action)) return false;
$objectType = $action->objectType;
$actionType = strtolower($action->action);
if(isset($this->lang->action->apiTitle->$actionType) and isset($action->extra))
{
/* If extra column is a username, then assemble link to that. */
if($action->action == "assigned")
{
$userDetails = $this->loadModel('user')->getUserDetailsForAPI($action->extra);
if(isset($userDetails[$action->extra]))
{
$userDetail = $userDetails[$action->extra];
$action->extra = "<a href='{$userDetail->url}' target='_blank'>{$action->extra}</a>";
}
}
echo sprintf($this->lang->action->apiTitle->$actionType, $action->extra);
}
elseif(isset($this->lang->action->apiTitle->$actionType) and !isset($action->extra))
{
echo $this->lang->action->apiTitle->$actionType;
}
else
{
echo $actionType;
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
.c-id {width: 50px !important;}
.c-branch, .c-module, .c-os {width: 120px;}
.c-execution {width: 130px;}
.c-build, .c-browser, .c-keywords, .c-other {width: 100px;}
.c-build, .c-browser, .c-keywords {width: 100px;}
.c-steps {width: 150px;}
.c-pri, .c-severity {width: 80px;}
+1 -1
View File
@@ -4,6 +4,6 @@
.c-id {width: 50px !important;}
.c-branch, .c-module, .c-os {width: 120px;}
.c-execution {width: 130px;}
.c-build, .c-browser, .c-keywords, .c-other {width: 100px;}
.c-build, .c-browser, .c-keywords {width: 100px;}
.c-steps, .c-title, .c-plan, .c-assigned, .c-resolution {width: 150px;}
.c-pri, .c-severity {width: 80px;}
+1 -1
View File
@@ -62,7 +62,7 @@
<th class='c-keywords<?php echo zget($visibleFields, 'keywords', ' hidden') . zget($requiredFields, 'keywords', '', ' required');?>'><?php echo $lang->bug->keywords;?></th>
<?php
$extendFields = $this->bug->getFlowExtendFields();
foreach($extendFields as $extendField) echo "<th class='c-other'>{$extendField->name}</th>";
foreach($extendFields as $extendField) echo "<th class='c-extend'>{$extendField->name}</th>";
?>
</tr>
</thead>
+1 -1
View File
@@ -66,7 +66,7 @@
<th class='c-resolution<?php echo zget($visibleFields, 'resolution', ' hidden')?>'><?php echo $lang->bug->resolutionAB;?></th>
<?php
$extendFields = $this->bug->getFlowExtendFields();
foreach($extendFields as $extendField) echo "<th class='c-other'>{$extendField->name}</th>";
foreach($extendFields as $extendField) echo "<th class='c-extend'>{$extendField->name}</th>";
?>
</tr>
</thead>
+3 -3
View File
@@ -8,9 +8,9 @@
#kanbanList .kanban-item {margin-top: 0; border: 1px solid #ebebeb; border-radius: 2px;}
#kanbanList .kanban-item:hover {border: 1px solid #ccc;}
#kanbanList .kanban-item + .kanban-item {margin-top: 10px;}
#kanbanList .kanban-lane-items {padding: 10px;}
#kanbanList .kanban-lane-items {padding: 10px; min-height: 38px;}
#kanbanList .kanban-header,
#kanbanList .kanban-lane {border-bottom: none; margin-bottom: 0;}
#kanbanList .kanban-lane {border-bottom: none; margin-bottom: 0; min-height: 60px;}
#kanbanList .kanban-sub-lane {border-bottom: 0;}
#kanbanList .kanban-lane {border-top: 2px solid #fff;}
#kanbanList .kanban-lane + .kanban-lane {border-top: 10px solid #fff;}
@@ -196,7 +196,7 @@ function renderExecutionItem(item, $item)
{
$item.addClass('link-block');
$title = $('<a class="title" />')
.attr('href', $.createLink('execution', 'task', 'executionID=' + item.id));
.attr('href', $.createLink('execution', 'task', 'executionID=' + item._id));
}
else
{
+1 -1
View File
@@ -334,7 +334,7 @@ class doc extends control
$lib = $this->doc->getLibByID($libID);
$type = isset($lib->type) ? $lib->type : 'product';
$libName = isset($lib->name) ? $lib->name : 'product';
$libName = isset($lib->name) ? $lib->name . $this->lang->colon : '';
$this->view->title = $libName . $this->lang->doc->create;
+3 -3
View File
@@ -35,7 +35,7 @@ $(function()
$('#subNavbar li[data-id="doc"]').addClass('active');
/* Automatically save document contents. */
setInterval("saveTempContent()", 60 * 1000);
setInterval("saveDraft()", 60 * 1000);
$(document).on("mouseup", 'span[data-name="fullscreen"]', function()
{
@@ -86,12 +86,12 @@ $(function()
})
/**
* Save temporary doc content.
* Save draft doc.
*
* @access public
* @return void
*/
function saveTempContent()
function saveDraft()
{
var content = $('#content').val();
var link = createLink('doc', 'ajaxSaveDraft', 'docID=' + docID);
+1 -1
View File
@@ -117,7 +117,7 @@ $lang->doc->allExecutions = 'All' . $lang->executionCommon . 's';
$lang->doc->libTypeList['product'] = $lang->productCommon . ' Library';
if($config->systemMode == 'new') $lang->doc->libTypeList['project'] = 'Project Library';
$lang->doc->libTypeList['execution'] = $lang->executionCommon . ' Library';
$lang->doc->libTypeList['execution'] = $lang->execution->common . ' Library';
$lang->doc->libTypeList['custom'] = 'Custom Library';
$lang->doc->libIconList['product'] = 'icon-product';
+1 -1
View File
@@ -117,7 +117,7 @@ $lang->doc->allExecutions = '所有' . $lang->executionCommon;
$lang->doc->libTypeList['product'] = $lang->productCommon . '文档库';
if($config->systemMode == 'new') $lang->doc->libTypeList['project'] = '项目文档库';
$lang->doc->libTypeList['execution'] = $lang->executionCommon . '文档库';
$lang->doc->libTypeList['execution'] = $lang->execution->common . '文档库';
$lang->doc->libTypeList['custom'] = '自定义文档库';
$lang->doc->libIconList['product'] = 'icon-product';
+5 -5
View File
@@ -31,11 +31,11 @@ $(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);
var $product = $('#products0');
if(copyExecutionID) productID = $product.val();
$product.val(productID);
$product.trigger("chosen:updated");
loadBranches($product);
var adjustMainCol = function()
{
+7 -10
View File
@@ -271,7 +271,7 @@ class executionModel extends model
public function setProjectSession($executionID)
{
$execution = $this->getByID($executionID);
$this->session->set('project', $execution->project);
if(!empty($execution)) $this->session->set('project', $execution->project);
}
/**
@@ -486,7 +486,6 @@ class executionModel extends model
/* Child stage inherits parent stage permissions. */
if(!isset($execution->acl)) $execution->acl = $oldExecution->acl;
if($execution->acl == 'open') $execution->whitelist = '';
$execution = $this->loadModel('file')->processImgURL($execution, $this->config->execution->editor->edit['id'], $this->post->uid);
@@ -2477,7 +2476,7 @@ class executionModel extends model
{
if(empty($projectID) and $this->config->systemMode == 'new') return array();
$teams = $this->dao->select('id,name,type')->from(TABLE_PROJECT)
$objects = $this->dao->select('id,name,type')->from(TABLE_PROJECT)
->where('deleted')->eq(0)
->andWhere('(project')->eq($projectID)
->orWhere('id')->eq($projectID)
@@ -2485,15 +2484,13 @@ class executionModel extends model
->orderBy('project_asc')
->fetchAll('id');
if(empty($teams)) return array();
if(empty($objects)) return array();
$teamPairs = array();
foreach($teams as $id => $team)
foreach($objects as $id => $object)
{
if(empty($team->name)) continue;
$prefix = ($team->type != 'project' and $this->config->systemMode == 'new') ? '&nbsp;&nbsp;&nbsp;' : '';
$teamPairs[$id] = $prefix . $team->name;
$prefix = ($object->type != 'project' and $this->config->systemMode == 'new') ? '&nbsp;&nbsp;&nbsp;' : '';
$teamPairs[$id] = $prefix . $object->name;
}
return $teamPairs;
@@ -3418,7 +3415,7 @@ class executionModel extends model
$days = count($dateList) - 1;
$rate = $days ? $firstTime / $days : '';
$baselineJSON = '[';
foreach($dateList as $i => $date) $baselineJSON .= round(($days - $i) * (int)$rate, 1) . ',';
foreach($dateList as $i => $date) $baselineJSON .= round(($days - $i) * (float)$rate, 1) . ',';
$baselineJSON = rtrim($baselineJSON, ',') . ']';
$chartData['labels'] = $this->report->convertFormat($dateList, DT_DATE5);
@@ -91,7 +91,7 @@ foreach($executions as $projectID => $projectExecutions)
}
else if($execution->status == 'done' or $execution->status == 'closed')
{
$closedExecutionsHtml .= '<li>' . html::a(sprintf($link, $execution->id), $execution->name, '', "class='$selected' title='$execution->name' data-key='" . zget($executionsPinYin, $execution->name, '') . "' data-app='{$this->app->tab}'") . '</li>';
$closedExecutionsHtml .= '<li>' . html::a(sprintf($link, $execution->id), $execution->name, '', "class='$selected executionName' title='$execution->name' data-key='" . zget($executionsPinYin, $execution->name, '') . "' data-app='{$this->app->tab}'") . '</li>';
if($selected == 'selected') $tabActive = 'closed';
}
+2 -2
View File
@@ -114,8 +114,8 @@
common::printIcon('bug', 'confirmBug', $params, $bug, 'list', 'ok', '', 'iframe', true);
common::printIcon('bug', 'resolve', $params, $bug, 'list', 'checked', '', 'iframe', true);
common::printIcon('bug', 'close', $params, $bug, 'list', '', '', 'iframe', true);
common::printIcon('bug', 'create', "product=$bug->product&branch=$bug->branch&extra=$params", $bug, 'list', 'copy');
common::printIcon('bug', 'edit', $params, $bug, 'list');
common::printIcon('bug', 'create', "product=$bug->product&branch=$bug->branch&extra=$params,executionID=$bug->execution", $bug, 'list', 'copy');
common::printIcon('bug', 'edit', $params, $bug, 'list');
}
?>
</td>
+1 -1
View File
@@ -12,7 +12,7 @@
?>
<?php include '../../common/view/header.html.php';?>
<?php js::set('systemMode', $config->systemMode);?>
<?php js::set('projectCommon', $lang->projectCommon);?>
<?php js::set('projectCommon', $lang->project->common);?>
<?php js::set('executionID', $execution->id);?>
<?php js::set('team2Import', $team2Import);?>
<?php js::set('roles', $roles);?>
+14 -2
View File
@@ -11,6 +11,20 @@
*/
class gitlab extends control
{
/**
* The gitlab constructor.
* @param string $moduleName
* @param string $methodName
*/
public function __construct($moduleName = '', $methodName = '')
{
parent::__construct($moduleName, $methodName);
/* This is essential when changing tab(menu) from gitlab to repo. */
/* Optional: common::setMenuVars('devops', $this->session->repoID); */
$this->loadModel('ci')->setMenu();
}
/**
* Browse gitlab.
*
@@ -23,8 +37,6 @@ class gitlab extends control
*/
public function browse($orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
{
/* This is essential when changing tab(menu) from gitlab to repo. */
common::setMenuVars('devops', $this->session->repoID);
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
+2
View File
@@ -159,6 +159,8 @@ class group extends control
foreach($this->lang->navGroup as $moduleName => $groupName)
{
if($groupName == $moduleName) continue;
if($moduleName == 'testcase') $moduleName = 'case';
$navGroup[$groupName][$moduleName] = $moduleName;
}
$this->view->navGroup = $navGroup;
+16 -3
View File
@@ -1,6 +1,20 @@
<?php
class mr extends control
{
/**
* The mr constructor.
* @param string $moduleName
* @param string $methodName
*/
public function __construct($moduleName = '', $methodName = '')
{
parent::__construct($moduleName, $methodName);
/* This is essential when changing tab(menu) from gitlab to repo. */
/* Optional: common::setMenuVars('devops', $this->session->repoID); */
$this->loadModel('ci')->setMenu();
}
/**
* Browse mr.
*
@@ -20,7 +34,6 @@ class mr extends control
/* Save current URI to session. */
$this->session->set('mrList', $this->app->getURI(true), 'repo');
common::setMenuVars('devops', $this->session->repoID);
/* Sync GitLab MR to ZenTao Database. */
$MRList = $this->mr->batchSyncMR($MRList);
@@ -103,12 +116,12 @@ class mr extends control
*/
public function delete($id, $confim = 'no')
{
if($confim != 'yes') die(js::confirm($this->lang->gitlab->confirmDelete, inlink('delete', "id=$id&confirm=yes")));
if($confim != 'yes') die(js::confirm($this->lang->mr->confirmDelete, inlink('delete', "id=$id&confirm=yes")));
$MR = $this->mr->getByID($id);
$this->dao->delete()->from(TABLE_MR)->where('id')->eq($id)->exec();
$this->mr->apiDeleteMR($MR->gitlabID, $MR->sourceProject, $MR->mriid);
$this->mr->apiDeleteMR($MR->gitlabID, $MR->targetProject, $MR->mriid);
die(js::locate(inlink('browse'), 'parent'));
}
+2 -1
View File
@@ -23,6 +23,7 @@ $lang->mr->reviewer = 'Reviewer';
$lang->mr->mergeStatus = 'Merge status';
$lang->mr->commits = 'commits';
$lang->mr->changes = 'changes';
$lang->mr->gitlabID = 'GitLab';
$lang->mr->statusList = array();
$lang->mr->statusList['opened'] = 'opened';
@@ -41,7 +42,7 @@ $lang->mr->sourceBranch = 'Source branch';
$lang->mr->targetProject = 'Target project';
$lang->mr->targetBranch = 'Target branch';
$lang->mr->usersTips = 'Tip: If you cannot choose the assignee and reviewer, please go to the GitLab page to bind the user first.';
$lang->mr->usersTips = 'Tip: If you cannot choose the assignee or reviewer, please go to the GitLab page to bind the user first.';
$lang->mr->notFound = "Merge Request does not exist!";
$lang->mr->apiError = new stdclass;
+2 -1
View File
@@ -23,6 +23,7 @@ $lang->mr->reviewer = '评审人';
$lang->mr->mergeStatus = '是否可合并';
$lang->mr->commits = '提交数';
$lang->mr->changes = '更改数';
$lang->mr->gitlabID = 'GitLab';
$lang->mr->statusList = array();
$lang->mr->statusList['opened'] = '开放中';
@@ -41,7 +42,7 @@ $lang->mr->sourceBranch = '源分支';
$lang->mr->targetProject = '目标项目';
$lang->mr->targetBranch = '目标分支';
$lang->mr->usersTips = '提示:如果无法选择指派人和评审人,请先前往GitLab页面绑定用户。';
$lang->mr->usersTips = '提示:如果无法选择指派人或评审人,请先前往GitLab页面绑定用户。';
$lang->mr->notFound = "此{$lang->mr->common}不存在。";
$lang->mr->apiError = new stdclass;
+1 -1
View File
@@ -41,7 +41,7 @@ $lang->mr->sourceBranch = '源分支';
$lang->mr->targetProject = '目標項目';
$lang->mr->targetBranch = '目標分支';
$lang->mr->usersTips = '提示:如果無法選擇指派人和評審人,請先前往GitLab頁面綁定用戶。';
$lang->mr->usersTips = '提示:如果無法選擇指派人或評審人,請先前往GitLab頁面綁定用戶。';
$lang->mr->notFound = "此{$lang->mr->common}不存在。";
$lang->mr->apiError = new stdclass;
+22 -6
View File
@@ -99,7 +99,6 @@ class mrModel extends model
$MRObject->title = $MR->title;
$MRObject->description = $MR->description;
$MRObject->assignee_ids = $MR->assignee;
$MRObject->reviewer_ids = $MR->reviewer;
$rawMR = $this->apiCreateMR($this->post->gitlabID, $this->post->sourceProject, $MRObject);
@@ -120,6 +119,9 @@ class mrModel extends model
return array('result' => 'fail', 'message' => $this->lang->mr->createFailedFromAPI);
}
/* Create a todo item for this MR. */
$this->apiCreateMRTodo($this->post->gitlabID, $this->post->targetProject, $rawMR->iid);
$newMR = new stdclass;
$newMR->mriid = $rawMR->iid;
$newMR->status = $rawMR->state;
@@ -128,7 +130,6 @@ class mrModel extends model
/* Change gitlab user ID to zentao account. */
$gitlabUsers = $this->gitlab->getUserIdAccountPairs($MR->gitlabID);
$newMR->assignee = zget($gitlabUsers, $MR->assignee, '');
$newMR->reviewer = zget($gitlabUsers, $MR->reviewer, '');
/* Update MR in Zentao database. */
$this->dao->update(TABLE_MR)->data($newMR)
@@ -157,7 +158,6 @@ class mrModel extends model
$newMR->title = $MR->title;
$newMR->description = $MR->description;
$newMR->assignee_ids = $MR->assignee;
$newMR->reviewer_ids = $MR->reviewer;
$newMR->target_branch = $MR->targetBranch;
$oldMR = $this->getByID($MRID);
@@ -168,7 +168,6 @@ class mrModel extends model
/* Change gitlab user ID to zentao account. */
$gitlabUsers = $this->gitlab->getUserIdAccountPairs($oldMR->gitlabID);
$MR->assignee = zget($gitlabUsers, $MR->assignee, '');
$MR->reviewer = zget($gitlabUsers, $MR->reviewer, '');
/* Update MR in Zentao database. */
$this->dao->update(TABLE_MR)->data($MR)
@@ -255,7 +254,7 @@ class mrModel extends model
$value = '';
list($field, $optionType, $options) = explode('|', $config);
if($optionType == 'field') $value = $rawMR->$field;
if($optionType == 'field') $value = $rawMR->$field;
if($optionType == 'userPairs')
{
$gitlabUserID = '';
@@ -269,7 +268,9 @@ class mrModel extends model
if($value) $newMR->$syncField = $value;
}
if(empty((array)$newMR)) continue;
/* For compatibility with PHP 5.4 . */
$condition = (array)$newMR;
if(empty($condition)) continue;
/* Update MR in Zentao database. */
$this->dao->update(TABLE_MR)->data($newMR)
@@ -492,4 +493,19 @@ class mrModel extends model
if(!empty($users[$zentaoUser])) return $users[$zentaoUser];
return "";
}
/**
* Create a todo item for merge request.
*
* @param int $gitlabID
* @param int $projectID
* @param int $MRID
* @access public
* @return object
*/
public function apiCreateMRTodo($gitlabID, $projectID, $MRID)
{
$url = sprintf($this->gitlab->getApiRoot($gitlabID), "/projects/$projectID/merge_requests/$MRID/todo");
return json_decode(commonModel::http($url, $data = null, $options = array(CURLOPT_CUSTOMREQUEST => 'POST')));
}
}
-4
View File
@@ -54,10 +54,6 @@
<th><?php echo $lang->mr->assignee;?></th>
<td><?php echo html::select('assignee', array(''), '', "class='form-control chosen'")?></td>
</tr>
<tr>
<th><?php echo $lang->mr->reviewer;?></th>
<td><?php echo html::select('reviewer', array(''), '', "class='form-control chosen'")?></td>
</tr>
<tr>
<th></th>
<td><?php echo $lang->mr->usersTips;?></td>
+1 -5
View File
@@ -55,16 +55,12 @@
<th><?php echo $lang->mr->assignee;?></th>
<td><?php echo html::select('assignee', $users, $assignee, "class='form-control chosen'")?></td>
</tr>
<tr>
<th><?php echo $lang->mr->reviewer;?></th>
<td><?php echo html::select('reviewer', $users, $reviewer, "class='form-control chosen'")?></td>
</tr>
<tr>
<th></th>
<td><?php echo $lang->mr->usersTips;?></td>
</tr>
<tr>
<td colspan='2' class='text-left form-actions'>
<td colspan='2' class='text-center form-actions'>
<?php echo html::submitButton(); ?>
<?php if(!isonlybody()) echo html::a(inlink('browse', ""), $lang->goback, '', 'class="btn btn-wide"');?>
</td>
+2 -1
View File
@@ -87,7 +87,8 @@ class personnelModel extends model
{
foreach($userGroups[$account] as $groupID => $userGroup)
{
$group = $groupInfo[$groupID];
$group = isset($groupInfo[$groupID]) ? $groupInfo[$groupID] : '';
if(!isset($group->programs))
{
$programRight = true;
+1 -2
View File
@@ -596,7 +596,6 @@ class productModel extends model
if($oldProduct->bind) $this->config->product->edit->requiredFields = 'name';
$product = fixer::input('post')
->setIF($this->post->acl == 'open', 'whitelist', '')
->setDefault('line', 0)
->join('whitelist', ',')
->stripTags($this->config->product->editor->edit['id'], $this->config->allowedTags)
@@ -1555,7 +1554,7 @@ class productModel extends model
->fetchGroup('product', 'id');
$executionListKey = $this->config->systemMode == 'new' ? 'project' : 'productID';
$executionList = $this->dao->select('t1.product as productID,t2.*')->from(TABLE_PROJECTPRODUCT)->alias('t1')
$executionList = $this->dao->select('t1.product as productID,t2.*')->from(TABLE_PROJECTPRODUCT)->alias('t1')
->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.project=t2.id')
->where('type')->in('stage,sprint')
->beginIF($this->config->systemMode == 'new')->andWhere('t2.project')->in(array_keys($projectList))->fi()
+1 -1
View File
@@ -95,7 +95,7 @@ foreach($products as $programID => $programProducts)
}
else if($product->status == 'closed')
{
$closedProductsHtml .= '<li>' . html::a($linkHtml, $productName, '', "class='$selected' title='$productName' class='closed' data-key='" . zget($productsPinYin, $product->name, '') . "' data-app='$app->tab'") . '</li>';
$closedProductsHtml .= '<li>' . html::a($linkHtml, $productName, '', "class='$selected productName' title='$productName' class='closed' data-key='" . zget($productsPinYin, $product->name, '') . "' data-app='$app->tab'") . '</li>';
if($selected == 'selected') $tabActive = 'closed';
}
+2 -2
View File
@@ -67,12 +67,12 @@ function processKanbanData(key, programsData)
$.each(doingProjects, function(_, project)
{
var projectID = project.id;
var projectItem = $.extend({}, project, {id: 'project-' + projectID, _id: projectID});
var projectItem = $.extend({}, project, {id: 'project-' + projectID, _id: projectID, execution: null});
items.doingProject.push(projectItem);
var execution = project.execution;
if(!execution || !execution.id) return;
projectItem.execution = execution;
projectItem.execution = $.extend({}, execution, {id: 'execution-' + execution.id, _id: execution.id});
});
}
+10 -8
View File
@@ -147,7 +147,7 @@ class programModel extends model
* Get kanban group data.
*
* @access public
* @return array
* @return array
*/
public function getKanbanGroup()
{
@@ -252,7 +252,7 @@ class programModel extends model
/* Group data by program. */
foreach($programs as $programID => $programName)
{
$programGroup = new stdclass();
$programGroup = new stdclass();
$programGroup->name = $programName;
$programGroup->products = zget($productGroup, $programID, array());
@@ -274,7 +274,7 @@ class programModel extends model
*
* @param string $account
* @access public
* @return array
* @return array
*/
public function getInvolvedPrograms($account)
{
@@ -658,7 +658,6 @@ class programModel extends model
->setDefault('end', '')
->setIF($this->post->begin == '0000-00-00', 'begin', '')
->setIF($this->post->end == '0000-00-00', 'end', '')
->setIF($this->post->acl == 'open', 'whitelist', '')
->setIF($this->post->delta == 999, 'end', LONG_TIME)
->setIF($this->post->future, 'budget', 0)
->setIF($this->post->budget != 0, 'budget', round($this->post->budget, 2))
@@ -740,9 +739,12 @@ class programModel extends model
$this->processNode($programID, $program->parent, $oldProgram->path, $oldProgram->grade);
/* Move product to new top program. */
$oldTopProgram = $this->getTopByPath($oldProgram->path);
$newTopProgram = $this->getTopByID($programID);
if($oldTopProgram != $newTopProgram) $this->dao->update(TABLE_PRODUCT)->set('program')->eq($newTopProgram)->where('program')->eq($oldTopProgram)->exec();
if($oldProgram->parent == 0)
{
$oldTopProgram = $this->getTopByPath($oldProgram->path);
$newTopProgram = $this->getTopByID($programID);
if($oldTopProgram != $newTopProgram) $this->dao->update(TABLE_PRODUCT)->set('program')->eq($newTopProgram)->where('program')->eq($oldTopProgram)->exec();
}
}
return common::createChanges($oldProgram, $program);
@@ -819,7 +821,7 @@ class programModel extends model
while($program = $stmt->fetch())
{
$link = $this->getLink($moduleName, $methodName, $program->id, $vars, $from);
$linkHtml = html::a($link, $program->name, '', "id='program$program->id' class='text-ellipsis' title=$program->name");
$linkHtml = html::a($link, $program->name, '', "id='program$program->id' class='text-ellipsis programName' title=$program->name");
if(isset($programMenu[$program->id]) and !empty($programMenu[$program->id]))
{
@@ -54,6 +54,8 @@ $programsPinYin = common::convert2Pinyin($programNames);
#programTree ul > li.has-list:after {width: 14px;}
#programTree ul > li.item-meas a.selected{color: #0c64eb;}
#showClosed1 + label{color: #3c4353}
a.programName:focus, a.programName:hover {background: #0c64eb; color: #fff !important;}
</style>
<script>
$('#programTree').tree();
+1 -1
View File
@@ -303,7 +303,7 @@ class project extends control
extract($this->project->getStats4Kanban());
$this->view->title = $this->lang->project->kanban;
$this->view->kanbanGroup = $kanbanGroup;
$this->view->kanbanGroup = array_filter($kanbanGroup);
$this->view->latestExecutions = $latestExecutions;
$this->view->programPairs = array(0 => $this->lang->project->noProgram) + $this->loadModel('program')->getPairs(true);
+1 -1
View File
@@ -4,7 +4,7 @@
* @access public
* @return void
*/
function saveMemebers()
function saveMembers()
{
var isDeleted = false;
var accountList = [];
+2 -4
View File
@@ -933,7 +933,6 @@ class projectModel extends model
->setIF($this->post->delta == 999, 'days', 0)
->setIF($this->post->begin == '0000-00-00', 'begin', '')
->setIF($this->post->end == '0000-00-00', 'end', '')
->setIF($this->post->acl == 'open', 'whitelist', '')
->setIF($this->post->future, 'budget', 0)
->setIF($this->post->budget != 0, 'budget', round($this->post->budget, 2))
->join('whitelist', ',')
@@ -1318,8 +1317,7 @@ class projectModel extends model
{
$this->dao->delete()->from(TABLE_TEAM)->where('root')->eq((int)$projectID)->andWhere('type')->eq('project')->andWhere('account')->eq($account)->exec();
$this->loadModel('user');
$this->user->updateUserView($projectID, 'project', array($account));
$this->loadModel('user')->updateUserView($projectID, 'project', array($account));
if($removeExecution == 'yes')
{
@@ -1660,7 +1658,7 @@ class projectModel extends model
$type = $this->config->systemMode == 'new' ? $project->type : 'project';
$members = $this->dao->select("t1.account, if(t2.deleted='0', t2.realname, t1.account) as realname")->from(TABLE_TEAM)->alias('t1')
$members = $this->dao->select("t1.account, if(t2.deleted='0', t2.realname, t1.account) as realname")->from(TABLE_TEAM)->alias('t1')
->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account')
->where('t1.root')->eq((int)$projectID)
->andWhere('t1.type')->eq($type)
+1 -1
View File
@@ -97,7 +97,7 @@ foreach($projects as $programID => $programProjects)
}
else if($project->status == 'done' or $project->status == 'closed')
{
$closedProjectsHtml .= '<li>' . html::a(sprintf($link, $project->id), $projectName, '', "class='$selected' title='$projectName' data-key='" . zget($projectsPinYin, $project->name, '') . "'") . '</li>';
$closedProjectsHtml .= '<li>' . html::a(sprintf($link, $project->id), $projectName, '', "class='$selected projectName' title='$projectName' data-key='" . zget($projectsPinYin, $project->name, '') . "'") . '</li>';
if($selected == 'selected') $tabActive = 'closed';
}
+1 -1
View File
@@ -169,7 +169,7 @@
<?php endif;?>
</div>
<?php endif;?>
<div class='project-members-total pull-left'><?php echo html::a(helper::createLink('project', 'team', "projectID=$projectID"), sprintf($lang->project->teamSumCount, $project->teamCount));?></div>
<div class='project-members-total pull-left'><?php echo html::a(helper::createLink('project', 'team', "projectID=$projectID"), sprintf($lang->project->teamSumCount, $project->teamCount));?></div>
</div>
<div class='project-actions'>
<div class='dropdown'>
+2 -2
View File
@@ -112,8 +112,8 @@
common::printIcon('bug', 'confirmBug', $params, $bug, 'list', 'ok', '', 'iframe', true);
common::printIcon('bug', 'resolve', $params, $bug, 'list', 'checked', '', 'iframe', true);
common::printIcon('bug', 'close', $params, $bug, 'list', '', '', 'iframe', true);
common::printIcon('bug', 'create', "product=$bug->product&branch=$bug->branch&extra=$params", $bug, 'list', 'copy');
common::printIcon('bug', 'edit', $params, $bug, 'list');
common::printIcon('bug', 'create', "product=$bug->product&branch=$bug->branch&extra=$params,projectID={$bug->project}", $bug, 'list', 'copy');
common::printIcon('bug', 'edit', $params, $bug, 'list');
}
?>
</td>
+1 -1
View File
@@ -116,7 +116,7 @@
else
{
echo html::submitButton('', '', 'hidden btn btn-wide btn-primary');
echo html::commonButton($lang->save, 'onclick="saveMemebers()" id="saveBtn"', 'btn btn-wide btn-primary');
echo html::commonButton($lang->save, 'onclick="saveMembers()" id="saveBtn"', 'btn btn-wide btn-primary');
}
echo html::backButton();
?>
+2
View File
@@ -1,5 +1,7 @@
a {color: #169;}
a:hover, a:active {text-decoration:underline; color: #C61A1A;}
#swapper a {text-decoration: none;}
#swapper .col-footer a:hover {color: #0c64eb;}
h2,h3 {font-size: 20px; margin: 0; clear: both;}
h3 {font-size: 16px;}
.revision {font-size: 12px; line-height: 20px; text-align: right; padding-right: 8px;}
+1 -1
View File
@@ -48,7 +48,7 @@ class story extends control
*/
public function create($productID = 0, $branch = 0, $moduleID = 0, $storyID = 0, $objectID = 0, $bugID = 0, $planID = 0, $todoID = 0, $extra = '', $type = 'story')
{
if($productID == 0) $this->locate($this->createLink('product', 'create'));
if($productID == 0 and $objectID == 0) $this->locate($this->createLink('product', 'create'));
$this->story->replaceURLang($type);
if($this->app->tab == 'product')
+1 -1
View File
@@ -61,7 +61,7 @@
<th class='c-keywords<?php echo zget($visibleFields, 'keywords', ' hidden') . zget($requiredFields, 'keywords', '', ' required');?>'><?php echo $lang->story->keywords;?></th>
<?php
$extendFields = $this->story->getFlowExtendFields();
foreach($extendFields as $extendField) echo "<th class='c-other'>{$extendField->name}</th>";
foreach($extendFields as $extendField) echo "<th class='c-extend'>{$extendField->name}</th>";
?>
</tr>
</thead>
+1 -1
View File
@@ -61,7 +61,7 @@ foreach(explode(',', $showFields) as $field)
<th class='c-keywords<?php echo zget($visibleFields, 'keywords', ' hidden')?>'><?php echo $lang->story->keywords;?></th>
<?php
$extendFields = $this->story->getFlowExtendFields();
foreach($extendFields as $extendField) echo "<th class='c-other'>{$extendField->name}</th>";
foreach($extendFields as $extendField) echo "<th class='c-extend'>{$extendField->name}</th>";
?>
</tr>
</thead>
+2 -2
View File
@@ -1423,7 +1423,7 @@ class taskModel extends model
/* Record consumed and left. */
$estimate = new stdclass();
$estimate->date = zget($task, 'realStarted', $now);
$estimate->date = helper::isZeroDate($task->realStarted) ? helper::today() : substr($task->realStarted, 0, 10);
$estimate->task = $taskID;
$estimate->consumed = zget($_POST, 'consumed', 0);
$estimate->left = zget($_POST, 'left', 0);
@@ -1681,7 +1681,7 @@ class taskModel extends model
}
$estimate = new stdclass();
$estimate->date = zget($_POST, 'finishedDate', date(DT_DATE1));
$estimate->date = helper::isZeroDate($task->finishedDate) ? helper::today() : substr($task->finishedDate, 0, 10);
$estimate->task = $taskID;
$estimate->left = 0;
$estimate->work = zget($task, 'work', '');
+1 -1
View File
@@ -71,7 +71,7 @@ js::set('dittoNotice', $dittoNotice);
<th class='c-reason<?php echo zget($visibleFields, 'closedReason', ' hidden') . zget($requiredFields, 'closedReason', '', ' required');?>'><?php echo $lang->task->closedReason;?></th>
<?php
$extendFields = $this->task->getFlowExtendFields();
foreach($extendFields as $extendField) echo "<th class='c-other'>{$extendField->name}</th>";
foreach($extendFields as $extendField) echo "<th class='c-extend'>{$extendField->name}</th>";
?>
</tr>
</thead>
+1 -1
View File
@@ -66,7 +66,7 @@
<th class='c-review<?php echo zget($visibleFields, 'review', ' hidden') . zget($requiredFields, 'review', '', ' required')?>'><?php echo $lang->testcase->review;?></th>
<?php
$extendFields = $this->testcase->getFlowExtendFields();
foreach($extendFields as $extendField) echo "<th class='c-other'>{$extendField->name}</th>";
foreach($extendFields as $extendField) echo "<th class='c-extend'>{$extendField->name}</th>";
?>
</tr>
</thead>
+1 -1
View File
@@ -59,7 +59,7 @@
<th class='c-stage<?php echo zget($visibleFields, 'stage', ' hidden') . zget($requiredFields, 'stage', '', ' required');?>'><?php echo $lang->testcase->stage;?></th>
<?php
$extendFields = $this->testcase->getFlowExtendFields();
foreach($extendFields as $extendField) echo "<th class='c-other'>{$extendField->name}</th>";
foreach($extendFields as $extendField) echo "<th class='c-extend'>{$extendField->name}</th>";
?>
</tr>
</thead>
+1 -1
View File
@@ -41,7 +41,7 @@ $(function()
<th><?php echo $lang->testcase->precondition?></th>
<?php if(!empty($appendFields)):?>
<?php foreach($appendFields as $appendField):?>
<th class='c-other'><?php echo $lang->testcase->{$appendField->field}?></th>
<th class='c-extend'><?php echo $lang->testcase->{$appendField->field}?></th>
<?php endforeach;?>
<?php endif;?>
<th class='c-step'>
+3
View File
@@ -42,7 +42,10 @@ if(!$app->version) $config->requestType = 'GET';
$config->default->view = 'json';
$app->parseRequest();
/* Old version need check priv here, new version check priv in entry. */
if(!$app->version) $common->checkPriv();
$app->loadModule();
$output = ob_get_clean();
+2 -2
View File
@@ -1,6 +1,6 @@
/*!
* ZUI: ZUI Kanban View - v1.9.2 - 2021-09-08
* ZUI: ZUI Kanban View - v1.9.2 - 2021-09-09
* http://openzui.com
* GitHub: https://github.com/easysoft/zui.git
* Copyright (c) 2021 cnezsoft.com; Licensed MIT
*/.kanban{min-height:300px;overflow-x:auto}.kanban-header,.kanban-lane,.kanban-sub-lane{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;flex-direction:row;background-color:#f1f3f5;border-bottom:1px solid #d5d9de;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.no-flex .kanban-lane{padding-left:20px}.kanban-header{padding-left:20px;background-color:rgba(0,0,0,.07)}.kanban-no-lane-name .kanban-header{padding-left:0}.kanban-col{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.not-use-flex .kanban-col{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none}.no-flex .kanban-col{float:left}.kanban-col+.kanban-col{border-left:1px solid #d5d9de}.kanban-header-col{position:relative;height:32px}.kanban-header-col>.title{display:block;margin:6px 32px;line-height:20px;text-align:center}.kanban-header-col>.title>.text{display:inline-block;max-width:100px;margin:0 5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kanban-header-col>.title>.count,.kanban-header-col>.title>.icon{position:relative;top:-6px}.kanban-header-col[data-id=ADD]>.title{margin:6px;opacity:.7}.kanban-header-col[data-id=ADD]>.actions{display:none}.kanban-header-col>.actions{position:absolute;top:0;right:0}.kanban-header-col>.actions>.btn{min-width:32px}.kanban-header-col>.actions>.btn>.icon{opacity:.5}.kanban-lane{min-height:100px;margin-bottom:3px}.kanban-lane-name{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:20px;padding:10px 0;color:#fff;text-align:center;background-color:#3dc6fd;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none}.no-flex .kanban-lane-name{position:absolute;top:0;bottom:0;left:0}.kanban-header+.kanban-lane>.kanban-lane-name{margin-top:-33px}.kanban-lane-name .char{display:block;line-height:1;white-space:pre}.kanban-lane-name .char.rotate-90{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.kanban-lane-name.is-arab{font-size:12px;-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.kanban-lane-name.is-arab .char{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.kanban-sub-lanes{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;flex-direction:column;-webkit-box-flex:1;-webkit-flex:auto;-ms-flex:auto;flex:auto;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-pack:stretch;-webkit-justify-content:stretch;-ms-flex-pack:stretch;justify-content:stretch;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column}.kanban-sub-lane{-webkit-box-flex:1;-webkit-flex:auto;-ms-flex:auto;flex:auto}.kanban-lane-col.drop-to{outline:3px solid rgba(255,190,57,.25);outline-offset:-3px}.kanban-lane-col.drop-to .kanban-lane-actions>.btn{background-color:rgba(255,190,57,.25);border:1px dotted #ff9800}.kanban-lane-col.drop-to .kanban-lane-actions>.btn>span{opacity:0}.kanban-lane-col[data-type=EMPTY]{background-color:#fff}.kanban-lane-items{max-height:300px;padding:0 15px;overflow:auto}.kanban-lane-actions{padding:10px 15px}.kanban-item{padding:10px;margin-top:10px;background:#fff;border:1px solid #fff;border-radius:4px;-webkit-transition:-webkit-box-shadow .2s,-webkit-transform .2s;-o-transition:box-shadow .2s,-o-transform .2s;transition:-webkit-box-shadow .2s,-webkit-transform .2s;transition:box-shadow .2s,transform .2s;transition:box-shadow .2s,transform .2s,-webkit-box-shadow .2s,-webkit-transform .2s,-o-transform .2s}.kanban-item.drag-from{background-color:#aaa;opacity:.2}.kanban-item:hover{border-color:rgba(0,0,0,.1);-webkit-box-shadow:0 4px 10px 0 rgba(0,0,0,.09);box-shadow:0 4px 10px 0 rgba(0,0,0,.09)}.kanban-item.drag-shadow{border-color:rgba(0,0,0,.2);-webkit-box-shadow:0 4px 10px 0 rgba(0,0,0,.09),0 4px 20px 0 rgba(0,0,0,.5);box-shadow:0 4px 10px 0 rgba(0,0,0,.09),0 4px 20px 0 rgba(0,0,0,.5);-webkit-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}
*/.kanban{min-height:300px;overflow-x:auto}.kanban-header,.kanban-lane,.kanban-sub-lane{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;flex-direction:row;background-color:#f1f3f5;border-bottom:1px solid #d5d9de;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-webkit-flex-direction:row;-ms-flex-direction:row;-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap}.no-flex .kanban-lane{position:relative;padding-left:20px}.kanban-header{padding-left:20px;background-color:rgba(0,0,0,.07)}.kanban-no-lane-name .kanban-header{padding-left:0}.kanban-col{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.not-use-flex .kanban-col{-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none}.no-flex .kanban-col{float:left}.kanban-col+.kanban-col{border-left:1px solid #d5d9de}.kanban-header-col{position:relative;height:32px}.kanban-header-col>.title{display:block;margin:6px 32px;line-height:20px;text-align:center}.kanban-header-col>.title>.text{display:inline-block;max-width:100px;margin:0 5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kanban-header-col>.title>.count,.kanban-header-col>.title>.icon{position:relative;top:-6px}.kanban-header-col[data-id=ADD]>.title{margin:6px;opacity:.7}.kanban-header-col[data-id=ADD]>.actions{display:none}.kanban-header-col>.actions{position:absolute;top:0;right:0}.kanban-header-col>.actions>.btn{min-width:32px}.kanban-header-col>.actions>.btn>.icon{opacity:.5}.kanban-lane{min-height:100px;margin-bottom:3px}.kanban-lane-name{position:relative;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:20px;color:#fff;text-align:center;background-color:#3dc6fd;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-box-flex:0;-webkit-flex:none;-ms-flex:none;flex:none}.kanban-lane-name>.text{position:absolute;top:0;bottom:0;display:block;padding:5px 0;overflow:hidden;text-align:center;text-overflow:ellipsis;white-space:nowrap;-webkit-writing-mode:tb-rl;-ms-writing-mode:tb-rl;writing-mode:tb-rl;-webkit-writing-mode:vertical-rl;writing-mode:vertical-rl;-webkit-writing-mode:sideways-lr;-ms-writing-mode:sideways-lr;writing-mode:sideways-lr}.no-flex .kanban-lane-name{position:absolute;top:0;bottom:0;left:0}.kanban-header+.kanban-lane>.kanban-lane-name{margin-top:-33px}.kanban-sub-lanes{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;flex-direction:column;-webkit-box-flex:1;-webkit-flex:auto;-ms-flex:auto;flex:auto;-webkit-box-align:stretch;-webkit-align-items:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-pack:stretch;-webkit-justify-content:stretch;-ms-flex-pack:stretch;justify-content:stretch;-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-flex-direction:column;-ms-flex-direction:column}.kanban-sub-lane{-webkit-box-flex:1;-webkit-flex:auto;-ms-flex:auto;flex:auto}.kanban-lane-col.drop-to{outline:3px solid rgba(255,190,57,.25);outline-offset:-3px}.kanban-lane-col.drop-to .kanban-lane-actions>.btn{background-color:rgba(255,190,57,.25);border:1px dotted #ff9800}.kanban-lane-col.drop-to .kanban-lane-actions>.btn>span{opacity:0}.kanban-lane-col[data-type=EMPTY]{background-color:#fff}.kanban-lane-items{max-height:300px;padding:0 15px;overflow:auto}.kanban-size-inited .kanban-lane-items{max-height:100%!important}.kanban-lane-actions{padding:10px 15px}.kanban-item{padding:10px;margin-top:10px;background:#fff;border:1px solid #fff;border-radius:4px;-webkit-transition:-webkit-box-shadow .2s,-webkit-transform .2s;-o-transition:box-shadow .2s,-o-transform .2s;transition:-webkit-box-shadow .2s,-webkit-transform .2s;transition:box-shadow .2s,transform .2s;transition:box-shadow .2s,transform .2s,-webkit-box-shadow .2s,-webkit-transform .2s,-o-transform .2s}.kanban-item.drag-from{background-color:#aaa;opacity:.2}.kanban-item:hover{border-color:rgba(0,0,0,.1);-webkit-box-shadow:0 4px 10px 0 rgba(0,0,0,.09);box-shadow:0 4px 10px 0 rgba(0,0,0,.09)}.kanban-item.drag-shadow{border-color:rgba(0,0,0,.2);-webkit-box-shadow:0 4px 10px 0 rgba(0,0,0,.09),0 4px 20px 0 rgba(0,0,0,.5);box-shadow:0 4px 10px 0 rgba(0,0,0,.09),0 4px 20px 0 rgba(0,0,0,.5);-webkit-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}
File diff suppressed because one or more lines are too long
+4 -4
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -57,7 +57,7 @@ a.showMoreImage:hover {opacity: 1;}
.c-estimate {width: 70px;}
.c-number, .c-stage, .c-role, .c-estimate-box, .c-result {width: 80px;}
.c-company, .c-budget {width: 80px;}
.c-status, .c-type, .c-user, .c-date, .c-encode, .c-resolution, .c-pri-box, .c-other {width: 100px;}
.c-status, .c-type, .c-user, .c-date, .c-encode, .c-resolution, .c-pri-box, .c-extend {width: 100px;}
.c-object-type {width: 130px;}
.c-full-date, .c-mobile, .c-email, .c-text, .c-subject, .c-assigned-box, .c-user-box {width: 150px;}
.c-module, .c-date-box {width: 180px;}