Merge branch 'sprint/zentaopms230'

This commit is contained in:
wangyidong
2022-09-01 13:28:26 +08:00
47 changed files with 1591 additions and 1099 deletions
+2
View File
@@ -224,6 +224,7 @@ $config->openMethods[] = 'personnel.unbindwhitelist';
$config->openMethods[] = 'tree.viewhistory';
$config->openMethods[] = 'doc.createbasicinfo';
$config->openMethods[] = 'project.createguide';
$config->openMethods[] = 'task.editteam';
/* Define the tables. */
define('TABLE_COMPANY', '`' . $config->db->prefix . 'company`');
@@ -265,6 +266,7 @@ define('TABLE_PROJECT', '`' . $config->db->prefix . 'project`');
define('TABLE_EXECUTION', '`' . $config->db->prefix . 'project`');
define('TABLE_TASK', '`' . $config->db->prefix . 'task`');
define('TABLE_TASKSPEC', '`' . $config->db->prefix . 'taskspec`');
define('TABLE_TASKTEAM', '`' . $config->db->prefix . 'taskteam`');
define('TABLE_TEAM', '`' . $config->db->prefix . 'team`');
define('TABLE_PROJECTADMIN', '`' . $config->db->prefix . 'projectadmin`');
define('TABLE_PROJECTPRODUCT','`' . $config->db->prefix . 'projectproduct`');
+13
View File
@@ -0,0 +1,13 @@
CREATE TABLE `zt_taskteam` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`task` mediumint(8) unsigned NOT NULL,
`account` char(30) NOT NULL,
`estimate` decimal(12,2) NOT NULL,
`consumed` decimal(12,2) NOT NULL,
`left` decimal(12,2) NOT NULL,
`transfer` char(30) NOT NULL,
`status` enum('wait','doing','done') NOT NULL DEFAULT 'wait',
`order` tinyint(3) NOT NULL,
PRIMARY KEY (`id`),
KEY `task` (`task`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+14
View File
@@ -1606,6 +1606,20 @@ CREATE TABLE IF NOT EXISTS `zt_taskspec` (
`deadline` date NOT NULL,
UNIQUE KEY `task` (`task`,`version`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_taskteam`;
CREATE TABLE `zt_taskteam` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`task` mediumint(8) unsigned NOT NULL,
`account` char(30) NOT NULL,
`estimate` decimal(12,2) NOT NULL,
`consumed` decimal(12,2) NOT NULL,
`left` decimal(12,2) NOT NULL,
`transfer` char(30) NOT NULL,
`status` enum('wait','doing','done') NOT NULL DEFAULT 'wait',
`order` tinyint(3) NOT NULL,
PRIMARY KEY (`id`),
KEY `task` (`task`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_team`;
CREATE TABLE IF NOT EXISTS `zt_team` (
`id` mediumint(8) unsigned NOT NULL auto_increment,
Regular → Executable
+8 -12
View File
@@ -1206,6 +1206,8 @@ class block extends control
->andWhere('parent')->lt(1)
->fetch();
$this->weekly->save($this->session->project, $date);
$this->view->pv = $this->weekly->getPV($this->session->project, $today);
$this->view->ev = $this->weekly->getEV($this->session->project, $today);
$this->view->ac = $this->weekly->getAC($this->session->project, $today);
@@ -1301,23 +1303,17 @@ class block extends control
$projectID = $this->session->project;
$project = $this->loadModel('project')->getByID($projectID);
$begin = $project->begin;
$today = helper::today();
$end = date('Y-m-d', strtotime($today));
$projectWeekly = $this->dao->select('*')->from(TABLE_WEEKLYREPORT)->where('project')->eq($projectID)->orderBy('weekStart_asc')->fetchAll('weekStart');
$charts['PV'] = '[';
$charts['EV'] = '[';
$charts['AC'] = '[';
$i = 1;
while($begin < $end)
foreach($projectWeekly as $weekStart => $data)
{
$charts['labels'][] = $this->lang->block->time . $i . $this->lang->block->month;
$charts['PV'] .= $this->weekly->getPV($projectID, $begin) . ',';
$charts['EV'] .= $this->weekly->getEV($projectID, $begin) . ',';
$charts['AC'] .= $this->weekly->getAC($projectID, $begin) . ',';
$stageEnd = $this->weekly->getThisSunday($begin);
$begin = date('Y-m-d', strtotime("$stageEnd + 30 day"));
$i ++;
$charts['labels'][] = $weekStart;
$charts['PV'] .= $data->pv . ',';
$charts['EV'] .= $data->ev . ',';
$charts['AC'] .= $data->ac . ',';
}
$charts['PV'] .= ']';
+1 -1
View File
@@ -171,7 +171,7 @@ class blockModel extends model
$tasks = $this->dao->select("count(t1.id) as tasks, count(if(t1.status = 'done', 1, null)) as doneTasks")->from(TABLE_TASK)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on("t1.project = t2.id")
->leftJoin(TABLE_EXECUTION)->alias('t3')->on("t1.execution = t3.id")
->leftJoin(TABLE_TEAM)->alias('t4')->on("t4.root = t1.id and t4.type = 'task' and t4.account = '{$this->app->user->account}'")
->leftJoin(TABLE_TASKTEAM)->alias('t4')->on("t4.task = t1.id and t4.account = '{$this->app->user->account}'")
->where("(t1.assignedTo = '{$this->app->user->account}' or (t1.mode = 'multi' and t4.`account` = '{$this->app->user->account}') )")
->andWhere('(t2.status')->ne('suspended')
->orWhere('t3.status')->ne('suspended')
+1 -1
View File
@@ -18,7 +18,7 @@ $(document).ready(function()
var $tbody = $(this);
$tbody.sortable(
{
selector: 'tr',
selector: typeof(sortSelector) == 'undefined' ? 'tr' : sortSelector,
dragCssClass: 'drag-row',
trigger: $tbody.find('.sort-handler').length ? '.sort-handler' : null,
finish: function(e)
-2
View File
@@ -71,7 +71,6 @@ $config->execution->search['fields']['canceledBy'] = $lang->task->canceledBy
$config->execution->search['fields']['lastEditedBy'] = $lang->task->lastEditedBy;
$config->execution->search['fields']['mailto'] = $lang->task->mailto;
$config->execution->search['fields']['finishedList'] = $lang->task->finishedList;
$config->execution->search['fields']['openedDate'] = $lang->task->openedDate;
$config->execution->search['fields']['deadline'] = $lang->task->deadline;
@@ -107,7 +106,6 @@ $config->execution->search['params']['cancelBy'] = array('operator' => '='
$config->execution->search['params']['lastEditedBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
$config->execution->search['params']['mailto'] = array('operator' => 'include', 'control' => 'select', 'values' => 'users');
$config->execution->search['params']['finishedList'] = array('operator' => 'include', 'control' => 'select', 'values' => 'users');
$config->execution->search['params']['openedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->execution->search['params']['deadline'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
+6 -27
View File
@@ -2343,7 +2343,8 @@ class executionModel extends model
{
$this->loadModel('task');
$tasks = $this->dao->select('id,execution,assignedTo,story,consumed,status')->from(TABLE_TASK)->where('id')->in($this->post->tasks)->fetchAll('id');
$execution = $this->getByID($executionID);
$tasks = $this->dao->select('id,execution,assignedTo,story,consumed,status')->from(TABLE_TASK)->where('id')->in($this->post->tasks)->fetchAll('id');
foreach($tasks as $task)
{
/* Save the assignedToes and stories, should linked to execution. */
@@ -2351,8 +2352,9 @@ class executionModel extends model
$stories[$task->story] = $task->story;
$data = new stdclass();
$data->project = $execution->project;
$data->execution = $executionID;
$data->status = $task->consumed > 0 ? 'doing' : 'wait';
$data->status = $task->consumed > 0 ? 'doing' : 'wait';
if($task->status == 'cancel')
{
@@ -2931,29 +2933,6 @@ class executionModel extends model
->fetchGroup('root');
}
/**
* Get the skip members of the team.
*
* @param array $teams
* @param string $begin
* @param string $end
* @access public
* @return array
*/
public function getTeamSkip($teams, $begin, $end)
{
$members = array();
foreach($teams as $account => $team)
{
if($account == $end) break;
if(!empty($begin) and $account != $begin and empty($members)) continue;
$members[$account] = $team;
}
return $members;
}
/**
* Get teams which can be imported.
*
@@ -3669,7 +3648,7 @@ class executionModel extends model
if(empty($tasks)) return array();
$taskTeam = $this->dao->select('*')->from(TABLE_TEAM)->where('root')->in(array_keys($tasks))->andWhere('type')->eq('task')->fetchGroup('root');
$taskTeam = $this->dao->select('*')->from(TABLE_TASKTEAM)->where('task')->in(array_keys($tasks))->fetchGroup('task');
if(!empty($taskTeam))
{
foreach($taskTeam as $taskID => $team) $tasks[$taskID]->team = $team;
@@ -4642,7 +4621,7 @@ class executionModel extends model
echo '<td class="c-actions">';
common::printIcon('execution', 'start', "executionID={$execution->id}", $execution, 'list', '', '', 'iframe', true);
$class = !empty($execution->children) ? 'disabled' : '';
common::printIcon('task', 'create', "executionID={$execution->id}", $execution, 'list', '', '', $class, false, "data-app='execution'");
common::printIcon('task', 'create', "executionID={$execution->id}", '', 'list', '', '', $class, false, "data-app='execution'");
if($execution->type == 'stage')
{
+16 -6
View File
@@ -1534,19 +1534,29 @@ class kanbanModel extends model
if($browseType == 'bug') $cardList = $this->loadModel('bug')->getExecutionBugs($executionID);
if($browseType == 'task') $cardList = $this->loadModel('execution')->getKanbanTasks($executionID);
$multiTasks = array();
if($browseType == 'task' and $groupBy == 'assignedTo')
{
foreach($cardList as $id => $task)
{
if($task->mode == 'multi')
{
$task->team = $this->dao->select('t1.account,t2.realname')->from(TABLE_TEAM)->alias('t1')
->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account')
->where('t1.root')->eq($id)->andWhere('t1.type')->eq('task')->orderBy('t1.order')->fetchPairs('account');
}
if($task->mode == 'multi') $multiTasks[$id] = $task;
}
}
$taskTeams = $this->dao->select('t1.account,t1.task,t2.realname')->from(TABLE_TASKTEAM)->alias('t1')
->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account')
->where('t1.task')->in(array_keys($multiTasks))
->orderBy('t1.order')
->fetchGroup('task', 'account');
foreach($multiTasks as $taskID => $task)
{
if(!isset($taskTeams[$taskID])) continue;
$teamPairs = array();
foreach($taskTeams[$taskID] as $account => $team) $teamPairs[$account] = $team->realname;
$task->team = $teamPairs;
}
/* Get objects cards menus. */
if($browseType == 'story') $storyCardMenu = $this->getKanbanCardMenu($executionID, $cardList, 'story');
if($browseType == 'bug') $bugCardMenu = $this->getKanbanCardMenu($executionID, $cardList, 'bug');
+3 -2
View File
@@ -588,6 +588,7 @@ class myModel extends model
->leftJoin(TABLE_EXECUTION)->alias('t2')->on("t1.execution = t2.id")
->leftJoin(TABLE_STORY)->alias('t3')->on('t1.story = t3.id')
->leftJoin(TABLE_PROJECT)->alias('t4')->on("t1.project = t4.id")
->leftJoin(TABLE_TASKTEAM)->alias('t5')->on("t1.id = t5.task")
->where($query)
->andWhere('t1.deleted')->eq(0)
->andWhere('t2.deleted')->eq(0)
@@ -598,7 +599,7 @@ class myModel extends model
->orWhere('t1.closedBy')->eq($account)
->orWhere('t1.canceledBy')->eq($account)
->orWhere('t1.finishedby', 1)->eq($account)
->orWhere('t1.finishedList')->like("%,{$account},%")
->orWhere('t5.status')->eq("done")
->orWhere('t1.id')->in($taskIDList)
->markRight(1)
->fi()
@@ -612,7 +613,7 @@ class myModel extends model
$this->loadModel('common')->saveQueryCondition($this->dao->get(), 'task', false);
$taskTeam = $this->dao->select('*')->from(TABLE_TEAM)->where('root')->in(array_keys($tasks))->andWhere('type')->eq('task')->fetchGroup('root');
$taskTeam = $this->dao->select('*')->from(TABLE_TASKTEAM)->where('task')->in(array_keys($tasks))->fetchGroup('task');
if(!empty($taskTeam))
{
foreach($taskTeam as $taskID => $team) $tasks[$taskID]->team = $team;
+29 -20
View File
@@ -224,7 +224,7 @@ class programplanModel extends model
if(empty($selectCustom)) $selectCustom = $this->loadModel('setting')->getItem("owner={$owner}&module={$module}&section={$section}&key={$object}");
$tasks = $this->dao->select('*')->from(TABLE_TASK)->where('deleted')->eq(0)->andWhere('execution')->in($planIdList)->orderBy('execution_asc, order_asc, id_desc')->fetchAll('id');
$taskTeams = $this->dao->select('root,account')->from(TABLE_TEAM)->where('type')->eq('task')->andWhere('root')->in(array_keys($tasks))->fetchGroup('root', 'account');
$taskTeams = $this->dao->select('task,account')->from(TABLE_TASKTEAM)->where('task')->in(array_keys($tasks))->fetchGroup('task', 'account');
$users = $this->loadModel('user')->getPairs('noletter');
if($baselineID)
@@ -381,33 +381,42 @@ class programplanModel extends model
$tasksGroup = $this->dao->select('*')->from(TABLE_TASK)->where('deleted')->eq(0)->andWhere('execution')->in($planIdList)->fetchGroup('assignedTo','id');
$users = $this->loadModel('user')->getPairs('noletter');
$tasksMap = array();
$tasksMap = array();
$multiTasks = array();
foreach($tasksGroup as $group => $tasks)
{
foreach($tasks as $id => $task)
{
if($task->mode == 'multi')
{
$team = $this->dao->select('t1.*,t2.realname')->from(TABLE_TEAM)->alias('t1')
->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account')
->where('t1.root')->eq($id)->andWhere('t1.type')->eq('task')->orderBy('t1.order')->fetchAll('account');
foreach($team as $account => $member)
{
if($account == $group) continue;
if(!isset($taskGroups[$account])) $taskGroups[$account] = array();
$taskGroups[$account][$id] = clone $task;
$taskGroups[$account][$id]->id = $id . '_' . $account;
$taskGroups[$account][$id]->realID = $id;
$taskGroups[$account][$id]->assignedTo = $account;
$taskGroups[$account][$id]->realname = $member->realname;
}
}
if($task->mode == 'multi') $multiTasks[$id] = $group;
$tasksMap[$task->id] = $task;
}
}
if($multiTasks)
{
$taskTeams = $this->dao->select('t1.*,t2.realname')->from(TABLE_TASKTEAM)->alias('t1')
->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account')
->where('t1.task')->in(array_keys($multiTasks))
->orderBy('t1.order')
->fetchGroup('task', 'id');
foreach($taskTeams as $taskID => $team)
{
$group = $multiTasks[$taskID];
foreach($team as $member)
{
$account = $member->account;
if($account == $group) continue;
if(!isset($taskGroups[$account])) $taskGroups[$account] = array();
$taskGroups[$account][$taskID] = clone $tasksMap[$taskID];
$taskGroups[$account][$taskID]->id = $taskID . '_' . $account;
$taskGroups[$account][$taskID]->realID = $taskID;
$taskGroups[$account][$taskID]->assignedTo = $account;
$taskGroups[$account][$taskID]->realname = $member->realname;
}
}
}
$groupID = 0;
foreach($tasksGroup as $group => $tasks)
{
+2 -3
View File
@@ -358,10 +358,9 @@ class reportModel extends model
$taskGroups[$task->assignedTo][$task->id] = $task;
}
$multiTaskTeams = $this->dao->select('*')->from(TABLE_TEAM)->where('type')->eq('task')
->andWhere('root')->in(array_keys($allTasks))
$multiTaskTeams = $this->dao->select('*')->from(TABLE_TASKTEAM)->where('task')->in(array_keys($allTasks))
->beginIF($dept)->andWhere('account')->in(array_keys($deptUsers))->fi()
->fetchGroup('account', 'root');
->fetchGroup('account', 'task');
foreach($multiTaskTeams as $assignedTo => $multiTasks)
{
foreach($multiTasks as $task)
+41 -64
View File
@@ -719,12 +719,12 @@ class task extends control
/* Get edited tasks. */
$tasks = $this->dao->select('*')->from(TABLE_TASK)->where('id')->in($taskIDList)->fetchAll('id');
$teams = $this->dao->select('*')->from(TABLE_TEAM)->where('root')->in($taskIDList)->andWhere('type')->eq('task')->fetchGroup('root', 'account');
$teams = $this->dao->select('*')->from(TABLE_TASKTEAM)->where('task')->in($taskIDList)->fetchGroup('task', 'id');
/* Get execution teams. */
$executionIDList = array();
foreach($tasks as $task) if(!in_array($task->execution, $executionIDList)) $executionIDList[] = $task->execution;
$executionTeams = $this->dao->select('*')->from(TABLE_TEAM)->where('root')->in($executionIDList)->andWhere('type')->eq('execution')->fetchGroup('root', 'account');
$executionTeams = $this->dao->select('*')->from(TABLE_TASKTEAM)->where('task')->in($executionIDList)->fetchGroup('task', 'id');
/* Judge whether the editedTasks is too large and set session. */
$countInputVars = count($tasks) * (count(explode(',', $this->config->task->custom->batchEditFields)) + 3);
@@ -787,9 +787,9 @@ class task extends control
$this->commonAction($taskID);
$task = $this->task->getByID($taskID);
if(!empty($task->team) and $task->mode == 'multi')
if(!empty($task->team) and $task->mode == 'multi' and strpos('done,cencel,closed', $task->status) === false)
{
return $this->editTeam($executionID, $task, $kanbanGroup);
return $this->editTeam($executionID, $taskID, $kanbanGroup, $from);
}
if(!empty($_POST))
@@ -841,9 +841,9 @@ class task extends control
$members = $this->loadModel('user')->getTeamMemberPairs($executionID, 'execution', 'nodeleted');
/* Compute next assignedTo. */
if(!empty($task->team))
if(!empty($task->team) and strpos('done,cencel,closed', $task->status) === false)
{
$task->nextUser = $this->task->getNextUser(array_keys($task->team), $task->assignedTo);
$task->nextUser = $this->task->getAssignedTo4Multi($task->team, $task, 'next');
$members = $this->task->getMemberPairs($task);
}
@@ -903,7 +903,7 @@ class task extends control
if(!is_array($taskIDList)) return print(js::locate($this->createLink('execution', 'task', "executionID=$execution"), 'parent'));
$taskIDList = array_unique($taskIDList);
$muletipleTasks = $this->dao->select('root , account')->from(TABLE_TEAM)->where('type')->eq('task')->andWhere('root')->in($taskIDList)->fetchGroup('root', 'account');
$muletipleTasks = $this->dao->select('task, account')->from(TABLE_TASKTEAM)->where('task')->in($taskIDList)->fetchGroup('task', 'account');
$tasks = $this->task->getByList($taskIDList);
$this->loadModel('action');
foreach($tasks as $taskID => $task)
@@ -1098,12 +1098,15 @@ class task extends control
return print(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
$assignedTo = empty($task->assignedTo) ? $this->app->user->account : $task->assignedTo;
if(!empty($task->team)) $assignedTo = $this->task->getAssignedTo4Multi($task->team, $task);
$this->view->title = $this->view->execution->name . $this->lang->colon .$this->lang->task->start;
$this->view->position[] = $this->lang->task->start;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->members = $this->loadModel('user')->getTeamMemberPairs($task->execution, 'execution', 'nodeleted');
$this->view->assignedTo = $task->assignedTo == '' ? $this->app->user->account : $task->assignedTo;
$this->view->assignedTo = $assignedTo;
$this->display();
}
@@ -1177,6 +1180,7 @@ class task extends control
$this->view->task = $this->task->getById($taskID);
$this->view->estimates = $this->task->getTaskEstimate($taskID);
$this->view->title = $this->lang->task->record;
$this->view->users = $this->loadModel('user')->getPairs('noclosed|noletter');
$this->display();
}
@@ -1202,11 +1206,10 @@ class task extends control
return print(js::locate($url, 'parent'));
}
$estimate = $this->task->getEstimateById($estimateID);
$this->view->title = $this->lang->task->editEstimate;
$this->view->position[] = $this->lang->task->editEstimate;
$this->view->estimate = $estimate;
$this->view->task = $this->task->getById($estimate->task);
$this->display();
}
@@ -1220,35 +1223,21 @@ class task extends control
*/
public function deleteEstimate($estimateID, $confirm = 'no')
{
$estimate = $this->task->getEstimateById($estimateID);
$task = $this->task->getById($estimate->task);
if($confirm == 'no' and $task->consumed - $estimate->consumed != 0)
if($confirm == 'no')
{
return print(js::confirm($this->lang->task->confirmDeleteEstimate, $this->createLink('task', 'deleteEstimate', "estimateID=$estimateID&confirm=yes")));
}
elseif($confirm == 'no' and $task->consumed - $estimate->consumed == 0)
{
return print(js::confirm($this->lang->task->confirmDeleteLastEstimate, $this->createLink('task', 'deleteEstimate', "estimateID=$estimateID&confirm=yes")));
}
else
{
$estimate = $this->task->getEstimateById($estimateID);
$task = $this->task->getById($estimate->task);
$changes = $this->task->deleteEstimate($estimateID);
if(dao::isError()) return print(js::error(dao::getError()));
$actionID = $this->loadModel('action')->create('task', $estimate->task, 'DeleteEstimate');
$this->action->logHistory($actionID, $changes);
if($task->consumed - $estimate->consumed == 0)
{
$actionID = $this->loadModel('action')->create('task', $estimate->task, 'Adjusttasktowait');
}
if($task->consumed - $estimate->consumed == 0)
{
return print(js::reload('parent.parent'));
}
else
{
return print(js::reload('parent'));
}
return print(js::reload('parent'));
}
}
@@ -1346,21 +1335,10 @@ class task extends control
if(!empty($task->team))
{
$teams = array_keys($task->team);
$task->nextBy = $this->task->getNextUser($teams, $this->app->user->account);
$task->myConsumed = isset($task->team[$this->app->user->account]) ? $task->team[$this->app->user->account]->consumed : 0;
$lastAccount = end($teams);
$finishedUsers = $this->task->getFinishedUsers($taskID, $teams);
if(($lastAccount != $task->assignedTo and $task->mode == 'linear') or ($task->mode == 'multi' and count($teams) != count($finishedUsers)))
{
$members = $this->task->getMemberPairs($task);
}
else
{
$task->nextBy = $task->openedBy;
}
$task->nextBy = $this->task->getAssignedTo4Multi($task->team, $task, 'next');
$task->myConsumed = 0;
$currentTeam = $this->task->getTeamByAccount($task->team);
if($currentTeam) $task->myConsumed = $currentTeam->consumed;
}
$this->view->title = $this->view->execution->name . $this->lang->colon .$this->lang->task->finish;
@@ -1817,14 +1795,8 @@ class task extends control
return print(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
if(!empty($this->view->task->team))
{
$members = array();
foreach($this->view->task->team as $account => $member) $members[$account] = zget($this->view->members, $account);
$this->view->members = $members;
}
if(!isset($this->view->members[$this->view->task->finishedBy])) $this->view->members[$this->view->task->finishedBy] = $this->view->task->finishedBy;
$this->view->title = $this->view->execution->name . $this->lang->colon . $this->lang->task->activate;
$this->view->position[] = $this->lang->task->activate;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
@@ -2107,10 +2079,7 @@ class task extends control
}
/* Get team for multiple task. */
$taskTeam = $this->dao->select('*')->from(TABLE_TEAM)
->where('root')->in(array_keys($tasks))
->andWhere('type')->eq('task')
->fetchGroup('root');
$taskTeam = $this->dao->select('*')->from(TABLE_TASKTEAM)->where('task')->in(array_keys($tasks))->fetchGroup('task');
/* Process multiple task info. */
if(!empty($taskTeam))
@@ -2332,14 +2301,15 @@ class task extends control
* Update assign of multi task.
*
* @param int $requestID
* @param object $task
* @param object $taskID
* @param string $kanbanGroup
* @param string $from
* @access public
* @return void
*/
public function editTeam($executionID, $task, $kanbanGroup = 'default')
public function editTeam($executionID, $taskID, $kanbanGroup = 'default', $from = '')
{
$taskID = $task->id;
$task = $this->task->getById($taskID);
$this->commonAction($taskID);
if(!empty($_POST))
@@ -2361,9 +2331,18 @@ class task extends control
if($this->viewType == 'json' or (defined('RUN_MODE') && RUN_MODE == 'api')) return $this->send(array('result' => 'success'));
if(isonlybody())
{
$task = $this->task->getById($taskID);
$execution = $this->execution->getByID($task->execution);
if(($this->app->tab == 'execution' or $this->config->vision == 'lite') and $this->app->tab == 'execution')
if(($this->app->tab == 'execution' or ($this->config->vision == 'lite' and $this->app->tab == 'project' and $this->session->kanbanview == 'kanban')) and $execution->type == 'kanban')
{
$rdSearchValue = $this->session->rdSearchValue ? $this->session->rdSearchValue : '';
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $execLaneType, 'id_desc', 0, $execGroupBy, $rdSearchValue);
$kanbanData = json_encode($kanbanData);
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
if($from == 'taskkanban')
{
$rdSearchValue = $this->session->rdSearchValue ? $this->session->rdSearchValue : '';
$kanbanData = $this->loadModel('kanban')->getRDKanban($task->execution, $this->session->execLaneType ? $this->session->execLaneType : 'all', 'id_desc', 0, $kanbanGroup, $rdSearchValue);
@@ -2371,10 +2350,8 @@ class task extends control
return print(js::closeModal('parent.parent', '', "parent.parent.updateKanban($kanbanData)"));
}
else
{
return print(js::closeModal('parent.parent', 'this'));
}
return print(js::closeModal('parent.parent', 'this'));
}
return print(js::locate($this->createLink('task', 'view', "taskID=$taskID"), 'parent'));
}
+6
View File
@@ -1 +1,7 @@
.table-recorded thead{background: rgb(245 245 245);}
.form-condensed .table-form {margin-bottom: 20px;}
.hours {display: flex; float: left; transform: translate(0, 50%); margin: 0 0 0 10px;}
.estimateTotally, .consumedTotally {border-radius: 9px; padding: 3px 7px; margin: 0 5px 0 5px; min-width: 18px;}
.consumedTotally {background: #EAF3FF; color: #2B80FF;}
.estimateTotally {background: #FFEFEF; color: #FF6262;}
.nav > li.divider {margin: 0 10px 0 5px; background-color: #000; opacity: 0.06; width: 1px ; height: 15px; padding: 0 !important;}
+109
View File
@@ -0,0 +1,109 @@
$('#confirmButton').click(function()
{
var memberCount = '';
var totalEstimate = 0;
var totalConsumed = oldConsumed;
var totalLeft = 0;
var error = false;
$('select[name^=team]').each(function()
{
if($(this).val() == '') return;
memberCount++;
var $tr = $(this).closest('tr');
var account = $(this).find('option:selected').text();
estimate = parseFloat($tr.find('[name^=teamEstimate]').val());
if(!isNaN(estimate)) totalEstimate += estimate;
if(isNaN(estimate) || estimate == 0)
{
bootbox.alert(account + ' ' + estimateNotEmpty);
error = true;
return false;
}
consumed = parseFloat($tr.find('[name^=teamConsumed]').val());
if(!isNaN(consumed)) totalConsumed += consumed;
left = parseFloat($tr.find('[name^=teamLeft]').val());
if(!isNaN(left)) totalLeft += left;
if(!$tr.hasClass('member-done') && (isNaN(left) || left == 0))
{
bootbox.alert(account + ' ' + leftNotEmpty);
error = true;
return false;
}
if(estimate == 0 || isNaN(estimate))
{
$(this).val('').trigger("chosen:updated");
bootbox.alert(estimateNotEmpty);
error = true;
return false;
}
})
if(error) return false;
if(memberCount < 2)
{
bootbox.alert(teamMemberError);
return false;
}
$('#left').val(totalLeft);
updateAssignedTo();
$('.close').click();
});
/**
* Update assignedTo.
*
* @access public
* @return void
*/
function updateAssignedTo()
{
var html = '';
var multiple = $('#multiple').prop('checked');
var assignedTo = $('#assignedTo').val();
if(multiple)
{
var isTeamMember = false;
var mode = $('#mode').val();
$('select[name^=team]').each(function()
{
if($(this).find('option:selected').text() == '') return;
if($(this).val() == currentUser) isTeamMember = true;
var account = $(this).find('option:selected').val();
var realName = $(this).find('option:selected').text();
var selected = account == assignedTo ? 'selected' : '';
html += "<option value='" + account + "' title='" + realName + "'" + selected + ">" + realName + "</option>";
});
if(mode == 'multi' && isTeamMember && mode != 'linear')
{
$('[name=assignedTo]').removeAttr('disabled').trigger('chosen:updated');
}
else
{
$('[name=assignedTo]').attr('disabled', 'disabled').trigger('chosen:updated');
}
}
else
{
for(key in members)
{
var selected = key == assignedTo ? 'selected' : '';
html += "<option value='" + key + "' title='" + members[key] + "'" + selected + ">" + members[key] + "</option>";
}
}
$('#assignedTo').html(html);
if(multiple && mode == 'linear' && $('#modalTeam tr.member-doing').length == 0 && $('#modalTeam tr.member-wait').length >= 1) $('[name=assignedTo]').val($('#modalTeam tr.member-wait:first').find('select[name^=team]:first').val());
$('#assignedTo').trigger('chosen:updated');
}
+12 -67
View File
@@ -536,44 +536,6 @@ $(document).ready(function()
$('#dataPlanGroup').fixInputGroup();
});
/* Init task team manage dialog */
var $taskTeamEditor = $('#taskTeamEditor').batchActionForm(
{
idStart: 0,
idEnd: 5,
chosen: true,
datetimepicker: false,
colorPicker: false,
});
var taskTeamEditor = $taskTeamEditor.data('zui.batchActionForm');
var adjustButtons = function()
{
var $deleteBtn = $taskTeamEditor.find('.btn-delete');
if ($deleteBtn.length == 1) $deleteBtn.addClass('disabled').attr('disabled', 'disabled');
};
$taskTeamEditor.on('click', '.btn-add', function()
{
var $newRow = taskTeamEditor.createRow(null, $(this).closest('tr'));
$newRow.addClass('highlight');
setTimeout(function()
{
$newRow.removeClass('highlight');
}, 1600);
adjustButtons();
}).on('click', '.btn-delete', function()
{
var $row = $(this).closest('tr');
$row.addClass('highlight').fadeOut(700, function()
{
$row.remove();
adjustButtons();
});
});
adjustButtons();
$('#showAllModule').change(function()
{
var executionID = $('#execution').val();
@@ -604,45 +566,28 @@ $(document).on('click', '#testStory_chosen', function()
$obj.trigger("chosen:updated");
})
$('#modalTeam .btn').click(function()
$('#modalTeam tfoot .btn').click(function()
{
var team = '';
var time = 0;
var error = false;
/* Unique team. */
$('select[name^=team]').each(function(i)
{
value = $(this).val();
if(value == '') return;
$('select[name^=team]').each(function(j)
{
if(i <= j) return;
if(value == $(this).val()) $(this).closest('tr').addClass('hidden');
})
})
$('select[name^=team]').closest('tr.hidden').remove();
var mode = $('#mode').val();
$('select[name^=team]').each(function()
{
if($(this).val() == '') return;
var tr = $(this).closest('tr');
var account = $(this).find('option:selected').text();
if(account != '')
{
team += ' ' + account;
}
team += ' ' + account;
estimate = parseFloat($(this).parents('td').next('td').find('[name^=teamEstimate]').val());
if(!isNaN(estimate))
if(!isNaN(estimate) && estimate > 0) time += estimate;
if(account != '' && (isNaN(estimate) || estimate == 0))
{
time += estimate;
}
var requiredFieldList = ',' + requiredFields + ',';
if(account && requiredFieldList.indexOf(',estimate,') >= 0 && (estimate == 0 || isNaN(estimate)))
{
alert(estimateNotEmpty);
error = true;
return false;
bootbox.alert(account + ' ' + estimateNotEmpty);
error = true;
return false;
}
});
@@ -650,7 +595,7 @@ $('#modalTeam .btn').click(function()
var teamList = team.split(" ");
if(teamList.length <= 2)
{
alert(teamMemberError);
bootbox.alert(teamMemberError);
return false;
}
else
+27 -96
View File
@@ -70,76 +70,6 @@ function setPreview(){}
$(document).ready(function()
{
/* show team menu. */
$('[name=multiple]').change(function()
{
var checked = $(this).prop('checked');
if(checked)
{
$('#teamTr').removeClass('hidden');
$('.modeBox').removeClass('hidden');
$('#mode').removeAttr('disabled').trigger('chosen:updated');
$('#parent').val('');
$('#parent').trigger('chosen:updated');
$('#parent').closest('tr').addClass('hidden');
$('#estimate').attr('disabled', 'disabled');
$('#left').attr('disabled', 'disabled');
var mode = $('#mode').val();
if((mode == 'linear' && currentUser != oldAssignedTo) || !team[currentUser]) $('[name=assignedTo]').attr('disabled', 'disabled').trigger('chosen:updated');
}
else
{
$('#teamTr').addClass('hidden');
$('.modeBox').addClass('hidden');
$('#mode').attr('disabled', 'disabled').trigger('chosen:updated');
$('#parent').closest('tr').removeClass('hidden');
$('#estimate').removeAttr('disabled');
$('#left').removeAttr('disabled');
$('[name=assignedTo]').removeAttr('disabled').trigger('chosen:updated');
}
updateAssignedTo();
});
/* Init task team manage dialog */
var $taskTeamEditor = $('#taskTeamEditor').batchActionForm(
{
idStart: 0,
idEnd: newRowCount - 1,
chosen: true,
datetimepicker: false,
colorPicker: false,
});
var taskTeamEditor = $taskTeamEditor.data('zui.batchActionForm');
var adjustButtons = function()
{
var $deleteBtn = $taskTeamEditor.find('.btn-delete');
if ($deleteBtn.length == 1) $deleteBtn.addClass('disabled').attr('disabled', 'disabled');
};
$taskTeamEditor.on('click', '.btn-add', function()
{
var $newRow = taskTeamEditor.createRow(null, $(this).closest('tr'));
$newRow.addClass('highlight');
setTimeout(function()
{
$newRow.removeClass('highlight');
}, 1600);
adjustButtons();
}).on('click', '.btn-delete', function()
{
var $row = $(this).closest('tr');
$row.addClass('highlight').fadeOut(700, function()
{
$row.remove();
adjustButtons();
});
});
adjustButtons();
$('#showAllModule').change(function()
{
var moduleID = $('#moduleIdBox #module').val();
@@ -153,20 +83,6 @@ $(document).ready(function()
$('#confirmButton').click(function()
{
/* Unique team. */
$('select[name^=team]').each(function(i)
{
value = $(this).val();
if(value == '') return;
$('select[name^=team]').each(function(j)
{
if(i <= j) return;
if(value == $(this).val()) $(this).closest('tr').addClass('hidden');
})
});
$('select[name^=team]').closest('tr.hidden').remove();
var memberCount = '';
var totalEstimate = 0;
var totalConsumed = oldConsumed;
@@ -174,24 +90,38 @@ $('#confirmButton').click(function()
var error = false;
$('select[name^=team]').each(function()
{
if($(this).find('option:selected').text() == '') return;
if($(this).val() == '') return;
memberCount++;
estimate = parseFloat($(this).parents('td').next('td').find('[name^=teamEstimate]').val());
if(!isNaN(estimate)) totalEstimate += estimate;
var $tr = $(this).closest('tr');
var account = $(this).find('option:selected').text();
consumed = parseFloat($(this).parents('td').next('td').find('[name^=teamConsumed]').val());
estimate = parseFloat($tr.find('[name^=teamEstimate]').val());
if(!isNaN(estimate)) totalEstimate += estimate;
if(isNaN(estimate) || estimate == 0)
{
bootbox.alert(account + ' ' + estimateNotEmpty);
error = true;
return false;
}
consumed = parseFloat($tr.find('[name^=teamConsumed]').val());
if(!isNaN(consumed)) totalConsumed += consumed;
left = parseFloat($(this).parents('td').next('td').find('[name^=teamLeft]').val());
left = parseFloat($tr.find('[name^=teamLeft]').val());
if(!isNaN(left)) totalLeft += left;
if(!$tr.hasClass('member-done') && (isNaN(left) || left == 0))
{
bootbox.alert(account + ' ' + leftNotEmpty);
error = true;
return false;
}
var requiredFieldList = ',' + requiredFields + ',';
if(requiredFieldList.indexOf(',estimate,') >= 0 && (estimate == 0 || isNaN(estimate)))
if(estimate == 0 || isNaN(estimate))
{
$(this).val('').trigger("chosen:updated");
alert(estimateNotEmpty);
bootbox.alert(estimateNotEmpty);
error = true;
return false;
}
@@ -201,13 +131,13 @@ $('#confirmButton').click(function()
if(memberCount < 2)
{
alert(teamMemberError);
bootbox.alert(teamMemberError);
return false;
}
if(totalLeft == 0 && (taskStatus == 'doing' || taskStatus == 'pause'))
{
alert(totalLeftError);
bootbox.alert(totalLeftError);
return false;
}
@@ -246,13 +176,13 @@ function updateAssignedTo()
html += "<option value='" + account + "' title='" + realName + "'" + selected + ">" + realName + "</option>";
});
if(mode == 'multi' && isTeamMember)
if(mode == 'multi' && isTeamMember && mode != 'linear')
{
$('[name=assignedTo]').removeAttr('disabled').trigger('chosen:updated');
}
else
{
if(currentUser != oldAssignedTo || !isTeamMember) $('[name=assignedTo]').attr('disabled', 'disabled').trigger('chosen:updated');
$('[name=assignedTo]').attr('disabled', 'disabled').trigger('chosen:updated');
}
}
else
@@ -265,5 +195,6 @@ function updateAssignedTo()
}
$('#assignedTo').html(html);
if(multiple && mode == 'linear' && $('#modalTeam tr.member-doing').length == 0 && $('#modalTeam tr.member-wait').length >= 1) $('[name=assignedTo]').val($('#modalTeam tr.member-wait:first').find('select[name^=team]:first').val());
$('#assignedTo').trigger('chosen:updated');
}
+2 -1
View File
@@ -6,7 +6,8 @@
*/
function confirmLeft()
{
if($('#left').val() === '0') return confirm(confirmRecord);
$left = $('#left');
if(!$left.prop('readonly') && $left.val() === '0') return confirm(confirmRecord);
}
$(function()
+11 -117
View File
@@ -1,124 +1,18 @@
$(document).ready(function()
{
/* show team menu. */
$('[name=multiple]').change(function()
$('#submit').click(function()
{
var checked = $(this).prop('checked');
if(checked)
var memberCount = 0;
$('select[name^=team]').each(function()
{
$('#teamTr').removeClass('hidden');
$('.modeBox').removeClass('hidden');
$('#mode').removeAttr('disabled').trigger('chosen:updated');
$('#parent').val('');
$('#parent').trigger('chosen:updated');
$('#parent').closest('tr').addClass('hidden');
$('#estimate').attr('disabled', 'disabled');
$('#left').attr('disabled', 'disabled');
var mode = $('#mode').val();
if((mode == 'linear' && currentUser != oldAssignedTo) || !team[currentUser]) $('[name=assignedTo]').attr('disabled', 'disabled').trigger('chosen:updated');
}
else
{
$('#teamTr').addClass('hidden');
$('.modeBox').addClass('hidden');
$('#mode').attr('disabled', 'disabled').trigger('chosen:updated');
$('#parent').closest('tr').removeClass('hidden');
$('#estimate').removeAttr('disabled');
$('#left').removeAttr('disabled');
$('[name=assignedTo]').removeAttr('disabled').trigger('chosen:updated');
}
updateAssignedTo();
});
/* Init task team manage dialog */
var $taskTeamEditor = $('#taskTeamEditor').batchActionForm(
{
idStart: 0,
idEnd: newRowCount - 1,
chosen: true,
datetimepicker: false,
colorPicker: false,
});
var taskTeamEditor = $taskTeamEditor.data('zui.batchActionForm');
var adjustButtons = function()
{
var $deleteBtn = $taskTeamEditor.find('.btn-delete');
if ($deleteBtn.length == 1) $deleteBtn.addClass('disabled').attr('disabled', 'disabled');
};
$taskTeamEditor.on('click', '.btn-add', function()
{
var $newRow = taskTeamEditor.createRow(null, $(this).closest('tr'));
$newRow.addClass('highlight');
setTimeout(function()
{
$newRow.removeClass('highlight');
}, 1600);
adjustButtons();
}).on('click', '.btn-delete', function()
{
var $row = $(this).closest('tr');
$row.addClass('highlight').fadeOut(700, function()
{
$row.remove();
adjustButtons();
});
});
adjustButtons();
});
$('#confirmButton').click(function()
{
/* Unique team. */
$('select[name^=team]').each(function(i)
{
value = $(this).val();
if(value == '') return;
$('select[name^=team]').each(function(j)
{
if(i <= j) return;
if(value == $(this).val()) $(this).closest('tr').addClass('hidden');
if($(this).find('option:selected').text() == '') return;
memberCount++;
})
if(memberCount < 2)
{
alert(teamMemberError);
return false;
}
});
$('select[name^=team]').closest('tr.hidden').remove();
var memberCount = '';
var totalEstimate = 0;
var totalConsumed = oldConsumed;
var totalLeft = 0;
$('select[name^=team]').each(function()
{
if($(this).find('option:selected').text() == '') return;
memberCount++;
estimate = parseFloat($(this).parents('td').next('td').find('[name^=teamEstimate]').val());
if(!isNaN(estimate)) totalEstimate += estimate;
consumed = parseFloat($(this).parents('td').next('td').find('[name^=teamConsumed]').val());
if(!isNaN(consumed)) totalConsumed += consumed;
left = parseFloat($(this).parents('td').next('td').find('[name^=teamLeft]').val());
if(!isNaN(left)) totalLeft += left;
})
$('#estimate').val(totalEstimate);
$('#consumedSpan').html(totalConsumed);
$('#left').val(totalLeft);
if(memberCount < 2)
{
alert(teamMemberError);
return false;
}
if(totalLeft == 0 && (taskStatus == 'doing' || taskStatus == 'pause'))
{
alert(totalLeftError);
return false;
}
$('.close').click();
});
+4 -1
View File
@@ -25,6 +25,7 @@ $lang->task->delayed = 'Verzögert';
$lang->task->view = "Übersicht";
$lang->task->logEfforts = "Stunden";
$lang->task->record = "Schätzung";
$lang->task->recordedBy = "Recorded By";
$lang->task->teamConsumed = "Tean Consumed";
$lang->task->start = "Start";
$lang->task->startAction = "Start Task";
@@ -54,6 +55,7 @@ $lang->task->progressTips = 'Genutzt/(Genutzt+Rest)';
$lang->task->copy = 'Aufgabe kopieren';
$lang->task->waitTask = 'Waiting Task';
$lang->task->allModule = 'All Module';
$lang->task->replace = 'Replace';
$lang->task->common = 'Aufgabe';
$lang->task->id = 'ID';
@@ -216,7 +218,6 @@ $lang->task->legendMisc = 'Misc.';
$lang->task->confirmDelete = "Möchten Sie diese Aufgabe löschen?";
$lang->task->confirmDeleteEstimate = "Do you want to delete it?";
$lang->task->confirmDeleteLastEstimate = "Do you want to delete the log? After deleting the last work log, the task status will be adjusted to Not Started.";
$lang->task->copyStoryTitle = "Story kopieren";
$lang->task->afterSubmit = "Nach der Erstellung,";
$lang->task->successSaved = "Erstellt!";
@@ -232,6 +233,8 @@ $lang->task->noticeLinkStory = "Es wurde keine Story verknüpft. Sie k
$lang->task->noticeSaveRecord = 'Ihre Stunden wurden nicht gespeichrt. Bitte erst speichern.';
$lang->task->commentActions = '%s. %s, kommentiert von <strong>%s</strong>.';
$lang->task->deniedNotice = 'Nur %s kann die Aufgabe %s.';
$lang->task->deniedStatusNotice = 'The task status is %s, the effort cannot be maintained.';
$lang->task->transferNotice = 'Linear task cannot be transferred.';
$lang->task->noTask = 'Keine Aufagben. ';
$lang->task->createDenied = 'Aufgben erstellen it in diesem Projekt gesperrt';
$lang->task->cannotDeleteParent = 'Cannot delete parent task';
+4 -1
View File
@@ -25,6 +25,7 @@ $lang->task->delayed = 'Delayed';
$lang->task->view = "Task Detail";
$lang->task->logEfforts = "Effort";
$lang->task->record = "Estimates";
$lang->task->recordedBy = "Recorded By";
$lang->task->teamConsumed = "Tean Consumed";
$lang->task->start = "Start";
$lang->task->startAction = "Start Task";
@@ -54,6 +55,7 @@ $lang->task->progressTips = 'Cost/(Cost+Left)';
$lang->task->copy = 'Copy Task';
$lang->task->waitTask = 'Waiting Task';
$lang->task->allModule = 'All Module';
$lang->task->replace = 'Replace';
$lang->task->common = 'Task';
$lang->task->id = 'ID';
@@ -216,7 +218,6 @@ $lang->task->legendMisc = 'Misc.';
$lang->task->confirmDelete = "Do you want to delete this task?";
$lang->task->confirmDeleteEstimate = "Do you want to delete it?";
$lang->task->confirmDeleteLastEstimate = "Do you want to delete the log? After deleting the last work log, the task status will be adjusted to Not Started.";
$lang->task->copyStoryTitle = "Copy Story";
$lang->task->afterSubmit = "Next ";
$lang->task->successSaved = "Created!";
@@ -232,6 +233,8 @@ $lang->task->noticeLinkStory = "No story has been linked. You can %s f
$lang->task->noticeSaveRecord = 'Your Hour is not saved. Please save it first.';
$lang->task->commentActions = '%s. %s, commented by <strong>%s</strong>.';
$lang->task->deniedNotice = 'Only the %s can %s the task.';
$lang->task->deniedStatusNotice = 'The task status is %s, the effort cannot be maintained.';
$lang->task->transferNotice = 'Linear task cannot be transferred.';
$lang->task->noTask = 'No tasks yet. ';
$lang->task->createDenied = 'Create Task is denied in this project';
$lang->task->cannotDeleteParent = 'Cannot delete parent task';
+4 -1
View File
@@ -25,6 +25,7 @@ $lang->task->delayed = 'Ajournées';
$lang->task->view = "Détail Tâche";
$lang->task->logEfforts = "Effort";
$lang->task->record = "Estimés";
$lang->task->recordedBy = "Recorded By";
$lang->task->teamConsumed = "Tean Consumed";
$lang->task->start = "Démarrer";
$lang->task->startAction = "Démarrer Tâche";
@@ -54,6 +55,7 @@ $lang->task->progressTips = 'Coût/(Coût+Reste)';
$lang->task->copy = 'Copier Tâche';
$lang->task->waitTask = 'Tâche en attente';
$lang->task->allModule = 'Tous Modules';
$lang->task->replace = 'Replace';
$lang->task->common = 'Tâche';
$lang->task->id = 'ID';
@@ -216,7 +218,6 @@ $lang->task->legendMisc = 'Misc.';
$lang->task->confirmDelete = "Voulez-vous réellement supprimer cette tâche ?";
$lang->task->confirmDeleteEstimate = "Voulez-vous la supprimer ?";
$lang->task->confirmDeleteLastEstimate = "Do you want to delete the log? After deleting the last work log, the task status will be adjusted to Not Started.";
$lang->task->copyStoryTitle = '<span style="color:blue;">StoryModel</span>';
$lang->task->afterSubmit = "Suiv. ";
$lang->task->successSaved = "Créée !";
@@ -232,6 +233,8 @@ $lang->task->noticeLinkStory = "Aucune Story n'est associée. Vous pou
$lang->task->noticeSaveRecord = "Votre temps n'a pas été sauvé. Enregistrez-le d'abord.";
$lang->task->commentActions = '%s. %s, commenté par <strong>%s</strong>.';
$lang->task->deniedNotice = 'Seulement le %s peut %s la tâche.';
$lang->task->deniedStatusNotice = 'The task status is %s, the effort cannot be maintained.';
$lang->task->transferNotice = 'Linear task cannot be transferred.';
$lang->task->noTask = "Pas de tâche pour l'instant. ";
$lang->task->createDenied = 'La création de tâches est interdite dans ce projet';
$lang->task->cannotDeleteParent = 'Impossible de supprimer la tâche parente';
+2
View File
@@ -25,6 +25,7 @@ $lang->task->delayed = 'Tạm ngưng';
$lang->task->view = "Chi tiết nhiệm vụ";
$lang->task->logEfforts = "Chấm công";
$lang->task->record = "Dự tính";
$lang->task->recordedBy = "Recorded By";
$lang->task->start = "Bắt đầu";
$lang->task->startAction = "Bắt đầu nhiệm vụ";
$lang->task->restart = "Tiếp tục";
@@ -52,6 +53,7 @@ $lang->task->progressTips = 'Đã làm/(Đã làm + Còn lại)';
$lang->task->copy = 'Copy nhiệm vụ';
$lang->task->waitTask = 'Đang đợi nhiệm vụ';
$lang->task->allModule = 'Tất cả Module';
$lang->task->replace = 'Replace';
$lang->task->common = 'Nhiệm vụ';
$lang->task->id = 'ID';
+5 -2
View File
@@ -25,6 +25,7 @@ $lang->task->delayed = '延期';
$lang->task->view = "查看任务";
$lang->task->logEfforts = "记录工时";
$lang->task->record = "工时";
$lang->task->recordedBy = "记录人";
$lang->task->teamConsumed = "团队工时";
$lang->task->start = "开始";
$lang->task->startAction = "开始任务";
@@ -54,6 +55,7 @@ $lang->task->progressTips = '已消耗/(已消耗+剩余)';
$lang->task->copy = '复制任务';
$lang->task->waitTask = '未开始的任务';
$lang->task->allModule = '所有模块';
$lang->task->replace = '替换';
$lang->task->common = '任务';
$lang->task->id = '编号';
@@ -216,7 +218,6 @@ $lang->task->legendMisc = '其他相关';
$lang->task->confirmDelete = "您确定要删除这个任务吗?";
$lang->task->confirmDeleteEstimate = "您确定要删除这个记录吗?";
$lang->task->confirmDeleteLastEstimate = "您确定要删除该条日志吗?删除最后一条工时日志后,该任务状态将调整为未开始。";
$lang->task->copyStoryTitle = "同{$lang->SRCommon}";
$lang->task->afterSubmit = "添加之后";
$lang->task->successSaved = "成功添加,";
@@ -232,6 +233,8 @@ $lang->task->noticeLinkStory = "没有可关联的相关{$lang->SRComm
$lang->task->noticeSaveRecord = '您有尚未保存的工时记录,请先将其保存。';
$lang->task->commentActions = '%s. %s, 由 <strong>%s</strong> 添加备注。';
$lang->task->deniedNotice = '当前任务只有%s才可以%s。';
$lang->task->deniedStatusNotice = '当前任务状态是%s,不能维护日志。';
$lang->task->transferNotice = '串行多人任务不能转交。';
$lang->task->noTask = '暂时没有任务。';
$lang->task->createDenied = '你不能在该项目添加任务';
$lang->task->cannotDeleteParent = '不能删除父任务。';
@@ -354,4 +357,4 @@ $lang->taskestimate = new stdclass();
$lang->taskestimate->consumed = '工时';
$lang->task->overEsStartDate = '已超出%s计划开始时间,请先修改%s计划开始时间';
$lang->task->overEsEndDate = '已超出%s计划结束时间,请先修改%s计划结束时间';
$lang->task->overEsEndDate = '已超出%s计划结束时间,请先修改%s计划结束时间';
Regular → Executable
+547 -433
View File
File diff suppressed because it is too large Load Diff
+58 -5
View File
@@ -12,6 +12,14 @@
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/kindeditor.html.php';?>
<?php include '../../common/view/sortable.html.php';?>
<?php js::set('oldConsumed', $task->consumed);?>
<?php js::set('currentUser', $app->user->account);?>
<?php js::set('members', $members);?>
<?php js::set('teamMemberError', $lang->task->error->teamMember);?>
<?php js::set('totalLeftError', sprintf($this->lang->task->error->leftEmptyAB, $this->lang->task->statusList[$task->status]));?>
<?php js::set('estimateNotEmpty', sprintf($lang->error->notempty, $lang->task->estimate))?>
<?php js::set('leftNotEmpty', sprintf($lang->error->notempty, $lang->task->left))?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<div class='main-header'>
@@ -23,20 +31,41 @@
<?php endif;?>
</h2>
</div>
<form method='post' target='hiddenwin'>
<table class='table table-form'>
<?php $isMultiple = !empty($task->team);?>
<?php if($isMultiple):?>
<tr>
<th class='thWidth'><?php echo $lang->task->mode;?></th>
<td class='w-p35-f'><?php echo zget($lang->task->modeList, $task->mode) . html::hidden('mode', $task->mode);?></td>
<td></td>
</tr>
<?php endif;?>
<tr>
<th class='thWidth'><?php echo $lang->task->assignedTo;?></th>
<td class='w-p25-f'><?php echo html::select('assignedTo', $members, $task->finishedBy, "class='form-control chosen'");?></td>
<td></td>
<td class='w-p35-f'>
<div class="input-group" id="dataPlanGroup">
<?php echo html::select('assignedTo', $members, $task->finishedBy, "class='form-control chosen'" . ($isMultiple ? ' disabled' : ''));?>
<?php if($isMultiple):?>
<span class="input-group-btn team-group"><a class="btn br-0" href="#modalTeam" data-toggle="modal"><?php echo $lang->task->team;?></a></span>
<?php endif;?>
</div>
</td>
<td>
<?php if($isMultiple):?>
<div class="checkbox-primary c-multipleTask affair">
<input type="checkbox" name="multiple" value="1" id="multiple" checked disabled /><label for="multiple" class="no-margin"><?php echo $lang->task->multiple;?></label>
</div>
<?php endif;?>
</td>
</tr>
<?php if($task->parent != '-1'):?>
<tr>
<th><?php echo $lang->task->left;?></th>
<td>
<div class='input-group'>
<?php echo html::input('left', '', "class='form-control'");?>
<?php echo html::input('left', '', "class='form-control'" . ($isMultiple ? ' readonly' : ''));?>
<span class='input-group-addon'><?php echo $lang->task->hour;?></span>
</div>
</td>
@@ -53,16 +82,40 @@
</tr>
<tr>
<td colspan='3' class='text-center'>
<?php
<?php
echo html::submitButton($lang->task->activate);
echo html::linkButton($lang->goback, $this->session->taskList);
?>
</td>
</tr>
</table>
<div class='modal fade modal-team' id='modalTeam' data-scroll-inside='false'>
<div class='modal-dialog'>
<div class='modal-content with-padding'>
<div class='modal-header'>
<button type='button' class='close' data-dismiss='modal'>
<i class="icon icon-close"></i>
</button>
<h4 class='modal-title'><?php echo $lang->task->team;?></h4>
</div>
<div class='modal-body'>
<table class="table table-form" id='taskTeamEditor'>
<tbody class='sortable'>
<?php include __DIR__ . DS . 'taskteam.html.php';?>
</tbody>
<tfoot>
<tr><td colspan='3' class='text-center form-actions'><?php echo html::a('javascript:void(0)', $lang->confirm, '', "id='confirmButton' class='btn btn-primary btn-wide'");?></td></tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</form>
<hr class='small' />
<div class='main'><?php include '../../common/view/action.html.php';?></div>
</div>
</div>
<?php js::set('newRowCount', (!empty($task->team) and count($task->team) < 6) ? 6 - count($task->team) : 1);?>
<?php include '../../common/view/footer.html.php';?>
+7 -7
View File
@@ -14,12 +14,12 @@
<?php include '../../common/view/kindeditor.html.php';?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<?php if(!empty($task->team) and (!isset($task->team[$app->user->account]) or ($task->assignedTo != $app->user->account and $task->mode == 'linear'))):?>
<?php if(!empty($task->members) and strpos('wait,doing,pause', $task->status) !== false and (!isset($task->members[$app->user->account]) or $task->mode == 'linear')):?>
<div class="alert with-icon">
<i class="icon-exclamation-sign"></i>
<div class="content">
<?php if($task->assignedTo != $app->user->account and $task->mode == 'linear'):?>
<p><?php echo sprintf($lang->task->deniedNotice, '<strong>' . $task->assignedToRealName . '</strong>', $lang->task->transfer);?></p>
<?php if($task->mode == 'linear'):?>
<p><?php echo $lang->task->transferNotice;?></p>
<?php else:?>
<p><?php echo sprintf($lang->task->deniedNotice, '<strong>' . $lang->task->teamMember . '</strong>', $lang->task->transfer);?></p>
<?php endif;?>
@@ -38,14 +38,14 @@
<form method='post' target='hiddenwin'>
<table class='table table-form'>
<tr>
<th class='w-80px'><?php echo empty($task->team) ? $lang->task->assign : $lang->task->transferTo;?></th>
<td class='w-p25-f'><?php echo html::select('assignedTo', $members, empty($task->team) ? $task->assignedTo : $task->nextUser, "class='form-control chosen'");?></td><td></td>
</tr>
<th class='w-80px'><?php echo (empty($task->team) or strpos('done,cencel,closed', $task->status) !== false) ? $lang->task->assign : $lang->task->transferTo;?></th>
<td class='w-p25-f'><?php echo html::select('assignedTo', $members, (empty($task->team) or strpos('done,cencel,closed', $task->status) !== false) ? $task->assignedTo : $task->nextUser, "class='form-control chosen'");?></td><td></td>
</tr>
<?php if($task->status != 'done' and $task->status != 'closed' and $task->parent >= 0):?>
<tr>
<th><?php echo $lang->task->left;?></th>
<td><div class='input-group'><?php echo html::input('left', $task->left, "class='form-control'");?> <span class='input-group-addon'><?php echo $lang->task->hour;?></span></div></td><td></td>
</tr>
</tr>
<?php endif;?>
<tr class='hide'>
<th><?php echo $lang->task->status;?></th>
+4 -16
View File
@@ -78,7 +78,7 @@ foreach(explode(',', $config->task->create->requiredFields) as $field)
</td>
<td>
<div class="checkbox-primary c-multipleTask affair">
<input type="checkbox" name="multiple" value="1" id="multipleBox"><label for="multipleBox" class="no-margin"><?php echo $lang->task->multiple;?></label>
<input type="checkbox" name="multiple" value="1" id="multipleBox" /><label for="multipleBox" class="no-margin"><?php echo $lang->task->multiple;?></label>
</div>
<button id='selectAllUser' type="button" class="btn btn-link<?php if($task->type !== 'affair') echo ' hidden';?>"><?php echo $lang->task->selectAllUser;?></button>
</td>
@@ -293,24 +293,11 @@ foreach(explode(',', $config->task->create->requiredFields) as $field)
<div class='modal-body'>
<table class="table table-form" id='taskTeamEditor'>
<tbody class='sortable'>
<tr class='template'>
<td><?php echo html::select("team[]", $members, '', "class='form-control chosen'");?></td>
<td class="<?php echo zget($requiredFields, 'estimate', '', ' required')?>">
<div class='input-group'>
<?php echo html::input("teamEstimate[]", '', "class='form-control text-center' placeholder='{$lang->task->estimateAB}'") ?>
<span class='input-group-addon'><?php echo $lang->task->hour;?></span>
</div>
</td>
<td class='w-130px sort-handler'>
<button type="button" class="btn btn-link btn-sm btn-icon btn-add"><i class="icon icon-plus"></i></button>
<button type='button' class='btn btn-link btn-sm btn-icon btn-move'><i class='icon-move'></i></button>
<button type="button" class="btn btn-link btn-sm btn-icon btn-delete"><i class="icon icon-close"></i></button>
</td>
</tr>
<?php include __DIR__ . DS . 'taskteam.html.php';?>
</tbody>
<tfoot>
<tr>
<td colspan='3' class='text-center'><?php echo html::a('javascript:void(0)', $lang->confirm, '', "class='btn btn-primary'");?></td>
<td colspan='3' class='text-center form-actions'><?php echo html::a('javascript:void(0)', $lang->confirm, '', "id='confirmButton' class='btn btn-primary'");?></td>
</tr>
</tfoot>
</table>
@@ -347,6 +334,7 @@ foreach(explode(',', $config->task->create->requiredFields) as $field)
<?php js::set('testStoryIdList', $testStoryIdList);?>
<?php js::set('executionID', $execution->id);?>
<?php js::set('executionType', $execution->type);?>
<?php js::set('newRowCount', 5);?>
<script>
$(function(){parent.$('body.hide-modal-close').removeClass('hide-modal-close');})
</script>
+11 -51
View File
@@ -20,13 +20,14 @@
<?php js::set('oldConsumed', $task->consumed);?>
<?php js::set('taskStatus', $task->status);?>
<?php js::set('currentUser', $app->user->account);?>
<?php js::set('team', $task->team);?>
<?php js::set('team', $task->members);?>
<?php js::set('members', $members);?>
<?php js::set('confirmChangeExecution', $lang->task->confirmChangeExecution);?>
<?php js::set('newRowCount', count($task->team) < 6 ? 6 - count($task->team) : 1);?>
<?php js::set('teamMemberError', $lang->task->error->teamMember);?>
<?php js::set('totalLeftError', sprintf($this->lang->task->error->leftEmptyAB, $this->lang->task->statusList[$task->status]));?>
<?php js::set('estimateNotEmpty', sprintf($lang->error->notempty, $lang->task->estimate))?>
<?php js::set('leftNotEmpty', sprintf($lang->error->notempty, $lang->task->left))?>
<?php js::set('requiredFields', $config->task->edit->requiredFields);?>
<?php
$requiredFields = array();
@@ -65,7 +66,7 @@ foreach(explode(',', $config->task->edit->requiredFields) as $field)
<?php if(empty($task->children) and empty($task->parent) and $task->type != 'affair'):?>
<span class='input-group-addon'>
<div class='checkbox-primary'>
<input type='checkBox' name='multiple' id='multiple' value='1' <?php echo empty($task->team) ? '' : 'checked';?> />
<input type='checkBox' name='multiple' id='multiple' value='1' disabled <?php echo empty($task->team) ? '' : 'checked';?> />
<label for='multiple'><?php echo $lang->task->multipleAB;?></label>
</div>
</span>
@@ -138,12 +139,12 @@ foreach(explode(',', $config->task->edit->requiredFields) as $field)
<?php endif;?>
<tr>
<th><?php echo $lang->task->assignedTo;?></th>
<?php $disableAssignedTo = (!empty($task->team) and (($task->assignedTo != $this->app->user->account and $task->mode == 'linear') or !isset($task->team[$app->user->account]))) ? "disabled='disabled'" :'';?>
<?php $disableAssignedTo = (!empty($task->team) and $task->mode == 'linear') ? "disabled='disabled'" : '';?>
<?php
$taskMembers = array();
if(!empty($task->team))
{
$teamAccounts = array_keys($task->team);
$teamAccounts = $task->members;
foreach($teamAccounts as $teamAccount)
{
if(!isset($members[$teamAccount])) continue;
@@ -159,8 +160,7 @@ foreach(explode(',', $config->task->edit->requiredFields) as $field)
</tr>
<tr class="modeBox <?php echo $task->mode ? '' : 'hidden';?>">
<th><?php echo $lang->task->mode;?></th>
<?php $disabledMode = isset($task->team[$app->user->account]) ? '' : "disabled='disabled'"?>
<td><?php echo html::select('mode', $lang->task->modeList, $task->mode, "class='form-control chosen' $disabledMode onchange='updateAssignedTo()'");?></td>
<td><?php echo zget($lang->task->modeList, $task->mode) . html::hidden('mode', $task->mode);?></td>
</tr>
<tr class='<?php echo empty($task->team) ? 'hidden' : ''?>' id='teamTr'>
<th><?php echo $lang->task->team;?></th>
@@ -205,8 +205,8 @@ foreach(explode(',', $config->task->edit->requiredFields) as $field)
<tr>
<th><?php echo $lang->task->estimate;?></th>
<td>
<?php $disabled = (!empty($task->team) or $task->parent < 0) ? "disabled='disabled'" : '';?>
<?php echo html::input('estimate', $task->estimate, "class='form-control' {$disabled}");?>
<?php $readonly = (!empty($task->team) or $task->parent < 0) ? "readonly" : '';?>
<?php echo html::input('estimate', $task->estimate, "class='form-control' {$readonly}");?>
</td>
</tr>
<tr>
@@ -215,10 +215,7 @@ foreach(explode(',', $config->task->edit->requiredFields) as $field)
</tr>
<tr>
<th><?php echo $lang->task->left;?></th>
<td>
<?php $disabled = (!empty($task->team) or $task->parent < 0) ? "disabled='disabled'" : '';?>
<?php echo html::input('left', $task->left, "class='form-control' {$disabled}");?>
</td>
<td><?php echo html::input('left', $task->left, "class='form-control' {$readonly}");?></td>
</tr>
</table>
</div>
@@ -278,44 +275,7 @@ foreach(explode(',', $config->task->edit->requiredFields) as $field)
<div class="modal-content with-padding" id='taskTeamEditor'>
<table class='table table-form'>
<tbody class="sortable">
<?php foreach($task->team as $member):?>
<tr>
<td class='w-250px'><?php echo html::select("team[]", $members, $member->account, "class='form-control chosen'")?></td>
<td>
<div class='input-group'>
<span class="input-group-addon <?php echo zget($requiredFields, 'estimate', '', ' required');?>"><?php echo $lang->task->estimate?></span>
<?php echo html::input("teamEstimate[]", (float)$member->estimate, "class='form-control text-center' placeholder='{$lang->task->hour}'")?>
<span class='input-group-addon fix-border'><?php echo $lang->task->consumed?></span>
<?php echo html::input("teamConsumed[]", (float)$member->consumed, "class='form-control text-center' readonly placeholder='{$lang->task->hour}'")?>
<span class='input-group-addon fix-border'><?php echo $lang->task->left?></span>
<?php echo html::input("teamLeft[]", (float)$member->left, "class='form-control text-center' placeholder='{$lang->task->hour}'")?>
</div>
</td>
<td class='w-130px sort-handler'>
<button type="button" class="btn btn-link btn-sm btn-icon btn-add"><i class="icon icon-plus"></i></button>
<button type='button' class='btn btn-link btn-sm btn-icon btn-move'><i class='icon-move'></i></button>
<button type="button" class="btn btn-link btn-sm btn-icon btn-delete"><i class="icon icon-close"></i></button>
</td>
</tr>
<?php endforeach;?>
<tr class='template'>
<td class='w-250px'><?php echo html::select("team[]", $members, '', "class='form-control chosen'")?></td>
<td>
<div class='input-group'>
<span class="input-group-addon <?php echo zget($requiredFields, 'estimate', '', ' required');?>"><?php echo $lang->task->estimate?></span>
<?php echo html::input("teamEstimate[]", '', "class='form-control text-center' placeholder='{$lang->task->hour}'")?>
<span class='input-group-addon fix-border'><?php echo $lang->task->consumed?></span>
<?php echo html::input("teamConsumed[]", '', "class='form-control text-center' placeholder='{$lang->task->hour}'")?>
<span class='input-group-addon fix-border'><?php echo $lang->task->left?></span>
<?php echo html::input("teamLeft[]", '', "class='form-control text-center' placeholder='{$lang->task->hour}'")?>
</div>
</td>
<td class='w-130px sort-handler'>
<button type="button" class="btn btn-link btn-sm btn-icon btn-add"><i class="icon icon-plus"></i></button>
<button type='button' class='btn btn-link btn-sm btn-icon btn-move'><i class='icon-move'></i></button>
<button type="button" class="btn btn-link btn-sm btn-icon btn-delete"><i class="icon icon-close"></i></button>
</td>
</tr>
<?php include dirname(__FILE__) . DS . 'taskteam.html.php';?>
</tbody>
<tfoot>
<tr><td colspan='3' class='text-center form-actions'><?php echo html::a('javascript:void(0)', $lang->confirm, '', "id='confirmButton' class='btn btn-primary btn-wide'");?></td></tr>
+3 -1
View File
@@ -32,7 +32,9 @@
</tr>
<tr>
<th><?php echo $lang->task->left;?></th>
<td><?php echo html::input('left', $estimate->left, 'class="form-control"');?></td>
<?php $readonly = $estimate->isLast ? '' : 'readonly';?>
<?php if(!empty($task->team) and $estimate->left == 0) $readonly = 'readonly';?>
<td><?php echo html::input('left', $estimate->left, "class='form-control' {$readonly}");?></td>
</tr>
<tr>
<th><?php echo $lang->comment;?></th>
+7 -42
View File
@@ -16,12 +16,11 @@
<?php js::set('oldConsumed', $task->consumed);?>
<?php js::set('team', $task->team);?>
<?php js::set('members', $members);?>
<?php js::set('newRowCount', count($task->team) < 6 ? 6 - count($task->team) : 1);?>
<?php js::set('teamMemberError', $lang->task->error->teamMember);?>
<?php js::set('totalLeftError', sprintf($this->lang->task->error->leftEmptyAB, $this->lang->task->statusList[$task->status]));?>
<div id='mainContent' class='main-content'>
<div class='center-block' id='taskTeamEditor'>
<?php if(empty($task->team) and !isset($task->team[$app->user->account])):?>
<?php if(empty($task->members) and !isset($task->members[$app->user->account])):?>
<div class="alert with-icon">
<i class="icon-exclamation-sign"></i>
<div class="content">
@@ -38,7 +37,7 @@
<?php endif;?>
</h2>
</div>
<form method='post' target='hiddenwin'>
<form method='post' target='hiddenwin' action='<?php echo inlink('editTeam', "executionID=$task->execution&taskID=$task->id")?>' id='teamForm'>
<table class='table table-form'>
<tbody class="sortable">
<tr class='hidden'>
@@ -48,6 +47,7 @@
<?php echo html::input('estimate', $task->estimate, "class='form-control' {$disabled}");?>
</td>
</tr>
<?php echo html::hidden('status', $task->status);?>
<tr class='hidden'>
<th><?php echo $lang->task->left;?></th>
<td>
@@ -55,47 +55,12 @@
<?php echo html::input('left', $task->left, "class='form-control' {$disabled}");?>
</td>
</tr>
<?php foreach($task->team as $member):?>
<tr>
<td class='w-250px'><?php echo html::select("team[]", $members, $member->account, "class='form-control chosen'")?></td>
<td>
<div class='input-group'>
<span class='input-group-addon'><?php echo $lang->task->estimate?></span>
<?php echo html::input("teamEstimate[]", (float)$member->estimate, "class='form-control text-center' placeholder='{$lang->task->hour}'")?>
<span class='input-group-addon fix-border'><?php echo $lang->task->consumed?></span>
<?php echo html::input("teamConsumed[]", (float)$member->consumed, "class='form-control text-center' readonly placeholder='{$lang->task->hour}'")?>
<span class='input-group-addon fix-border'><?php echo $lang->task->left?></span>
<?php echo html::input("teamLeft[]", (float)$member->left, "class='form-control text-center' placeholder='{$lang->task->hour}'")?>
</div>
</td>
<td class='w-130px sort-handler'>
<button type="button" class="btn btn-link btn-sm btn-icon btn-add"><i class="icon icon-plus"></i></button>
<button type='button' class='btn btn-link btn-sm btn-icon btn-move'><i class='icon-move'></i></button>
<button type="button" class="btn btn-link btn-sm btn-icon btn-delete"><i class="icon icon-close"></i></button>
</td>
</tr>
<?php endforeach;?>
<tr class='template'>
<td class='w-250px'><?php echo html::select("team[]", $members, '', "class='form-control chosen'")?></td>
<td>
<div class='input-group'>
<span class='input-group-addon'><?php echo $lang->task->estimate?></span>
<?php echo html::input("teamEstimate[]", '', "class='form-control text-center' placeholder='{$lang->task->hour}'")?>
<span class='input-group-addon fix-border'><?php echo $lang->task->consumed?></span>
<?php echo html::input("teamConsumed[]", '', "class='form-control text-center' placeholder='{$lang->task->hour}'")?>
<span class='input-group-addon fix-border'><?php echo $lang->task->left?></span>
<?php echo html::input("teamLeft[]", '', "class='form-control text-center' placeholder='{$lang->task->hour}'")?>
</div>
</td>
<td class='w-130px sort-handler'>
<button type="button" class="btn btn-link btn-sm btn-icon btn-add"><i class="icon icon-plus"></i></button>
<button type='button' class='btn btn-link btn-sm btn-icon btn-move'><i class='icon-move'></i></button>
<button type="button" class="btn btn-link btn-sm btn-icon btn-delete"><i class="icon icon-close"></i></button>
</td>
</tr>
<?php include dirname(__FILE__) . DS . 'taskteam.html.php';?>
</tbody>
<tfoot>
<tr><td colspan='3' class='text-center form-actions'><?php echo html::submitButton();?></td></tr>
<tr>
<td colspan='3' class='text-center form-actions'><?php echo html::submitButton();?></td>
</tr>
</tfoot>
</table>
</form>
+14 -3
View File
@@ -17,7 +17,7 @@
<?php js::set('consumedEmpty', $lang->task->error->consumedEmptyAB);?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<?php if(!empty($task->team) and (!isset($task->team[$app->user->account]) or ($task->assignedTo != $app->user->account and $task->mode == 'linear'))):?>
<?php if(!empty($task->members) and (!isset($task->members[$app->user->account]) or ($task->assignedTo != $app->user->account and $task->mode == 'linear'))):?>
<div class="alert with-icon">
<i class="icon-exclamation-sign"></i>
<div class="content">
@@ -67,9 +67,20 @@
?>
</td>
</tr>
<tr>
<tr class='<?php if($task->mode == 'multi') echo 'hidden'?>'>
<th><?php echo (!empty($task->team) and $task->mode == 'linear') ? $lang->task->transferTo : $lang->task->assign;?></th>
<td><?php echo html::select('assignedTo', $members, $task->nextBy, "class='form-control chosen'");?></td><td></td>
<td>
<?php
if(!empty($task->team) and $task->mode == 'linear')
{
echo zget($members, $task->nextBy) . html::hidden('assignedTo', $task->nextBy);
}
else
{
echo html::select('assignedTo', $members, $task->nextBy, "class='form-control chosen'");
}
?>
</td>
</tr>
<tr>
<th><?php echo $lang->task->realStarted;?></th>
+1 -1
View File
@@ -14,7 +14,7 @@
<?php include '../../common/view/kindeditor.html.php';?>
<div id='mainContent' class='main-content'>
<div class='center-block'>
<?php if(!empty($task->team) and (!isset($task->team[$app->user->account]) or ($task->assignedTo != $app->user->account and $task->mode == 'linear'))):?>
<?php if(!empty($task->members) and (!isset($task->members[$app->user->account]) or ($task->assignedTo != $app->user->account and $task->mode == 'linear'))):?>
<div class="alert with-icon">
<i class="icon-exclamation-sign"></i>
<div class="content">
+63 -49
View File
@@ -12,17 +12,8 @@
?>
<?php include '../../common/view/header.lite.html.php';?>
<?php include '../../common/view/datepicker.html.php';?>
<style>
<?php if(empty($estimates) and strpos('wait,pause,doing', $task->status) !== false):?>
#recordForm {margin-top:60px;}
<?php endif;?>
<?php if(count($estimates) == 1 and strpos('wait,pause,doing', $task->status) !== false):?>
#recordForm {margin-top:20px;}
<?php endif;?>
#recordForm table .form-actions{padding:25px;}
</style>
<?php $team = array_keys($task->team);?>
<?php js::set('confirmRecord', (!empty($team) && $task->assignedTo != end($team)) ? $lang->task->confirmTransfer : $lang->task->confirmRecord);?>
<?php $members = $task->members;?>
<?php js::set('confirmRecord', (!empty($members) && $task->mode == 'linear' && $task->assignedTo != end($members)) ? $lang->task->confirmTransfer : $lang->task->confirmRecord);?>
<?php js::set('noticeSaveRecord', $lang->task->noticeSaveRecord);?>
<?php js::set('today', helper::today());?>
<div id='mainContent' class='main-content'>
@@ -31,73 +22,96 @@
<h2>
<span class='label label-id'><?php echo $task->id;?></span>
<?php echo isonlybody() ? ("<span title='$task->name'>" . $task->name . '</span>') : html::a($this->createLink('task', 'view', 'task=' . $task->id), $task->name);?>
<?php if(!isonlybody()):?>
<small><?php echo $lang->arrow . $lang->task->logEfforts;?></small>
<?php endif;?>
</div>
</h2>
<ul class='nav nav-default hours'>
<li><span><?php echo $lang->task->estimate;?></span> </li>
<li><span class='estimateTotally'><?php echo $task->estimate . 'h';?></span></li>
<li class='divider'></li>
<li><span><?php echo $lang->task->consumed;?></span> </li>
<li><span class='consumedTotally'><?php echo $task->consumed . 'h';?></span></li>
</ul>
<?php if(!isonlybody()):?>
<small><?php echo $lang->arrow . $lang->task->logEfforts;?></small>
<?php endif;?>
</div>
<form id="recordForm" method='post' target='hiddenwin'>
<table class='table table-form table-fixed'>
<?php if(count($estimates)):?>
<table class='table table-bordered table-fixed table-recorded'>
<thead>
<tr class='text-center'>
<th class="w-id"><?php echo $lang->idAB;?></th>
<th class="w-120px"><?php echo $lang->task->date;?></th>
<th class="w-120px"><?php echo $lang->task->recordedBy;?></th>
<th><?php echo $lang->comment;?></th>
<th class="thWidth"><?php echo $lang->task->consumed;?></th>
<th class="thWidth"><?php echo $lang->task->left;?></th>
<th><?php echo $lang->comment;?></th>
<th class='c-actions-2'><?php if(empty($task->team) or $task->assignedTo == $this->app->user->account or ($task->mode == 'multi' and isset($task->team[$app->user->account]))) echo $lang->actions;?></th>
<th class='c-actions-2'><?php echo $lang->actions;?></th>
</tr>
</thead>
<tbody>
<?php if(count($estimates)):?>
<?php foreach($estimates as $estimate):?>
<tr class="text-center">
<td><?php echo $estimate->id;?></td>
<td><?php echo $estimate->date;?></td>
<td><?php echo zget($users, $estimate->account);?></td>
<td class="text-left" title="<?php echo $estimate->work;?>"><?php echo $estimate->work;?></td>
<td title="<?php echo $estimate->consumed . ' ' . $lang->execution->workHour;?>"><?php echo $estimate->consumed . ' ' . $lang->execution->workHourUnit;?></td>
<td title="<?php echo $estimate->left . ' ' . $lang->execution->workHour;?>"><?php echo $estimate->left . ' ' . $lang->execution->workHourUnit;?></td>
<td class="text-left" title="<?php echo $estimate->work;?>"><?php echo $estimate->work;?></td>
<?php if(empty($task->team) or $task->assignedTo == $this->app->user->account or ($task->mode == 'multi' and isset($task->team[$app->user->account]))):?>
<td align='center' class='c-actions'>
<?php
if($this->app->user->account == $estimate->account)
{
common::printIcon('task', 'editEstimate', "estimateID=$estimate->id", '', 'list', 'pencil', '', 'showinonlybody', true);
common::printIcon('task', 'deleteEstimate', "estimateID=$estimate->id", '', 'list', 'close', 'hiddenwin', 'showinonlybody');
}
$canOperateEffort = $this->task->canOperateEffort($task, $estimate);
common::printIcon('task', 'editEstimate', "estimateID=$estimate->id", '', 'list', 'edit', '', 'showinonlybody', true, $canOperateEffort ? '' : 'disabled');
common::printIcon('task', 'deleteEstimate', "estimateID=$estimate->id", '', 'list', 'trash', 'hiddenwin', 'showinonlybody', false, ($canOperateEffort and ($task->mode != 'linear' or ($task->mode == 'linear' and $estimate->left > 0))) ? '' : 'disabled');
?>
</td>
</tr>
<?php endif;?>
<?php endforeach;?>
<?php endif;?>
<?php if(!empty($task->team) and (!isset($task->team[$app->user->account]) or ($task->assignedTo != $app->user->account and $task->mode == 'linear'))):?>
</tbody>
</table>
</form>
<div class="alert with-icon">
<i class="icon-exclamation-sign"></i>
<div class="content">
<?php if($task->assignedTo != $app->user->account and $task->mode == 'linear'):?>
<p><?php echo sprintf($lang->task->deniedNotice, '<strong>' . $task->assignedToRealName . '</strong>', $lang->task->logEfforts);?></p>
<?php else:?>
<p><?php echo sprintf($lang->task->deniedNotice, '<strong>' . $lang->task->teamMember . '</strong>', $lang->task->logEfforts);?></p>
<?php endif;?>
<?php endif;?>
<?php if(!$this->task->canOperateEffort($task)):?>
<div class="alert with-icon">
<i class="icon-exclamation-sign"></i>
<div class="content">
<?php if(strpos('|done|closed|cancel|pause|', $task->status) !== false):?>
<p><?php echo sprintf($lang->task->deniedStatusNotice, '<strong>' . zget($this->lang->task->statusList, $task->status) . '</strong>');?></p>
<?php elseif($task->assignedTo != $app->user->account and $task->mode == 'linear'):?>
<p><?php echo sprintf($lang->task->deniedNotice, '<strong>' . $task->assignedToRealName . '</strong>', $lang->task->logEfforts);?></p>
<?php else:?>
<p><?php echo sprintf($lang->task->deniedNotice, '<strong>' . $lang->task->teamMember . '</strong>', $lang->task->logEfforts);?></p>
<?php endif;?>
</div>
</div>
</div>
<?php else:?>
<?php for($i = 1; $i <= 3; $i++):?>
<?php else:?>
<table class='table table-form table-fixed table-record'>
<thead>
<tr class='text-center'>
<th class="w-120px"><?php echo $lang->task->date;?></th>
<th><?php echo $lang->comment;?></th>
<th class="w-100px"><?php echo $lang->task->consumedAB;?></th>
<th class="w-100px"><?php echo $lang->task->leftAB;?></th>
</tr>
</thead>
<tbody>
<?php for($i = 1; $i <= 5; $i++):?>
<tr class="text-center">
<td><?php echo $i . html::hidden("id[$i]", $i);?></td>
<?php echo html::hidden("id[$i]", $i);?>
<td><?php echo html::input("dates[$i]", helper::today(), "class='form-control text-center form-date'");?></td>
<td><?php echo html::input("consumed[$i]", '', "class='form-control text-center'");?></td>
<td><?php echo html::input("left[$i]", '', "class='form-control text-center left'");?></td>
<td class="text-left"><?php echo html::textarea("work[$i]", '', "class='form-control' style='height:50px;'");?></td>
<td></td>
<td class="text-left"><?php echo html::textarea("work[$i]", '', "class='form-control' rows=1");?></td>
<td>
<div class='input-group'>
<?php echo html::input("consumed[$i]", '', "class='form-control text-center'");?>
<span class='input-group-addon'>h</span>
</div>
</td>
<td>
<div class='input-group'>
<?php echo html::input("left[$i]", '', "class='form-control text-center left'");?>
<span class='input-group-addon'>h</span>
</div>
</td>
</tr>
<?php endfor;?>
<tr>
<td colspan='6' class='text-center form-actions'><?php echo html::submitButton() . html::backButton('', '', 'btn btn-wide');?></td>
<td colspan='4' class='text-center form-actions'><?php echo html::submitButton() . html::backButton('', '', 'btn btn-wide');?></td>
</tr>
</tbody>
</table>
+19 -7
View File
@@ -18,7 +18,7 @@
<div id='mainContent' class='main-content'>
<?php
/* IF it is multi-task, the suspened can only be restarted by the current user who it is assigned to. */
if(!empty($task->team) and (!isset($task->team[$app->user->account]) or ($task->assignedTo != $app->user->account and $task->mode == 'linear'))):
if(!empty($task->members) and (!isset($task->members[$app->user->account]) or ($task->assignedTo != $app->user->account and $task->mode == 'linear'))):
?>
<div class="alert with-icon">
<i class="icon-exclamation-sign"></i>
@@ -43,10 +43,19 @@
</div>
<form method='post' target='hiddenwin' <?php if($app->rawMethod == 'start') echo "onsubmit='return checkLeft();'"?>>
<table class='table table-form'>
<tr>
<tr class='<?php if($task->mode == 'multi') echo 'hidden'?>'>
<th class='w-90px'><?php echo $lang->task->assignedTo;?></th>
<td class='w-p25-f'>
<?php echo html::select('assignedTo', $members, $assignedTo, "class='form-control chosen'");?>
<?php
if($task->mode == 'linear')
{
echo zget($members, $assignedTo) . html::hidden('assignedTo', $assignedTo);
}
else
{
echo html::select('assignedTo', $members, $assignedTo, "class='form-control chosen'");
}
?>
</td>
<td></td>
</tr>
@@ -59,16 +68,19 @@
<th><?php echo $lang->task->consumed;?></th>
<td>
<div class='input-group'>
<?php $consumed = (!empty($task->team) && isset($task->team[$task->assignedTo])) ? (float)$task->team[$task->assignedTo]->consumed : $task->consumed;?>
<?php
$currentTeam = !empty($task->team) ? $this->task->getTeamByAccount($task->team) : '';
$consumed = !empty($currentTeam) ? (float)$currentTeam->consumed : $task->consumed;
?>
<?php echo html::input('consumed', $consumed, "class='form-control'");?> <span class='input-group-addon'><?php echo $lang->task->hour;?></span>
</div>
</td>
</tr>
</tr>
<tr>
<th><?php echo $lang->task->left;?></th>
<td>
<div class='input-group'>
<?php $left = (!empty($task->team) && isset($task->team[$task->assignedTo])) ? (float)$task->team[$task->assignedTo]->left : $task->left;?>
<?php $left = !empty($currentTeam) ? (float)$currentTeam->left : $task->left;?>
<?php echo html::input('left', $left, "class='form-control'");?> <span class='input-group-addon'><?php echo $lang->task->hour;?></span>
</div>
</td>
@@ -77,7 +89,7 @@
<th><?php echo $lang->task->status;?></th>
<td><?php echo html::hidden('status', 'doing');?></td>
</tr>
<?php $this->printExtendFields($task, 'table', 'columns=2');?>
<?php $this->printExtendFields($task, 'table', 'columns=2');?>
<tr>
<th><?php echo $lang->comment;?></th>
<td colspan='2'><?php echo html::textarea('comment', '', "rows='6' class='form-control'");?></td>
+254
View File
@@ -0,0 +1,254 @@
<?php if(!empty($task->team)):?>
<?php foreach($task->team as $member):?>
<?php
$memberDisabled = false;
$sortDisabled = false;
$memberStatus = $member->status;
if($memberStatus == 'done') $memberDisabled = true;
if($memberStatus != 'wait' and $task->mode == 'linear') $sortDisabled = true;
if($memberStatus == 'done' and $task->mode == 'multi') $sortDisabled = true;
if($task->mode == 'linear' and strpos('|closed|cancel|pause|', $task->status) !== false and $app->rawMethod != 'activate')
{
$memberStatus = $task->status;
$memberDisabled = true;
$sortDisabled = true;
}
$hourDisabled = $memberDisabled;
if($task->mode == 'multi' and $app->rawMethod == 'activate') $hourDisabled = false;
?>
<tr class='member-<?php echo $memberStatus;?>' data-estimate='<?php echo (float)$member->estimate?>' data-consumed='<?php echo (float)$member->consumed?>' data-left='<?php echo (float)$member->left?>'>
<td class='w-250px'>
<?php echo html::select("team[]", $members, $member->account, "class='form-control chosen'" . ($memberDisabled ? ' disabled' : ''))?>
<?php echo html::hidden("teamSource[]", $member->account);?>
<?php if($memberDisabled) echo html::hidden("team[]", $member->account);?>
</td>
<td>
<div class='input-group'>
<span class="input-group-addon <?php echo zget($requiredFields, 'estimate', '', ' required');?>"><?php echo $lang->task->estimate?></span>
<?php echo html::input("teamEstimate[]", (float)$member->estimate, "class='form-control text-center' placeholder='{$lang->task->hour}'" . ($hourDisabled ? ' readonly' : ''))?>
<span class='input-group-addon fix-border'><?php echo $lang->task->consumed?></span>
<?php echo html::input("teamConsumed[]", (float)$member->consumed, "class='form-control text-center' readonly placeholder='{$lang->task->hour}'")?>
<span class='input-group-addon fix-border'><?php echo $lang->task->left?></span>
<?php echo html::input("teamLeft[]", (float)$member->left, "class='form-control text-center' placeholder='{$lang->task->hour}'" . ($hourDisabled ? ' readonly' : ''))?>
</div>
</td>
<td class='w-130px sort-handler'>
<button type="button" <?php echo $memberDisabled ? 'disabled' : '';?> class="btn btn-link btn-sm btn-icon btn-add"><i class="icon icon-plus"></i></button>
<?php if(isset($task->mode) and $task->mode == 'linear'):?>
<button type="button" <?php echo $sortDisabled ? 'disabled' : '';?> class='btn btn-link btn-sm btn-icon btn-move'><i class='icon-move'></i></button>
<?php endif;?>
<button type="button" <?php echo $memberDisabled ? 'disabled' : '';?> class="btn btn-link btn-sm btn-icon btn-delete"><i class="icon icon-close"></i></button>
</td>
</tr>
<?php endforeach;?>
<?php endif;?>
<tr class='template teamTemplate member-wait'>
<td class='w-250px'>
<?php echo html::select("team[]", $members, '', "class='form-control chosen'")?>
<?php echo html::hidden("teamSource[]", '');?>
</td>
<td>
<?php if(empty($task->team)):?>
<div class='input-group'>
<?php echo html::input("teamEstimate[]", '', "class='form-control text-center' placeholder='{$lang->task->estimateAB}'") ?>
<span class='input-group-addon'><?php echo $lang->task->hour;?></span>
</div>
<?php else:?>
<div class='input-group'>
<span class="input-group-addon <?php echo zget($requiredFields, 'estimate', '', ' required');?>"><?php echo $lang->task->estimate?></span>
<?php echo html::input("teamEstimate[]", '', "class='form-control text-center' placeholder='{$lang->task->hour}'")?>
<span class='input-group-addon fix-border'><?php echo $lang->task->consumed?></span>
<?php echo html::input("teamConsumed[]", 0, "class='form-control text-center' readonly placeholder='{$lang->task->hour}'")?>
<span class='input-group-addon fix-border'><?php echo $lang->task->left?></span>
<?php echo html::input("teamLeft[]", '', "class='form-control text-center' placeholder='{$lang->task->hour}'")?>
</div>
<?php endif;?>
</td>
<td class='w-130px sort-handler'>
<button type="button" class="btn btn-link btn-sm btn-icon btn-add"><i class="icon icon-plus"></i></button>
<?php if(empty($task->mode) or $task->mode == 'linear'):?>
<button type='button' class='btn btn-link btn-sm btn-icon btn-move'><i class='icon-move'></i></button>
<?php endif;?>
<button type="button" class="btn btn-link btn-sm btn-icon btn-delete"><i class="icon icon-close"></i></button>
</td>
</tr>
<?php $newRowCount = (!empty($task->team) and count($task->team) < 6) ? 6 - count($task->team) : 1;?>
<?php if(isset($task->status) and $task->status != 'wait' and $task->status != 'doing') $newRowCount = 0;?>
<?php js::set('newRowCount', $newRowCount);?>
<?php if(isset($task->mode) and $task->mode == 'linear') js::set('sortSelector', 'tr.member-wait');?>
<?php js::set('teamMemberError', $lang->task->error->teamMember);?>
<?php if(isset($task->status)):?>
<?php js::set('taskStatus', $task->status);?>
<?php js::set('totalLeftError', sprintf($this->lang->task->error->leftEmptyAB, $this->lang->task->statusList[$task->status]));?>
<?php endif;?>
<script>
$(document).ready(function()
{
<?php if(isset($task->mode) and $task->mode == 'multi'):?>
$('tr.teamTemplate').closest('tbody.sortable').sortable('destroy');
<?php endif;?>
/* Init task team manage dialog */
var $taskTeamEditor = $('tr.teamTemplate').closest('table').batchActionForm(
{
idStart: 0,
idEnd: newRowCount - 1,
chosen: true,
datetimepicker: false,
colorPicker: false,
});
var taskTeamEditor = $taskTeamEditor.data('zui.batchActionForm');
var adjustButtons = function()
{
var $deleteBtn = $taskTeamEditor.find('.btn-delete');
if ($deleteBtn.length == 1) $deleteBtn.addClass('disabled').attr('disabled', 'disabled');
};
var disableMembers = function()
{
var mode = $('#mode').length > 0 ? $('#mode').val() : '<?php echo (isset($task->mode) ? $task->mode : '')?>';
if(mode == 'multi')
{
var members = [];
var $teams = $taskTeamEditor.find('select#team');
for(i = 0; i < $teams.length; i++)
{
var value = $teams.eq(i).val();
if($.inArray(value, members) >= 0)
{
$teams.eq(i).closest('tr').addClass('hidden');
continue;
}
if(value != '') members.push(value);
}
$teams.each(function()
{
var $this = $(this);
var value = $this.val();
$this.find('option:disabled').removeAttr('disabled');
$.each(members, function(i, account)
{
if(account == value) return;
$this.find('option[value=' + account + ']').attr('disabled', 'disabled');
})
$this.trigger("chosen:updated");
});
$taskTeamEditor.find('tr.hidden').remove();
}
}
var checkRemove = function(removeIndex)
{
var $teams = $taskTeamEditor.find('select#team');
var totalLeft = 0;
var memberCount = 0;
for(i = 0; i < $teams.length; i++)
{
var $this = $teams.eq(i);
var value = $this.val();
if(value == '') continue;
var $tr = $this.closest('tr');
if($tr.index() == removeIndex) continue;
memberCount++;
var $teamLeft = $tr.find('[name^=teamLeft]');
if($teamLeft.length > 0)
{
left = parseFloat($teamLeft.val());
if(!isNaN(left)) totalLeft += left;
}
}
if(memberCount < 2)
{
bootbox.alert(teamMemberError);
return false;
}
<?php if($app->rawMethod == 'edit'):?>
if(totalLeft == 0 && (taskStatus == 'doing' || taskStatus == 'pause'))
{
bootbox.alert(totalLeftError);
return false;
}
<?php endif;?>
if($taskTeamEditor.find('td > .btn-delete:enabled').length == 1) return false;
return true;
}
$taskTeamEditor.on('click', '.btn-add', function()
{
var $newRow = taskTeamEditor.createRow(null, $(this).closest('tr'));
$newRow.addClass('highlight');
setTimeout(function()
{
$newRow.removeClass('highlight');
}, 1600);
disableMembers();
adjustButtons();
}).on('click', '.btn-delete', function()
{
var $row = $(this).closest('tr');
<?php if(!empty($task->team)):?>
if(!checkRemove($row.index())) return;
<?php endif;?>
$row.addClass('highlight').fadeOut(700, function()
{
$row.remove();
disableMembers();
adjustButtons();
});
});
adjustButtons();
disableMembers();
$taskTeamEditor.on('change', 'select#team', function()
{
$(this).closest('tr').find('input[id^=teamEstimate]').closest('.input-group').toggleClass('required', $(this).val() != '')
disableMembers();
var $teamSource = $(this).siblings('[name^=teamSource]');
if($teamSource.val() == '') return;
var $tr = $(this).closest('tr');
var consumed = 0;
var estimate = $tr.attr('data-left');;
if($(this).val() == $teamSource.val())
{
consumed = $tr.attr('data-consumed');
estimate = $tr.attr('data-estimate');
}
$tr.find('[name^=teamConsumed]').val(consumed);
$tr.find('[name^=teamEstimate]').val(estimate);
});
$taskTeamEditor.find('select#team:enabled').each(function()
{
$(this).closest('tr').find('input[id^=teamEstimate]').closest('.input-group').toggleClass('required', $(this).val() != '')
});
$('#mode').change(function()
{
if($(this).val() == 'multi')
{
disableMembers();
}
else
{
$taskTeamEditor.find('select#team').each(function()
{
$(this).find('option:disabled').removeAttr('disabled').trigger("chosen:updated");
})
}
if($('#teamMember').val() != '') $taskTeamEditor.find('tfoot .btn').click();
})
});
</script>
+7 -2
View File
@@ -262,7 +262,7 @@
<th><?php echo $lang->task->assignedTo;?></th>
<td>
<?php
if(!empty($task->team) and $task->mode == 'multi' and $task->status != 'closed')
if(!empty($task->team) and $task->mode == 'multi' and strpos('done,cencel,closed', $task->status) === false)
{
foreach($task->team as $member) echo ' ' . zget($users, $member->account);
}
@@ -349,14 +349,19 @@
<th class='text-center'><?php echo $lang->task->estimate?></th>
<th class='text-center'><?php echo $lang->task->consumed?></th>
<th class='text-center'><?php echo $lang->task->left?></th>
<th class='text-center'><?php echo $lang->statusAB;?></th>
</tr>
</thead>
<?php foreach($task->team as $member):?>
<tr class='text-center'>
<td class='text-left'><?php echo zget($users, $member->account)?></td>
<td class='text-left'>
<?php echo zget($users, $member->account);?>
<?php if($member->transfer) echo "({$lang->task->replace})";?>
</td>
<td><?php echo (float)$member->estimate?></td>
<td><?php echo (float)$member->consumed?></td>
<td><?php echo (float)$member->left?></td>
<td class="status-<?php echo $member->status;?>"><?php echo zget($lang->task->statusList, $member->status);?></td>
</tr>
<?php endforeach;?>
</table>
+1 -1
View File
@@ -1452,7 +1452,7 @@ class treeModel extends model
$module = $this->getById((int)$moduleID);
if(empty($module)) return array();
return $this->dao->select('id')->from(TABLE_MODULE)->where('path')->like($module->path . '%')->andWhere('deleted')->eq(0)->fetchPairs();
return $this->dao->select('id')->from(TABLE_MODULE)->where("CONCAT(',', path, ',')")->like("%,$module->path,%")->andWhere('deleted')->eq(0)->fetchPairs();
}
/**
+2 -1
View File
@@ -2848,10 +2848,11 @@ class userModel extends model
$personalData['createdDocs'] = $this->dao->select($count)->from(TABLE_DOC)->where('addedBy')->eq($account)->andWhere('lib')->in(array_keys($allLibs))->andWhere('deleted')->eq('0')->fetch('count');
$personalData['finishedTasks'] = $this->dao->select($t1Count)->from(TABLE_TASK)->alias('t1')
->leftjoin(TABLE_EXECUTION)->alias('t2')->on('t1.execution = t2.id')
->leftjoin(TABLE_TASKTEAM)->alias('t3')->on('t1.id = t3.task')
->where('t1.deleted')->eq('0')
->andWhere('t2.deleted')->eq('0')
->andWhere('t1.finishedBy', true)->eq($account)
->orWhere('t1.finishedList')->like("%,{$account},%")
->orWhere('t3.status')->eq("done")
->markRight(1)
->fetch('count');
Regular → Executable
+2 -1
View File
@@ -50,6 +50,8 @@ class weekly extends control
if(!$date) $date = helper::today();
$date = date('Y-m-d', strtotime($date));
$this->weekly->save($projectID, $date);
$this->view->title = $this->lang->weekly->common;
$this->view->pv = $this->weekly->getPV($projectID, $date);
@@ -67,7 +69,6 @@ class weekly extends control
$this->view->postponed = $this->weekly->getPostponed($projectID, $date);
$this->view->nextWeek = $this->weekly->getTasksOfNextWeek($projectID, $date);
$this->view->workload = $this->weekly->getWorkloadByType($projectID, $date);
$this->weekly->save($projectID, $date);
$this->lang->modulePageNav = $this->weekly->getPageNav($this->view->project, $date);
$this->display();
+16 -7
View File
@@ -114,7 +114,11 @@ class weeklyModel extends model
*/
public function save($project, $date)
{
$this->dao->delete()->from(TABLE_WEEKLYREPORT)->where('project')->eq($project)->exec();
$weekStart = $this->getThisMonday($date);
$this->dao->delete()->from(TABLE_WEEKLYREPORT)
->where('project')->eq($project)
->andWhere('weekStart')->eq($weekStart)
->exec();
$report = new stdclass;
$report->pv = $this->getPV($project, $date);
@@ -123,7 +127,7 @@ class weeklyModel extends model
$report->sv = $this->getSV($report->ev, $report->pv);
$report->cv = $this->getCV($report->ev, $report->ac);
$report->project = $project;
$report->weekStart = $this->getThisMonday($date);
$report->weekStart = $weekStart;
$report->staff = $this->getStaff($project);
$report->workload = json_encode($this->getWorkloadByType($project, $date));
$this->dao->replace(TABLE_WEEKLYREPORT)->data($report)->exec();
@@ -378,9 +382,10 @@ class weeklyModel extends model
$tasks = $this->dao->select('*')->from(TABLE_TASK)
->where('execution')->in($executionIdList)
->andWhere("(estStarted < '$nextMonday' or estStarted='0000-00-00')")
->andWhere("parent")->ge(0)
->andWhere("deleted")->eq(0)
->andWhere("estStarted")->ge($monday)
->andWhere("estStarted")->lt($nextMonday)
->fetchAll('id');
$PV = 0;
@@ -400,7 +405,7 @@ class weeklyModel extends model
$PV += count($passedDays) * $task->estimate / count($fullDays);
}
return round($PV, 2);
return sprintf("%.2f",$PV);
}
/**
@@ -429,7 +434,8 @@ class weeklyModel extends model
->from(TABLE_TASK)
->where('execution')->in($executionIdList)
->andWhere('consumed')->gt(0)
->andWhere("(estStarted < '$nextMonday' or estStarted='0000-00-00')")
->andWhere("estStarted")->ge($monday)
->andWhere("estStarted")->lt($nextMonday)
->andWhere("parent")->ge(0)
->andWhere("deleted")->eq(0)
->andWhere('status')->ne('cancel')
@@ -448,7 +454,8 @@ class weeklyModel extends model
$EV += $task->estimate * $task->progress / 100;
}
}
return round($EV, 2);
return sprintf("%.2f", $EV);
}
/**
@@ -483,6 +490,7 @@ class weeklyModel extends model
->where('objectType')->eq('task')
->andWhere('objectID')->in($taskIdList)
->andWhere('execution')->in($executionIdList)
->andWhere('date')->ge($monday)
->andWhere('date')->lt($nextMonday)
->fetch('consumed');
}
@@ -491,13 +499,14 @@ class weeklyModel extends model
$AC = $this->dao->select('sum(consumed) as consumed')
->from(TABLE_TASKESTIMATE)
->where('task')->in($taskIdList)
->andWhere('date')->ge($monday)
->andWhere('date')->lt($nextMonday)
->fetch('consumed');
}
if(is_null($AC)) $AC = 0;
return round($AC, 2);
return sprintf("%.2f", $AC);
}
/**
+38 -14
View File
@@ -195,7 +195,7 @@ class taskTest
return $object[1];
}
public function startTest($taskID,$param = array())
public function startTest($taskID, $param = array())
{
$createFields = array( 'status' => 'doing', 'consumed' => '9', 'assignedTo' => '', 'comment' => '9', 'realStarted' => '', 'left' => '3');
foreach($createFields as $field => $defaultValue) $_POST[$field] = $defaultValue;
@@ -655,12 +655,14 @@ class taskTest
* Test get task estimate.
*
* @param int $taskID
* @param string $account
* @param string $append
* @access public
* @return object
*/
public function getTaskEstimateTest($taskID)
public function getTaskEstimateTest($taskID, $account = '', $append = '')
{
$object = $this->objectModel->getTaskEstimate($taskID);
$object = $this->objectModel->getTaskEstimate($taskID, $account, $append);
if(dao::isError())
{
$error = dao::getError();
@@ -1383,25 +1385,47 @@ class taskTest
}
/**
* Test get next user.
* Test for get team by account.
*
* @param array $users
* @param string $account
* @param string $filter
* @access public
* @return string
*/
public function getTeamByAccount($users, $account, $filter = array('filter' => 'done'))
{
$object = $this->objectModel->getTeamByAccount($users, $account, $filter);
if(empty($object)) return '_';
return $object->account . '_' . $object->status;
}
/**
* Test get assignedTo for multi task.
*
* @param array $users
* @param string $current
* @access public
* @return string
*/
public function getNextUserTest($users, $current)
public function getAssignedTo4Multi($users, $task, $type = 'current')
{
$object = $this->objectModel->getNextUser($users, $current);
$assignedTo = $this->objectModel->getAssignedTo4Multi($users, $task, $type);
return empty($assignedTo) ? 'null' : $assignedTo;
}
if(dao::isError())
{
return dao::getError();
}
else
{
return $object;
}
/**
* Test for can operate effort;
*
* @param object $task
* @param object $effort
* @access public
* @return bool
*/
public function canOperateEffort($task, $effort = null)
{
$result = $this->objectModel->canOperateEffort($task, $effort);
return $result ? 1 : 0;
}
/**
+103
View File
@@ -0,0 +1,103 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/task.class.php';
su('admin');
/**
title=taskModel->canOperateEffort();
cid=1
pid=1
判断非多人任务 >> 1
判断已完成的串行多人任务并且不判断日志 >> 0
判断已关闭的串行多人任务并且不判断日志 >> 0
判断已取消的串行多人任务并且不判断日志 >> 0
判断已暂停的串行多人任务并且不判断日志 >> 0
判断当前用户不在多人任务团队成员列表中 >> 0
判断串行多人任务的指派给不是当前用户 >> 0
判断串行多人任务的指派给是当前用户 >> 1
判断当前用户在并行多人任务团队成员列表中 >> 1
判断已完成多人任务并且日志创建者和当前用户一致 >> 1
判断已完成多人任务并且日志创建者和当前用户不一致 >> 0
判断已关闭的串行多人任务并且判断日志 >> 0
判断已取消的串行多人任务并且判断日志 >> 0
判断已暂停的串行多人任务并且判断日志 >> 0
判断进行中的串行多人任务并且当前日志创建者不是当前用户 >> 0
判断进行中的串行多人任务并且当前日志创建者是当前用户 >> 1
*/
$user = new stdclass();
$user->account = 'dev1';
$user->status = 'wait';
$user->order = '1';
$users[] = $user;
$user = new stdclass();
$user->account = 'dev2';
$user->status = 'wait';
$user->order = '2';
$users[] = $user;
$task = new stdclass();
$task->mode = '';
$task->openedBy = 'dev1';
$task->assignedTo = 'admin';
$taskTest = new taskTest();
r($taskTest->canOperateEffort($task)) && p() && e('1'); //判断非多人任务
$task->mode = 'linear';
$task->team = $users;
$task->status = 'done';
r($taskTest->canOperateEffort($task)) && p() && e('0'); //判断已完成的串行多人任务并且不判断日志
$task->status = 'closed';
r($taskTest->canOperateEffort($task)) && p() && e('0'); //判断已关闭的串行多人任务并且不判断日志
$task->status = 'cancel';
r($taskTest->canOperateEffort($task)) && p() && e('0'); //判断已取消的串行多人任务并且不判断日志
$task->status = 'pause';
r($taskTest->canOperateEffort($task)) && p() && e('0'); //判断已暂停的串行多人任务并且不判断日志
$task->status = 'wait';
r($taskTest->canOperateEffort($task)) && p() && e('0'); //判断当前用户不在多人任务团队成员列表中
$user = new stdclass();
$user->account = 'admin';
$user->status = 'wait';
$user->order = '0';
$users[] = $user;
$task->mode = 'linear';
$task->assignedTo = 'dev1';
$task->team = $users;
r($taskTest->canOperateEffort($task)) && p() && e('0'); //判断串行多人任务的指派给不是当前用户
$task->assignedTo = 'admin';
r($taskTest->canOperateEffort($task)) && p() && e('1'); //判断串行多人任务的指派给是当前用户
$task->mode = 'multi';
r($taskTest->canOperateEffort($task)) && p() && e('1'); //判断当前用户在并行多人任务团队成员列表中
$effort = new stdclass();
$effort->account = 'admin';
$task->mode = 'linear';
$task->status = 'done';
r($taskTest->canOperateEffort($task, $effort)) && p() && e('1'); //判断已完成多人任务并且日志创建者和当前用户一致
$effort->account = 'dev1';
r($taskTest->canOperateEffort($task, $effort)) && p() && e('0'); //判断已完成多人任务并且日志创建者和当前用户不一致
$task->mode = 'linear';
$task->status = 'closed';
r($taskTest->canOperateEffort($task, $effort)) && p() && e('0'); //判断已关闭的串行多人任务并且判断日志
$task->status = 'cancel';
r($taskTest->canOperateEffort($task, $effort)) && p() && e('0'); //判断已取消的串行多人任务并且判断日志
$task->status = 'pause';
r($taskTest->canOperateEffort($task, $effort)) && p() && e('0'); //判断已暂停的串行多人任务并且判断日志
$task->status = 'doing';
r($taskTest->canOperateEffort($task, $effort)) && p() && e('0'); //判断进行中的串行多人任务并且当前日志创建者不是当前用户
$effort->account = 'admin';
r($taskTest->canOperateEffort($task, $effort)) && p() && e('1'); //判断进行中的串行多人任务并且当前日志创建者是当前用户
+2 -2
View File
@@ -85,7 +85,7 @@ $user2->estimate = 2;
$user2->consumed = 2;
$user2->left = 2;
$team = array('po82' => $user1, 'user92' => $user2);
$team = array($user1, $user2);
$autoStatusList = array(true, false);
@@ -102,4 +102,4 @@ r($task->computeHours4MultipleTest($task5, $task6, $team)) && p('id,ass
r($task->computeHours4MultipleTest($task7)) && p('id,assignedTo,status,estimate,consumed,left') && e('0'); // 老task不存在的情况有新老task和团队计算多人工时
r($task->computeHours4MultipleTest($task7, $task8)) && p('id,assignedTo,status,estimate,consumed,left') && e('0'); // 老task不存在的情况有新老task计算多人工时
r($task->computeHours4MultipleTest($task1, $task8, $team)) && p('id,assignedTo,status,estimate,consumed,left') && e('10001,po82,doing,3,3,3'); // 新task不存在的情况有新老task和团队计算多人工时
$db->restoreDB();
$db->restoreDB();
+61
View File
@@ -0,0 +1,61 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/task.class.php';
su('admin');
/**
title=taskModel->getAssignedTo4Multi();
cid=1
pid=1
获取非多人任务的指派给 >> admin
获取非串行多人任务的指派给 >> null
获取串行多人任务的指派给 >> admin
获取排除已经完成的串行多人任务的指派给 >> dev1
获取串行多人任务的下一个指派给 >> admin
获取已经完成的串行多人任务的指派给 >> dev1
*/
$user = new stdclass();
$user->account = 'admin';
$user->status = 'wait';
$user->order = '0';
$users[] = $user;
$user = new stdclass();
$user->account = 'dev1';
$user->status = 'wait';
$user->order = '1';
$users[] = $user;
$user = new stdclass();
$user->account = 'admin';
$user->status = 'wait';
$user->order = '2';
$users[] = $user;
$task = new stdclass();
$task->mode = '';
$task->openedBy = 'dev1';
$task->assignedTo = 'admin';
$taskTest = new taskTest();
r($taskTest->getAssignedTo4Multi($users, $task)) && p() && e('admin'); //获取非多人任务的指派给
$task->mode = 'multi';
$task->team = $users;
r($taskTest->getAssignedTo4Multi($users, $task)) && p() && e('admin'); //获取非串行多人任务的指派给
$task->mode = 'linear';
r($taskTest->getAssignedTo4Multi($users, $task)) && p() && e('admin'); //获取串行多人任务的指派给
$users[0]->status = 'done';
r($taskTest->getAssignedTo4Multi($users, $task)) && p() && e('dev1'); //获取排除已经完成的串行多人任务的指派给
r($taskTest->getAssignedTo4Multi($users, $task, 'next')) && p() && e('admin'); //获取串行多人任务的下一个指派给
$users[1]->status = 'done';
$users[2]->status = 'done';
r($taskTest->getAssignedTo4Multi($users, $task)) && p() && e('dev1'); //获取已经完成的串行多人任务的指派给
-32
View File
@@ -1,32 +0,0 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/task.class.php';
su('admin');
/**
title=taskModel->getDataOfTasksPerEstimate();
cid=1
pid=1
计算current为0的下一个用户 >> user1
计算current为1的下一个用户 >> user2
计算current为2的下一个用户 >> po1
计算current为3的下一个用户 >> po2
计算current为4的下一个用户 >> pm1
计算current为5的下一个用户 >> pm2
计算current为6的下一个用户 >> admin
*/
$users = array('admin', 'user1', 'user2', 'po1', 'po2', 'pm1', 'pm2');
$task = new taskTest();
r($task->getNextUserTest($users, $users[0])) && p() && e('user1'); //计算current为0的下一个用户
r($task->getNextUserTest($users, $users[1])) && p() && e('user2'); //计算current为1的下一个用户
r($task->getNextUserTest($users, $users[2])) && p() && e('po1'); //计算current为2的下一个用户
r($task->getNextUserTest($users, $users[3])) && p() && e('po2'); //计算current为3的下一个用户
r($task->getNextUserTest($users, $users[4])) && p() && e('pm1'); //计算current为4的下一个用户
r($task->getNextUserTest($users, $users[5])) && p() && e('pm2'); //计算current为5的下一个用户
r($task->getNextUserTest($users, $users[6])) && p() && e('admin'); //计算current为6的下一个用户
+49
View File
@@ -0,0 +1,49 @@
#!/usr/bin/env php
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/task.class.php';
su('admin');
/**
title=taskModel->getTeamByAccount();
cid=1
pid=1
获取未开始的指定账号的团队信息 >> admin_wait
获取进行中的指定账号的团队信息 >> admin_doing
过滤已完成的成员获取的指定账号的团队信息 >> admin_wait
不过滤已完成的成员获取的指定账号的团队信息 >> admin_done
获取的不存在账号 >> _
*/
$user = new stdclass();
$user->account = 'admin';
$user->status = 'wait';
$user->order = '0';
$users[] = $user;
$user = new stdclass();
$user->account = 'dev1';
$user->status = 'wait';
$user->order = '1';
$users[] = $user;
$user = new stdclass();
$user->account = 'admin';
$user->status = 'wait';
$user->order = '2';
$users[] = $user;
$task = new taskTest();
r($task->getTeamByAccount($users, 'admin')) && p() && e('admin_wait'); //获取未开始的指定账号的团队信息
$users[0]->status = 'doing';
r($task->getTeamByAccount($users, 'admin')) && p() && e('admin_doing'); //获取进行中的指定账号的团队信息
$users[0]->status = 'done';
r($task->getTeamByAccount($users, 'admin')) && p() && e('admin_wait'); //过滤已完成的成员获取的指定账号的团队信息
r($task->getTeamByAccount($users, 'admin', array('filter' => ''))) && p() && e('admin_done'); //不过滤已完成的成员获取的指定账号的团队信息
r($task->getTeamByAccount($users, 'dev')) && p() && e('_'); //获取的不存在账号