* Adjust for display tips after create execution.

This commit is contained in:
wangyidong
2023-09-12 13:18:16 +08:00
parent 8bcd14a7ee
commit e4f3aee3b0
8 changed files with 110 additions and 157 deletions
+17 -38
View File
@@ -935,9 +935,6 @@ class execution extends control
if($copyExecutionID) $this->executionZen->setFieldsByCopyExecution($execution, $copyExecutionID);
$projectID = $execution->project;
$this->app->loadLang('program');
$this->app->loadLang('stage');
$this->app->loadLang('programplan');
if($executionID) return $this->executionZen->displayAfterCreated($projectID, $executionID, $planID, $confirm);
$project = empty($projectID) ? null : $this->loadModel('project')->fetchByID($projectID);
@@ -955,53 +952,36 @@ class execution extends control
$_POST['plans'] = array_filter($_POST['plans']);
}
$execution= $this->storyZen->buildExecutionForCreate();
$execution = $this->executionZen->buildExecutionForCreate();
if(!$execution) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$executionID = $this->execution->create($execution, isset($_POST['teamMembers']) ? $_POST['teamMembers'] : array());
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$this->execution->updateProducts($executionID, $postData);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$comment = $execution->hasProduct ? implode(',', $_POST['products']) : '';
$this->loadModel('action')->create($this->objectType, $executionID, 'opened', '', $comment);
$this->execution->updateProducts($executionID, zget($_POST, 'products', array()), zget($_POST, 'plans', array()), zget($_POST, 'branch', array(0)));
$this->loadModel('action')->create($this->objectType, $executionID, 'opened', '', $execution->hasProduct ? implode(',', $_POST['products']) : '');
$this->loadModel('programplan')->computeProgress($executionID, 'create');
if(!empty($projectID) and strpos(',kanban,agileplus,waterfallplus,', ",$project->model,") !== false and $execution->type == 'kanban')
{
$execution = $this->execution->fetchByID($executionID);
$this->loadModel('kanban')->createRDKanban($execution);
}
$message = $this->executeHooks($executionID);
if($message) $this->lang->saveSuccess = $message;
if(empty($message)) $message = $this->lang->saveSuccess;
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $executionID));
if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $message, 'id' => $executionID));
if($this->app->tab == 'doc') return $this->send(array('result' => 'success', 'message' => $message, 'load' => $this->createLink('doc', 'projectSpace', "objectID=$executionID")));
if(!empty($_POST['plans'])) return $this->send(array('result' => 'success', 'message' => $message, 'load' => inlink('create', "projectID=$projectID&executionID=$executionID&copyExecutionID=&planID=1&confirm=no")));
if($this->app->tab == 'doc')
if(!empty($projectID) and $project->model == 'kanban')
{
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $this->createLink('doc', 'projectSpace', "objectID=$executionID")));
}
$link = $this->config->vision != 'lite' ? $this->createLink('project', 'index', "projectID=$projectID") : $this->createLink('project', 'execution', "status=all&projectID=$projectID");
if($this->app->tab == 'project') return $this->send(array('result' => 'success', 'message' => $message, 'load' => $link));
if(!empty($projectID) and strpos(',kanban,agileplus,waterfallplus,', ",$project->model,") !== false)
{
$execution = $this->execution->getById($executionID);
if($execution->type == 'kanban') $this->loadModel('kanban')->createRDKanban($execution);
}
if(!empty($_POST['plans']))
{
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => inlink('create', "projectID=$projectID&executionID=$executionID&copyExecutionID=&planID=1&confirm=no")));
}
else
{
if(!empty($projectID) and $project->model == 'kanban')
{
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
$link = $this->config->vision != 'lite' ? $this->createLink('project', 'index', "projectID=$projectID") : $this->createLink('project', 'execution', "status=all&projectID=$projectID");
if($this->app->tab == 'project') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => $link));
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => inlink('kanban', "executionID=$executionID")));
}
return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'load' => inlink('create', "projectID=$projectID&executionID=$executionID")));
return $this->send(array('result' => 'success', 'message' => $message, 'load' => inlink('kanban', "executionID=$executionID")));
}
return $this->send(array('result' => 'success', 'message' => $message, 'load' => inlink('create', "projectID=$projectID&executionID=$executionID")));
}
list($this->view->pmUsers, $this->view->poUsers, $this->view->qdUsers, $this->view->rdUsers) = $this->executionZen->setUserMoreLink();
@@ -1023,7 +1003,6 @@ class execution extends control
$this->view->from = $this->app->tab;
$this->view->isStage = isset($project->model) && in_array($project->model, array('waterfall', 'waterfallplus'));
$this->view->project = $project;
$this->view->stageBy = empty($project->stageBy) ? '' : $project->stageBy;
$this->display();
}
-1
View File
@@ -14,4 +14,3 @@
#copyExecutions .btn.primary-outline {background-color: var(--color-primary-50);}
#copyExecutions .btn.primary-outline:after {position: absolute; content: '\e92f'; font-family: ZentaoIcon; font-size: 20px; right: 25px;}
#copyExecutions .btn.primary-outline span{color: rgba(var(--color-fore-rgb),var(--tw-text-opacity));}
#tipsModal.modal-no-backdrop {background-color: var(--modal-bg) !important; pointer-events: unset !important;}
+2
View File
@@ -0,0 +1,2 @@
#tipsModal {margin-top: 10%; max-width: 800px;}
#tipsModal .panel-heading {border-bottom:1px solid #e5e5e5; padding: 20px;}
-15
View File
@@ -1,11 +1,5 @@
$(function()
{
if(executionID)
{
triggerTips();
return false;
}
loadProjectExecutions(copyProjectID);
if($('#methodHover').length) new zui.Tooltip('#methodHover', {title: methodTip, trigger: 'hover', placement: 'right', type: 'white', 'className': 'text-gray border border-light methodTip'});
@@ -140,15 +134,6 @@ function setCopyExecution()
zui.Modal.hide();
}
window.triggerTips = function()
{
const modal = zui.Modal.open({
url: $.createLink('execution', 'tips', 'executionID=' + executionID),
id: 'tipsModal',
backdrop: false
});
}
window.branchChange = function(e)
{
let $product = $(e.target).closest('.form-row').find("[name^='products']");
+38 -53
View File
@@ -236,6 +236,7 @@ class executionModel extends model
{
$this->dao->insert(TABLE_EXECUTION)->data($execution)
->autoCheck('begin,end')
->batchcheck($this->config->execution->create->requiredFields, 'notempty')
->checkIF(!empty($execution->name), 'name', 'unique', "`type` in ('sprint','stage', 'kanban') and `project` = " . (int)$execution->project . " and `deleted` = '0'")
->checkIF(!empty($execution->code), 'code', 'unique', "`type` in ('sprint','stage', 'kanban') and `deleted` = '0'")
->checkIF($execution->begin != '', 'begin', 'date')
@@ -2326,16 +2327,17 @@ class executionModel extends model
* Update products of a execution.
*
* @param int $executionID
* @param object $postData
* @param array $products
* @param array $plans
* @param array $branches
* @access public
* @return void
* @return bool
*/
public function updateProducts($executionID, object $postData)
public function updateProducts(int $executionID, array $products, array $plans, array $branches): bool
{
$this->loadModel('user');
$products = $postData->products;
$oldProducts = $this->dao->select('*')->from(TABLE_PROJECTPRODUCT)->where('project')->eq((int)$executionID)->fetchGroup('product', 'branch');
$this->dao->delete()->from(TABLE_PROJECTPRODUCT)->where('project')->eq((int)$executionID)->exec();
$oldProducts = $this->dao->select('*')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($executionID)->fetchGroup('product', 'branch');
$this->dao->delete()->from(TABLE_PROJECTPRODUCT)->where('project')->eq($executionID)->exec();
$members = array_keys($this->getTeamMembers($executionID));
if(empty($products))
{
@@ -2343,8 +2345,6 @@ class executionModel extends model
return true;
}
$branches = isset($postData->branch) ? $postData->branch : array(0);
$plans = isset($postData->plans) ? $postData->plans : array();
$existedProducts = array();
foreach($products as $i => $productID)
{
@@ -2353,11 +2353,9 @@ class executionModel extends model
$oldPlan = 0;
$branch = isset($branches[$i]) ? (array) $branches[$i] : array();
foreach($branch as $branchID)
{
if(isset($existedProducts[$productID][$branchID])) continue;
if(isset($oldProducts[$productID][$branchID]))
{
$oldProduct = $oldProducts[$productID][$branchID];
@@ -2366,7 +2364,7 @@ class executionModel extends model
$data = new stdclass();
$data->project = $executionID;
$data->product = $productID;
$data->product = (int)$productID;
$data->branch = (int)$branchID;
$data->plan = isset($plans[$productID]) ? implode(',', $plans[$productID]) : $oldPlan;
$data->plan = trim($data->plan, ',');
@@ -2377,8 +2375,9 @@ class executionModel extends model
}
$oldProductKeys = array_keys($oldProducts);
$needUpdate = array_merge(array_diff($oldProductKeys, $products), array_diff($products, $oldProductKeys));
$needUpdate = array_merge(array_diff($oldProductKeys, $products), array_diff($products, $oldProductKeys));
if($needUpdate) $this->user->updateUserView($needUpdate, 'product', $members);
return true;
}
/**
@@ -2763,42 +2762,41 @@ class executionModel extends model
*/
public function linkStory(int $executionID, array $stories = array(), string $extra = '', array $lanes = array()): bool
{
if(empty($executionID)) return false;
if(empty($stories)) return false;
$this->loadModel('action');
$this->loadModel('kanban');
$versions = $this->loadModel('story')->getVersions($stories);
$linkedStories = $this->dao->select('story,`order`')->from(TABLE_PROJECTSTORY)->where('project')->eq($executionID)->orderBy('order_desc')->fetchPairs('story', 'order');
$lastOrder = reset($linkedStories);
$storyList = $this->dao->select('id, status, branch, product')->from(TABLE_STORY)->where('id')->in(array_values($stories))->fetchAll('id');
$execution = $this->getByID($executionID);
if(empty($executionID) || empty($stories)) return false;
$extra = str_replace(array(',', ' '), array('&', ''), $extra);
parse_str($extra, $output);
$this->loadModel('action');
$this->loadModel('kanban');
$versions = $this->loadModel('story')->getVersions($stories);
$linkedStories = $this->dao->select('story,`order`')->from(TABLE_PROJECTSTORY)->where('project')->eq($executionID)->orderBy('order_desc')->fetchPairs('story', 'order');
$lastOrder = (int)reset($linkedStories);
$storyList = $this->dao->select('id, status, branch, product')->from(TABLE_STORY)->where('id')->in(array_values($stories))->fetchAll('id');
$execution = $this->fetchByID($executionID);
$notAllowedStatus = $this->app->rawMethod == 'batchcreate' ? 'closed' : 'draft,reviewing,closed';
$laneID = isset($output['laneID']) ? $output['laneID'] : 0;
foreach($stories as $storyID)
{
if(isset($linkedStories[$storyID])) continue;
$notAllowedStatus = $this->app->rawMethod == 'batchcreate' ? 'closed' : 'draft,reviewing,closed';
if(strpos($notAllowedStatus, $storyList[$storyID]->status) !== false) continue;
$laneID = isset($output['laneID']) ? $output['laneID'] : 0;
$story = zget($storyList, $storyID, '');
if(empty($story)) continue;
if(!empty($lanes[$storyID])) $laneID = $lanes[$storyID];
$columnID = $this->kanban->getColumnIDByLaneID($laneID, 'backlog');
if(empty($columnID)) $columnID = isset($output['columnID']) ? $output['columnID'] : 0;
if(!empty($laneID) and !empty($columnID)) $this->kanban->addKanbanCell($executionID, $laneID, $columnID, 'story', $storyID);
$lastOrder ++;
$data = new stdclass();
$data->project = $executionID;
$data->product = (int)$storyList[$storyID]->product;
$data->branch = $storyList[$storyID]->branch;
$data->product = (int)$story->product;
$data->branch = $story->branch;
$data->story = $storyID;
$data->version = $versions[$storyID];
$data->order = (int)$lastOrder;
$data->order = ++ $lastOrder;
$this->dao->replace(TABLE_PROJECTSTORY)->data($data)->exec();
$this->story->setStage($storyID);
@@ -2827,22 +2825,19 @@ class executionModel extends model
{
$this->loadModel('action');
$linkedCases = $this->dao->select('*')->from(TABLE_PROJECTCASE)->where('project')->eq($executionID)->orderBy('order_desc')->fetchPairs('case', 'order');
$lastCaseOrder = empty($linkedCases) ? 0 : reset($linkedCases);
$lastCaseOrder = empty($linkedCases) ? 0 : (int)reset($linkedCases);
$cases = $this->dao->select('id, version')->from(TABLE_CASE)->where('story')->eq($storyID)->fetchPairs();
$execution = $this->getByID($executionID);
foreach($cases as $caseID => $version)
{
if(isset($linkedCases[$caseID])) continue;
$lastCaseOrder ++;
$object = new stdclass();
$object->project = $executionID;
$object->product = $productID;
$object->case = $caseID;
$object->version = $version;
$object->order = $lastCaseOrder;
$object->order = ++ $lastCaseOrder;
$this->dao->insert(TABLE_PROJECTCASE)->data($object)->exec();
$action = $execution->type == 'project' ? 'linked2project' : 'linked2execution';
@@ -2860,39 +2855,29 @@ class executionModel extends model
*/
public function linkStories(int $executionID): bool
{
$plans = $this->dao->select('product, plan')->from(TABLE_PROJECTPRODUCT)
->where('project')->eq($executionID)
->fetchPairs('product', 'plan');
$stories = array();
$plans = $this->dao->select('product, plan')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($executionID)->fetchPairs('product', 'plan');
$projectID = $this->dao->select('project')->from(TABLE_EXECUTION)->where('id')->eq($executionID)->fetch('project');
$this->session->set('project', $projectID);
$stories = array();
$planProducts = array();
$this->loadModel('story');
$executionProducts = $this->loadModel('project')->getBranchesByProject($executionID);
foreach($plans as $productID => $planIdList)
{
if(empty($planIdList)) continue;
$planIdList = explode(',', $planIdList);
$planIdList = array_filter(explode(',', $planIdList));
$executionBranches = zget($executionProducts, $productID, array());
foreach($planIdList as $planID)
{
$planStories = $this->story->getPlanStories($planID);
if(!empty($planStories))
if(empty($planStories)) continue;
foreach($planStories as $id => $story)
{
foreach($planStories as $id => $story)
{
if($story->status != 'active' || (!empty($story->branch) && !empty($executionBranches) && !isset($executionBranches[$story->branch])))
{
unset($planStories[$id]);
continue;
}
$planProducts[$story->id] = $story->product;
}
$stories = array_merge($stories, array_keys($planStories));
if($story->status != 'active' || (!empty($story->branch) && !empty($executionBranches) && !isset($executionBranches[$story->branch]))) unset($planStories[$id]);
}
$stories = array_merge($stories, array_keys($planStories));
}
}
-5
View File
@@ -545,10 +545,5 @@ modalTrigger
)
);
modalTrigger
(
modal(set::id('tipsModal'))
);
/* ====== Render page ====== */
render();
+49 -43
View File
@@ -10,53 +10,59 @@ declare(strict_types=1);
*/
namespace zin;
set::className('pt-6');
set::closeBtn(array('url' => createLink('execution', 'create'), 'class' => 'ghost'));
div
panel
(
set::className('flex items-center'),
icon('check-circle text-success icon-2x mr-2'),
span
setID('tipsModal'),
set::title($lang->execution->tips),
set::headingActions(array
(
set::className('article-h2 tip-title'),
$lang->execution->afterInfo
array('url' => createLink('execution', 'task', "executionID={$executionID}"), 'icon' => 'close', 'class' => 'ghost')
)),
setClass('m-auto'),
div
(
set::className('flex items-center'),
icon('check-circle text-success icon-2x mr-2'),
span
(
set::className('article-h2 tip-title'),
$lang->execution->afterInfo
)
),
div
(
btn
(
set::className('mr-4 tipBtn ml-1'),
$lang->execution->setTeam,
set('data-url', createLink('execution', 'team', "executionID={$executionID}")),
),
$execution->lifetime != 'ops' ? btn
(
set::className('mr-4 tipBtn'),
$lang->execution->linkStory,
set('data-url', createLink('execution', 'linkstory', "executionID=$executionID")),
) : null,
btn
(
set::className('mr-4 tipBtn'),
$lang->execution->createTask,
set('data-url', createLink('task', 'create', "execution=$executionID")),
),
btn
(
set::className('mr-4 tipBtn'),
$lang->execution->goback,
set('data-url', createLink('execution', 'task', "executionID={$executionID}")),
),
btn
(
set::className('tipBtn'),
$lang->execution->gobackExecution,
set('data-url', createLink('execution', 'all')),
),
)
);
div
(
set::className('my-4'),
btn
(
set::className('mr-4 tipBtn ml-1'),
$lang->execution->setTeam,
set('data-url', createLink('execution', 'team', "executionID={$executionID}")),
),
$execution->lifetime != 'ops' ? btn
(
set::className('mr-4 tipBtn'),
$lang->execution->linkStory,
set('data-url', createLink('execution', 'linkstory', "executionID=$executionID")),
) : null,
btn
(
set::className('mr-4 tipBtn'),
$lang->execution->createTask,
set('data-url', createLink('task', 'create', "execution=$executionID")),
),
btn
(
set::className('mr-4 tipBtn'),
$lang->execution->goback,
set('data-url', createLink('execution', 'task', "executionID={$executionID}")),
),
btn
(
set::className('tipBtn'),
$lang->execution->gobackExecution,
set('data-url', createLink('execution', 'all')),
),
);
/* ====== Render page ====== */
render();
+4 -2
View File
@@ -884,6 +884,7 @@ class executionZen extends execution
$fields = $this->config->execution->form->create;
$editorFields = array_keys(array_filter(array_map(function($config){return $config['control'] == 'editor';}, $fields)));
foreach(explode(',', trim($this->config->execution->create->requiredFields, ',')) as $field) $fields[$field]['required'] = true;
if(!isset($_POST['code'])) $fields['code']['required'] = false;
$this->config->execution->create->requiredFields = implode(',', array_keys(array_filter(array_map(function($config){return $config['required'] == true;}, $fields))));
$this->correctErrorLang();
@@ -900,7 +901,7 @@ class executionZen extends execution
->setIF($this->post->acl == 'open', 'whitelist', '')
->join('whitelist', ',')
->setDefault('type', $type)
->stripTags($editorFields, $this->config->allowedTags)
->stripTags(implode(',', $editorFields), $this->config->allowedTags)
->remove('products, workDays, delta, branch, uid, plans, teams, teamMembers, contactListMenu, heightType')
->get();
@@ -1953,7 +1954,8 @@ class executionZen extends execution
$this->view->title = $this->lang->execution->tips;
$this->view->executionID = $executionID;
$this->display();
$this->view->execution = $this->execution->fetchByID($executionID);
$this->display('execution', 'tips');
}
/**