diff --git a/module/product/control.php b/module/product/control.php index 4517c4b093..8002552377 100755 --- a/module/product/control.php +++ b/module/product/control.php @@ -1130,4 +1130,20 @@ class product extends control $this->session->set('product', $productID, $this->app->tab); return $this->send(array('result' => 'success', 'productID' => $this->session->product)); } + + /** + * Delete a prodcut line. + * + * @param int $lineID + * @access public + * @return void + */ + public function ajaxDeleteLine(int $lineID) + { + $this->dao->update(TABLE_MODULE)->set('deleted')->eq(1)->where('id')->eq($lineID)->exec(); + $this->dao->update(TABLE_PRODUCT)->set('line')->eq('0')->where('line')->eq($lineID)->exec(); + + $link = inlink('manageLine'); + return $this->send(array('result' => 'success', 'callback' => "loadModal(\"$link\", 'manageLineModal');")); + } } diff --git a/module/product/css/manageline.ui.css b/module/product/css/manageline.ui.css new file mode 100644 index 0000000000..32a7824c0a --- /dev/null +++ b/module/product/css/manageline.ui.css @@ -0,0 +1,4 @@ +#manageLineModal .lineTree {overflow: hidden;} +#manageLineModal .lineTree .line-item > span {overflow: hidden; white-space: nowrap; text-overflow: clip;} +#manageLineModal .form-group.required {position: relative;} +#manageLineModal .form-group.required:after {content: '*'; color: rgba(var(--color-danger-500-rgb),var(--tw-text-opacity)); position: absolute; top: 0.5rem; right: -0.875rem;} diff --git a/module/product/js/manageline.ui.js b/module/product/js/manageline.ui.js index 23a952331b..9df2e2f259 100644 --- a/module/product/js/manageline.ui.js +++ b/module/product/js/manageline.ui.js @@ -1,4 +1,34 @@ -window.onClickPanel = function(e) +/** + * Add new line for link product. + * + * @param obj $obj + * @access public + * @return void + */ +function addNewLine(e) { - e.stopPropagation(); + const newLine = $(e.target).closest('.form-row').clone(); + + newLine.find('.addLine').on('click', addNewLine); + newLine.find('.removeLine').on('click', removeLine); + newLine.find('input[name^=modules]').val('').attr('name', 'modules[' + index + ']').attr('id', 'modules[' + index + ']'); + newLine.find('select[name^=programs]').val('').attr('name', 'programs[' + index + ']').attr('id', 'programs[' + index + ']'); + $(e.target).closest('.form-row').after(newLine); + + index ++; +} + +/** + * Remove line for link product. + * + * @param obj e + * @access public + * @return void + */ +function removeLine(e) +{ + if($('.line-row-add').length == 1) return; + + const obj = e.target; + $(obj).closest('.form-row').remove(); } diff --git a/module/product/lang/de.php b/module/product/lang/de.php index 62a4358291..240b4b7f2e 100644 --- a/module/product/lang/de.php +++ b/module/product/lang/de.php @@ -103,6 +103,7 @@ $lang->product->programEmpty = 'Program should not be empty!'; $lang->product->nameIsDuplicate = "『%s』 product line already exists, please reset!"; $lang->product->nameIsDuplicated = "Product Line『%s』 exists. Go to Admin->System->Data->Recycle Bin to restore it, if you are sure it is deleted."; $lang->product->reviewStory = 'You are not a reviewer for needs "%s" , and cannot review. This operation has been filtered'; +$lang->product->confirmDeleteLine = "Do you want to delete this product line?"; $lang->product->id = 'ID'; $lang->product->program = "Program"; diff --git a/module/product/lang/en.php b/module/product/lang/en.php index edd3d89af7..97c453ac52 100644 --- a/module/product/lang/en.php +++ b/module/product/lang/en.php @@ -103,6 +103,7 @@ $lang->product->programEmpty = 'Program should not be empty!'; $lang->product->nameIsDuplicate = "『%s』 product line already exists, please reset!"; $lang->product->nameIsDuplicated = "Product Line『%s』 exists. Go to Admin->System->Data->Recycle Bin to restore it, if you are sure it is deleted."; $lang->product->reviewStory = 'You are not a reviewer for needs "%s" , and cannot review. This operation has been filtered'; +$lang->product->confirmDeleteLine = "Do you want to delete this product line?"; $lang->product->id = 'ID'; $lang->product->program = "Program"; diff --git a/module/product/lang/fr.php b/module/product/lang/fr.php index 693d7f62ac..8616ee1ae0 100644 --- a/module/product/lang/fr.php +++ b/module/product/lang/fr.php @@ -103,6 +103,7 @@ $lang->product->programEmpty = 'Program should not be empty!'; $lang->product->nameIsDuplicate = "『%s』 product line already exists, please reset!"; $lang->product->nameIsDuplicated = "Product Line『%s』 exists. Go to Admin->System->Data->Recycle Bin to restore it, if you are sure it is deleted."; $lang->product->reviewStory = 'You are not a reviewer for needs "%s" , and cannot review. This operation has been filtered'; +$lang->product->confirmDeleteLine = "Do you want to delete this product line?"; $lang->product->id = 'ID'; $lang->product->program = "Program"; diff --git a/module/product/lang/zh-cn.php b/module/product/lang/zh-cn.php index 998a26c9f6..8159a7dbe2 100644 --- a/module/product/lang/zh-cn.php +++ b/module/product/lang/zh-cn.php @@ -103,6 +103,7 @@ $lang->product->programEmpty = '项目集不能为空'; $lang->product->nameIsDuplicate = "『%s』产品线已经存在,请重新设置!"; $lang->product->nameIsDuplicated = "产品线已经有『%s』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。"; $lang->product->reviewStory = '您不是研发需求 "%s" 的评审人,无法评审,本次操作已被过滤。'; +$lang->product->confirmDeleteLine = "您确定删除该产品线吗?"; $lang->product->id = '编号'; $lang->product->program = "所属项目集"; diff --git a/module/product/model.php b/module/product/model.php index f58e23bfe9..cc110e2755 100755 --- a/module/product/model.php +++ b/module/product/model.php @@ -734,7 +734,7 @@ class productModel extends model } if(dao::isError()) return array('result' => 'fail', 'message' => dao::getError()); - return array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true); + return array('result' => 'success', 'message' => $this->lang->saveSuccess, 'closeModal' => true, 'load' => true); } /** diff --git a/module/product/ui/all.html.php b/module/product/ui/all.html.php index 5b2fde8967..592a71762d 100644 --- a/module/product/ui/all.html.php +++ b/module/product/ui/all.html.php @@ -125,6 +125,7 @@ toolbar set::icon('edit'), set('data-toggle', 'modal'), set('data-url', createLink('product', 'manageLine', $browseType)), + set('data-id', 'manageLineModal'), $lang->product->editLine ) : null, item(set(array diff --git a/module/product/ui/manageline.html.php b/module/product/ui/manageline.html.php index 09b486d389..99b4c3d307 100644 --- a/module/product/ui/manageline.html.php +++ b/module/product/ui/manageline.html.php @@ -1,111 +1,127 @@ + * @package product + * @link https://www.zentao.net + */ namespace zin; -$lineMenuList = array(); -$formRowList = array(); +$lineMenuList = null; +$formRowList = null; foreach($lines as $line) { $lineMenuList[] = div - ( - setClass('flex items-center'), - $line->name, - div ( - setClass('self-end ml-auto'), - btn(set::size('sm'), setClass('ghost'), icon('move')), + set::class('ml-4 line-item flex items-center'), + span + ( + $line->name + ), btn ( icon('trash'), set::size('sm'), - setClass('ghost'), - set::url(createLink('tree', 'delete', array('rootID' => 0, 'moduleID' => $line->id))) + setClass('ghost text-gray ajax-submit'), + set::url(createLink('product', 'ajaxDeleteLine', "lineID={$line->id}")), + set('data-confirm', $lang->product->confirmDeleteLine), ) - ) - ); + ); $formRowList[] = formRow - ( - set::width('full'), - formGroup ( - set::width('2/5'), - input + formGroup ( - set::name("modules[id{$line->id}]"), - set::value($line->name) - ) - ), - formGroup - ( - set::width('2/5'), - setClass('ml-4'), - $this->config->systemMode == 'ALM' ? select + set::width('1/3'), + set::name("modules[id$line->id]"), + set::value($line->name), + ), + $config->systemMode == 'ALM' ? formGroup ( - set::name("programs[id{$line->id}]"), + set::width('1/3'), + set::class('ml-4 required'), + set::name("programs[id$line->id]"), + set::items($programs), set::value($line->root), - set::items($programs) - ) : '' - ), - formGroup - ( - set::width('1/5'), - setClass('ml-4') - ) - ); + ) : null, + ); } -/* Attach input group rows. */ -for($i = 0; $i <= 5; $i++) +for($i = 0; $i <= 5; $i ++) { $formRowList[] = formRow - ( - set::width('full'), - formGroup(set::width('2/5'), input(set::name('modules[]'))), - formGroup(set::width('2/5'), setClass('ml-4'), $this->config->systemMode == 'ALM' ? select(set::name('programs[]'), set::items($programs)) : ''), - formGroup(set::width('1/5'), setClass('ml-4'), btn(icon('plus')), btn(icon('close'))) - ); + ( + set::class('line-row-add'), + formGroup + ( + set::width('1/3'), + set::name("modules[$i]"), + ), + $config->systemMode == 'ALM' ? formGroup + ( + set::width('1/3'), + set::class('ml-4 required'), + set::name("programs[$i]"), + set::items($programs), + ) : null, + formGroup + ( + setClass('ml-2 pl-2 flex self-center'), + btn + ( + setClass('btn btn-link text-gray addLine'), + icon('plus'), + on::click('addNewLine') + ), + btn + ( + setClass('btn btn-link text-gray removeLine'), + icon('trash'), + on::click('removeLine'), + ), + ) + ); } -div( - on::click('window.onClickPanel'), - setClass('w-full flex'), +jsVar('+index', $i); - /* Product line list. */ - cell +to::header( + span ( - setClass('w-2/6'), - panel - ( - set::title($lang->product->line), - menu($lineMenuList) - ) + set::class('article-h2 w-1/4'), + $lang->product->line, ), - /* Manage product line. */ + span + ( + set::class('article-h2'), + $lang->product->manageLine, + ), +); + +div +( + set::class('flex'), cell ( - setClass('w-4/6 pl-6'), - panel + set::width('1/3'), + set::class('lineTree mr-1'), + $lineMenuList + ), + cell + ( + set::width('2/3'), + form ( - set::title($lang->product->manageLine), - form( - formRow - ( - set::width('full'), - formGroup - ( - set::width('2/5'), - $lang->product->lineName - ), - formGroup - ( - set::width('2/5'), - $this->config->systemMode == 'ALM' ? $lang->product->program : '' - ) - ), - $formRowList - ) + set::submitBtnText($lang->save), + set::actionsClass('justify-start'), + set::class('border-b-0'), + $formRowList ) ) ); +/* ====== Render page ====== */ render(); diff --git a/module/product/zen.php b/module/product/zen.php index 7a014e2d61..07481f07c5 100644 --- a/module/product/zen.php +++ b/module/product/zen.php @@ -651,7 +651,7 @@ class productZen extends product if(empty($name)) continue; if($this->config->systemMode == 'ALM' and empty($data->programs[$id])) { - dao::$errors[] = $this->lang->product->programEmpty; + dao::$errors["programs[{$id}]"] = $this->lang->product->programEmpty; return false; } @@ -659,7 +659,7 @@ class productZen extends product if(!isset($lines[$programID])) $lines[$programID] = array(); if(in_array($name, $lines[$programID])) { - dao::$errors[] = sprintf($this->lang->product->nameIsDuplicate, $name); + dao::$errors["modules[$id]"] = sprintf($this->lang->product->nameIsDuplicate, $name); return false; } $lines[$programID][$id] = $name;