diff --git a/module/kanban/control.php b/module/kanban/control.php
index cbb3863c1b..0c701c025b 100644
--- a/module/kanban/control.php
+++ b/module/kanban/control.php
@@ -1987,14 +1987,11 @@ class kanban extends control
if($this->viewType == 'json') return print($lanes);
- if($pageType == 'batch')
- {
- $laneList = array();
- foreach($lanes as $laneID => $laneName) $laneList[] = array('value' => $laneID, 'text' => $laneName);
- return $this->send($laneList);
- }
+ $laneList = array();
+ foreach($lanes as $laneID => $laneName) $laneList[] = array('value' => $laneID, 'text' => $laneName);
- return print(html::select($field, $lanes, '', "class='form-control'"));
+ if($pageType == 'batch') return $this->send($laneList);
+ return print(json_encode(array('items' => $laneList, 'name' => $field)));
}
/**
diff --git a/module/story/js/common.ui.js b/module/story/js/common.ui.js
index a0690468db..0194dd0b52 100644
--- a/module/story/js/common.ui.js
+++ b/module/story/js/common.ui.js
@@ -154,7 +154,7 @@ window.loadProductPlans = function(productID, branch)
new zui.Picker('#planIdBox #plan', {items: items, name: 'plan', defaultValue: planID.toString()});
if(items.length == 0)
{
- $inputGroup.append('');
+ $inputGroup.append('');
$inputGroup.append('');
}
})
diff --git a/module/story/js/create.ui.js b/module/story/js/create.ui.js
index bf3eb8ec29..26084b97bf 100644
--- a/module/story/js/create.ui.js
+++ b/module/story/js/create.ui.js
@@ -5,19 +5,23 @@ window.toggleReviewer = function(obj)
const $this = $(obj);
const isChecked = $this.prop('checked');
- $('#reviewer').attr('disabled', isChecked ? 'disabled' : null).trigger('chosen:updated');
+ $reviewer = $('#reviewer').zui('picker');
+ options = $reviewer.options;
if(isChecked)
{
+ options.disabled = true;
+ $reviewer.render(options);
$('#reviewerBox').closest('.form-row').addClass('hidden');
$('#needNotReview').val(1);
}
else
{
+ options.disabled = false;
+ $reviewer.render(options);
$('#reviewerBox').closest('.form-row').removeClass('hidden');
$('#needNotReview').val(0);
}
}
-toggleReviewer($('#needNotReview[type=checkbox]'));
window.toggleFeedback = function(obj)
{
@@ -30,7 +34,7 @@ window.toggleFeedback = function(obj)
$(document).on('change', '#module', function(){loadURS();})
-if($("form select[id^='branches']").length == $('.switchBranch #branchBox option').length)
+if(branchCount <= 1)
{
$('.switchBranch .addNewLine').css('pointer-events', 'none')
$('.switchBranch .addNewLine').addClass('disabled')
@@ -46,9 +50,10 @@ window.loadProduct = function(e)
window.loadBranchRelation = function(e)
{
const $this = $(e.target);
- const branch = $this.val();
- const branchIndex = $this.data('index');
- const productID = $('#product').val();
+ const $picker = $this.zui('picker');
+ const branch = $picker.$.value;
+ const branchIndex = $picker.options.index;
+ const productID = $('[name=product]').val();
$.ajaxSettings.async = false;
loadModuleForTwins(productID, branch, branchIndex)
@@ -60,55 +65,49 @@ window.loadBranchRelation = function(e)
window.addBranchesBox = function(e)
{
- const productID = $('#product').val();
- const $formRow = $(e.target).closest('.form-row');
+ const productID = $('#product').zui('picker').$.value;
+ const $formRow = $(e.target).closest('.form-row');
+ const $branchPicker = $('.switchBranch #branchBox .picker-box').zui('picker');
+ const $modulePicker = $('.switchBranch #moduleIdBox .picker-box').zui('picker');
+ const $planPicker = $('.switchBranch #planIdBox .picker-box').zui('picker');
$('#storyNoticeBranch').removeClass('hidden');
- if($("form select[id^='branches']").length == $('.switchBranch #branchBox option').length) return false;
+ if($("form [name^='branches']").length == $branchPicker.options.items.length) return false;
var selectedVal = [];
- $("form select[id^='branches']").each(function()
+ $("form [name^='branches']").each(function()
{
var selectedProduct = $(this).val();
if(!selectedVal.includes(selectedProduct)) selectedVal.push(selectedProduct);
});
var branch = 0;
- $('.switchBranch [id^=branches] option').each(function()
+ $branchPicker.options.items.forEach(function(item)
{
- if(!selectedVal.includes($(this).val()))
+ if(!selectedVal.includes(item.value))
{
- branch = $(this).val();
+ branch = item.value;
return false;
}
});
var $newLine = $('#addBranchesBox').clone();
+ $formRow.after($newLine);
$newLine.addClass('newLine').removeClass('hidden').addClass('addBranchesBox' + itemIndex).removeAttr('id');
- $newLine.find('[id^=branches]').attr('name', 'branches[' + itemIndex + ']').attr('id', 'branches[' + itemIndex + ']').attr('data-index', itemIndex).on('change', loadBranchRelation);
- $newLine.find('[id^=modules]').attr('name', 'modules[' + itemIndex + ']').attr('id', 'modules[' + itemIndex + ']');
- $newLine.find('[id^=plans]').attr('name', 'plans[' + itemIndex + ']').attr('id', 'plans[' + itemIndex + ']');
+ $newLine.find('#branches').addClass('picker-box').attr('id', 'branches_' + itemIndex).attr('data-on', 'change').attr('data-call', 'loadBranchRelation').attr('data-params', 'event').picker($.extend({}, $branchPicker.options, {name: "branches[" + itemIndex + "]", index: itemIndex, afterRender: function(){disableSelectedBranches()}}));
+ $newLine.find('#modules').addClass('picker-box').attr('id', 'modules_' + itemIndex).picker($.extend({}, $modulePicker.options, {name: "modules[" + itemIndex + "]"}));
+ $newLine.find('#plans').addClass('picker-box').attr('id', 'plans_' + itemIndex).picker($.extend({}, $planPicker.options, {name: "plans[" + itemIndex + "]"}));
$newLine.find('.addNewLine').on('click', addBranchesBox);
$newLine.find('.removeNewLine').on('click', deleteBranchesBox);
- //$('#branches_i__chosen').remove();
- //$('#branches' + itemIndex).chosen();
- //$('#modules_i__chosen').remove();
- //$('#modules' + itemIndex).chosen();
- //$('#plans_i__chosen').remove();
- //$('#plans' + itemIndex).chosen();
- //$('.addBranchesBox' + itemIndex + ' #planIdBox').css('flex', '0 0 ' + gap + 'px');
- $formRow.after($newLine);
$.ajaxSettings.async = false;
loadModuleForTwins(productID, branch, itemIndex)
loadPlanForTwins(productID, branch, itemIndex)
$.ajaxSettings.async = true;
- disableSelectedBranches();
-
- if($("form select[id^='branches']").length == $('.switchBranch #branchBox option').length)
+ if($("form [id^='branches']").length == $branchPicker.options.items.length)
{
$('.addNewLine').css('pointer-events', 'none')
$('.addNewLine').addClass('disabled')
@@ -125,7 +124,7 @@ window.deleteBranchesBox = function(e)
$('.addNewLine').css('pointer-events', 'auto')
$('.addNewLine').removeClass('disabled')
- if($('form select[name^="branches"]').length < 2) $('#storyNoticeBranch').addClass('hidden');
+ if($('form [name^="branches"]').length < 2) $('#storyNoticeBranch').addClass('hidden');
};
window.loadProductPlans = function(productID, branch)
@@ -133,15 +132,24 @@ window.loadProductPlans = function(productID, branch)
if(typeof(branch) == 'undefined') branch = 0;
if(!branch) branch = 0;
- var param = config.currentMethod == 'edit' ? 'skipParent|forStory' : 'skipParent';
- var expired = config.currentMethod == 'create' ? 'unexpired' : '';
- var planLink = $.createLink('product', 'ajaxGetPlans', 'productID=' + productID + '&branch=' + branch + '&planID=' + $('#plan').val() + '&fieldID=&needCreate=true&expired='+ expired +'¶m=skipParent,forStory,' + config.currentMethod);
- var $planIdBox = $('#planIdBox');
+ let planID = $('[name=plan]').val();
+ let param = config.currentMethod == 'edit' ? 'skipParent|forStory' : 'skipParent';
+ let expired = config.currentMethod == 'create' ? 'unexpired' : '';
+ let planLink = $.createLink('product', 'ajaxGetPlans', 'productID=' + productID + '&branch=' + branch + '&planID=' + planID + '&fieldID=&needCreate=true&expired='+ expired +'¶m=skipParent,forStory,' + config.currentMethod);
+ let $planIdBox = $('#planIdBox');
- $planIdBox.load(planLink, function()
+ $.get(planLink, function(data)
{
- //$planIdBox.find('#plan').chosen();
- });
+ let items = JSON.parse(data);
+ let $inputGroup = $planIdBox.closest('.input-group');
+ $inputGroup.html("")
+ new zui.Picker('#planIdBox #plan', {items: items, name: 'plan', defaultValue: planID.toString()});
+ if(items.length == 0)
+ {
+ $inputGroup.append('');
+ $inputGroup.append('');
+ }
+ })
};
window.setLane = function(e)
@@ -150,11 +158,7 @@ window.setLane = function(e)
const laneLink = $.createLink('kanban', 'ajaxGetLanes', 'regionID=' + regionID + '&type=story&field=lane');
$.get(laneLink, function(lane)
{
- if(!lane) lane = "";
- $('#lane').replaceWith(lane);
- $('#lane' + "_chosen").remove();
- $('#lane').next('.picker').remove();
- $('#lane').chosen();
+ $('#myPicker').picker(JSON.parse(lane));
});
};
@@ -162,7 +166,7 @@ function loadModuleForTwins(productID, branch, branchIndex)
{
/* Load module */
var currentModule = 0;
- var moduleLink = $.createLink('tree', 'ajaxGetOptionMenu', 'productID=' + productID + '&viewtype=story&branch=' + branch + '&rootModuleID=0&returnType=html&fieldID=' + branchIndex + '&needManage=false&extra=nodeleted¤tModuleID=' + currentModule);
+ var moduleLink = $.createLink('tree', 'ajaxGetOptionMenu', 'productID=' + productID + '&viewtype=story&branch=' + branch + '&rootModuleID=0&returnType=html&fieldID=' + branchIndex + '&needManage=false&extra=nodeleted¤tModuleID=' + currentModule);
if(branchIndex > 0)
{
var $moduleIdBox = $('.addBranchesBox' + branchIndex + ' #moduleIdBox');
@@ -172,10 +176,7 @@ function loadModuleForTwins(productID, branch, branchIndex)
var $moduleIdBox = $('.switchBranch #moduleIdBox');
}
- $moduleIdBox.load(moduleLink, function()
- {
- //$moduleIdBox.find('[id^=#modules]').chosen();
- });
+ $.get(moduleLink, function(data){$moduleIdBox.find('.picker-box').picker(JSON.parse(data));});
}
function loadPlanForTwins(productID, branch, branchIndex)
@@ -191,32 +192,37 @@ function loadPlanForTwins(productID, branch, branchIndex)
{
var $planIdBox = $('.switchBranch #planIdBox');
}
- $planIdBox.load(planLink, function()
- {
- //$planIdBox.find('[id^=plans]').chosen();
- });
+
+ $.get(planLink, function(data){$planIdBox.find('.picker-box').picker(JSON.parse(data));});
}
function disableSelectedBranches()
{
- $("form select[id^='branches'] option[disabled='disabled']").removeAttr('disabled');
-
- var selectedVal = [];
- $("form select[id^='branches']").each(function()
+ let selectedVal = [];
+ let $pickers = [];
+ $("form [name^='branches']").each(function()
{
- var selectedBranch = $(this).val();
- if(!selectedVal.includes(selectedBranch)) selectedVal.push(selectedBranch);
+ let $picker = $(this).zui('picker');
+ let value = $picker.$.value;
+
+ $pickers.push($picker);
+ if(!selectedVal.includes(value)) selectedVal.push(value);
})
- $("form select[id^='branches']").each(function()
+ $pickers.forEach(function($picker)
{
- var selectedBranch = $(this).val();
- $(this).find('option').each(function()
+ let value = $picker.$.value;
+ let options = $picker.options;
+ let items = [];
+ options.items.forEach(function(item)
{
- var optionVal = $(this).attr('value');
- if(optionVal != selectedBranch && selectedVal.includes(optionVal)) $(this).attr('disabled', 'disabled');
+ item = $.extend({}, item, {disabled: false});
+ if(value !== item.value && selectedVal.includes(item.value)) item = $.extend({}, item, {disabled: true});
+ items.push(item);
})
- })
+ options.items = items;
+ delete options.afterRender;
- //$("form select[id^=branches]").trigger('chosen:updated');
+ $picker.render(options);
+ });
}
diff --git a/module/story/ui/create.html.php b/module/story/ui/create.html.php
index 9e9551b309..239f5738e7 100644
--- a/module/story/ui/create.html.php
+++ b/module/story/ui/create.html.php
@@ -18,6 +18,7 @@ array_shift($params);
jsVar('createParams', http_build_query($params));
jsVar('storyType', $type);
jsVar('feedbackSource', $config->story->feedbackSource);
+jsVar('branchCount', isset($fields['branches']['options']) ? count($fields['branches']['options']) : 0);
$showFields = $config->story->custom->createFields;
$fnGenerateCustomizedFields = function() use ($showFields, $customFields)
@@ -59,8 +60,8 @@ formPanel
set::width('1/2'),
inputGroup
(
- select(set::name('product'), set::value($fields['product']['default']), set::items($fields['product']['options'])),
- isset($fields['branch']) && $type != 'story' ? select(set::name('branch'), set::items($fields['branch']['options']), set::value($fields['branch']['default'])) : null,
+ picker(setID('product'), set::name('product'), set::value($fields['product']['default']), set::items($fields['product']['options'])),
+ isset($fields['branch']) && $type != 'story' ? picker(setID('branch'), set::name('branch'), set::items($fields['branch']['options']), set::value($fields['branch']['default'])) : null,
),
set::required(true),
),
@@ -80,10 +81,10 @@ formPanel
span
(
set::id('moduleIdBox'),
- picker(set::name('module'), set::items($fields['module']['options']), set::value($fields['module']['default']), set::required(true)),
+ picker(setID('module'), set::name('module'), set::items($fields['module']['options']), set::value($fields['module']['default']), set::required(true)),
),
- empty($fields['module']['options']) ? btn(set::url($this->createLink('tree', 'browse', "rootID=$productID&view=story¤tModuleID=0&branch=$branch")), setClass('primary'), set('data-toggle', 'modal'), $lang->tree->manage) : null,
- empty($fields['module']['options']) ? btn(set('data-on', 'click'), set('data-call', 'loadProductModules'), set('data-params', $productID), setClass('refresh'), icon('refresh')) : null,
+ count($fields['module']['options']) == 1 ? btn(set::url($this->createLink('tree', 'browse', "rootID=$productID&view=story¤tModuleID=0&branch=$branch")), setClass('primary'), set('data-toggle', 'modal'), $lang->tree->manage) : null,
+ count($fields['module']['options']) == 1 ? btn(set('data-on', 'click'), set('data-call', 'loadProductModules'), set('data-params', $productID), setClass('refresh'), icon('refresh')) : null,
)
),
),
@@ -99,6 +100,7 @@ formPanel
set::id('branchBox'),
picker
(
+ setID('branches_0'),
set::name('branches[0]'),
set::items($fields['branches']['options']),
set::value($fields['branches']['default']),
@@ -116,7 +118,7 @@ formPanel
inputGroup
(
set::id('moduleIdBox'),
- picker(set::name('modules[0]'), set::items($fields['modules']['options']), set::value($fields['modules']['default']), set::required(true))
+ picker(setID('modules_0'), set::name('modules[0]'), set::items($fields['modules']['options']), set::value($fields['modules']['default']), set::required(true))
),
),
formGroup
@@ -125,7 +127,7 @@ formPanel
inputGroup
(
set::id('planIdBox'),
- picker(set::name('plans[0]'), set::items($fields['plans']['options']), set::value($fields['plans']['default']))
+ picker(setID('plans_0'), set::name('plans[0]'), set::items($fields['plans']['options']), set::value($fields['plans']['default']))
),
),
count($branches) > 1 ? formGroup
@@ -156,7 +158,7 @@ formPanel
span
(
set::id('planIdBox'),
- picker(set::name('plan'), set::items($fields['plan']['options']), set::value($fields['plan']['default'])),
+ picker(setID('plan'), set::name('plan'), set::items($fields['plan']['options']), set::value($fields['plan']['default'])),
),
empty($fields['plan']['options']) ? btn(set::url($this->createLink('productplan', 'create', "productID=$productID&branch=$branch")), set('data-toggle', 'modal'), set::title($lang->productplan->create), icon('plus')) : null,
empty($fields['plan']['options']) ? btn(setClass('refresh'), set('data-toggle', 'modal'), set::title($lang->refresh), set('data-on', 'click'), set('data-call', 'loadProductPlans'), set('data-params', $productID), icon('refresh')) : null,
@@ -221,14 +223,14 @@ formPanel
inputGroup
(
set::id('assignedToBox'),
- picker(set::name('assignedTo'), set::items($fields['assignedTo']['options']), set::value($fields['assignedTo']['value']))
+ picker(setID('assignedTo'), set::name('assignedTo'), set::items($fields['assignedTo']['options']), set::value($fields['assignedTo']['value']))
)
),
formGroup
(
set::width('1/4'),
set::label($lang->story->source),
- picker(set::name('source'), set::items($fields['source']['options']), set::value($fields['source']['value']))
+ picker(setID('source'), set::name('source'), set::items($fields['source']['options']), set::value($fields['source']['value']))
),
formGroup
(
@@ -237,23 +239,28 @@ formPanel
input(set::name('sourceNote'), set::value($fields['sourceNote']['value']))
),
) : null,
- formGroup
+ formRow
(
- set::width('1/2'),
- set::label($lang->story->reviewedBy),
- set::required($forceReview),
- inputGroup
+ set::hidden($forceReview && $needReview),
+ formGroup
(
- set::id('reviewerBox'),
- picker
+ set::width('1/2'),
+ set::label($lang->story->reviewedBy),
+ set::required($forceReview),
+ inputGroup
(
- set::name('reviewer[]'),
- set::multiple(true),
- set::items($fields['reviewer']['options']),
- set::value($fields['reviewer']['default']),
+ set::id('reviewerBox'),
+ picker
+ (
+ setID('reviewer'),
+ set::name('reviewer[]'),
+ set::multiple(true),
+ set::items($fields['reviewer']['options']),
+ set::value($fields['reviewer']['default']),
+ ),
),
+ $forceReview ? null : formHidden('needNotReview', 1),
),
- $forceReview ? null : formHidden('needNotReview', 1),
),
isset($fields['URS']) ? formRow
(
@@ -263,7 +270,7 @@ formPanel
set::label($lang->story->requirement),
inputGroup
(
- span(setClass('URSBox'), picker(set::name('URS[]'), set::items($fields['URS']['options']), set::value($fields['URS']['value']))),
+ span(setClass('URSBox'), picker(setID('URS'), set::name('URS[]'), set::items($fields['URS']['options']), set::value($fields['URS']['value']))),
btn(set('data-on', 'click'), set('data-call', 'loadURS'), set('data-params', 'allURS'), $lang->story->loadAllStories),
)
),
@@ -293,6 +300,7 @@ formPanel
formGroup
(
set::width('1/2'),
+ setID($fields['region']['title']),
set::label($fields['region']['title']),
set::name('region'),
set::items($fields['region']['options']),
@@ -324,7 +332,7 @@ formPanel
inputGroup
(
$lang->story->category,
- picker(set::name('category'), set::items($fields['category']['options']), set::value($fields['category']['default'])),
+ picker(setID('category'), set::name('category'), set::items($fields['category']['options']), set::value($fields['category']['default'])),
$lang->story->pri,
priPicker(set::name('pri'), set::items($fields['pri']['options']), set::value($fields['pri']['default'])),
$lang->story->estimateAB,
@@ -357,10 +365,14 @@ formPanel
formGroup
(
set::label($lang->story->mailto),
- set::name('mailto[]'),
- set::control(array('type' => 'picker', 'multiple' => true)),
- set::items($fields['mailto']['options']),
- set::value($fields['mailto']['default']),
+ picker
+ (
+ setID('mailto'),
+ set::name('mailto[]'),
+ set::items($fields['mailto']['options']),
+ set::value($fields['mailto']['default']),
+ set::multiple(true),
+ ),
),
formGroup
(
@@ -383,12 +395,7 @@ isset($fields['branches']) && $type == 'story' ? formRow
inputGroup
(
set::id('branchBox'),
- picker
- (
- set::name('branches[%i%]'),
- set::items($fields['branches']['options']),
- set::value($fields['branches']['default']),
- )
+ div(setID('branches'), setClass('form-group-wrapper')),
),
),
formGroup
@@ -398,7 +405,7 @@ isset($fields['branches']) && $type == 'story' ? formRow
inputGroup
(
set::id('moduleIdBox'),
- picker(set::name('modules[%i%]'), set::items($fields['modules']['options']), set::value($fields['modules']['default']))
+ div(setID('modules'), setClass('form-group-wrapper')),
),
),
formGroup
@@ -407,7 +414,7 @@ isset($fields['branches']) && $type == 'story' ? formRow
inputGroup
(
set::id('planIdBox'),
- picker(set::name('plans[%i%]'), set::items($fields['plans']['options']), set::value($fields['plans']['default']))
+ div(setID('plans'), setClass('form-group-wrapper')),
),
),
formGroup
diff --git a/module/story/ui/edit.html.php b/module/story/ui/edit.html.php
index 2fd3c20549..cb74373153 100644
--- a/module/story/ui/edit.html.php
+++ b/module/story/ui/edit.html.php
@@ -251,7 +251,7 @@ detailBody
set::id('planIdBox'),
picker(setID('plan'), set::name($multiplePlan ? 'plan[]' : 'plan'), set::items($plans), set::value($story->plan), set::multiple($multiplePlan)),
),
- empty($plans) ? btn(set::url($this->createLink('productplan', 'create', "productID={$story->product}&branch={$story->branch}")), set('data-toggle', 'modal'), icon('cog')) : null,
+ empty($plans) ? btn(set::url($this->createLink('productplan', 'create', "productID={$story->product}&branch={$story->branch}")), set('data-toggle', 'modal'), icon('plus')) : null,
empty($plans) ? btn(set('data-on', 'click'), set('data-call', 'loadProductPlans'), set('data-params', $story->product), setClass('refresh'), icon('refresh')) : null,
)
),
diff --git a/module/tree/control.php b/module/tree/control.php
index 431ca9caea..6c217b4611 100644
--- a/module/tree/control.php
+++ b/module/tree/control.php
@@ -551,7 +551,7 @@ class tree extends control
}
else
{
- $optionMenu = $this->tree->getOptionMenu($rootID, $viewType, $rootModuleID, $branch, $extra);
+ $optionMenu = $this->tree->getOptionMenu($rootID, $viewType, $rootModuleID, (int)$branch, $extra);
}
if(strpos($extra, 'excludeModuleID') !== false)
diff --git a/module/tree/model.php b/module/tree/model.php
index e971012654..94ba35a8e2 100644
--- a/module/tree/model.php
+++ b/module/tree/model.php
@@ -134,9 +134,9 @@ class treeModel extends model
* @param string $grade
* @param string $divide /|>
* @access public
- * @return void
+ * @return array
*/
- public function getOptionMenu($rootID, $type = 'story', $startModule = 0, $branch = 0, $param = 'nodeleted', $grade = 'all', $divide = '/')
+ public function getOptionMenu(int $rootID, string $type = 'story', int $startModule = 0, int|array $branch = 0, string $param = 'nodeleted', string $grade = 'all', string $divide = '/'): array
{
if(empty($branch) and !is_array($branch)) $branch = 0;
if(commonModel::isTutorialMode())