| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 |
- <?php
- /**
- * The taskkanban view file of execution 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 Yidong Wangy <yidong@easycorp.ltd>
- * @package execution
- * @link https://www.zentao.net
- */
- namespace zin;
- $this->app->loadLang('risk');
- $laneCount = 0;
- $lanePairs = array();
- $colPairs = array();
- $groupCols = array(); // 卡片可以移动到的同一group下的列。
- foreach($kanbanGroup as $index => $group)
- {
- $groupID = $group['id'];
- $group['getLane'] = jsRaw('window.getLane');
- $group['getCol'] = jsRaw('window.getCol');
- $group['getItem'] = jsRaw('window.getItem');
- $group['canDrop'] = jsRaw('window.canDrop');
- $group['onDrop'] = jsRaw('window.onDrop');
- $group['minColWidth'] = $execution->fluidBoard == '0' ? $execution->colWidth : $execution->minColWidth;
- $group['maxColWidth'] = $execution->fluidBoard == '0' ? $execution->colWidth : $execution->maxColWidth;
- $group['colProps'] = array('actions' => jsRaw('window.getColActions'));
- $group['itemProps'] = array('actions' => jsRaw('window.getItemActions'));
- foreach($group['data']['lanes'] as $lane) $lanePairs[$lane['id']] = $lane['type'];
- foreach($group['data']['cols'] as $colIndex => $col)
- {
- $colPairs[$col['id']] = $col['type'];
- if(isset($col['parent']) && $col['parent'] != '-1') $groupCols[$groupID][$col['id']] = $col['title'];
- }
- if($execution->displayCards > 0)
- {
- $group['minLaneHeight'] = $execution->displayCards * 70;
- $group['maxLaneHeight'] = $execution->displayCards * 70;
- }
- $kanbanGroup[$index] = $group;
- }
- if(!empty($kanbanGroup)) $laneCount += count($kanbanGroup);
- $checkObject = new stdclass();
- $checkObject->execution = $executionID;
- $canModifyExecution = common::canModify('execution', $execution);
- $canCreateTask = $canModifyExecution && !$isLimited && common::hasPriv('task', 'create', $checkObject);
- $canBatchCreateTask = $canModifyExecution && !$isLimited && common::hasPriv('task', 'batchCreate', $checkObject);
- $canCreateRisk = $canModifyExecution && common::hasPriv('risk', 'create', $checkObject) && in_array($config->edition, array('max', 'ipd'));
- $canBatchCreateRisk = $canModifyExecution && common::hasPriv('risk', 'batchCreate', $checkObject) && in_array($config->edition, array('max', 'ipd'));
- $canCreateBug = ($canModifyExecution && $productID && common::hasPriv('bug', 'create'));
- $canBatchCreateBug = ($canModifyExecution && $productID && common::hasPriv('bug', 'batchCreate'));
- $canImportBug = ($canModifyExecution && $productID && !$isLimited && common::hasPriv('execution', 'importBug'));
- $canCreateStory = (!$hasFrozenStories && $canModifyExecution && $productID && common::hasPriv('story', 'create'));
- $canBatchCreateStory = (!$hasFrozenStories && $canModifyExecution && $productID && common::hasPriv('story', 'batchCreate'));
- $canLinkStory = (!$hasFrozenStories && $canModifyExecution && $productID && common::hasPriv('execution', 'linkStory') && !empty($execution->hasProduct));
- $canLinkStoryByPlan = (!$hasFrozenStories && $canModifyExecution && $productID && common::hasPriv('execution', 'importplanstories') && !$hiddenPlan && !empty($execution->hasProduct));
- $hasStoryButton = !$hasFrozenStories && ($canCreateStory or $canBatchCreateStory or $canLinkStory or $canLinkStoryByPlan);
- $hasTaskButton = ($canCreateTask or $canBatchCreateTask or $canImportBug);
- $hasBugButton = ($canCreateBug or $canBatchCreateBug);
- $canStartExecution = true;
- if($config->edition == 'ipd')
- {
- $executionStatus = $this->execution->checkStageStatus($execution->id, 'start');
- $canStartExecution = empty($executionStatus['disabled']);
- }
- jsVar('laneCount', $laneCount);
- jsVar('cardLang', $lang->kanbancard);
- jsVar('groupCols', $groupCols);
- jsVar('lanePairs', $lanePairs);
- jsVar('colPairs', $colPairs);
- jsVar('vision', $config->vision);
- jsVar('colorList', $config->kanban->cardColorList);
- jsVar('ERURColumn', array_keys($lang->kanban->ERURColumn));
- jsVar('executionID', $executionID);
- jsVar('productID', $productID);
- jsVar('kanbanGroup', $kanbanGroup);
- jsVar('kanbanList', array_keys($kanbanGroup));
- jsVar('browseType', $browseType);
- jsVar('groupBy', $groupBy);
- jsVar('productNum', $productNum);
- jsVar('childrenAB', $lang->task->childrenAB);
- jsVar('parentAB', $lang->task->parentAB);
- jsVar('priv', array(
- 'canEditName' => common::hasPriv('kanban', 'setColumn'),
- 'canSetWIP' => common::hasPriv('kanban', 'setWIP'),
- 'canSetLane' => common::hasPriv('kanban', 'setLane'),
- 'canSortCards' => common::hasPriv('kanban', 'cardsSort'),
- 'canCreateTask' => $canCreateTask,
- 'canBatchCreateTask' => $canBatchCreateTask,
- 'canCreateRisk' => $canCreateRisk,
- 'canBatchCreateRisk' => $canBatchCreateRisk,
- 'canImportBug' => $canImportBug,
- 'canCreateBug' => $canCreateBug,
- 'canBatchCreateBug' => $canBatchCreateBug,
- 'canCreateStory' => $canCreateStory,
- 'canBatchCreateStory' => $canBatchCreateStory,
- 'canLinkStory' => $canLinkStory,
- 'canLinkStoryByPlan' => $canLinkStoryByPlan,
- 'canAssignTask' => $canModifyExecution && common::hasPriv('task', 'assignto'),
- 'canAssignStory' => $canModifyExecution && common::hasPriv('story', 'assignto'),
- 'canFinishTask' => $canModifyExecution && common::hasPriv('task', 'finish') && $canStartExecution,
- 'canPauseTask' => $canModifyExecution && common::hasPriv('task', 'pause'),
- 'canCancelTask' => $canModifyExecution && common::hasPriv('task', 'cancel'),
- 'canCloseTask' => $canModifyExecution && common::hasPriv('task', 'close'),
- 'canActivateTask' => $canModifyExecution && common::hasPriv('task', 'activate'),
- 'canStartTask' => $canModifyExecution && common::hasPriv('task', 'start') && $canStartExecution,
- 'canAssignBug' => $canModifyExecution && common::hasPriv('bug', 'assignto'),
- 'canConfirmBug' => $canModifyExecution && common::hasPriv('bug', 'confirmBug'),
- 'canActivateBug' => $canModifyExecution && common::hasPriv('bug', 'activate'),
- 'canResolveBug' => $canModifyExecution && common::hasPriv('bug', 'resolve'),
- 'canCloseBug' => $canModifyExecution && common::hasPriv('bug', 'close'),
- 'canCloseStory' => $canModifyExecution && common::hasPriv('story', 'close'),
- 'canTrackRisk' => $canModifyExecution && common::hasPriv('risk', 'track'),
- 'canAssignRisk' => $canModifyExecution && common::hasPriv('risk', 'assignto'),
- 'canCloseRisk' => $canModifyExecution && common::hasPriv('risk', 'close'),
- 'canHangupRisk' => $canModifyExecution && common::hasPriv('risk', 'hangup'),
- 'canCancelRisk' => $canModifyExecution && common::hasPriv('risk', 'cancel'),
- 'canActivateRisk' => $canModifyExecution && common::hasPriv('risk', 'activate')
- )
- );
- jsVar('executionLang', $lang->execution);
- jsVar('storyLang', $lang->story);
- jsVar('taskLang', $lang->task);
- jsVar('riskLang', $lang->risk);
- jsVar('bugLang', $lang->bug);
- jsVar('editName', $lang->execution->editName);
- jsVar('setWIP', $lang->execution->setWIP);
- jsVar('sortColumn', $lang->execution->sortColumn);
- jsVar('kanbanLang', $lang->kanban);
- jsVar('deadlineLang', $lang->task->deadlineAB);
- jsVar('estStartedLang', $lang->task->estStarted);
- jsVar('noAssigned', $lang->task->noAssigned);
- jsVar('userList', $userList);
- jsVar('entertime', time());
- jsVar('fluidBoard', $execution->fluidBoard);
- jsVar('displayCards', $execution->displayCards);
- jsVar('needLinkProducts', $lang->execution->needLinkProducts);
- jsVar('hourUnit', $config->hourUnit);
- jsVar('orderBy', $storyOrder);
- jsVar('minColWidth', $execution->fluidBoard == '0' ? $execution->colWidth : $execution->minColWidth);
- jsVar('maxColWidth', $execution->fluidBoard == '0' ? $execution->colWidth : $execution->maxColWidth);
- jsVar('teamWords', $lang->execution->teamWords);
- jsVar('canImportBug', $features['qa']);
- jsVar('canChangeObject', common::canModify('execution', $execution));
- $canCreateObject = ($canCreateTask or $canBatchCreateTask or $canCreateRisk or $canBatchCreateRisk or $canImportBug or $canCreateBug or $canBatchCreateBug or $canCreateStory or $canBatchCreateStory or $canLinkStory or $canLinkStoryByPlan);
- if($execution->type != 'stage' || !in_array($execution->attribute, array('mix', 'request', 'design')))
- {
- unset($lang->kanban->type['epic'], $lang->kanban->type['requirement']);
- }
- else
- {
- if(strpos($project->storyType, 'epic') === false) unset($lang->kanban->type['epic']);
- if(strpos($project->storyType, 'requirement') === false) unset($lang->kanban->type['requirement']);
- }
- featureBar
- (
- inputControl
- (
- setClass('c-type'),
- picker
- (
- set::width('200'),
- set::name('type'),
- set::items($lang->kanban->type),
- set::value($browseType),
- set::required(true),
- set::onchange('changeBrowseType()')
- )
- ),
- $browseType != 'all' ? inputControl
- (
- setClass('c-group ml-5'),
- picker
- (
- set::width('200'),
- set::name('group'),
- set::items($lang->kanban->group->$browseType),
- set::value($groupBy),
- set::required(true),
- set::onchange('changeGroupBy()')
- )
- ) : null,
- in_array($browseType, array('all', 'task')) ? checkbox
- (
- set::rootClass('ml-4 mr-4'),
- set::name('showParent'),
- set::checked($this->cookie->showParent ? 'checked' : ''),
- set::onchange('changeShowParent()'),
- set::text($lang->task->showParent)
- ) : null
- );
- toolbar
- (
- inputGroup
- (
- set::style(array('display' => 'none')),
- setID('taskKanbanSearch'),
- inputControl
- (
- setID('searchBox'),
- setClass('search-box'),
- input
- (
- setID('taskKanbanSearchInput'),
- set::name('taskKanbanSearchInput'),
- set::placeholder($lang->execution->pleaseInput)
- )
- )
- ),
- btn(setClass('querybox-toggle'), set::type('link'), set::onclick('toggleSearchBox()'), set::icon('search'), $lang->searchAB),
- common::hasPriv('task', 'export') ? btn(set::type('link'), set::url(createLink('task', 'export', "execution=$executionID&orderBy=$orderBy&type=unclosed")), set::icon('export'), set('data-toggle', 'modal'), $lang->export) : null,
- $canBeChanged ? dropdown
- (
- setID('importAction'),
- set::arrow(true),
- set::caret(false),
- btn(set::type('link'), set::icon('import'), $lang->import),
- set::items(array
- (
- common::hasPriv('execution', 'importTask') && $execution->multiple ? array('text' => $lang->execution->importTask, 'url' => createLink('execution', 'importTask', "execution=$execution->id")) : null,
- ($features['qa'] && !$isLimited && common::hasPriv('execution', 'importBug')) ? array('text' => $lang->execution->importBug, 'url' => createLink('execution', 'importBug', "execution=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'lg') : null
- ))
- ) : null,
- dropdown
- (
- setClass('kanbanSetting'),
- btn(set::type('link'), setClass('btn-icon'), icon('ellipsis-v')),
- set::caret(false),
- set::items(array
- (
- common::hasPriv('execution', 'setKanban') ? array('text' => $lang->execution->setKanban, 'url' => createLink('execution', 'setKanban', "executionID=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'sm') : null,
- common::hasPriv('execution', 'printKanban') ? array('text' => $lang->execution->printKanban, 'url' => createLink('execution', 'printKanban', "executionID=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'sm', 'id' => 'printKanban') : null,
- array('text' => $lang->execution->fullScreen, 'url' => "javascript:$(\"#kanbanList\").fullscreen();")
- ))
- ),
- $canCreateObject ? dropdown
- (
- setID('createDropdown'),
- btn(setClass('primary'),set::icon('plus'), $lang->create),
- set::items(array
- (
- !$hasFrozenStories && $features['story'] && common::hasPriv('story', 'create') ? ($hasStoryButton && $canCreateStory && !empty($productID) ? array('text' => $lang->execution->createStory, 'url' => createLink('story', 'create', "productID=$productID&branch=0&moduleID=0&story=0&execution=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'lg') : array('text' => $lang->story->create, 'data-on' => 'click', 'data-do' => "zui.Modal.alert('" . $lang->execution->needLinkProducts . "')")) : null,
- ($features['story'] && $hasStoryButton && $canBatchCreateStory) ? array('text' => $lang->execution->batchCreateStory, 'url' => createLink('story', 'batchCreate', "productID=$productID&branch=0&moduleID=0&story=0&execution=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'lg') : null,
- ($features['story'] && $hasStoryButton && $canLinkStory) ? array('text' => $lang->execution->linkStory, 'url' => createLink('execution', 'linkStory', "execution=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'lg') : null,
- ($features['story'] && $hasStoryButton && $canLinkStoryByPlan) ? array('text' => $lang->execution->linkStoryByPlan, 'url' => '#linkStoryByPlan', 'data-toggle' => 'modal', 'data-size' => 'sm') : null,
- ($features['story'] && $hasStoryButton && $features['qa']) ? array('class' => 'divider menu-divider') : null,
- $features['qa'] && common::hasPriv('bug', 'create') ? ($canCreateBug && !empty($productID) ? array('text' => $lang->bug->create, 'url' => createLink('bug', 'create', "productID=$productID&branch=0&extra=executionID=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'lg') : array('text' => $lang->bug->create, 'data-on' => 'click', 'data-do' => "zui.Modal.alert('" . $lang->execution->needLinkProducts . "')" )) : null,
- ($features['qa'] && $canBatchCreateBug) ? array('text' => $lang->bug->batchCreate, 'url' => ($productNum > 1 ? '#batchCreateBug' : createLink('bug', 'batchCreate', "productID=$productID&branch=0&executionID=$execution->id")), 'data-toggle' => 'modal', 'data-size' => $productNum > 1 ? null : 'lg') : null,
- ($features['qa'] && $canImportBug) ? array('text' => $lang->execution->importBug, 'url' => createLink('execution', 'importBug', "execution=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'lg') : null,
- ($features['qa'] && ($canCreateTask || $canBatchCreateTask)) ? array('text' => '', 'class' => 'divider menu-divider') : null,
- ($canCreateTask) ? array('text' => $lang->task->create, 'url' => createLink('task', 'create', "execution=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'lg') : null,
- ($canBatchCreateTask) ? array('text' => $lang->execution->batchCreateTask, 'url' => createLink('task', 'batchCreate', "execution=$execution->id"), 'data-toggle' => 'modal', 'data-size' => 'lg') : null,
- ($canCreateRisk || $canBatchCreateRisk) ? array('class' => 'divider menu-divider') : null,
- ($canCreateRisk) ? array('text' => $lang->risk->create, 'url' => createLink('risk', 'create', "execution=$execution->id&from=execution"), 'data-toggle' => 'modal', 'data-size' => 'lg') : null,
- ($canBatchCreateRisk) ? array('text' => $lang->risk->batchCreateRisk, 'url' => createLink('risk', 'batchCreate', "execution=$execution->id&from=execution"), 'data-toggle' => 'modal', 'data-size' => 'lg') : null
- ))
- ) : null
- );
- div
- (
- set::id('kanbanList'),
- setClass('bg-white'),
- zui::kanbanList
- (
- set('$replace', false),
- set::key('kanban'),
- set::items($kanbanGroup),
- set::height('calc(100vh - 120px)'),
- set::links($links),
- set::selectable(true),
- set::showLinkOnSelected(true)
- )
- );
- $linkStoryByPlanTips = $lang->execution->linkNormalStoryByPlanTips;
- $linkStoryByPlanTips = $execution->multiple ? $linkStoryByPlanTips : str_replace($lang->execution->common, $lang->projectCommon, $linkStoryByPlanTips);
- modal
- (
- setID('linkStoryByPlan'),
- setData('size', '500px'),
- set::modalProps(array('title' => $lang->execution->linkStoryByPlan)),
- div
- (
- setClass('flex-auto'),
- icon('info-sign', setClass('warning-pale rounded-full mr-1')),
- $linkStoryByPlanTips
- ),
- form
- (
- setClass('text-center', 'py-4'),
- set::actions(array('submit')),
- set::submitBtnText($lang->execution->linkStory),
- formGroup
- (
- set::label($lang->execution->selectStoryPlan),
- set::required(true),
- setClass('text-left'),
- picker
- (
- set::name('plan'),
- set::required(true),
- set::items($allPlans)
- )
- )
- )
- );
- modal
- (
- setID('batchCreateBug'),
- set::title($lang->bug->product),
- setData('size', '500px'),
- inputGroup
- (
- setClass('mt-3'),
- picker
- (
- set::width(300),
- setID('product'),
- set::name('productName'),
- set::items($productNames),
- set::required(true),
- set::onchange('changeBugProduct()')
- ),
- span
- (
- setClass('input-group-btn ml-2'),
- btn
- (
- setClass('primary'),
- setID('batchCreateBugButton'),
- set::url(createLink('bug', 'batchCreate', 'productID=' . key($productNames) . '&branch=&executionID=' . $executionID)),
- set('data-toggle', 'modal'),
- set('data-dismiss', 'modal'),
- set('data-size', 'lg'),
- $lang->bug->batchCreate
- )
- )
- )
- );
- render();
|