Merge branch 'master' of https://gitlab.zcorp.cc/easycorp/zentaopms into importExport

This commit is contained in:
tanghucheng
2022-08-05 13:07:31 +08:00
79 changed files with 1078 additions and 260 deletions
+7
View File
@@ -1,3 +1,5 @@
ALTER TABLE `zt_task` ADD `order` mediumint(8) NOT NULL DEFAULT 0 AFTER `activatedDate`;
ALTER TABLE `zt_task` ADD INDEX `order` (`order`);
ALTER TABLE `zt_story` ADD COLUMN `linkRequirements` varchar(255) NOT NULL AFTER `linkStories`;
ALTER TABLE `zt_searchindex` ADD FULLTEXT `title_content` (`title`, `content`);
@@ -13,11 +15,16 @@ ALTER TABLE `zt_release` ADD `createdDate` datetime NOT NULL AFTER `createdBy`;
ALTER TABLE `zt_testtask` ADD `createdBy` varchar(30) NOT NULL AFTER `subStatus`;
ALTER TABLE `zt_testtask` ADD `createdDate` datetime NOT NULL AFTER `createdBy`;
ALTER TABLE `zt_build` ADD `createdBy` varchar(30) NOT NULL AFTER `desc`;
ALTER TABLE `zt_build` ADD `createdDate` datetime NOT NULL AFTER `createdBy`;
INSERT IGNORE INTO `zt_workflowfield` (`module`, `field`, `type`, `length`, `name`, `control`, `expression`, `options`, `default`, `rules`, `placeholder`, `order`, `searchOrder`, `exportOrder`, `canExport`, `canSearch`, `isValue`, `readonly`, `buildin`, `role`, `desc`, `createdBy`, `createdDate`, `editedBy`, `editedDate`) VALUES
('testtask', 'createdBy', 'varchar', '30', '由谁创建', 'select', '', 'user', '', '', '', 393, 0, 0, '0', '0', '0', '1', 1, 'buildin', '', '', '2022-08-02 14:49', '', '0000-00-00 00:00:00'),
('testtask', 'createdDate', 'datetime', '', '创建时间', 'datetime', '', '', '', '', '', 394, 0, 0, '0', '0', '0', '1', 1, 'buildin', '', '', '2022-08-02 14:49', '', '0000-00-00 00:00:00'),
('productplan', 'createdBy', 'varchar', '30', '由谁创建', 'select', '', 'user', '', '', '', 11, 0, 0, '0', '0', '0', '1', 1, 'buildin', '', '', '2022-08-02 14:49', '', '0000-00-00 00:00:00'),
('productplan', 'createdDate', 'datetime', '', '创建时间', 'datetime', '', '', '', '', '', 12, 0, 0, '0', '0', '0', '1', 1, 'buildin', '', '', '2022-08-02 14:49', '', '0000-00-00 00:00:00'),
('build', 'createdBy', 'varchar', '30', '由谁创建', 'select', '', 'user', '', '', '', 15, 0, 0, '0', '0', '0', '1', 1, 'buildin', '', '', '2022-08-02 14:49', '', '0000-00-00 00:00:00'),
('build', 'createdDate', 'datetime', '', '创建时间', 'datetime', '', '', '', '', '', 16, 0, 0, '0', '0', '0', '1', 1, 'buildin', '', '', '2022-08-02 14:49', '', '0000-00-00 00:00:00'),
('release', 'createdBy', 'varchar', '30', '由谁创建', 'select', '', 'user', '', '', '', 14, 0, 0, '0', '0', '0', '1', 1, 'buildin', '', '', '2022-08-02 14:49', '', '0000-00-00 00:00:00'),
('release', 'createdDate', 'datetime', '', '创建时间', 'datetime', '', '', '', '', '', 15, 0, 0, '0', '0', '0', '1', 1, 'buildin', '', '', '2022-08-02 14:49', '', '0000-00-00 00:00:00');
+4
View File
@@ -331,6 +331,8 @@ CREATE TABLE IF NOT EXISTS `zt_build` (
`bugs` text NOT NULL,
`builder` char(30) NOT NULL default '',
`desc` mediumtext NOT NULL,
`createdBy` varchar(30) NOT NULL,
`createdDate` datetime NOT NULL,
`deleted` enum('0','1') NOT NULL default '0',
PRIMARY KEY (`id`),
KEY `product` (`product`),
@@ -1527,6 +1529,7 @@ CREATE TABLE IF NOT EXISTS `zt_task` (
`lastEditedBy` varchar(30) NOT NULL,
`lastEditedDate` datetime NOT NULL,
`activatedDate` datetime NOT NULL,
`order` mediumint(8) unsigned NOT NULL,
`repo` mediumint(8) unsigned NOT NULL,
`mr` mediumint(8) unsigned NOT NULL,
`entry` varchar(255) NOT NULL,
@@ -1540,6 +1543,7 @@ CREATE TABLE IF NOT EXISTS `zt_task` (
KEY `story` (`story`),
KEY `parent` (`parent`),
KEY `assignedTo` (`assignedTo`)
KEY `order` (`order`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_taskestimate`;
CREATE TABLE IF NOT EXISTS `zt_taskestimate` (
+2 -2
View File
@@ -240,8 +240,8 @@ $lang->action->desc->linkrelatedcase = '$date, <strong>$actor</strong> hat ein
$lang->action->desc->unlinkrelatedcase = '$date, <strong>$actor</strong> hate eine Fallverknüpfung aufgelöst <strong>$extra</strong>.' . "\n";
/* Used to describe the history of operations link story and bug to productplan. */
$lang->action->desc->linkstory = '$date, <strong>$actor</strong> link stories <strong>$extra</strong> to plan.' . "\n";
$lang->action->desc->linkbug = '$date, <strong>$actor</strong> link bugs <strong>$extra</strong> to plan.' . "\n";
$lang->action->desc->linkstory = '$date, <strong>$actor</strong> link stories <strong>$extra</strong>.' . "\n";
$lang->action->desc->linkbug = '$date, <strong>$actor</strong> link bugs <strong>$extra</strong>.' . "\n";
$lang->action->desc->unlinkstory = '$date, <strong>$actor</strong> remove stories <strong>$extra</strong> from plan.' . "\n";
$lang->action->desc->unlinkbug = '$date, <strong>$actor</strong> remove bugs <strong>$extra</strong> from plan.' . "\n";
+2 -2
View File
@@ -240,8 +240,8 @@ $lang->action->desc->linkrelatedcase = '$date, <strong>$actor</strong> linked
$lang->action->desc->unlinkrelatedcase = '$date, <strong>$actor</strong> unlinked a case <strong>$extra</strong>.' . "\n";
/* Used to describe the history of operations link story and bug to productplan. */
$lang->action->desc->linkstory = '$date, <strong>$actor</strong> link stories <strong>$extra</strong> to plan.' . "\n";
$lang->action->desc->linkbug = '$date, <strong>$actor</strong> link bugs <strong>$extra</strong> to plan.' . "\n";
$lang->action->desc->linkstory = '$date, <strong>$actor</strong> link stories <strong>$extra</strong>.' . "\n";
$lang->action->desc->linkbug = '$date, <strong>$actor</strong> link bugs <strong>$extra</strong>.' . "\n";
$lang->action->desc->unlinkstory = '$date, <strong>$actor</strong> remove stories <strong>$extra</strong> from plan.' . "\n";
$lang->action->desc->unlinkbug = '$date, <strong>$actor</strong> remove bugs <strong>$extra</strong> from plan.' . "\n";
+2 -2
View File
@@ -240,8 +240,8 @@ $lang->action->desc->linkrelatedcase = '$date, <strong>$actor</strong> a fait
$lang->action->desc->unlinkrelatedcase = '$date, <strong>$actor</strong> a délié le CasTest <strong>$extra</strong>.' . "\n";
/* Used to describe the history of operations link story and bug to productplan. */
$lang->action->desc->linkstory = '$date, <strong>$actor</strong> link stories <strong>$extra</strong> to plan.' . "\n";
$lang->action->desc->linkbug = '$date, <strong>$actor</strong> link bugs <strong>$extra</strong> to plan.' . "\n";
$lang->action->desc->linkstory = '$date, <strong>$actor</strong> link stories <strong>$extra</strong>.' . "\n";
$lang->action->desc->linkbug = '$date, <strong>$actor</strong> link bugs <strong>$extra</strong>.' . "\n";
$lang->action->desc->unlinkstory = '$date, <strong>$actor</strong> remove stories <strong>$extra</strong> from plan.' . "\n";
$lang->action->desc->unlinkbug = '$date, <strong>$actor</strong> remove bugs <strong>$extra</strong> from plan.' . "\n";
+2 -2
View File
@@ -240,8 +240,8 @@ $lang->action->desc->linkrelatedcase = '$date, 由 <strong>$actor</strong> 关
$lang->action->desc->unlinkrelatedcase = '$date, 由 <strong>$actor</strong> 移除相关用例 <strong>$extra</strong>。' . "\n";
/* 用来描述计划关联和移除需求、bug时的历史操作记录。*/
$lang->action->desc->linkstory = '$date, 由 <strong>$actor</strong> 关联需求 <strong>$extra</strong> 到计划。' . "\n";
$lang->action->desc->linkbug = '$date, 由 <strong>$actor</strong> 关联BUG <strong>$extra</strong> 到计划。' . "\n";
$lang->action->desc->linkstory = '$date, 由 <strong>$actor</strong> 关联需求 <strong>$extra</strong>。' . "\n";
$lang->action->desc->linkbug = '$date, 由 <strong>$actor</strong> 关联BUG <strong>$extra</strong>。' . "\n";
$lang->action->desc->unlinkstory = '$date, 由 <strong>$actor</strong> 从计划移除需求 <strong>$extra</strong>。' . "\n";
$lang->action->desc->unlinkbug = '$date, 由 <strong>$actor</strong> 从计划移除BUG <strong>$extra</strong>。' . "\n";
+2 -2
View File
@@ -858,7 +858,7 @@ class actionModel extends model
$this->app->loadLang('mr');
$desc = sprintf($this->lang->mr->createAction, $mrCreatedDate, $mrActor, $mrLink);
}
elseif($this->config->edition == 'max' and strpos($this->config->action->assetType, $action->objectType) !== false and $action->action == 'approved')
elseif($this->config->edition == 'max' and strpos($this->config->action->assetType, ",{$action->objectType},") !== false and $action->action == 'approved')
{
$desc = empty($this->lang->action->approve->{$action->extra}) ? '' : $this->lang->action->approve->{$action->extra};
}
@@ -1469,7 +1469,7 @@ class actionModel extends model
}
if($this->config->edition == 'max'
and strpos($this->config->action->assetType, $action->objectType) !== false
and strpos($this->config->action->assetType, ",{$action->objectType},") !== false
and empty($action->project) and empty($action->product) and empty($action->execution))
{
if($action->objectType == 'doc')
+10 -8
View File
@@ -1146,13 +1146,15 @@ class bugModel extends model
if(dao::isError()) return false;
$buildData = new stdclass();
$buildData->product = (int)$oldBug->product;
$buildData->branch = (int)$oldBug->branch;
$buildData->project = $this->dao->select('project')->from(TABLE_EXECUTION)->where('id')->eq($bug->buildExecution)->fetch('project');
$buildData->execution = $bug->buildExecution;
$buildData->name = $bug->buildName;
$buildData->date = date('Y-m-d');
$buildData->builder = $this->app->user->account;
$buildData->product = (int)$oldBug->product;
$buildData->branch = (int)$oldBug->branch;
$buildData->project = $this->dao->select('project')->from(TABLE_EXECUTION)->where('id')->eq($bug->buildExecution)->fetch('project');
$buildData->execution = $bug->buildExecution;
$buildData->name = $bug->buildName;
$buildData->date = date('Y-m-d');
$buildData->builder = $this->app->user->account;
$buildData->createdBy = $this->app->user->account;
$buildData->createdDate = helper::now();
$this->dao->insert(TABLE_BUILD)->data($buildData)->autoCheck()
->check('name', 'unique', "product = {$buildData->product} AND branch = {$buildData->branch} AND deleted = '0'")
->exec();
@@ -1686,7 +1688,7 @@ class bugModel extends model
$bugIDList = array();
if($moduleName == 'contributeBug')
{
$bugsAssignedByMe = $this->loadModel('my')->getAssignedByMe($account, 0, $pager, $orderBy, 0, 'bug');
$bugsAssignedByMe = $this->loadModel('my')->getAssignedByMe($account, 0, '', $orderBy, 'bug');
foreach($bugsAssignedByMe as $bugID => $bug) $bugIDList[$bugID] = $bugID;
}
-1
View File
@@ -1,2 +1 @@
#branch_chosen .chosen-single {border-left: 0px;}
#noProduct {display: inline-block; width: 110%;}
+2
View File
@@ -313,6 +313,8 @@ class buildModel extends model
->setDefault('branch', 0)
->cleanInt('product,branch')
->add('execution', (int)$executionID)
->add('createdBy', $this->app->user->account)
->add('createdDate', helper::now())
->stripTags($this->config->build->editor->create['id'], $this->config->allowedTags)
->remove('resolvedBy,allchecker,files,labels,uid')
->get();
+3 -1
View File
@@ -152,17 +152,19 @@ class caselibModel extends model
/**
* Get library list.
*
* @param string $type
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getList($orderBy = 'id_desc', $pager = null)
public function getList($type = 'all', $orderBy = 'id_desc', $pager = null)
{
return $this->dao->select('*')->from(TABLE_TESTSUITE)
->where('product')->eq(0)
->andWhere('deleted')->eq(0)
->andWhere('type')->eq('library')
->beginIF($type == 'review')->andWhere("FIND_IN_SET('{$this->app->user->account}', `reviewers`)")->fi()
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
+5 -3
View File
@@ -1521,10 +1521,12 @@ class commonModel extends model
public static function printLink($module, $method, $vars = '', $label = '', $target = '', $misc = '', $newline = true, $onlyBody = false, $object = null)
{
/* Add data-app attribute. */
global $app;
global $app, $config;
$currentModule = strtolower($module);
$currentMethod = strtolower($method);
if(strpos($misc, 'data-app') === false) $misc .= ' data-app="' . $app->tab . '"';
if(!commonModel::hasPriv($module, $method, $object)) return false;
if(!commonModel::hasPriv($module, $method, $object) and !in_array("$currentModule.$currentMethod", $config->openMethods)) return false;
echo html::a(helper::createLink($module, $method, $vars, '', $onlyBody), $label, $target, $misc, $newline);
return true;
}
@@ -1966,7 +1968,7 @@ EOD;
}
}
$changes = array();
$changes = array();
foreach($new as $key => $value)
{
if(is_object($value) or is_array($value)) continue;
+9 -5
View File
@@ -11,14 +11,18 @@
*/
css::import($jsRoot . 'dhtmlxgantt/min.css');
js::import($jsRoot . 'dhtmlxgantt/min.js');
js::import($jsRoot . 'dhtmlxgantt/ext/dhtmlxgantt_critical_path.js');
js::import($jsRoot . 'dhtmlxgantt/ext/dhtmlxgantt_fullscreen.js');
js::import($jsRoot . 'dhtmlxgantt/ext/dhtmlxgantt_smart_rendering.js');
js::import($jsRoot . 'dhtmlxgantt/ext/dhtmlxgantt_marker.js');
js::import($jsRoot . 'dhtmlxgantt/ext/dhtmlxgantt_tooltip.js');
$currentLang = $app->getClientLang();
if($currentLang != 'en') js::import($jsRoot . 'dhtmlxgantt/lang/' . $currentLang . '.js');
?>
<style>
.gantt_message_area{display:none;}
</style>
<script>
gantt.plugins({
marker: true,
critical_path: true,
fullscreen: true,
tooltip: true,
click_drag: true
});
</script>
+7 -5
View File
@@ -947,11 +947,13 @@ class convertModel extends model
$productID = $projectProduct[$projectID];
$build = new stdclass();
$build->product = $productID;
$build->project = $projectID;
$build->name = $data->vname;
$build->date = substr($data->RELEASEDATE, 0, 10);
$build->builder = $this->app->user->account;
$build->product = $productID;
$build->project = $projectID;
$build->name = $data->vname;
$build->date = substr($data->RELEASEDATE, 0, 10);
$build->builder = $this->app->user->account;
$build->createdBy = $this->app->user->account;
$build->createdDate = helper::now();
$this->dao->dbh($this->dbh)->insert(TABLE_BUILD)->data($build)->exec();
$buildID = $this->dao->dbh($this->dbh)->lastInsertID();
+7 -19
View File
@@ -3675,7 +3675,6 @@ class execution extends control
* All execution.
*
* @param string $status
* @param int $projectID
* @param string $orderBy
* @param int $productID
* @param string $param
@@ -3685,7 +3684,7 @@ class execution extends control
* @access public
* @return void
*/
public function all($status = 'undone', $projectID = 0, $orderBy = 'order_asc', $productID = 0, $param = '', $recTotal = 0, $recPerPage = 100, $pageID = 1)
public function all($status = 'undone', $orderBy = 'order_asc', $productID = 0, $param = '', $recTotal = 0, $recPerPage = 100, $pageID = 1)
{
$this->app->loadLang('my');
$this->app->loadLang('product');
@@ -3698,17 +3697,8 @@ class execution extends control
if($this->app->viewType == 'mhtml')
{
if($this->app->rawModule == 'project' and $this->app->rawMethod == 'execution')
{
$projects = $this->project->getPairsByProgram();
$projectID = $this->project->saveState($projectID, $projects);
$this->project->setMenu($projectID);
}
else
{
$executionID = $this->execution->saveState(0, $this->executions);
$this->execution->setMenu($executionID);
}
$executionID = $this->execution->saveState(0, $this->executions);
$this->execution->setMenu($executionID);
}
/* Load pager and get tasks. */
@@ -3716,13 +3706,13 @@ class execution extends control
$pager = new pager($recTotal, $recPerPage, $pageID);
$queryID = ($status == 'bySearch') ? (int)$param : 0;
$actionURL = $this->createLink('execution', 'all', "status=bySearch&projectID=$projectID&orderBy=$orderBy&productID=$productID&param=myQueryID");
$actionURL = $this->createLink('execution', 'all', "status=bySearch&orderBy=$orderBy&productID=$productID&param=myQueryID");
$this->execution->buildSearchFrom($queryID, $actionURL);
$this->view->title = $this->lang->execution->allExecutions;
$this->view->position[] = $this->lang->execution->allExecutions;
$executionStats = $this->project->getStats($projectID, $status, $productID, 0, 30, $orderBy, $pager, false, $queryID);
$executionStats = $this->project->getStats(0, $status, $productID, 0, 30, $orderBy, $pager, false, $queryID);
$parentIdList = array();
foreach($executionStats as $execution)
@@ -3733,15 +3723,13 @@ class execution extends control
$parents = array();
if($parentIdList) $parents = $this->execution->getByIdList($parentIdList);
$allExecutionsNum = $this->project->getStats($projectID, 'all');
$allExecutionsNum = $this->project->getStats(0, 'all');
$this->view->allExecutionsNum = count($allExecutionsNum);
$this->view->executionStats = $executionStats;
$this->view->productList = $this->loadModel('product')->getProductPairsByProject($projectID);
$this->view->productList = $this->loadModel('product')->getProductPairsByProject(0);
$this->view->productID = $productID;
$this->view->projectID = $projectID;
$this->view->parents = $parents;
$this->view->projects = array('') + $this->project->getPairsByProgram();
$this->view->pager = $pager;
$this->view->orderBy = $orderBy;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
+4 -2
View File
@@ -32,6 +32,8 @@ td.flex span.project-type-label {min-width: 40px;}
.c-project{text-overflow: unset !important;}
canvas {height: 28px;}
.parent.has-child.c-name.flex, .table-child-bottom > .c-name.flex {border-bottom: 0px solid #cbd0db !important;}
.parent.has-child.c-name.flex {margin-bottom: -2px !important;}
#tableCustomBtn {padding-bottom: 5px;}
#bysearchTab {margin-left: 5px;}
#datatable-executionList .table-child-bottom > .c-name.flex {border-bottom: 1px solid #cbd0db !important;}
#datatable-executionList .table-child-bottom.table-child-top > .c-name.flex {border-bottom: 2px solid #cbd0db !important;}
#datatable-executionList .parent.has-child.c-name.flex {border-bottom: 1px solid #cbd0db !important;}
#datatable-executionList tr:last-child .c-name.flex {margin-top: 1px !important;}
+1 -1
View File
@@ -11,7 +11,7 @@ $(function()
if(isCNLang && nameWidth < 150 && !useDatatable) $('#executionsForm thead th.c-name').css('width', '150px');
if(!isCNLang && nameWidth < 200 && !useDatatable) $('#executionsForm thead th.c-name').css('width', '200px');
toggleFold('#executionsForm', unfoldExecutions, projectID, 'execution');
toggleFold('#executionsForm', unfoldExecutions, 0, 'execution');
$('.table td.has-child > .plan-toggle').each(function()
{
+3
View File
@@ -514,6 +514,9 @@ $lang->execution->featureBar['all']['doing'] = $lang->execution->statusList[
$lang->execution->featureBar['all']['suspended'] = $lang->execution->statusList['suspended'];
$lang->execution->featureBar['all']['closed'] = $lang->execution->statusList['closed'];
$lang->execution->featureBar['bug']['all'] = 'All';
$lang->execution->featureBar['bug']['unresolved'] = 'Active';
$lang->execution->featureBar['build']['all'] = 'Build List';
$lang->execution->myExecutions = 'Ich bin beteiligt.';
+3
View File
@@ -514,6 +514,9 @@ $lang->execution->featureBar['all']['doing'] = $lang->execution->statusList[
$lang->execution->featureBar['all']['suspended'] = $lang->execution->statusList['suspended'];
$lang->execution->featureBar['all']['closed'] = $lang->execution->statusList['closed'];
$lang->execution->featureBar['bug']['all'] = 'All';
$lang->execution->featureBar['bug']['unresolved'] = 'Active';
$lang->execution->featureBar['build']['all'] = 'Build List';
$lang->execution->myExecutions = 'Mine';
+3
View File
@@ -514,6 +514,9 @@ $lang->execution->featureBar['all']['doing'] = $lang->execution->statusList[
$lang->execution->featureBar['all']['suspended'] = $lang->execution->statusList['suspended'];
$lang->execution->featureBar['all']['closed'] = $lang->execution->statusList['closed'];
$lang->execution->featureBar['bug']['all'] = 'All';
$lang->execution->featureBar['bug']['unresolved'] = 'Active';
$lang->execution->featureBar['build']['all'] = 'Build List';
$lang->execution->myExecutions = "J'étais impliqué";
+3
View File
@@ -418,6 +418,9 @@ $lang->execution->featureBar['all']['doing'] = $lang->execution->statusList[
$lang->execution->featureBar['all']['suspended'] = $lang->execution->statusList['suspended'];
$lang->execution->featureBar['all']['closed'] = $lang->execution->statusList['closed'];
$lang->execution->featureBar['bug']['all'] = 'All';
$lang->execution->featureBar['bug']['unresolved'] = 'Active';
$lang->execution->featureBar['build']['all'] = 'Build List';
$lang->execution->myExecutions = 'Tôi tham gia';
+3
View File
@@ -514,6 +514,9 @@ $lang->execution->featureBar['all']['doing'] = $lang->execution->statusList[
$lang->execution->featureBar['all']['suspended'] = $lang->execution->statusList['suspended'];
$lang->execution->featureBar['all']['closed'] = $lang->execution->statusList['closed'];
$lang->execution->featureBar['bug']['all'] = '所有';
$lang->execution->featureBar['bug']['unresolved'] = '未解决';
$lang->execution->featureBar['build']['all'] = '所有版本';
$lang->execution->myExecutions = '我参与的';
+18 -2
View File
@@ -4361,6 +4361,8 @@ class executionModel extends model
$this->loadModel('execution');
$this->loadModel('programplan');
$today = helper::today();
if(!$isChild)
{
$trClass = 'is-top-level table-nest-child-hide';
@@ -4385,8 +4387,22 @@ class executionModel extends model
echo '<td>' . zget($users, $execution->PM) . '</td>';
echo "<td class='status-{$execution->status}'>" . zget($this->lang->project->statusList, $execution->status) . '</td>';
echo '<td>' . html::ring($execution->hours->progress) . '</td>';
echo '<td>' . $execution->begin . '</td>';
echo '<td>' . $execution->end . '</td>';
echo helper::isZeroDate($execution->begin) ? '<td></td>' : '<td>' . $execution->begin . '</td>';
if(!helper::isZeroDate($execution->end))
{
if($execution->status != 'closed')
{
echo strtotime($today) > strtotime($execution->end) ? '<td class="delayed" title="' . $this->lang->execution->delayed . '">' . $execution->end . '</td>' : '<td>' . $execution->end . '</td>';
}
else
{
echo '<td>' . $execution->end . '</td>';
}
}
else
{
echo '<td></td>';
}
echo "<td class='hours' title='{$execution->hours->totalEstimate}{$this->lang->execution->workHour}'>" . $execution->hours->totalEstimate . $this->lang->execution->workHourUnit . '</td>';
echo "<td class='hours' title='{$execution->hours->totalConsumed}{$this->lang->execution->workHour}'>" . $execution->hours->totalConsumed . $this->lang->execution->workHourUnit . '</td>';
echo "<td class='hours' title='{$execution->hours->totalLeft}{$this->lang->execution->workHour}'>" . $execution->hours->totalLeft . $this->lang->execution->workHourUnit . '</td>';
+8 -30
View File
@@ -16,14 +16,11 @@
$datatableId = $this->moduleName . ucfirst($this->methodName);
$useDatatable = (isset($config->datatable->$datatableId->mode) and $config->datatable->$datatableId->mode == 'datatable');
?>
<?php js::set('unfoldExecutions', array());?>
<?php js::set('useDatatable', $useDatatable);?>
<?php js::set('from', $from);?>
<?php js::set('projectID', $projectID);?>
<?php
/* Set unfold parent executionID. */
$unfoldExecutions = isset($config->execution->all->unfoldExecutions) ? json_decode($config->execution->all->unfoldExecutions, true) : array();
$unfoldExecutions = zget($unfoldExecutions, $projectID, array());
js::set('unfoldExecutions', $unfoldExecutions);
js::set('unfoldAll', $lang->execution->treeLevel['all']);
js::set('foldAll', $lang->execution->treeLevel['root']);
js::set('isCNLang', !$this->loadModel('common')->checkNotCN())
@@ -38,11 +35,11 @@ js::set('isCNLang', !$this->loadModel('common')->checkNotCN())
<?php
$class = '';
if($productID == 0) $class = 'class="active"';
echo "<li $class>" . html::a($this->createLink('project', 'execution', "status=$status&projectID=$projectID&orderby=$orderBy"), $lang->product->allProduct) . "</li>";
echo "<li $class>" . html::a($this->createLink('project', 'execution', "status=$status&orderby=$orderBy"), $lang->product->allProduct) . "</li>";
foreach($productList as $key => $product)
{
$class = $productID == $key ? 'class="active"' : '';
echo "<li $class>" . html::a($this->createLink('project', 'execution', "status=$status&projectID=$projectID&orderby=$orderBy&productID=$key"), $product) . "</li>";
echo "<li $class>" . html::a($this->createLink('project', 'execution', "status=$status&orderby=$orderBy&productID=$key"), $product) . "</li>";
}
?>
</ul>
@@ -52,22 +49,13 @@ js::set('isCNLang', !$this->loadModel('common')->checkNotCN())
<?php foreach($lang->execution->featureBar['all'] as $key => $label):?>
<?php $label = "<span class='text'>$label</span>";?>
<?php if($status == $key) $label .= " <span class='label label-light label-badge'>{$pager->recTotal}</span>";?>
<?php echo html::a($this->createLink($this->app->rawModule, $this->app->rawMethod, "status=$key&projectID=$projectID&orderBy=$orderBy&productID=$productID"), $label, '', "class='btn btn-link' id='{$key}Tab' data-app='$from'");?>
<?php echo html::a($this->createLink($this->app->rawModule, $this->app->rawMethod, "status=$key&orderBy=$orderBy&productID=$productID"), $label, '', "class='btn btn-link' id='{$key}Tab' data-app='$from'");?>
<?php endforeach;?>
<?php if($from == 'execution' and $this->config->systemMode == 'new'):?>
<div class='input-control w-180px'>
<?php echo html::select('project', $projects, $projectID, "class='form-control chosen' data-placeholder='{$lang->execution->selectProject}'");?>
</div>
<?php endif;?>
<a class="btn btn-link querybox-toggle" id='bysearchTab'><i class="icon icon-search muted"></i> <?php echo $lang->execution->byQuery;?></a>
</div>
<div class='btn-toolbar pull-right'>
<?php common::printLink('execution', 'export', "status=$status&productID=$productID&orderBy=$orderBy&from=$from", "<i class='icon-export muted'> </i> " . $lang->export, '', "class='btn btn-link export'")?>
<?php if(common::hasPriv('programplan', 'create') and $isStage):?>
<?php echo html::a($this->createLink('programplan', 'create', "projectID=$projectID&productID=$productID"), "<i class='icon icon-plus'></i> " . $lang->programplan->create, '', "class='btn btn-primary'");?>
<?php else: ?>
<?php if(common::hasPriv('execution', 'create')) echo html::a($this->createLink('execution', 'create', "projectID=$projectID"), "<i class='icon icon-sm icon-plus'></i> " . ((($from == 'execution') and ($config->systemMode == 'new')) ? $lang->execution->createExec : $lang->execution->create), '', "class='btn btn-primary create-execution-btn' data-app='execution' onclick='$(this).removeAttr(\"data-toggle\")'");?>
<?php endif;?>
<?php if(common::hasPriv('execution', 'create')) echo html::a($this->createLink('execution', 'create'), "<i class='icon icon-sm icon-plus'></i> " . ((($from == 'execution') and ($config->systemMode == 'new')) ? $lang->execution->createExec : $lang->execution->create), '', "class='btn btn-primary create-execution-btn' data-app='execution' onclick='$(this).removeAttr(\"data-toggle\")'");?>
</div>
</div>
<div id='mainContent' class="main-row fade">
@@ -77,12 +65,8 @@ js::set('isCNLang', !$this->loadModel('common')->checkNotCN())
<p>
<span class="text-muted"><?php echo $from == 'execution' ? $lang->execution->noExecutions : $lang->execution->noExecution;?></span>
<?php if(empty($allExecutionsNum)):?>
<?php if(common::hasPriv('programplan', 'create') and $isStage):?>
<?php echo html::a($this->createLink('programplan', 'create', "projectID=$projectID&productID=$productID"), "<i class='icon icon-plus'></i> " . $lang->programplan->create, '', "class='btn btn-info'");?>
<?php else: ?>
<?php if(common::hasPriv('execution', 'create')):?>
<?php echo html::a($this->createLink('execution', 'create', "projectID=$projectID"), "<i class='icon icon-plus'></i> " . (($from == 'execution' and $config->systemMode == 'new') ? $lang->execution->createExec : $lang->execution->create), '', "class='btn btn-info' data-app='execution'");?>
<?php endif;?>
<?php if(common::hasPriv('execution', 'create')):?>
<?php echo html::a($this->createLink('execution', 'create'), "<i class='icon icon-plus'></i> " . (($from == 'execution' and $config->systemMode == 'new') ? $lang->execution->createExec : $lang->execution->create), '', "class='btn btn-info' data-app='execution'");?>
<?php endif;?>
<?php endif;?>
</p>
@@ -94,7 +78,7 @@ js::set('isCNLang', !$this->loadModel('common')->checkNotCN())
<nav class="btn-toolbar pull-right setting"></nav>
</div>
<?php
$vars = "status=$status&projectID=$projectID&orderBy=%s&productID=$productID&param=$param&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";
$vars = "status=$status&orderBy=%s&productID=$productID&param=$param&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";
if($useDatatable) include '../../common/view/datatable.html.php';
else include '../../common/view/tablesorter.html.php';
@@ -167,12 +151,6 @@ $(document).on('click', '.plan-toggle', function(e)
e.stopPropagation();
e.preventDefault();
});
$('#project').change(function()
{
var projectID = $('#project').val();
location.href = createLink('execution', 'all', 'status=' + status + '&projectID=' + projectID);
});
</script>
<?php js::set('orderBy', $orderBy)?>
<?php js::set('status', $status)?>
+11 -6
View File
@@ -31,12 +31,17 @@
</div>
</div>
<div class="btn-toolbar pull-left">
<?php
$buildName = $build ? " <span class='label label-danger'>Build:{$build->name}</span>" : '';
$module = $type != 'bysearch' ? "&param=$param" : '';
echo html::a($this->inlink('bug', "executionID={$execution->id}&productID={$productID}&branch={$branchID}&orderBy=status,id_desc&build=$buildID&type=all$module"), "<span class='text'>{$lang->bug->allBugs}</span>" . ($type == 'all' ? " <span class='label label-light label-badge'>{$pager->recTotal}</span>$buildName" : ''), '', "id='allTab' class='btn btn-link" . ('all' == $type ? ' btn-active-text' : '') . "'");
echo html::a($this->inlink('bug', "executionID={$execution->id}&productID={$productID}&branch={$branchID}&orderBy=status,id_desc&build=$buildID&type=unresolved$module"), "<span class='text'>{$lang->bug->unResolved}</span>" . ($type == 'unresolved' ? " <span class='label label-light label-badge'>{$pager->recTotal}</span>$buildName" : ''), '', "id='unresolvedTab' class='btn btn-link" . ('unresolved' == $type ? ' btn-active-text' : '') . "'");
?>
<?php common::sortFeatureMenu();?>
<?php foreach($lang->execution->featureBar['bug'] as $featureType => $label):?>
<?php $active = $type == $featureType ? 'btn-active-text' : '';?>
<?php $label = "<span class='text'>$label</span>";?>
<?php if($type == $featureType):?>
<?php $label .= " <span class='label label-light label-badge'>{$pager->recTotal}</span>";?>
<?php $label .= $build ? " <span class='label label-danger'>Build:{$build->name}</span>" : '';?>
<?php endif;?>
<?php $module = $type != 'bysearch' ? "&param=$param" : '';?>
<?php echo html::a(inlink('bug', "executionID=$execution->id&productID={$productID}&branch={$branchID}&orderBy=status,id_desc&build=$buildID&type={$featureType}$module"), $label, '', "class='btn btn-link $active' id='{$featureType}Tab'");?>
<?php endforeach;?>
<a class="btn btn-link querybox-toggle" id="bysearchTab"><i class="icon icon-search muted"></i> <?php echo $lang->bug->search;?></a>
</div>
<div class="btn-toolbar pull-right">
+1 -1
View File
@@ -91,7 +91,7 @@
<th><?php echo $lang->execution->days;?></th>
<td>
<div class='input-group'>
<?php echo html::input('days', (isset($plan) && !empty($plan->begin) ? helper::workDays($plan->begin, $plan->end) : ''), "class='form-control'");?>
<?php echo html::input('days', (isset($plan) && !empty($plan->begin) ? (helper::workDays($plan->begin, $plan->end) + 1) : ''), "class='form-control'");?>
<span class='input-group-addon'><?php echo $lang->execution->day;?></span>
</div>
</td><td></td><td></td>
+2 -2
View File
@@ -754,8 +754,8 @@ $.extend(
var searchModule = types[0];
var searchMethod = typeof(types[1]) == 'undefined' ? 'view' : types[1];
var searchLink = createLink(searchModule, searchMethod, "id=" + objectValue);
var assetType = 'story,issue,risk,opportunity,doc';
if(assetType.indexOf(searchModule) > -1)
var assetType = ',story,issue,risk,opportunity,doc,';
if(assetType.indexOf(',' + searchModule + ',') > -1)
{
var link = createLink('index', 'ajaxGetViewMethod' , 'objectID=' + objectValue + '&objectType=' + searchModule);
$.get(link, function(data)
+26 -10
View File
@@ -3345,7 +3345,7 @@ class kanbanModel extends model
{
$groupBy = ($this->session->execGroupBy and ($this->app->tab == 'execution' or $this->config->vision == 'lite')) ? $this->session->execGroupBy : '';
$fromCell = $this->dao->select('cards, lane')->from(TABLE_KANBANCELL)
$fromCell = $this->dao->select('id,cards,lane')->from(TABLE_KANBANCELL)
->where('`column`')->eq($fromColID)
->beginIF(!$groupBy or $groupBy == 'default')->andWhere('lane')->eq($fromLaneID)->fi()
->beginIF($groupBy and $groupBy != 'default')
@@ -3355,20 +3355,36 @@ class kanbanModel extends model
->fetch();
if($groupBy and $groupBy != 'default') $fromLaneID = $toLaneID = $fromCell->lane;
$fromCells[$fromCell->id] = $fromCell;
$fromCellCards = $fromCell->cards;
$toCell = $this->dao->select('*')->from(TABLE_KANBANCELL)->where('lane')->eq($toLaneID)->andWhere('`column`')->eq($toColID)->fetch();
$toCellCards = $this->dao->select('cards')->from(TABLE_KANBANCELL)->where('lane')->eq($toLaneID)->andWhere('`column`')->eq($toColID)->fetch('cards');
/* Remove all cells with cardID in fromCell. */
$fromLane = $this->getLaneById($fromLaneID);
$fromCells += $this->dao->select('t1.id as id,t1.cards,t1.lane')->from(TABLE_KANBANCELL)->alias('t1')
->leftJoin(TABLE_KANBANLANE)->alias('t2')->on('t1.lane=t2.id')
->where('t1.type')->eq($fromLane->type)
->andWhere('t1.id')->ne($fromCell->id)
->andWhere('t2.region')->eq($fromLane->region)
->andWhere('t1.cards')->like("%,$cardID,%")
->fetchAll('id');
$kanbanID = $kanbanID == 0 ? $toCell->kanban : $kanbanID;
foreach($fromCells as $fromCell)
{
$fromCellCards = explode(',', $fromCell->cards);
$fromCellCards = array_unique($fromCellCards);
$fromCellCards = array_filter($fromCellCards);
$fromCellCards = implode(',', $fromCellCards);
$fromCardList = str_replace(",$cardID,", ',', ",$fromCellCards,");
if($fromCardList == ',') $fromCardList = '';
$this->dao->update(TABLE_KANBANCELL)->set('cards')->eq($fromCardList)->where('id')->eq($fromCell->id)->exec();
}
/* Add cardID to toCell. */
$toCell = $this->dao->select('*')->from(TABLE_KANBANCELL)->where('lane')->eq($toLaneID)->andWhere('`column`')->eq($toColID)->fetch();
$toCellCards = $this->dao->select('cards')->from(TABLE_KANBANCELL)->where('lane')->eq($toLaneID)->andWhere('`column`')->eq($toColID)->fetch('cards');
$kanbanID = $kanbanID == 0 ? $toCell->kanban : $kanbanID;
if(!$toCell) $this->addKanbanCell($kanbanID, $toLaneID, $toColID, 'common');
$fromCardList = str_replace(",$cardID,", ',', $fromCellCards);
$toCardList = rtrim($toCellCards, ',') . ",$cardID,";
if($fromCardList == ',') $fromCardList = '';
$this->dao->update(TABLE_KANBANCELL)->set('cards')->eq($fromCardList)->where('`column`')->eq($fromColID)->andWhere('lane')->eq($fromLaneID)->exec();
$toCardList = rtrim($toCellCards, ',') . ",$cardID,";
$this->dao->update(TABLE_KANBANCELL)->set('cards')->eq($toCardList)->where('`column`')->eq($toColID)->andWhere('lane')->eq($toLaneID)->exec();
}
+7 -7
View File
@@ -336,7 +336,7 @@ EOF;
if($type == 'assignedBy')
{
$stories = $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, '', 'story');
$stories = $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, 'story');
}
elseif($type == 'bysearch')
{
@@ -400,7 +400,7 @@ EOF;
if($type == 'assignedBy')
{
$stories = $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, '', 'requirement');
$stories = $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, 'requirement');
}
elseif($type == 'bysearch')
{
@@ -468,7 +468,7 @@ EOF;
/* Get tasks. */
if($type == 'assignedBy')
{
$tasks = $this->my->getAssignedByMe($this->app->user->account, 0, $pager, $sort, 0, 'task');
$tasks = $this->my->getAssignedByMe($this->app->user->account, 0, $pager, $sort, 'task');
}
elseif($type == 'bySearch')
{
@@ -571,7 +571,7 @@ EOF;
$sort = common::appendOrder($orderBy);
if($type == 'assignedBy')
{
$bugs = $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, '', 'bug');
$bugs = $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, 'bug');
}
else
{
@@ -877,7 +877,7 @@ EOF;
$this->view->pager = $pager;
$this->view->type = $type;
$this->view->param = $param;
$this->view->issues = $type == 'assignedBy' ? $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, '', 'issue') : $this->loadModel('issue')->getUserIssues($type, $queryID, $this->app->user->account, $orderBy, $pager);
$this->view->issues = $type == 'assignedBy' ? $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, 'issue') : $this->loadModel('issue')->getUserIssues($type, $queryID, $this->app->user->account, $orderBy, $pager);
$this->view->projectList = $this->loadModel('project')->getPairsByProgram();
@@ -911,7 +911,7 @@ EOF;
/* Get risks by type*/
if($type == 'assignedBy')
{
$risks = $this->my->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, '', 'risk');
$risks = $this->my->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, 'risk');
}
else
{
@@ -1002,7 +1002,7 @@ EOF;
$this->app->loadClass('pager', $static = true);
if($this->app->getViewType() == 'mhtml') $recPerPage = 10;
$pager = pager::init($recTotal, $recPerPage, $pageID);
$ncList = $browseType == 'assignedBy' ? $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, '', 'nc') : $this->my->getNcList($browseType, $orderBy, $pager, 'active');
$ncList = $browseType == 'assignedBy' ? $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, 'nc') : $this->my->getNcList($browseType, $orderBy, $pager, 'active');
foreach($ncList as $nc) $ncIdList[] = $nc->id;
$this->session->set('ncIdList', isset($ncIdList) ? $ncIdList : '');
+6
View File
@@ -21,3 +21,9 @@ td.delayed {background: #e84e0f !important; color: white;}
html[lang="en"] .c-date {width: 80px;}
html[lang="en"] .c-user-short {width: 88px;}
[lang^='de'] .c-user-short, [lang^='fr'] .c-user-short {width: 75px;}
[lang^='de'] .c-date, [lang^='fr'] .c-date {width: 100px;}
[lang^='de'] .c-user, [lang^='fr'] .c-user {width: 118px;}
[lang^='de'] .c-hours.consumed {width: 70px;}
[lang^='de'] .c-hours.estimate {width: 75px;}
[lang^='de'] .c-project {width: 100px;}
+5 -5
View File
@@ -322,7 +322,7 @@ class myModel extends model
* @access public
* @return array
*/
public function getAssignedByMe($account, $limit = 0, $pager = null, $orderBy = "id_desc", $projectID = 0, $objectType = '')
public function getAssignedByMe($account, $limit = 0, $pager = null, $orderBy = "id_desc", $objectType = '')
{
$module = $objectType == 'requirement' ? 'story' : $objectType;
$this->loadModel($module);
@@ -550,7 +550,7 @@ class myModel extends model
$taskIDList = array();
if($moduleName == 'contributeTask')
{
$tasksAssignedByMe = $this->getAssignedByMe($account, 0, $pager, $orderBy, 0, 'task');
$tasksAssignedByMe = $this->getAssignedByMe($account, 0, '', $orderBy, 'task');
foreach($tasksAssignedByMe as $taskID => $task)
{
$taskIDList[$taskID] = $taskID;
@@ -725,7 +725,7 @@ class myModel extends model
if($type == 'contribute')
{
$assignedByMe = $this->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, '', 'risk');
$assignedByMe = $this->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, 'risk');
$risks = $this->dao->select('*')->from(TABLE_RISK)
->where($riskQuery)
@@ -822,7 +822,7 @@ class myModel extends model
$storyIDList = array();
if($type == 'contribute')
{
$storiesAssignedByMe = $this->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, '', 'story');
$storiesAssignedByMe = $this->getAssignedByMe($this->app->user->account, '', '', $orderBy, 'story');
foreach($storiesAssignedByMe as $storyID => $story)
{
$storyIDList[$storyID] = $storyID;
@@ -941,7 +941,7 @@ class myModel extends model
$requirementIDList = array();
if($type == 'contribute')
{
$requirementsAssignedByMe = $this->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, '', 'requirement');
$requirementsAssignedByMe = $this->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, 'requirement');
foreach($requirementsAssignedByMe as $requirementID => $requirement)
{
$requirementIDList[$requirementID] = $requirementID;
+1 -1
View File
@@ -65,7 +65,7 @@
<?php if($action->objectType == 'meeting') $tab = $action->project ? "data-app='project'" : "data-app='my'";?>
<span class='label-name'>
<?php
if(($config->edition == 'max' and strpos($config->action->assetType, $action->objectType) !== false) and empty($action->objectName))
if(($config->edition == 'max' and strpos($config->action->assetType, ",{$action->objectType},") !== false) and empty($action->objectName))
{
echo '#' . $action->objectID;
}
+2 -2
View File
@@ -78,8 +78,8 @@
<?php if($type != 'finishedBy'): ?>
<th class='c-user'><?php common::printOrderLink('finishedBy', $orderBy, $vars, $lang->task->finishedBy);?></th>
<?php endif;?>
<th class='c-hours'><?php common::printOrderLink('estimate', $orderBy, $vars, $lang->task->estimateAB);?></th>
<th class='c-hours'><?php common::printOrderLink('consumed', $orderBy, $vars, $lang->task->consumedAB);?></th>
<th class='c-hours estimate'><?php common::printOrderLink('estimate', $orderBy, $vars, $lang->task->estimateAB);?></th>
<th class='c-hours consumed'><?php common::printOrderLink('consumed', $orderBy, $vars, $lang->task->consumedAB);?></th>
<th class='c-hours'><?php common::printOrderLink('left', $orderBy, $vars, $lang->task->leftAB);?></th>
<th class='c-status'><?php common::printOrderLink('status', $orderBy, $vars, $lang->statusAB);?></th>
<th class="c-actions-6 text-center"><?php echo $lang->actions;?></th>
+5 -13
View File
@@ -43,14 +43,12 @@
<?php
$vars = "mode=$mode&type=$type&param=$param&orderBy=%s&recTotal=$recTotal&recPerPage=$recPerPage&pageID=$pageID";
$this->app->loadLang('testtask');
$canBatchRun = (common::hasPriv('testtask', 'batchRun') and $type == 'assigntome');
$canBatchEdit = (common::hasPriv('testcase', 'batchEdit') and $type == 'assigntome');
$canBatchAction = ($canBatchRun or $canBatchEdit);
$canBatchEdit = (common::hasPriv('testcase', 'batchEdit') and $type == 'assigntome');
?>
<thead>
<tr>
<th class="<?php echo $canBatchAction ? 'w-100px' : 'w-50px';?>">
<?php if($canBatchAction):?>
<th class="<?php echo $canBatchEdit ? 'w-100px' : 'w-50px';?>">
<?php if($canBatchEdit):?>
<div class="checkbox-primary check-all" title="<?php echo $lang->selectAll?>">
<label></label>
</div>
@@ -80,7 +78,7 @@
?>
<tr>
<td class="c-id">
<?php if($canBatchAction):?>
<?php if($canBatchEdit):?>
<div class="checkbox-primary">
<input type='checkbox' name='caseIDList[]' value='<?php echo $case->id;?>' <?php if(!$canBeChanged) echo 'disabled';?> />
<label></label>
@@ -120,7 +118,7 @@
</tbody>
</table>
<div class="table-footer">
<?php if($canBatchAction):?>
<?php if($canBatchEdit):?>
<div class="checkbox-primary check-all"><label><?php echo $lang->selectAll?></label></div>
<?php endif;?>
<div class="table-actions btn-toolbar">
@@ -131,12 +129,6 @@
$misc = "data-form-action='$actionLink'";
echo html::commonButton($lang->edit, $misc);
}
if($canBatchRun)
{
$actionLink = $this->createLink('testtask', 'batchRun', 'productID=0');
$misc = "data-form-action='$actionLink'";
echo html::commonButton($lang->testtask->runCase, $misc);
}
?>
</div>
<?php $pager->show('right', 'pagerjs');?>
+1 -1
View File
@@ -32,7 +32,7 @@ $(function()
}
else
{
$.apps.open(createLink('execution', 'create', 'projectID=' + projectID + '&executionID=&copyExecutionID=&planID=' + planID + '&confirm=&productID=' + productID), 'project')
$.apps.open(createLink('execution', 'create', 'projectID=' + projectID + '&executionID=&copyExecutionID=&planID=' + planID + '&confirm=&productID=' + productID), 'execution')
}
$('#projects').modal('hide');
});
+51
View File
@@ -86,6 +86,18 @@ class programplan extends control
$plans = $this->programplan->getDataForGantt($projectID, $this->productID, $baselineID, $selectCustom, false);
}
if($type == 'assignedTo')
{
$owner = $this->app->user->account;
$module = 'programplan';
$section = 'browse';
$object = 'stageCustom';
$selectCustom = $this->loadModel('setting')->getItem("owner={$owner}&module={$module}&section={$section}&key={$object}");
if(strpos($selectCustom, 'date') !== false) $dateDetails = 0;
$plans = $this->programplan->getDataForGanttGroupByAssignedTo($projectID, $this->productID, $baselineID, $selectCustom, false);
}
if($type == 'lists')
{
$sort = common::appendOrder($orderBy);
@@ -103,6 +115,7 @@ class programplan extends control
$this->view->selectCustom = $selectCustom;
$this->view->dateDetails = $dateDetails;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->ganttType = $type;
$this->display();
}
@@ -237,4 +250,42 @@ class programplan extends control
$response['message'] = '';
return $this->send($response);
}
/**
* Save task drag position.
*
* @access public
* @return void
*/
public function ajaxSaveTaskDrag()
{
if(!empty($_POST))
{
if(!isset($_POST['id']) or empty($_POST['id'])) return $this->send(array('result' => 'fail', 'message' => ''));
$objectID = $_POST['id'];
$this->loadModel('task')->saveTaskDrag($objectID, $_POST['type']);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return $this->send(array('result' => 'success'));
}
}
/**
* Save task drag action.
*
* @param int $productID
*
* @access public
* @access public
* @return void
*/
public function ajaxSaveGanttMove($productID = 0)
{
if(!empty($_POST))
{
$this->loadModel('task')->saveTaskMove($productID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return $this->send(array('result' => 'success'));
}
}
}
+2
View File
@@ -12,6 +12,7 @@
$lang->programplan->common = 'Program Plan';
$lang->programplan->browse = 'Program Plan';
$lang->programplan->gantt = 'Gantt Chart';
$lang->programplan->ganttEdit = 'Gantt Edit';
$lang->programplan->list = 'Stage List';
$lang->programplan->create = 'Create';
$lang->programplan->edit = 'Edit';
@@ -84,3 +85,4 @@ $lang->programplan->error->createdTask = 'The task has been decomposed. Sub
$lang->programplan->error->parentWorkload = 'The sum of the workload of the child phase cannot be greater than that of the parent phase: %s.';
$lang->programplan->error->parentDuration = 'The planned start and planned completion of the child phase cannot exceed the parent phase.';
$lang->programplan->error->sameName = 'Stage name cannot be the same!';
$lang->programplan->error->taskDrag = 'The %s task cannot be dragged';
+2
View File
@@ -12,6 +12,7 @@
$lang->programplan->common = 'Program Plan';
$lang->programplan->browse = 'Gantt Chart';
$lang->programplan->gantt = 'Gantt Chart';
$lang->programplan->ganttEdit = 'Gantt Edit';
$lang->programplan->list = 'Stage List';
$lang->programplan->create = 'Create';
$lang->programplan->edit = 'Edit';
@@ -84,3 +85,4 @@ $lang->programplan->error->createdTask = 'The task is decomposed. Sub stages
$lang->programplan->error->parentWorkload = 'The sum of the workload in the sub stage cannot be > that in the parent stage: %s.';
$lang->programplan->error->parentDuration = 'The planned start and planned completion of the child phase cannot exceed the parent phase.';
$lang->programplan->error->sameName = 'Stage name cannot be the same!';
$lang->programplan->error->taskDrag = 'The %s task cannot be dragged';
+2
View File
@@ -12,6 +12,7 @@
$lang->programplan->common = 'Program Plan';
$lang->programplan->browse = 'Program Plan';
$lang->programplan->gantt = 'Gantt Chart';
$lang->programplan->ganttEdit = 'Gantt Edit';
$lang->programplan->list = 'Stage List';
$lang->programplan->create = 'Create';
$lang->programplan->edit = 'Edit';
@@ -84,3 +85,4 @@ $lang->programplan->error->createdTask = 'The task has been decomposed. Sub
$lang->programplan->error->parentWorkload = 'The sum of the workload of the child phase cannot be greater than that of the parent phase: %s.';
$lang->programplan->error->parentDuration = 'The planned start and planned completion of the child phase cannot exceed the parent phase.';
$lang->programplan->error->sameName = 'Stage name cannot be the same!';
$lang->programplan->error->taskDrag = 'The %s task cannot be dragged';
+7
View File
@@ -12,6 +12,7 @@
$lang->programplan->common = '项目阶段';
$lang->programplan->browse = '浏览甘特图';
$lang->programplan->gantt = '甘特图';
$lang->programplan->ganttEdit = '甘特图编辑';
$lang->programplan->list = '阶段列表';
$lang->programplan->create = '设置阶段';
$lang->programplan->edit = '编辑';
@@ -84,3 +85,9 @@ $lang->programplan->error->createdTask = '已分解任务,不可添加子
$lang->programplan->error->parentWorkload = '子阶段的工作量之和不能大于父阶段的工作量:%s';
$lang->programplan->error->parentDuration = '子阶段计划开始、计划完成不能超过父阶段';
$lang->programplan->error->sameName = '阶段名称不能相同!';
$lang->programplan->error->taskDrag = '%s的任务不可以拖动';
$lang->programplan->error->planDrag = '%s的阶段不可以拖动';
$lang->programplan->ganttBrowseType['gantt'] = '按阶段分组';
$lang->programplan->ganttBrowseType['assignedTo'] = '按指派给分组';
+196 -9
View File
@@ -191,17 +191,17 @@ class programplanModel extends model
$data->status = $this->processStatus('execution', $plan);
$data->begin = $start;
$data->deadline = $end;
$data->realBegan = helper::isZeroDate($plan->realBegan) ? '' : substr($plan->realBegan, 0, 10);
$data->realEnd = helper::isZeroDate($plan->realEnd) ? '' : substr($plan->realEnd, 0, 10);
$data->realBegan = helper::isZeroDate($plan->realBegan) ? '' : $plan->realBegan;
$data->realEnd = helper::isZeroDate($plan->realEnd) ? '' : $plan->realEnd;
$data->parent = $plan->grade == 1 ? 0 :$plan->parent;
$data->open = true;
$data->start_date = $data->realBegan ? $data->realBegan : $data->begin;
$data->endDate = $data->realEnd ? $data->realEnd : $data->deadline;
$data->duration = 0;
$data->duration = 1;
if($data->endDate > $data->start_date) $data->duration = helper::diffDate($data->endDate, $data->start_date) + 1;
if($data->start_date) $data->start_date = date('d-m-Y', strtotime($data->start_date));
if($data->start_date == '' or $data->endDate == '') $data->duration = 0;
if($data->start_date == '' or $data->endDate == '') $data->duration = 1;
$datas['data'][$plan->id] = $data;
$stageIndex[$plan->id] = array('planID' => $plan->id, 'parent' => $plan->parent, 'progress' => array('totalConsumed' => 0, 'totalReal' => 0));
@@ -218,7 +218,7 @@ class programplanModel extends model
if(empty($selectCustom)) $selectCustom = $this->loadModel('setting')->getItem("owner={$owner}&module={$module}&section={$section}&key={$object}");
$tasks = $this->dao->select('*')->from(TABLE_TASK)->where('deleted')->eq(0)->andWhere('execution')->in($planIdList)->fetchAll('id');
$tasks = $this->dao->select('*')->from(TABLE_TASK)->where('deleted')->eq(0)->andWhere('execution')->in($planIdList)->orderBy('execution_asc, order_asc, id_desc')->fetchAll('id');
$taskTeams = $this->dao->select('root,account')->from(TABLE_TEAM)->where('type')->eq('task')->andWhere('root')->in(array_keys($tasks))->fetchGroup('root', 'account');
$users = $this->loadModel('user')->getPairs('noletter');
@@ -242,8 +242,8 @@ class programplanModel extends model
$estStart = helper::isZeroDate($task->estStarted) ? '' : $task->estStarted;
$estEnd = helper::isZeroDate($task->deadline) ? '' : $task->deadline;
$realBegan = helper::isZeroDate($task->realStarted) ? '' : substr($task->realStarted, 0, 10);
$realEnd = (in_array($task->status, array('done', 'closed')) and !helper::isZeroDate($task->finishedDate)) ? substr($task->finishedDate, 0, 10) : '';
$realBegan = helper::isZeroDate($task->realStarted) ? '' : $task->realStarted;
$realEnd = (in_array($task->status, array('done', 'closed')) and !helper::isZeroDate($task->finishedDate)) ? $task->finishedDate : '';
$start = $realBegan ? $realBegan : $estStart;
$end = $realEnd ? $realEnd : $estEnd;
@@ -272,7 +272,7 @@ class programplanModel extends model
$data->taskProgress = ($progress * 100) . '%';
$data->start_date = $start;
$data->endDate = $end;
$data->duration = 0;
$data->duration = 1;
/* If multi task then show the teams. */
if($task->mode == 'multi' and !empty($taskTeams[$task->id]))
@@ -285,7 +285,7 @@ class programplanModel extends model
if($data->endDate > $data->start_date) $data->duration = helper::diffDate($data->endDate, $data->start_date) + 1;
if($data->start_date) $data->start_date = date('d-m-Y', strtotime($data->start_date));
if($data->start_date == '' or $data->endDate == '') $data->duration = 0;
if($data->start_date == '' or $data->endDate == '') $data->duration = 1;
if(strpos($selectCustom, 'task') !== false) $datas['data'][$data->id] = $data;
foreach($stageIndex as $index => $stage)
@@ -333,6 +333,193 @@ class programplanModel extends model
return $returnJson ? json_encode($datas) : $datas;
}
/**
* Get gantt data group by assigned.
*
* @param int $executionID
* @param int $productID
* @param int $baselineID
* @param string $selectCustom
* @param bool $returnJson
* @access public
* @return string
*/
public function getDataForGanttGroupByAssignedTo($executionID, $productID, $baselineID = 0, $selectCustom = '', $returnJson = true)
{
$plans = $this->getStage($executionID, $productID);
$datas = array();
$planIdList = array();
$isMilestone = "<icon class='icon icon-flag icon-sm red'></icon> ";
$stageIndex = array();
foreach($plans as $plan) $planIdList[$plan->id] = $plan->id;
$taskSign = "<span class='task-label'>[ T ] </span>";
$taskPri = "<span class='label-pri label-pri-%s' title='%s'>%s</span> ";
/* Judge whether to display tasks under the stage. */
$owner = $this->app->user->account;
$module = 'programplan';
$section = 'browse';
$object = 'stageCustom';
if(empty($selectCustom)) $selectCustom = $this->loadModel('setting')->getItem("owner={$owner}&module={$module}&section={$section}&key={$object}");
$tasksGroup = $this->dao->select('*')->from(TABLE_TASK)->where('deleted')->eq(0)->andWhere('execution')->in($planIdList)->fetchGroup('assignedTo','id');
$users = $this->loadModel('user')->getPairs('noletter');
$tasksMap = array();
foreach($tasksGroup as $group => $tasks)
{
foreach($tasks as $id => $task)
{
if($task->mode == 'multi')
{
$team = $this->dao->select('t1.*,t2.realname')->from(TABLE_TEAM)->alias('t1')
->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account')
->where('t1.root')->eq($id)->andWhere('t1.type')->eq('task')->orderBy('t1.order')->fetchAll('account');
foreach($team as $account => $member)
{
if($account == $group) continue;
if(!isset($taskGroups[$account])) $taskGroups[$account] = array();
$taskGroups[$account][$id] = clone $task;
$taskGroups[$account][$id]->id = $id . '_' . $account;
$taskGroups[$account][$id]->realID = $id;
$taskGroups[$account][$id]->assignedTo = $account;
$taskGroups[$account][$id]->realname = $member->realname;
}
}
$tasksMap[$task->id] = $task;
}
}
$groupID = 0;
foreach($tasksGroup as $group => $tasks)
{
$groupID --;
$groupName = $group;
$groupName = zget($users, $group);
$dataGroup = new stdclass();
$dataGroup->id = $groupID;
$dataGroup->type = 'group';
$dataGroup->text = $groupName;
$dataGroup->percent = '';
$dataGroup->attribute = '';
$dataGroup->milestone = '';
$dataGroup->owner_id = $group;
$dataGroup->status = '';
$dataGroup->begin = '';
$dataGroup->deadline = '';
$dataGroup->realBegan = '';
$dataGroup->realEnd = '';
$dataGroup->parent = 0;
$dataGroup->open = true;
$dataGroup->progress = '';
$dataGroup->taskProgress = '';
$groupKey = $groupID . $group;
$datas['data'][$groupKey] = $dataGroup;
$realStartDate = array();
$realEndDate = array();
$totalTask = count($tasks);
foreach($tasks as $taskID => $task)
{
$execution = zget($plans, $task->execution, array());
$priIcon = sprintf($taskPri, $task->pri, $task->pri, $task->pri);
$estStart = helper::isZeroDate($task->estStarted) ? '' : $task->estStarted;
$estEnd = helper::isZeroDate($task->deadline) ? '' : $task->deadline;
$realBegan = helper::isZeroDate($task->realStarted) ? '' : $task->realStarted;
$realEnd = (in_array($task->status, array('done', 'closed')) and !helper::isZeroDate($task->finishedDate)) ? $task->finishedDate : '';
$start = $realBegan ? $realBegan : $estStart;
$end = $realEnd ? $realEnd : $estEnd;
if(empty($start) and $execution) $start = $execution->begin;
if(empty($end) and $execution) $end = $execution->end;
if($start > $end) $end = $start;
$data = new stdclass();
$data->id = $task->id;
$data->type = 'task';
$data->text = $taskSign . $priIcon . $task->name;
$data->percent = '';
$data->status = $this->processStatus('task', $task);
$data->owner_id = $task->assignedTo;
$data->attribute = '';
$data->milestone = '';
$data->begin = $start;
$data->deadline = $end;
$data->realBegan = $realBegan;
$data->realEnd = $realEnd;
$data->pri = $task->pri;
$data->parent = ($task->parent > 0 and $task->assignedTo != '' and !empty($tasksMap[$task->parent]->assignedTo)) ? $task->parent : $groupID;
$data->open = true;
$progress = $task->consumed ? round($task->consumed / ($task->left + $task->consumed), 3) : 0;
$data->progress = $progress;
$data->taskProgress = ($progress * 100) . '%';
$data->start_date = $start;
$data->endDate = $end;
$data->duration = 1;
if($data->endDate > $data->start_date) $data->duration = helper::diffDate($data->endDate, $data->start_date) + 1;
if($data->start_date) $data->start_date = date('d-m-Y', strtotime($data->start_date));
if($data->start_date == '' or $data->endDate == '') $data->duration = 1;
if(strpos($selectCustom, 'task') !== false) $datas['data'][$data->id] = $data;
if(!empty($start)) $realStartDate[] = strtotime($start);
if(!empty($end)) $realEndDate[] = strtotime($end);
if(isset($stageIndex[$groupKey]['totalConsumed']))
{
$stageIndex[$groupKey]['totalConsumed'] += $task->consumed;
$stageIndex[$groupKey]['totalReal'] += $task->left + $task->consumed;
}
else
{
$stageIndex[$groupKey]['totalConsumed'] = $task->consumed;
$stageIndex[$groupKey]['totalReal'] = $task->left + $task->consumed;
}
}
/* Calculate group realBegan and realEnd. */
if(!empty($realStartDate)) $datas['data'][$groupKey]->realBegan = date('Y-m-d H:i:s', min($realStartDate));
if(!empty($realEndDate) and (count($realEndDate) == $totalTask)) $datas['data'][$groupKey]->realEnd = date('Y-m-d H:i:s', max($realEndDate));
}
/* Calculate the progress of the phase. */
foreach($stageIndex as $index => $stage)
{
$progress = empty($stage['totalReal']) ? 0 : round($stage['totalConsumed'] / $stage['totalReal'], 3);
$datas['data'][$index]->progress = $progress;
$progress = ($progress * 100) . '%';
$datas['data'][$index]->taskProgress = $progress;
}
$datas['links'] = array();
if($this->config->edition != 'open')
{
$relations = $this->dao->select('*')->from(TABLE_RELATIONOFTASKS)->where('execution')->in($planIdList)->orderBy('task,pretask')->fetchAll();
foreach($relations as $relation)
{
$link['source'] = $relation->execution . '-' . $relation->pretask;
$link['target'] = $relation->execution . '-' . $relation->task;
$link['type'] = $this->config->execution->gantt->linkType[$relation->condition][$relation->action];
$datas['links'][] = $link;
}
}
$datas['data'] = isset($datas['data']) ? array_values($datas['data']) : array();
return $returnJson ? json_encode($datas) : $datas;
}
/**
* Get total percent.
*
+1 -1
View File
@@ -24,7 +24,7 @@
</p>
</div>
<?php else:?>
<?php if($type == 'gantt') include './gantt.html.php';?>
<?php if($type == 'gantt' or $type == 'assignedTo') include './gantt.html.php';?>
<?php if($type == 'lists') include './list.html.php';?>
<?php endif;?>
</div>
+145 -30
View File
@@ -60,16 +60,19 @@ form {display: block; margin-top: 0em; margin-block-end: 1em;}
#mainContent.loading #ganttContainer {padding: 40px;}
#mainContent.loading .scrollVer_cell,
#mainContent.loading .scrollVer_cell {display: none;}
#
.gantt-fullscreen #header,
.gantt-fullscreen #mainMenu,
.gantt-fullscreen #footer {display: none!important;}
.gantt-fullscreen #mainContent {position: fixed; top: 0; right: 0; bottom: 0; left: 0}
.gantt_grid_head_cell.gantt_grid_head_text{overflow:visible;}
</style>
<?php js::set('customUrl', $this->createLink('programplan', 'ajaxCustom'));?>
<?php js::set('dateDetails', $dateDetails);?>
<?php js::set('module', $app->rawModule);?>
<?php js::set('method', $app->rawMethod);?>
<?php js::set('ganttType', $ganttType);?>
<?php js::set('canGanttEdit', common::hasPriv('programplan', 'ganttEdit'));?>
<div id='mainContent' class='main-content load-indicator' data-loading='<?php echo $lang->programplan->exporting;?>'>
<form class="main-form form-ajax not-watch">
<div class="example">
@@ -93,6 +96,16 @@ form {display: block; margin-top: 0em; margin-block-end: 1em;}
</div>
<?php $fileName = "gantt-export-{$projectID}";?>
<a id='ganttDownload' target='hiddenwin' download='<?php echo "{$fileName}.png";?>'></a>
<?php
$typeHtml = '<div class="btn-group">';
$typeHtml .= '<button class="btn btn-link" data-toggle="dropdown"><span class="text">' . $lang->programplan->ganttBrowseType[$ganttType] . '</span> <span class="caret"></span></button>';
$typeHtml .= '<ul class="dropdown-menu">';
foreach($lang->programplan->ganttBrowseType as $browseType => $typeName)
{
$typeHtml .= '<li ' . ($ganttType == $browseType ? "class='active'" : '') . '>' . html::a($this->createLink('programplan', 'browse', "projectID=$projectID&productID=$productID&type=$browseType"), $typeName) . '</li>';
}
$typeHtml .= '</ul></div>';
?>
</div>
<script>
var scriptLoadedMap = {};
@@ -381,6 +394,67 @@ function exitHandler()
}
}
/* Validate task drag. */
function validateResources(id)
{
var task = gantt.getTask(id);
var from = new Date(task.start_date),
to = new Date(task.end_date);
var status = task.status;
var type = task.type;
var statusLang = "<?php echo $lang->task->statusList['wait'];?>";
flag = true;
/* Check status. */
if(status !== statusLang)
{
if(type == 'task')
{
tipMsg = "<?php echo $lang->programplan->error->taskDrag;?>";
}
else
{
tipMsg = "<?php echo $lang->programplan->error->planDrag;?>";
}
new $.zui.Messager(tipMsg.replace('%s', status), {
type: 'danger',
icon: 'exclamation-sign'
}).show();
gantt.refreshData();
return false;
}
/* Check data. */
var postData = {
'id' : type == 'task' ? task.id.split("-")[1] : task.id,
'start_date': from.toLocaleDateString('en-CA'),
'end_date' : to.toLocaleDateString('en-CA'),
'type' : type
};
var link = createLink('programplan', 'ajaxSaveTaskDrag');
/* Sync Close. */
$.ajax({
url: link,
dataType: "json",
async: false,
data: postData,
type: "post",
success: function(response)
{
if(response.result == 'fail' && response.message)
{
new $.zui.Messager(response.message, {
type: 'danger',
icon: 'exclamation-sign'
}).show();
flag = false;
}
}
});
return flag;
}
$(function()
{
document.addEventListener('fullscreenchange', exitHandler);
@@ -409,40 +483,46 @@ $(function()
?>
gantt.serverList("userList", <?php echo json_encode($userList);?>);
gantt.config.readonly = true;
gantt.config.smart_rendering = true;
gantt.config.smart_scales = true;
gantt.config.static_background = true;
gantt.config.show_task_cells = false;
gantt.config.row_height = 25;
gantt.config.min_column_width = 40;
gantt.config.details_on_create = false;
gantt.config.scales = [{unit: "year", step: 1, format: "%Y"}, {unit: 'day', step: 1, format: '%m-%d'}];
gantt.config.scale_height = 22 * gantt.config.scales.length;
gantt.config.duration_unit = "day";
gantt.config.readonly = canGanttEdit ? false : true;
gantt.config.details_on_dblclick = false;
gantt.config.order_branch = ganttType == 'assignedTo' ? false : 'marker';
gantt.config.drag_progress = false;
gantt.config.drag_links = false;
gantt.config.drag_move = ganttType == 'assignedTo' ? false : true;
gantt.config.drag_resize = ganttType == 'assignedTo' ? false : true;
gantt.config.smart_rendering = true;
gantt.config.smart_scales = true;
gantt.config.static_background = true;
gantt.config.show_task_cells = false;
gantt.config.row_height = 25;
gantt.config.min_column_width = 40;
gantt.config.details_on_create = false;
gantt.config.scales = [{unit: "year", step: 1, format: "%Y"}, {unit: 'day', step: 1, format: '%m-%d'}];
gantt.config.scale_height = 22 * gantt.config.scales.length;
gantt.config.duration_unit = "day";
gantt.config.columns = [
{name: 'text', width: '*', tree: true, resize: true, width:200},
{name: 'status', align: 'center', resize: true, width: 80},
{name: 'begin', align: 'center', resize: true, width: 80},
{name: 'deadline', align: 'center', resize: true, width: 80},
{name: 'duration', align: 'center', resize: true, width: 60},
{name: 'percent', align: 'center', resize: true, width:70, template: function(plan)
{name: 'text', width: '*', tree: true, resize: true, width:200},
{name: 'status', align: 'center', resize: true, width: 80},
{name: 'start_date', align: 'center', resize: true, width: 80},
{name: 'end_date', align: 'center', resize: true, width: 80},
{name: 'duration', align: 'center', resize: true, width: 60},
{name: 'percent', align: 'center', resize: true, width:70, template: function(plan)
{
if(plan.percent) return Math.round(plan.percent) + '%';
}
},
{name: 'taskProgress', align: 'center', resize: true, width: 60},
{name: 'realBegan', align: 'center', resize: true, width: 80},
{name: 'realEnd', align: 'center', width: 80}
{name: 'realBegan', align: 'center', resize: true, width: 150},
{name: 'realEnd', align: 'center', width: 150}
];
gantt.locale.labels.column_text = "<?php echo $lang->programplan->name;?>";
gantt.locale.labels.column_text = <?php echo json_encode($typeHtml);?>;
gantt.locale.labels.column_status = "<?php echo $lang->statusAB;?>";
gantt.locale.labels.column_percent = "<?php echo $lang->programplan->percentAB;?>";
gantt.locale.labels.column_taskProgress = "<?php echo $lang->programplan->taskProgress;?>";
gantt.locale.labels.column_begin = "<?php echo $lang->programplan->begin;?>";
gantt.locale.labels.column_deadline = "<?php echo $lang->programplan->end;?>";
gantt.locale.labels.column_start_date = "<?php echo $lang->programplan->begin;?>";
gantt.locale.labels.column_end_date = "<?php echo $lang->programplan->end;?>";
gantt.locale.labels.column_realBegan = "<?php echo $lang->programplan->realBegan;?>";
gantt.locale.labels.column_realEnd = "<?php echo $lang->programplan->realEnd;?>";
gantt.locale.labels.column_duration = "<?php echo $lang->programplan->duration;?>";
@@ -488,7 +568,7 @@ $(function()
{
if(module == 'review' && method == 'assess')
{
gantt.config.layout = layout;
gantt.config.layout = layout;
gantt.init('ganttView');
}
gantt.expand();
@@ -552,16 +632,45 @@ $(function()
gantt.attachEvent('onTaskClick', function(id, e)
{
if($(e.srcElement).hasClass('gantt_close') || $(e.srcElement).hasClass('gantt_open')) return false;
/* The id of task item is like executionID-taskID. e.g. 1507-37829, 37829 is task id. */
var position = id.indexOf('-');
if(position < 0) return;
var taskID = parseInt(id.substring(position + 1));
if(ganttType == 'assignedTo')
{
taskID = id;
}
else
{
/* The id of task item is like executionID-taskID. e.g. 1507-37829, 37829 is task id. */
var position = id.indexOf('-');
if(position < 0) return;
var taskID = parseInt(id.substring(position + 1));
}
if(!isNaN(taskID) && taskID > 0) taskModalTrigger.show({url: createLink('task', 'view', 'taskID=' + taskID, 'html', true)});
});
gantt.attachEvent("onBeforeRowDragEnd", function(id, parent, tindex)
{
var task = gantt.getTask(id);
var link = createLink('programplan', 'ajaxSaveGanttMove');
//prevent moving to another position.
if(task.parent != parent || id.indexOf('-') == -1)
{
return false;
}
else
{
$.ajax({
url: link,
dataType: "json",
data: {id: id, type: task.type, index: tindex},
type: "post",
success: function(result){}
});
}
return true;
});
// Make folder can open or close by click
$('#ganttView').on('click', '.gantt_close,.gantt_open', function()
{
@@ -596,5 +705,11 @@ $(function()
{
setTimeout(function(){$('.gantt_tooltip').remove()}, 100);
});
/* Link attachEvent onAfterTaskDrag */
gantt.attachEvent("onBeforeTaskChanged", function(id, mode, task)
{
return validateResources(id);
});
});
</script>
+1
View File
@@ -1,3 +1,4 @@
.future {display: inline-block;}
.c-number {overflow: hidden; text-align: right !important; text-overflow: ellipsis; white-space: nowrap;}
.text-remind {color: #ffa34d;}
td.delayed {color: #fff; background: #e84e0f !important;}
+2 -2
View File
@@ -192,7 +192,7 @@ class projectModel extends model
$project = $this->dao->select('*')->from(TABLE_PROJECT)
->where('id')->eq($projectID)
->beginIF($this->config->system == 'new')->andWhere('`type`')->in($type)->fi()
->beginIF($this->config->systemMode == 'new')->andWhere('`type`')->in($type)->fi()
->fetch();
if(!$project) return false;
@@ -437,7 +437,7 @@ class projectModel extends model
$progressList[$projectID] = $progress;
}
return is_numeric($projectIDList) ? $progressList[$projectIDList] : $progressList;
return is_numeric($projectIDList) ? (empty($progressList) ? 0 : $progressList[$projectIDList]) : $progressList;
}
/**
+10 -8
View File
@@ -169,14 +169,16 @@ class releaseModel extends model
else
{
$build = new stdclass();
$build->project = $projectID;
$build->product = (int)$productID;
$build->branch = (int)$branch;
$build->name = $release->name;
$build->date = $release->date;
$build->builder = $this->app->user->account;
$build->desc = $release->desc;
$build->execution = 0;
$build->project = $projectID;
$build->product = (int)$productID;
$build->branch = (int)$branch;
$build->name = $release->name;
$build->date = $release->date;
$build->builder = $this->app->user->account;
$build->desc = $release->desc;
$build->execution = 0;
$build->createdBy = $this->app->user->account;
$build->createdDate = helper::now();
$build = $this->loadModel('file')->processImgURL($build, $this->config->release->editor->create['id']);
$this->app->loadLang('build');
+2
View File
@@ -4,3 +4,5 @@
.main-actions .btn-toolbar .btn {padding-right: 6px; padding-left: 6px;}
.btn-edit-comment {z-index: 100;}
#legendRelated .table-data tbody>tr>th {width: 90px;}
#legendStories .list-unstyled li a {padding: 6px;}
[lang^='zh'] #legendStories .list-unstyled li a {padding: 6px 12px;}
+1 -1
View File
@@ -794,7 +794,7 @@ class storyModel extends model
->cleanFloat('estimate')
->setDefault('assignedDate', $oldStory->assignedDate)
->setDefault('lastEditedBy', $this->app->user->account)
->setDefault('reviewedBy', '')
->setDefault('reviewedBy', $oldStory->reviewedBy)
->setDefault('mailto', '')
->add('id', $storyID)
->add('lastEditedDate', $now)
+1 -1
View File
@@ -66,7 +66,7 @@
</td>
<?php endif;?>
<?php if(count($track) != 0):?>
<?php $i = 1;?>
<?php $i = 0;?>
<?php foreach($track as $storyID => $story):?>
<?php if($i != 1) echo '<tr>';?>
<td>
+1 -1
View File
@@ -19,4 +19,4 @@
.c-leftAB {width: 60px;}
.c-actions {width: 175px;}
#mainContent .main-actions .btn-toolbar .btn {padding-left: 7px; padding-right: 6px;}
[lang^='de'] #mainContent .main-actions .btn-toolbar .btn {padding-left: 3px; padding-right: 3px;}
+3
View File
@@ -349,6 +349,8 @@ function toggleSelectTestStory()
$('#testStoryBox').removeClass('hidden');
$('#copyButton').addClass('hidden');
$('.colorpicker').css('right', '0');
$('#dataform .table-form>tbody>tr>th').css('width', '130px');
$('[lang^="zh-"] #dataform .table-form>tbody>tr>th').css('width', '120px');
}
else
{
@@ -358,6 +360,7 @@ function toggleSelectTestStory()
$('#estStarted').closest('tr').removeClass('hidden');
$('#estimate').closest('.table-col').removeClass('hidden');
$('#testStoryBox').addClass('hidden');
$('#dataform .table-form>tbody>tr>th').css('width', '100px');
}
}
+2
View File
@@ -352,3 +352,5 @@ $lang->task->report->finishedTasksPerDay->graph->xAxisName = 'Datum';
$lang->taskestimate = new stdclass();
$lang->taskestimate->consumed = 'Schätzung';
$lang->task->overTime = 'The %s scheduled time has been exceeded, please modify the %s time first';
+2
View File
@@ -352,3 +352,5 @@ $lang->task->report->finishedTasksPerDay->graph->xAxisName = 'Date';
$lang->taskestimate = new stdclass();
$lang->taskestimate->consumed = 'Estimates';
$lang->task->overTime = 'The %s scheduled time has been exceeded, please modify the %s time first';
+2
View File
@@ -352,3 +352,5 @@ $lang->task->report->finishedTasksPerDay->graph->xAxisName = 'Date';
$lang->taskestimate = new stdclass();
$lang->taskestimate->consumed = 'Estimés';
$lang->task->overTime = 'The %s scheduled time has been exceeded, please modify the %s time first';
+2
View File
@@ -352,3 +352,5 @@ $lang->task->report->finishedTasksPerDay->graph->xAxisName = '日期';
$lang->taskestimate = new stdclass();
$lang->taskestimate->consumed = '工时';
$lang->task->overTime = '已超出%s计划时间,请先修改%s时间';
+177 -2
View File
@@ -3782,6 +3782,9 @@ class taskModel extends model
*/
public function buildNestedList($execution, $task, $isChild = false, $showmore = false, $users = array())
{
$this->app->loadLang('execution');
$today = helper::today();
$showmore = $showmore ? 'showmore' : '';
$trAttrs = "data-id='t$task->id'";
if(!$isChild)
@@ -3806,8 +3809,22 @@ class taskModel extends model
$list .= '<td>' . zget($users, $task->assignedTo, '') . '</td>';
$list .= "<td class='status-{$task->status}'>" . $this->processStatus('task', $task) . '</td>';
$list .= '<td></td>';
$list .= '<td>' . $task->estStarted . '</td>';
$list .= '<td>' . $task->deadline . '</td>';
$list .= helper::isZeroDate($task->estStarted) ? '<td></td>' : '<td>' . $task->estStarted . '</td>';
if(!helper::isZeroDate($task->deadline))
{
if($task->status != 'done')
{
$list .= strtotime($today) > strtotime($task->deadline) ? '<td class="delayed" ' . 'title="' . $this->lang->execution->delayed . '">' . $task->deadline . '</td>' : '<td>' . $task->deadline . '</td>';
}
else
{
$list .= '<td>' . $task->deadline . '</td>';
}
}
else
{
$list .= '<td></td>';
}
$list .= '<td>' . $task->estimate . $this->lang->execution->workHourUnit . '</td>';
$list .= '<td>' . $task->consumed . $this->lang->execution->workHourUnit . '</td>';
$list .= '<td>' . $task->left . $this->lang->execution->workHourUnit . '</td>';
@@ -3912,4 +3929,162 @@ class taskModel extends model
return $menu;
}
/**
* Save Task Drag.
*
* @param int $objectID
* @param string $objectType
* @access public
* @return bool
*/
public function saveTaskDrag($objectID, $objectType)
{
$post = fixer::input('post')->get();
$post->end_date = date('Y-m-d', strtotime('-1 day', strtotime($post->end_date)));
if($objectType == 'task')
{
$objectData = $this->dao->select('*')->from(TABLE_TASK)->where('id')->eq($objectID)->fetch();
$parent = $objectData->parent;
$project = $objectData->project;
$execution = $objectData->execution;
$stage = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($execution)->andWhere('project')->eq($project)->fetch();
if($parent <= 0)
{
$parentData = $stage;
$start = $parentData->begin;
$end = $parentData->end;
}
else
{
$parentData = $this->dao->select('*')->from(TABLE_TASK)->where('id')->eq($parent)->fetch();
$start = helper::isZeroDate($parentData->estStarted) ? '' : $parentData->estStarted;
$end = helper::isZeroDate($parentData->deadline) ? '' : $parentData->deadline;
}
if(helper::diffDate($start, $post->start_date) > 0)
{
$arg = !empty($parent) ? $this->lang->task->parent : $this->lang->project->stage;
return dao::$errors = sprintf($this->lang->task->overTime, $arg, $arg);
}
$this->dao->update(TABLE_TASK)
->set('estStarted')->eq($post->start_date)
->set('deadline')->eq($post->end_date)
->set('lastEditedBy')->eq($this->app->user->account)
->where('id')->eq($objectID)
->exec();
}
elseif($objectType == 'plan')
{
$objectData = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($objectID)->fetch();
$parent = $objectData->parent;
$project = $objectData->project;
if(empty($parent))
{
$parentData = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($project)->fetch();
}
else
{
$parentData = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($parent)->fetch();
}
$start = helper::isZeroDate($parentData->begin) ? '' : $parentData->begin;
$end = helper::isZeroDate($parentData->end) ? '' : $parentData->end;
if(helper::diffDate($start, $post->start_date) > 0)
{
$arg = !empty($parent) ? $this->lang->programplan->parent : $this->lang->project->common;
return dao::$errors = sprintf($this->lang->task->overTime, $arg, $arg);
}
$this->dao->update(TABLE_PROJECT)
->set('begin')->eq($post->start_date)
->set('end')->eq($post->end_date)
->set('lastEditedBy')->eq($this->app->user->account)
->where('id')->eq($objectID)
->exec();
}
else
{
return false;
}
return true;
}
/**
* Save task order.
*
* @param int $productID
* @access public
* @return void
*/
public function saveTaskMove($productID = 0)
{
$data = fixer::input('post')->get();
$IdList = explode('-', $data->id);
$executionID = $IdList[0];
$taskID = $IdList[1];
$oldTask = $this->loadModel('task')->getByID($taskID);
$index = (int)$data->index;
$hasZeroOrder = $this->dao->select('id')->from(TABLE_TASK)
->where('deleted')->eq(0)
->andWhere('execution')->eq($executionID)
->andWhere('`order`')->eq(0)
->beginIF($oldTask->parent <= 0)->andWhere('parent')->le(0)->fi()
->beginIF($oldTask->parent > 0)->andWhere('parent')->eq($oldTask->parent)->fi()
->limit(1)
->fetch('id');
if($hasZeroOrder)
{
$tasks = $this->dao->select('id')->from(TABLE_TASK)
->where('execution')->eq($executionID)
->andWhere('deleted')->eq(0)
->beginIF($oldTask->parent <= 0)->andWhere('parent')->le(0)->fi()
->beginIF($oldTask->parent > 0)->andWhere('parent')->eq($oldTask->parent)->fi()
->orderBy('order_asc, id_desc')
->fetchPairs('id');
$order = 1;
foreach($tasks as $task)
{
$this->dao->update(TABLE_TASK)->set('`order`')->eq($order)->where('id')->eq($task)->exec();
$order ++;
}
$oldTask = $this->loadModel('task')->getByID($taskID);
}
$order = ++ $index;
$oldOrder = (int)$oldTask->order;
if($order > $oldOrder)
{
$this->dao->update(TABLE_TASK)->set('`order`=`order`-1')
->where('execution')->eq($executionID)
->andWhere('`order`')->le($order)
->andWhere('`order`')->gt($oldOrder)
->beginIF($oldTask->parent <= 0)->andWhere('parent')->le(0)->fi()
->beginIF($oldTask->parent > 0)->andWhere('parent')->eq($oldTask->parent)->fi()
->exec();
}
else if($order < $oldOrder)
{
$this->dao->update(TABLE_TASK)->set('`order`=`order`+1')
->where('execution')->eq($executionID)
->andWhere('`order`')->lt($oldOrder)
->andWhere('`order`')->ge($order)
->beginIF($oldTask->parent <= 0)->andWhere('parent')->le(0)->fi()
->beginIF($oldTask->parent > 0)->andWhere('parent')->eq($oldTask->parent)->fi()
->exec();
}
$this->dao->update(TABLE_TASK)->set('`order`')->eq($order)->where('id')->eq($taskID)->exec();
}
}
+1
View File
@@ -1377,6 +1377,7 @@ class testtask extends control
$this->view->title = $this->lang->testtask->batchRun;
$this->view->position[] = $this->lang->testtask->common;
$this->view->position[] = $this->lang->testtask->batchRun;
$this->view->from = $from;
$this->display();
}
+1 -1
View File
@@ -1,5 +1,5 @@
#mailtoGroup .chosen-container-single a {border-left-width: 0px;}
#ownerAndPriBox .picker .picker-selections .picker-selection {width: 158px;}
.table tbody>tr>td {width: 400px;}
[lang^='en'] .table tbody>tr>td, [lang^='de'].table tbody>tr>td {width: 460px;}
[lang^='en'] .table tbody>tr>td, [lang^='de'] .table tbody>tr>td {width: 460px;}
[lang^='fr'] .table tbody>tr>td {width: 480px;}
+1 -1
View File
@@ -1,5 +1,5 @@
#mailtoGroup .chosen-container-single a {border-left-width: 0px;}
#ownerAndPriBox .picker .picker-selections .picker-selection {width: 158px;}
.table tbody>tr>td {width: 400px;}
[lang^='en'] .table tbody>tr>td, [lang^='de'].table tbody>tr>td {width: 460px;}
[lang^='en'] .table tbody>tr>td, [lang^='de'] .table tbody>tr>td {width: 460px;}
[lang^='fr'] .table tbody>tr>td {width: 480px;}
+9
View File
@@ -1,3 +1,12 @@
$(function()
{
if(from == 'testcase')
{
$("#navbar li[data-id='testtask']").toggleClass('active');
$("#navbar li[data-id='testcase']").toggleClass('active');
}
});
$(document).on('keyup', 'form input:text', function()
{
var preSelect = $(this).parent().prev().find('select');
+2 -1
View File
@@ -11,10 +11,11 @@
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php js::set('from', $from);?>
<?php $this->app->loadLang('testcase'); unset($this->lang->testcase->resultList['n/a']); ?>
<div id='mainContent' class='main-content'>
<div class='main-header'>
<h2><?php echo $lang->testtask->common . $lang->colon . $lang->testtask->batchRun;?></h2>
<h2><?php echo ($from == 'testtask' ? ($lang->testtask->common . $lang->colon) : ''). $lang->testtask->batchRun;?></h2>
</div>
<form class='main-form' method='post' target='hiddenwin'>
<table class='table table-fixed table-form table-bordered'>
+3 -3
View File
@@ -534,8 +534,8 @@ class upgradeModel extends model
case '17_4':
$this->changeTableEngine();
$this->processCreatedInfo();
$this->updateApproval();
$this->processCreatedBy();
$this->updateApproval();
break;
}
@@ -6777,8 +6777,8 @@ class upgradeModel extends model
*/
public function processCreatedInfo()
{
$objectTypes = array('productplan', 'release', 'testtask');
$tables = array('productplan' => TABLE_PRODUCTPLAN, 'release' => TABLE_RELEASE, 'testtask' => TABLE_TESTTASK);
$objectTypes = array('productplan', 'release', 'testtask', 'build');
$tables = array('productplan' => TABLE_PRODUCTPLAN, 'release' => TABLE_RELEASE, 'testtask' => TABLE_TESTTASK, 'build' => TABLE_BUILD);
$actions = $this->dao->select('objectType, objectID, actor, date')->from(TABLE_ACTION)->where('objectType')->in($objectTypes)->andWhere('action')->eq('opened')->fetchGroup('objectType');
foreach($actions as $objectType => $objectActions)
+88
View File
@@ -0,0 +1,88 @@
<?php
class gitlabTest
{
public $tester;
public function __construct()
{
global $tester;
$this->tester = $tester;
$this->gitlab = $this->tester->loadModel('gitlab');
}
/**
* Get by id.
*
* @param int $id
* @access public
* @return object
*/
public function getByID($id)
{
$gitlab = $this->gitlab->getByID($id);
if(empty($gitlab)) return 0;
return $gitlab;
}
/**
* Get gitlab list.
*
* @param string $orderBy
* @access public
* @return object
*/
public function getList($orderBy = 'id_desc')
{
$gitlab = $this->gitlab->getList($orderBy);
if(empty($gitlab)) return 0;
return array_shift($gitlab);
}
/**
* Get gitlab pairs
*
* @return string
*/
public function getPairs()
{
$pairs = $this->gitlab->getPairs();
return key($pairs);
}
/**
* Create a gitlab.
*
* @access public
* @return object|string
*/
public function create()
{
$gitlabID = $this->gitlab->create();
if(dao::isError())
{
$errors = dao::getError();
return key($errors);
}
return $this->gitlab->getById($gitlabID);
}
/**
* Update a gitlab.
*
* @param int $id
* @access public
* @return object|string
*/
public function update($id)
{
$this->gitlab->update($id);
if(dao::isError())
{
$errors = dao::getError();
return key($errors);
}
return $this->gitlab->getById($id);
}
}
+1 -1
View File
@@ -4,7 +4,7 @@ version: "1.0"
fields:
- field: id
range: 1
- field: gitlabID
- field: hostID
range: 1
- field: sourceProject
range: 42
+4
View File
@@ -14,6 +14,10 @@ fields:
range: Gitlab
- field: client
range: 1
- field: serviceHost
range: 1
- field: serviceProject
range: 42
- field: extra
range: 42
- field: preMerge
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/gitlab.class.php';
su('admin');
/**
title=测试gitlabModel->create();
cid=1
pid=1
GitLab名称为空 >> name
服务器地址为空 >> url
正确GitLab数据 >> GitLab,http://10.0.1.161:58080,1196c85ba525a268570df9da627e3a7b2d
*/
$gitlab = new gitlabTest();
$_POST = array();
$_POST['name'] = '';
$_POST['url'] = 'http://10.0.1.161:51080';
$_POST['token'] = 'y2UBqwPPzaLxsniy8R6A';
$_POST['password'] = '';
r($gitlab->create()) && p() && e('name'); // GitLab名称为空
$_POST['name'] = 'GitLab';
$_POST['url'] = '';
r($gitlab->create()) && p() && e('url'); // 服务器地址为空
$_POST['url'] = 'http://10.0.1.161:51080';
r($gitlab->create()) && p('name,url,token') && e('GitLab,http://10.0.1.161:51080,y2UBqwPPzaLxsniy8R6A'); // 正确GitLab数据
system("./ztest init");
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/gitlab.class.php';
su('admin');
/**
title=测试gitlabModel->gitById();
cid=1
pid=1
使用存在的ID >> 3
使用空的ID >> 0
使用不存在的ID >> 0
*/
$gitlab = new gitlabTest();
$gitlabID = 1;
r($gitlab->getById($gitlabID)) && p('id') && e('1'); // 使用存在的ID
$gitlabID = 0;
r($gitlab->getById($gitlabID)) && p() && e(0); // 使用空的ID
$gitlabID = 111;
r($gitlab->getById($gitlabID)) && p() && e(0); // 使用不存在的ID
system("./ztest init");
+22
View File
@@ -0,0 +1,22 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/gitlab.class.php';
su('admin');
/**
title=测试gitlabModel->gitList();
cid=1
pid=1
获取GiLlab列表 >> 1
*/
$gitlab = new gitlabTest();
$orderBy = 'id_desc';
r($gitlab->getList($orderBy)) && p('id') && e('1'); // 获取GitLab列表
system("./ztest init");
+21
View File
@@ -0,0 +1,21 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/gitlab.class.php';
su('admin');
/**
title=测试gitlabModel->gitPairs();
cid=1
pid=1
获取GitLab >> 1
*/
$gitlab = new gitlabTest();
r($gitlab->getPairs()) && p() && e('1'); // 获取GitLab
system("./ztest init");
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/gitlab.class.php';
su('admin');
/**
title=测试gitlabModel->update();
cid=1
pid=1
GitLab名称为空 >> name
服务器地址为空 >> url
正确GitLab数据 >> Changed GitLab
*/
$gitlab = new gitlabTest();
$gitlabID = 3;
$_POST = array();
$_POST['name'] = '';
$_POST['url'] = 'http://10.0.1.161:51080';
$_POST['account'] = 'admin';
$_POST['token'] = 'y2UBqwPPzaLxsniy8R6A';
$_POST['password'] = '';
r($gitlab->update($gitlabID)) && p() && e('name'); // GitLab名称为空
$_POST['name'] = 'Changed GitLab';
$_POST['url'] = '';
r($gitlab->update($gitlabID)) && p() && e('url'); // 服务器地址为空
$_POST['url'] = 'http://10.0.1.161:51080';
r($gitlab->update($gitlabID)) && p('name') && e('Changed GitLab'); // 正确GitLab数据
system("./ztest init");
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,12 +0,0 @@
/*
@license
dhtmlxGantt v.6.2.4 Professional
This software is covered by DHTMLX Commercial License. Usage without proper license is prohibited.
(c) XB Software Ltd.
*/
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var n=t();for(var o in n)("object"==typeof exports?exports:e)[o]=n[o]}}(window,function(){return function(e){var t={};function n(o){if(t[o])return t[o].exports;var l=t[o]={i:o,l:!1,exports:{}};return e[o].call(l.exports,l,l.exports,n),l.l=!0,l.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var l in e)n.d(o,l,function(t){return e[t]}.bind(null,l));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/codebase/",n(n.s=245)}({245:function(e,t){!function(){var e=gantt.getState;function t(){var e=document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement||document.msFullscreenElement;return e&&e===document.body}gantt.getState=function(){var n=e.apply(this,arguments);return n.fullscreen=t(),n};var n=!1,o={width:null,height:null,top:null,position:null,modified:!1};function l(e){e?(!function(){var e=gantt.$root;o.width=e.style.width,o.height=e.style.height,o.top=e.style.top,o.position=e.style.position,e.style.width="100vw",e.style.height="100vh",e.style.top="0",e.style.position="absolute",o.modified=!0}(),setTimeout(function(){gantt.render()})):(!function(){var e=gantt.$root;o.modified&&(e.style.width=o.width,e.style.height=o.height,e.style.top=o.top,e.style.position=o.position,o.modified=!1)}(),gantt.render())}function u(){if(gantt.$container){var e=t();l(e),e?(n=!0,setTimeout(function(){gantt.callEvent("onExpand")})):n&&(n=!1,setTimeout(function(){gantt.callEvent("onCollapse")}))}}function r(){return!gantt.$container||!(document.fullscreenEnabled||document.webkitFullscreenEnabled||document.mozFullScreenEnabled||document.msFullscreenEnabled)&&((console.warning||console.log)("The `fullscreen` feature not being allowed, or full-screen mode not being supported"),!0)}gantt.attachEvent("onGanttReady",function(){gantt.event(document,"webkitfullscreenchange",u),gantt.event(document,"mozfullscreenchange",u),gantt.event(document,"MSFullscreenChange",u),gantt.event(document,"fullscreenChange",u),gantt.event(document,"fullscreenchange",u)}),gantt.expand=function(){if(!r()&&gantt.callEvent("onBeforeExpand",[])){var e=document.body;e.requestFullscreen?e.requestFullscreen():e.msRequestFullscreen?e.msRequestFullscreen():e.mozRequestFullScreen?e.mozRequestFullScreen():e.webkitRequestFullscreen&&e.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT)}},gantt.collapse=function(){r()||t()&&gantt.callEvent("onBeforeCollapse",[])&&(document.exitFullscreen?document.exitFullscreen():document.msExitFullscreen?document.msExitFullscreen():document.mozCancelFullScreen?document.mozCancelFullScreen():document.webkitExitFullscreen&&document.webkitExitFullscreen())}}()}})});
//# sourceMappingURL=dhtmlxgantt_fullscreen.js.map
@@ -1,11 +0,0 @@
/*
@license
dhtmlxGantt v.6.1.1 Professional
This software is covered by DHTMLX Commercial License. Usage without proper license is prohibited.
(c) Dinamenta, UAB.
*/
!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var r=e();for(var a in r)("object"==typeof exports?exports:t)[a]=r[a]}}(window,function(){return function(t){var e={};function r(a){if(e[a])return e[a].exports;var n=e[a]={i:a,l:!1,exports:{}};return t[a].call(n.exports,n,n.exports,r),n.l=!0,n.exports}return r.m=t,r.c=e,r.d=function(t,e,a){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:a})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var a=Object.create(null);if(r.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)r.d(a,n,function(e){return t[e]}.bind(null,n));return a},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="/codebase/",r(r.s=216)}({216:function(t,e){!function(){function t(t){if(!gantt.config.show_markers)return!1;if(!t.start_date)return!1;var e=gantt.getState();if(!(+t.start_date>+e.max_date||+t.end_date&&+t.end_date<+e.min_date||+t.start_date<+e.min_date)){var r=document.createElement("div");r.setAttribute("data-marker-id",t.id);var a="gantt_marker";gantt.templates.marker_class&&(a+=" "+gantt.templates.marker_class(t)),t.css&&(a+=" "+t.css),t.title&&(r.title=t.title),r.className=a;var n=gantt.posFromDate(t.start_date);if(r.style.left=n+"px",r.style.height=Math.max(gantt.getRowTop(gantt.getVisibleTaskCount()),0)+"px",t.end_date){var i=gantt.posFromDate(t.end_date);r.style.width=Math.max(i-n,0)+"px"}return t.text&&(r.innerHTML="<div class='gantt_marker_content' >"+t.text+"</div>"),r}}function e(){if(gantt.$task_data){var t=document.createElement("div");t.className="gantt_marker_area",gantt.$task_data.appendChild(t),gantt.$marker_area=t}}gantt._markers||(gantt._markers=gantt.createDatastore({name:"marker",initItem:function(t){return t.id=t.id||gantt.uid(),t}})),gantt.config.show_markers=!0,gantt.attachEvent("onBeforeGanttRender",function(){gantt.$marker_area||e()}),gantt.attachEvent("onGanttReady",function(){e(),gantt.$services.getService("layers").createDataRender({name:"marker",defaultContainer:function(){return gantt.$marker_area}}).addLayer(t)}),gantt.getMarker=function(t){return this._markers?this._markers.getItem(t):null},gantt.addMarker=function(t){return this._markers.addItem(t)},gantt.deleteMarker=function(t){return!!this._markers.exists(t)&&(this._markers.removeItem(t),!0)},gantt.updateMarker=function(t){this._markers.refresh(t)},gantt._getMarkers=function(){return this._markers.getItems()},gantt.renderMarkers=function(){this._markers.refresh()}}()}})});
//# sourceMappingURL=dhtmlxgantt_marker.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -82,13 +82,14 @@ a.showMoreImage:hover {opacity: 1;}
.fixed-head-table{z-index:1000;}
#headerActions {position: absolute; top: 9px; right: 230px; border-right: 2px solid rgba(255, 255, 255, 0.3);}
#headerActions {position: absolute; top: 9px; right: 175px; border-right: 2px solid rgba(255, 255, 255, 0.3);}
#headerActions .btn-group > .btn{ color: #fff; margin-right: 8px; border-radius: 4px !important;}
#headerActions .btn-group > .btn.active, #headerActions .btn:active, #headerActions .open .dropdown-toggle.btn {background: rgba(0,0,0,0.15) !important;}
#headerActions #kanbanActionMenu {left: 55px}
#headerActions .setting {border-color: transparent;}
#headerActions .dropdown-menu {top: 35px; z-index: 2000;}
#headerActions .dropdown-menu:before, #headerActions .dropdown-menu:hover:before {position: absolute; top: -9px; right: 50%; width: 0; height: 0; content: ' '; border-color: transparent transparent #fff transparent; border-style: solid; border-width: 0 10px 10px 10px;}
[lang^='zh'] #headerActions {width: 230px;}
.icon-size-width:before {content: "\e9c5"; transform: rotate(90deg); -ms-transform: rotate(90deg); -moz-transform: rotate(90deg); -webkit-transform: rotate(90deg); -o-transform: rotate(90deg);}
.checkbox-primary > label{overflow: hidden;}