* Refactor batchcreate task pages.
This commit is contained in:
@@ -107,7 +107,7 @@ $config->task->form->batchCreate['name'] = array('type' => 'array', 're
|
||||
$config->task->form->batchCreate['color'] = array('type' => 'array', 'required' => false, 'default' => array());
|
||||
$config->task->form->batchCreate['type'] = array('type' => 'array', 'required' => false, 'default' => array());
|
||||
$config->task->form->batchCreate['assignedTo'] = array('type' => 'array', 'required' => false, 'default' => array());
|
||||
$config->task->form->batchCreate['estimated'] = array('type' => 'array', 'required' => false, 'default' => array());
|
||||
$config->task->form->batchCreate['estimate'] = array('type' => 'array', 'required' => false, 'default' => array());
|
||||
$config->task->form->batchCreate['estStarted'] = array('type' => 'array', 'required' => false, 'default' => array());
|
||||
$config->task->form->batchCreate['deadline'] = array('type' => 'array', 'required' => false, 'default' => array());
|
||||
$config->task->form->batchCreate['desc'] = array('type' => 'array', 'required' => false, 'default' => array());
|
||||
|
||||
@@ -122,8 +122,10 @@ class task extends control
|
||||
if(!empty($_POST))
|
||||
{
|
||||
/* 批量创建任务。 Batch create tasks. */
|
||||
$postData = form::data($this->config->task->form->batchCreate);
|
||||
$tasks = $this->taskZen->prepareTasks4BatchCreate($execution, $postData->rawdata);
|
||||
$postData = form::data($this->config->task->form->batchCreate);
|
||||
$tasks = $this->taskZen->prepareTasks4BatchCreate($execution, $postData->get(), $taskID);
|
||||
if(dao::isError()) return print(js::error(dao::getError()));
|
||||
|
||||
$taskIdList = $this->task->batchCreate($execution, $tasks, $taskID, $output);
|
||||
if(dao::isError()) return print(js::error(dao::getError()));
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/* Get select of stories.*/
|
||||
function setStories()
|
||||
{
|
||||
const moduleID = $(this).val();
|
||||
const index = $(this).closest('td').attr('data-init');
|
||||
const link = $.createLink('story', 'ajaxGetExecutionStories', 'executionID=' + executionID + '&productID=0&branch=all&moduleID=' + moduleID + '&storyID=0&num=' + index + '&type=short');
|
||||
$.get(link, function(stories)
|
||||
{
|
||||
var $story = $('#story_' + index);
|
||||
var storyID = $story.val();
|
||||
if(!stories) stories = '<select id="story' + index + '" name="story[' + index + ']" class="form-control"></select>';
|
||||
$story.replaceWith(stories);
|
||||
$story.val(storyID);
|
||||
if($('#zeroTaskStory').hasClass('checked'))
|
||||
{
|
||||
$story.find('option').each(function()
|
||||
{
|
||||
value = $(this).attr('value');
|
||||
if(value != 'ditto' && storyTasks[value] > 0)
|
||||
{
|
||||
$(this).hide();
|
||||
if(storyID == value) $story.val('');
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
$(function()
|
||||
{
|
||||
lifetimeList = JSON.parse(lifetimeList);
|
||||
attributeList = JSON.parse(attributeList);
|
||||
|
||||
if(hideStory)
|
||||
{
|
||||
$("input[name='after'][value='toStoryList']").parent().hide();
|
||||
@@ -93,6 +90,7 @@ function toggleSelectTestStory()
|
||||
$('#estStarted').closest('.form-row').addClass('hidden');
|
||||
$('#estimate').parent().prev().addClass('hidden');
|
||||
$('#estimate').parent().addClass('hidden');
|
||||
$('#testStoryBox').removeClass('hidden');
|
||||
|
||||
$('[name^=multiple]').prop('checked', false);
|
||||
showTeamBox();
|
||||
@@ -105,6 +103,7 @@ function toggleSelectTestStory()
|
||||
$('#estStarted').closest('.form-row').removeClass('hidden');
|
||||
$('#estimate').parent().prev().removeClass('hidden');
|
||||
$('#estimate').parent().removeClass('hidden');
|
||||
$('#testStoryBox').addClass('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1711,12 +1711,14 @@ class taskModel extends model
|
||||
->andWhere('t1.vision')->eq($this->config->vision)
|
||||
->fetch();
|
||||
if(!$task) return false;
|
||||
$task->openedDate = !empty($task->openedDate) ? substr($task->openedDate, 0, 19) : null;
|
||||
$task->finishedDate = !empty($task->finishedDate) ? substr($task->finishedDate, 0, 19) : null;
|
||||
$task->canceledDate = !empty($task->canceledDate) ? substr($task->canceledDate, 0, 19) : null;
|
||||
$task->closedDate = !empty($task->closedDate) ? substr($task->closedDate, 0, 19) : null;
|
||||
|
||||
$task->openedDate = !empty($task->openedDate) ? substr($task->openedDate, 0, 19) : null;
|
||||
$task->finishedDate = !empty($task->finishedDate) ? substr($task->finishedDate, 0, 19) : null;
|
||||
$task->canceledDate = !empty($task->canceledDate) ? substr($task->canceledDate, 0, 19) : null;
|
||||
$task->closedDate = !empty($task->closedDate) ? substr($task->closedDate, 0, 19) : null;
|
||||
$task->lastEditedDate = !empty($task->lastEditedDate) ? substr($task->lastEditedDate, 0, 19) : null;
|
||||
$task->realStarted = !empty($task->realStarted) ? substr($task->realStarted, 0, 19) : null;
|
||||
$task->realStarted = !empty($task->realStarted) ? substr($task->realStarted, 0, 19) : null;
|
||||
$task->mailto = empty($task->mailto) ? '' : $task->mailto;
|
||||
|
||||
$children = $this->dao->select('*')->from(TABLE_TASK)->where('parent')->eq($taskID)->andWhere('deleted')->eq(0)->fetchAll('id');
|
||||
$task->children = $children;
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* The batchCreate view file of task module of ZenTaoPMS.
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.zentao.net)
|
||||
* @license ZPL(https://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author Shujie Tian<tianshujie@easycorp.ltd>
|
||||
* @package task
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
namespace zin;
|
||||
/* ====== Preparing and processing page data ====== */
|
||||
jsVar('executionID', $execution->id);
|
||||
jsVar('storyTasks', $storyTasks);
|
||||
|
||||
/* zin: Set variables to define picker options for form. */
|
||||
|
||||
$items = array();
|
||||
|
||||
/* Field of ID. */
|
||||
$items[] = array
|
||||
(
|
||||
'name' => 'id',
|
||||
'label' => $lang->idAB,
|
||||
'control' => 'index',
|
||||
'width' => '30px',
|
||||
);
|
||||
|
||||
/* Field of module. */
|
||||
$items[] = array
|
||||
(
|
||||
'name' => 'module',
|
||||
'label' => $lang->task->module,
|
||||
'control' => 'select',
|
||||
'value' => $moduleID,
|
||||
'items' => $modules,
|
||||
'width' => '180px',
|
||||
);
|
||||
|
||||
/* Field of story. */
|
||||
if(!$hideStory)
|
||||
{
|
||||
$items[] = array
|
||||
(
|
||||
'name' => 'story',
|
||||
'label' => $lang->task->story,
|
||||
'control' => 'select',
|
||||
'items' => $stories,
|
||||
'width' => '200px',
|
||||
'ditto' => true,
|
||||
);
|
||||
}
|
||||
|
||||
/* Field of name. */
|
||||
$items[] = array
|
||||
(
|
||||
'name' => 'name',
|
||||
'label' => $lang->task->name,
|
||||
'width' => '165px',
|
||||
);
|
||||
|
||||
/* Field of region and lane. */
|
||||
if($execution->type == 'kanban')
|
||||
{
|
||||
$items[] = array
|
||||
(
|
||||
'name' => 'regions',
|
||||
'label' => $lang->kanbancard->region,
|
||||
'control' => 'select',
|
||||
'value' => $regionID,
|
||||
'items' => $regionPairs,
|
||||
'width' => '180px',
|
||||
);
|
||||
|
||||
$items[] = array
|
||||
(
|
||||
'name' => 'lanes',
|
||||
'label' => $lang->kanbancard->lane,
|
||||
'control' => 'select',
|
||||
'value' => $laneID,
|
||||
'items' => $lanePairs,
|
||||
'width' => '180px',
|
||||
);
|
||||
}
|
||||
|
||||
/* Field of type. */
|
||||
$items[] = array
|
||||
(
|
||||
'name' => 'type',
|
||||
'label' => $lang->task->type,
|
||||
'control' => 'select',
|
||||
'items' => $lang->task->typeList,
|
||||
'width' => '100px',
|
||||
'ditto' => true,
|
||||
);
|
||||
|
||||
/* Field of assignedTo. */
|
||||
$items[] = array
|
||||
(
|
||||
'name' => 'assignedTo',
|
||||
'label' => $lang->task->assignedTo,
|
||||
'control' => 'select',
|
||||
'items' => $members,
|
||||
'width' => '130px',
|
||||
'ditto' => true,
|
||||
);
|
||||
|
||||
/* Field of estimate. */
|
||||
$items[] = array
|
||||
(
|
||||
'name' => 'estimate',
|
||||
'label' => $lang->task->estimateAB,
|
||||
'width' => '70px',
|
||||
);
|
||||
|
||||
/* Field of estStarted. */
|
||||
$items[] = array
|
||||
(
|
||||
'name' => 'estStarted',
|
||||
'label' => $lang->task->estStarted,
|
||||
'control' => 'date',
|
||||
'width' => '120px',
|
||||
'ditto' => true,
|
||||
);
|
||||
|
||||
/* Field of deadline. */
|
||||
$items[] = array
|
||||
(
|
||||
'name' => 'deadline',
|
||||
'label' => $lang->task->deadline,
|
||||
'control' => 'date',
|
||||
'width' => '120px',
|
||||
'ditto' => true,
|
||||
);
|
||||
|
||||
/* Field of desc. */
|
||||
$items[] = array
|
||||
(
|
||||
'name' => 'desc',
|
||||
'label' => $lang->task->desc,
|
||||
'control' => 'editor',
|
||||
'width' => '150px',
|
||||
);
|
||||
|
||||
/* Field of pri. */
|
||||
$items[] = array
|
||||
(
|
||||
'name' => 'pri',
|
||||
'label' => $lang->task->pri,
|
||||
'control' => 'select',
|
||||
'items' => $lang->task->priList,
|
||||
'width' => '130px',
|
||||
'ditto' => true,
|
||||
);
|
||||
|
||||
/* ====== Define the page structure with zin widgets ====== */
|
||||
|
||||
formBatchPanel
|
||||
(
|
||||
set::items($items),
|
||||
on::change('[data-name="module"]', 'setStories'),
|
||||
);
|
||||
|
||||
/* ====== Render page ====== */
|
||||
render();
|
||||
@@ -25,8 +25,8 @@ jsVar('requiredFields', $config->task->create->requiredFields);
|
||||
jsVar('estimateNotEmpty', sprintf($lang->error->gt, $lang->task->estimate, '0'));
|
||||
jsVar('window.lifetime', $execution->lifetime);
|
||||
jsVar('window.attribute', $execution->attribute);
|
||||
jsVar('window.lifetimeList', json_encode($lifetimeList));
|
||||
jsVar('window.attributeList', json_encode($attributeList));
|
||||
jsVar('window.lifetimeList', $lifetimeList);
|
||||
jsVar('window.attributeList', $attributeList);
|
||||
jsVar('hasProduct', $execution->hasProduct);
|
||||
jsVar('hideStory', $hideStory);
|
||||
$requiredFields = array();
|
||||
@@ -253,6 +253,7 @@ formPanel
|
||||
setClass('empty-story-tip input-control has-prefix has-suffix'),
|
||||
$storyEmptyPreTip,
|
||||
input(
|
||||
set::name(''),
|
||||
prop('readonly'),
|
||||
prop('onfocus', 'this.blur()'),
|
||||
),
|
||||
|
||||
+16
-21
@@ -544,12 +544,13 @@ class taskZen extends task
|
||||
* 处理批量创建任务的请求数据。
|
||||
* Process the request data for batch create tasks.
|
||||
*
|
||||
* @param object $execution
|
||||
* @param object $formData
|
||||
* @param object $execution
|
||||
* @param object $formData
|
||||
* @param int $taskID
|
||||
* @access protected
|
||||
* @return object[]|false
|
||||
*/
|
||||
protected function prepareTasks4BatchCreate(object $execution, object $formData): array|false
|
||||
protected function prepareTasks4BatchCreate(object $execution, object $formData, int $taskID): array|false
|
||||
{
|
||||
/* 去除重复数据。 Deduplicated data. */
|
||||
$tasks = $this->removeDuplicate4BatchCreate($execution, $formData);
|
||||
@@ -569,6 +570,8 @@ class taskZen extends task
|
||||
$data = array();
|
||||
foreach($formData->name as $i => $name)
|
||||
{
|
||||
if(empty($name)) continue;
|
||||
|
||||
/* 给同上的变量赋值。 Assign values to ditto fields. */
|
||||
$story = !isset($tasks->story[$i]) || $tasks->story[$i] == 'ditto' ? $story : $tasks->story[$i];
|
||||
$module = !isset($tasks->module[$i]) || $tasks->module[$i] == 'ditto' ? $module : $tasks->module[$i];
|
||||
@@ -577,19 +580,9 @@ class taskZen extends task
|
||||
$estStarted = !isset($tasks->estStarted[$i]) || isset($tasks->estStartedDitto[$i]) ? $estStarted : $tasks->estStarted[$i];
|
||||
$deadline = !isset($tasks->deadline[$i]) || isset($tasks->deadlineDitto[$i]) ? $deadline : $tasks->deadline[$i];
|
||||
|
||||
/* 检查任务名称为空的数据。 Check the data whick task's name. */
|
||||
if(empty($tasks->name[$i]))
|
||||
{
|
||||
if($this->common->checkValidRow('task', $tasks, $i))
|
||||
{
|
||||
dao::$errors['message'][] = sprintf($this->lang->error->notempty, $this->lang->task->name);
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$dittoFields = array('story' => $story, 'module' => $module, 'type' => $type, 'assignedTo' => $assignedTo, 'estStarted' => $estStarted, 'deadline' => $deadline);
|
||||
$data[$i] = $this->buildData4BatchCreate($execution, $tasks, $i, $dittoFields, $extendFields);
|
||||
$data[$i] = $this->buildData4BatchCreate($execution, $tasks, $i, $dittoFields, $extendFields, $taskID);
|
||||
}
|
||||
|
||||
return $data;
|
||||
@@ -652,10 +645,11 @@ class taskZen extends task
|
||||
* @param int $index
|
||||
* @param array $dittoFields
|
||||
* @param array $extendFields
|
||||
* @param int $taskID
|
||||
* @access protected
|
||||
* @return object
|
||||
*/
|
||||
protected function buildData4BatchCreate(object $execution, object $tasks, int $index, array $dittoFields, array $extendFields): object
|
||||
protected function buildData4BatchCreate(object $execution, object $tasks, int $index, array $dittoFields, array $extendFields, int $taskID): object
|
||||
{
|
||||
extract($dittoFields);
|
||||
$now = helper::now();
|
||||
@@ -665,10 +659,10 @@ class taskZen extends task
|
||||
$task->type = $type;
|
||||
$task->module = (int)$module;
|
||||
$task->assignedTo = $assignedTo;
|
||||
$task->color = $tasks->color[$index];
|
||||
$task->color = isset($tasks->color[$index]) ? $tasks->color[$index] : '';
|
||||
$task->name = $tasks->name[$index];
|
||||
$task->desc = nl2br($tasks->desc[$index]);
|
||||
$task->pri = $tasks->pri[$index];
|
||||
$task->pri = (int)$tasks->pri[$index];
|
||||
$task->estimate = $tasks->estimate[$index] ? $tasks->estimate[$index] : 0;
|
||||
$task->left = $tasks->estimate[$index] ? $tasks->estimate[$index] : 0;
|
||||
$task->project = $execution->project;
|
||||
@@ -678,7 +672,7 @@ class taskZen extends task
|
||||
$task->status = 'wait';
|
||||
$task->openedBy = $this->app->user->account;
|
||||
$task->openedDate = $now;
|
||||
$task->parent = $tasks->parent[$index];
|
||||
$task->parent = $taskID;
|
||||
$task->vision = isset($tasks->vision[$index]) ? $tasks->vision[$index] : 'rnd';
|
||||
$task->version = 1;
|
||||
if($story) $task->storyVersion = (int)$this->dao->findById($task->story)->from(TABLE_STORY)->fetch('version');
|
||||
@@ -1103,8 +1097,8 @@ class taskZen extends task
|
||||
{
|
||||
$this->loadModel('kanban');
|
||||
|
||||
$regionID = (int)$output['regionID'];
|
||||
$laneID = (int)$output['laneID'];
|
||||
$regionID = isset($output['regionID']) ? (int)$output['regionID'] : 0;
|
||||
$laneID = isset($output['laneID']) ? (int)$output['laneID'] : 0;
|
||||
$regionPairs = $this->kanban->getRegionPairs($executionID, 0, 'execution');
|
||||
$regionID = $regionID ? $regionID : key($regionPairs);
|
||||
$lanePairs = $this->kanban->getLanePairsByRegion($regionID, 'task');
|
||||
@@ -1360,7 +1354,7 @@ class taskZen extends task
|
||||
{
|
||||
/* 获取区域和泳道下拉数据,并设置区域和泳道的默认值。 */
|
||||
/* Get region and lane dropdown data and set default values for regions and lanes. */
|
||||
if($execution->type == 'kanban') $this->assignKanbanRelatedVars($execution->id, $output);
|
||||
if($execution->type == 'kanban') $this->assignKanban4Create($execution->id, $output);
|
||||
|
||||
if($taskID)
|
||||
{
|
||||
@@ -1390,6 +1384,7 @@ class taskZen extends task
|
||||
$this->view->taskConsumed = isset($task) ? $task->consumed : 0;
|
||||
$this->view->customFields = $customFields;
|
||||
$this->view->checkedFields = $checkedFields;
|
||||
$this->view->hideStory = $this->task->isNoStoryExecution($execution);
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user