$('#kanbanList').on('enterFullscreen', () => {$('#kanbanList > div').css('height', '100%'); window.hideAllAction();}); $('#kanbanList').on('exitFullscreen', () => {$('#kanbanList > div').css('height', 'calc(100vh - 120px)')}); searchValue = ''; const kanbanDropRules = { story: { backlog: ['ready', 'backlog'], ready: ['backlog', 'ready'], tested: ['verified', 'rejected'], verified: ['tested', 'pending', 'released'], pending: ['verified', 'released'], released: ['verified', 'closed'], closed: ['released'] }, bug: { 'unconfirmed': ['confirmed', 'fixing', 'fixed'], 'confirmed': ['fixing', 'fixed'], 'fixing': ['fixed'], 'fixed': ['testing', 'tested', 'fixing'], 'testing': ['tested', 'closed', 'fixing'], 'tested': ['closed', 'fixing'], 'closed': ['fixing'], }, task: { 'wait': ['developing', 'developed', 'canceled'], 'developing': ['developed', 'pause', 'canceled'], 'developed': ['developing', 'closed'], 'pause': ['developing'], 'canceled': ['developing', 'closed'], 'closed': ['developing'], }, risk: { 'active': ['track', 'hangup', 'canceled', 'closed'], 'track': ['active', 'hangup', 'canceled', 'closed'], 'hangup': ['active', 'track', 'canceled', 'closed'], 'canceled': ['active', 'track', 'closed'], 'closed': ['active', 'track'], } }; window.changeBrowseType = function() { const type = $('.c-type [name=type]').val(); loadPage($.createLink('execution', 'taskKanban', "executionID=" + executionID + '&type=' + type)); }; window.changeGroupBy = function() { const group = $('.c-group [name=group]').val(); const type = $('.c-type [name=type]').val(); loadPage($.createLink('execution', 'taskKanban', 'executionID=' + executionID + '&type=' + type + '&orderBy=order_asc' + '&groupBy=' + group)); }; window.changeBugProduct = function() { const productID = $('[name=productName]').val(); if(productID) $('#batchCreateBugButton').attr('href', $.createLink('bug', 'batchCreate', 'productID=' + productID + '&branch=&executionID=' + executionID)); }; window.changeShowParent = function() { const showParent = $('[name=showParent]').prop('checked') ? 1 : 0; $.cookie.set('showParent', showParent, {expires:config.cookieLife, path:config.webRoot}); const type = $('.c-type [name=type]').val(); const group = $('.c-group [name=group]').val(); let link = $.createLink('execution', 'taskKanban', 'executionID=' + executionID + '&type=' + type); if(typeof group != 'undefined') link = $.createLink('execution', 'taskKanban', 'executionID=' + executionID + '&type=' + type + '&orderBy=order_asc' + '&groupBy=' + group); loadPage(link); }; window.linkPlanStory = function() { const planID = $('[name=plan]').val(); if(planID) { var param = "¶m=executionID=" + executionID + ",browseType=" + browseType + ",orderBy=id_asc,groupBy=" + groupBy; $.ajaxSubmit({url: $.createLink('execution', 'importPlanStories', 'executionID=' + executionID + '&planID=' + planID + '&productID=0&fromMethod=taskKanban&extra=' + param)}); } }; window.toggleSearchBox = function() { $('#taskKanbanSearch').toggle(); if($('#taskKanbanSearch').css('display') == 'block') { $(".querybox-toggle").css("color", "#0c64eb"); } else { $(".querybox-toggle").css("color", "#3c495c"); $('#taskKanbanSearchInput').attr('value', ''); searchCards(''); } }; window.getLane = function(lane) { /* 看板只有一个泳道时,铺满全屏。 */ if(laneCount < 2) lane.minHeight = window.innerHeight - 235; } /* * 构造看板泳道上的操作按钮。 * Build action buttons on the kanban lane. */ window.getLaneActions = function(lane) { return [{ type: 'dropdown', icon: 'ellipsis-v', caret: false, }]; } window.getCol = function(col) { /* 计算WIP。*/ if(['story', 'epic', 'requirement', 'parentStory'].includes(col.group) && ERURColumn.includes(col.type)) return; const limit = col.limit == -1 ? "" : col.limit; const cards = col.cards; col.subtitleClass = 'ml-1'; let wip = `(${cards}/${limit})`; if(col.limit != -1 && cards > col.limit) { col.subtitleClass += ' text-danger'; wip += ' '; } col.subtitle = {html: wip}; } window.getColActions = function(col) { let actionList = []; /* 父列不需要创建卡片相关的操作按钮。 */ if(col.parent != '-1' && (['backlog', 'unconfirmed', 'wait', 'active'].includes(col.type))) { let cardActions = buildColCardActions(col); if(cardActions.length > 0) actionList.push({type:'dropdown', icon:'expand-alt text-primary', caret:false, items:cardActions}); if(cardActions.length == 0 && ((col.type == 'backlog' && !priv.canCreateStory && productID == '0') || (col.type == 'unconfirmed' && !priv.canCreateBug && productID == '0'))) actionList.push({icon:'expand-alt text-primary', 'data-on': 'click', 'data-do': "zui.Modal.alert('" + needLinkProducts + "')"}); } actionList.push({type:'dropdown', icon:'ellipsis-v', caret:false, items:buildColActions(col)}); return actionList; } /* * 构造看板上的创建卡片相关操作按钮。 * Build create card related action buttons on the kanban. */ window.buildColCardActions = function(col) { let actions = []; if(col.group == 'parentStory') return actions; if(col.type == 'backlog') { if(priv.canCreateStory) actions.push({text: storyLang.create, url:$.createLink('story', 'create', 'productID=' + productID + '&branch=0&moduleID=0&storyID=0&objectID=' + executionID), 'data-toggle': 'modal', 'data-size': 'lg'}); if(priv.canBatchCreateStory) actions.push({text: executionLang.batchCreateStory, url: $.createLink('story', 'batchcreate', 'productID=' + productID + '&branch=0&moduleID=0&storyID=0&executionID=' + executionID), 'data-toggle': 'modal', 'data-size': 'lg'}); if(priv.canLinkStory) actions.push({text: executionLang.linkStory, url: $.createLink('execution', 'linkStory', 'executionID=' + executionID), 'data-toggle': 'modal', 'data-size': 'lg'}); if(priv.canLinkStoryByPlan) actions.push({text: executionLang.linkStoryByPlan, url: '#linkStoryByPlan', 'data-toggle': 'modal', 'data-size': 'sm'}); } else if(col.type == 'unconfirmed') { if(priv.canCreateBug) actions.push({text: bugLang.create, url: $.createLink('bug', 'create', 'productID=' + productID + '&moduleID=0&extra=executionID=' + executionID), 'data-toggle': 'modal', 'data-size': 'lg'}); if(priv.canBatchCreateBug) { if(productNum > 1) actions.push({text: bugLang.batchCreate, url: '#batchCreateBug', 'data-toggle': 'modal', 'data-size': 'lg'}); else actions.push({text: bugLang.batchCreate, url: $.createLink('bug', 'batchcreate', 'productID=' + productID + '&moduleID=0&executionID=' + executionID), 'data-toggle': 'modal', 'data-size': 'lg'}); } } else if(col.type == 'wait') { if(priv.canCreateTask) actions.push({text: taskLang.create, url: $.createLink('task', 'create', 'executionID=' + executionID), 'data-toggle': 'modal', 'data-size': 'lg'}); if(priv.canBatchCreateTask) actions.push({text: taskLang.batchCreate, url: $.createLink('task', 'batchcreate', 'executionID=' + executionID), 'data-toggle': 'modal', 'data-size': 'lg'}); if(priv.canImportBug && canImportBug) actions.push({text: executionLang.importBug, url: $.createLink('execution', 'importBug', 'executionID=' + executionID), 'data-toggle': 'modal', 'data-size': 'lg'}); } else if(col.type == 'active') { if(priv.canCreateRisk) actions.push({text: riskLang.create, url: $.createLink('risk', 'create', 'executionID=' + executionID + '&from=execution'), 'data-toggle': 'modal', 'data-size': 'lg'}); if(priv.canBatchCreateRisk) actions.push({text: riskLang.batchCreateRisk, url: $.createLink('risk', 'batchcreate', 'executionID=' + executionID + '&from=execution'), 'data-toggle': 'modal', 'data-size': 'lg'}); } return actions; } /* * 构造看板上的创建列、拆分列等操作按钮。 * Build create column, split column and other action buttons on the kanban. */ window.buildColActions = function(col) { let actions = []; if(priv.canEditName && col.actionList && col.actionList.includes('setColumn')) actions.push({text: kanbanLang.setColumn, url: $.createLink('kanban', 'setColumn', `columnID=${col.id}&executionID=${executionID}&from=RDKanban`), 'data-toggle': 'modal', 'icon': 'edit'}); if(priv.canSetWIP && col.actionList && col.actionList.includes('setWIP') && !(['story', 'epic', 'requirement', 'parentStory'].includes(col.group) && ERURColumn.includes(col.type))) actions.push({text: kanbanLang.setWIP, url: $.createLink('kanban', 'setWIP', `columnID=${col.id}&executionID=${executionID}&from=RDKanban`), 'data-toggle': 'modal', 'icon': 'alert'}); return actions; } /** * 渲染卡片内容。 * Render card content. */ window.getItem = function(info) { let begin = info.item.begin; let end = info.item.end; let beginAndEnd = ''; let assignLink = ''; let assignedTo = ''; let avatar = ""; info.item.originalTitle = info.item.title; if(begin < '1970-01-01' && end > '1970-01-01') { beginAndEnd = end + ' ' + cardLang.deadlineAB; } else if(end < '1970-01-01' && begin > '1970-01-01') { beginAndEnd = begin + ' ' + cardLang.beginAB; } else if(begin > '1970-01-01' && end > '1970-01-01') { beginAndEnd = formatDate(begin) + ' ~ ' + formatDate(end); } if(info.item.assignedTo && typeof userList[info.item.assignedTo] != 'undefined') { user = userList[info.item.assignedTo]; assignedTo = user.realname; userAvatar = user.avatar ? "" : assignedTo.slice(-2).toUpperCase(); avatar = "" + avatar + ""; } else if(['parentStory', 'requirement', 'epic'].includes(info.laneInfo.type)) { avatar = '
'; } if(info.laneInfo.type == 'risk') { var content = `
#${info.item.id} ${info.item.pri} ${info.item.strategy} ${beginAndEnd}
${avatar}
`; } else { var content = `
#${info.item.id} ${info.item.pri} ${beginAndEnd}
${avatar}
`; } if(searchValue != '') { info.item.title = info.item.title.replaceAll(searchValue, "" + searchValue + ""); info.item.title = {html: info.item.title}; } if(info.laneInfo.type == 'task') { let label = ''; if(info.item.isParent == '1') { label = "" + parentAB + " "; } else if(info.item.parent > 0) { label = "" + childrenAB + " "; } if(typeof info.item.title == 'string') info.item.title = {html: info.item.title}; if(label && typeof info.item.title == 'object') info.item.title.html = label + info.item.title.html; } if(['story', 'epic', 'requirement', 'parentStory'].includes(info.laneInfo.type)) { info.item.titleUrl = $.createLink('execution', 'storyView', `id=${info.item.id}&executionID=${executionID}`); } else if(info.laneInfo.type == 'task' || info.laneInfo.type == 'bug') { info.item.titleUrl = $.createLink(info.laneInfo.type, 'view', `id=${info.item.id}`); } else if(info.laneInfo.type == 'risk') { info.item.titleUrl = $.createLink(info.laneInfo.type, 'view', `id=${info.item.id}&from=execution`); } info.item.titleAttrs = {'data-toggle': 'modal', 'data-size': 'lg', 'title': info.item.originalTitle, 'class': 'card-title clip'}; info.item.content = {html: content}; if(info.item.color && info.item.color != '#fff') info.item.className = 'color-' + info.item.color.replace('#', ''); } window.getItemActions = function(item) { const actionList = typeof item.actionList == 'object' ? Object.values(item.actionList) : item.actionList; if(actionList.length) { return [{ type: 'dropdown', icon: 'ellipsis-v', caret: false, items: buildCardActions(item), }]; } } window.buildCardActions = function(item) { let actions = []; const actionList = typeof item.actionList == 'object' ? Object.values(item.actionList) : item.actionList; actionList.forEach(action => { actionMap = {'text': action.label, 'icon': action.icon, 'url': action.url}; if(typeof(action.confirm) != 'undefined') actionMap['data-confirm'] = action.confirm; if(typeof(action.modal) != 'undefined') actionMap['data-toggle'] = 'modal'; if(typeof(action.size) != 'undefined') actionMap['data-size'] = action.size; if(typeof(action.modal) == 'undefined') actionMap['innerClass'] = 'ajax-submit'; actions.push(actionMap); }); return actions; } window.canDrop = function(dragInfo, dropInfo) { if(!dragInfo || $.getFullscreenElement()) return false; const fromColumn = this.getCol(dragInfo.col); const toColumn = this.getCol(dropInfo.col); const lane = this.getLane(dropInfo.lane); const laneType = lanePairs[lane.id]; const fromColType = colPairs[fromColumn.id]; const toColType = colPairs[toColumn.id]; if(!fromColumn || !lane) return false; if(dragInfo.type == 'item' && dragInfo.item.group == 'task' && dragInfo.item.isParent == '1') return false; // 父任务不可拖动。 if(priv.canSortCards && dropInfo.type == 'item' && (dropInfo.col != dragInfo.item.col || dropInfo.lane != dragInfo.item.lane)) return false; if(!priv.canSortCards && dropInfo.type == 'item') return false; /* 卡片可在同组内拖动。 */ if(dragInfo.lane != dropInfo.lane) return false; if(dragInfo.item.group != toColumn.group) return false; if(dropInfo.type != 'item') { if(!canChangeObject) return false; let kanbanRules = kanbanDropRules[laneType]; let colRules = typeof kanbanRules[fromColType] == 'undefined' ? null : kanbanRules[fromColType]; if(!colRules) return false; if(!colRules.includes(toColType)) return false; } } window.onDrop = function(changes, dropInfo) { if(!dropInfo) return false; const toLaneID = dropInfo.drop.lane; const toColumn = this.getCol(dropInfo.drop.col); const laneType = lanePairs[dropInfo.drag.lane]; const fromColID = dropInfo.drag.col; const toColID = dropInfo.drop.col; const fromColType = colPairs[fromColID]; const toColType = colPairs[toColID]; const item = dropInfo.drag.item; const objectID = item.id; let link = ''; let moveCard = false; let laneID = toLaneID; if(typeof toColumn.laneName != 'undefined') laneID = toColumn.laneName; if(item.col == toColID && item.lane == toLaneID && priv.canSortCards) { link = $.createLink('kanban', 'sortCard', 'kanbanID=' + executionID + '&laneID=' + laneID + '&columnID=' + toColID + '&cards=' + dropInfo['data']['list'].join(',')); $.get(link, function(){refreshKanban()}) return true; } /* Task lane. */ if(laneType == 'task') { if(toColType == 'developed' && (fromColType == 'developing' || fromColType == 'wait') && priv.canFinishTask && typeof item.actionList.finish != 'undefined') link = $.createLink('task', 'finish', 'taskID=' + objectID + '&extra=from=taskkanban'); if(toColType == 'pause' && fromColType == 'developing' && priv.canPauseTask && typeof item.actionList.pause != 'undefined') link = $.createLink('task', 'pause', 'taskID=' + objectID + '&extra=from=taskkanban'); if(toColType == 'canceled' && (fromColType == 'developing' || fromColType == 'wait' || fromColType == 'pause') && priv.canCancelTask && typeof item.actionList.cancel != 'undefined') link = $.createLink('task', 'cancel', 'taskID=' + objectID + '&cardPosition=&from=taskkanban'); if(toColType == 'closed' && (fromColType == 'developed' || fromColType == 'canceled') && priv.canCloseTask) link = $.createLink('task', 'close', 'taskID=' + objectID + '&extra=from=taskkanban'); if(toColType == 'developing') { if((fromColType == 'canceled' || fromColType == 'closed' || fromColType == 'developed') && priv.canActivateTask && typeof item.actionList.activate != 'undefined') link = $.createLink('task', 'activate', 'taskID=' + objectID + '&extra=&from=taskkanban'); if(fromColType == 'pause' && priv.canActivateTask && typeof item.actionList.restart != 'undefined') link = $.createLink('task', 'restart', 'taskID=' + objectID + '&from=taskkanban'); if(fromColType == 'wait' && priv.canStartTask && typeof item.actionList.start != 'undefined') link = $.createLink('task', 'start', 'taskID=' + objectID + '&extra=from=taskkanban'); } } if(laneType == 'bug') { if(toColType == 'confirmed' && fromColType == 'unconfirmed' && priv.canConfirmBug) link = $.createLink('bug', 'confirm', 'bugID=' + objectID + '&extra=&from=taskkanban'); if(toColType == 'fixed' && (fromColType == 'fixing' || fromColType == 'confirmed' || fromColType == 'unconfirmed') && priv.canResolveBug) link = $.createLink('bug', 'resolve', 'bugID=' + objectID + '&extra=&from=taskkanban'); if(toColType == 'closed' && (fromColType == 'testing' || fromColType == 'tested') && priv.canCloseBug) link = $.createLink('bug', 'close', 'bugID=' + objectID + '&extra=&from=taskkanban'); if(toColType == 'testing' && fromColType == 'fixed') moveCard = true; if(toColType == 'tested' && (fromColType == 'fixed' || fromColType == 'testing')) moveCard = true; if(toColType == 'fixing') { if(fromColType == 'confirmed' || fromColType == 'unconfirmed') moveCard = true; if((fromColType == 'closed' || fromColType == 'fixed' || fromColType == 'testing' || fromColType == 'tested') && priv.canActivateBug) link = $.createLink('bug', 'activate', 'bugID=' + objectID); } if(moveCard) { link = $.createLink('kanban', 'ajaxMoveCard', 'cardID=' + objectID + '&fromColID=' + fromColID + '&toColID=' + toColID + '&fromLaneID=' + laneID + '&toLaneID=' + laneID + '&execitionID=' + executionID + '&browseType=' + browseType + '&groupBy=' + groupBy); refreshKanban(link); return true; } } if(laneType == 'story') { if(toColType == 'closed' && priv.canCloseStory) link = $.createLink('story', 'close', 'storyID=' + objectID + '&from=taskkanban'); if(toColType == 'ready') { if(item.status == 'draft' || item.status == 'changing' || item.status == 'reviewing') { zui.Modal.alert(executionLang.storyDragError); return false; } } if(!link) { ajaxMoveCard(objectID, fromColID, toColID, laneID, laneID); return true; } } if(laneType == 'risk') { let params = window.btoa('module=kanban&method=moveRiskCard&objectID=' + objectID + '&fromColID=' + fromColID + '&toColID=' + toColID + '&laneID=' + laneID + '&execution=' + executionID + '&browseType=' + browseType + '&groupBy=' + groupBy); if(toColType == 'active' && fromColType == 'track') { ajaxMoveCard(objectID, fromColID, toColID, laneID, laneID); return true; } if(toColType == 'active' && (fromColType == 'hangup' || fromColType == 'canceled' || fromColType == 'closed') && priv.canActivateRisk) link = $.createLink('risk', 'activate', 'riskID=' + objectID); if(toColType == 'track' && fromColType == 'active' && priv.canTrackRisk) link = $.createLink('risk', 'track', 'riskID=' + objectID + '¶ms=' + params); if(toColType == 'track' && (fromColType == 'hangup' || fromColType == 'canceled' || fromColType == 'closed') && priv.canTrackRisk) link = $.createLink('risk', 'activate', 'riskID=' + objectID + '¶ms=' + params); if(toColType == 'hangup' && (fromColType == 'active' || fromColType == 'track') && priv.canHangupRisk) link = $.createLink('risk', 'hangup', 'riskID=' + objectID); if(toColType == 'canceled' && (fromColType == 'active' || fromColType == 'track' || fromColType == 'hangup') && priv.canCancelRisk) link = $.createLink('risk', 'cancel', 'riskID=' + objectID); if(toColType == 'closed' && (fromColType == 'active' || fromColType == 'track' || fromColType == 'hangup' || fromColType == 'canceled') && priv.canCancelRisk) link = $.createLink('risk', 'close', 'riskID=' + objectID); } if(link) zui.Modal.open({url: link}); return false; } function formatDate(inputDate) { const date = new Date(inputDate); const formattedDate = `${(date.getMonth() + 1).toString().padStart(2, '0')}/${date.getDate().toString().padStart(2, '0')}`; return formattedDate; } window.fullScreen = function() { var element = document.getElementById('kanbanList'); var requestMethod = element.requestFullScreen || element.webkitRequestFullScreen || element.mozRequestFullScreen || element.msRequestFullscreen; if(requestMethod) { var afterEnterFullscreen = function() { $('#kanbanList').addClass('fullscreen').css('background', '#fff'); window.hideAllAction(); $.cookie.set('isFullScreen', 1, {expires:config.cookieLife, path:config.webRoot}); }; var whenFailEnterFullscreen = function() { exitFullScreen(); }; try { var result = requestMethod.call(element); if(result && (typeof result.then === 'function' || result instanceof window.Promise)) { result.then(afterEnterFullscreen).catch(whenFailEnterFullscreen); } else { afterEnterFullscreen(); } } catch (error) { whenFailEnterFullscreen(error); } } } /** * Exit full screen. * * @access public * @return void */ function exitFullScreen() { $('.btn').show(); $.cookie.set('isFullScreen', 0, {expires:config.cookieLife, path:config.webRoot}); $('#kanbanList .card-heading a').each(function(){restoreDiv($(this));}); $('#kanbanList .avatar').closest('a').each(function(){restoreDiv($(this));}); } function restoreDiv(obj) { const $this = $(obj); const relatedDiv = $this.data('relatedDiv'); if(relatedDiv) { relatedDiv.remove(); $this.show().removeData('relatedDiv'); } } document.addEventListener('fullscreenchange', function (e) { if(!document.fullscreenElement) exitFullScreen(); }); document.addEventListener('webkitfullscreenchange', function (e) { if(!document.webkitFullscreenElement) exitFullScreen(); }); document.addEventListener('mozfullscreenchange', function (e) { if(!document.mozFullScreenElement) exitFullScreen(); }); document.addEventListener('msfullscreenChange', function (e) { if(!document.msfullscreenElement) exitFullScreen(); }); window.hideAllAction = function() { $('.btn').hide(); $('#kanbanList .card-heading a').each(function(){replaceDiv($(this));}); $('#kanbanList .avatar').closest('a').each(function(){replaceDiv($(this));}); } function replaceDiv(obj) { var $this = $(obj); var newDiv = $('
').addClass($this.attr('class')).html($this.html()); $this.data('relatedDiv', newDiv).before(newDiv).hide(); } /** * AJAX: move card. * * @param int $objectID * @param int $fromColID * @param int $toColID * @param int $fromLaneID * @param int $toLaneID * @access public * @return void */ window.ajaxMoveCard = function(objectID, fromColID, toColID, fromLaneID, toLaneID) { var link = $.createLink('kanban', 'ajaxMoveCard', 'cardID=' + objectID + '&fromColID=' + fromColID + '&toColID=' + toColID + '&fromLaneID=' + fromLaneID + '&toLaneID=' + toLaneID + '&execitionID=' + executionID + '&browseType=' + browseType + '&groupBy=' + groupBy); refreshKanban(link); }; window.debounce = function (callback, delay) { let timer; return function() { const context = this; const args = arguments; clearTimeout(timer); timer = setTimeout(function () { callback.apply(context, args); }, delay); }; }; $('#taskKanbanSearchInput').on('input', debounce(function(){ searchCards($(this).val()); }, 500)); window.searchCards = function(value, order) { searchValue = value; if(typeof order == 'undefined') order = orderBy; refreshKanban($.createLink('execution', 'ajaxUpdateKanban', "executionID=" + executionID + "&entertime=0&browseType=" + browseType + "&groupBy=" + groupBy + '&from=taskkanban&searchValue=' + value + '&orderBy=' + order)); }; window.refreshKanban = function(url) { if(typeof url == 'undefined') url = $.createLink('execution', 'ajaxUpdateKanban', "executionID=" + executionID + "&entertime=0&browseType=" + browseType + "&groupBy=" + groupBy + '&from=taskkanban&searchValue=' + searchValue + '&orderBy=' + orderBy); const $kanbanList = $('[data-zui-kanbanlist]').zui('kanbanList'); let options = $kanbanList.options; $.getJSON(url, function(data) { for(const group of data) { group.getLane = window.getLane; group.getCol = window.getCol; group.getItem = window.getItem; group.canDrop = window.canDrop; group.onDrop = window.onDrop; group.minColWidth = minColWidth; group.maxColWidth = maxColWidth; group.colProps = {'actions': window.getColActions}; group.itemProps = {'actions': window.getItemActions}; } options.items = data; $kanbanList.render(options); }); }; waitDom('.c-group .picker-box .picker-single-selection', function(){this.html(kanbanLang.laneGroup + ': ' + this.attr('title'));}); $(document).off('click', '#linkStoryByPlan button[type="submit"]').on('click', '#linkStoryByPlan button[type="submit"]', function() { const planID = $('[name=plan]').val(); if(planID) { var param = "¶m=executionID=" + executionID + ",browseType=" + browseType + ",orderBy=id_asc,groupBy=" + groupBy; $.ajaxSubmit({url: $.createLink('execution', 'importPlanStories', 'executionID=' + executionID + '&planID=' + planID + '&productID=0&fromMethod=taskKanban&extra=' + param)}); } return false; })