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

This commit is contained in:
tanghucheng
2022-08-04 00:03:14 +08:00
27 changed files with 189 additions and 31 deletions
+2
View File
@@ -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';
+1 -1
View File
@@ -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)
+33
View File
@@ -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;
+9 -3
View File
@@ -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&param=myQueryID");
$this->execution->buildSearchFrom($queryID, $actionURL);
$this->view->title = $this->lang->execution->allExecutions;
$this->view->position[] = $this->lang->execution->allExecutions;
$executionStats = $this->project->getStats($projectID, $status, $productID, 0, 30, $orderBy, $pager);
$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();
+1
View File
@@ -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;}
+1
View File
@@ -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';
+3 -2
View File
@@ -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";
+1
View File
@@ -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';
+1
View File
@@ -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';
+21
View File
@@ -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 '</td>';
}
}
/*
* 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);
}
}
+3 -1
View File
@@ -58,6 +58,7 @@ js::set('isCNLang', !$this->loadModel('common')->checkNotCN())
<?php echo html::select('project', $projects, $projectID, "class='form-control chosen' data-placeholder='{$lang->execution->selectProject}'");?>
</div>
<?php endif;?>
<a class="btn btn-link querybox-toggle" id='bysearchTab'><i class="icon icon-search muted"></i> <?php echo $lang->execution->byQuery;?></a>
</div>
<div class='btn-toolbar pull-right'>
<?php common::printLink('execution', 'export', "status=$status&productID=$productID&orderBy=$orderBy&from=$from", "<i class='icon-export muted'> </i> " . $lang->export, '', "class='btn btn-link export'")?>
@@ -69,6 +70,7 @@ js::set('isCNLang', !$this->loadModel('common')->checkNotCN())
</div>
</div>
<div id='mainContent' class="main-row fade">
<div class="cell<?php if($status == 'bySearch') echo ' show';?>" id="queryBox" data-module='execution'></div>
<?php if(empty($executionStats)):?>
<div class="table-empty-tip">
<p>
@@ -91,7 +93,7 @@ js::set('isCNLang', !$this->loadModel('common')->checkNotCN())
<nav class="btn-toolbar pull-right setting"></nav>
</div>
<?php
$vars = "status=$status&projectID=$projectID&orderBy=%s&productID=$productID&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";
$vars = "status=$status&projectID=$projectID&orderBy=%s&productID=$productID&param=$param&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";
if($useDatatable) include '../../common/view/datatable.html.php';
else include '../../common/view/tablesorter.html.php';
+1
View File
@@ -226,6 +226,7 @@
<td colspan='13'>
<div class="table-row segments-list">
<?php if($groupBy == 'assignedTo' and isset($members[$task->assignedTo])) printf($lang->execution->memberHours, zget($users, $task->assignedTo), $members[$task->assignedTo]->totalHours);?>
<?php if($groupBy == 'assignedTo' and $task->assignedTo and !isset($members[$task->assignedTo])) printf($lang->execution->memberHours, zget($users, $task->assignedTo), '0.0');?>
<?php if($groupBy == 'assignedTo' and empty($task->assignedTo)):?>
<div class="table-col">
<div class="clearfix segments">
+2 -2
View File
@@ -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 = $('<div class="progress-box"><div class="progress"><div class="progress-bar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width: ' + item.progress + '%;"></div></div><div class="progress-number">' + item.progress + '%</div></div>').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')
{
+5
View File
@@ -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));
+17 -4
View File
@@ -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;}
</style>
<?php
$app->loadLang('execution');
@@ -71,6 +76,7 @@ js::set('systemMode', $this->config->systemMode);
<div class='card-item' data-card='<?php echo $card->id;?>'>
<div class='col-xs-10'>
<?php
$class = '';
$color = '';
if($card->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 "<div class='cardName' title='$name'>$name</div>";
if($card->fromType == 'productplan' or $card->fromType == 'build') echo "<div class='desc' title='$card->desc'>$card->desc</div>";
if($card->fromType == 'productplan' or $card->fromType == 'build')
{
echo "<div class='desc' title='$card->desc'>$card->desc</div>";
if(!empty($card->desc)) $class .= ' has-desc';
}
echo "<div class='info $card->fromType'>";
if(isset($lang->{$card->fromType}->statusList[$card->objectStatus])) echo "<span class='label label-$card->objectStatus'>" . $lang->{$card->fromType}->statusList[$card->objectStatus] . '</span>';
if(isset($card->date) and !helper::isZeroDate($card->date)) echo "<span class='time label label-light'>" . date("Y-m-d", strtotime($card->date)) . "</span>"
@@ -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';
}
?>
<?php if($count > 2) echo "<span>...</span>";?>
@@ -159,11 +170,12 @@ js::set('systemMode', $this->config->systemMode);
echo "<div class='users pull-right' title='" . $users[$assignedToList] . "'>";
echo html::smallAvatar(array('avatar' => $usersAvatar[$assignedToList], 'account' => $assignedToList, 'name' => $users[$assignedToList]), 'avatar-circle');
echo "</div>";
$class .= ' has-avatar';
}
?>
<?php endif;?>
</div>
<?php if($kanban->performable):?>
<?php if($kanban->performable and ($card->fromType == 'execution' or empty($card->fromType))):?>
<div class='progress-box'>
<div class='progress'>
<div class="progress-bar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width: <?php echo round($card->progress, 2) . '%';?>"></div>
@@ -173,7 +185,8 @@ js::set('systemMode', $this->config->systemMode);
<?php endif;?>
</div>
</div>
<div class='col-xs-2 card-actions' <?php if($kanban->performable) echo "id='performable'";?>>
<?php $class .= (!empty($kanban->performable) and ($card->fromType == 'execution' or empty($card->fromType))) ? ' has-progress' : ' no-progress';?>
<div class='col-xs-2 card-actions<?php echo $class;?>'>
<?php
$CRKanban = !(isset($this->config->CRKanban) and $this->config->CRKanban == '0' and $kanban->status == 'closed');
$canRestore = (commonModel::hasPriv('kanban', 'restoreCard') and $CRKanban);
+1 -1
View File
@@ -189,7 +189,7 @@
<td class='text-left nobr' title='<?php echo $story->title?>'>
<?php
if($story->parent > 0) echo "<span class='label label-badge label-light' title={$lang->story->children}>{$lang->story->childrenAB}</span>";
echo html::a($viewLink , $story->title);
echo html::a($viewLink , $story->title, '', "style='color: $story->color'");
?>
</td>
<td><?php echo zget($users, $story->openedBy);?></td>
+1 -1
View File
@@ -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("<div class='checkbox-primary'><input type='checkbox' name='executionIDList[]' value='" + executionID + "' id='executionIDList" + executionID + "'/><label for='executionIDList" + executionID + "'></lable></div>");
$tr.find('td:first').find('.checkbox-primary').css('margin-left', marginLeft).css('width', '14');
+33 -1
View File
@@ -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()
+11 -6
View File
@@ -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";
}
}
+14 -1
View File
@@ -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, "<i class='icon icon-hand-right'></i> <span title='" . zget($users, $task->assignedTo) . "' class='{$btnTextClass}'>{$assignedToText}</span>", '', "class='$btnClass'");
$assignToHtml = html::a($assignToLink, "<i class='icon icon-hand-right'></i> <span title='" . $assignedToTitle . "' class='{$btnTextClass}'>{$assignedToText}</span>", '', "class='$btnClass'");
echo !common::hasPriv('task', 'assignTo', $task) ? "<span style='padding-left: 21px' class='{$btnTextClass}'>{$assignedToText}</span>" : $assignToHtml;
}
+11
View File
@@ -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,
+1
View File
@@ -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;
+1
View File
@@ -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;
+1
View File
@@ -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;
+1
View File
@@ -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;
+1
View File
@@ -11,6 +11,7 @@
include '../../common/view/header.lite.html.php';
if(empty($config->notMd5Pwd))js::import($jsRoot . 'md5.js');
?>
<?php js::set('loginTimeoutTip', $lang->user->error->loginTimeoutTip);?>
<main id="main" class="fade no-padding">
<div class="container" id="login">
<div id="loginPanel">
+12 -8
View File
@@ -2,6 +2,7 @@
<?php
include dirname(dirname(dirname(__FILE__))) . '/lib/init.php';
include dirname(dirname(dirname(__FILE__))) . '/class/todo.class.php';
$db->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();