From bffc71132dead146c65c8732e186dc3a2c820e6b Mon Sep 17 00:00:00 2001 From: tianshujie Date: Mon, 24 Jan 2022 16:58:14 +0800 Subject: [PATCH 01/16] * Add permission judgment. --- module/kanban/config.php | 2 +- module/kanban/model.php | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/module/kanban/config.php b/module/kanban/config.php index fe33b047f2..3ccfd55b79 100644 --- a/module/kanban/config.php +++ b/module/kanban/config.php @@ -47,7 +47,7 @@ $config->kanban->editor->viewcard = array('id' => 'comment', 'tools' => 'simp $config->kanban->fromType = array('execution', 'productplan', 'release', 'build'); $config->kanban->executionField = array('name', 'status', 'end', 'PM', 'type', 'deleted'); $config->kanban->productplanField = array(); -$config->kanban->releaseField = array(); +$config->kanban->releaseField = array('name', 'status', 'date'); $config->kanban->buildField = array(); $config->kanban->default = new stdclass(); diff --git a/module/kanban/model.php b/module/kanban/model.php index fcd4581d27..ac3fddf325 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -1032,7 +1032,7 @@ class kanbanModel extends model ->andWhere('type')->eq('common') ->fetchAll(); - $actions = array('editCard', 'finishCard', 'activateCard', 'archiveCard', 'deleteCard', 'moveCard', 'setCardColor', 'viewCard', 'sortCard', 'viewExecution'); + $actions = array('editCard', 'finishCard', 'activateCard', 'archiveCard', 'deleteCard', 'moveCard', 'setCardColor', 'viewCard', 'sortCard', 'viewExecution', 'viewPlan', 'viewRelease', 'viewBuild'); $cardGroup = array(); foreach($cellList as $cell) @@ -1051,13 +1051,17 @@ class kanbanModel extends model $card->actions = array(); foreach($actions as $action) { - if($action == 'viewExecution') + if(in_array($action, array('viewExecution', 'viewPlan', 'viewRelease', 'viewBuild'))) { if($card->fromType == 'execution') { if($card->execType == 'kanban' and common::hasPriv('execution', 'kanban')) $card->actions[] = $action; if($card->execType != 'kanban' and common::hasPriv('execution', 'view')) $card->actions[] = $action; } + else + { + if(common::hasPriv($fromType, 'view')) $card->actions[] = $action; + } continue; } if(common::hasPriv('kanban', $action)) $card->actions[] = $action; From 331e00ab2bdef027922a90685726e744659d4e25 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Mon, 24 Jan 2022 17:04:07 +0800 Subject: [PATCH 02/16] * Modify area style. --- module/kanban/css/view.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/kanban/css/view.css b/module/kanban/css/view.css index 735d62d60e..a5db20fa63 100644 --- a/module/kanban/css/view.css +++ b/module/kanban/css/view.css @@ -12,7 +12,7 @@ #kanbanContainer {padding-bottom: 0; margin-bottom: 0;} #kanbanContainer.fullscreen {overflow: auto;} -.region {border: 1px solid #dcdcdc; background-color: #fff;} +.region {border: 1px solid #dcdcdc; background-color: #fff; overflow: scroll;} .region + .region {margin-top: 20px;} .region .region-header {padding: 10px;} .region .region-header span {font-size: 14px; color: #999EAB} From c4fffd292ed1e28368a639d291179622b522efc4 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Mon, 24 Jan 2022 17:04:10 +0800 Subject: [PATCH 03/16] * Modify iframe class. --- module/kanban/js/view.js | 8 ++++---- module/kanban/view/importbuild.html.php | 4 ++-- module/kanban/view/importcard.html.php | 4 ++-- module/kanban/view/importexecution.html.php | 4 ++-- module/kanban/view/importplan.html.php | 4 ++-- module/kanban/view/importrelease.html.php | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/module/kanban/js/view.js b/module/kanban/js/view.js index 8136b47aa2..7d818e713c 100644 --- a/module/kanban/js/view.js +++ b/module/kanban/js/view.js @@ -1099,10 +1099,10 @@ $(function() var columnID = $(this).closest('.kanban-col').data('id'); /* The submenu of import. */ - var importPlanLink = kanban.object.indexOf('plan') != -1 ? "
  • " + kanbanLang.importPlan + '
  • ' : ''; - var importReleaseLink = kanban.object.indexOf('release') != -1 ? "
  • " + kanbanLang.importRelease + '
  • ' : ''; - var importExecutionLink = kanban.object.indexOf('execution') != -1 ? "
  • " + kanbanLang.importExecution + '
  • ' : ''; - var importBuildLink = kanban.object.indexOf('build') != -1 ? "
  • " + kanbanLang.importBuild + '
  • ' : ''; + var importPlanLink = kanban.object.indexOf('plan') != -1 ? "
  • " + kanbanLang.importPlan + '
  • ' : ''; + var importReleaseLink = kanban.object.indexOf('release') != -1 ? "
  • " + kanbanLang.importRelease + '
  • ' : ''; + var importExecutionLink = kanban.object.indexOf('execution') != -1 ? "
  • " + kanbanLang.importExecution + '
  • ' : ''; + var importBuildLink = kanban.object.indexOf('build') != -1 ? "
  • " + kanbanLang.importBuild + '
  • ' : ''; var importSubmenu = ''; $('.import').parent().append(importSubmenu); diff --git a/module/kanban/view/importbuild.html.php b/module/kanban/view/importbuild.html.php index e148aa7f65..621630cb7b 100644 --- a/module/kanban/view/importbuild.html.php +++ b/module/kanban/view/importbuild.html.php @@ -24,11 +24,11 @@

    kanban->selectedProject;?>

    -
    +

    kanban->selectedLane;?>

    -
    +
    diff --git a/module/kanban/view/importcard.html.php b/module/kanban/view/importcard.html.php index 7b6e79662c..dd6cdfbabe 100644 --- a/module/kanban/view/importcard.html.php +++ b/module/kanban/view/importcard.html.php @@ -24,11 +24,11 @@

    kanban->selectedKanban;?>

    -
    +

    kanban->selectedLane;?>

    -
    +
    diff --git a/module/kanban/view/importexecution.html.php b/module/kanban/view/importexecution.html.php index ca22858247..5c44d0ef8d 100644 --- a/module/kanban/view/importexecution.html.php +++ b/module/kanban/view/importexecution.html.php @@ -24,11 +24,11 @@

    kanban->selectedProject;?>

    -
    +

    kanban->selectedLane;?>

    -
    +
    diff --git a/module/kanban/view/importplan.html.php b/module/kanban/view/importplan.html.php index 813f86fe58..8787cbc82a 100644 --- a/module/kanban/view/importplan.html.php +++ b/module/kanban/view/importplan.html.php @@ -24,11 +24,11 @@

    kanban->selectedProduct;?>

    -
    +

    kanban->selectedLane;?>

    -
    +
    diff --git a/module/kanban/view/importrelease.html.php b/module/kanban/view/importrelease.html.php index e9bf78dfac..2dcac7727a 100644 --- a/module/kanban/view/importrelease.html.php +++ b/module/kanban/view/importrelease.html.php @@ -24,11 +24,11 @@

    kanban->selectedProduct;?>

    -
    +

    kanban->selectedLane;?>

    -
    +
    From 7a7ad37f3cbf871d0c9ffa43e04ea530a7d0f7a5 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Mon, 24 Jan 2022 18:16:28 +0800 Subject: [PATCH 04/16] * Finish task #47990. --- module/kanban/config.php | 2 +- module/kanban/css/view.css | 22 +++++----- module/kanban/js/view.js | 71 +++++++++++++++++++++++++++++++- module/kanban/view/view.html.php | 2 + 4 files changed, 84 insertions(+), 13 deletions(-) diff --git a/module/kanban/config.php b/module/kanban/config.php index 3ccfd55b79..c612fdf70e 100644 --- a/module/kanban/config.php +++ b/module/kanban/config.php @@ -47,7 +47,7 @@ $config->kanban->editor->viewcard = array('id' => 'comment', 'tools' => 'simp $config->kanban->fromType = array('execution', 'productplan', 'release', 'build'); $config->kanban->executionField = array('name', 'status', 'end', 'PM', 'type', 'deleted'); $config->kanban->productplanField = array(); -$config->kanban->releaseField = array('name', 'status', 'date'); +$config->kanban->releaseField = array('name', 'status', 'date', 'deleted'); $config->kanban->buildField = array(); $config->kanban->default = new stdclass(); diff --git a/module/kanban/css/view.css b/module/kanban/css/view.css index a5db20fa63..731bde545c 100644 --- a/module/kanban/css/view.css +++ b/module/kanban/css/view.css @@ -102,15 +102,17 @@ .gray .actions {display:none;} .kanban-card .header .executionName {display: flex; width: 100%; float: left; white-space: nowrap; overflow: hidden;} -.kanban-card .header .executionName .title {padding-right: 0px; margin-right: 5px; white-space: nowrap; overflow: hidden;} -.kanban-card .header .executionName .title .icon {padding-right: 5px;} +.kanban-card .header .executionName .title, .releaseTitle {padding-right: 0px; margin-right: 5px; white-space: nowrap; overflow: hidden;} .kanban-card .header .executionName > span {flex: none;} -.execInfo {margin-top: 23px;} +.execInfo, .releaseInfo {margin-top: 23px;} .execInfo .execStatus{margin-right: 20px;} -.execInfo .label-wait {background: #EFEFEF !important; color: #838A9D;} -.execInfo .label-doing {background: #f8d2d2 !important; color: #e64b4c;} -.execInfo .label-suspended {background: #fff3d9 !important; color: #ff9800;} -.execInfo .label-closed {background: #e5e5e5 !important; color: #b8b8b8;} -.execInfo .label-deleted {background: #ff5d5d !important; color: #fff;} -.region .kanban-item > .kanban-card > .execInfo > .user {position: absolute; right: 10px; bottom: -2px} -.region .kanban-item > .kanban-card > .execInfo > .user > .avatar {display: inline-block; width: 24px; height: 24px; line-height: 24px; margin-right: 0px; margin-left: 2px} +.label-wait {background: #EFEFEF !important; color: #838A9D;} +.label-doing {background: #f8d2d2 !important; color: #e64b4c;} +.label-suspended {background: #fff3d9 !important; color: #ff9800;} +.label-closed, .label-terminate {background: #e5e5e5 !important; color: #b8b8b8;} +.label-deleted {background: #ff5d5d !important; color: #fff;} +.label-normal {background: #e1e8d9 !important; color: #9abe76;} +.region .kanban-item > .kanban-card > .execInfo > .user, .region .kanban-item > .kanban-card > .releaseInfo > .user {position: absolute; right: 10px; bottom: -2px} +.region .kanban-item > .kanban-card > .execInfo > .user > .avatar, .region .kanban-item > .kanban-card > .releaseInfo > .user > .avatar {display: inline-block; width: 24px; height: 24px; line-height: 24px; margin-right: 0px; margin-left: 2px} +.kanban-card .releaseTitle .icon, .kanban-card .title .icon {padding-right: 5px;} +.kanban-card .releaseTitle {width: 100%; float: left;} diff --git a/module/kanban/js/view.js b/module/kanban/js/view.js index 8136b47aa2..86ce2ccf53 100644 --- a/module/kanban/js/view.js +++ b/module/kanban/js/view.js @@ -280,6 +280,10 @@ function renderKanbanItem(item, $item) { renderExecutionItem(item, $item); } + else if(item.fromType == 'release') + { + renderReleaseItem(item, $item); + } else { var $title = $item.children('.title'); @@ -457,9 +461,72 @@ function renderExecutionItem(item, $item) /* Display avatars of PM. */ var $user = $info.children('.user'); var user = [item.PM]; - if(!$user.length) $user = $('
    ').appendTo($info); + if(users[item.PM]) + { + if(!$user.length) $user = $('
    ').appendTo($info); + $user.html(renderUsersAvatar(user, item.id)).attr('title', users[item.PM]); + } +} - $user.html(renderUsersAvatar(user, item.id)).attr('title', item.PM); +/** + * Render plan item. + * + * @param object item + * @param object $item + * @access public + * @return void + */ +function renderReleaseItem(item, $item) +{ + var privs = item.actions; + + /* Print name. */ + var $title = $item.children('.releaseTitle'); + if(!$title.length) + { + if(privs.includes('viewRelease') && item.deleted == '0') $title = $('' + item.name + '').appendTo($item).attr('href', createLink('release', 'view', 'releaseID=' + item.fromID)); + if(!privs.includes('viewRelease') || item.deleted == '1') $title = $('' + item.name + '').appendTo($item); + } + $title.attr('title', item.name); + + var $info = $item.children('.releaseInfo'); + if(!$info.length) $info = $( + [ + '
    ', + '
    ' + ].join('')).appendTo($item); + + var $statusBox = $info.children('.releaseStatus'); + if(!$statusBox.length) + { + if(item.deleted == '0') + { + $statusBox = $('' + releaseLang.statusList[item.status] + '').appendTo($info); + } + else + { + $statusBox = $('' + releaseLang.deleted + '').appendTo($info); + } + } + + /* Display release date. */ + var $date = $info.children('.date'); + var releaseDate = $.zui.createDate(item.date); + var today = new Date(); + var labelType = releaseDate.toLocaleDateString() == today.toLocaleDateString() ? 'light' : 'wait'; + if(!$date.length) $date = $('').appendTo($info); + + $date.text($.zui.formatDate(releaseDate, 'yyyy-MM-dd')).attr('title', $.zui.formatDate(releaseDate, 'yyyy-MM-dd')).show(); + if(labelType == 'light') $date.css('background-color', 'rgba(210, 50, 61, 0.3)'); + + /* Display avatars of creator. */ + var $user = $info.children('.user'); + var user = [item.createdBy]; + if(users[item.createdBy]) + { + if(!$user.length) $user = $('
    ').appendTo($info); + $user.html(renderUsersAvatar(user, item.id)).attr('title', users[item.createdBy]); + } } /** diff --git a/module/kanban/view/view.html.php b/module/kanban/view/view.html.php index a63744238e..12e47ee495 100644 --- a/module/kanban/view/view.html.php +++ b/module/kanban/view/view.html.php @@ -15,6 +15,7 @@ loadLang('execution'); +$app->loadLang('release'); $laneCount = 0; foreach($regions as $region) $laneCount += $region->laneCount; @@ -25,6 +26,7 @@ js::set('kanbanlaneLang', $lang->kanbanlane); js::set('kanbancolumnLang', $lang->kanbancolumn); js::set('kanbancardLang', $lang->kanbancard); js::set('executionLang', $lang->execution); +js::set('releaseLang', $lang->release); js::set('kanbanID', $kanban->id); js::set('laneCount', $laneCount); js::set('userList', $userList); From c1faac726f59a71b0d6fd18577dd184a51455c41 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Mon, 24 Jan 2022 18:26:16 +0800 Subject: [PATCH 05/16] * Finish task #47992. --- module/kanban/config.php | 2 +- module/kanban/js/view.js | 52 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/module/kanban/config.php b/module/kanban/config.php index c612fdf70e..2a30d9f20c 100644 --- a/module/kanban/config.php +++ b/module/kanban/config.php @@ -48,7 +48,7 @@ $config->kanban->fromType = array('execution', 'productplan', 'release', $config->kanban->executionField = array('name', 'status', 'end', 'PM', 'type', 'deleted'); $config->kanban->productplanField = array(); $config->kanban->releaseField = array('name', 'status', 'date', 'deleted'); -$config->kanban->buildField = array(); +$config->kanban->buildField = array('name', 'date', 'builder'); $config->kanban->default = new stdclass(); $config->kanban->default->story = new stdclass(); diff --git a/module/kanban/js/view.js b/module/kanban/js/view.js index c8760f5c21..83a7b76e4b 100644 --- a/module/kanban/js/view.js +++ b/module/kanban/js/view.js @@ -284,6 +284,10 @@ function renderKanbanItem(item, $item) { renderReleaseItem(item, $item); } + else if(item.fromType == 'build') + { + renderBuildItem(item, $item); + } else { var $title = $item.children('.title'); @@ -529,6 +533,54 @@ function renderReleaseItem(item, $item) } } +/** + * Render build item. + * + * @param object item + * @param object $item + * @access public + * @return void + */ +function renderBuildItem(item, $item) +{ + var privs = item.actions; + + /* Print name. */ + var $title = $item.children('.title'); + if(!$title.length) + { + if(privs.includes('viewBuild') && item.deleted == '0') $title = $('' + item.name + '').appendTo($item).attr('href', createLink('build', 'view', 'buildID=' + item.fromID)); + if(!privs.includes('viewBuild') || item.deleted == '1') $title = $('' + item.name + '').appendTo($item); + } + $title.attr('title', item.name); + + var $info = $item.children('.info'); + if(!$info.length) $info = $( + [ + '
    ', + '
    ' + ].join('')).appendTo($item); + + /* Display build date. */ + var $date = $info.children('.date'); + var buildDate = $.zui.createDate(item.date); + var today = new Date(); + var labelType = buildDate.toLocaleDateString() == today.toLocaleDateString() ? 'light' : 'wait'; + if(!$date.length) $date = $('').appendTo($info); + + $date.text($.zui.formatDate(buildDate, 'yyyy-MM-dd')).attr('title', $.zui.formatDate(buildDate, 'yyyy-MM-dd')).show(); + if(labelType == 'light') $date.css('background-color', 'rgba(210, 50, 61, 0.3)'); + + /* Display avatars of creator. */ + var $user = $info.children('.user'); + var user = [item.builder]; + if(users[item.builder]) + { + if(!$user.length) $user = $('
    ').appendTo($info); + $user.html(renderUsersAvatar(user, item.id)).attr('title', users[item.builder]); + } +} + /** * Show error message * @param {string|object} message Message From 053985fb05b418545477cc793fffd1be112d5c88 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Mon, 24 Jan 2022 23:12:40 +0800 Subject: [PATCH 06/16] * Code for task#47988. --- module/kanban/config.php | 2 +- module/kanban/css/view.css | 12 +++--- module/kanban/js/view.js | 65 ++++++++++++++++++++++++++++++++ module/kanban/model.php | 13 ++++--- module/kanban/view/view.html.php | 2 + 5 files changed, 82 insertions(+), 12 deletions(-) diff --git a/module/kanban/config.php b/module/kanban/config.php index 2a30d9f20c..3a08fde5c7 100644 --- a/module/kanban/config.php +++ b/module/kanban/config.php @@ -46,7 +46,7 @@ $config->kanban->editor->viewcard = array('id' => 'comment', 'tools' => 'simp $config->kanban->fromType = array('execution', 'productplan', 'release', 'build'); $config->kanban->executionField = array('name', 'status', 'end', 'PM', 'type', 'deleted'); -$config->kanban->productplanField = array(); +$config->kanban->productplanField = array('title', 'status', 'begin', 'end', 'deleted'); $config->kanban->releaseField = array('name', 'status', 'date', 'deleted'); $config->kanban->buildField = array('name', 'date', 'builder'); diff --git a/module/kanban/css/view.css b/module/kanban/css/view.css index 731bde545c..5efe68a76a 100644 --- a/module/kanban/css/view.css +++ b/module/kanban/css/view.css @@ -102,9 +102,9 @@ .gray .actions {display:none;} .kanban-card .header .executionName {display: flex; width: 100%; float: left; white-space: nowrap; overflow: hidden;} -.kanban-card .header .executionName .title, .releaseTitle {padding-right: 0px; margin-right: 5px; white-space: nowrap; overflow: hidden;} +.kanban-card .header .executionName .title, .releaseTitle, .productplanTitle {padding-right: 0px; margin-right: 5px; white-space: nowrap; overflow: hidden;} .kanban-card .header .executionName > span {flex: none;} -.execInfo, .releaseInfo {margin-top: 23px;} +.execInfo, .releaseInfo, .productplanInfo {margin-top: 23px;} .execInfo .execStatus{margin-right: 20px;} .label-wait {background: #EFEFEF !important; color: #838A9D;} .label-doing {background: #f8d2d2 !important; color: #e64b4c;} @@ -112,7 +112,7 @@ .label-closed, .label-terminate {background: #e5e5e5 !important; color: #b8b8b8;} .label-deleted {background: #ff5d5d !important; color: #fff;} .label-normal {background: #e1e8d9 !important; color: #9abe76;} -.region .kanban-item > .kanban-card > .execInfo > .user, .region .kanban-item > .kanban-card > .releaseInfo > .user {position: absolute; right: 10px; bottom: -2px} -.region .kanban-item > .kanban-card > .execInfo > .user > .avatar, .region .kanban-item > .kanban-card > .releaseInfo > .user > .avatar {display: inline-block; width: 24px; height: 24px; line-height: 24px; margin-right: 0px; margin-left: 2px} -.kanban-card .releaseTitle .icon, .kanban-card .title .icon {padding-right: 5px;} -.kanban-card .releaseTitle {width: 100%; float: left;} +.region .kanban-item > .kanban-card > .execInfo > .user, .region .kanban-item > .kanban-card > .releaseInfo > .user, .region .kanban-item > .kanban-card > .productplanInfo > .user {position: absolute; right: 10px; bottom: -2px} +.region .kanban-item > .kanban-card > .execInfo > .user > .avatar, .region .kanban-item > .kanban-card > .releaseInfo > .user > .avatar, .region .kanban-item > .kanban-card > .productplanInfo > .user > .avatar {display: inline-block; width: 24px; height: 24px; line-height: 24px; margin-right: 0px; margin-left: 2px} +.kanban-card .releaseTitle .icon, .kanban-card .title .icon, .kanban-card .productplanTitle .icon, .kanban-card .title .icon {padding-right: 5px;} +.kanban-card .releaseTitle, .kanban-card .productplanTitle {width: 100%; float: left;} diff --git a/module/kanban/js/view.js b/module/kanban/js/view.js index 83a7b76e4b..3769819126 100644 --- a/module/kanban/js/view.js +++ b/module/kanban/js/view.js @@ -288,6 +288,10 @@ function renderKanbanItem(item, $item) { renderBuildItem(item, $item); } + else if(item.fromType == 'productplan') + { + renderProductplanItem(item, $item); + } else { var $title = $item.children('.title'); @@ -533,6 +537,67 @@ function renderReleaseItem(item, $item) } } +/** + * Render product plan item. + * + * @param object item + * @param object $item + * @access public + * @return void + */ +function renderProductplanItem(item, $item) +{ + var privs = item.actions; + + /* Print name. */ + var $title = $item.children('.productplanTitle'); + if(!$title.length) + { + if(privs.includes('viewPlan') && item.deleted == '0') $title = $('' + item.title + '').appendTo($item).attr('href', createLink('productplan', 'view', 'productplanID=' + item.fromID)); + if(!privs.includes('viewPlan') || item.deleted == '1') $title = $('' + item.title + '').appendTo($item); + } + $title.attr('title', item.title); + + var $info = $item.children('.productplanInfo'); + if(!$info.length) $info = $( + [ + '
    ', + '
    ' + ].join('')).appendTo($item); + + var $statusBox = $info.children('.productplanStatus'); + if(!$statusBox.length) + { + if(item.deleted == '0') + { + $statusBox = $('' + productplanLang.statusList[item.status] + '').appendTo($info); + } + else + { + $statusBox = $('' + productplanLang.deleted + '').appendTo($info); + } + } + + /* Display product plan date. */ + var $date = $info.children('.date'); + var productplanDate = $.zui.createDate(item.date); + var today = new Date(); + var labelType = productplanDate.toLocaleDateString() == today.toLocaleDateString() ? 'light' : 'wait'; + if(!$date.length) $date = $('').appendTo($info); + + $date.text($.zui.formatDate(productplanDate, 'yyyy-MM-dd')).attr('title', $.zui.formatDate(productplanDate, 'yyyy-MM-dd')).show(); + if(labelType == 'light') $date.css('background-color', 'rgba(210, 50, 61, 0.3)'); + + /* Display avatars of creator. */ + var $user = $info.children('.user'); + var user = [item.createdBy]; + if(users[item.createdBy]) + { + if(!$user.length) $user = $('
    ').appendTo($info); + $user.html(renderUsersAvatar(user, item.id)).attr('title', users[item.createdBy]); + } +} + /** * Render build item. * diff --git a/module/kanban/model.php b/module/kanban/model.php index ac3fddf325..06fa9a9c0d 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -523,14 +523,17 @@ class kanbanModel extends model $targetLaneID = $data->targetLane; $objectCards = array(); + $now = helper::now(); foreach($objectIDList as $objectID) { $cardData = new stdClass(); - $cardData->kanban = $kanbanID; - $cardData->region = $regionID; - $cardData->group = $groupID; - $cardData->fromID = $objectID; - $cardData->fromType = $objectType; + $cardData->kanban = $kanbanID; + $cardData->region = $regionID; + $cardData->group = $groupID; + $cardData->fromID = $objectID; + $cardData->fromType = $objectType; + $cardData->createdBy = $this->app->user->account; + $cardData->createdDate = $now; $this->dao->insert(TABLE_KANBANCARD)->data($cardData)->exec(); $cardID = $this->dao->lastInsertID(); diff --git a/module/kanban/view/view.html.php b/module/kanban/view/view.html.php index 12e47ee495..0322c6e2b7 100644 --- a/module/kanban/view/view.html.php +++ b/module/kanban/view/view.html.php @@ -16,6 +16,7 @@ loadLang('execution'); $app->loadLang('release'); +$app->loadLang('productplan'); $laneCount = 0; foreach($regions as $region) $laneCount += $region->laneCount; @@ -27,6 +28,7 @@ js::set('kanbancolumnLang', $lang->kanbancolumn); js::set('kanbancardLang', $lang->kanbancard); js::set('executionLang', $lang->execution); js::set('releaseLang', $lang->release); +js::set('productplanLang', $lang->productplan); js::set('kanbanID', $kanban->id); js::set('laneCount', $laneCount); js::set('userList', $userList); From d5210fdc57ea4413d96d9307c9b4fa033c95fd87 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Tue, 25 Jan 2022 07:58:57 +0800 Subject: [PATCH 07/16] * Modify writing error. --- db/zentao.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/zentao.sql b/db/zentao.sql index 9fcaf3a999..133e72936b 100644 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -709,7 +709,7 @@ CREATE TABLE `zt_kanbancard` ( `kanban` mediumint(8) unsigned NOT NULL, `region` mediumint(8) unsigned NOT NULL, `group` mediumint(8) unsigned NOT NULL, - `fromID` mediumint(8) undigned NOT NULL, + `fromID` mediumint(8) unsigned NOT NULL, `fromType` varchar(30) NOT NULL, `name` varchar(255) NOT NULL, `pri` mediumint(8) unsigned NOT NULL, From 1801b1e783b273ad1f83d8d760c2f0365468b122 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Tue, 25 Jan 2022 09:10:26 +0800 Subject: [PATCH 08/16] * Add pending future to the product plan. --- module/kanban/css/view.css | 1 + module/kanban/js/view.js | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/module/kanban/css/view.css b/module/kanban/css/view.css index 5efe68a76a..81b5c22cc8 100644 --- a/module/kanban/css/view.css +++ b/module/kanban/css/view.css @@ -109,6 +109,7 @@ .label-wait {background: #EFEFEF !important; color: #838A9D;} .label-doing {background: #f8d2d2 !important; color: #e64b4c;} .label-suspended {background: #fff3d9 !important; color: #ff9800;} +.label-future {background: #EFEFEF !important; color: #838A9D; border-radius: 9px} .label-closed, .label-terminate {background: #e5e5e5 !important; color: #b8b8b8;} .label-deleted {background: #ff5d5d !important; color: #fff;} .label-normal {background: #e1e8d9 !important; color: #9abe76;} diff --git a/module/kanban/js/view.js b/module/kanban/js/view.js index 3769819126..dd04421bbb 100644 --- a/module/kanban/js/view.js +++ b/module/kanban/js/view.js @@ -578,15 +578,21 @@ function renderProductplanItem(item, $item) } } - /* Display product plan date. */ - var $date = $info.children('.date'); - var productplanDate = $.zui.createDate(item.date); - var today = new Date(); - var labelType = productplanDate.toLocaleDateString() == today.toLocaleDateString() ? 'light' : 'wait'; - if(!$date.length) $date = $('').appendTo($info); + /* Display deadline of product plan. */ + var $date = $info.children('.date'); + var begin = $.zui.createDate(item.begin); + var end = $.zui.createDate(item.end); + var today = new Date(); + var labelType = 'wait'; + var labelTitle = $.zui.formatDate(begin, 'MM-dd') + ' ' + productplanLang.to + ' ' + $.zui.formatDate(end, 'MM-dd'); - $date.text($.zui.formatDate(productplanDate, 'yyyy-MM-dd')).attr('title', $.zui.formatDate(productplanDate, 'yyyy-MM-dd')).show(); - if(labelType == 'light') $date.css('background-color', 'rgba(210, 50, 61, 0.3)'); + if((item.begin == '2030-01-01' || item.end == '2030-01-01')) + { + labelType = 'future'; + labelTitle = productplanLang.future; + } + if(!$date.length) $date = $('').appendTo($info); + $date.text(labelTitle).attr('title', labelTitle).show(); /* Display avatars of creator. */ var $user = $info.children('.user'); From 590715c6d4f4f6656c16e4df4f76e0e9206a2927 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Tue, 25 Jan 2022 09:25:35 +0800 Subject: [PATCH 09/16] * Query plan and version creator. --- module/kanban/model.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/module/kanban/model.php b/module/kanban/model.php index 06fa9a9c0d..7230d683bc 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -1088,6 +1088,7 @@ class kanbanModel extends model */ public function getImportedCards($kanbanID, $cards, $fromType) { + /* Get imported cards based on imported object type. */ $objectCards = $this->dao->select('*')->from(TABLE_KANBANCARD) ->where('deleted')->eq(0) ->andWhere('kanban')->eq($kanbanID) @@ -1097,11 +1098,22 @@ class kanbanModel extends model if(!empty($objectCards)) { + /* Get imported objects. */ $table = $this->config->objectTables[$fromType]; $objects = $this->dao->select('*')->from($table) ->where('id')->in(array_keys($objectCards)) ->fetchAll('id'); + if($fromType == 'productplan' or $fromType == 'release') + { + $creators = $this->dao->select('objectID, actor')->from(TABLE_ACTION) + ->where('objectID')->in(array_keys($objectCards)) + ->andWhere('objectType')->eq($fromType) + ->andWhere('action')->eq('opened') + ->fetchPairs(); + } + + /* Data for constructing the card. */ foreach($objectCards as $objectCard) { $object = $objects[$objectCard->fromID]; @@ -1109,6 +1121,11 @@ class kanbanModel extends model foreach($this->config->kanban->$fieldType as $field) $objectCard->$field = $object->$field; + if($fromType == 'productplan' or $fromType == 'release') + { + $objectCard->createdBy = zget($creators, $object->id, ''); + } + if($fromType =='execution') { if($object->status != 'done' and $object->status != 'closed' and $object->status != 'suspended') From 14c68e0cf72090497529aae9a1876bd60aa33ee2 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Tue, 25 Jan 2022 09:29:43 +0800 Subject: [PATCH 10/16] * Modify card style. --- module/kanban/css/view.css | 1 - 1 file changed, 1 deletion(-) diff --git a/module/kanban/css/view.css b/module/kanban/css/view.css index 81b5c22cc8..9a482fc618 100644 --- a/module/kanban/css/view.css +++ b/module/kanban/css/view.css @@ -105,7 +105,6 @@ .kanban-card .header .executionName .title, .releaseTitle, .productplanTitle {padding-right: 0px; margin-right: 5px; white-space: nowrap; overflow: hidden;} .kanban-card .header .executionName > span {flex: none;} .execInfo, .releaseInfo, .productplanInfo {margin-top: 23px;} -.execInfo .execStatus{margin-right: 20px;} .label-wait {background: #EFEFEF !important; color: #838A9D;} .label-doing {background: #f8d2d2 !important; color: #e64b4c;} .label-suspended {background: #fff3d9 !important; color: #ff9800;} From a8334bed66a8650eb98d403fefe62e4fae404f5d Mon Sep 17 00:00:00 2001 From: tianshujie Date: Tue, 25 Jan 2022 10:02:59 +0800 Subject: [PATCH 11/16] * Modify details. --- module/kanban/js/view.js | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/module/kanban/js/view.js b/module/kanban/js/view.js index dd04421bbb..285317c107 100644 --- a/module/kanban/js/view.js +++ b/module/kanban/js/view.js @@ -488,12 +488,12 @@ function renderReleaseItem(item, $item) { var privs = item.actions; - /* Print name. */ + /* Print name. */ var $title = $item.children('.releaseTitle'); if(!$title.length) { - if(privs.includes('viewRelease') && item.deleted == '0') $title = $('' + item.name + '').appendTo($item).attr('href', createLink('release', 'view', 'releaseID=' + item.fromID)); - if(!privs.includes('viewRelease') || item.deleted == '1') $title = $('' + item.name + '').appendTo($item); + if(privs.includes('viewRelease') && item.deleted == '0') $title = $('' + item.name + '').appendTo($item).attr('href', createLink('release', 'view', 'releaseID=' + item.fromID)); + if(!privs.includes('viewRelease') || item.deleted == '1') $title = $('' + item.name + '').appendTo($item); } $title.attr('title', item.name); @@ -520,12 +520,9 @@ function renderReleaseItem(item, $item) /* Display release date. */ var $date = $info.children('.date'); var releaseDate = $.zui.createDate(item.date); - var today = new Date(); - var labelType = releaseDate.toLocaleDateString() == today.toLocaleDateString() ? 'light' : 'wait'; - if(!$date.length) $date = $('').appendTo($info); + if(!$date.length) $date = $('').appendTo($info); $date.text($.zui.formatDate(releaseDate, 'yyyy-MM-dd')).attr('title', $.zui.formatDate(releaseDate, 'yyyy-MM-dd')).show(); - if(labelType == 'light') $date.css('background-color', 'rgba(210, 50, 61, 0.3)'); /* Display avatars of creator. */ var $user = $info.children('.user'); @@ -549,7 +546,7 @@ function renderProductplanItem(item, $item) { var privs = item.actions; - /* Print name. */ + /* Print name. */ var $title = $item.children('.productplanTitle'); if(!$title.length) { @@ -578,7 +575,7 @@ function renderProductplanItem(item, $item) } } - /* Display deadline of product plan. */ + /* Display date of product plan. */ var $date = $info.children('.date'); var begin = $.zui.createDate(item.begin); var end = $.zui.createDate(item.end); @@ -616,7 +613,7 @@ function renderBuildItem(item, $item) { var privs = item.actions; - /* Print name. */ + /* Print name. */ var $title = $item.children('.title'); if(!$title.length) { @@ -633,14 +630,11 @@ function renderBuildItem(item, $item) ].join('')).appendTo($item); /* Display build date. */ - var $date = $info.children('.date'); - var buildDate = $.zui.createDate(item.date); - var today = new Date(); - var labelType = buildDate.toLocaleDateString() == today.toLocaleDateString() ? 'light' : 'wait'; - if(!$date.length) $date = $('').appendTo($info); + var $date = $info.children('.date'); + var buildDate = $.zui.createDate(item.date); + if(!$date.length) $date = $('').appendTo($info); $date.text($.zui.formatDate(buildDate, 'yyyy-MM-dd')).attr('title', $.zui.formatDate(buildDate, 'yyyy-MM-dd')).show(); - if(labelType == 'light') $date.css('background-color', 'rgba(210, 50, 61, 0.3)'); /* Display avatars of creator. */ var $user = $info.children('.user'); From a182d706286a3e633e9cd34a1860ff6495ced91e Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Tue, 25 Jan 2022 10:11:41 +0800 Subject: [PATCH 12/16] * Display duplicate imported cards. --- module/kanban/model.php | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/module/kanban/model.php b/module/kanban/model.php index 7230d683bc..0f23fd7443 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -1094,7 +1094,7 @@ class kanbanModel extends model ->andWhere('kanban')->eq($kanbanID) ->andWhere('archived')->eq(0) ->andWhere('fromType')->eq($fromType) - ->fetchAll('fromID'); + ->fetchAll('fromID, id'); if(!empty($objectCards)) { @@ -1114,29 +1114,32 @@ class kanbanModel extends model } /* Data for constructing the card. */ - foreach($objectCards as $objectCard) + foreach($objectCards as $objectID => $cardsInfo) { - $object = $objects[$objectCard->fromID]; - $fieldType = $fromType . 'Field'; - - foreach($this->config->kanban->$fieldType as $field) $objectCard->$field = $object->$field; - - if($fromType == 'productplan' or $fromType == 'release') + foreach($cardsInfo as $cardID => $objectCard) { - $objectCard->createdBy = zget($creators, $object->id, ''); - } + $object = $objects[$objectID]; + $fieldType = $fromType . 'Field'; - if($fromType =='execution') - { - if($object->status != 'done' and $object->status != 'closed' and $object->status != 'suspended') + foreach($this->config->kanban->$fieldType as $field) $objectCard->$field = $object->$field; + + if($fromType == 'productplan' or $fromType == 'release') { - $delay = helper::diffDate(helper::today(), $object->end); - if($delay > 0) $objectCard->delay = $delay; + $objectCard->createdBy = zget($creators, $object->id, ''); } - $objectCard->execType = $object->type; - } - $cards[$objectCard->id] = $objectCard; + if($fromType =='execution') + { + if($object->status != 'done' and $object->status != 'closed' and $object->status != 'suspended') + { + $delay = helper::diffDate(helper::today(), $object->end); + if($delay > 0) $objectCard->delay = $delay; + } + $objectCard->execType = $object->type; + } + + $cards[$cardID] = $objectCard; + } } } return $cards; From eae8f49e94d5ef58ab4391ef6bb7c5973b4d0b47 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Tue, 25 Jan 2022 10:14:32 +0800 Subject: [PATCH 13/16] * Modify error. --- module/kanban/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/kanban/model.php b/module/kanban/model.php index 0f23fd7443..ff47837e82 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -1094,7 +1094,7 @@ class kanbanModel extends model ->andWhere('kanban')->eq($kanbanID) ->andWhere('archived')->eq(0) ->andWhere('fromType')->eq($fromType) - ->fetchAll('fromID, id'); + ->fetchGroup('fromID', 'id'); if(!empty($objectCards)) { From f010d79708414cf0482f1b86fba8335d25ac3e41 Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Tue, 25 Jan 2022 10:34:12 +0800 Subject: [PATCH 14/16] * Add color. --- module/kanban/js/view.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/module/kanban/js/view.js b/module/kanban/js/view.js index 285317c107..e0395a688f 100644 --- a/module/kanban/js/view.js +++ b/module/kanban/js/view.js @@ -550,8 +550,8 @@ function renderProductplanItem(item, $item) var $title = $item.children('.productplanTitle'); if(!$title.length) { - if(privs.includes('viewPlan') && item.deleted == '0') $title = $('' + item.title + '').appendTo($item).attr('href', createLink('productplan', 'view', 'productplanID=' + item.fromID)); - if(!privs.includes('viewPlan') || item.deleted == '1') $title = $('' + item.title + '').appendTo($item); + if(privs.includes('viewPlan') && item.deleted == '0') $title = $('' + item.title + '').appendTo($item).attr('href', createLink('productplan', 'view', 'productplanID=' + item.fromID)); + if(!privs.includes('viewPlan') || item.deleted == '1') $title = $('' + item.title + '').appendTo($item); } $title.attr('title', item.title); @@ -580,7 +580,7 @@ function renderProductplanItem(item, $item) var begin = $.zui.createDate(item.begin); var end = $.zui.createDate(item.end); var today = new Date(); - var labelType = 'wait'; + var labelType = end.toLocaleDateString() == today.toLocaleDateString() ? 'danger' : 'wait'; var labelTitle = $.zui.formatDate(begin, 'MM-dd') + ' ' + productplanLang.to + ' ' + $.zui.formatDate(end, 'MM-dd'); if((item.begin == '2030-01-01' || item.end == '2030-01-01')) From 8b0bd45bf6661ae8a32d4bb4c1af5c0d36861725 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Tue, 25 Jan 2022 10:39:17 +0800 Subject: [PATCH 15/16] * Build add delete flag. --- module/kanban/config.php | 2 +- module/kanban/js/view.js | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/module/kanban/config.php b/module/kanban/config.php index 3a08fde5c7..d45192d2b1 100644 --- a/module/kanban/config.php +++ b/module/kanban/config.php @@ -48,7 +48,7 @@ $config->kanban->fromType = array('execution', 'productplan', 'release', $config->kanban->executionField = array('name', 'status', 'end', 'PM', 'type', 'deleted'); $config->kanban->productplanField = array('title', 'status', 'begin', 'end', 'deleted'); $config->kanban->releaseField = array('name', 'status', 'date', 'deleted'); -$config->kanban->buildField = array('name', 'date', 'builder'); +$config->kanban->buildField = array('name', 'date', 'builder', 'deleted'); $config->kanban->default = new stdclass(); $config->kanban->default->story = new stdclass(); diff --git a/module/kanban/js/view.js b/module/kanban/js/view.js index 285317c107..3a770b80b5 100644 --- a/module/kanban/js/view.js +++ b/module/kanban/js/view.js @@ -629,6 +629,12 @@ function renderBuildItem(item, $item) '' ].join('')).appendTo($item); + var $statusBox = $info.children('.buildStatus'); + if(!$statusBox.length && item.deleted == '1') + { + $statusBox = $('' + productplanLang.deleted + '').appendTo($info); + } + /* Display build date. */ var $date = $info.children('.date'); var buildDate = $.zui.createDate(item.date); From a0306d6c6b105f6f4e8fc5be8efa3f436216806f Mon Sep 17 00:00:00 2001 From: xieqiyu Date: Tue, 25 Jan 2022 10:42:03 +0800 Subject: [PATCH 16/16] * Delete space line. --- module/kanban/model.php | 1 - 1 file changed, 1 deletion(-) diff --git a/module/kanban/model.php b/module/kanban/model.php index ff47837e82..31038730d1 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -1036,7 +1036,6 @@ class kanbanModel extends model ->fetchAll(); $actions = array('editCard', 'finishCard', 'activateCard', 'archiveCard', 'deleteCard', 'moveCard', 'setCardColor', 'viewCard', 'sortCard', 'viewExecution', 'viewPlan', 'viewRelease', 'viewBuild'); - $cardGroup = array(); foreach($cellList as $cell) {