From 2bda72de166f76241b52faed4f8116f2b7f920d3 Mon Sep 17 00:00:00 2001 From: liumengyi Date: Thu, 11 May 2023 20:53:19 +0800 Subject: [PATCH] * Refactor the view of task-create. --- module/task/config.php | 2 +- module/task/css/create.ui.css | 5 + module/task/js/create.ui.js | 314 ++++++++++++++++++++++++++++++--- module/task/lang/de.php | 1 + module/task/lang/en.php | 1 + module/task/lang/fr.php | 1 + module/task/lang/zh-cn.php | 3 +- module/task/ui/create.html.php | 231 +++++++++++++++++++----- module/task/zen.php | 25 +-- 9 files changed, 494 insertions(+), 89 deletions(-) diff --git a/module/task/config.php b/module/task/config.php index 8b7c5de0c8..7d9ee66c42 100644 --- a/module/task/config.php +++ b/module/task/config.php @@ -258,5 +258,5 @@ $config->task->modeOptions[] = array('text' => $lang->task->modeList['multi'], ' $config->task->afterOptions = array(); $config->task->afterOptions[] = array('text' => $lang->task->afterChoices['continueAdding'], 'value' => 'continueAdding'); -$config->task->afterOptions[] = array('text' => $lang->task->afterChoices['toTaskList'], 'value' => 'toTaskList'); +$config->task->afterOptions[] = array('text' => $lang->task->afterChoices['toTaskList'], 'value' => 'toTaskList', 'checked' => true); $config->task->afterOptions[] = array('text' => $lang->task->afterChoices['toStoryList'], 'value' => 'toStoryList'); diff --git a/module/task/css/create.ui.css b/module/task/css/create.ui.css index 213d8afef3..df9f598267 100644 --- a/module/task/css/create.ui.css +++ b/module/task/css/create.ui.css @@ -1,2 +1,7 @@ .flex-none {flex: none !important;} .items-center {align-items: center !important;} +#taskCreateForm #pri {width: 5rem;} +#taskCreateForm .empty-story-tip input {padding: 0;} +#taskCreateForm .empty-story-tip .input-control-suffix {padding-right: 0;} +#taskCreateForm .empty-story-tip .input-control-suffix .btn:hover:before {background: none;} +#taskCreateForm .no-background .input-group-addon {background: none;} diff --git a/module/task/js/create.ui.js b/module/task/js/create.ui.js index a54c816336..a9af6422b3 100644 --- a/module/task/js/create.ui.js +++ b/module/task/js/create.ui.js @@ -1,4 +1,23 @@ -/* Show team menu. */ +$(function() +{ + lifetimeList = JSON.parse(lifetimeList); + attributeList = JSON.parse(attributeList); + + if(hideStory) + { + $("input[name='after'][value='toStoryList']").parent().hide(); + $("input[name='after'][value='continueAdding']").parent().hide(); + $("input[name='after'][value='toTaskList']").prop('checked', true); + } +}) + +/** + * 根据多人任务是否勾选展示团队。 + * Show team menu box. + * + * @access public + * @return void + */ function showTeamBox() { if($('[name^=multiple]').prop('checked')) @@ -11,14 +30,22 @@ function showTeamBox() { $('.team-group').addClass('hidden'); $('.modeBox').addClass('hidden'); - $('#estimate').attr('readonly', false); + $('#estimate').removeAttr('readonly'); } } -/* Set the assignedTos field. */ +/** + * 根据任务类型设置任务相关字段。 + * Set task-related fields based on the task type. + * + * @param object e + * @access public + * @return void + */ function typeChange(e) { - var result = $(e.target).val(); + const result = $(e.target).val(); + /* Change assigned person to multiple selection, and hide multiple team box. */ if(result == 'affair') { $("#multipleBox").removeAttr("checked"); @@ -28,22 +55,20 @@ function typeChange(e) $('#assignedTo').next('.picker').removeClass('hidden'); $('#assignedTo').attr('multiple', 'multiple'); - $('#assignedTo').chosen('destroy'); - $('#assignedTo').chosen(); $('.affair').hide(); $('.team-group').addClass('hidden'); $('.modeBox').addClass('hidden'); $('#selectAllUser').removeClass('hidden'); } + /* If assigned selection is multiple, remove multiple and hide the selection of select all members. */ else if($('#assignedTo').attr('multiple') == 'multiple') { $('#assignedTo').removeAttr('multiple'); - $('#assignedTo').chosen('destroy'); - $('#assignedTo').chosen(); $('.affair').show(); $('#selectAllUser').addClass('hidden'); } + /* If the execution has story list, toggle between hiding and displaying the selection of select test story box. */ if(lifetime != 'ops' && attribute != 'request' && attribute != 'review') { $('#selectTestStoryBox').toggleClass('hidden', result != 'test'); @@ -51,32 +76,267 @@ function typeChange(e) } } +/** + * 根据选择研发需求是否勾选切换相关字段的展示与隐藏。 + * Dynamically control whether task fields are hidden based on selection status of selectTestStory. + * + * @access public + * @return void + */ function toggleSelectTestStory() { if(!$('#selectTestStoryBox').hasClass('hidden') && $('#selectTestStory').prop('checked')) { - $('#module').closest('tr').addClass('hidden'); - $('#multipleBox').closest('td').addClass('hidden'); - $('#story').closest('tr').addClass('hidden'); - $('#estStarted').closest('tr').addClass('hidden'); - $('#estimate').closest('.table-col').addClass('hidden'); - $('#testStoryBox').removeClass('hidden'); - $('#copyButton').addClass('hidden'); - $('.colorpicker').css('right', '0'); - $('#dataform .table-form>tbody>tr>th').css('width', '130px'); - $('[lang^="zh-"] #dataform .table-form>tbody>tr>th').css('width', '120px'); + $('#module').closest('.form-group').addClass('hidden'); + $('#multipleBox').closest('.form-group').addClass('hidden'); + $('#story').closest('.form-row').addClass('hidden'); + $('#estStarted').closest('.form-row').addClass('hidden'); + $('#estimate').parent().prev().addClass('hidden'); + $('#estimate').parent().addClass('hidden'); - $('[name^=multiple]').attr('checked', false); - showTeamMenu(); + $('[name^=multiple]').prop('checked', false); + showTeamBox(); } else { - $('#module').closest('tr').removeClass('hidden'); - $('#multipleBox').closest('td').removeClass('hidden'); - if(showFields.indexOf('story') != -1) $('#story').closest('tr').removeClass('hidden'); - $('#estStarted').closest('tr').removeClass('hidden'); - $('#estimate').closest('.table-col').removeClass('hidden'); - $('#testStoryBox').addClass('hidden'); - $('#dataform .table-form>tbody>tr>th').css('width', '100px'); + $('#module').closest('.form-group').removeClass('hidden'); + $('#multipleBox').closest('.form-group').removeClass('hidden'); + if(showFields.indexOf('story') != -1) $('#story').closest('.form-row').removeClass('hidden'); + $('#estStarted').closest('.form-row').removeClass('hidden'); + $('#estimate').parent().prev().removeClass('hidden'); + $('#estimate').parent().removeClass('hidden'); + } +} + +/** + * 根据执行ID加载模块、需求和团队成员。 + * Load module, stories and members base on the execution id. + * + * @access public + * @return void + */ +function loadAll() +{ + const executionID = $(this).val(); + const fieldList = showFields + ','; + lifetime = lifetimeList[executionID]; + attribute = attributeList[executionID]; + /* If the execution doesn't have story list, hide the related fields.*/ + if(lifetime == 'ops' || attribute == 'request' || attribute == 'review') + { + $('.storyBox').addClass('hidden'); + + $("input[name='after'][value='toStoryList']").parent().hide(); + $("input[name='after'][value='continueAdding']").parent().hide(); + $("input[name='after'][value='toTaskList']").prop('checked', true); + } + /* If story field is showed, show the story field. */ + else if(fieldList.indexOf('story') >= 0) + { + $('.storyBox').removeClass('hidden'); + if($('#selectTestStory').prop('checked')) $('#selectTestStory').removeClass('hidden'); + + $("input[name='after'][value='toStoryList']").parent().show(); + $("input[name='after'][value='continueAdding']").parent().show(); + } + + /* Load modules, stories and members of the execution. */ + loadModules(executionID); + loadExecutionStories(); + loadExecutionMembers(executionID); +} + +/** + * 加载执行的模块。 + * Load modules of the execution. + * + * @param int $executionID + * @access public + * @return void + */ +function loadModules(executionID) +{ + const extra = $('#showAllModule').prop('checked') ? 'allModule' : ''; + const getModuleLink = $.createLink('tree', 'ajaxGetOptionMenu', 'rootID=' + executionID + '&viewtype=task&branch=0&rootModuleID=0&returnType=html&fieldID=&needManage=0&extra=' + extra); + $.get(getModuleLink, function(data) + { + $('#module').replaceWith(data); + }); +} + +/** + * 加载执行的需求。 + * Load stories of the execution + * + * @access public + * @return void + */ +function loadExecutionStories() +{ + var storyID = $('#story').val(); + const executionID = $('#execution').val(); + const moduleID = $('#module').val(); + const getStoryLink = $.createLink('story', 'ajaxGetExecutionStories', 'executionID=' + executionID + '&productID=0&branch=0&moduleID=' + moduleID + '&storyID=' + storyID + '&number=&type=full&status=active'); + $.get(getStoryLink, function(stories) + { + if(!stories) stories = ''; + $('#story').replaceWith(stories); + $('#story').removeAttr('onchange'); + if($('#story').length == 0 && $('#storyBox').length != 0) $('#storyBox').html(stories); + + $('#story').val(storyID); + setPreview(); + $('#story').next('.picker').remove(); + + /* If there is no story option, select will be hidden and text will be displayed; otherwise, the opposite is true */ + if($('#story option').length > 1 || parseInt(hasProduct) == 0) + { + $('#story').closest('.form-group').removeClass('hidden'); + $('.empty-story-tip').closest('.form-group').addClass('hidden'); + + $('#taskCreateForm').on('change', '#story', setStoryRelated); + } + else + { + $('#story').closest('.form-group').addClass('hidden'); + $('.empty-story-tip').closest('.form-group').removeClass('hidden'); + } + + }); +} + +/** + * 加载执行的团队成员。 + * Load team members of the execution. + * + * @param executionID $executionID + * @access public + * @return void + */ +function loadExecutionMembers(executionID) +{ + $('#multipleBox').removeAttr('checked'); + $('.team-group,.modeBox').addClass('hidden'); + + const getAssignedToLink = $.createLink('execution', 'ajaxGetMembers', 'executionID=' + executionID + '&assignedTo=' + $('#assignedTo').val()); + $.get(getAssignedToLink, function(data) + { + $('#assignedTo').replaceWith(data); + $('#assignedTo').attr('name', 'assignedTo[]'); + }); +} + +/** + * 加载区域对应泳道。 + * Load lanes of the region. + * + * @access public + * @return void + */ +function loadLanes() +{ + const regionID = $(this).val(); + const getLaneLink = $.createLink('kanban', 'ajaxGetLanes', 'regionID=' + regionID + '&type=task&field=lane'); + $.get(getLaneLink, function(data) + { + $('#lane').replaceWith(data); + }); +} + +/** + * 根据选择需求设置查看链接和所属模块。 + * Set preview and module of story. + * + * @access public + * @return void + */ +function setStoryRelated() +{ + setPreview(); + setStoryModule(); +} + +/** + * 设置需求的查看链接。 + * Set the story priview link. + * + * @access public + * @return void + */ +function setPreview() +{ + if(!Number($('#story').val())) + { + $('#preview').addClass('hidden'); + $('.title-group.required > div').removeAttr('id', 'copyStory-input').addClass('.required'); + } + else + { + var storyLink = $.createLink('execution', 'storyView', "storyID=" + $('#story').val()); + var concat = storyLink.indexOf('?') < 0 ? '?' : '&'; + + if(storyLink.indexOf("onlybody=yes") < 0) storyLink = storyLink + concat + 'onlybody=yes'; + + $('#preview').removeClass('hidden'); + $('#preview .btn').attr('data-url', storyLink); + $('.title-group.required > div').attr('id', 'copyStory-input').removeClass('.required'); + } + + setAfter(); +} + +/** + * 根据需求设置任务的所属模块。 + * Set the story module. + * + * @access public + * @return void + */ +function setStoryModule() +{ + var storyID = $('#story').val(); + if(storyID) + { + var link = $.createLink('story', 'ajaxGetInfo', 'storyID=' + storyID); + $.getJSON(link, function(storyInfo) + { + if(storyInfo) + { + $('#module').val(storyInfo.moduleID); + $("#module").trigger("chosen:updated"); + + $('#storyEstimate').val(storyInfo.estimate); + $('#storyPri').val(storyInfo.pri); + $('#storyDesc').val(storyInfo.spec); + } + }); + } +} + +/** + * 设置保存任务之后的选项。 + * Set after locate. + * + * @access public + * @return void + */ +function setAfter() +{ + if($("#story").length == 0 || $("#story").val() == '') + { + /* If the exeuction doesn't have stories, hide the selections of story. */ + if($('input[value="continueAdding"]').attr('checked') == 'checked') + { + $('input[value="toTaskList"]').prop('checked', true); + } + $('input[value="continueAdding"]').attr('disabled', 'disabled'); + $('input[value="toStoryList"]').attr('disabled', 'disabled'); + } + else + { + /* If the exeuction has stories, show the selections of story. */ + if(!toTaskList) $('input[value="continueAdding"]').prop('checked', true); + $('input[value="continueAdding"]').attr('disabled', false); + $('input[value="toStoryList"]').attr('disabled', false); } } diff --git a/module/task/lang/de.php b/module/task/lang/de.php index 8c6c39561c..c58a8b9382 100644 --- a/module/task/lang/de.php +++ b/module/task/lang/de.php @@ -165,6 +165,7 @@ $lang->task->lblHour = '(h)'; $lang->task->lblTestStory = 'Story Tested'; $lang->task->teamMember = 'Team Member'; $lang->task->to = 'To'; +$lang->task->suffixHour = 'H'; /* Fields of zt_taskestimate. */ $lang->task->task = 'Task'; diff --git a/module/task/lang/en.php b/module/task/lang/en.php index 16717826db..533fcac9ef 100755 --- a/module/task/lang/en.php +++ b/module/task/lang/en.php @@ -165,6 +165,7 @@ $lang->task->lblHour = '(h)'; $lang->task->lblTestStory = 'Story Tested'; $lang->task->teamMember = 'Team Member'; $lang->task->to = 'To'; +$lang->task->suffixHour = 'H'; /* Fields of zt_taskestimate. */ $lang->task->task = 'Task'; diff --git a/module/task/lang/fr.php b/module/task/lang/fr.php index 13cf4279c3..6c2756c7b6 100644 --- a/module/task/lang/fr.php +++ b/module/task/lang/fr.php @@ -165,6 +165,7 @@ $lang->task->lblHour = '(h)'; $lang->task->lblTestStory = 'Story Testée'; $lang->task->teamMember = 'Team Member'; $lang->task->to = 'To'; +$lang->task->suffixHour = 'H'; /* Fields of zt_taskestimate. */ $lang->task->task = 'Task'; diff --git a/module/task/lang/zh-cn.php b/module/task/lang/zh-cn.php index c0fe0495d4..b99f2c40ed 100755 --- a/module/task/lang/zh-cn.php +++ b/module/task/lang/zh-cn.php @@ -165,6 +165,7 @@ $lang->task->lblHour = '(h)'; $lang->task->lblTestStory = "测试{$lang->SRCommon}"; $lang->task->teamMember = '团队成员'; $lang->task->to = '至'; +$lang->task->suffixHour = 'H'; /* Fields of zt_taskestimate. */ $lang->task->task = '任务'; @@ -251,7 +252,7 @@ $lang->task->confirmFinish = '"预计剩余"为0,确认将任务 $lang->task->confirmRecord = '"剩余"为0,任务将标记为"已完成",您确定吗?'; $lang->task->confirmTransfer = '剩余工时为0,当前成员已完成任务,任务指派给:%s。'; $lang->task->noticeTaskStart = '"总计消耗"和"预计剩余"不能同时为0'; -$lang->task->noticeLinkStory = "没有可关联的相关{$lang->SRCommon},您可以为当前{$lang->projectCommon}%s,然后%s"; +$lang->task->noticeLinkStory = "没有可关联的相关{$lang->SRCommon},您可以为当前{$lang->projectCommon}"; $lang->task->noticeLinkStoryNoProduct = "没有可关联的相关{$lang->SRCommon}"; $lang->task->noticeSaveRecord = '您有尚未保存的工时记录,请先将其保存。'; $lang->task->noticeManageTeam = '任务状态是%s,不能维护团队'; diff --git a/module/task/ui/create.html.php b/module/task/ui/create.html.php index c4567add04..a46faeb79f 100644 --- a/module/task/ui/create.html.php +++ b/module/task/ui/create.html.php @@ -15,9 +15,6 @@ namespace zin; /* ====== Preparing and processing page data ====== */ /* zin: Set variables to define picker options for form. */ -jsVar('lifetime', $execution->lifetime); -jsVar('attribute', $execution->attribute); -jsVar('showFields', $showFields); jsVar('toTaskList', !empty($task->id)); jsVar('blockID', $blockID); jsVar('executionID', $execution->id); @@ -26,24 +23,133 @@ jsVar('teamMemberError', $lang->task->error->teamMember); jsVar('vision', $config->vision); 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('hasProduct', $execution->hasProduct); +jsVar('hideStory', $hideStory); +$requiredFields = array(); +foreach(explode(',', $config->task->create->requiredFields) as $field) +{ + if($field) $requiredFields[$field] = ''; + if($field and strpos($showFields, $field) === false) $showFields .= ',' . $field; +} +jsVar('showFields', $showFields); -/* ====== Define the page structure with zin widgets ====== */ - -/* zin: Define the form in main content. */ -formPanel -( - set::title($lang->task->create), // The form title is diffrent from the page title, - formRow +$executionBox = ''; +/* Cannot show execution field in kanban. */ +if($execution->type != 'kanban' or $this->config->vision == 'lite') +{ + $executionBox = formGroup ( + set::width('1/2'), + set::name('execution'), + set::label($lang->task->execution), + set::value($execution->id), + set::items($executions), + on::change('loadAll') + ); +} + +$kanbanRow = ''; +/* The region and lane fields are only showed in kanban. */ +if($execution->type == 'kanban') +{ + $kanbanRow = formRow ( formGroup ( set::width('1/2'), - set::name('execution'), - set::label($lang->task->execution), - set::value($execution->id), - set::items($executions) + set::name('region'), + set::label($lang->kanbancard->region), + set::value($regionID), + set::items($regionPairs), + on::change('loadLanes') ), formGroup + ( + set::width('1/2'), + set::name('lane'), + set::label($lang->kanbancard->lane), + set::value($laneID), + set::items($lanePairs), + ), + ); +} + +/* Set the tip when there is no story. */ +if(!empty($execution->hasProduct)) +{ + $storyEmptyPreTip = span + ( + setClass('input-control-prefix'), + span + ( + $lang->task->noticeLinkStory, + ), + a + ( + set::href($this->createLink('execution', 'linkStory', "executionID=$execution->id")), + setClass('text-primary'), + $lang->execution->linkStory + ), + ); +} +else +{ + $storyEmptyPreTip = span + ( + setClass('input-control-prefix'), + span + ( + $lang->task->noticeLinkStory, + ), + ); +} +$storyPreviewBtn = span +( + setClass('input-group-btn flex hidden'), + set::id('preview'), + modalTrigger + ( + to::trigger( + btn( + setClass('text-gray'), + set::icon('eye'), + ), + ), + set::url('') + ), +); + +$aftoicesRow = ''; +/* Ct redirect within pop-ups. */ +if(!isonlybody()) +{ + $afterChoicesRow = formGroup + ( + set::width('3/4'), + set::label($lang->task->afterSubmit), + radioList + ( + set::name('after'), + set::value(!empty($task->id) ? 'toTaskList' : 'continueAdding'), + set::items($config->task->afterOptions), + set::inline(true) + ), + ); +} + +/* ====== Define the page structure with zin widgets ====== */ + +formPanel +( + set::id('taskCreateForm'), + set::title($lang->task->create), + formRow + ( + $executionBox, + formGroup ( set::width('1/2'), set::name('module'), @@ -52,6 +158,7 @@ formPanel set::items($moduleOptionMenu) ) ), + $kanbanRow, formRow ( formGroup @@ -70,6 +177,7 @@ formPanel set::id('selectTestStoryBox'), setClass('hidden items-center'), checkbox( + set::id('selectTestStory'), set::name('selectTestStory'), set::text($lang->task->selectTestStory), set::rootClass('ml-4'), @@ -82,10 +190,14 @@ formPanel formGroup ( set::width('1/4'), - set::name('assignedTo[]'), set::label($lang->task->assignTo), - set::value($task->assignedTo), - set::items($members), + select + ( + set::id('assignedTo'), + set::name('assignedTo[]'), + set::value($task->assignedTo), + set::items($members), + ), ), formGroup ( @@ -112,27 +224,67 @@ formPanel ) ) ), - formGroup + formRow ( - set::width('1/2'), - set::name('story'), - set::label($lang->task->story), - set::value($task->story), - set::items($stories), + setClass($hideStory ? 'hidden' : ''), + formGroup + ( + set::label($lang->task->story), + setClass(empty($stories) ? 'hidden' : ''), + inputGroup + ( + select + ( + set::id('story'), + set::name('story'), + set::value($task->story), + set::items($stories), + on::change('setStoryRelated'), + ), + $storyPreviewBtn, + ) + ), + formGroup + ( + set::label($lang->task->story), + setClass(!empty($stories) ? 'hidden' : ''), + div + ( + setClass('empty-story-tip input-control has-prefix has-suffix'), + $storyEmptyPreTip, + input( + prop('readonly'), + prop('onfocus', 'this.blur()'), + ), + span + ( + setClass('input-control-suffix'), + btn( + setClass('text-gray'), + set::id('refreshStories'), + set::icon('refresh'), + on::click('loadExecutionStories'), + ) + ), + ), + ), ), formRow ( formGroup ( + set::width('3/4'), set::label($lang->task->name), + set::name('name'), + set::value($task->name), + set::strong(true), + ), + formGroup + ( + set::width('1/4'), + setClass('no-background'), inputGroup ( - input - ( - set::name('name'), - set::value($task->name), - setClass('flex-none w-3/4'), - ), $lang->task->pri, select ( @@ -140,12 +292,14 @@ formPanel set::items($lang->task->priList), ), $lang->task->estimate, - input + inputControl ( - set::name('estimate'), + input(set::name('estimate')), + to::suffix($lang->task->suffixHour), + set::suffixWidth(20), ), ), - ) + ), ), formGroup ( @@ -188,18 +342,7 @@ formPanel set::name('mailto[]'), set::items($users), ), - formGroup - ( - set::width('3/4'), - set::label($lang->task->afterSubmit), - radioList - ( - set::name('after'), - set::value(!empty($task->id) ? 'toTaskList' : 'continueAdding'), - set::items($config->task->afterOptions), - set::inline(true) - ), - ), + $afterChoicesRow ); diff --git a/module/task/zen.php b/module/task/zen.php index ce50b11a12..0fdfd0e33d 100644 --- a/module/task/zen.php +++ b/module/task/zen.php @@ -839,6 +839,7 @@ class taskZen extends task $this->view->task = $task; $this->view->storyID = $storyID; $this->view->blockID = isonlybody() ? $this->loadModel('block')->getSpecifiedBlockID('my', 'assingtome', 'assingtome') : 0; + $this->view->hideStory = $this->task->isNoStoryExecution($execution); $this->display(); } @@ -916,31 +917,23 @@ class taskZen extends task $projectID = $execution ? $execution->project : 0; $lifetimeList = array(); $attributeList = array(); + $executions = $this->executionPairs; if($projectID) { - $executionKey = 0; $executions = $this->execution->getByProject($projectID, 'all', 0, true); $executionList = $this->execution->getByIdList(array_keys($executions)); foreach($executionList as $executionItem) { - if(!common::canModify('execution', $executionItem)) $executionKey = $executionItem->id; - if($executionKey) unset($executions[$executionKey]); - if(!$executionKey) continue; - - $lifetimeList[$executionKey] = $executionItem->lifetime; - $attributeList[$executionKey] = $executionItem->attribute; + if(!common::canModify('execution', $executionItem)) unset($executions[$executionItem->id]); } } - else + + $executionList = $this->execution->getByIdList(array_keys($executions)); + foreach($executionList as $executionItem) { - $executions = $this->executionPairs; - $executionList = $this->execution->getByIdList(array_keys($executions)); - foreach($executionList as $executionItem) - { - $executionKey = $executionItem->id; - $lifetimeList[$executionKey] = $executionItem->lifetime; - $attributeList[$executionKey] = $executionItem->attribute; - } + $executionKey = $executionItem->id; + $lifetimeList[$executionKey] = $executionItem->lifetime; + $attributeList[$executionKey] = $executionItem->attribute; } $this->view->projectID = $projectID;