* Replace with common::buildOperateMenu to get the story actions.
This commit is contained in:
@@ -53,3 +53,120 @@ $config->story->custom->batchCreateFields = 'module,plan,spec,pri,estimate,revie
|
||||
$config->story->custom->batchEditFields = 'branch,module,plan,estimate,pri,source,stage,closedBy,closedReason';
|
||||
|
||||
$config->story->excludeCheckFields = ',uploadImage,category,reviewer,reviewDitto,lanes,regions,branch,pri,';
|
||||
|
||||
global $app, $lang;
|
||||
$config->story->actionList = array();
|
||||
$config->story->actionList['change']['icon'] = 'alert';
|
||||
$config->story->actionList['change']['text'] = $lang->story->change;
|
||||
$config->story->actionList['change']['hint'] = $lang->story->change;
|
||||
$config->story->actionList['change']['url'] = array('module' => 'story', 'method' => 'change', 'params' => 'storyID={id}');
|
||||
$config->story->actionList['change']['data-app'] = $app->tab;
|
||||
|
||||
$config->story->actionList['submitReview']['icon'] = 'confirm';
|
||||
$config->story->actionList['submitReview']['text'] = $lang->story->submitReview;
|
||||
$config->story->actionList['submitReview']['hint'] = $lang->story->submitReview;
|
||||
$config->story->actionList['submitReview']['url'] = array('module' => 'story', 'method' => 'submitReview', 'params' => 'storyID={id}&storyType={type}');
|
||||
$config->story->actionList['submitReview']['data-toggle'] = 'modal';
|
||||
|
||||
$config->story->actionList['recall']['icon'] = 'undo';
|
||||
$config->story->actionList['recall']['text'] = $lang->story->recall;
|
||||
$config->story->actionList['recall']['hint'] = $lang->story->recall;
|
||||
$config->story->actionList['recall']['url'] = array('module' => 'story', 'method' => 'recall', 'params' => 'storyID={id}&from=view&confirm=no&storyType={type}');
|
||||
$config->story->actionList['recall']['data-app'] = $app->tab;
|
||||
$config->story->actionList['recall']['className'] = 'ajax-submit';
|
||||
|
||||
$config->story->actionList['recallChange']['icon'] = 'undo';
|
||||
$config->story->actionList['recallChange']['text'] = $lang->story->recallChange;
|
||||
$config->story->actionList['recallChange']['hint'] = $lang->story->recallChange;
|
||||
$config->story->actionList['recallChange']['url'] = array('module' => 'story', 'method' => 'recall', 'params' => 'storyID={id}&from=view&confirm=no&storyType={type}');
|
||||
$config->story->actionList['recallChange']['data-app'] = $app->tab;
|
||||
$config->story->actionList['recallChange']['className'] = 'ajax-submit';
|
||||
|
||||
$config->story->actionList['review']['icon'] = 'alert';
|
||||
$config->story->actionList['review']['text'] = $lang->story->review;
|
||||
$config->story->actionList['review']['hint'] = $lang->story->review;
|
||||
$config->story->actionList['review']['url'] = array('module' => 'story', 'method' => 'review', 'params' => 'storyID={id}&from=' . $app->tab . '&storyType={type}');
|
||||
$config->story->actionList['review']['data-app'] = $app->tab;
|
||||
|
||||
$config->story->actionList['subdivide']['icon'] = 'split';
|
||||
$config->story->actionList['subdivide']['text'] = $lang->story->subdivide;
|
||||
$config->story->actionList['subdivide']['hint'] = $lang->story->subdivide;
|
||||
$config->story->actionList['subdivide']['url'] = array('module' => 'story', 'method' => 'batchCreate', 'params' => 'productID={product}&branch={branch}&moduleID={module}&storyID={id}&executionID={executionID}&plan=0&storyType=story');
|
||||
$config->story->actionList['subdivide']['data-app'] = $app->tab;
|
||||
|
||||
$config->story->actionList['assignTo']['icon'] = 'hand-right';
|
||||
$config->story->actionList['assignTo']['text'] = $lang->story->assignTo;
|
||||
$config->story->actionList['assignTo']['hint'] = $lang->story->assignTo;
|
||||
$config->story->actionList['assignTo']['url'] = array('module' => 'story', 'method' => 'assignTo', 'params' => 'storyID={id}&kanbanGroup=default&from=&storyType={type}');
|
||||
$config->story->actionList['assignTo']['data-toggle'] = 'modal';
|
||||
|
||||
$config->story->actionList['close']['icon'] = 'off';
|
||||
$config->story->actionList['close']['text'] = $lang->story->close;
|
||||
$config->story->actionList['close']['hint'] = $lang->story->close;
|
||||
$config->story->actionList['close']['url'] = array('module' => 'story', 'method' => 'close', 'params' => 'storyID={id}&from=&storyType={type}');
|
||||
$config->story->actionList['close']['data-toggle'] = 'modal';
|
||||
|
||||
$config->story->actionList['activate']['icon'] = 'magic';
|
||||
$config->story->actionList['activate']['text'] = $lang->story->activate;
|
||||
$config->story->actionList['activate']['hint'] = $lang->story->activate;
|
||||
$config->story->actionList['activate']['url'] = array('module' => 'story', 'method' => 'activate', 'params' => 'storyID={id}&storyType={type}');
|
||||
$config->story->actionList['activate']['data-toggle'] = 'modal';
|
||||
|
||||
$config->story->actionList['importToLib']['icon'] = 'assets';
|
||||
$config->story->actionList['importToLib']['text'] = $lang->story->importToLib;
|
||||
$config->story->actionList['importToLib']['hint'] = $lang->story->importToLib;
|
||||
$config->story->actionList['importToLib']['url'] = '#importToLib';
|
||||
$config->story->actionList['importToLib']['data-toggle'] = 'modal';
|
||||
|
||||
$app->loadLang('testcase');
|
||||
$config->story->actionList['createTestcase']['text'] = $lang->story->create;
|
||||
$config->story->actionList['createTestcase']['hint'] = $lang->story->create;
|
||||
$config->story->actionList['createTestcase']['url'] = array('module' => 'testcase', 'method' => 'create', 'params' => 'product={product}&branch={branch}&moduleID=0&from=¶m=0&storyid={id}');
|
||||
$config->story->actionList['createTestcase']['data-size'] = 'lg';
|
||||
$config->story->actionList['createTestcase']['data-toggle'] = 'modal';
|
||||
|
||||
$config->story->actionList['batchCreateTestcase']['text'] = $lang->story->batchCreate;
|
||||
$config->story->actionList['batchCreateTestcase']['hint'] = $lang->story->batchCreate;
|
||||
$config->story->actionList['batchCreateTestcase']['url'] = array('module' => 'testcase', 'method' => 'batchCreate', 'params' => 'product={product}&branch={branch}&moduleID=0&storyid={id}');
|
||||
$config->story->actionList['batchCreateTestcase']['data-size'] = 'lg';
|
||||
$config->story->actionList['batchCreateTestcase']['data-toggle'] = 'modal';
|
||||
|
||||
$config->story->actionList['testcase']['type'] = 'dropdown';
|
||||
$config->story->actionList['testcase']['text'] = $lang->testcase->common;
|
||||
$config->story->actionList['testcase']['hint'] = $lang->testcase->common;
|
||||
$config->story->actionList['testcase']['caret'] = 'up';
|
||||
$config->story->actionList['testcase']['placement'] = 'top-end';
|
||||
$config->story->actionList['testcase']['items'] = array('createTestcase', 'batchCreateTestcase');
|
||||
|
||||
$app->loadLang('task');
|
||||
$config->story->actionList['createTask']['icon'] = 'plus';
|
||||
$config->story->actionList['createTask']['text'] = $lang->task->create;
|
||||
$config->story->actionList['createTask']['hint'] = $lang->task->create;
|
||||
$config->story->actionList['createTask']['url'] = array('module' => 'task', 'method' => 'create', 'params' => 'executionID={execution}&storyID={id}&moduleID={module}');
|
||||
$config->story->actionList['createTask']['data-size'] = 'lg';
|
||||
$config->story->actionList['createTask']['data-toggle'] = 'modal';
|
||||
|
||||
$config->story->actionList['edit']['icon'] = 'edit';
|
||||
$config->story->actionList['edit']['text'] = $lang->story->edit;
|
||||
$config->story->actionList['edit']['hint'] = $lang->story->edit;
|
||||
$config->story->actionList['edit']['url'] = array('module' => 'story', 'method' => 'edit', 'params' => 'storyID={id}&kanbanGroup=default&storyType={type}');
|
||||
$config->story->actionList['edit']['data-app'] = $app->tab;
|
||||
$config->story->actionList['edit']['notInModal'] = true;
|
||||
|
||||
$config->story->actionList['copy']['icon'] = 'copy';
|
||||
$config->story->actionList['copy']['text'] = $lang->story->copy;
|
||||
$config->story->actionList['copy']['hint'] = $lang->story->copy;
|
||||
$config->story->actionList['copy']['url'] = array('module' => 'story', 'method' => 'create', 'params' => 'product={product}&branch={branch}&moduleID={module}&storyID={id}&executionID=0&bugID=0&planID=0&todoID=0&extra=&storyType={type}');
|
||||
$config->story->actionList['copy']['data-app'] = $app->tab;
|
||||
$config->story->actionList['copy']['notInModal'] = true;
|
||||
|
||||
$config->story->actionList['delete']['icon'] = 'trash';
|
||||
$config->story->actionList['delete']['text'] = $lang->task->delete;
|
||||
$config->story->actionList['delete']['hint'] = $lang->task->delete;
|
||||
$config->story->actionList['delete']['url'] = array('module' => 'story', 'method' => 'delete', 'params' => 'storyID={id}');
|
||||
$config->story->actionList['delete']['className'] = 'ajax-submit';
|
||||
|
||||
$config->story->actions = new stdclass();
|
||||
$config->story->actions->view = array();
|
||||
$config->story->actions->view['mainActions'] = array('change', 'submitReview', 'recall', 'recallChange', 'review', 'subdivide', 'assignTo', 'close', 'activate', 'importToLib', 'testcase', 'createTask');
|
||||
$config->story->actions->view['suffixActions'] = array('edit', 'copy', 'delete');
|
||||
|
||||
+27
-11
@@ -3157,14 +3157,30 @@ class storyModel extends model
|
||||
global $app, $config;
|
||||
$action = strtolower($action);
|
||||
|
||||
if($action == 'recall') return strpos('reviewing,changing', $story->status) !== false;
|
||||
if($action == 'close') return $story->status != 'closed';
|
||||
if($action == 'activate') return $story->status == 'closed';
|
||||
if($action == 'assignto') return $story->status != 'closed';
|
||||
if($action == 'batchcreate' and $story->parent > 0) return false;
|
||||
if($action == 'batchcreate' and !empty($story->twins)) return false;
|
||||
if($action == 'batchcreate' and $story->type == 'requirement' and $story->status != 'closed') return strpos('draft,reviewing,changing', $story->status) === false;
|
||||
if($action == 'submitreview' and strpos('draft,changing', $story->status) === false) return false;
|
||||
if($action == 'recallchange') return $story->status == 'changing';
|
||||
if($action == 'recall') return $story->status == 'reviewing';
|
||||
if($action == 'close') return $story->status != 'closed';
|
||||
if($action == 'activate') return $story->status == 'closed';
|
||||
if($action == 'assignto') return $story->status != 'closed';
|
||||
if($action == 'batchcreate' && $story->parent > 0) return false;
|
||||
if($action == 'batchcreate' && !empty($story->twins)) return false;
|
||||
if($action == 'submitreview' && strpos('draft,changing', $story->status) === false) return false;
|
||||
if($action == 'subdivide' && (!helper::isAjaxRequest('modal') || $config->vision != 'lite')) return false;
|
||||
if($action == 'batchcreate' && $story->type == 'requirement' && $story->status != 'closed') return strpos('draft,reviewing,changing', $story->status) === false;
|
||||
if($action == 'createtestcase' || $action == 'batchcreatetestcase') return $config->vision != 'lite' && $story->parent >= 0 && $story->type != 'requirement';
|
||||
|
||||
if($action == 'createtask')
|
||||
{
|
||||
if($app->tab == 'project' && !empty($_SESSION['project']))
|
||||
{
|
||||
global $dao;
|
||||
$project = $dao->findByID($_SESSION['project'])->from(TABLE_PROJECT)->fetch();
|
||||
}
|
||||
return ($app->tab == 'execution' || (!empty($project) && $project->multiple == '0')) && $story->status == 'active' && $story->type == 'story';
|
||||
}
|
||||
|
||||
$disabledFeatures = ",{$config->disabledFeatures},";
|
||||
if($action == 'importToLib') return in_array($config->edition, array('max', 'ipd')) && $app->tab == 'project' && common::hasPriv('story', 'importToLib') && strpos($disabledFeatures, ',assetlibStorylib,') === false && strpos($disabledFeatures, ',assetlib,') === false;
|
||||
|
||||
static $shadowProducts = array();
|
||||
static $taskGroups = array();
|
||||
@@ -3176,7 +3192,7 @@ class storyModel extends model
|
||||
foreach($stmt as $row) $shadowProducts[$row->id] = $row->id;
|
||||
}
|
||||
|
||||
if($hasShadow and empty($taskGroups[$story->id])) $taskGroups[$story->id] = $app->dbQuery('SELECT id FROM ' . TABLE_TASK . " WHERE story = $story->id")->fetch();
|
||||
if($hasShadow && empty($taskGroups[$story->id])) $taskGroups[$story->id] = $app->dbQuery('SELECT id FROM ' . TABLE_TASK . " WHERE story = $story->id")->fetch();
|
||||
|
||||
if(isset($story->parent) && $story->parent < 0 && strpos($config->story->list->actionsOperatedParentStory, ",$action,") === false) return false;
|
||||
|
||||
@@ -3193,8 +3209,8 @@ class storyModel extends model
|
||||
$story->notReview = isset($story->notReview) ? $story->notReview : array();
|
||||
$isSuperReviewer = strpos(',' . trim(zget($config->story, 'superReviewers', ''), ',') . ',', ',' . $app->user->account . ',');
|
||||
|
||||
if($action == 'change') return (($isSuperReviewer !== false or count($story->reviewer) == 0 or count($story->notReview) == 0) and $story->status == 'active');
|
||||
if($action == 'review') return (($isSuperReviewer !== false or in_array($app->user->account, $story->notReview)) and $story->status == 'reviewing');
|
||||
if($action == 'change') return (($isSuperReviewer !== false || count($story->reviewer) == 0 || count($story->notReview) == 0) && $story->status == 'active');
|
||||
if($action == 'review') return (($isSuperReviewer !== false || in_array($app->user->account, $story->notReview)) && $story->status == 'reviewing');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -17,9 +17,6 @@ include($this->app->getModuleRoot() . 'ai/ui/promptmenu.html.php');
|
||||
$isInModal = isInModal();
|
||||
$isRequirement = $story->type == 'requirement';
|
||||
$isStoryType = $story->type == 'story';
|
||||
$actions = $this->story->buildOperateMenu($story, 'view', $project ? $project : null);
|
||||
if($story->deleted) $actions = array();
|
||||
if($isInModal) $actions = false;
|
||||
|
||||
/* 版本列表。Version list. */
|
||||
$versions = array();
|
||||
@@ -173,6 +170,10 @@ $versionBtn = count($versions) > 1 ? to::title(dropdown
|
||||
set::items($versions)
|
||||
)) : null;
|
||||
|
||||
$actions = $story->deleted || $isInModal ? array() : $this->loadModel('common')->buildOperateMenu($story);
|
||||
$hasDivider = !empty($actions['mainActions']) && !empty($actions['suffixActions']);
|
||||
$actions = array_merge($actions['mainActions'], array(array('type' => 'divider')), $actions['suffixActions']);
|
||||
if(!$hasDivider) unset($actions['type']);
|
||||
detail
|
||||
(
|
||||
set::objectType('story'),
|
||||
|
||||
Reference in New Issue
Block a user