Merge branch 'master' into 'sprint/183_xieqiyu_47995new'

# Conflicts:
#   db/update16.2.sql
#   module/group/lang/resource.php
#   module/kanban/js/view.js
#   module/kanban/model.php
This commit is contained in:
孙广明
2022-01-24 07:28:48 +00:00
67 changed files with 1644 additions and 263 deletions
+3 -3
View File
@@ -1,7 +1,7 @@
ALTER TABLE `zt_kanbanspace` ADD `type` varchar(50) NOT NULL AFTER `name`;
UPDATE `zt_kanbanspace` SET `type` = 'cooperation';
UPDATE `zt_kanbanspace` SET `type` = 'cooperation', `whitelist` = '';
ALTER TABLE `zt_kanban` ADD `importObject` varchar(255) NOT NULL AFTER `displayCards`;
ALTER TABLE `zt_kanban` ADD `object` varchar(255) NOT NULL AFTER `displayCards`;
ALTER TABLE `zt_kanban` ADD `performable` enum ('0', '1') NOT NULL DEFAULT '0' AFTER `archived`;
ALTER TABLE `zt_kanbancard` ADD `status` varchar(30) NOT NULL AFTER `name`;
@@ -9,4 +9,4 @@ ALTER TABLE `zt_kanbancard` ADD `fromID` mediumint(8) unsigned NOT NULL AFTER `g
ALTER TABLE `zt_kanbancard` ADD `fromType` varchar(30) NOT NULL AFTER `fromID`;
ALTER TABLE `zt_job` ADD `sonarqubeServer` mediumint(8) unsigned NOT NULL AFTER `triggerType`;
ALTER TABLE `zt_job` ADD `projectKey` varchar(255) NOT NULL AFTER `sonarqubeServer`;
ALTER TABLE `zt_job` ADD `projectKey` varchar(255) NOT NULL AFTER `sonarqubeServer`;
+1
View File
@@ -679,6 +679,7 @@ CREATE TABLE `zt_kanban` (
`status` enum('active','closed') NOT NULL default 'active',
`order` mediumint(8) NOT NULL DEFAULT '0',
`displayCards` smallint(6) NOT NULL default '0',
`object` varchar(255) NOT NULL,
`createdBy` char(30) NOT NULL,
`createdDate` datetime NOT NULL,
`lastEditedBy` char(30) NOT NULL,
+1 -1
View File
@@ -632,7 +632,7 @@ $lang->action->label->issue = 'Issue|issue|view|issueID=%s';
$lang->action->label->design = 'Design|design|view|designID=%s';
$lang->action->label->stakeholder = 'Stakeholder|stakeholder|view|userID=%s';
$lang->action->label->api = 'Interface|api|index|libID=%s&moduleID=%s&apiID=%s';
$lang->action->label->kanbanspace = 'Kanban Space|kanban|space|browseType=all';
$lang->action->label->kanbanspace = 'Kanban Space|kanban|space|browseType=%s';
$lang->action->label->kanbanregion = 'Kanban Region|kanban|view|kanbanID=%s';
$lang->action->label->kanban = 'Kanban|kanban|view|kanbanID=%s';
$lang->action->label->kanbancolumn = 'Kanban Column|execution|kanban|execution=%s';
+1 -1
View File
@@ -632,7 +632,7 @@ $lang->action->label->issue = '问题|issue|view|issueID=%s';
$lang->action->label->design = '设计|design|view|designID=%s';
$lang->action->label->stakeholder = '干系人|stakeholder|view|userID=%s';
$lang->action->label->api = '接口|api|index|libID=%s&moduleID=%s&apiID=%s';
$lang->action->label->kanbanspace = '看板空间|kanban|space|browseType=all';
$lang->action->label->kanbanspace = '看板空间|kanban|space|browseType=%s';
$lang->action->label->kanbanregion = '看板区域|kanban|view|kanbanID=%s';
$lang->action->label->kanban = '看板|kanban|view|kanbanID=%s';
$lang->action->label->kanbancolumn = '看板列|execution|kanban|execution=%s';
+5
View File
@@ -1301,6 +1301,11 @@ class actionModel extends model
{
$params = sprintf($vars, trim($action->product, ','));
}
elseif($action->objectType == 'kanbanspace')
{
$kanbanSpace = $this->dao->select('type')->from(TABLE_KANBANSPACE)->where('id')->eq($action->objectID)->fetch();
$params = sprintf($vars, $kanbanSpace->type);
}
elseif($action->objectType == 'kanbancolumn' or $action->objectType == 'kanbanlane')
{
$params = sprintf($vars, $action->extra);
+10 -1
View File
@@ -3,7 +3,16 @@
.ztf-logo {width: 30%;}
.zendata-logo { width: 30%;}
.block-zendata {height:230px;}
.block-zendata {height:230px; padding: 30px 14px;}
.block-details {padding: 30px 60px;}
.block-details li {width: 50%;}
.block-details-line li {width: 100%;}
.zendata-download {width: 68%;}
.ztf-download {width: 58%;}
.ztf-download-trait {margin: 35px 0 6px 0;}
.ztf-download-trait div {width: 47%;}
.qr-code {padding: 20px 0 20px 32px;}
@media screen and (max-height: 768px)
{
-19
View File
@@ -106,25 +106,6 @@ $lang->block->spent = 'Has Been Spent';
$lang->block->budget = 'Budget';
$lang->block->left = 'Residuals';
$lang->block->titleList['flowchart'] = 'Flowchart';
$lang->block->titleList['statistic'] = 'Statistic';
$lang->block->titleList['recentproject'] = 'Recent Project';
$lang->block->titleList['assigntome'] = 'Assign To Me';
$lang->block->titleList['projectteam'] = 'Project Team';
$lang->block->titleList['project'] = 'Project';
$lang->block->titleList['dynamic'] = 'Dynamic';
$lang->block->titleList['list'] = 'List';
$lang->block->titleList['contribute'] = 'Contribute';
$lang->block->titleList['scrumoverview'] = 'Scrum Overview';
$lang->block->titleList['scrumtest'] = 'Scrum Test';
$lang->block->titleList['scrumlist'] = 'Scrum List';
$lang->block->titleList['sprint'] = 'Sprint';
$lang->block->titleList['projectdynamic'] = 'Project Dynamic';
$lang->block->titleList['bug'] = 'Bug';
$lang->block->titleList['case'] = 'Case';
$lang->block->titleList['testtask'] = 'Testtask';
$lang->block->default['waterfall']['project']['3']['title'] = 'Plan Gantt Chart';
$lang->block->default['waterfall']['project']['3']['block'] = 'waterfallgantt';
$lang->block->default['waterfall']['project']['3']['source'] = 'project';
-19
View File
@@ -106,25 +106,6 @@ $lang->block->spent = '已花费';
$lang->block->budget = '预算';
$lang->block->left = '剩余';
$lang->block->titleList['flowchart'] = '流程图';
$lang->block->titleList['statistic'] = '项目统计';
$lang->block->titleList['recentproject'] = '我近期参与的项目';
$lang->block->titleList['assigntome'] = '待处理';
$lang->block->titleList['projectteam'] = '项目人力投入';
$lang->block->titleList['project'] = '项目列表';
$lang->block->titleList['dynamic'] = '最新动态';
$lang->block->titleList['list'] = '我的待办';
$lang->block->titleList['contribute'] = '我的贡献';
$lang->block->titleList['scrumoverview'] = '项目概况';
$lang->block->titleList['scrumtest'] = '待测版本';
$lang->block->titleList['scrumlist'] = '迭代列表';
$lang->block->titleList['sprint'] = '迭代总览';
$lang->block->titleList['projectdynamic'] = '最新动态';
$lang->block->titleList['bug'] = '指派给我的Bug';
$lang->block->titleList['case'] = '指派给我的用例';
$lang->block->titleList['testtask'] = '待测版本列表';
$lang->block->default['waterfall']['project']['3']['title'] = "项目计划";
$lang->block->default['waterfall']['project']['3']['block'] = 'waterfallgantt';
$lang->block->default['waterfall']['project']['3']['source'] = 'project';
+2 -2
View File
@@ -35,7 +35,7 @@ $useGuest = $this->app->user->account == 'guest';
<?php $hasHeading = ($block->block != 'welcome');?>
<?php if($hasHeading):?>
<div class='panel-heading'>
<div class='panel-title'><?php echo zget($lang->block->titleList, $block->block);?></div>
<div class='panel-title'><?php echo $block->title;?></div>
<?php endif;?>
<nav class='panel-actions nav nav-default'>
<?php if(!empty($block->moreLink)) echo '<li>' . html::a($block->moreLink, '<i class="icon icon-more"></i>', '', "title='{$lang->more}'") . '</li>'; ?>
@@ -70,7 +70,7 @@ $useGuest = $this->app->user->account == 'guest';
<?php $hasHeading = ($block->block != 'welcome');?>
<?php if($hasHeading):?>
<div class='panel-heading'>
<div class='panel-title'><?php echo zget($lang->block->titleList, $block->block);?></div>
<div class='panel-title'><?php echo $block->title;?></div>
<?php endif;?>
<nav class='panel-actions nav nav-default'>
<?php if(!empty($block->moreLink)) echo '<li>' . html::a($block->moreLink, '<i class="icon icon-more"></i>', '', "title='{$lang->more}'") . '</li>';?>
+130 -14
View File
@@ -402,8 +402,22 @@ class bug extends control
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $bugID));
/* If link from no head then reload. */
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
if(isset($output['executionID']) and isonlybody())
{
$executionID = $this->post->execution ? $this->post->execution : $output['executionID'];
if($executionID == $output['executionID'])
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.updateKanban($kanbanData, 0)"));
}
else
{
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true));
}
}
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success', 'data' => $bugID));
if($this->app->tab == 'execution')
@@ -683,7 +697,25 @@ class bug extends control
setcookie('bugModule', 0, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
/* If link from no head then reload. */
if(isonlybody() and $executionID)
{
$execution = $this->loadModel('execution')->getByID($executionID);
if($execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::reload('parent.parent'));
}
}
if(isonlybody()) return print(js::reload('parent.parent'));
return print(js::locate($this->createLink('bug', 'browse', "productID={$productID}&branch=$branch&browseType=unclosed&param=0&orderBy=id_desc"), 'parent'));
}
@@ -1180,7 +1212,22 @@ class bug extends control
$this->executeHooks($bugID);
if(isonlybody()) return print(js::closeModal('parent.parent'));
if(isonlybody())
{
$bug = $this->bug->getById($bugID);
$execution = $this->loadModel('execution')->getByID($bug->execution);
if(isset($execution->type) and $execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($bug->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent'));
}
}
return print(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
}
@@ -1354,6 +1401,7 @@ class bug extends control
*/
public function confirmBug($bugID, $extra = '')
{
$bug = $this->bug->getById($bugID);
if(!empty($_POST))
{
$changes = $this->bug->confirm($bugID, $extra);
@@ -1363,11 +1411,27 @@ class bug extends control
$this->executeHooks($bugID);
if(isonlybody()) return print(js::closeModal('parent.parent'));
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(isonlybody())
{
$execution = $this->loadModel('execution')->getByID($bug->execution);
if(isset($execution->type) and $execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($bug->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent'));
}
}
return print(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
}
$bug = $this->bug->getById($bugID);
$productID = $bug->product;
$this->bug->checkBugExecutionPriv($bug);
$this->qa->setMenu($this->products, $productID, $bug->branch);
@@ -1410,6 +1474,7 @@ class bug extends control
*/
public function resolve($bugID, $extra = '')
{
$bug = $this->bug->getById($bugID);
if(!empty($_POST))
{
$changes = $this->bug->resolve($bugID, $extra);
@@ -1436,19 +1501,36 @@ class bug extends control
die(js::confirm(sprintf($this->lang->bug->remindTask, $bug->toTask), $confirmURL, $cancelURL, 'parent', 'parent.parent'));
}
}
if(isonlybody()) die(js::reload('parent.parent'));
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(isonlybody())
{
$execution = $this->loadModel('execution')->getByID($bug->execution);
if(isset($execution->type) and $execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($bug->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent'));
}
}
if(defined('RUN_MODE') && RUN_MODE == 'api')
{
die(array('status' => 'success', 'data' => $bugID));
return print(array('status' => 'success', 'data' => $bugID));
}
else
{
die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
return print(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
}
}
$projectID = $this->lang->navGroup->bug == 'project' ? $this->session->project : 0;
$bug = $this->bug->getById($bugID);
$productID = $bug->product;
$users = $this->user->getPairs('noclosed');
$assignedTo = $bug->openedBy;
@@ -1504,6 +1586,7 @@ class bug extends control
*/
public function activate($bugID, $extra = '')
{
$bug = $this->bug->getById($bugID);
if(!empty($_POST))
{
$changes = $this->bug->activate($bugID, $extra);
@@ -1516,11 +1599,27 @@ class bug extends control
$this->executeHooks($bugID);
if(isonlybody()) die(js::closeModal('parent.parent'));
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(isonlybody())
{
$execution = $this->loadModel('execution')->getByID($bug->execution);
if(isset($execution->type) and $execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($bug->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent'));
}
}
die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
}
$bug = $this->bug->getById($bugID);
$productID = $bug->product;
$this->bug->checkBugExecutionPriv($bug);
$this->qa->setMenu($this->products, $productID, $bug->branch);
@@ -1547,6 +1646,7 @@ class bug extends control
*/
public function close($bugID, $extra = '')
{
$bug = $this->bug->getById($bugID);
if(!empty($_POST))
{
$changes = $this->bug->close($bugID, $extra);
@@ -1557,18 +1657,34 @@ class bug extends control
$this->executeHooks($bugID);
if(isonlybody()) die(js::closeModal('parent.parent'));
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(isonlybody())
{
$execution = $this->loadModel('execution')->getByID($bug->execution);
if(isset($execution->type) and $execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($bug->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent'));
}
}
if(defined('RUN_MODE') && RUN_MODE == 'api')
{
die(array('status' => 'success', 'data' => $bugID));
return print(array('status' => 'success', 'data' => $bugID));
}
else
{
die(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
return print(js::locate($this->createLink('bug', 'view', "bugID=$bugID"), 'parent'));
}
}
$bug = $this->bug->getById($bugID);
$productID = $bug->product;
$this->bug->checkBugExecutionPriv($bug);
$this->qa->setMenu($this->products, $productID, $bug->branch);
+2 -3
View File
@@ -48,8 +48,8 @@ $lang->bug->confirmed = 'Confirmed';
$lang->bug->confirmedAB = 'C';
$lang->bug->toTask = 'Convert to Task';
$lang->bug->toStory = 'Convert to Story';
$lang->bug->feedbackBy = 'From Name';
$lang->bug->notifyEmail = 'From Email';
$lang->bug->feedbackBy = 'Discovered by';
$lang->bug->notifyEmail = 'Discoverer Email';
$lang->bug->mailto = 'Mailto';
$lang->bug->openedBy = 'ReportedBy';
$lang->bug->openedByAB = 'Reporter';
@@ -419,7 +419,6 @@ $lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe;
$lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved;
$lang->bug->featureBar['browse']['more'] = $lang->more;
$lang->bug->moreSelects['toclosed'] = $lang->bug->toClosed;
$lang->bug->moreSelects['unconfirmed'] = $lang->bug->unconfirmed;
$lang->bug->moreSelects['assigntonull'] = $lang->bug->assignToNull;
$lang->bug->moreSelects['longlifebugs'] = $lang->bug->longLifeBugs;
-1
View File
@@ -419,7 +419,6 @@ $lang->bug->featureBar['browse']['toclosed'] = $lang->bug->toClosed;
$lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved;
$lang->bug->featureBar['browse']['more'] = $lang->more;
$lang->bug->moreSelects['unconfirmed'] = $lang->bug->unconfirmed;
$lang->bug->moreSelects['assigntonull'] = $lang->bug->assignToNull;
$lang->bug->moreSelects['longlifebugs'] = $lang->bug->longLifeBugs;
+1 -1
View File
@@ -491,7 +491,7 @@ $lang->admin->menu->allModel['subMenu']->storyConcept = array('link' => "{$lang-
$lang->admin->menu->allModel['menuOrder'][5] = 'storyConcept';
$lang->admin->menu->waterfall['subMenu'] = new stdclass();
$lang->admin->menu->waterfall['subMenu']->stage = array('link' => '阶段|stage|setType|', 'subModule' => 'stage');
$lang->admin->menu->waterfall['subMenu']->stage = array('link' => "{$lang->stage->common}|stage|setType|", 'subModule' => 'stage');
/* Admin menu order. */
$lang->admin->menuOrder[5] = 'index';
+69 -14
View File
@@ -1709,10 +1709,11 @@ class execution extends control
* Start execution.
*
* @param int $executionID
* @param string $from
* @access public
* @return void
*/
public function start($executionID)
public function start($executionID, $from = 'execution')
{
$execution = $this->commonAction($executionID);
$executionID = $execution->id;
@@ -1732,7 +1733,14 @@ class execution extends control
$this->loadModel('common')->syncPPEStatus($executionID);
$this->executeHooks($executionID);
die(js::reload('parent.parent'));
if(isonlybody() and $from == 'kanban')
{
return print(js::closeModal('parent.parent', '', "parent.parent.changeStatus('doing')"));
}
else
{
return print(js::reload('parent.parent'));
}
}
$this->view->title = $this->view->execution->name . $this->lang->colon .$this->lang->execution->start;
@@ -1747,10 +1755,11 @@ class execution extends control
* Delay execution.
*
* @param int $executionID
* @param string $from
* @access public
* @return void
*/
public function putoff($executionID)
public function putoff($executionID, $from = 'execution')
{
$execution = $this->commonAction($executionID);
$executionID = $execution->id;
@@ -1767,7 +1776,14 @@ class execution extends control
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($executionID);
die(js::reload('parent.parent'));
if(isonlybody() and $from == 'kanban')
{
return print(js::closeModal('parent.parent', '', "parent.parent.changeStatus('doing')"));
}
else
{
return print(js::reload('parent.parent'));
}
}
$this->view->title = $this->view->execution->name . $this->lang->colon .$this->lang->execution->putoff;
@@ -1782,10 +1798,11 @@ class execution extends control
* Suspend execution.
*
* @param int $executionID
* @param string $from
* @access public
* @return void
*/
public function suspend($executionID)
public function suspend($executionID, $from = 'execution')
{
$execution = $this->commonAction($executionID);
$executionID = $execution->id;
@@ -1803,7 +1820,14 @@ class execution extends control
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($executionID);
die(js::reload('parent.parent'));
if(isonlybody() and $from == 'kanban')
{
return print(js::closeModal('parent.parent', '', "parent.parent.changeStatus('suspended')"));
}
else
{
return print(js::reload('parent.parent'));
}
}
$this->view->title = $this->view->execution->name . $this->lang->colon .$this->lang->execution->suspend;
@@ -1818,10 +1842,11 @@ class execution extends control
* Activate execution.
*
* @param int $executionID
* @param string $frim
* @access public
* @return void
*/
public function activate($executionID)
public function activate($executionID, $from = 'execution')
{
$execution = $this->commonAction($executionID);
$executionID = $execution->id;
@@ -1839,7 +1864,14 @@ class execution extends control
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($executionID);
die(js::reload('parent.parent'));
if(isonlybody() and $from == 'kanban')
{
return print(js::closeModal('parent.parent', '', "parent.parent.changeStatus('doing')"));
}
else
{
return print(js::reload('parent.parent'));
}
}
$newBegin = date('Y-m-d');
@@ -1861,10 +1893,11 @@ class execution extends control
* Close execution.
*
* @param int $executionID
* @param string $from
* @access public
* @return void
*/
public function close($executionID)
public function close($executionID, $from = 'execution')
{
$execution = $this->commonAction($executionID);
$executionID = $execution->id;
@@ -1882,7 +1915,14 @@ class execution extends control
$this->action->logHistory($actionID, $changes);
}
$this->executeHooks($executionID);
die(js::reload('parent.parent'));
if(isonlybody() and $from == 'kanban')
{
return print(js::closeModal('parent.parent', '', "parent.parent.changeStatus('closed')"));
}
else
{
return print(js::reload('parent.parent'));
}
}
$this->view->title = $this->view->execution->name . $this->lang->colon .$this->lang->execution->close;
@@ -1969,6 +2009,7 @@ class execution extends control
$this->app->loadLang('bug');
$this->app->loadLang('story');
if(empty($groupBy)) $groupBy = 'default';
$this->session->set('execLaneType', $browseType);
$this->lang->execution->menu = new stdclass();
$execution = $this->commonAction($executionID);
@@ -2658,7 +2699,7 @@ class execution extends control
if(empty($products))
{
echo js::alert($this->lang->execution->errorNoLinkedProducts);
die(js::locate($this->createLink('execution', 'manageproducts', "executionID=$objectID")));
return print(js::locate($this->createLink('execution', 'manageproducts', "executionID=$objectID")));
}
if(!empty($_POST))
@@ -2666,8 +2707,22 @@ class execution extends control
$this->execution->linkStory($objectID, array(), array(), $extra);
if($object->type != 'project' and $object->project != 0) $this->execution->linkStory($object->project);
if(isonlybody()) die(js::reload('parent'));
die(js::locate($browseLink));
if(isonlybody())
{
if($this->app->tab == 'execution' and $object->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($objectID, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent', '', "parent.updateKanban($kanbanData)"));
}
else
{
return print(js::reload('parent'));
}
}
return print(js::locate($browseLink));
}
if($object->type == 'project')
@@ -3441,7 +3496,7 @@ class execution extends control
include $this->app->getModulePath('', 'execution') . 'lang/' . $this->app->getClientLang() . '.php';
}
if($count != 0) echo js::alert(sprintf($this->lang->execution->haveDraft, $count)) . js::locate($this->createLink($moduleName, $execution->type == 'sprint' ? 'story' : 'kanban', $param));
die(js::locate(helper::createLink($moduleName, $fromMethod, $param)));
return print(js::locate(helper::createLink($moduleName, $fromMethod, $param)));
}
/**
+60 -21
View File
@@ -1,3 +1,46 @@
/**
* When execution status change.
*
* @param stirng executionStatus
* @access public
* @return void
*/
function changeStatus(executionStatus)
{
if(executionStatus == 'wait')
{
$('.startButton').removeClass('hidden');
$('.putoffButton').removeClass('hidden');
$('.suspendButton').removeClass('hidden');
$('.closeButton').removeClass('hidden');
$('.activateButton').addClass('hidden');
}
else if(executionStatus == 'doing')
{
$('.startButton').addClass('hidden');
$('.putoffButton').removeClass('hidden');
$('.suspendButton').removeClass('hidden');
$('.closeButton').removeClass('hidden');
$('.activateButton').addClass('hidden');
}
else if(executionStatus == 'suspended')
{
$('.startButton').addClass('hidden');
$('.putoffButton').addClass('hidden');
$('.suspendButton').addClass('hidden');
$('.closeButton').removeClass('hidden');
$('.activateButton').removeClass('hidden');
}
else if(executionStatus == 'closed')
{
$('.startButton').addClass('hidden');
$('.putoffButton').addClass('hidden');
$('.suspendButton').addClass('hidden');
$('.closeButton').addClass('hidden');
$('.activateButton').removeClass('hidden');
}
}
/**
* Display the kanban in full screen.
*
@@ -788,7 +831,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
{
if(fromColType == 'developing' && priv.canPauseTask)
{
var link = createLink('task', 'pause', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('task', 'pause', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -796,12 +839,12 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
{
if((fromColType == 'pause' || fromColType == 'canceled' || fromColType == 'closed' || fromColType == 'developed') && priv.canActivateTask)
{
var link = createLink('task', 'activate', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('task', 'activate', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
if(fromColType == 'wait' && priv.canStartTask)
{
var link = createLink('task', 'start', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('task', 'start', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -809,7 +852,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
{
if((fromColType == 'developing' || fromColType == 'wait' || fromColType == 'pause') && priv.canCancelTask)
{
var link = createLink('task', 'cancel', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('task', 'cancel', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -817,7 +860,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
{
if((fromColType == 'developed' || fromColType == 'canceled') && priv.canCloseTask)
{
var link = createLink('task', 'close', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('task', 'close', 'taskID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -832,7 +875,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
{
if(fromColType == 'unconfirmed' && priv.canConfirmBug)
{
var link = createLink('bug', 'confirmBug', 'bugID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('bug', 'confirmBug', 'bugID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -841,7 +884,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
if(fromColType == 'confirmed' || fromColType == 'unconfirmed') moveCard = true;
if((fromColType == 'closed' || fromColType == 'fixed' || fromColType == 'testing' || fromColType == 'tested') && priv.canActivateBug)
{
var link = createLink('bug', 'activate', 'bugID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('bug', 'activate', 'bugID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -849,7 +892,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
{
if(fromColType == 'fixing' || fromColType == 'confirmed' || fromColType == 'unconfirmed')
{
var link = createLink('bug', 'resolve', 'bugID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('bug', 'resolve', 'bugID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -865,7 +908,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
{
if(fromColType == 'testing' || fromColType == 'tested')
{
var link = createLink('bug', 'close', 'bugID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID, '', true);
var link = createLink('bug', 'close', 'bugID=' + objectID + '&extra=fromColID=' + fromColID + ',toColID=' + toColID + ',fromLaneID=' + fromLaneID + ',toLaneID=' + toLaneID + ',regionID=' + regionID, '', true);
showIframe = true;
}
}
@@ -884,6 +927,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
method: 'post',
dataType: 'json',
url: link,
async: false,
success: function(data)
{
updateRegion(regionID, data[regionID]);
@@ -911,7 +955,7 @@ function changeCardColType(cardID, fromColID, toColID, fromLaneID, toLaneID, car
* @access public
* @return void
*/
function updateKanban(kanbanData, regionID)
function updateKanban(kanbanData, regionID = 0)
{
setTimeout(function()
{
@@ -950,6 +994,7 @@ function shiftCard(objectID, fromColID, toColID, fromLaneID, toLaneID, regionID)
method: 'post',
dataType: 'json',
url: link,
async: false,
success: function(data)
{
updateRegion(regionID, data[regionID]);
@@ -1046,6 +1091,10 @@ function initKanban($kanban)
*/
$(function()
{
changeStatus(execution.status);
if($.cookie('isFullScreen') == 1) $.cookie('isFullScreen', 0);
window.kanbanScaleSize = +$.zui.store.get('executionKanbanScaleSize', 1);
$('#kanbanScaleSize').text(window.kanbanScaleSize);
$('#kanbanScaleControl .btn[data-type="+"]').attr('disabled', window.kanbanScaleSize >= 4 ? 'disabled' : null);
@@ -1182,13 +1231,6 @@ $(function()
return $ele.parent().children('.kanban-lane');
}
/* Sort lanes */
if($ele.hasClass('kanban-item'))
{
sortType = 'item';
return $ele.parent().children('.kanban-item');
}
},
start: function(e)
{
@@ -1237,10 +1279,7 @@ $(function()
var region = e.element.parent().parent().data('id');
url = createLink('kanban', 'sortLane', 'region=' + region + '&lanes=' + orders.join(','));
}
if(sortType == 'item')
{
url = createLink('task', 'sort', 'kanbanID=' + kanbanID + '&tasks=' + orders.join(','));
}
if(!url) return true;
$.getJSON(url, function(response)
+5 -5
View File
@@ -126,11 +126,11 @@ js::set('hasTaskButton', $hasTaskButton);
if(common::hasPriv('kanban', 'setLaneHeight')) $actions .= '<li>' . html::a(helper::createLink('kanban', 'setLaneHeight', "kanbanID=$execution->id&from=execution", '', true), '<i class="icon icon-size-height"></i>' . $lang->kanban->laneHeight, '', "class='iframe btn btn-link text-left' data-width=$width") . '</li>';
$kanbanActions = '';
if(common::hasPriv('execution', 'edit')) $kanbanActions .= '<li>' . html::a(helper::createLink('execution', 'edit', "executionID=$execution->id", '', true), '<i class="icon icon-edit"></i>' . $lang->kanban->edit, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(in_array('start', $executionActions)) $kanbanActions .= '<li>' . html::a(helper::createLink('execution', 'start', "executionID=$execution->id", '', true), '<i class="icon icon-play"></i>' . $lang->execution->start, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(in_array('putoff', $executionActions)) $kanbanActions .= '<li>' . html::a(helper::createLink('execution', 'putoff', "executionID=$execution->id", '', true), '<i class="icon icon-calendar"></i>' . $lang->execution->putoff, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(in_array('suspend', $executionActions)) $kanbanActions .= '<li>' . html::a(helper::createLink('execution', 'suspend', "executionID=$execution->id", '', true), '<i class="icon icon-pause"></i>' . $lang->execution->suspend, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(in_array('close', $executionActions)) $kanbanActions .= '<li>' . html::a(helper::createLink('execution', 'close', "executionID=$execution->id", '', true), '<i class="icon icon-off"></i>' . $lang->execution->close, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(in_array('activate', $executionActions)) $kanbanActions .= '<li>' . html::a(helper::createLink('execution', 'activate', "executionID=$execution->id", '', true), '<i class="icon icon-magic"></i>' . $lang->execution->activate, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(common::hasPriv('execution', 'start')) $kanbanActions .= '<li class="startButton hidden">' . html::a(helper::createLink('execution', 'start', "executionID=$execution->id&from=kanban", '', true), '<i class="icon icon-play"></i>' . $lang->execution->start, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(common::hasPriv('execution', 'putoff')) $kanbanActions .= '<li class="putoffButton hidden">' . html::a(helper::createLink('execution', 'putoff', "executionID=$execution->id&from=kanban", '', true), '<i class="icon icon-calendar"></i>' . $lang->execution->putoff, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(common::hasPriv('execution', 'suspend')) $kanbanActions .= '<li class="suspendButton hidden">' . html::a(helper::createLink('execution', 'suspend', "executionID=$execution->id&from=kanban", '', true), '<i class="icon icon-pause"></i>' . $lang->execution->suspend, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(common::hasPriv('execution', 'close')) $kanbanActions .= '<li class="closeButton hidden">' . html::a(helper::createLink('execution', 'close', "executionID=$execution->id&from=kanban", '', true), '<i class="icon icon-off"></i>' . $lang->execution->close, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(common::hasPriv('execution', 'activate')) $kanbanActions .= '<li class="activateButton hidden">' . html::a(helper::createLink('execution', 'activate', "executionID=$execution->id&from=kanban", '', true), '<i class="icon icon-magic"></i>' . $lang->execution->activate, '', "class='iframe btn btn-link text-left' data-width='75%'") . '</li>';
if(common::hasPriv('execution', 'delete')) $kanbanActions .= '<li>' . html::a(helper::createLink('execution', 'delete', "executionID=$execution->id"), '<i class="icon icon-trash"></i>' . $lang->delete, 'hiddenwin', "class='btn btn-link text-left'") . '</li>';
if($kanbanActions)
{
+15 -7
View File
@@ -644,6 +644,7 @@ $lang->resource->kanban->close = 'close';
$lang->resource->kanban->delete = 'delete';
$lang->resource->kanban->createRegion = 'createRegion';
$lang->resource->kanban->editRegion = 'editRegion';
$lang->resource->kanban->performable = 'performable';
$lang->resource->kanban->sortRegion = 'sortRegion';
$lang->resource->kanban->sortGroup = 'sortGroup';
$lang->resource->kanban->deleteRegion = 'deleteRegion';
@@ -668,13 +669,17 @@ $lang->resource->kanban->assigntoCard = 'assigntoCard';
//$lang->resource->kanban->copyCard = 'copyCard';
$lang->resource->kanban->deleteCard = 'deleteCard';
$lang->resource->kanban->moveCard = 'moveCard';
$lang->resource->kanban->finishCard = 'finishCard';
$lang->resource->kanban->activateCard = 'activateCard';
$lang->resource->kanban->setCardColor = 'setCardColor';
$lang->resource->kanban->laneMove = 'laneMove';
$lang->resource->kanban->viewArchivedColumn = 'viewArchivedColumn';
$lang->resource->kanban->viewArchivedCard = 'viewArchivedCard';
$lang->resource->kanban->restoreCard = 'restoreCard';
$lang->resource->kanban->setLaneHeight = 'setLaneHeight';
$lang->resource->kanban->importCard = 'importCard';
$lang->resource->kanban->batchCreateCard = 'batchCreateCard';
$lang->resource->kanban->import = 'import';
$lang->resource->kanban->enableArchived = 'enableArchived';
$lang->kanban->methodOrder[5] = 'space';
$lang->kanban->methodOrder[10] = 'createSpace';
@@ -714,12 +719,15 @@ $lang->kanban->methodOrder[170] = 'assigntoCard';
$lang->kanban->methodOrder[175] = 'moveCard';
$lang->kanban->methodOrder[180] = 'setCardColor';
$lang->kanban->methodOrder[185] = 'laneMove';
$lang->kanban->methodOrder[190] = 'viewArchivedColumn';
$lang->kanban->methodorder[195] = 'viewArchivedCard';
$lang->kanban->methodorder[200] = 'archiveColumn';
$lang->kanban->methodorder[205] = 'restoreCard';
$lang->kanban->methodorder[210] = 'setLaneHeight';
$lang->kanban->methodorder[215] = 'importCard';
$lang->kanban->methodorder[190] = 'cardsSort';
$lang->kanban->methodOrder[195] = 'viewArchivedColumn';
$lang->kanban->methodorder[200] = 'viewArchivedCard';
$lang->kanban->methodorder[205] = 'archiveColumn';
$lang->kanban->methodorder[210] = 'restoreCard';
$lang->kanban->methodorder[215] = 'setLaneHeight';
$lang->kanban->methodOrder[220] = 'batchCreateCard';
$lang->kanban->methodorder[225] = 'import';
$lang->kanban->methodorder[230] = 'enableArchived';
/* Execution. */
$lang->resource->execution = new stdclass();
+59
View File
@@ -159,6 +159,65 @@ $lang->install->account = 'Admin Account';
$lang->install->password = 'Admin Password';
$lang->install->errorEmptyPassword = 'Password should not be blank.';
$lang->install->processList['11'] = 'Project management';
$lang->install->processList['12'] = 'Project planning';
$lang->install->processList['13'] = 'Project monitoring';
$lang->install->processList['14'] = 'Risk management';
$lang->install->processList['15'] = 'Closing management';
$lang->install->processList['16'] = 'Quantitative Project management';
$lang->install->processList['17'] = 'Requirements development';
$lang->install->processList['18'] = 'Design and development';
$lang->install->processList['19'] = 'Implementation and testing';
$lang->install->processList['20'] = 'System test';
$lang->install->processList['21'] = 'Customer acceptance';
$lang->install->processList['22'] = 'Quality assurance';
$lang->install->processList['23'] = 'Configuration management';
$lang->install->processList['24'] = 'Metric analysis';
$lang->install->processList['25'] = 'Cause analysis and resolution';
$lang->install->processList['26'] = 'Decision analysis';
$lang->install->basicmeasList['2'] = array('name' => 'Initial size of project user requirements', 'unit' => 'Story points or function points', 'definition' => 'Sum of the size of the baseline version of the first CUSTOMER requirements specification for each product of the project');
$lang->install->basicmeasList['3'] = array('name' => 'Initial scale of project software requirements', 'unit' => 'Story points or function points', 'definition' => 'Sum of the size of the first software requirements specification baseline release for each product of the project');
$lang->install->basicmeasList['4'] = array('name' => 'Real-time scale of project user requirements', 'unit' => 'Story points or function points', 'definition' => 'The actual size of the project user requirements');
$lang->install->basicmeasList['5'] = array('name' => 'Real-time scale of project software requirements', 'unit' => 'Story points or function points', 'definition' => 'The actual scale of the project software requirements');
$lang->install->basicmeasList['6'] = array('name' => 'Estimated project size', 'unit' => 'Story points or function points', 'definition' => 'The estimated size of the project when it was originally estimated');
$lang->install->basicmeasList['8'] = array('name' => 'Project requirements phase planning days', 'unit' => 'Day', 'definition' => 'The sum of planned days for all requirements phases under the project');
$lang->install->basicmeasList['9'] = array('name' => 'Number of days planned during project design phase', 'unit' => 'Day', 'definition' => 'The sum of planned days for all design phases under the project');
$lang->install->basicmeasList['10'] = array('name' => 'Planned number of days during project development phase', 'unit' => 'Day', 'definition' => 'The sum of planned days for all development phases under the project');
$lang->install->basicmeasList['11'] = array('name' => 'Number of days planned for project test phase', 'unit' => 'Day', 'definition' => 'The sum of planned days for all test phases under the project');
$lang->install->basicmeasList['12'] = array('name' => 'Actual days of project requirements phase', 'unit' => 'Day', 'definition' => 'The sum of the actual days of all requirements phases under the project');
$lang->install->basicmeasList['13'] = array('name' => 'Actual days of project design phase', 'unit' => 'Day', 'definition' => 'The sum of the actual days of all design phases under the project');
$lang->install->basicmeasList['14'] = array('name' => 'Actual number of days during the project development phase', 'unit' => 'Day', 'definition' => 'The sum of the actual days of all r&d phases under the project');
$lang->install->basicmeasList['15'] = array('name' => 'Actual number of days during the project test phase', 'unit' => 'Day', 'definition' => 'The sum of the actual days of all test phases under the project');
$lang->install->basicmeasList['26'] = array('name' => 'Plan days by product demand phase', 'unit' => 'Day', 'definition' => 'The sum of planned days for all requirements phases under the product');
$lang->install->basicmeasList['27'] = array('name' => 'Plan days by product design stage', 'unit' => 'Day', 'definition' => 'The sum of planned days for all design phases under the product');
$lang->install->basicmeasList['28'] = array('name' => 'Planned days by product development phase', 'unit' => 'Day', 'definition' => 'The sum of planned days for all development phases under the product');
$lang->install->basicmeasList['29'] = array('name' => 'Plan days by product test phase', 'unit' => 'Day', 'definition' => 'The sum of planned days for all test phases under the product');
$lang->install->basicmeasList['30'] = array('name' => 'Actual days of product demand stage', 'unit' => 'Day', 'definition' => 'The sum of the actual days of all requirement phases under the product');
$lang->install->basicmeasList['31'] = array('name' => 'Actual days of product design stage', 'unit' => 'Day', 'definition' => 'The sum of the actual days of all design phases under the product');
$lang->install->basicmeasList['32'] = array('name' => 'By actual days of product development stage', 'unit' => 'Day', 'definition' => 'The sum of the actual days of all development phases under the product');
$lang->install->basicmeasList['33'] = array('name' => 'By actual days of product test phase', 'unit' => 'Day', 'definition' => 'The sum of the actual days of all testing phases under the product');
$lang->install->basicmeasList['34'] = array('name' => 'Real-time estimated working hours of project tasks', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours for all tasks under the project');
$lang->install->basicmeasList['35'] = array('name' => 'Total estimated real-time working hours of project requirements', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours for all requirements related tasks of the project');
$lang->install->basicmeasList['36'] = array('name' => 'Total estimated time of project design work in real time', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours for all design-related tasks of the project');
$lang->install->basicmeasList['37'] = array('name' => 'Total estimated time of project development in real time', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours for all development related tasks of the project');
$lang->install->basicmeasList['38'] = array('name' => 'Total estimated time of project test work in real time', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours for all test related tasks of the project');
$lang->install->basicmeasList['39'] = array('name' => 'Actual man-hours consumed by project tasks', 'unit' => 'Hour','definition' => 'The sum of the actual man-hours consumed for all tasks under the project');
$lang->install->basicmeasList['40'] = array('name' => 'The actual number of man-hours consumed by project demand work', 'unit' => 'Hour','definition' => 'The sum of the actual man-hours consumed by all demand-related tasks of the project');
$lang->install->basicmeasList['41'] = array('name' => 'The actual number of man-hours consumed by project design work', 'unit' => 'Hour','definition' => 'The sum of the actual man-hours consumed by all design-related tasks of the project');
$lang->install->basicmeasList['42'] = array('name' => 'The actual number of man-hours consumed by project development work', 'unit' => 'Hour','definition' => 'The sum of the actual man-hours consumed by all development related tasks of the project');
$lang->install->basicmeasList['43'] = array('name' => 'The actual number of man-hours consumed by the project testing work', 'unit' => 'Hour','definition' => 'The sum of the actual man-hours consumed by all test related tasks of the project');
$lang->install->basicmeasList['44'] = array('name' => 'Total estimated initial hours of project development work', 'unit' => 'Hour','definition' => 'The sum of the initial estimated work hours of all development related work in the first baseline release of the project plan');
$lang->install->basicmeasList['45'] = array('name' => 'Total estimated initial hours of project design work', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours of all design-related work in the first baseline version of the project plan');
$lang->install->basicmeasList['46'] = array('name' => 'Total estimated initial work hours for project testing', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours of all test-related work in the first baseline release of the project plan');
$lang->install->basicmeasList['47'] = array('name' => 'Total estimated initial hours of work required for the project', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours of all requirements related work in the first baseline version of the project plan');
$lang->install->basicmeasList['48'] = array('name' => 'Total estimated initial work hours for project tasks', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours for all tasks in the first baseline version of the project plan');
$lang->install->basicmeasList['49'] = array('name' => 'The final estimated number of project development hours', 'unit' => 'Hour','definition' => 'The sum of the initial estimated work hours of all development-related tasks in the last baseline release of the project plan');
$lang->install->basicmeasList['50'] = array('name' => 'Total estimated final work hours of project requirements', 'unit' => 'Hour','definition' => 'The sum of the initial estimated work hours of all requirements related tasks in the last baseline release of the project plan');
$lang->install->basicmeasList['51'] = array('name' => 'The final estimated number of project testing hours', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours of all test related tasks in the last baseline release of the project plan');
$lang->install->basicmeasList['52'] = array('name' => 'The final estimated total working hours of project design work', 'unit' => 'Hour','definition' => 'The sum of the initial estimated man-hours of all design-related tasks in the last baseline release of the project plan');
$lang->install->basicmeasList['53'] = array('name' => 'Total estimated final work hours of project tasks', 'unit' => 'Hour', 'definition' => 'The sum of the initial estimated man-hours for all tasks in the last baseline release of the project plan');
$lang->install->selectedMode = 'Selection mode';
$lang->install->selectedModeTips = 'You can go to the Admin - Custom - Mode to set it later.';
+59
View File
@@ -159,6 +159,65 @@ $lang->install->account = '管理员帐号';
$lang->install->password = '管理员密码';
$lang->install->errorEmptyPassword = '密码不能为空';
$lang->install->processList['11'] = '立项管理';
$lang->install->processList['12'] = '项目规划';
$lang->install->processList['13'] = '项目监控';
$lang->install->processList['14'] = '风险管理';
$lang->install->processList['15'] = '结项管理';
$lang->install->processList['16'] = '量化项目管理';
$lang->install->processList['17'] = '需求开发';
$lang->install->processList['18'] = '设计开发';
$lang->install->processList['19'] = '实现与测试';
$lang->install->processList['20'] = '系统测试';
$lang->install->processList['21'] = '客户验收';
$lang->install->processList['22'] = '质量保证';
$lang->install->processList['23'] = '配置管理';
$lang->install->processList['24'] = '度量分析';
$lang->install->processList['25'] = '原因分析与解决';
$lang->install->processList['26'] = '决策分析';
$lang->install->basicmeasList['2'] = array('name' => '项目用户需求初始规模', 'unit' => '故事点或功能点', 'definition' => '项目每个产品的第一个用户需求规格说明书基线版本的规模之和');
$lang->install->basicmeasList['3'] = array('name' => '项目软件需求初始规模', 'unit' => '故事点或功能点', 'definition' => '项目每个产品的第一个软件需求规格说明书基线版本的规模之和');
$lang->install->basicmeasList['4'] = array('name' => '项目用户需求实时规模', 'unit' => '故事点或功能点', 'definition' => '项目用户需求实际的规模');
$lang->install->basicmeasList['5'] = array('name' => '项目软件需求实时规模', 'unit' => '故事点或功能点', 'definition' => '项目软件需求实际的规模');
$lang->install->basicmeasList['6'] = array('name' => '项目估算规模', 'unit' => '故事点或功能点', 'definition' => '项目最初估算时估计的规模');
$lang->install->basicmeasList['8'] = array('name' => '项目需求阶段计划天数', 'unit' => '天', 'definition' => '项目下面所有需求阶段计划天数的和');
$lang->install->basicmeasList['9'] = array('name' => '项目设计阶段计划天数', 'unit' => '天', 'definition' => '项目下面所有设计阶段计划天数的和');
$lang->install->basicmeasList['10'] = array('name' => '项目开发阶段计划天数', 'unit' => '天', 'definition' => '项目下面所有研发阶段计划天数的和');
$lang->install->basicmeasList['11'] = array('name' => '项目测试阶段计划天数', 'unit' => '天', 'definition' => '项目下面所有测试阶段计划天数的和');
$lang->install->basicmeasList['12'] = array('name' => '项目需求阶段实际天数', 'unit' => '天', 'definition' => '项目下面所有需求阶段实际天数的和');
$lang->install->basicmeasList['13'] = array('name' => '项目设计阶段实际天数', 'unit' => '天', 'definition' => '项目下面所有设计阶段实际天数的和');
$lang->install->basicmeasList['14'] = array('name' => '项目开发阶段实际天数', 'unit' => '天', 'definition' => '项目下面所有研发阶段实际天数的和');
$lang->install->basicmeasList['15'] = array('name' => '项目测试阶段实际天数', 'unit' => '天', 'definition' => '项目下面所有测试阶段实际天数的和');
$lang->install->basicmeasList['26'] = array('name' => '分产品需求阶段计划天数', 'unit' => '天', 'definition' => '产品下面所有需求阶段计划天数的和');
$lang->install->basicmeasList['27'] = array('name' => '分产品设计阶段计划天数', 'unit' => '天', 'definition' => '产品下面所有设计阶段计划天数的和');
$lang->install->basicmeasList['28'] = array('name' => '分产品开发阶段计划天数', 'unit' => '天', 'definition' => '产品下面所有研发阶段计划天数的和');
$lang->install->basicmeasList['29'] = array('name' => '分产品测试阶段计划天数', 'unit' => '天', 'definition' => '产品下面所有测试阶段计划天数的和');
$lang->install->basicmeasList['30'] = array('name' => '分产品需求阶段实际天数', 'unit' => '天', 'definition' => '产品下面所有需求阶段实际天数的和');
$lang->install->basicmeasList['31'] = array('name' => '分产品设计阶段实际天数', 'unit' => '天', 'definition' => '产品下面所有设计阶段实际天数的和');
$lang->install->basicmeasList['32'] = array('name' => '分产品开发阶段实际天数', 'unit' => '天', 'definition' => '产品下面所有研发阶段实际天数的和');
$lang->install->basicmeasList['33'] = array('name' => '分产品测试阶段实际天数', 'unit' => '天', 'definition' => '产品下面所有测试阶段实际天数的和');
$lang->install->basicmeasList['34'] = array('name' => '项目任务实时预计工时数', 'unit' => '小时', 'definition' => '项目下面所有任务的最初预计工时和');
$lang->install->basicmeasList['35'] = array('name' => '项目需求工作实时总预计工时数', 'unit' => '小时', 'definition' => '项目所有需求相关任务的最初预计工时和');
$lang->install->basicmeasList['36'] = array('name' => '项目设计工作实时总预计工时数', 'unit' => '小时', 'definition' => '项目所有设计相关任务的最初预计工时和');
$lang->install->basicmeasList['37'] = array('name' => '项目开发工作实时总预计工时数', 'unit' => '小时', 'definition' => '项目所有开发相关任务的最初预计工时和');
$lang->install->basicmeasList['38'] = array('name' => '项目测试工作实时总预计工时数', 'unit' => '小时', 'definition' => '项目所有测试相关任务的最初预计工时和');
$lang->install->basicmeasList['39'] = array('name' => '项目任务实际消耗工时数', 'unit' => '小时', 'definition' => '项目下面所有任务的实际消耗工时和');
$lang->install->basicmeasList['40'] = array('name' => '项目需求工作实际消耗工时数', 'unit' => '小时', 'definition' => '项目所有需求相关任务的实际消耗工时和');
$lang->install->basicmeasList['41'] = array('name' => '项目设计工作实际消耗工时数', 'unit' => '小时', 'definition' => '项目所有设计相关任务的实际消耗工时和');
$lang->install->basicmeasList['42'] = array('name' => '项目开发工作实际消耗工时数', 'unit' => '小时', 'definition' => '项目所有开发相关任务的实际消耗工时和');
$lang->install->basicmeasList['43'] = array('name' => '项目测试工作实际消耗工时数', 'unit' => '小时', 'definition' => '项目所有测试相关任务的实际消耗工时和');
$lang->install->basicmeasList['44'] = array('name' => '项目开发工作最初总预计工时数', 'unit' => '小时', 'definition' => '项目计划第一个基线版本中所有开发相关工作最初预计工时和');
$lang->install->basicmeasList['45'] = array('name' => '项目设计工作最初总预计工时数', 'unit' => '小时', 'definition' => '项目计划第一个基线版本中所有设计相关工作最初预计工时和');
$lang->install->basicmeasList['46'] = array('name' => '项目测试工作最初总预计工时数', 'unit' => '小时', 'definition' => '项目计划第一个基线版本中所有测试相关工作最初预计工时和');
$lang->install->basicmeasList['47'] = array('name' => '项目需求工作最初总预计工时数', 'unit' => '小时', 'definition' => '项目计划第一个基线版本中所有需求相关工作最初预计工时和');
$lang->install->basicmeasList['48'] = array('name' => '项目任务最初总预计工时数', 'unit' => '小时', 'definition' => '项目计划第一个基线版本中所有任务最初预计工时和');
$lang->install->basicmeasList['49'] = array('name' => '项目开发工作最终总预计工时数', 'unit' => '小时', 'definition' => '项目计划最后一个基线版本中所有开发相关任务最初预计工时和');
$lang->install->basicmeasList['50'] = array('name' => '项目需求工作最终总预计工时数', 'unit' => '小时', 'definition' => '项目计划最后一个基线版本中所有需求相关任务最初预计工时和');
$lang->install->basicmeasList['51'] = array('name' => '项目测试工作最终总预计工时数', 'unit' => '小时', 'definition' => '项目计划最后一个基线版本中所有测试相关任务最初预计工时和');
$lang->install->basicmeasList['52'] = array('name' => '项目设计工作最终总预计工时数', 'unit' => '小时', 'definition' => '项目计划最后一个基线版本中所有设计相关任务最初预计工时和');
$lang->install->basicmeasList['53'] = array('name' => '项目任务最终总预计工时数', 'unit' => '小时', 'definition' => '项目计划最后一个基线版本中所有任务最初预计工时和');
$lang->install->selectedMode = '选择模式';
$lang->install->selectedModeTips = '后续您还可以去后台-自定义-模式中进行调整';
+24
View File
@@ -542,6 +542,30 @@ class installModel extends model
{
$this->dao->update(TABLE_CRON)->set('remark')->eq($remark)->where('command')->eq($command)->exec();
}
if(!empty($this->config->maxVersion))
{
/* Update process by lang. */
foreach($this->lang->install->processList as $id => $name)
{
$this->dao->update(TABLE_PROCESS)->set('name')->eq($name)->where('id')->eq($id)->exec();
}
/* Update basicmeas by lang. */
foreach($this->lang->install->basicmeasList as $id => $basic)
{
$this->dao->update(TABLE_BASICMEAS)->set('name')->eq($basic['name'])->set('unit')->eq($basic['unit'])->set('definition')->eq($basic['definition'])->where('id')->eq($id)->exec();
}
/* Update lang,stage by lang. */
$this->app->loadLang('stage');
foreach($this->lang->stage->typeList as $key => $value)
{
$this->dao->update(TABLE_LANG)->set('value')->eq($value)->where('`key`')->eq($key)->exec();
$this->dao->update(TABLE_STAGE)->set('name')->eq($value)->where('`type`')->eq($key)->exec();
}
}
}
/**
+2
View File
@@ -108,3 +108,5 @@ $config->kanban->taskColumnStatusList['closed'] = 'closed';
$config->kanban->laneColorList = array('#7ec5ff', '#333', '#2b529c', '#e48600', '#d2323d', '#229f24', '#777', '#d2691e', '#008b8b', '#2e8b57', '#4169e1', '#4b0082', '#fa8072', '#ba55d3', '#6b8e23');
$config->kanban->columnColorList = array('#333', '#2b519c', '#e48610', '#d2313d', '#2a9f23', '#777', '#d2691e', '#2e8b8b', '#2f8b58', '#4168e0', '#4b0082', '#f58072', '#ba55d3', '#6a8e22');
$config->kanban->cardColorList = array('#fff', '#b10b0b', '#cfa227', '#2a5f29');
$config->kanban->batchCreate = 10;
+165 -10
View File
@@ -167,7 +167,11 @@ class kanban extends control
unset($this->lang->kanbanspace->featureBar['involved']);
$this->view->users = $this->loadModel('user')->getPairs('noclosed|nodeleted');
$space = $this->kanban->getSpaceById($spaceID);
$spaceUsers = $spaceID == 0 ? ',' : trim($space->owner) . ',' . trim($space->team) . ',' . trim($space->whitelist);
$users = $this->loadModel('user')->getPairs('noclosed|nodeleted', '', 0, $spaceUsers);
$this->view->users = $users;
$this->view->spaceID = $spaceID;
$this->view->spacePairs = array(0 => '') + $this->kanban->getSpacePairs($type);
$this->view->type = $type;
@@ -198,10 +202,12 @@ class kanban extends control
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$kanban = $this->kanban->getByID($kanbanID);
$space = $this->kanban->getSpaceById($kanban->space);
$kanban = $this->kanban->getByID($kanbanID);
$space = $this->kanban->getSpaceById($kanban->space);
$spaceUsers = trim($space->owner) . ',' . trim($space->team) . ',' . trim($space->whitelist);
$users = $this->loadModel('user')->getPairs('noclosed|nodeleted', '', 0, $spaceUsers);
$this->view->users = $this->loadModel('user')->getPairs('noclosed');
$this->view->users = $users;
$this->view->spacePairs = array(0 => '') + $this->kanban->getSpacePairs($space->type);
$this->view->kanban = $kanban;
$this->view->type = $space->type;
@@ -460,7 +466,7 @@ class kanban extends control
* @param int $regionID
* @param string $lanes
* @access public
* @return void
* @return array
*/
public function sortLane($regionID, $lanes = '')
{
@@ -477,6 +483,29 @@ class kanban extends control
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess));
}
/**
* Sort columns.
*
* @param int $regionID
* @param int $kanbanID
* @param string $columns
* @access public
* @return array|string
*/
public function sortColumn($regionID, $kanbanID, $columns = '')
{
if(empty($columns)) return;
$columns = explode(',', trim($columns, ','));
$order = 1;
foreach($columns as $columnID) $this->dao->update(TABLE_KANBANCOLUMN)->set('`order`')->eq($order++)->where('id')->eq($columnID)->andWhere('region')->eq($regionID)->exec();
$kanbanGroup = $this->kanban->getKanbanData($kanbanID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return print(json_encode($kanbanGroup));
}
/**
* Set lane height.
*
@@ -591,6 +620,9 @@ class kanban extends control
}
else
{
$column = $this->kanban->getColumnById($columnID);
if($column->parent) $this->kanban->processCards($column);
$this->kanban->archiveColumn($columnID);
if(dao::isError()) die(js::error(dao::getError()));
@@ -671,7 +703,11 @@ class kanban extends control
}
else
{
$this->kanban->delete(TABLE_KANBANCOLUMN, $columnID);
$column = $this->kanban->getColumnById($columnID);
if($column->parent) $this->kanban->processCards($column);
$this->dao->delete()->from(TABLE_KANBANCOLUMN)->where('id')->eq($columnID)->exec();
die(js::reload('parent'));
}
}
@@ -703,6 +739,39 @@ class kanban extends control
$this->display();
}
/**
* Batch create cards.
*
* @param int $kanbanID
* @param int $regionID
* @param int $groupID
* @param int $laneID
* @param int $columnID
* @access public
* @return void
*/
public function batchCreateCard($kanbanID = 0, $regionID = 0, $groupID = 0, $laneID = 0, $columnID = 0)
{
$backLink = $this->createLink('kanban', 'view', "kanbanID=$kanbanID");
if($_POST)
{
$this->kanban->batchCreateCard($kanbanID, $regionID, $groupID, $columnID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $backLink));
}
$users = $this->loadModel('user')->getPairs('noclosed|nodeleted');
$lanePairs = $this->kanban->getLanePairsByGroup($groupID);
$lanePairs['ditto'] = $this->lang->kanbancard->ditto;
$this->view->users = $users;
$this->view->lanePairs = $lanePairs;
$this->display();
}
/**
* Edit a card.
*
@@ -732,6 +801,44 @@ class kanban extends control
$this->display();
}
/**
* Finish a card.
*
* @param int $cardID
* @param int $kanbanID
* @access public
* @return void
*/
public function finishCard($cardID, $kanbanID)
{
$this->dao->update(TABLE_KANBANCARD)->set('status')->eq('done')->where('id')->eq($cardID)->exec();
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
if(isonlybody()) return print(js::reload('parent.parent'));
$kanbanGroup = $this->kanban->getKanbanData($kanbanID);
return print(json_encode($kanbanGroup));
}
/**
* Activate a card.
*
* @param int $cardID
* @param int $kanbanID
* @access public
* @return void
*/
public function activateCard($cardID, $kanbanID)
{
$this->dao->update(TABLE_KANBANCARD)->set('status')->eq('doing')->where('id')->eq($cardID)->exec();
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
if(isonlybody()) return print(js::reload('parent.parent'));
$kanbanGroup = $this->kanban->getKanbanData($kanbanID);
return print(json_encode($kanbanGroup));
}
/**
* View a card.
*
@@ -1195,7 +1302,7 @@ class kanban extends control
{
if(dao::isError()) return $this->sendError(dao::getError());
$regionID = $column->region;
$kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, 'all', 'id_desc', $regionID);
$kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.updateKanban($kanbanData, $regionID)"));
@@ -1276,7 +1383,7 @@ class kanban extends control
{
if(dao::isError()) return $this->sendError(dao::getError());
$regionID = $column->region;
$kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, 'all', 'id_desc', $regionID);
$kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.updateKanban($kanbanData, $regionID)"));
@@ -1291,13 +1398,13 @@ class kanban extends control
}
/**
* Set done function.
* Setup done function.
*
* @param int $kanbanID
* @access public
* @return void
*/
public function setDoneFunction($kanbanID)
public function performable($kanbanID)
{
if(!empty($_POST))
{
@@ -1311,6 +1418,28 @@ class kanban extends control
$this->display();
}
/**
* Set archived.
*
* @param int $kanbanID
* @access public
* @return void
*/
public function enableArchived($kanbanID)
{
if(!empty($_POST))
{
$this->dao->update(TABLE_KANBAN)->set('archived')->eq($_POST['archived'])->exec();
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$this->view->kanban = $this->kanban->getByID($kanbanID);
$this->display();
}
/**
* AJAX: Update the cards sorting of the lane column.
@@ -1491,4 +1620,30 @@ class kanban extends control
if(empty($lanes)) return;
return print(html::select('otherLane', $lanes, '', "class='form-control'"));
}
/**
* Import.
*
* @param int $kanbanID
* @access public
* @return void
*/
public function import($kanbanID)
{
if(!empty($_POST))
{
$this->kanban->import($kanbanID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
$kanban = $this->kanban->getByID($kanbanID);
$this->view->enableImport = empty($kanban->object) ? 'off' : 'on';
$this->view->importObjects = empty($kanban->object) ? array() : explode(',', $kanban->object);
$this->display();
}
}
+1
View File
@@ -0,0 +1 @@
.c-date {width:150px;}
+1
View File
@@ -0,0 +1 @@
#mainContent .c-comment {width: 50px}
+2
View File
@@ -0,0 +1,2 @@
#importForm .checkbox-primary:not(:first-child) {margin-left: 10px;}
#importForm .checkbox-primary {display: inline-block}
+1
View File
@@ -7,6 +7,7 @@
#spaceList .spaceActions > a{margin-left: 10px;}
.space .menu {margin-left: 5px; margin-right:5px;}
.space .table-empty-tip {padding: 40px 10px;}
.space .spaceTitle.pull-left {overflow: hidden; white-space: nowrap; max-width: calc(100% - 255px)}
.kanbans > .col {width: 25% !important;}
@media screen and (max-width: 1500px) {.kanbans > .col {width: 25%;}}
+27
View File
@@ -0,0 +1,27 @@
$(document).on('change', "[name^='begin'], [name^='end']", function()
{
toggleCheck($(this));
})
/**
* Toggle checkbox.
*
* @param object $obj
* @access public
* @return void
*/
function toggleCheck(obj)
{
var $this = $(obj);
var date = $this.val();
var $ditto = $this.closest('div').find("input[type='checkBox']");
if(date == '')
{
$ditto.attr('checked', true);
$ditto.closest('.input-group-addon').show();
}
else
{
$ditto.removeAttr('checked');
$ditto.closest('.input-group-addon').hide();
}
}
+3 -2
View File
@@ -1,13 +1,14 @@
/**
* When type change.
* When space type or space value change.
*
* @oaram int spaceID
* @param string type
* @access public
* @return void
*/
function changeType(spaceID, type)
function changeValue(spaceID, type = '')
{
if(type == '') type = spaceType;
location.href = createLink('kanban', 'create', 'spaceID=' + spaceID + '&type=' + type);
}
+33
View File
@@ -0,0 +1,33 @@
$(function()
{
if(enableImport == 'off') $("input[name^='importObjectList']").attr('disabled', 'disabled');
$("input[name='import']").change(function()
{
if($(this).val() == 'off')
{
$("input[name^='importObjectList']").attr('disabled', 'disabled');
}
else
{
$("input[name^='importObjectList']").removeAttr('disabled');
}
})
$("input[name^='importObjectList']").change(function()
{
if($("input:checked[name^=importObjectList]").length != 0 && !$('#emptyTip').is('.hidden')) $('#emptyTip').addClass('hidden');
})
$('#submit').click(function()
{
var enableImport = $("input:checked[name='import']").val();
var objectListLength = $("input:checked[name^=importObjectList]").length;
if(enableImport == 'on' && objectListLength == 0)
{
$('#emptyTip').removeClass('hidden');
return false;
}
})
})
+172 -22
View File
@@ -111,7 +111,7 @@ function renderHeaderCol($column, column, $header, kanbanData)
{
/* Render group header. */
var privs = kanbanData.actions;
var columnPrivs = kanbanData.columns[0].actions;
var columnPrivs = $column.data().col.actions;
if(privs.includes('sortGroup'))
{
@@ -142,15 +142,25 @@ function renderHeaderCol($column, column, $header, kanbanData)
if(!$column.children('.actions').length) $column.append('<div class="actions"></div>');
var $actions = $column.children('.actions');
if(columnPrivs.includes('createCard') && column.parent != -1)
if(column.parent != -1)
{
var cardUrl = createLink('kanban', 'importcard', 'kanbanID=' + kanbanID + '&regionID=' + regionID + '&groupID=' + groupID + '&columnID=' + columnID);
addItemBtn = ['<a data-contextmenu="columnCreate" data-toggle="modal" data-action="addItem" data-column="' + column.id + '" data-lane="' + laneID + '" href="' + cardUrl + '" class="text-primary iframe">', '<i class="icon icon-expand-alt"></i>', '</a>'].join('');
addItemBtn = ['<a data-contextmenu="columnCreate" data-action="addItem" data-column="' + column.id + '" data-lane="' + laneID + '" class="text-primary">', '<i class="icon icon-expand-alt"></i>', '</a>'].join('');
}
var moreAction = ' <button class="btn btn-link action" title="' + kanbanLang.moreAction + '" data-contextmenu="column" data-column="' + column.id + '"><i class="icon icon-ellipsis-v"></i></button>';
$actions.html(addItemBtn + moreAction);
}
if(columnPrivs.includes('sortColumn'))
{
if($column.hasClass('kanban-header-parent-col'))
{
$column.children('.kanban-header-col').addClass('sort');
}
else
{
$column.addClass('sort');
}
}
}
@@ -276,6 +286,15 @@ function renderKanbanItem(item, $item)
var privs = item.actions;
var printMoreBtn = (privs.includes('editCard') || privs.includes('archiveCard') || privs.includes('copyCard') || privs.includes('deleteCard') || privs.includes('moveCard') || privs.includes('setCardColor'));
if(kanban.performable == 1 && item.status == 'done' )
{
$item.closest('.kanban-card').css({'filter' : 'opacity(0.5)', 'text-decoration' : 'line-through'});
}
else
{
$item.closest('.kanban-card').css({'filter' : '', 'text-decoration' : ''});
}
if(privs.includes('sortCard')) $item.parent().addClass('sort');
if(!$title.length)
{
@@ -496,6 +515,7 @@ function moveCard(cardID, fromColID, toColID, fromLaneID, toLaneID, kanbanID, re
method: 'post',
dataType: 'json',
url: url,
async: false,
success: function(data)
{
regions = data;
@@ -539,7 +559,6 @@ function setCardColor(cardID, color, kanbanID, regionID)
url: url,
success: function(data)
{
regions = data;
updateRegion(regionID, data[regionID]);
},
error: function(xhr, status, error)
@@ -549,6 +568,56 @@ function setCardColor(cardID, color, kanbanID, regionID)
});
}
/**
* Finish a card.
*
* @param int $cardID
* @param int $kanbanID
* @param int $regionID
* @access public
* @return void
*/
function finishCard(cardID, kanbanID, regionID)
{
if(!cardID) return false;
var url = createLink('kanban', 'finishCard', 'cardID=' + cardID + '&kanbanID=' + kanbanID);
return $.ajax(
{
method: 'post',
dataType: 'json',
url: url,
success: function(data)
{
updateRegion(regionID, data[regionID]);
}
});
}
/**
* Activate a card.
*
* @param int $cardID
* @param int $kanbanID
* @param int $regionID
* @access public
* @return void
*/
function activateCard(cardID, kanbanID, regionID)
{
if(!cardID) return false;
var url = createLink('kanban', 'activateCard', 'cardID=' + cardID + '&kanbanID=' + kanbanID);
return $.ajax(
{
method: 'post',
dataType: 'json',
url: url,
success: function(data)
{
updateRegion(regionID, data[regionID]);
}
});
}
/**
* Update a region.
*
@@ -801,6 +870,17 @@ function createCardMenu(options)
var items = [];
if(privs.includes('editCard')) items.push({label: kanbanLang.editCard, icon: 'edit', url: createLink('kanban', 'editCard', 'cardID=' + card.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}});
if(kanban.performable == 1)
{
if(privs.includes('activateCard') && card.status != 'doing')
{
items.push({label: kanbanLang.activateCard, icon: 'magic', onClick: function(){activateCard(card.id, card.kanban, card.region);}});
}
else
{
items.push({label: kanbanLang.finishCard, icon: 'checked', onClick: function(){finishCard(card.id, card.kanban, card.region);}});
}
}
if(privs.includes('archiveCard') && kanban.archived == '1') items.push({label: kanbanLang.archiveCard, icon: 'card-archive', url: createLink('kanban', 'archiveCard', 'cardID=' + card.id), attrs: {'target': 'hiddenwin'}});
if(privs.includes('copyCard')) items.push({label: kanbanLang.copyCard, icon: 'copy', url: createLink('kanban', 'copyCard', 'cardID=' + card.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal'}});
if(privs.includes('deleteCard')) items.push({label: kanbanLang.deleteCard, icon: 'trash', url: createLink('kanban', 'deleteCard', 'cardID=' + card.id), attrs: {'target': 'hiddenwin'}});
@@ -862,14 +942,40 @@ function createColumnMenu(options)
items.push({label: kanbanLang.createColumnOnRight, icon: 'col-add-right', url: createLink('kanban', 'createColumn', 'columnID=' + column.id + '&position=right'), className: 'iframe', attrs: {'data-toggle': 'modal'}});
}
if(privs.includes('copyColumn')) items.push({label: kanbanLang.copyColumn, icon: 'copy', url: createLink('kanban', 'copyColumn', 'columnID=' + column.id), className: 'iframe', attrs: {'data-toggle': 'modal'}});
if(privs.includes('archiveColumn') && kanban.archived == '1' && column.$kanbanData.columns.length > 1) items.push({label: kanbanLang.archiveColumn, icon: 'card-archive', url: createLink('kanban', 'archiveColumn', 'columnID=' + column.id), attrs: {'target': 'hiddenwin'}});
if(privs.includes('deleteColumn') && column.$kanbanData.columns.length > 1) items.push({label: kanbanLang.deleteColumn, icon: 'trash', url: createLink('kanban', 'deleteColumn', 'columnID=' + column.id), attrs: {'target': 'hiddenwin'}});
if(privs.includes('archiveColumn') && kanban.archived == '1') items.push({label: kanbanLang.archiveColumn, icon: 'card-archive', url: createLink('kanban', 'archiveColumn', 'columnID=' + column.id), attrs: {'target': 'hiddenwin'}});
if(privs.includes('deleteColumn')) items.push({label: kanbanLang.deleteColumn, icon: 'trash', url: createLink('kanban', 'deleteColumn', 'columnID=' + column.id), attrs: {'target': 'hiddenwin'}});
var bounds = options.$trigger[0].getBoundingClientRect();
items.$options = {x: bounds.right, y: bounds.top};
return items;
}
/**
* Create create menu for column.
*
* @param object $options
* @access public
* @return object
*/
function createColumnCreateMenu(options)
{
var col = options.$trigger.closest('.kanban-col').data('col');
var privs = col.actions;
var items = [];
var regionID = col.region;
var groupID = col.group;
var laneID = col.$kanbanData.lanes[0].id ? col.$kanbanData.lanes[0].id : 0;
var columnID = col.id;
if(privs.includes('createCard')) items.push({label: kanbanLang.createCard, url: $.createLink('kanban', 'createCard', 'kanbanID=' + kanbanID + '&regionID=' + regionID + '&groupID=' + groupID + '&columnID=' + columnID), className: 'iframe', attrs: {'data-toggle': 'modal'}});
if(privs.includes('batchCreateCard')) items.push({label: kanbanLang.batchCreateCard, url: $.createLink('kanban', 'batchCreateCard', 'kanbanID=' + kanbanID + '&regionID=' + regionID + '&groupID=' + groupID + '&laneID=' + laneID + '&columnID=' + columnID), attrs: {'data-width': '80%'}});
if(privs.includes('import') && kanban.object.indexOf('cards') != -1) items.push({label: kanbanLang.importCard, url: $.createLink('kanban', 'importCard', 'kanbanID=' + kanbanID + '&regionID=' + regionID + '&groupID=' + groupID + '&laneID=' + laneID + '&columnID=' + columnID), attrs: {'data-width': '80%'}});
if(privs.includes('import') && kanban.object) items.push({className: 'parentDivider'});
if(privs.includes('import') && kanban.object) items.push({label: kanbanLang.importAB, className: 'import'});
return items;
}
/** Calculate column height */
function calcColHeight(col, lane, colCards, colHeight, kanban)
{
@@ -889,7 +995,8 @@ window.menuCreators =
{
card: createCardMenu,
lane: createLaneMenu,
column: createColumnMenu
column: createColumnMenu,
columnCreate: createColumnCreateMenu
};
/**
@@ -983,6 +1090,18 @@ $(function()
if(!items || !items.length) return;
$.zui.ContextMenu.show(items, items.$options || {event: event});
$('.parentDivider').parent().addClass('divider');
$('.import').parent().addClass('dropdown-submenu top');
/* The submenu of import. */
var importPlanLink = kanban.object.indexOf('plan') != -1 ? '<li><a href="' + createLink('kanban', 'importPlan') + '">' + kanbanLang.importPlan + '</a></li>' : '';
var importReleaseLink = kanban.object.indexOf('release') != -1 ? '<li><a href="' + createLink('kanban', 'importRelease') + '">' + kanbanLang.importRelease + '</a></li>' : '';
var importExecutionLink = kanban.object.indexOf('execution') != -1 ? '<li><a href="' + createLink('kanban', 'importExecution') + '">' + kanbanLang.importExecution + '</a></li>' : '';
var importBuildLink = kanban.object.indexOf('build') != -1 ? '<li><a href="' + createLink('kanban', 'importBuild') + '">' + kanbanLang.importBuild + '</a></li>' : '';
var importSubmenu = '<ul class="dropdown-menu">' + importPlanLink + importReleaseLink + importExecutionLink + importBuildLink +'</ul>';
$('.import').parent().append(importSubmenu);
});
/* Adjust the add button position on window resize */
@@ -1030,12 +1149,14 @@ $(function()
});
/* Init sortable */
var sortType = '';
var $cards = null;
var sortType = '';
var oldLaneID = '';
var oldColID = '';
var $cards = null;
$('#kanban').sortable(
{
selector: '.region, .kanban-board, .kanban-lane, .kanban-item.sort',
trigger: '.region.sort > .region-header, .kanban-board.sort > .kanban-header > .kanban-group-header, .kanban-lane.sort > .kanban-lane-name, .kanban-item.sort',
selector: '.region, .kanban-board, .kanban-lane, .kanban-item.sort, .kanban-col',
trigger: '.region.sort > .region-header, .kanban-board.sort > .kanban-header > .kanban-group-header, .kanban-lane.sort > .kanban-lane-name, .kanban-item.sort, .kanban-col.sort',
container: function($ele)
{
return $ele.parent();
@@ -1065,6 +1186,13 @@ $(function()
return $ele.parent().children('.kanban-lane');
}
/* Sort columns. */
if($ele.hasClass('kanban-col'))
{
sortType = 'column';
return $ele.parent().children('.kanban-col');
}
/* Sort cards. */
if($ele.hasClass('kanban-item'))
{
@@ -1086,11 +1214,23 @@ $(function()
$('.region').find('.kanban').hide();
hideKanbanAction();
}
if(sortType == 'column')
{
$('.kanban-item').addClass('hidden');
}
if(sortType == 'card')
{
oldLaneID = e.element.closest('.kanban-lane').data('id');
oldColID = e.element.closest('.kanban-col').data('id');
}
},
finish: function(e)
{
var url = '';
var orders = [];
var url = '';
var orders = [];
var regionID = '';
e.list.each(function(index, data)
{
orders.push(data.item.data('id'));
@@ -1111,19 +1251,24 @@ $(function()
}
if(sortType == 'board')
{
var region = e.element.parent().data('id');
url = createLink('kanban', 'sortGroup', 'region=' + region + '&groups=' + orders.join(','));
regionID = e.element.closest('.region').data('id');
url = createLink('kanban', 'sortGroup', 'region=' + regionID + '&groups=' + orders.join(','));
}
if(sortType == 'lane')
{
var region = e.element.parent().parent().data('id');
url = createLink('kanban', 'sortLane', 'region=' + region + '&lanes=' + orders.join(','));
regionID = e.element.closest('.region').data('id');
url = createLink('kanban', 'sortLane', 'region=' + regionID + '&lanes=' + orders.join(','));
}
if(sortType == 'column')
{
regionID = e.element.closest('.region').data('id');
url = createLink('kanban', 'sortColumn', 'region=' + regionID + '&kanbanID=' + kanban.id + '&columns=' + orders.join(','));
}
if(sortType == 'card')
{
var laneID = e.element.closest('.kanban-lane').data('id');
var columnID = e.element.closest('.kanban-col').data('id');
url = createLink('kanban', 'sortCard', 'kanbanID=' + kanbanID + '&laneID=' + laneID + '&columnID=' + columnID + '&cards=' + orders.join(','));
var newLaneID = e.element.closest('.kanban-lane').data('id');
var newColID = e.element.closest('.kanban-col').data('id');
if(newLaneID == oldLaneID && newColID == oldColID) url = createLink('kanban', 'sortCard', 'kanbanID=' + kanbanID + '&laneID=' + newLaneID + '&columnID=' + newColID + '&cards=' + orders.join(','));
}
if(!url) return true;
@@ -1134,6 +1279,11 @@ $(function()
bootbox.alert(response.message);
setTimeout(function(){return location.reload()}, 3000);
}
else if (sortType == 'column')
{
updateRegion(regionID, response[regionID]);
}
$('.kanban-item').removeClass('hidden');
});
},
always: function(e)
+25 -5
View File
@@ -27,6 +27,8 @@ $lang->kanban->sortColumn = 'Sort Column';
$lang->kanban->deleteColumn = 'Delete Column';
$lang->kanban->createCard = 'Create Card';
$lang->kanban->editCard = 'Edit Card';
$lang->kanban->finishCard = 'Finish Card';
$lang->kanban->activateCard = 'Activate Card';
$lang->kanban->viewCard = 'View Card';
$lang->kanban->archiveCard = 'Archive Card';
$lang->kanban->sortCard = 'Sort Card';
@@ -37,7 +39,9 @@ $lang->kanban->setCardColor = 'Set Card Color';
$lang->kanban->deleteCard = 'Delete Card';
$lang->kanban->assigntoCard = 'Assign';
$lang->kanban->setting = 'Setting';
$lang->kanban->setDoneFunction = 'Set done function';
$lang->kanban->enableArchived = 'Enable Archived';
$lang->kanban->archive = 'Archive';
$lang->kanban->performable = 'Set done function';
$lang->kanban->doneFunction = 'Done function';
$lang->kanban->splitColumn = 'Split Column';
$lang->kanban->createColumnOnLeft = 'Create Column On Left';
@@ -57,6 +61,9 @@ $lang->kanban->restoreColumn = 'Restore Column';
$lang->kanban->restoreCard = 'Restore Card';
$lang->kanban->restore = 'Restore';
$lang->kanban->child = 'Child';
$lang->kanban->batchCreateCard = 'Batchcreate Card';
$lang->kanban->import = 'Import';
$lang->kanban->importAB = 'Import';
$lang->kanban->showClosed = 'Closed';
$lang->kanban->importCard = 'Import Card';
$lang->kanban->importPlan = 'Import Plan';
@@ -107,10 +114,10 @@ $lang->kanban->aclGroup['extend'] = 'Extend';
$lang->kanban->aclList['extend'] = 'Extend (Accessible with space view permissions)';
$lang->kanban->aclList['private'] = 'Private (For the kanban team, whitelist members and space owner only)';
$lang->kanban->enableArchived['0'] = 'No Enable';
$lang->kanban->enableArchived['1'] = 'Enable';
$lang->kanban->archiveList['0'] = 'Disable';
$lang->kanban->archiveList['1'] = 'Enable';
$lang->kanban->enableFinished['0'] = 'No Enable';
$lang->kanban->enableFinished['0'] = 'Disable';
$lang->kanban->enableFinished['1'] = 'Enable';
$lang->kanban->type = array();
@@ -177,6 +184,18 @@ $lang->kanban->error = new stdclass();
$lang->kanban->error->mustBeInt = 'The WIPs must be positive integer.';
$lang->kanban->error->parentLimitNote = 'The WIPs in the parent column cannot be < the sum of the WIPs in the child column.';
$lang->kanban->error->childLimitNote = 'The sum of products in the child column cannot be > the number of products in the parent column.';
$lang->kanban->error->importObjNotEmpty = 'Please select at least one import object.';
$lang->kanban->importList = array();
$lang->kanban->importList['off'] = 'Import is not enabled';
$lang->kanban->importList['on'] = 'Enable the import function, you can only import content that you have permission to view.';
$lang->kanban->importObjectList = array();
$lang->kanban->importObjectList['plan'] = 'Product Plan';
$lang->kanban->importObjectList['release'] = 'Release';
$lang->kanban->importObjectList['build'] = 'Build';
$lang->kanban->importObjectList['execution'] = 'Execution';
$lang->kanban->importObjectList['cards'] = 'Other Kanban Cards';
$lang->kanban->defaultColumn = array();
$lang->kanban->defaultColumn['wait'] = 'wait';
@@ -325,10 +344,11 @@ $lang->kanbancard->beginAB = 'Begin';
$lang->kanbancard->to = '~';
$lang->kanbancard->archived = 'Archived';
$lang->kanbancard->empty = 'No Card';
$lang->kanbancard->ditto = 'Ditto';
$lang->kanbancard->confirmArchive = 'Are you sure to archive this card? After archiving the card, it will be hidden from the column and you can view it in the Region - Archived.';
$lang->kanbancard->confirmDelete = 'Are you sure to delete this card? After deleting the card, it will be deleted from the Kanban. You can only view it in the system recycle bin.';
$lang->kanbancard->confirmRestore = 'Are you sure you want to restore this card? After the card is restored, the card will be restored to the "%s" Kanban column.';
$lang->kanbancard->confirmRestore = "Are you sure you want to restore this card? After the card is restored, the card will be restored to the '%s' Kanban column.";
$lang->kanbancard->confirmRestoreTip = "The card's column has been archived or deleted, please restore '%s' column first.";
$lang->kanbancard->priList[1] = 1;
+29 -9
View File
@@ -27,6 +27,8 @@ $lang->kanban->sortColumn = '看板列排序';
$lang->kanban->deleteColumn = '删除看板列';
$lang->kanban->createCard = '创建卡片';
$lang->kanban->editCard = '编辑卡片';
$lang->kanban->finishCard = '完成卡片';
$lang->kanban->activateCard = '激活卡片';
$lang->kanban->viewCard = '查看卡片';
$lang->kanban->archiveCard = '归档卡片';
$lang->kanban->sortCard = '卡片排序';
@@ -37,7 +39,9 @@ $lang->kanban->setCardColor = '设置卡片颜色';
$lang->kanban->deleteCard = '删除卡片';
$lang->kanban->assigntoCard = '指派';
$lang->kanban->setting = '设置';
$lang->kanban->setDoneFunction = '设置完成功能';
$lang->kanban->enableArchived = '设置归档功能';
$lang->kanban->archive = '归档功能';
$lang->kanban->performable = '设置完成功能';
$lang->kanban->doneFunction = '完成功能';
$lang->kanban->splitColumn = '新增子看板列';
$lang->kanban->createColumnOnLeft = '左侧新增看板列';
@@ -57,6 +61,9 @@ $lang->kanban->restoreColumn = '还原看板列';
$lang->kanban->restoreCard = '还原卡片';
$lang->kanban->restore = '还原';
$lang->kanban->child = '子';
$lang->kanban->batchCreateCard = '批量创建卡片';
$lang->kanban->import = '导入功能';
$lang->kanban->importAB = '导入';
$lang->kanban->showClosed = '显示已关闭';
$lang->kanban->importCard = '转入卡片';
$lang->kanban->importPlan = '导入产品计划';
@@ -107,8 +114,8 @@ $lang->kanban->aclGroup['extend'] = '继承空间';
$lang->kanban->aclList['extend'] = '继承空间访问权限(能访问当前空间,即可访问)';
$lang->kanban->aclList['private'] = '私有(看板团队成员、白名单、空间负责人可访问)';
$lang->kanban->enableArchived['0'] = '不启用';
$lang->kanban->enableArchived['1'] = '启用';
$lang->kanban->archiveList['0'] = '不启用';
$lang->kanban->archiveList['1'] = '启用';
$lang->kanban->enableFinished['0'] = '不启用';
$lang->kanban->enableFinished['1'] = '启用';
@@ -174,9 +181,21 @@ $lang->kanban->my = '我的看板';
$lang->kanban->other = '其他';
$lang->kanban->error = new stdclass();
$lang->kanban->error->mustBeInt = '在制品数量必须是正整数。';
$lang->kanban->error->parentLimitNote = '父列的在制品数量不能小于子列在制品数量之和';
$lang->kanban->error->childLimitNote = '子列在制品数量之和不能大于父列的在制品数量';
$lang->kanban->error->mustBeInt = '在制品数量必须是正整数。';
$lang->kanban->error->parentLimitNote = '父列的在制品数量不能小于子列在制品数量之和';
$lang->kanban->error->childLimitNote = '子列在制品数量之和不能大于父列的在制品数量';
$lang->kanban->error->importObjNotEmpty = '请至少选择一个导入对象';
$lang->kanban->importList = array();
$lang->kanban->importList['off'] = '不启用导入功能';
$lang->kanban->importList['on'] = '启用导入功能,只能导入自己有权限查看的内容';
$lang->kanban->importObjectList = array();
$lang->kanban->importObjectList['plan'] = '产品计划';
$lang->kanban->importObjectList['release'] = '产品发布';
$lang->kanban->importObjectList['build'] = '项目版本';
$lang->kanban->importObjectList['execution'] = '项目执行';
$lang->kanban->importObjectList['cards'] = '其他看板卡片';
$lang->kanban->defaultColumn = array();
$lang->kanban->defaultColumn['wait'] = '未开始';
@@ -257,9 +276,9 @@ $lang->kanbancolumn->childName = '子列名称';
$lang->kanbancolumn->childColor = '子状态颜色';
$lang->kanbancolumn->empty = '暂时没有看板列';
$lang->kanbancolumn->confirmArchive = '您确认归档该列吗?归档列后,该列和列中所有卡片将被隐藏,您可以在区域-已归档中查看已归档的列。';
$lang->kanbancolumn->confirmDelete = '您确认删除该列吗?删除列后,该列中所有卡片也会被删除。';
$lang->kanbancolumn->confirmRestore = '您确定要还原该看板列吗?还原看板列后,该看板列和看板列中所有的任务将同时还原到之前的位置。';
$lang->kanbancolumn->confirmArchive = '您确认归档该列吗?归档列后,该列将被隐藏,列中所有卡片移动到兄弟列或父列,您可以在区域-已归档中查看已归档的列。';
$lang->kanbancolumn->confirmDelete = '您确认删除该列吗?删除列后,该列中所有卡片会被移动到兄弟列或父列。';
$lang->kanbancolumn->confirmRestore = '您确定要还原该看板列吗?还原后,该看板列将回到之前的位置。';
$lang->kanbanlane = new stdclass();
$lang->kanbanlane->name = $lang->kanban->laneName;
@@ -325,6 +344,7 @@ $lang->kanbancard->beginAB = '开始';
$lang->kanbancard->to = '~';
$lang->kanbancard->archived = '已归档';
$lang->kanbancard->empty = '暂时没有卡片';
$lang->kanbancard->ditto = '同上';
$lang->kanbancard->confirmArchive = '您确认归档该卡片吗?归档卡片后,该卡片将从列中隐藏,您可以在区域-已归档中查看。';
$lang->kanbancard->confirmDelete = '您确认删除该卡片吗?删除卡片后,该卡片将从看板中删除,您只能通过系统回收站查看。';
+190 -21
View File
@@ -548,6 +548,80 @@ class kanbanModel extends model
return false;
}
/*
* Batch create kanban cards.
* @access public
* @return void
*/
public function batchCreateCard($kanbanID, $regionID, $groupID, $columnID)
{
foreach($_POST['name'] as $index => $value)
{
if($_POST['name'][$index] and isset($_POST['assignedTo'][$index])) $_POST['assignedTo'][$index] = implode(',', $_POST['assignedTo'][$index]);
}
$cards = fixer::input('post')->get();
$now = helper::now();
$data = array();
$lanes = array();
$lane = '';
$begin = '0000-00-00';
$end = '0000-00-00';
foreach($cards->name as $i => $name)
{
$lane = ($cards->lane[$i] == 'ditto') ? $lane : $cards->lane[$i];
$begin = (isset($cards->beginDitto[$i])) ? $begin : $cards->begin[$i];
$end = (isset($cards->endDitto[$i])) ? $end : $cards->end[$i];
if(empty($cards->name[$i])) continue;
$data[$i] = new stdclass();
$data[$i]->name = trim($cards->name[$i]);
$data[$i]->begin = $begin;
$data[$i]->end = $end;
$data[$i]->assignedTo = $cards->assignedTo[$i];
$data[$i]->desc = nl2br($cards->desc[$i]);
$data[$i]->pri = $cards->pri[$i];
$data[$i]->kanban = $kanbanID;
$data[$i]->region = $regionID;
$data[$i]->group = $groupID;
$data[$i]->createdBy = $this->app->user->account;
$data[$i]->createdDate = $now;
$data[$i]->assignedDate = $now;
$data[$i]->color = '#fff';
$data[$i]->estimate = is_numeric($cards->estimate[$i]) ? (float)$cards->estimate[$i] : $cards->estimate[$i];
$lanes[$i] = $lane;
}
foreach($data as $i => $card)
{
$this->dao->insert(TABLE_KANBANCARD)->data($card)->autoCheck()
->checkIF($card->estimate != '', 'estimate', 'float')
->batchCheck($this->config->kanban->createcard->requiredFields, 'notempty')
->exec();
if($card->estimate < 0)
{
dao::$errors[] = $this->lang->kanbancard->error->recordMinus;
return false;
}
if($card->end && $card->begin > $card->end)
{
dao::$errors[] = $this->lang->kanbancard->error->endSmall;
return false;
}
if(!dao::isError())
{
$cardID = $this->dao->lastInsertID();
$lane = $lanes[$i];
$this->addKanbanCell($kanbanID, $lane, $columnID, 'common', $cardID);
$this->loadModel('action')->create('kanbancard', $cardID, 'created');
}
}
}
/**
* Get kanban by id.
*
@@ -887,7 +961,7 @@ class kanbanModel extends model
->orderBy($order)
->fetchGroup('group');
$actions = array('createColumn', 'setColumn', 'setWIP', 'archiveColumn', 'restoreColumn', 'deleteColumn', 'createCard', 'splitColumn');
$actions = array('createColumn', 'setColumn', 'setWIP', 'archiveColumn', 'restoreColumn', 'deleteColumn', 'createCard', 'batchCreateCard', 'splitColumn', 'import', 'sortColumn');
/* Group by parent. */
$parentColumnGroup = array();
@@ -958,7 +1032,8 @@ class kanbanModel extends model
->andWhere('type')->eq('common')
->fetchAll();
$actions = array('editCard', 'archiveCard', 'deleteCard', 'moveCard', 'setCardColor', 'viewCard', 'sortCard', 'viewExecution');
$actions = array('editCard', 'finishCard', 'activateCard', 'archiveCard', 'deleteCard', 'moveCard', 'setCardColor', 'viewCard', 'sortCard', 'viewExecution');
$cardGroup = array();
foreach($cellList as $cell)
{
@@ -969,7 +1044,10 @@ class kanbanModel extends model
{
if(!isset($cards[$cardID])) continue;
$card = zget($cards, $cardID);
$card = zget($cards, $cardID);
$card->column = $cell->column;
$card->lane = $cell->lane;
$card->actions = array();
foreach($actions as $action)
{
@@ -1564,7 +1642,7 @@ class kanbanModel extends model
->beginIF(strpos($param, 'noclosed') !== false)->andWhere('status')->ne('closed')->fi()
->fetchAll('id');
$spaceList = $objectType == 'kanban' ? $this->dao->select('id,owner')->from(TABLE_KANBANSPACE)->fetchAll('id') : array();
$spaceList = $objectType == 'kanban' ? $this->dao->select('id,owner,type')->from(TABLE_KANBANSPACE)->fetchAll('id') : array();
if($this->app->user->admin) return array_keys($objects);
@@ -1581,7 +1659,9 @@ class kanbanModel extends model
if($objectType == 'kanban')
{
$spaceOwner = isset($spaceList[$object->space]->owner) ? $spaceList[$object->space]->owner : '';
$spaceType = isset($spaceList[$object->space]->type) ? $spaceList[$object->space]->type : '';
if(strpos(",$spaceOwner,", ",$account,") !== false) $remove = false;
if($spaceType == 'public') $remove = false;
}
if($remove) unset($objects[$objectID]);
@@ -1603,7 +1683,6 @@ class kanbanModel extends model
->setDefault('createdBy', $account)
->setDefault('createdDate', helper::now())
->setdefault('team', '')
->setdefault('owner', $account)
->setdefault('whitelist', '')
->join('whitelist', ',')
->join('team', ',')
@@ -1611,6 +1690,8 @@ class kanbanModel extends model
->remove('uid,contactListMenu')
->get();
if($space->type == 'private') $space->owner = $account;
if(strpos(",{$space->team},", ",$account,") === false and $space->owner != $account) $space->team .= ",$account";
$space = $this->loadModel('file')->processImgURL($space, $this->config->kanban->editor->createspace['id'], $this->post->uid);
@@ -2720,20 +2801,22 @@ class kanbanModel extends model
$actions .= "<div class='btn-group'>";
$actions .= "<a href='javascript:fullScreen();' id='fullScreenBtn' class='btn btn-link'><i class='icon icon-fullscreen'></i> {$this->lang->kanban->fullScreen}</a>";
$printSettingBtn = (common::hasPriv('kanban', 'createRegion') or $printSetHeight or common::hasPriv('kanban', 'setDoneFunction') or common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'delete'));
$printSettingBtn = (common::hasPriv('kanban', 'createRegion') or $printSetHeight or common::hasPriv('kanban', 'performable') or common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'enableArchived') or common::hasPriv('kanban', 'delete'));
if($printSettingBtn)
{
$actions .= "<a data-toggle='dropdown' class='btn btn-link dropdown-toggle setting' type='button'>" . '<i class="icon icon-cog-outline"></i> ' . $this->lang->kanban->setting . '</a>';
$actions .= "<ul id='kanbanActionMenu' class='dropdown-menu text-left'>";
if(common::hasPriv('kanban', 'createRegion')) $actions .= '<li>' . html::a(helper::createLink('kanban', 'createRegion', "kanbanID=$kanban->id", '', true), '<i class="icon icon-plus"></i>' . $this->lang->kanban->createRegion, '', "class='iframe btn btn-link'") . '</li>';
if(common::hasPriv('kanban', 'import')) $actions .= '<li>' . html::a(helper::createLink('kanban', 'import', "kanbanID=$kanban->id", '', true), '<i class="icon icon-import"></i>' . $this->lang->kanban->import, '', "class='iframe btn btn-link'") . '</li>';
if(common::hasPriv('kanban', 'enableArchived')) $actions .= '<li>' . html::a(helper::createLink('kanban', 'enableArchived', "kanbanID=$kanban->id", '', true), '<i class="icon icon-card-archive"></i>' . $this->lang->kanban->archived, '', "class='iframe btn btn-link'") . '</li>';
if($printSetHeight)
{
$width = $this->app->getClientLang() == 'en' ? '70%' : '60%';
$actions .= '<li>' . html::a(helper::createLink('kanban', 'setLaneHeight', "kanbanID=$kanban->id", '', true), '<i class="icon icon-size-height"></i>' . $this->lang->kanban->laneHeight, '', "class='iframe btn btn-link' data-width='$width'") . '</li>';
}
if(common::hasPriv('kanban', 'setDoneFunction')) $actions .= '<li>' . html::a(helper::createLink('kanban', 'setDoneFunction', "kanbanID=$kanban->id", '', true), '<i class="icon icon-checked"></i>' . $this->lang->kanban->doneFunction, '', "class='iframe btn btn-link'") . '</li>';
if(common::hasPriv('kanban', 'performable')) $actions .= '<li>' . html::a(helper::createLink('kanban', 'performable', "kanbanID=$kanban->id", '', true), '<i class="icon icon-checked"></i>' . $this->lang->kanban->doneFunction, '', "class='iframe btn btn-link'") . '</li>';
$kanbanActions = '';
$attr = $kanban->status == 'closed' ? "disabled='disabled'" : '';
@@ -2742,7 +2825,7 @@ class kanbanModel extends model
if(common::hasPriv('kanban', 'delete')) $kanbanActions .= '<li>' . html::a(helper::createLink('kanban', 'delete', "kanbanID=$kanban->id"), '<i class="icon icon-trash"></i>' . $this->lang->kanban->delete, 'hiddenwin', "class='btn btn-link'") . '</li>';
if($kanbanActions)
{
$actions .= ((common::hasPriv('kanban', 'createRegion') or $printSetHeight or common::hasPriv('kanban', 'setDoneFunction')) and (common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'delete'))) ? "<div class='divider'></div>" . $kanbanActions : $kanbanActions;
$actions .= ((common::hasPriv('kanban', 'createRegion') or $printSetHeight or common::hasPriv('kanban', 'performable')) and (common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'enableArchived') or common::hasPriv('kanban', 'delete'))) ? "<div class='divider'></div>" . $kanbanActions : $kanbanActions;
}
$actions .= "</ul>";
}
@@ -2817,9 +2900,10 @@ class kanbanModel extends model
$fromCellCards = $this->dao->select('cards')->from(TABLE_KANBANCELL)->where('lane')->eq($fromLaneID)->andWhere('`column`')->eq($fromColID)->fetch('cards');
$toCellCards = $this->dao->select('cards')->from(TABLE_KANBANCELL)->where('lane')->eq($toLaneID)->andWhere('`column`')->eq($toColID)->fetch('cards');
$fromCardList = str_replace("$cardID,", '', $fromCellCards);
$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();
$this->dao->update(TABLE_KANBANCELL)->set('cards')->eq($toCardList)->where('`column`')->eq($toColID)->andWhere('lane')->eq($toLaneID)->exec();
}
@@ -2897,6 +2981,39 @@ class kanbanModel extends model
*/
public function restoreColumn($columnID)
{
$column = $this->getColumnByID($columnID);
if($column->parent)
{
$parent = $this->getColumnByID($column->parent);
/* If the parent column is normal now, put its card into child column. */
if($parent->parent != -1)
{
$parentCells = $this->dao->select('*')->from(TABLE_KANBANCELL)
->where('`column`')->eq($column->parent)
->andWhere('type')->eq('common')
->fetchAll('id');
foreach($parentCells as $cell)
{
$this->dao->update(TABLE_KANBANCELL)->set('cards')->eq($cell->cards)
->where('lane')->eq($cell->lane)
->andWhere('`column`')->eq($columnID)
->andWhere('type')->eq('common')
->exec();
$this->dao->update(TABLE_KANBANCELL)->set('cards')->eq('')
->where('lane')->eq($cell->lane)
->andWhere('`column`')->eq($cell->column)
->andWhere('type')->eq('common')
->exec();
}
$this->dao->update(TABLE_KANBANCOLUMN)->set('parent')->eq(-1)->where('id')->eq($column->parent)->exec();
}
}
$this->dao->update(TABLE_KANBANCOLUMN)
->set('archived')->eq(0)
->where('id')->eq($columnID)
@@ -2949,6 +3066,53 @@ class kanbanModel extends model
if(!dao::isError()) return common::createChanges($oldCard, $card);
}
/**
* Process cards when delete a column.
*
* @param object $column
* @access public
* @return void
*/
public function processCards($column)
{
$firstColumnID = $this->dao->select('id')->from(TABLE_KANBANCOLUMN)
->where('parent')->eq($column->parent)
->andWhere('id')->ne($column->id)
->andWhere('deleted')->eq('0')
->andWhere('archived')->eq('0')
->orderBy('`order` asc')
->fetch('id');
$extendID = $firstColumnID;
if(!$firstColumnID)
{
$extendID = $column->parent;
$this->dao->update(TABLE_KANBANCOLUMN)->set('parent')->eq(0)->where('id')->eq($column->parent)->exec();
}
$cells = $this->dao->select('*')->from(TABLE_KANBANCELL)
->where('`column`')->eq($column->id)
->andWhere('type')->eq('common')
->fetchAll('id');
foreach($cells as $cell)
{
$extendCards = $this->dao->select('cards')->from(TABLE_KANBANCELL)
->where('lane')->eq($cell->lane)
->andWhere('`column`')->eq($extendID)
->andWhere('type')->eq('common')
->fetch('cards');
$extendCards = $extendCards ? $extendCards . ltrim($cell->cards, ',') : $cell->cards;
$this->dao->update(TABLE_KANBANCELL)->set('cards')->eq($extendCards)
->where('lane')->eq($cell->lane)
->andWhere('`column`')->eq($extendID)
->andWhere('type')->eq('common')
->exec();
}
}
/**
* Get space by id.
*
@@ -3276,18 +3440,6 @@ class kanbanModel extends model
case 'deletecolumn' :
if($object->deleted != '0') return false;
if($object->parent > 0)
{
$childrenCount = $this->dao->select('COUNT(id) AS count')->from(TABLE_KANBANCOLUMN)
->where('parent')->eq($object->parent)
->andWhere('deleted')->eq('0')
->andWhere('archived')->eq('0')
->fetch('count');
return $childrenCount > 2;
}
$count = $this->dao->select('COUNT(id) AS count')->from(TABLE_KANBANCOLUMN)
->where('region')->eq($object->region)
->andWhere('parent')->in('0,-1')
@@ -3297,8 +3449,25 @@ class kanbanModel extends model
->fetch('count');
return $count > 1;
case 'sortColumn' :
if($object->deleted != '0') return false;
}
return true;
}
/**
* Import.
*
* @param int $kanbanID
* @access public
* @return void
*/
public function import($kanbanID)
{
$importObjects = $_POST['import'] == 'off' ? array() : $_POST['importObjectList'];
$importObjectList = implode(',', $importObjects);
$this->dao->update(TABLE_KANBAN)->set('object')->eq($importObjectList)->where('id')->eq($kanbanID)->exec();
}
}
@@ -0,0 +1,78 @@
<?php
/**
* The batch create view of kanban module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Xin Zhou <zhouxin@cnezsoft.com>
* @package kanban
* @version $Id$
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id="mainContent" class="main-content fade">
<div class="main-header clearfix">
<h2 class="pull-left">
<?php echo $lang->kanban->batchCreateCard;?>
</h2>
</div>
<form method='post' class='load-indicator batch-actions-form form-ajax' enctype='multipart/form-data' id="batchCreateCardForm">
<div class="table-responsive">
<table class="table table-form">
<thead>
<tr>
<th class='c-id text-center'><?php echo $lang->idAB;?></th>
<th class='c-name required'><?php echo $lang->kanbancard->name?></th>
<th><?php echo $lang->kanbancard->lane;?></th>
<th><?php echo $lang->kanbancard->assignedTo;?></th>
<th class='c-estimate'><?php echo $lang->kanbancard->estimate;?></th>
<th class='c-date'><?php echo $lang->kanbancard->begin;?></th>
<th class='c-date'><?php echo $lang->kanbancard->end;?></th>
<th><?php echo $lang->kanbancard->desc;?></th>
<th class='c-pri w-120px'><?php echo $lang->kanbancard->pri;?></th>
</tr>
</thead>
<tbody>
<?php $pri = 3;?>
<?php for($i = 0; $i < $config->kanban->batchCreate; $i++):?>
<tr>
<td class='text-center'><?php echo $i + 1;?></td>
<td class='text-center'><?php echo html::input("name[$i]", '', "class='form-control title-import'");?></td>
<td style='overflow:visible'><?php echo html::select("lane[$i]", $lanePairs, key($lanePairs), "class='form-control chosen'")?></td>
<td style='overflow:visible'><?php echo html::select("assignedTo[$i][]", $users, $app->user->account, "class='form-control chosen' multiple");?></td>
<td><?php echo html::input("estimate[$i]", '', "class='form-control text-center'");?></td>
<td>
<div class='input-group'>
<?php
echo html::input("begin[$i]", '', "class='form-control form-date' onkeyup='toggleCheck(this)'");
if($i != 0) echo "<span class='input-group-addon estStartedBox'><input type='checkbox' name='beginDitto[$i]' id='beginDitto$i' " . ($i > 0 ? "checked" : '') . " /> {$lang->kanbancard->ditto}</span>";
?>
</div>
</td>
<td>
<div class='input-group'>
<?php
echo html::input("end[$i]", '', "class='form-control form-date' onkeyup='toggleCheck(this)'");
if($i != 0) echo "<span class='input-group-addon deadlineBox'><input type='checkbox' name='endDitto[$i]' id='endDitto$i' " . ($i > 0 ? "checked" : '') . " /> {$lang->kanbancard->ditto}</span>";
?>
</div>
</td>
<td ><?php echo html::textarea("desc[$i]", '', "rows='1' class='form-control autosize'");?></td>
<td ><?php echo html::select("pri[$i]", (array)$lang->kanbancard->priList, $pri, 'class=form-control');?></td>
</tr>
<?php endfor;?>
</tbody>
<tfoot>
<tr>
<td colspan='8' class='text-center form-actions'>
<?php echo html::submitButton();?>
<?php echo html::backButton();?>
</td>
</tr>
</tfoot>
</table>
</div>
</form>
</div>
<?php include '../../common/view/footer.html.php';?>
+3 -3
View File
@@ -23,11 +23,11 @@
<form method='post' enctype='multipart/form-data' target='hiddenwin'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->comment;?></th>
<td colspan='2'><?php echo html::textarea('comment', '', "rows='6'");?></td>
<th class='c-comment'><?php echo $lang->comment;?></th>
<td><?php echo html::textarea('comment', '', "rows='6'");?></td>
</tr>
<tr>
<td colspan='3' class='text-center form-actions'>
<td colspan='2' class='text-center form-actions'>
<?php echo html::submitButton($lang->kanban->closeSpace);?>
</td>
</tr>
+3 -7
View File
@@ -12,6 +12,7 @@
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php js::set('spaceType', $type);?>
<div id='mainContent' class='main-content'>
<div class='main-header'>
<h2><?php echo $lang->kanban->create;?></h2>
@@ -20,22 +21,18 @@
<table class='table table-form'>
<tr>
<th><?php echo $lang->kanbanspace->type;?></th>
<td><?php echo html::select('type', $typeList, $type, "onchange='changeType({$spaceID}, this.value)' class='form-control chosen'");?></td>
<td><?php echo html::select('type', $typeList, $type, "onchange='changeValue({$spaceID}, this.value)' class='form-control chosen'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->kanban->space;?></th>
<td><?php echo html::select('space', $spacePairs, $spaceID, "class='form-control chosen'");?></td>
<td><?php echo html::select('space', $spacePairs, $spaceID, "onchange='changeValue(this.value)' class='form-control chosen'");?></td>
<td></td>
</tr>
<tr>
<th><?php echo $lang->kanban->name;?></th>
<td><?php echo html::input('name', '', "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->kanban->archived;?></th>
<td><?php echo html::radio('archived', $lang->kanban->enableArchived, '0');?></td>
</tr>
<?php if($type != 'private'):?>
<tr>
<th><?php echo $lang->kanban->owner;?></th>
@@ -46,7 +43,6 @@
<td colspan='2'>
<div class="input-group">
<?php echo html::select('team[]', $users, '', "class='form-control chosen' multiple data-drop_direction='down'");?>
<?php echo $this->fetch('my', 'buildContactLists');?>
</div>
</td>
</tr>
+1 -1
View File
@@ -5,7 +5,7 @@
* @copyright Copyright 2009-2021 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Shujie Tian<tianshujie@cnezsoft.com>
* @package kanban
* @package kanban
* @version $Id: createcard.html.php 5090 2021-12-13 13:49:24Z tainshujie@cnezsoft.com $
* @link https://www.zentao.net
*/
+1 -1
View File
@@ -20,7 +20,7 @@
<table class='table table-form'>
<tr>
<th><?php echo $lang->kanbanspace->type;?></th>
<td><?php echo html::select('type', $typeList, $type, "onchange='changeType(this.value)' class='form-control'");?></td>
<td><?php echo html::select('type', $typeList, $type, "onchange='changeType(this.value)' class='form-control chosen'");?></td>
<td></td>
</tr>
<tr>
-5
View File
@@ -26,10 +26,6 @@
<th><?php echo $lang->kanban->name;?></th>
<td><?php echo html::input('name', $kanban->name, "class='form-control'");?></td>
</tr>
<tr>
<th><?php echo $lang->kanban->archived;?></th>
<td><?php echo html::radio('archived', $lang->kanban->enableArchived, $kanban->archived);?></td>
</tr>
<?php if($type != 'private'):?>
<tr>
<th><?php echo $lang->kanban->owner;?></th>
@@ -40,7 +36,6 @@
<td colspan='2'>
<div class="input-group">
<?php echo html::select('team[]', $users, $kanban->team, "class='form-control chosen' multiple data-drop_direction='down'");?>
<?php echo $this->fetch('my', 'buildContactLists');?>
</div>
</td>
</tr>
@@ -0,0 +1,35 @@
<?php
/**
* The enableArchived file of kanban module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Runyu Zheng <zhengrunyu@easycorp.ltd>
* @package kanban
* @version $Id: enableArchived.html.php 935 2022-01-21 11:02:24Z $
* @link https://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2><?php echo $lang->kanban->enableArchived;?></h2>
</div>
<form class='main-form form-ajax' method='post' enctype='multipart/form-data' id='dataform'>
<table class='table table-form'>
<tr>
<th><?php echo $lang->kanban->archive;?></th>
<td><?php echo nl2br(html::radio('archived', $lang->kanban->archiveList, $kanban->archived));?></td>
</tr>
<tr>
<td colspan='2' class='text-center form-actions'>
<?php echo html::submitButton();?>
</td>
</tr>
</table>
</form>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
+52
View File
@@ -0,0 +1,52 @@
<?php
/**
* The import file of kanban module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Fangzhou Hu <hufangzhou@easycorp.ltd>
* @package kanban
* @version $Id: import.html.php 935 2022-01-19 14:15:24Z hufangzhou@easycorp.ltd $
* @link https://www.zentao.net
*/
?>
<?php include '../../common/view/header.lite.html.php';?>
<?php js::set('enableImport', $enableImport);?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2>
<?php echo "<span>" . $lang->kanban->import . '</span>';?>
</h2>
</div>
<form method='post' class="load-indicator main-form form-ajax" target='hiddenwin' id='importForm'>
<table align='center' class='table table-form'>
<tr>
<td colspan='2'>
<label class="radio-inline">
<input type='radio' name='import' value='off' <?php echo $enableImport == 'off' ? "checked='checked'" : ''; ?> id='importoff'/>
<?php echo $lang->kanban->importList['off'];?>
</label>
</td>
</tr>
<tr>
<td colspan='2'>
<label class="radio-inline">
<input type='radio' name='import' value='on' <?php echo $enableImport == 'on' ? "checked='checked'" : ''; ?> id='importon'/>
<?php echo $lang->kanban->importList['on'];?>
</label>
</td>
</tr>
<tr>
<td colspan='2'><?php echo html::checkbox('importObjectList', $lang->kanban->importObjectList, $importObjects);?></td>
</tr>
<tr id='emptyTip' class='hidden'><td colspan='3' style='color: red;'><?php echo $lang->kanban->error->importObjNotEmpty;?></td></tr>
<tr>
<td class='form-actions'><?php echo html::submitButton();?></td>
</tr>
</table>
</form>
</div>
</div>
<?php include '../../common/view/footer.html.php';?>
@@ -1,12 +1,12 @@
<?php
/**
* The setdonefunction file of kanban module of ZenTaoPMS.
* The performable file of kanban module of ZenTaoPMS.
*
* @copyright Copyright 2009-2022 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html)
* @author Yue Ma <mayue@easycorp.ltd>
* @package kanban
* @version $Id: setdonefunction.html.php 935 2022-01-1 14:20:24Z $
* @version $Id: performable.html.php 935 2022-01-1 14:20:24Z $
* @link https://www.zentao.net
*/
?>
@@ -14,7 +14,7 @@
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
<h2><?php echo $lang->kanban->setDoneFunction;?></h2>
<h2><?php echo $lang->kanban->performable;?></h2>
</div>
<form class='main-form form-ajax' method='post' enctype='multipart/form-data' id='dataform'>
<table class='table table-form'>
+1 -1
View File
@@ -50,7 +50,7 @@
</div>
<div class='spaceActions pull-right'>
<?php $class = $space->status == 'closed' ? 'disabled' : '';?>
<?php if($space->status != 'closed' and $browseType != 'involved') common::printLink('kanban', 'create', "spaceID={$space->id}&type={$space->type}", '<i class="icon icon-plus"></i> ' . $lang->kanban->create, '', "class='iframe' data-width='75%'", '', true);?>
<?php if($space->status != 'closed' and $browseType != 'involved' and !empty($unclosedSpace)) common::printLink('kanban', 'create', "spaceID={$space->id}&type={$space->type}", '<i class="icon icon-plus"></i> ' . $lang->kanban->create, '', "class='iframe' data-width='75%'", '', true);?>
<?php common::printLink('kanban', 'editSpace', "spaceID={$space->id}", '<i class="icon icon-cog-outline"></i> ' . $lang->kanban->setting, '', "class='iframe' data-width='75%'", '', true);?>
<?php common::printLink('kanban', 'closeSpace', "spaceID={$space->id}", '<i class="icon icon-off"></i> ' . $lang->close, '', "class='iframe {$class}'", '', true);?>
<?php common::printLink('kanban', 'deleteSpace', "spaceID={$space->id}", '<i class="icon icon-trash"></i> ' . $lang->delete, 'hiddenwin', '', '', true);?>
+8 -1
View File
@@ -39,12 +39,19 @@
//common::printLink('kanban', 'assigntoCard', "cardID=$card->id", "<i class='icon icon-hand-right'></i><span class='text'>{$lang->kanbancard->assign}</span>", '', "class='btn btn-link iframe' title='{$lang->kanbancard->assign}'", true, true);
if($kanban->archived)
{
common::printLink('kanban', 'archiveCard', "cardID=$card->id", "<i class='icon icon-ban-circle'></i><span class='text'>{$lang->kanbancard->archive}</span>", 'hiddenwin', "class='btn btn-link' title='{$lang->kanbancard->archive}'", true, true);
common::printLink('kanban', 'archiveCard', "cardID=$card->id", "<i class='icon icon-ban-circle'></i><span class='text'>{$lang->kanbancard->archive}</span>", 'hiddenwin', "class='btn btn-link' title='{$lang->kanbancard->archive}'", true, true);
echo "<div class='divider'></div>";
}
common::printLink('kanban', 'editCard', "cardID=$card->id", '<i class="icon icon-edit"></i>', '', "class='btn btn-link iframe' data-width='80%' title='{$lang->kanbancard->edit}'", true, true);
if($kanban->performable)
{
if($card->status == 'done') common::printLink('kanban', 'activateCard', "cardID={$card->id}&kanbanID={$kanban->id}", '<i class="icon icon-magic"></i>', '', "class='btn btn-link iframe' title='{$lang->kanban->activateCard}'", true, true);
if($card->status == 'doing') common::printLink('kanban', 'finishCard', "cardID={$card->id}&kanbanID={$kanban->id}", '<i class="icon icon-checked"></i>', '', "class='btn btn-link iframe' title='{$lang->kanban->finishCard}'", true, true);
}
common::printLink('kanban', 'copyCard', "cardID=$card->id", '<i class="icon icon-copy"></i>', '', "class='btn btn-link iframe' title='{$lang->kanbancard->copy}'", true, true);
common::printLink('kanban', 'deleteCard', "cardID=$card->id", '<i class="icon icon-trash"></i>', 'hiddenwin', "class='btn btn-link' title='{$lang->kanbancard->delete}'",true, true);
?>
+1 -1
View File
@@ -187,7 +187,7 @@ $lang->project->tenThousand = '';
$lang->project->unitList['CNY'] = 'RMB';
$lang->project->unitList['USD'] = 'USD';
$lang->project->unitList['HKD'] = 'HKD';
$lang->project->unitList['NTD'] = 'NTW';
$lang->project->unitList['NTD'] = 'NTD';
$lang->project->unitList['EUR'] = 'EUR';
$lang->project->unitList['DEM'] = 'DEM';
$lang->project->unitList['CHF'] = 'CHF';
+1
View File
@@ -18,6 +18,7 @@ $lang->report->undefined = 'Undefined';
$lang->report->query = 'Query';
$lang->report->annual = 'Annual Summary';
$lang->report->project = 'Project';
$lang->report->PO = 'PO';
$lang->report->colors[] = 'AFD8F8';
$lang->report->colors[] = 'F6BD0F';
+1
View File
@@ -18,6 +18,7 @@ $lang->report->undefined = '未设定';
$lang->report->query = '查询';
$lang->report->annual = '年度总结';
$lang->report->project = '项目';
$lang->report->PO = 'PO';
$lang->report->colors[] = 'AFD8F8';
$lang->report->colors[] = 'F6BD0F';
+1 -1
View File
@@ -44,7 +44,7 @@
<thead>
<tr>
<th class='c-name'><?php echo $lang->product->name;?></th>
<th class='c-user'><?php echo $lang->product->PO;?></th>
<th class='c-user'><?php echo $lang->report->PO;?></th>
<th><?php echo $lang->productplan->common;?></th>
<th class="c-date"><?php echo $lang->productplan->begin;?></th>
<th class="c-date"><?php echo $lang->productplan->end;?></th>
+103 -17
View File
@@ -157,7 +157,21 @@ class story extends control
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $storyID));
/* If link from no head then reload. */
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
if(isonlybody())
{
$execution = $this->execution->getByID($this->session->execution);
if($this->app->tab == 'execution' and $execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($this->session->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.updateKanban($kanbanData, 0)"));
}
else
{
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
}
if($this->post->newStory)
{
@@ -398,13 +412,13 @@ class story extends control
if($storyID)
{
$story = $this->story->getById($storyID);
if($story->status != 'active' or $story->stage != 'wait' or $story->parent > 0) die(js::alert($this->lang->story->errorNotSubdivide) . js::locate('back'));
if($story->status != 'active' or $story->stage != 'wait' or $story->parent > 0) return print(js::alert($this->lang->story->errorNotSubdivide) . js::locate('back'));
}
if(!empty($_POST))
{
$mails = $this->story->batchCreate($productID, $branch, $type);
if(dao::isError()) die(js::error(dao::getError()));
if(dao::isError()) return print(js::error(dao::getError()));
$stories = array();
foreach($mails as $mail) $stories[] = $mail->storyID;
@@ -426,11 +440,25 @@ class story extends control
}
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'idList' => $stories));
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
if(isonlybody())
{
$execution = $this->execution->getByID($this->session->execution);
if($this->app->tab == 'execution' and $execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($this->session->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
if($storyID)
{
die(js::locate(inlink('view', "storyID=$storyID"), 'parent'));
return print(js::locate(inlink('view', "storyID=$storyID"), 'parent'));
}
elseif($executionID)
{
@@ -438,13 +466,13 @@ class story extends control
$moduleName = $execution->type == 'project' ? 'projectstory' : 'execution';
$param = $execution->type == 'project' ? "projectID=$executionID&productID=$productID" : "executionID=$executionID&orderBy=id_desc&browseType=unclosed";
$link = $this->createLink($moduleName, 'story', $param);
die(js::locate($link, 'parent'));
return print(js::locate($link, 'parent'));
}
else
{
setcookie('storyModule', 0, 0, $this->config->webRoot, '', $this->config->cookieSecure, false);
$locateLink = $this->session->storyList ? $this->session->storyList : $this->createLink('product', 'browse', "productID=$productID&branch=$branch&browseType=unclosed&queryID=0&type=$type");
die(js::locate($locateLink, 'parent'));
return print(js::locate($locateLink, 'parent'));
}
}
@@ -921,9 +949,24 @@ class story extends control
$module = $this->app->tab == 'project' ? 'projectstory' : 'story';
if(isonlybody()) die(js::reload('parent.parent'));
if(isonlybody())
{
$execution = $this->execution->getByID($this->session->execution);
if($this->app->tab == 'execution' and $execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($this->session->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::reload('parent.parent'));
}
}
if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success'));
die(js::locate($this->createLink($module, 'view', "storyID=$storyID"), 'parent'));
return print(js::locate($this->createLink($module, 'view', "storyID=$storyID"), 'parent'));
}
$this->commonAction($storyID);
@@ -974,8 +1017,22 @@ class story extends control
$this->executeHooks($storyID);
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
die(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent'));
if(isonlybody())
{
$execution = $this->execution->getByID($this->session->execution);
if($this->app->tab == 'execution' and $execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($this->session->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
return print(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent'));
}
$this->commonAction($storyID);
@@ -1243,7 +1300,7 @@ class story extends control
if(!empty($_POST))
{
$changes = $this->story->close($storyID);
if(dao::isError()) die(js::error(dao::getError()));
if(dao::isError()) return print(js::error(dao::getError()));
if($changes)
{
@@ -1253,14 +1310,29 @@ class story extends control
$this->executeHooks($storyID);
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
if(isonlybody())
{
$execution = $this->execution->getByID($this->session->execution);
if($this->app->tab == 'execution' and $execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($this->session->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
if(defined('RUN_MODE') && RUN_MODE == 'api')
{
die(array('status' => 'success', 'data' => $storyID));
return print(array('status' => 'success', 'data' => $storyID));
}
else
{
die(js::locate(inlink('view', "storyID=$storyID"), 'parent'));
return print(js::locate(inlink('view', "storyID=$storyID"), 'parent'));
}
}
@@ -1586,8 +1658,22 @@ class story extends control
$this->executeHooks($storyID);
if(isonlybody()) die(js::closeModal('parent.parent', 'this', 'function(){parent.parent.$(\'[data-ride="searchList"]\').searchList();}'));
die(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent'));
if(isonlybody())
{
$execution = $this->execution->getByID($this->session->execution);
if($this->app->tab == 'execution' and $execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($this->session->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent', 'this', 'function(){parent.parent.$(\'[data-ride="searchList"]\').searchList();}'));
}
}
return print(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent'));
}
/* Get story and product. */
+6 -1
View File
@@ -2142,6 +2142,12 @@ class storyModel extends model
$releases = $this->dao->select('*')->from(TABLE_RELEASE)->where("CONCAT(',', stories, ',')")->like("%,$storyID,%")->andWhere('deleted')->eq(0)->fetchPairs('branch', 'branch');
foreach($releases as $branch) $stages[$branch] = 'released';
$currentStory = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch();
foreach($executions as $executionID => $branch)
{
$this->kanban->updateLane($executionID, 'story', $storyID);
}
if(empty($stages)) return;
if($hasBranch)
{
@@ -2173,7 +2179,6 @@ class storyModel extends model
$this->dao->update(TABLE_STORY)->set('stage')->eq(current($stages))->where('id')->eq($storyID)->exec();
}
$currentStory = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch();
if($story->stage != $currentStory->stage)
{
foreach($executions as $executionID => $branch)
+200 -17
View File
@@ -146,7 +146,20 @@ class task extends control
if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $taskID));
/* If link from no head then reload. */
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
if(isonlybody())
{
if($execution->type == 'kanban')
{
$kanbanData = $this->kanban->getRDKanban($executionID, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.updateKanban($kanbanData, 0)"));
}
else
{
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
}
/* Locate the browser. */
if($this->app->getViewType() == 'xhtml')
@@ -235,7 +248,7 @@ class task extends control
$this->view->position = $position;
$this->view->gobackLink = (isset($output['from']) and $output['from'] == 'global') ? $this->createLink('execution', 'task', "executionID=$executionID") : '';
$this->view->execution = $execution;
$this->view->executions = $this->config->systemMode == 'classic' ? $executions : $this->execution->getByProject(0, 'all', 0, true);
$this->view->executions = $this->config->systemMode == 'classic' ? $executions : $this->execution->getByProject(0, 'undone', 0, true);
$this->view->task = $task;
$this->view->users = $users;
$this->view->storyID = $storyID;
@@ -309,7 +322,20 @@ class task extends control
if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'idList' => $taskIDList));
/* If link from no head then reload. */
if(isonlybody()) return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
if(isonlybody())
{
if($execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'callback' => "parent.updateKanban($kanbanData, 0)"));
}
else
{
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent'));
}
}
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $taskLink));
}
@@ -424,7 +450,22 @@ class task extends control
}
}
if(isonlybody()) die(js::reload('parent.parent'));
if(isonlybody())
{
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::reload('parent.parent'));
}
}
if(defined('RUN_MODE') && RUN_MODE == 'api')
{
return $this->send(array('status' => 'success', 'data' => $taskID));
@@ -622,8 +663,23 @@ class task extends control
$this->executeHooks($taskID);
if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'success'));
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
if(isonlybody())
{
$task = $this->task->getById($taskID);
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
return print(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
$members = $this->loadModel('user')->getTeamMemberPairs($executionID, 'execution', 'nodeleted');
@@ -809,6 +865,9 @@ class task extends control
{
$this->commonAction($taskID);
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
$task = $this->task->getById($taskID);
if(!empty($_POST))
@@ -848,7 +907,23 @@ class task extends control
}
if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'success'));
if(isonlybody()) die(js::closeModal('parent.parent', 'this', "function(){parent.parent.location.reload();}"));
if(isonlybody())
{
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent', 'this', "function(){parent.parent.location.reload();}"));
}
}
die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
@@ -895,8 +970,22 @@ class task extends control
}
}
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
if(isonlybody())
{
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
return print(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
$this->session->set('estimateList', $this->app->getURI(true), 'execution');
@@ -1021,6 +1110,7 @@ class task extends control
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, 'all', 'id_desc', $regionID);
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
@@ -1083,6 +1173,9 @@ class task extends control
{
$this->commonAction($taskID);
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(!empty($_POST))
{
$this->loadModel('action');
@@ -1097,8 +1190,25 @@ class task extends control
$this->executeHooks($taskID);
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
if(isonlybody())
{
$task = $this->task->getById($taskID);
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
return print(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
$this->view->title = $this->view->execution->name . $this->lang->colon .$this->lang->task->pause;
@@ -1136,8 +1246,23 @@ class task extends control
$this->executeHooks($taskID);
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
if(isonlybody())
{
$task = $this->task->getById($taskID);
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all');
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
return print(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
$this->view->title = $this->view->execution->name . $this->lang->colon .$this->lang->task->restart;
@@ -1161,6 +1286,9 @@ class task extends control
{
$this->commonAction($taskID);
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(!empty($_POST))
{
$this->loadModel('action');
@@ -1176,7 +1304,24 @@ class task extends control
$this->executeHooks($taskID);
if(isonlybody()) die(js::closeModal('parent.parent', 'this', "function(){parent.parent.location.reload();}"));
if(isonlybody())
{
$task = $this->task->getById($taskID);
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent', 'this', "function(){parent.parent.location.reload();}"));
}
}
if(defined('RUN_MODE') && RUN_MODE == 'api')
{
return $this->send(array('status' => 'success', 'data' => $taskID));
@@ -1293,6 +1438,9 @@ class task extends control
{
$this->commonAction($taskID);
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(!empty($_POST))
{
$this->loadModel('action');
@@ -1307,7 +1455,23 @@ class task extends control
$this->executeHooks($taskID);
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
if(isonlybody())
{
$task = $this->task->getById($taskID);
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
@@ -1330,6 +1494,9 @@ class task extends control
{
$this->commonAction($taskID);
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
if(!empty($_POST))
{
$this->loadModel('action');
@@ -1344,8 +1511,24 @@ class task extends control
$this->executeHooks($taskID);
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
die(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
if(isonlybody())
{
$task = $this->task->getById($taskID);
$execution = $this->execution->getByID($task->execution);
if($execution->type == 'kanban')
{
$regionID = isset($output['regionID']) ? $output['regionID'] : 0;
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', $regionID);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData, $regionID)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
return print(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
if(!empty($this->view->task->team))
+1 -1
View File
@@ -37,7 +37,7 @@
<?php endif;?>
</h2>
</div>
<form method='post' target='hiddenwin' onsubmit='return checkLeft();'>
<form method='post' target='hiddenwin' <?php if($app->rawMethod == 'start') echo "onsubmit='return checkLeft();'"?>>
<table class='table table-form'>
<tr>
<th class='w-90px'><?php echo $lang->task->assignedTo;?></th>
+13 -2
View File
@@ -517,8 +517,19 @@ class testcase extends control
if(!empty($_POST))
{
$caseIDList = $this->testcase->batchCreate($productID, $branch, $storyID);
if(dao::isError()) die(js::error(dao::getError()));
if(isonlybody()) die(js::closeModal('parent.parent', 'this'));
if(dao::isError()) return print(js::error(dao::getError()));
if(isonlybody())
{
$execution = $this->execution->getByID($this->session->execution);
if($this->app->tab == 'execution' and $execution->type == 'kanban')
{
return print(js::closeModal('parent.parent', ''));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
}
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'idList' => $caseIDList));
+1 -1
View File
@@ -58,7 +58,7 @@ $lang->testreport->bugOpenedByGroups = 'Nach Ersteller';
$lang->testreport->bugResolvedByGroups = 'Nach Löser';
$lang->testreport->bugResolutionGroups = 'Nach Lösung';
$lang->testreport->bugModuleGroups = 'Nach Modul';
$lang->testreport->bugStageGroups = 'Bug importance stage distribution';
$lang->testreport->bugStageGroups = 'Bug Priority Distribution';
$lang->testreport->bugHandleGroups = 'Distribution of daily bug processing';
$lang->testreport->legacyBugs = 'Legacy Bugs';
$lang->testreport->bugConfirmedRate = 'Bestätigte Bugs Rate (Lösung ist gelöst oder verschoben / Status ist gelöst oder Geschlossen)';
+1 -1
View File
@@ -59,7 +59,7 @@ $lang->testreport->bugOpenedByGroups = 'Bug ReportedBy Distribution';
$lang->testreport->bugResolvedByGroups = 'Bug ResolvedBy Distribution';
$lang->testreport->bugResolutionGroups = 'Bug Resolution Distribution';
$lang->testreport->bugModuleGroups = 'Bug Module Distribution';
$lang->testreport->bugStageGroups = 'Bug importance stage distribution';
$lang->testreport->bugStageGroups = 'Bug Priority Distribution';
$lang->testreport->bugHandleGroups = 'Distribution of daily bug processing';
$lang->testreport->legacyBugs = 'Left Bugs';
$lang->testreport->bugConfirmedRate = 'Confirmed-Bug Rate (Resolution is fixed or postponed / status is resolved or closed)';
+1 -1
View File
@@ -58,7 +58,7 @@ $lang->testreport->bugOpenedByGroups = 'Distribution Bug Signalé par';
$lang->testreport->bugResolvedByGroups = 'Distribution Bug Résolu par';
$lang->testreport->bugResolutionGroups = 'Distribution Bug Résolution';
$lang->testreport->bugModuleGroups = 'Distribution Bug Module';
$lang->testreport->bugStageGroups = 'Bug importance stage distribution';
$lang->testreport->bugStageGroups = 'Bug Priority Distribution';
$lang->testreport->bugHandleGroups = 'Distribution of daily bug processing';
$lang->testreport->legacyBugs = 'Bugs Restants';
$lang->testreport->bugConfirmedRate = 'Taux de Bugs confirmés (Résolution est corrigée ou reportée / statut est résolu ou fermé)';
+1 -1
View File
@@ -58,7 +58,7 @@ $lang->testreport->bugOpenedByGroups = 'Phân chia người báo cáo Bug';
$lang->testreport->bugResolvedByGroups = 'Phân chia người giải quyết Bug';
$lang->testreport->bugResolutionGroups = 'Phân chia giải pháp Bug';
$lang->testreport->bugModuleGroups = 'Phân chia Module Bug';
$lang->testreport->bugStageGroups = 'Bug importance stage distribution';
$lang->testreport->bugStageGroups = 'Bug Priority Distribution';
$lang->testreport->bugHandleGroups = 'Distribution of daily bug processing';
$lang->testreport->legacyBugs = 'Bug còn lại';
$lang->testreport->bugConfirmedRate = 'Đánh giá Bug đã xác nhận (Nghị quyết đã ban hành hoặc tạm hoãn / tình trạng được giải quyết hoặc đóng)';
+1 -1
View File
@@ -179,7 +179,7 @@ $lang->testtask->report->charts['bugOpenedByGroups'] = 'Bugersteller Bericht'
$lang->testtask->report->charts['bugResolvedByGroups'] = 'Gelöst von Bericht';
$lang->testtask->report->charts['bugResolutionGroups'] = 'Lösungsbersicht';
$lang->testtask->report->charts['bugModuleGroups'] = 'Bug Modul Bericht';
$lang->testtask->report->charts['bugStageGroups'] = 'Bug importance stage distribution';
$lang->testtask->report->charts['bugStageGroups'] = 'Bug Priority Distribution';
$lang->testtask->report->charts['bugHandleGroups'] = 'Distribution of daily bug processing';
$lang->testtask->report->options = new stdclass();
+1 -1
View File
@@ -189,7 +189,7 @@ $lang->testtask->report->charts['bugOpenedByGroups'] = 'Bug ReportedBy Distri
$lang->testtask->report->charts['bugResolvedByGroups'] = 'Bug ResolvedBy Distribution';
$lang->testtask->report->charts['bugResolutionGroups'] = 'Bug Resolution Distribution';
$lang->testtask->report->charts['bugModuleGroups'] = 'Bug Module Distribution';
$lang->testtask->report->charts['bugStageGroups'] = 'Bug importance stage distribution';
$lang->testtask->report->charts['bugStageGroups'] = 'Bug Priority Distribution';
$lang->testtask->report->charts['bugHandleGroups'] = 'Distribution of daily bug processing';
$lang->testtask->report->options = new stdclass();
+1 -1
View File
@@ -179,7 +179,7 @@ $lang->testtask->report->charts['bugOpenedByGroups'] = 'Distribution signalem
$lang->testtask->report->charts['bugResolvedByGroups'] = 'Distribution Résolus par';
$lang->testtask->report->charts['bugResolutionGroups'] = 'Distribution Résolution';
$lang->testtask->report->charts['bugModuleGroups'] = 'Distribution Bug Module';
$lang->testtask->report->charts['bugStageGroups'] = 'Bug importance stage distribution';
$lang->testtask->report->charts['bugStageGroups'] = 'Bug Priority Distribution';
$lang->testtask->report->charts['bugHandleGroups'] = 'Distribution of daily bug processing';
$lang->testtask->report->options = new stdclass();
+1 -1
View File
@@ -179,7 +179,7 @@ $lang->testtask->report->charts['bugOpenedByGroups'] = 'Phân chia người b
$lang->testtask->report->charts['bugResolvedByGroups'] = 'Phân chia người giải quyết Bug';
$lang->testtask->report->charts['bugResolutionGroups'] = 'Phân chia giải pháp Bug';
$lang->testtask->report->charts['bugModuleGroups'] = 'Phân chia Module Bug';
$lang->testtask->report->charts['bugStageGroups'] = 'Bug importance stage distribution';
$lang->testtask->report->charts['bugStageGroups'] = 'Bug Priority Distribution';
$lang->testtask->report->charts['bugHandleGroups'] = 'Distribution of daily bug processing';
$lang->testtask->report->options = new stdclass();
+1 -1
View File
@@ -51,7 +51,7 @@ class todoModel extends model
if($todo->pri == 'low') $todo->pri = 3;
}
if($todo->type != 'custom')
if($todo->type != 'custom' and $todo->idvalue)
{
$type = $todo->type;
$object = $this->loadModel($type)->getByID($this->post->$type);
+8 -1
View File
@@ -22,8 +22,15 @@
<?php endif;?>
</div>
<?php if($result == 'fail'):?>
<div class='modal-footer text-left'><?php echo $lang->upgrade->afterDeleted;?> <?php echo html::a('#', $this->lang->refresh, '', "class='btn btn-sm' onclick='location.reload()'");?></div>
<div class='modal-footer text-left'><?php echo $lang->upgrade->afterDeleted;?> <?php echo html::a('#', $this->lang->refresh, '', "class='btn btn-sm' onclick='refreshPage(this)'");?></div>
<?php endif;?>
</div>
</div>
<script>
function refreshPage(obj)
{
$(obj).attr('disabled', true);
location.reload()
}
</script>
<?php include '../../common/view/footer.lite.html.php';?>
File diff suppressed because one or more lines are too long
@@ -1,4 +1,8 @@
<?php
$lang->setting->common = 'Settings';
$lang->setting->xuanxuan = 'Client';
$lang->setting->downloadXXD = 'Download XXD';
<?php
$lang->setting->common = 'Settings';
$lang->setting->xuanxuan = 'Client';
$lang->setting->downloadXXD = 'Download XXD';
$lang->setting->langs['zh-cn'] = 'Simplified Chinese';
$lang->setting->langs['zh-tw'] = 'Traditional Chinese';
$lang->setting->langs['en'] = 'English';
@@ -1,4 +1,7 @@
<?php
$lang->setting->common = '设置';
$lang->setting->xuanxuan = '客户端集成';
$lang->setting->downloadXXD = '下载喧喧服务端';
$lang->setting->common = '设置';
$lang->setting->xuanxuan = '客户端集成';
$lang->setting->downloadXXD = '下载喧喧服务端';
$lang->setting->langs['zh-cn'] = '简体';
$lang->setting->langs['zh-tw'] = '繁體';
$lang->setting->langs['en'] = 'English';
@@ -44,7 +44,7 @@
</tr>
<tr>
<th><?php echo $lang->im->backendLang;?></th>
<td><?php echo $type == 'edit' ? html::select('backendLang', $config->langs, $config->xuanxuan->backendLang, "class='form-control'") : zget($config->langs, $config->xuanxuan->backendLang, '');?></td>
<td><?php echo $type == 'edit' ? html::select('backendLang', $config->langs, $config->xuanxuan->backendLang, "class='form-control'") : zget($lang->setting->langs, $config->xuanxuan->backendLang, '');?></td>
<td></td>
</tr>
<tr>