diff --git a/db/update17.4.sql b/db/update17.4.sql
index 9b2e71b002..f8ea4c6321 100644
--- a/db/update17.4.sql
+++ b/db/update17.4.sql
@@ -200,3 +200,5 @@ ALTER TABLE `zt_sqlview` ENGINE='InnoDB';
ALTER TABLE `zt_searchindex` ADD FULLTEXT `title_content` (`title`, `content`);
ALTER TABLE `zt_searchindex` DROP INDEX `title`;
ALTER TABLE `zt_searchindex` DROP INDEX `content`;
+
+UPDATE `zt_project` SET `closedDate`='' AND `closedBy`='' WHERE `status` != 'closed';
diff --git a/module/bug/model.php b/module/bug/model.php
index b452613563..4b0b722e25 100644
--- a/module/bug/model.php
+++ b/module/bug/model.php
@@ -1719,8 +1719,8 @@ class bugModel extends model
->beginIF($type != 'closedBy' and $this->app->moduleName == 'block')->andWhere('t1.status')->ne('closed')->fi()
->beginIF($type != 'all' and $type != 'bySearch')->andWhere("t1.`$type`")->eq($account)->fi()
->beginIF($type == 'bySearch' and $moduleName == 'workBug')->andWhere("t1.assignedTo")->eq($account)->fi()
- ->beginIF($type == 'bySearch' and $moduleName == 'contributeBug')
->beginIF($type == 'assignedTo' and $moduleName == 'workBug')->andWhere('t1.status')->ne('closed')->fi()
+ ->beginIF($type == 'bySearch' and $moduleName == 'contributeBug')
->andWhere('t1.openedBy', 1)->eq($account)
->orWhere('t1.closedBy')->eq($account)
->orWhere('t1.resolvedBy')->eq($account)
diff --git a/module/execution/config.php b/module/execution/config.php
index f9b0af12cf..46880f681f 100644
--- a/module/execution/config.php
+++ b/module/execution/config.php
@@ -119,6 +119,39 @@ $config->execution->search['params']['canceledDate'] = array('operator' => '='
$config->execution->search['params']['lastEditedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
$config->execution->search['params']['activatedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
+$app->loadLang('execution');
+$config->execution->all = new stdclass();
+$config->execution->all->search['module'] = 'execution';
+$config->execution->all->search['fields']['name'] = $lang->execution->execName;
+$config->execution->all->search['fields']['id'] = $lang->execution->execId;
+$config->execution->all->search['fields']['status'] = $lang->execution->execStatus;
+$config->execution->all->search['fields']['project'] = $lang->execution->project;
+$config->execution->all->search['fields']['PM'] = $lang->execution->owner;
+$config->execution->all->search['fields']['openedBy'] = $lang->execution->openedBy;
+$config->execution->all->search['fields']['openedDate'] = $lang->execution->openedDate;
+$config->execution->all->search['fields']['begin'] = $lang->execution->begin;
+$config->execution->all->search['fields']['end'] = $lang->execution->end;
+$config->execution->all->search['fields']['realBegan'] = $lang->execution->realBegan;
+$config->execution->all->search['fields']['realEnd'] = $lang->execution->realEnd;
+$config->execution->all->search['fields']['closedBy'] = $lang->execution->closedBy;
+$config->execution->all->search['fields']['lastEditedDate'] = $lang->execution->lastEditedDate;
+$config->execution->all->search['fields']['closedDate'] = $lang->execution->closedDate;
+
+$config->execution->all->search['params']['name'] = array('operator' => 'include', 'control' => 'input', 'values' => '');
+$config->execution->all->search['params']['id'] = array('operator' => '=', 'control' => 'input', 'values' => '');
+$config->execution->all->search['params']['status'] = array('operator' => '=', 'control' => 'select', 'values' => array('') + $lang->execution->statusList);
+$config->execution->all->search['params']['project'] = array('operator' => '=', 'control' => 'select', 'values' => '');
+$config->execution->all->search['params']['PM'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
+$config->execution->all->search['params']['openedBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
+$config->execution->all->search['params']['openedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
+$config->execution->all->search['params']['begin'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
+$config->execution->all->search['params']['end'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
+$config->execution->all->search['params']['realBegan'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
+$config->execution->all->search['params']['realEnd'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
+$config->execution->all->search['params']['closedBy'] = array('operator' => '=', 'control' => 'select', 'values' => 'users');
+$config->execution->all->search['params']['lastEditedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
+$config->execution->all->search['params']['closedDate'] = array('operator' => '=', 'control' => 'input', 'values' => '', 'class' => 'date');
+
$config->printKanban = new stdClass();
$config->printKanban->col['story'] = 1;
$config->printKanban->col['wait'] = 2;
diff --git a/module/execution/control.php b/module/execution/control.php
index d1b3a9c8f4..a8a7f93e52 100644
--- a/module/execution/control.php
+++ b/module/execution/control.php
@@ -241,7 +241,7 @@ class execution extends control
$this->view->moduleID = $moduleID;
$this->view->moduleTree = $this->tree->getTaskTreeMenu($executionID, $productID, $startModuleID = 0, array('treeModel', 'createTaskLink'), $extra);
$this->view->memberPairs = $memberPairs;
- $this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products), 'noempty');
+ $this->view->branchGroups = $this->loadModel('branch')->getByProducts(array_keys($products));
$this->view->setModule = true;
$this->view->canBeChanged = common::canModify('execution', $execution); // Determines whether an object is editable.
$this->view->showBranch = $showBranch;
@@ -3678,13 +3678,14 @@ class execution extends control
* @param int $projectID
* @param string $orderBy
* @param int $productID
+ * @param string $param
* @param int $recTotal
* @param int $recPerPage
* @param int $pageID
* @access public
* @return void
*/
- public function all($status = 'undone', $projectID = 0, $orderBy = 'order_asc', $productID = 0, $recTotal = 0, $recPerPage = 100, $pageID = 1)
+ public function all($status = 'undone', $projectID = 0, $orderBy = 'order_asc', $productID = 0, $param = '', $recTotal = 0, $recPerPage = 100, $pageID = 1)
{
$this->app->loadLang('my');
$this->app->loadLang('product');
@@ -3714,10 +3715,14 @@ class execution extends control
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
+ $queryID = ($status == 'bySearch') ? (int)$param : 0;
+ $actionURL = $this->createLink('execution', 'all', "status=bySearch&projectID=$projectID&orderBy=$orderBy&productID=$productID¶m=myQueryID");
+ $this->execution->buildSearchFrom($queryID, $actionURL);
+
$this->view->title = $this->lang->execution->allExecutions;
$this->view->position[] = $this->lang->execution->allExecutions;
- $executionStats = $this->project->getStats($projectID, $status, $productID, 0, 30, $orderBy, $pager);
+ $executionStats = $this->project->getStats($projectID, $status, $productID, 0, 30, $orderBy, $pager, false, $queryID);
$parentIdList = array();
foreach($executionStats as $execution)
@@ -3742,6 +3747,7 @@ class execution extends control
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->view->status = $status;
$this->view->from = $from;
+ $this->view->param = $param;
$this->view->isStage = (isset($project->model) and $project->model == 'waterfall') ? true : false;
$this->display();
diff --git a/module/execution/css/all.css b/module/execution/css/all.css
index 36584c5c7a..f13f24181c 100644
--- a/module/execution/css/all.css
+++ b/module/execution/css/all.css
@@ -35,3 +35,4 @@ canvas {height: 28px;}
.parent.has-child.c-name.flex, .table-child-bottom > .c-name.flex {border-bottom: 1px solid #cbd0db !important;}
.parent.has-child.c-name.flex {margin-bottom: -2px !important;}
#tableCustomBtn {padding-bottom: 5px;}
+#bysearchTab {margin-left: 5px;}
diff --git a/module/execution/lang/de.php b/module/execution/lang/de.php
index e2c713bd1e..0ee79e91a9 100644
--- a/module/execution/lang/de.php
+++ b/module/execution/lang/de.php
@@ -137,6 +137,7 @@ $lang->execution->batchCreateTask = 'Batch create task';
$lang->execution->kanbanNoLinkProduct = "Kanban not linked {$lang->productCommon}";
$lang->execution->myTask = "My Task";
$lang->execution->list = "{$lang->executionCommon} List";
+$lang->execution->allProject = 'All';
/* Fields of zt_team. */
$lang->execution->root = 'Root';
diff --git a/module/execution/lang/en.php b/module/execution/lang/en.php
index ee0fd4982f..cce5e775fa 100644
--- a/module/execution/lang/en.php
+++ b/module/execution/lang/en.php
@@ -137,11 +137,12 @@ $lang->execution->batchCreateTask = 'Batch create task';
$lang->execution->kanbanNoLinkProduct = "Kanban not linked {$lang->productCommon}";
$lang->execution->myTask = "My Task";
$lang->execution->list = 'List';
+$lang->execution->allProject = 'All';
/* Fields of zt_team. */
$lang->execution->root = 'Root';
-$lang->execution->estimate = 'estimate';
-$lang->execution->consumed = 'consumed';
+$lang->execution->estimate = 'Estimate';
+$lang->execution->consumed = 'Consumed';
$lang->execution->left = 'Left';
if($this->config->systemMode == 'new') $lang->execution->copyTeamTip = "copy Project/{$lang->execution->common} team members";
diff --git a/module/execution/lang/fr.php b/module/execution/lang/fr.php
index 9915245c72..6e586431fd 100644
--- a/module/execution/lang/fr.php
+++ b/module/execution/lang/fr.php
@@ -137,6 +137,7 @@ $lang->execution->batchCreateTask = 'Batch create task';
$lang->execution->kanbanNoLinkProduct = "Kanban not linked {$lang->productCommon}";
$lang->execution->myTask = "My Task";
$lang->execution->list = "{$lang->executionCommon} List";
+$lang->execution->allProject = 'Tous';
/* Fields of zt_team. */
$lang->execution->root = 'Root';
diff --git a/module/execution/lang/zh-cn.php b/module/execution/lang/zh-cn.php
index ea81fd5260..e74392e1c6 100644
--- a/module/execution/lang/zh-cn.php
+++ b/module/execution/lang/zh-cn.php
@@ -137,6 +137,7 @@ $lang->execution->batchCreateTask = '批量建任务';
$lang->execution->kanbanNoLinkProduct = "看板没有关联{$lang->productCommon}";
$lang->execution->myTask = "我的任务";
$lang->execution->list = '列表';
+$lang->execution->allProject = '全部项目';
/* Fields of zt_team. */
$lang->execution->root = '源ID';
diff --git a/module/execution/model.php b/module/execution/model.php
index 1cce86f1be..9a090b9465 100644
--- a/module/execution/model.php
+++ b/module/execution/model.php
@@ -949,6 +949,8 @@ class executionModel extends model
->setDefault('status', 'doing')
->setDefault('lastEditedBy', $this->app->user->account)
->setDefault('lastEditedDate', $now)
+ ->setDefault('closedBy', '')
+ ->setDefault('closedDate', '')
->stripTags($this->config->execution->editor->activate['id'], $this->config->allowedTags)
->remove('comment,readjustTime,readjustTask')
->get();
@@ -4722,4 +4724,23 @@ class executionModel extends model
echo '';
}
}
+
+ /*
+ * Build search form
+ *
+ * @param int $queryID
+ * @param string $actionURL
+ * @return void
+ * */
+ public function buildSearchFrom($queryID, $actionURL)
+ {
+ $this->config->execution->all->search['queryID'] = $queryID;
+ $this->config->execution->all->search['actionURL'] = $actionURL;
+
+ $projectPairs = array(0 => '');
+ $projectPairs += $this->loadModel('project')->getPairsByProgram();
+ $this->config->execution->all->search['params']['project']['values'] = $projectPairs + array('all' => $this->lang->execution->allProject);
+
+ $this->loadModel('search')->setSearchParams($this->config->execution->all->search);
+ }
}
diff --git a/module/execution/view/all.html.php b/module/execution/view/all.html.php
index 2cca80f2ba..547fec517a 100644
--- a/module/execution/view/all.html.php
+++ b/module/execution/view/all.html.php
@@ -58,6 +58,7 @@ js::set('isCNLang', !$this->loadModel('common')->checkNotCN())
execution->selectProject}'");?>
+ execution->byQuery;?>
" . $lang->export, '', "class='btn btn-link export'")?>
@@ -69,6 +70,7 @@ js::set('isCNLang', !$this->loadModel('common')->checkNotCN())
+
@@ -91,7 +93,7 @@ js::set('isCNLang', !$this->loadModel('common')->checkNotCN())
recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";
+ $vars = "status=$status&projectID=$projectID&orderBy=%s&productID=$productID¶m=$param&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";
if($useDatatable) include '../../common/view/datatable.html.php';
else include '../../common/view/tablesorter.html.php';
diff --git a/module/execution/view/grouptask.html.php b/module/execution/view/grouptask.html.php
index d531a87e5c..6446735df7 100644
--- a/module/execution/view/grouptask.html.php
+++ b/module/execution/view/grouptask.html.php
@@ -226,6 +226,7 @@
assignedTo])) printf($lang->execution->memberHours, zget($users, $task->assignedTo), $members[$task->assignedTo]->totalHours);?>
+ assignedTo and !isset($members[$task->assignedTo])) printf($lang->execution->memberHours, zget($users, $task->assignedTo), '0.0');?>
assignedTo)):?>
diff --git a/module/kanban/js/view.js b/module/kanban/js/view.js
index 7e39e60137..5bec4a50a1 100644
--- a/module/kanban/js/view.js
+++ b/module/kanban/js/view.js
@@ -407,7 +407,7 @@ function renderKanbanItem(item, $item)
$user.html(renderUsersAvatar(assignedTo, item.id)).attr('title', title);
}
- if(kanban.performable == 1)
+ if(kanban.performable == 1 && (item.fromType == '' || item.fromType == 'execution'))
{
var $progress = $item.children('.progress-box');
if(!$progress.length) $progress = $(' ').appendTo($item);
@@ -1189,7 +1189,7 @@ function createCardMenu(options)
var items = [];
if(privs.includes('editCard') && card.fromType == '') items.push({label: kanbanLang.editCard, icon: 'edit', url: createLink('kanban', 'editCard', 'cardID=' + card.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}});
if(privs.includes('deleteCard')) items.push({label: card.fromType == '' ? kanbanLang.deleteCard : kanbanLang.removeCard, icon: card.fromType == '' ? 'trash' : 'unlink', url: createLink('kanban', 'deleteCard', 'cardID=' + card.id), attrs: {'target': 'hiddenwin'}});
- if(kanban.performable == 1)
+ if(kanban.performable == 1 && card.fromType == '')
{
if(card.status == 'done')
{
diff --git a/module/kanban/model.php b/module/kanban/model.php
index f4c67e50d7..e95c66f0b8 100644
--- a/module/kanban/model.php
+++ b/module/kanban/model.php
@@ -1207,6 +1207,10 @@ class kanbanModel extends model
->andWhere('action')->eq('opened')
->fetchPairs();
}
+ elseif($fromType == 'execution')
+ {
+ $executionProgress = $this->loadModel('project')->computerProgress($objects);
+ }
/* Data for constructing the card. */
foreach($objectCards as $objectID => $cardsInfo)
@@ -1231,6 +1235,7 @@ class kanbanModel extends model
if($delay > 0) $objectCard->delay = $delay;
}
$objectCard->execType = $object->type;
+ $objectCard->progress = isset($executionProgress[$objectID]->progress) ? $executionProgress[$objectID]->progress : 0;
}
$objectCard->desc = strip_tags(htmlspecialchars_decode($object->desc));
diff --git a/module/kanban/view/viewarchivedcard.html.php b/module/kanban/view/viewarchivedcard.html.php
index 74a334d0c1..d12d129862 100644
--- a/module/kanban/view/viewarchivedcard.html.php
+++ b/module/kanban/view/viewarchivedcard.html.php
@@ -47,7 +47,12 @@
#archivedCards .card-item .has-color .info > .label-pri {border-color: #FFFFFF;}
#archivedCards .card-item .has-color .progress-box > .progress-number {color: #FFFFFF;}
#archivedCards .progress-box {width: 97%;}
-#performable {padding: 25px 10px !important;}
+#archivedCards .no-progress {padding: 7px 10px !important;}
+#archivedCards .has-progress {padding: 21px 10px !important;}
+#archivedCards .has-desc.has-progress {padding: 26px 10px !important;}
+#archivedCards .has-desc.no-progress {padding: 19px 10px !important;}
+#archivedCards .has-avatar.has-progress {padding: 24px 10px !important;}
+#archivedCards .has-avatar.no-progress {padding: 9px 10px !important;}
loadLang('execution');
@@ -71,6 +76,7 @@ js::set('systemMode', $this->config->systemMode);
color == '#b10b0b') $color = 'has-color red';
if($card->color == '#cfa227') $color = 'has-color yellow';
@@ -98,7 +104,11 @@ js::set('systemMode', $this->config->systemMode);
$name = isset($card->title) ? $card->title : $card->name;
if(common::hasPriv($card->fromType, 'view')) echo html::a($this->createLink($card->fromType, 'view', "id=$card->fromID"), $name, '', "class='cardName' title='$name'");
if(!common::hasPriv($card->fromType, 'view')) echo " $name ";
- if($card->fromType == 'productplan' or $card->fromType == 'build') echo " $card->desc ";
+ if($card->fromType == 'productplan' or $card->fromType == 'build')
+ {
+ echo " $card->desc ";
+ if(!empty($card->desc)) $class .= ' has-desc';
+ }
echo " ";
if(isset($lang->{$card->fromType}->statusList[$card->objectStatus])) echo " " . $lang->{$card->fromType}->statusList[$card->objectStatus] . '';
if(isset($card->date) and !helper::isZeroDate($card->date)) echo " " . date("Y-m-d", strtotime($card->date)) . ""
@@ -147,6 +157,7 @@ js::set('systemMode', $this->config->systemMode);
if($count > 2) continue;
echo html::smallAvatar(array('avatar' => $usersAvatar[$account], 'account' => $account, 'name' => $users[$account]), 'avatar-circle');
$count ++;
+ $class .= ' has-avatar';
}
?>
2) echo " ...";?>
@@ -159,11 +170,12 @@ js::set('systemMode', $this->config->systemMode);
echo " ";
echo html::smallAvatar(array('avatar' => $usersAvatar[$assignedToList], 'account' => $assignedToList, 'name' => $users[$assignedToList]), 'avatar-circle');
echo " ";
+ $class .= ' has-avatar';
}
?>
- performable):?>
+ performable and ($card->fromType == 'execution' or empty($card->fromType))):?>
@@ -173,7 +185,8 @@ js::set('systemMode', $this->config->systemMode);
- performable) echo "id='performable'";?>>
+ performable) and ($card->fromType == 'execution' or empty($card->fromType))) ? ' has-progress' : ' no-progress';?>
+
config->CRKanban) and $this->config->CRKanban == '0' and $kanban->status == 'closed');
$canRestore = (commonModel::hasPriv('kanban', 'restoreCard') and $CRKanban);
diff --git a/module/productplan/view/view.html.php b/module/productplan/view/view.html.php
index 64e329c22f..815900cdc4 100644
--- a/module/productplan/view/view.html.php
+++ b/module/productplan/view/view.html.php
@@ -189,7 +189,7 @@
parent > 0) echo "story->children}>{$lang->story->childrenAB}";
- echo html::a($viewLink , $story->title);
+ echo html::a($viewLink , $story->title, '', "style='color: $story->color'");
?>
|
openedBy);?> |
diff --git a/module/project/js/execution.js b/module/project/js/execution.js
index 43337d4ee6..2d050e7b6e 100644
--- a/module/project/js/execution.js
+++ b/module/project/js/execution.js
@@ -180,7 +180,7 @@ function showEditCheckbox(show)
executionID = $tr.attr('data-id');
if(show)
{
- var marginLeft = $tr.find('td:first').find('span.table-nest-icon').css('margin-left');
+ var marginLeft = '7px';
$tr.find('td:first').prepend(" ");
$tr.find('td:first').find('.checkbox-primary').css('margin-left', marginLeft).css('width', '14');
diff --git a/module/project/model.php b/module/project/model.php
index ae369657db..6ca006a7df 100644
--- a/module/project/model.php
+++ b/module/project/model.php
@@ -2329,17 +2329,48 @@ class projectModel extends model
* @param int $projectID
* @param string $status
* @param int $productID
+ * @param int $branch
* @param int $itemCounts
* @param string $orderBy
* @param object $pager
+ * @param bool $withTasks
+ * @param int $queryID
* @access public
* @return array
*/
- public function getStats($projectID = 0, $status = 'undone', $productID = 0, $branch = 0, $itemCounts = 30, $orderBy = 'id_asc', $pager = null, $withTasks = false)
+ public function getStats($projectID = 0, $status = 'undone', $productID = 0, $branch = 0, $itemCounts = 30, $orderBy = 'id_asc', $pager = null, $withTasks = false, $queryID = 0)
{
if(empty($productID))
{
$myExecutionIDList = array();
+ $query = '';
+ if($status == 'bySearch')
+ {
+ $status = 'all';
+ if($queryID)
+ {
+ $query = $this->loadModel('search')->getQuery($queryID);
+ if($query)
+ {
+ $this->session->set('executionQuery', $query->sql);
+ $this->session->set('executionForm', $query->form);
+ }
+ else
+ {
+ $this->session->set('executionQuery', ' 1 = 1');
+ }
+ }
+ else
+ {
+ if($this->session->executionQuery == false) $this->session->set('executionQuery', ' 1 = 1');
+ }
+ $query = $this->session->executionQuery;
+ $allProject = "`project` = 'all'";
+
+ if(strpos($query, $allProject) !== false) $query = str_replace($allProject, '1', $query);
+ $query = preg_replace('/(`\w*`)/', 't1.$1',$query);
+ }
+
if($status == 'involved')
{
$myExecutionIDList = $this->dao->select('root')->from(TABLE_TEAM)
@@ -2351,6 +2382,7 @@ class projectModel extends model
$executions = $this->dao->select('t1.*,t2.name projectName, t2.model as projectModel')->from(TABLE_EXECUTION)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id')
->where('t1.type')->in('sprint,stage,kanban')
+ ->beginIF(!empty($query))->andWhere($query)->fi()
->beginIF($projectID != 0)->andWhere('t1.project')->eq($projectID)->fi()
->beginIF($projectID == 0 and $this->config->vision)->andWhere('t1.vision')->eq($this->config->vision)->fi()
->beginIF(!empty($myExecutionIDList))->andWhere('t1.id')->in(array_keys($myExecutionIDList))->fi()
diff --git a/module/story/model.php b/module/story/model.php
index 7a6f038151..bcbcbbfb42 100644
--- a/module/story/model.php
+++ b/module/story/model.php
@@ -1841,15 +1841,20 @@ class storyModel extends model
if($oldStory->branch) $story->plan = $planID;
/* Append the plan id to plan field if product is multi and story is all branch. */
- if($this->session->currentProductType != 'normal' and empty($story->branch) and $planID != 0)
+ if($this->session->currentProductType != 'normal' and empty($story->branch))
{
$branchPlanPairs = $this->dao->select('branch, id as plan')->from(TABLE_PRODUCTPLAN)
->where('product')->eq($oldStory->product)
->andWhere('id')->in($oldStory->plan)
->fetchPairs();
- if(isset($branchPlanPairs[$plan->branch])) $branchPlanPairs[$plan->branch] = $planID;
-
- $story->plan = $oldStory->plan ? ',' . implode(',', $branchPlanPairs) : ",$planID";
+ if($planID == 0 and !empty($oldStory->plan) and isset($branchPlanPairs[0]) and $branchPlanPairs[0] != $planID) $unlinkPlans[$branchPlanPairs[0]] = empty($unlinkPlans[$branchPlanPairs[0]]) ? $storyID : "{$unlinkPlans[$branchPlanPairs[0]]},$storyID";
+ if($planID != 0)
+ {
+ if(!empty($oldStory->plan) and isset($branchPlanPairs[$plan->branch]) and $branchPlanPairs[$plan->branch] != $planID) $unlinkPlans[$branchPlanPairs[$plan->branch]] = empty($unlinkPlans[$branchPlanPairs[$plan->branch]]) ? $storyID : "{$unlinkPlans[$branchPlanPairs[$plan->branch]]},$storyID";
+ if(isset($branchPlanPairs[$plan->branch])) $branchPlanPairs[$plan->branch] = $planID;
+ $story->plan = $oldStory->plan ? ',' . implode(',', $branchPlanPairs) : ",$planID";
+ if($story->plan != $oldStory->plan and !empty($planID)) $link2Plans[$planID] = empty($link2Plans[$planID]) ? $storyID : "{$link2Plans[$planID]},$storyID";
+ }
}
/* Change stage. */
@@ -1878,8 +1883,8 @@ class storyModel extends model
if(!dao::isError())
{
$allChanges[$storyID] = common::createChanges($oldStory, $story);
- if($story->plan != $oldStory->plan and !empty($oldStory->plan)) $unlinkPlans[$oldStory->plan] = empty($unlinkPlans[$oldStory->plan]) ? $storyID : "{$unlinkPlans[$oldStory->plan]},$storyID";
- if($story->plan != $oldStory->plan and !empty($story->plan)) $link2Plans[$story->plan] = empty($link2Plans[$story->plan]) ? $storyID : "{$link2Plans[$story->plan]},$storyID";
+ if($story->plan != $oldStory->plan and !empty($oldStory->plan) and strpos($story->plan, ',') === false) $unlinkPlans[$oldStory->plan] = empty($unlinkPlans[$oldStory->plan]) ? $storyID : "{$unlinkPlans[$oldStory->plan]},$storyID";
+ if($story->plan != $oldStory->plan and !empty($story->plan) and strpos($story->plan, ',') === false) $link2Plans[$story->plan] = empty($link2Plans[$story->plan]) ? $storyID : "{$link2Plans[$story->plan]},$storyID";
}
}
diff --git a/module/task/model.php b/module/task/model.php
index f8001be55f..12455fedf8 100644
--- a/module/task/model.php
+++ b/module/task/model.php
@@ -63,6 +63,7 @@ class taskModel extends model
$requiredFields = str_replace(",story,", ',', "$requiredFields");
$requiredFields = str_replace(",estStarted,", ',', "$requiredFields");
$requiredFields = str_replace(",deadline,", ',', "$requiredFields");
+ $requiredFields = str_replace(",module,", ',', "$requiredFields");
}
$this->loadModel('file');
@@ -3626,6 +3627,18 @@ class taskModel extends model
public function printAssignedHtml($task, $users)
{
$btnTextClass = '';
+ if(!empty($task->team) and $task->mode == 'multi' and $task->status != 'closed')
+ {
+ $assignedToText = $this->lang->task->team;
+
+ $teamMembers = array();
+ foreach($task->team as $teamMember) $teamMembers[] = zget($users, $teamMember->account);
+ $assignedToTitle = implode($this->lang->comma, $teamMembers);
+ }
+ else
+ {
+ $assignedToText = $assignedToTitle = zget($users, $task->assignedTo);
+ }
$assignedToText = (!empty($task->team) and $task->mode == 'multi' and $task->status != 'closed') ? $this->lang->task->team : zget($users, $task->assignedTo);
if(empty($task->assignedTo))
@@ -3638,7 +3651,7 @@ class taskModel extends model
$btnClass = $task->assignedTo == 'closed' ? ' disabled' : '';
$btnClass = "iframe btn btn-icon-left btn-sm {$btnClass}";
$assignToLink = $task->assignedTo == 'closed' ? '#' : helper::createLink('task', 'assignTo', "executionID=$task->execution&taskID=$task->id", '', true);
- $assignToHtml = html::a($assignToLink, " {$assignedToText}", '', "class='$btnClass'");
+ $assignToHtml = html::a($assignToLink, " {$assignedToText}", '', "class='$btnClass'");
echo !common::hasPriv('task', 'assignTo', $task) ? " {$assignedToText}" : $assignToHtml;
}
diff --git a/module/user/js/login.js b/module/user/js/login.js
index 31fe0854f2..9349326727 100644
--- a/module/user/js/login.js
+++ b/module/user/js/login.js
@@ -3,6 +3,8 @@ if(window.self !== window.top) window.top.location.href = window.location.href;
$(document).ready(function()
{
+ timeoutID = null;
+
/* Fix bug for misc-ping */
$('#hiddenwin').removeAttr('id');
@@ -33,10 +35,19 @@ $(document).ready(function()
var link = createLink('user', 'login');
var keepLogin = $('#keepLoginon').attr('checked') == 'checked' ? 1 : 0;
var captcha = $('#captcha').length == 1 ? $('#captcha').val() : '';
+ var timeout = true;
+
+ clearTimeout(timeoutID);
+ timeoutID = setTimeout(function()
+ {
+ if(timeout) alert(loginTimeoutTip);
+ }, 4000);
$.get(createLink('user', 'refreshRandom'), function(data)
{
var rand = data;
+ timeout = false;
+
$.ajax
({
url: link,
diff --git a/module/user/lang/de.php b/module/user/lang/de.php
index d52a0e5dc7..33808bfb72 100644
--- a/module/user/lang/de.php
+++ b/module/user/lang/de.php
@@ -251,6 +251,7 @@ $lang->user->error->noEmail = 'The user does not register email. Please
$lang->user->error->errorEmail = 'The account does not match the email. Please enter a new one.';
$lang->user->error->emailSetting = 'No email is configured in the system. Contact the admin to reset the email.';
$lang->user->error->sendMailFail = 'Message sending failed, please try again!';
+$lang->user->error->loginTimeoutTip = 'Login failed, please check if the proxy service is normal.';
$lang->user->contactFieldList['phone'] = $lang->user->phone;
$lang->user->contactFieldList['mobile'] = $lang->user->mobile;
diff --git a/module/user/lang/en.php b/module/user/lang/en.php
index f1460a4f46..0f314ec1c6 100644
--- a/module/user/lang/en.php
+++ b/module/user/lang/en.php
@@ -251,6 +251,7 @@ $lang->user->error->noEmail = 'The user does not register email. Please
$lang->user->error->errorEmail = 'The account does not match the email. Please enter a new one.';
$lang->user->error->emailSetting = 'No email is configured in the system. Contact the admin to reset the email.';
$lang->user->error->sendMailFail = 'Message sending failed, please try again!';
+$lang->user->error->loginTimeoutTip = 'Login failed, please check if the proxy service is normal.';
$lang->user->contactFieldList['phone'] = $lang->user->phone;
$lang->user->contactFieldList['mobile'] = $lang->user->mobile;
diff --git a/module/user/lang/fr.php b/module/user/lang/fr.php
index 4df771cfe6..622a42e2b3 100644
--- a/module/user/lang/fr.php
+++ b/module/user/lang/fr.php
@@ -251,6 +251,7 @@ $lang->user->error->noEmail = 'The user does not register email. Please
$lang->user->error->errorEmail = 'The account does not match the email. Please enter a new one.';
$lang->user->error->emailSetting = 'No email is configured in the system. Contact the admin to reset the email.';
$lang->user->error->sendMailFail = 'Message sending failed, please try again!';
+$lang->user->error->loginTimeoutTip = 'Échec de la connexion, veuillez vérifier si le service proxy est activé.';
$lang->user->contactFieldList['phone'] = $lang->user->phone;
$lang->user->contactFieldList['mobile'] = $lang->user->mobile;
diff --git a/module/user/lang/zh-cn.php b/module/user/lang/zh-cn.php
index 74af4e7151..37cafcb434 100644
--- a/module/user/lang/zh-cn.php
+++ b/module/user/lang/zh-cn.php
@@ -251,6 +251,7 @@ $lang->user->error->noEmail = '该用户未绑定邮箱,请联系管
$lang->user->error->errorEmail = '用户名和邮箱不匹配,请重新输入。';
$lang->user->error->emailSetting = '系统未配置发信邮箱,请联系管理员重置。';
$lang->user->error->sendMailFail = '邮件发送失败,请重试!';
+$lang->user->error->loginTimeoutTip = '系统登录失败,请检查代理服务是否正常';
$lang->user->contactFieldList['phone'] = $lang->user->phone;
$lang->user->contactFieldList['mobile'] = $lang->user->mobile;
diff --git a/module/user/view/login.html.php b/module/user/view/login.html.php
index 8490a2a58d..0530a028ad 100644
--- a/module/user/view/login.html.php
+++ b/module/user/view/login.html.php
@@ -11,6 +11,7 @@
include '../../common/view/header.lite.html.php';
if(empty($config->notMd5Pwd))js::import($jsRoot . 'md5.js');
?>
+user->error->loginTimeoutTip);?>
diff --git a/test/model/todo/createbycycle.php b/test/model/todo/createbycycle.php
index a1639b9ed8..959f65f5d6 100755
--- a/test/model/todo/createbycycle.php
+++ b/test/model/todo/createbycycle.php
@@ -2,6 +2,7 @@
switchDB();
su('admin');
/**
@@ -12,25 +13,28 @@ pid=1
测试创建周期日待办 >> 11
测试创建周期周待办 >> 9
-测试创建周期月待办 >> 70
+测试创建周期月待办 >> `%d`
*/
+$days = 31;
+$begin = call_user_func_array('date', array('Y-m-d'));
+$end = call_user_func_array('date', array('Y-m-d', strtotime("+$days days")));
$todo1 = new stdclass();
$todo1->name = 'cycle生成的待办1';
-$todo1->config = '{"specify":{"month":"0","day":"1"},"day":"1","type":"day","beforeDays":11,"end":"","begin":"2022-03-23"}';
+$todo1->config = '{"specify":{"month":"0","day":"1"},"day":"1","type":"day","beforeDays":11,"end":"' . $end . '","begin":"' . $begin . '"}';
$todo2 = new stdclass();
$todo2->name = 'cycle生成的待办2';
-$todo2->config = '{"specify":{"month":"0","day":"1"},"week":"2,4,7","type":"week","beforeDays":31,"end":"","begin":"2022-03-23"}';
+$todo2->config = '{"specify":{"month":"0","day":"1"},"week":"2,4,7","type":"week","beforeDays":31,"end":"' . $end . '","begin":"' . $begin . '"}';
$todo3 = new stdclass();
$todo3->name = 'cycle生成的待办3';
-$todo3->config = '{"specify":{"month":"0","day":"1"},"month":"1,8,13,15,27,29,30","type":"month","beforeDays":301,"end":"","begin":"2022-03-23"}';
+$todo3->config = '{"specify":{"month":"0","day":"1"},"month":"1,8,13,15,27,29,30","type":"month","beforeDays":301,"end":"' . $end . '","begin":"' . $begin . '"}';
$todo = new todoTest();
-r($todo->createByCycleTest($todo1)) && p() && e('11'); // 测试创建周期日待办
-r($todo->createByCycleTest($todo2)) && p() && e('9'); // 测试创建周期周待办
-r($todo->createByCycleTest($todo3)) && p() && e('70'); // 测试创建周期月待办
-system("./ztest init");
+r($todo->createByCycleTest($todo1)) && p() && e('11'); // 测试创建周期日待办
+r($todo->createByCycleTest($todo2)) && p() && e('9'); // 测试创建周期周待办
+r($todo->createByCycleTest($todo3)) && p() && e('`%d`'); // 测试创建周期月待办
+$db->restoreDB();
|