* Task#3576
This commit is contained in:
@@ -3,3 +3,5 @@ ALTER TABLE `zt_todo` ADD `config` varchar(255) NOT NULL;
|
||||
ALTER TABLE `zt_todo` ADD `cycle` tinyint unsigned NOT NULL DEFAULT '0' AFTER `type`;
|
||||
INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type`, `buildin`, `status`, `lastTime`) VALUES
|
||||
('1', '1', '*', '*', '*', 'moduleName=todo&methodName=createCycle', '生成周期性待办', 'zentao', 1, 'normal', '0000-00-00 00:00:00');
|
||||
|
||||
ALTER TABLE `zt_projectproduct` ADD `plan` MEDIUMINT(8) UNSIGNED NOT NULL AFTER `branch`;
|
||||
|
||||
+31
-10
@@ -5,7 +5,7 @@
|
||||
*
|
||||
* The author disclaims copyright to this source code. In place of
|
||||
* a legal notice, here is a blessing:
|
||||
*
|
||||
*
|
||||
* May you do good and not evil.
|
||||
* May you find forgiveness for yourself and forgive others.
|
||||
* May you share freely, never taking more than you give.
|
||||
@@ -43,7 +43,7 @@ class helper extends baseHelper
|
||||
{
|
||||
if(isset($_GET[$config->viewVar]))
|
||||
{
|
||||
$viewType = $_GET[$config->viewVar];
|
||||
$viewType = $_GET[$config->viewVar];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -59,9 +59,9 @@ class helper extends baseHelper
|
||||
|
||||
/**
|
||||
* Encode json for $.parseJSON
|
||||
*
|
||||
* @param array $data
|
||||
* @param int $options
|
||||
*
|
||||
* @param array $data
|
||||
* @param int $options
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
@@ -78,10 +78,10 @@ class helper extends baseHelper
|
||||
|
||||
/**
|
||||
* Convert encoding.
|
||||
*
|
||||
* @param string $string
|
||||
* @param string $fromEncoding
|
||||
* @param string $toEncoding
|
||||
*
|
||||
* @param string $string
|
||||
* @param string $fromEncoding
|
||||
* @param string $toEncoding
|
||||
* @static
|
||||
* @access public
|
||||
* @return string
|
||||
@@ -111,12 +111,33 @@ class helper extends baseHelper
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate two working days.
|
||||
*
|
||||
* @param string $begin
|
||||
* @param string $end
|
||||
*
|
||||
* @return bool|float
|
||||
*/
|
||||
static public function workDays($begin, $end)
|
||||
{
|
||||
$begin = strtotime($begin);
|
||||
$end = strtotime($end);
|
||||
if($end < $begin) return false;
|
||||
|
||||
$double = floor(($end - $begin) / (7 * 24 * 3600));
|
||||
$begin = date('w', $begin);
|
||||
$end = date('w', $end);
|
||||
$end = $begin > $end ? $end + 5 : $end;
|
||||
return $double * 5 + $end - $begin;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否是onlybody模式。
|
||||
* Check exist onlybody param.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
|
||||
@@ -191,6 +191,7 @@ class productplan extends control
|
||||
*/
|
||||
public function browse($productID = 0, $branch = 0, $browseType = 'all', $orderBy = 'begin_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1 )
|
||||
{
|
||||
$this->app->loadLang('project');
|
||||
/* Load pager. */
|
||||
$this->app->loadClass('pager', $static = true);
|
||||
$pager = new pager($recTotal, $recPerPage, $pageID);
|
||||
|
||||
@@ -185,9 +185,10 @@ class productplanModel extends model
|
||||
{
|
||||
$oldPlan = $this->dao->findByID((int)$planID)->from(TABLE_PRODUCTPLAN)->fetch();
|
||||
$plan = fixer::input('post')->stripTags($this->config->productplan->editor->edit['id'], $this->config->allowedTags)
|
||||
->setIF($this->post->delta == 9999 || empty($this->post->end), 'end', '2030-01-01')
|
||||
->setIF($this->post->delta == 9999 || $this->post->end == '', 'end', '2030-01-01')
|
||||
->remove('delta,uid')
|
||||
->get();
|
||||
|
||||
$plan = $this->loadModel('file')->processImgURL($plan, $this->config->productplan->editor->edit['id'], $this->post->uid);
|
||||
$this->dao->update(TABLE_PRODUCTPLAN)
|
||||
->data($plan)
|
||||
|
||||
@@ -43,18 +43,18 @@
|
||||
<thead>
|
||||
<?php $vars = "productID=$productID&branch=$branch&browseType=$browseType&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}"; ?>
|
||||
<tr class='colhead'>
|
||||
<th class='w-id'> <?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?></th>
|
||||
<th> <?php common::printOrderLink('title', $orderBy, $vars, $lang->productplan->title);?></th>
|
||||
<th class='w-id'> <?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?></th>
|
||||
<th> <?php common::printOrderLink('title', $orderBy, $vars, $lang->productplan->title);?></th>
|
||||
<?php if($this->session->currentProductType != 'normal'):?>
|
||||
<th class='w-100px'> <?php common::printOrderLink('branch',$orderBy, $vars, $lang->product->branch);?></th>
|
||||
<th class='w-100px'><?php common::printOrderLink('branch',$orderBy, $vars, $lang->product->branch);?></th>
|
||||
<?php endif;?>
|
||||
<th class='w-60px'> <?php echo $lang->productplan->stories;?></th>
|
||||
<th class='w-60px'> <?php echo $lang->productplan->bugs;?></th>
|
||||
<th class='w-60px'> <?php echo $lang->productplan->hour;?></th>
|
||||
<th class='w-p50'> <?php echo $lang->productplan->desc;?></th>
|
||||
<th class='w-100px'> <?php common::printOrderLink('begin', $orderBy, $vars, $lang->productplan->begin);?></th>
|
||||
<th class='w-100px'> <?php common::printOrderLink('end', $orderBy, $vars, $lang->productplan->end);?></th>
|
||||
<th class="w-110px {sorter: false}"><?php echo $lang->actions;?></th>
|
||||
<th class='w-p40'> <?php echo $lang->productplan->desc;?></th>
|
||||
<th class='w-100px'><?php common::printOrderLink('begin', $orderBy, $vars, $lang->productplan->begin);?></th>
|
||||
<th class='w-100px'><?php common::printOrderLink('end', $orderBy, $vars, $lang->productplan->end);?></th>
|
||||
<th class="w-130px {sorter: false}"><?php echo $lang->actions;?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@@ -78,6 +78,7 @@
|
||||
<td><?php echo $plan->end == '2030-01-01' ? $lang->productplan->future : $plan->end;?></td>
|
||||
<td class='text-center'>
|
||||
<?php
|
||||
if(common::hasPriv('project', 'create')) echo html::a(helper::createLink('project', 'create', "projectID=©ProjectID=&planID=$plan->id"), '<i class="icon-play"></i>', '', "class='btn-icon' title='{$lang->project->create}'");
|
||||
if(common::hasPriv('productplan', 'linkStory')) echo html::a(inlink('view', "planID=$plan->id&type=story&orderBy=id_desc&link=true"), '<i class="icon-link"></i>', '', "class='btn-icon' title='{$lang->productplan->linkStory}'");
|
||||
if(common::hasPriv('productplan', 'linkBug') and $config->global->flow != 'onlyStory') echo html::a(inlink('view', "planID=$plan->id&type=bug&orderBy=id_desc&link=true"), '<i class="icon-bug"></i>', '', "class='btn-icon' title='{$lang->productplan->linkBug}'");
|
||||
common::printIcon('productplan', 'edit', "planID=$plan->id", $plan, 'list');
|
||||
|
||||
+59
-40
@@ -41,7 +41,7 @@ class project extends control
|
||||
{
|
||||
if($this->app->user->account == 'guest' or commonModel::isTutorialMode()) $this->config->project->homepage = 'index';
|
||||
if(!isset($this->config->project->homepage))
|
||||
{
|
||||
{
|
||||
if($this->projects and $this->app->viewType != 'mhtml') die($this->fetch('custom', 'ajaxSetHomepage', "module=project"));
|
||||
|
||||
$this->config->project->homepage = 'index';
|
||||
@@ -375,7 +375,7 @@ class project extends control
|
||||
$this->view->title = $project->name . $this->lang->colon . $this->lang->project->importTask;
|
||||
$this->view->position[] = html::a(inlink('browse', "projectID=$toProject"), $project->name);
|
||||
$this->view->position[] = $this->lang->project->importTask;
|
||||
$this->view->tasks2Imported = $tasks2Imported;
|
||||
$this->view->tasks2Imported = $tasks2Imported;
|
||||
$this->view->projects = $projects;
|
||||
$this->view->projectID = $project->id;
|
||||
$this->view->fromProject = $fromProject;
|
||||
@@ -826,8 +826,8 @@ class project extends control
|
||||
|
||||
/**
|
||||
* Fix burn for first date.
|
||||
*
|
||||
* @param int $projectID
|
||||
*
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -873,11 +873,12 @@ class project extends control
|
||||
*
|
||||
* @param string $projectID
|
||||
* @param string $copyProjectID
|
||||
* @param int $planID
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function create($projectID = '', $copyProjectID = '')
|
||||
public function create($projectID = '', $copyProjectID = '', $planID = 0)
|
||||
{
|
||||
if($projectID)
|
||||
{
|
||||
@@ -888,12 +889,14 @@ class project extends control
|
||||
exit;
|
||||
}
|
||||
|
||||
$name = '';
|
||||
$code = '';
|
||||
$team = '';
|
||||
$products = array();
|
||||
$whitelist = '';
|
||||
$acl = 'open';
|
||||
$name = '';
|
||||
$code = '';
|
||||
$team = '';
|
||||
$products = array();
|
||||
$whitelist = '';
|
||||
$acl = 'open';
|
||||
$plan = new stdClass();
|
||||
$productPlan = new stdClass();
|
||||
|
||||
if($copyProjectID)
|
||||
{
|
||||
@@ -906,6 +909,16 @@ class project extends control
|
||||
$products = $this->project->getProducts($copyProjectID);
|
||||
}
|
||||
|
||||
if(!empty($planID))
|
||||
{
|
||||
$plan = $this->dao->select('*')->from(TABLE_PRODUCTPLAN)->where('id')->eq($planID)->fetch();
|
||||
$products = $this->dao->select('t1.id, t1.name, t1.type, t2.branch')->from(TABLE_PRODUCT)->alias('t1')
|
||||
->leftJoin(TABLE_PROJECTPRODUCT)->alias('t2')->on('t1.id = t2.product')
|
||||
->where('t1.id')->eq($plan->product)
|
||||
->fetchAll('id');
|
||||
$productPlan = $this->loadModel('productplan')->getPairs($plan->product, 0, 'unexpired');
|
||||
}
|
||||
|
||||
if(!empty($_POST))
|
||||
{
|
||||
$projectID = $copyProjectID == '' ? $this->project->create() : $this->project->create($copyProjectID);
|
||||
@@ -923,12 +936,14 @@ class project extends control
|
||||
$this->view->projects = array('' => '') + $this->projects;
|
||||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||||
$this->view->allProducts = array(0 => '') + $this->loadModel('product')->getPairs('noclosed|nocode');
|
||||
$this->view->acl = $acl;
|
||||
$this->view->plan = $plan;
|
||||
$this->view->name = $name;
|
||||
$this->view->code = $code;
|
||||
$this->view->team = $team;
|
||||
$this->view->products = $products ;
|
||||
$this->view->products = $products;
|
||||
$this->view->productPlan = $productPlan;
|
||||
$this->view->whitelist = $whitelist;
|
||||
$this->view->acl = $acl ;
|
||||
$this->view->copyProjectID = $copyProjectID;
|
||||
$this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products));
|
||||
$this->display();
|
||||
@@ -938,6 +953,9 @@ class project extends control
|
||||
* Edit a project.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $action
|
||||
* @param string $extra
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -994,6 +1012,7 @@ class project extends control
|
||||
$this->view->qdUsers = $this->user->getPairs('noclosed|nodeleted|qdfirst', $project->QD);
|
||||
$this->view->rdUsers = $this->user->getPairs('noclosed|nodeleted|devfirst', $project->RD);
|
||||
$this->view->groups = $this->loadModel('group')->getPairs();
|
||||
$this->view->plans = $this->project->getPlans(array_keys($linkedProducts));
|
||||
$this->view->allProducts = $allProducts;
|
||||
$this->view->linkedProducts = $linkedProducts;
|
||||
$this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($linkedProducts));
|
||||
@@ -1266,10 +1285,10 @@ class project extends control
|
||||
|
||||
/**
|
||||
* Kanban.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $type
|
||||
* @param string $orderBy
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $type
|
||||
* @param string $orderBy
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1313,8 +1332,8 @@ class project extends control
|
||||
/**
|
||||
* Tree view.
|
||||
* Product
|
||||
*
|
||||
* @param int $projectID
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $type
|
||||
* @access public
|
||||
* @return void
|
||||
@@ -1340,14 +1359,14 @@ class project extends control
|
||||
$this->view->projectID = $projectID;
|
||||
$this->view->level = $type;
|
||||
$this->view->tree = $tree;
|
||||
$this->display();
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Print kanban.
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $orderBy
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $orderBy
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1362,7 +1381,7 @@ class project extends control
|
||||
$storySpecs = $this->story->getStorySpecs(array_keys($stories));
|
||||
|
||||
$order = 1;
|
||||
foreach($stories as $story) $story->order = $order++;
|
||||
foreach($stories as $story) $story->order = $order++;
|
||||
|
||||
$kanbanTasks = $this->project->getKanbanTasks($projectID, "id");
|
||||
$kanbanBugs = $this->loadModel('bug')->getProjectBugs($projectID);
|
||||
@@ -1449,13 +1468,13 @@ class project extends control
|
||||
|
||||
$this->view->position[] = html::a($this->createLink('project', 'browse', "projectID=$projectID"), $project->name);
|
||||
$this->view->position[] = $this->lang->project->printKanban;
|
||||
$this->display();
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Story kanban.
|
||||
*
|
||||
* @param int $projectID
|
||||
*
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -1807,7 +1826,7 @@ class project extends control
|
||||
$this->project->unlinkStory($projectID, $storyID);
|
||||
|
||||
/* if kanban then reload and if ajax request then send result. */
|
||||
if(isonlybody())
|
||||
if(isonlybody())
|
||||
{
|
||||
die(js::reload('parent'));
|
||||
}
|
||||
@@ -2019,8 +2038,8 @@ class project extends control
|
||||
|
||||
/**
|
||||
* Story sort.
|
||||
*
|
||||
* @param int $projectID
|
||||
*
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -2079,11 +2098,11 @@ class project extends control
|
||||
}
|
||||
|
||||
/**
|
||||
* Export project.
|
||||
*
|
||||
* @param string $status
|
||||
* @param int $productID
|
||||
* @param string $orderBy
|
||||
* Export project.
|
||||
*
|
||||
* @param string $status
|
||||
* @param int $productID
|
||||
* @param string $orderBy
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -2144,8 +2163,8 @@ class project extends control
|
||||
|
||||
/**
|
||||
* Kanban setting.
|
||||
*
|
||||
* @param int $projectID
|
||||
*
|
||||
* @param int $projectID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -2181,9 +2200,9 @@ class project extends control
|
||||
|
||||
/**
|
||||
* Ajax reset kanban setting
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $confirm
|
||||
*
|
||||
* @param int $projectID
|
||||
* @param string $confirm
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
|
||||
+43
-20
@@ -16,8 +16,8 @@ function switchGroup(projectID, groupBy)
|
||||
|
||||
/**
|
||||
* Convert a date string like 2011-11-11 to date object in js.
|
||||
*
|
||||
* @param string $date
|
||||
*
|
||||
* @param string $date
|
||||
* @access public
|
||||
* @return date
|
||||
*/
|
||||
@@ -29,9 +29,9 @@ function convertStringToDate(dateString)
|
||||
|
||||
/**
|
||||
* Compute delta of two days.
|
||||
*
|
||||
* @param string $date1
|
||||
* @param string $date1
|
||||
*
|
||||
* @param string $date1
|
||||
* @param string $date1
|
||||
* @access public
|
||||
* @return int
|
||||
*/
|
||||
@@ -49,12 +49,12 @@ function computeDaysDelta(date1, date2)
|
||||
date1 += 1000 * 60 * 60 * 24;
|
||||
date1 = new Date(date1);
|
||||
}
|
||||
return delta - weekEnds;
|
||||
return delta - weekEnds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute work days.
|
||||
*
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -80,12 +80,12 @@ function computeWorkDays(currentID)
|
||||
endDate = $('#end').val();
|
||||
}
|
||||
|
||||
if(beginDate && endDate)
|
||||
if(beginDate && endDate)
|
||||
{
|
||||
if(isBactchEdit) $('#dayses\\[' + index + '\\]').val(computeDaysDelta(beginDate, endDate));
|
||||
if(!isBactchEdit) $('#days').val(computeDaysDelta(beginDate, endDate));
|
||||
}
|
||||
else if($('input[checked="true"]').val())
|
||||
else if($('input[checked="true"]').val())
|
||||
{
|
||||
computeEndDate();
|
||||
}
|
||||
@@ -93,8 +93,8 @@ function computeWorkDays(currentID)
|
||||
|
||||
/**
|
||||
* Compute the end date for project.
|
||||
*
|
||||
* @param int $delta
|
||||
*
|
||||
* @param int $delta
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -117,8 +117,8 @@ function computeEndDate(delta)
|
||||
|
||||
/**
|
||||
* Load branches.
|
||||
*
|
||||
* @param int $product
|
||||
*
|
||||
* @param int $product
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -134,20 +134,20 @@ function loadBranches(product)
|
||||
$product.trigger("chosen:updated");
|
||||
return false;
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
if($('#productsBox .input-group:last select:first').val() != 0)
|
||||
{
|
||||
var length = $('#productsBox .input-group').size();
|
||||
$('#productsBox .row').append('<div class="col-sm-3">' + $('#productsBox .col-sm-3:last').html() + '</div>');
|
||||
if($('#productsBox .input-group:last select').size() >= 2)$('#productsBox .input-group:last select:last').remove();
|
||||
if($('#productsBox .input-group:last select').size() >= 2) $('#productsBox .input-group:last select:last').remove();
|
||||
$('#productsBox .input-group:last .chosen-container').remove();
|
||||
$('#productsBox .input-group:last select:first').attr('name', 'products[' + length + ']').attr('id', 'products' + length);
|
||||
$('#productsBox .input-group:last .chosen').chosen(defaultChosenOptions);
|
||||
}
|
||||
|
||||
var $inputgroup = $(product).closest('.input-group');
|
||||
if($inputgroup.find('select').size() >= 2)$inputgroup.find('select:last').remove();
|
||||
if($inputgroup.find('select').size() >= 2) $inputgroup.find('select:last').remove();
|
||||
var index = $inputgroup.find('select:first').attr('id').replace('products' , '');
|
||||
$.get(createLink('branch', 'ajaxGetBranches', "productID=" + $(product).val()), function(data)
|
||||
{
|
||||
@@ -156,12 +156,35 @@ function loadBranches(product)
|
||||
$inputgroup.append(data);
|
||||
$inputgroup.find('select:last').attr('name', 'branch[' + index + ']').attr('id', 'branch' + index).css('width', '80px');
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
var productID = $(product).val();
|
||||
if(productID != 0)
|
||||
{
|
||||
console.log($("#plan" + productID).length );
|
||||
if($("#plan" + productID).length == 0)
|
||||
{
|
||||
$(product).data("last", productID);
|
||||
$.get(createLink('product', 'ajaxGetPlans', "productID=" + productID), function(data)
|
||||
{
|
||||
if(data)
|
||||
{
|
||||
$("#plansBox .row").append('<div class="col-sm-3" id="plan' + productID+ '">' + data + '</div>');
|
||||
$("#plan" + $(product).val()).find('select').attr('name', 'plans[' + productID + ']').attr('id', 'plans' + productID);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#plan" + $(product).data('last')).remove();
|
||||
}
|
||||
}
|
||||
|
||||
function loadBranch(){}
|
||||
|
||||
/* Auto compute the work days. */
|
||||
$(function()
|
||||
$(function()
|
||||
{
|
||||
if(typeof(replaceID) != 'undefined')
|
||||
{
|
||||
@@ -195,8 +218,8 @@ $(function()
|
||||
$('tr.parent-'+id).hide();
|
||||
$toggleIcon.removeClass('icon-double-angle-up').addClass('icon-double-angle-down');
|
||||
}
|
||||
|
||||
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
@@ -8,10 +8,10 @@ $(function()
|
||||
$('#cpmBtn').click(function(){$('#copyProjectModal').modal('show')});
|
||||
$('#copyProjects a').click(function(){setCopyProject($(this).data('id')); $('#copyProjectModal').modal('hide')});
|
||||
var typeWidth = $('#type').closest('td').width();
|
||||
$('#productsBox .col-sm-3').width(typeWidth);
|
||||
$('#productsBox .col-sm-3,#plansBox .col-sm-3').width(typeWidth);
|
||||
$(document).on('change', "#productsBox select", function()
|
||||
{
|
||||
$('#productsBox .col-sm-3').width(typeWidth);
|
||||
$('#productsBox .col-sm-3,#plansBox .col-sm-3').width(typeWidth);
|
||||
});
|
||||
$('#begin').on('change', function()
|
||||
{
|
||||
@@ -37,3 +37,4 @@ function showTypeTips()
|
||||
$('.type-tips').hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,6 +117,7 @@ $lang->project->team = 'Team Member';
|
||||
$lang->project->doc = 'Doc';
|
||||
$lang->project->manageProducts = 'Link ' . $lang->productCommon;
|
||||
$lang->project->linkStory = 'Linked Story';
|
||||
$lang->project->linkPlan = 'Linked Plan';
|
||||
$lang->project->unlinkStoryTasks = 'Unlinked';
|
||||
$lang->project->linkedProducts = 'Linked Products';
|
||||
$lang->project->unlinkedProducts = 'Unlinked Products';
|
||||
@@ -283,10 +284,10 @@ $lang->project->featureBar['task']['needconfirm'] = 'Story Changed';
|
||||
$lang->project->featureBar['task']['status'] = $lang->project->statusSelects[''];
|
||||
|
||||
$lang->project->treeLevel = array();
|
||||
$lang->project->treeLevel['root'] = 'Show Root';
|
||||
$lang->project->treeLevel['story'] = 'Show Story';
|
||||
$lang->project->treeLevel['task'] = 'Show Task';
|
||||
$lang->project->treeLevel['all'] = 'Show All';
|
||||
$lang->project->treeLevel['root'] = 'Show Root';
|
||||
$lang->project->treeLevel['story'] = 'Show Story';
|
||||
$lang->project->treeLevel['task'] = 'Show Task';
|
||||
$lang->project->treeLevel['all'] = 'Show All';
|
||||
|
||||
global $config;
|
||||
if($config->global->flow == 'onlyTask')
|
||||
|
||||
@@ -66,13 +66,13 @@ $lang->project->typeList['sprint'] = "短期$lang->projectCommon";
|
||||
$lang->project->typeList['waterfall'] = "长期$lang->projectCommon";
|
||||
$lang->project->typeList['ops'] = "运维$lang->projectCommon";
|
||||
|
||||
$lang->project->endList[7] = '一星期';
|
||||
$lang->project->endList[14] = '两星期';
|
||||
$lang->project->endList[31] = '一个月';
|
||||
$lang->project->endList[62] = '两个月';
|
||||
$lang->project->endList[93] = '三个月';
|
||||
$lang->project->endList[186] = '半年';
|
||||
$lang->project->endList[365] = '一年';
|
||||
$lang->project->endList[7] = '一星期';
|
||||
$lang->project->endList[14] = '两星期';
|
||||
$lang->project->endList[31] = '一个月';
|
||||
$lang->project->endList[62] = '两个月';
|
||||
$lang->project->endList[93] = '三个月';
|
||||
$lang->project->endList[186] = '半年';
|
||||
$lang->project->endList[365] = '一年';
|
||||
|
||||
$lang->team = new stdclass();
|
||||
$lang->team->account = '用户';
|
||||
@@ -117,6 +117,7 @@ $lang->project->team = '团队成员';
|
||||
$lang->project->doc = '文档列表';
|
||||
$lang->project->manageProducts = '关联' . $lang->productCommon;
|
||||
$lang->project->linkStory = '关联需求';
|
||||
$lang->project->linkPlan = '关联计划';
|
||||
$lang->project->unlinkStoryTasks = '未关联需求任务';
|
||||
$lang->project->linkedProducts = '已关联';
|
||||
$lang->project->unlinkedProducts = '未关联';
|
||||
@@ -283,10 +284,10 @@ $lang->project->featureBar['task']['needconfirm'] = '需求变动';
|
||||
$lang->project->featureBar['task']['status'] = $lang->project->statusSelects[''];
|
||||
|
||||
$lang->project->treeLevel = array();
|
||||
$lang->project->treeLevel['root'] = '全部折叠';
|
||||
$lang->project->treeLevel['story'] = '显示需求';
|
||||
$lang->project->treeLevel['task'] = '显示任务';
|
||||
$lang->project->treeLevel['all'] = '全部展开';
|
||||
$lang->project->treeLevel['root'] = '全部折叠';
|
||||
$lang->project->treeLevel['story'] = '显示需求';
|
||||
$lang->project->treeLevel['task'] = '显示任务';
|
||||
$lang->project->treeLevel['all'] = '全部展开';
|
||||
|
||||
global $config;
|
||||
if($config->global->flow == 'onlyTask')
|
||||
|
||||
@@ -219,6 +219,8 @@ class projectModel extends model
|
||||
/**
|
||||
* Create a project.
|
||||
*
|
||||
* @param string $copyProjectID
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
@@ -232,7 +234,7 @@ class projectModel extends model
|
||||
->setDefault('team', substr($this->post->name,0, 30))
|
||||
->join('whitelist', ',')
|
||||
->stripTags($this->config->project->editor->create['id'], $this->config->allowedTags)
|
||||
->remove('products, workDays, delta, branch,uid')
|
||||
->remove('products, workDays, delta, branch, uid, plans')
|
||||
->get();
|
||||
$project = $this->loadModel('file')->processImgURL($project, $this->config->project->editor->create['id'], $this->post->uid);
|
||||
$this->dao->insert(TABLE_PROJECT)->data($project)
|
||||
@@ -318,7 +320,7 @@ class projectModel extends model
|
||||
->setDefault('team', $this->post->name)
|
||||
->join('whitelist', ',')
|
||||
->stripTags($this->config->project->editor->edit['id'], $this->config->allowedTags)
|
||||
->remove('products,branch,uid')
|
||||
->remove('products, branch, uid, plans')
|
||||
->get();
|
||||
$project = $this->loadModel('file')->processImgURL($project, $this->config->project->editor->edit['id'], $this->post->uid);
|
||||
$this->dao->update(TABLE_PROJECT)->data($project)
|
||||
@@ -1035,7 +1037,7 @@ class projectModel extends model
|
||||
if(!$withBranch) return $this->loadModel('tutorial')->getProductPairs();
|
||||
return $this->loadModel('tutorial')->getProjectProducts();
|
||||
}
|
||||
$query = $this->dao->select('t2.id, t2.name, t2.type, t1.branch')->from(TABLE_PROJECTPRODUCT)->alias('t1')
|
||||
$query = $this->dao->select('t2.id, t2.name, t2.type, t1.branch, t1.plan')->from(TABLE_PROJECTPRODUCT)->alias('t1')
|
||||
->leftJoin(TABLE_PRODUCT)->alias('t2')
|
||||
->on('t1.product = t2.id')
|
||||
->where('t1.project')->eq((int)$projectID);
|
||||
@@ -1146,6 +1148,7 @@ class projectModel extends model
|
||||
if(!isset($_POST['products'])) return;
|
||||
$products = $_POST['products'];
|
||||
$branches = isset($_POST['branch']) ? $_POST['branch'] : array();
|
||||
$plans = $_POST['plans'];
|
||||
|
||||
$existedProducts = array();
|
||||
$addedProducts = array();
|
||||
@@ -1166,6 +1169,7 @@ class projectModel extends model
|
||||
$data->project = $projectID;
|
||||
$data->product = $productID;
|
||||
$data->branch = isset($branches[$i]) ? $branches[$i] : 0;
|
||||
$data->plan = isset($plans[$productID]) ? $plans[$productID] : 0;
|
||||
$this->dao->insert(TABLE_PROJECTPRODUCT)->data($data)->exec();
|
||||
$existedProducts[$productID] = true;
|
||||
}
|
||||
@@ -2543,4 +2547,25 @@ class projectModel extends model
|
||||
if(isset($fullTrees[0]) and empty($fullTrees[0]->children)) array_shift($fullTrees);
|
||||
return array_values($fullTrees);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plans by projectID.
|
||||
*
|
||||
* @param int|array $projectID
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPlans($projectID)
|
||||
{
|
||||
$plans = $this->dao->select('id,title,product')->from(TABLE_PRODUCTPLAN)
|
||||
->where('product')->in($projectID)
|
||||
->fetchAll();
|
||||
|
||||
$productPlans = array();
|
||||
foreach ($plans as $plan)
|
||||
{
|
||||
$productPlans[$plan->product][$plan->id] = $plan->title;
|
||||
}
|
||||
return $productPlans;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<form class='form-condensed' method='post' target='hiddenwin' id='dataform'>
|
||||
<table class='table table-form'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th class='w-90px'><?php echo $lang->project->name;?></th>
|
||||
<td class='w-p25-f'><?php echo html::input('name', $name, "class='form-control' autocomplete='off'");?></td><td></td>
|
||||
@@ -52,14 +52,14 @@
|
||||
<tr>
|
||||
<th><?php echo $lang->project->code;?></th>
|
||||
<td><?php echo html::input('code', $code, "class='form-control' autocomplete='off'");?></td>
|
||||
</tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->project->dateRange;?></th>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<?php echo html::input('begin',date('Y-m-d'), "class='form-control w-100px form-date' onchange='computeWorkDays()' placeholder='" . $lang->project->begin . "'");?>
|
||||
<?php echo html::input('begin', (isset($plan) && !empty($plan->begin) ? $plan->begin : date('Y-m-d')), "class='form-control w-100px form-date' onchange='computeWorkDays()' placeholder='" . $lang->project->begin . "'");?>
|
||||
<span class='input-group-addon'><?php echo $lang->project->to;?></span>
|
||||
<?php echo html::input('end', '', "class='form-control form-date' onchange='computeWorkDays()' placeholder='" . $lang->project->end . "'");?>
|
||||
<?php echo html::input('end', (isset($plan) && !empty($plan->end) ? $plan->end : ''), "class='form-control form-date' onchange='computeWorkDays()' placeholder='" . $lang->project->end . "'");?>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
@@ -70,15 +70,15 @@
|
||||
<th><?php echo $lang->project->days;?></th>
|
||||
<td>
|
||||
<div class='input-group'>
|
||||
<?php echo html::input('days', '', "class='form-control' autocomplete='off'");?>
|
||||
<?php echo html::input('days', (isset($plan) && !empty($plan->begin) ? helper::workDays($plan->begin, $plan->end) : ''), "class='form-control' autocomplete='off'");?>
|
||||
<span class='input-group-addon'><?php echo $lang->project->day;?></span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->project->teamname;?></th>
|
||||
<td><?php echo html::input('team', $team, "class='form-control' autocomplete='off'");?></td>
|
||||
</tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->project->type;?></th>
|
||||
<td>
|
||||
@@ -96,8 +96,8 @@
|
||||
<?php foreach($products as $product):?>
|
||||
<div class='col-sm-3'>
|
||||
<div class='input-group'>
|
||||
<?php echo html::select("products[$i]", $allProducts, $product->id, "class='form-control chosen' onchange='loadBranches(this)'");?>
|
||||
<span class='input-group-addon fix-border' style='padding:0px'></span>
|
||||
<?php echo html::select("products[$i]", $allProducts, $product->id, "class='form-control chosen' onchange='loadBranches(this)' data-last='" . $product->id . "'");?>
|
||||
<span class='input-group-addon fix-border' style='padding:0'></span>
|
||||
<?php if($product->type != 'normal') echo html::select("branch[$i]", $branchGroups[$product->id], $product->branch, "class='form-control' style='width:80px'")?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -106,20 +106,32 @@
|
||||
<div class='col-sm-3'>
|
||||
<div class='input-group'>
|
||||
<?php echo html::select("products[$i]", $allProducts, '', "class='form-control chosen' onchange='loadBranches(this)'");?>
|
||||
<span class='input-group-addon fix-border' style='padding:0px'></span>
|
||||
<span class='input-group-addon fix-border' style='padding:0'></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr <?php if($this->config->global->flow == 'onlyTask') echo "class='hidden'";?>>
|
||||
<th><?php echo $lang->project->linkPlan;?></th>
|
||||
<td colspan="2" id="plansBox">
|
||||
<div class='row'>
|
||||
<?php if(isset($plan) && !empty($plan->begin)):?>
|
||||
<div class="col-sm-3" id="plan<?php echo $plan->product;?>">
|
||||
<?php echo html::select("plans[<?php echo $plan->product;?>]", $productPlan, $plan->id, "class='form-control'");?>
|
||||
</div>
|
||||
<?php endif;?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->project->desc;?></th>
|
||||
<td colspan='2'><?php echo html::textarea('desc', '', "rows='6' class='form-control'");?></td>
|
||||
</tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->project->acl;?></th>
|
||||
<td colspan='2'><?php echo nl2br(html::radio('acl', $lang->project->aclList, $acl, "onclick='setWhite(this.value);'", 'block'));?></td>
|
||||
</tr>
|
||||
</tr>
|
||||
<tr id='whitelistBox' <?php if($acl != 'custom') echo "class='hidden'";?>>
|
||||
<th><?php echo $lang->project->whitelist;?></th>
|
||||
<td colspan='2'><?php echo html::checkbox('whitelist', $groups, $whitelist);?></td>
|
||||
|
||||
@@ -23,11 +23,11 @@
|
||||
</div>
|
||||
</div>
|
||||
<form class='form-condensed' method='post' target='hiddenwin' id='dataform'>
|
||||
<table class='table table-form'>
|
||||
<table class='table table-form'>
|
||||
<tr>
|
||||
<th class='w-90px'><?php echo $lang->project->name;?></th>
|
||||
<td class='w-p45'><?php echo html::input('name', $project->name, "class='form-control' autocomplete='off'");?></td><td></td>
|
||||
</tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->project->code;?></th>
|
||||
<td><?php echo html::input('code', $project->code, "class='form-control' autocomplete='off'");?></td>
|
||||
@@ -58,15 +58,15 @@
|
||||
<span class='input-group-addon'><?php echo $lang->project->day;?></span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->project->type;?></th>
|
||||
<td><?php echo html::select('type', $lang->project->typeList, $project->type, "class='form-control'");?></td>
|
||||
</tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->project->teamname;?></th>
|
||||
<td><?php echo html::input('team', $project->team, "class='form-control' autocomplete='off'");?></td>
|
||||
</tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->project->status;?></th>
|
||||
<td><?php echo html::select('status', $lang->project->statusList, $project->status, "class='form-control'");?></td>
|
||||
@@ -115,7 +115,7 @@
|
||||
<?php foreach($linkedProducts as $product):?>
|
||||
<div class='col-sm-3'>
|
||||
<div class='input-group'>
|
||||
<?php echo html::select("products[$i]", $allProducts, $product->id, "class='form-control chosen' onchange='loadBranches(this)'");?>
|
||||
<?php echo html::select("products[$i]", $allProducts, $product->id, "class='form-control chosen' onchange='loadBranches(this)' data-last='" . $product->id . "'");?>
|
||||
<span class='input-group-addon fix-border' style='padding:0px'></span>
|
||||
<?php if($product->type != 'normal' and isset($branchGroups[$product->id])) echo html::select("branch[$i]", $branchGroups[$product->id], $product->branch, "class='form-control' style='width:80px'")?>
|
||||
</div>
|
||||
@@ -131,6 +131,18 @@
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr <?php if($this->config->global->flow == 'onlyTask') echo "class='hidden'";?>>
|
||||
<th><?php echo $lang->project->linkPlan;?></th>
|
||||
<td class='text-left' id="plansBox" colspan="2">
|
||||
<div class='row'>
|
||||
<?php foreach($plans as $productID => $plan):?>
|
||||
<div class="col-sm-3" id="plan<?php echo $productID;?>">
|
||||
<?php echo html::select("plans[$productID]", $plan, $linkedProducts[$productID]->plan, "class='form-control'");?>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><?php echo $lang->project->desc;?></th>
|
||||
<td colspan='2'><?php echo html::textarea('desc', htmlspecialchars($project->desc), "rows='6' class='form-control'");?></td>
|
||||
|
||||
Reference in New Issue
Block a user