diff --git a/Makefile b/Makefile index c7bc6e9d02..89ba630a1b 100644 --- a/Makefile +++ b/Makefile @@ -137,6 +137,7 @@ package: for module in `ls zentaopms/module/`; do if [ ! -d "zentaopms/module/$$module/ext" ]; then mkdir zentaopms/module/$$module/ext; fi done find zentaopms/ -name ext |xargs chmod -R 777 mkdir zentaopms/tools; cp tools/cn2tw.php zentaopms/tools; cd zentaopms/tools; php cn2tw.php + rm -r zentaopms/module/misc/ext rm -rf zentaopms/tools pms: make common diff --git a/module/block/view/scrumoverviewblock.html.php b/module/block/view/scrumoverviewblock.html.php index a8d3323a1a..d5ac5ada73 100644 --- a/module/block/view/scrumoverviewblock.html.php +++ b/module/block/view/scrumoverviewblock.html.php @@ -48,7 +48,7 @@
block->spent;?>
¥0
- block->budget;?> ¥budget;?> + block->budget;?> ¥budget . ' ' . zget($lang->program->unitList, $totalData[$projectID]->budgetUnit);?>
diff --git a/module/common/lang/de.php b/module/common/lang/de.php index 1c6fdecce8..e765769ae0 100644 --- a/module/common/lang/de.php +++ b/module/common/lang/de.php @@ -33,7 +33,7 @@ $lang->unfoldMenu = 'Unfold Menu'; $lang->collapseMenu = 'Collapse Menu'; $lang->runInfo = "
Time %s MS, Memory %s KB, Query %s.
"; $lang->agreement = "I have read and agreed to the terms and conditions of Z PUBLIC LICENSE 1.2 . Without authorization, I should not remove, hide or cover any logos/links of ZenTao."; -$lang->designedByAIUX = "Designed by AIUX"; +$lang->designedByAIUX = " AIUX"; $lang->reset = 'Zurücksetzen'; $lang->cancel = 'Abbrechen'; diff --git a/module/common/lang/en.php b/module/common/lang/en.php index 52ca9a94ba..adb72d4aec 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -33,7 +33,7 @@ $lang->unfoldMenu = 'Unfold Menu'; $lang->collapseMenu = 'Collapse Menu'; $lang->runInfo = "
Time %s MS, Memory %s KB, Query %s.
"; $lang->agreement = "I have read and agreed to the terms and conditions of Z PUBLIC LICENSE 1.2 . Without authorization, I should not remove, hide or cover any logos/links of ZenTao."; -$lang->designedByAIUX = "Designed by AIUX"; +$lang->designedByAIUX = " AIUX"; $lang->reset = 'Reset'; $lang->cancel = 'Cancel'; diff --git a/module/common/lang/fr.php b/module/common/lang/fr.php index ccbabae896..973b107b64 100644 --- a/module/common/lang/fr.php +++ b/module/common/lang/fr.php @@ -33,7 +33,7 @@ $lang->unfoldMenu = 'Unfold Menu'; $lang->collapseMenu = 'Collapse Menu'; $lang->runInfo = "
Time %s MS, Memory %s KB, Query %s.
"; $lang->agreement = "J'ai lu et j'accepte les termes et conditions de la Z PUBLIC LICENSE 1.2 . Sans autorisation, je ne dois pas supprimer, masquer ou couvrir les logos / liens de ZenTao."; -$lang->designedByAIUX = "Designed by AIUX"; +$lang->designedByAIUX = " AIUX"; $lang->reset = 'Réinitialiser'; $lang->cancel = 'Annuler'; diff --git a/module/common/lang/vi.php b/module/common/lang/vi.php index 66d830d45c..c3fa553640 100644 --- a/module/common/lang/vi.php +++ b/module/common/lang/vi.php @@ -33,7 +33,7 @@ $lang->unfoldMenu = 'Unfold Menu'; $lang->collapseMenu = 'Collapse Menu'; $lang->runInfo = "
Time %s MS, Memory %s KB, Query %s.
"; $lang->agreement = "I have read and agreed to the terms and conditions of Z PUBLIC LICENSE 1.2 . Without authorization, I should not remove, hide or cover any logos/links of ZenTao."; -$lang->designedByAIUX = "Designed by AIUX"; +$lang->designedByAIUX = " AIUX"; $lang->reset = 'Thiết lập lại'; $lang->cancel = 'Hủy'; diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index 03d52274f6..c86ad97847 100755 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -33,7 +33,7 @@ $lang->unfoldMenu = '展开导航'; $lang->collapseMenu = '收起导航'; $lang->runInfo = "
时间: %s 毫秒, 内存: %s KB, 查询: %s.
"; $lang->agreement = "已阅读并同意《Z PUBLIC LICENSE授权协议1.2》。未经许可,不得去除、隐藏或遮掩禅道软件的任何标志及链接。"; -$lang->designedByAIUX = "Designed by 艾体验"; +$lang->designedByAIUX = " 艾体验设计"; $lang->reset = '重填'; $lang->cancel = '取消'; diff --git a/module/common/model.php b/module/common/model.php index 407372d9a5..7e3c73554f 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -353,6 +353,7 @@ class commonModel extends model echo '
  • ' . html::a(helper::createLink('misc', 'changeLog'), $lang->changeLog, '', "class='iframe' data-width='800' data-headerless='true' data-backdrop='true' data-keyboard='true'") . '
  • '; echo "\n"; echo '
  • ' . html::a(helper::createLink('misc', 'about'), " " . $lang->aboutZenTao, '', "class='about iframe' data-width='1050' data-headerless='true' data-backdrop='true' data-keyboard='true' data-class='modal-about'") . '
  • '; + echo '
  • ' . $lang->designedByAIUX . '
  • '; } /** diff --git a/module/my/control.php b/module/my/control.php index 903f442620..1a1f8e3b2e 100644 --- a/module/my/control.php +++ b/module/my/control.php @@ -616,7 +616,8 @@ class my extends control { $this->user->updatePassword($this->app->user->id); if(dao::isError()) die(js::error(dao::getError())); - die(js::closeModal('parent.parent', 'this')); + if(isonlybody()) die(js::closeModal('parent.parent', 'this')); + die(js::locate($this->createLink('my', 'index'), 'parent.parent')); } $this->view->title = $this->lang->my->common . $this->lang->colon . $this->lang->my->changePassword; diff --git a/module/my/lang/zh-cn.php b/module/my/lang/zh-cn.php index 049d01887c..2af5730db4 100644 --- a/module/my/lang/zh-cn.php +++ b/module/my/lang/zh-cn.php @@ -53,10 +53,10 @@ $lang->my->taskMenu->closedByMe = '由我关闭'; $lang->my->taskMenu->canceledByMe = '由我取消'; $lang->my->storyMenu = new stdclass(); -$lang->my->storyMenu->assignedToMe = '指给我'; -$lang->my->storyMenu->openedByMe = '我创建'; -$lang->my->storyMenu->reviewedByMe = '我评审'; -$lang->my->storyMenu->closedByMe = '我关闭'; +$lang->my->storyMenu->assignedToMe = '指派给我'; +$lang->my->storyMenu->openedByMe = '由我创建'; +$lang->my->storyMenu->reviewedByMe = '由我评审'; +$lang->my->storyMenu->closedByMe = '由我关闭'; $lang->my->projectMenu = new stdclass(); $lang->my->projectMenu->doing = '进行中'; diff --git a/module/product/model.php b/module/product/model.php index 3f118b81df..1170efdd1d 100644 --- a/module/product/model.php +++ b/module/product/model.php @@ -837,19 +837,8 @@ class productModel extends model ->fetchAll('id'); /* Determine how to display the name of the program. */ - $programList = $this->loadModel('program')->getPGMPairs(); - foreach($projectList as $id => $project) - { - $path = explode(',', $project->path); - $path = array_filter($path); - array_pop($path); - if(empty($path)) continue; - $programID = end($path); - - $programName = isset($programList[$programID]) ? $programList[$programID] : ''; - - $projectList[$id]->programName = $programName; - } + $programList = $this->loadModel('program')->getParentPairs(); + foreach($projectList as $id => $project) $projectList[$id]->programName = $programList[$project->parent]; return $projectList; } diff --git a/module/program/model.php b/module/program/model.php index 365f0d8bd9..a1a8e329ce 100644 --- a/module/program/model.php +++ b/module/program/model.php @@ -1639,7 +1639,7 @@ class programModel extends model break; case 'PRJName': $projectLink = helper::createLink('program', 'index', "projectID=$project->id", '', '', $project->id); - echo html::a($projectLink, $project->name, '', "class='not-in-tab'"); + echo html::a($projectLink, $project->name); if($project->model === 'waterfall') echo "{$this->lang->program->waterfall}"; if($project->model === 'scrum') echo "{$this->lang->program->scrum}"; break; diff --git a/module/todo/control.php b/module/todo/control.php index 0523f090b4..75209bcf1c 100644 --- a/module/todo/control.php +++ b/module/todo/control.php @@ -69,7 +69,7 @@ class todo extends control } if($this->app->getViewType() == 'xhtml') die(js::locate($this->createLink('todo', 'view', "todoID=$todoID"), 'parent')); - if(isonlybody()) die(js::locate($this->createLink('my', 'todo', "type=$date"), 'parent.parent')); + if(isonlybody()) die(js::closeModal('parent.parent')); die(js::locate($this->createLink('my', 'todo', "type=all&userID=&status=all&orderBy=id_desc"), 'parent')); } @@ -187,10 +187,16 @@ class todo extends control $user = $this->loadModel('user')->getById($userID, 'id'); $account = $user->account; - $bugs = $this->bug->getUserBugPairs($account); - $tasks = $this->task->getUserTaskPairs($account, $status); - $storys = $this->loadModel('story')->getUserStoryPairs($account); - $allTodos = $this->todo->getList($type, $account, $status); + $bugs = $this->bug->getUserBugPairs($account); + $tasks = $this->task->getUserTaskPairs($account, $status); + $storys = $this->loadModel('story')->getUserStoryPairs($account); + $issues = $this->loadModel('issue')->getUserIssuePairs($account); + $risks = $this->loadModel('risk')->getUserRiskPairs($account); + $testtasks = $this->loadModel('testtask')->getUserTestTaskPairs($account); + + $reviews = array(); + if(isset($this->config->qcVersion)) $reviews = $this->loadModel('review')->getUserReviewPairs($account); + $allTodos = $this->todo->getList($type, $account, $status); if($this->post->todoIDList) $todoIDList = $this->post->todoIDList; /* Initialize todos whose need to edited. */ @@ -203,9 +209,13 @@ class todo extends control } foreach($editedTodos as $todo) { - if($todo->type == 'story') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_STORY)->fetch('title'); - if($todo->type == 'task') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_TASK)->fetch('name'); - if($todo->type == 'bug') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_BUG)->fetch('title'); + if($todo->type == 'story') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_STORY)->fetch('title'); + if($todo->type == 'task') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_TASK)->fetch('name'); + if($todo->type == 'bug') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_BUG)->fetch('title'); + if($todo->type == 'issue') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_ISSUE)->fetch('title'); + if($todo->type == 'risk') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_RISK)->fetch('name'); + if($todo->type == 'review') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_REVIEW)->fetch('title'); + if($todo->type == 'testtask') $todo->name = $this->dao->findById($todo->idvalue)->from(TABLE_TESTTASK)->fetch('name'); $todo->begin = $todo->begin ? str_replace(':', '', $todo->begin) : '2400'; $todo->end = $todo->end ? str_replace(':', '', $todo->end) : '2400'; } @@ -231,6 +241,10 @@ class todo extends control $this->view->bugs = $bugs; $this->view->tasks = $tasks; $this->view->storys = $storys; + $this->view->issues = $issues; + $this->view->risks = $risks; + $this->view->reviews = $reviews; + $this->view->testtasks = $testtasks; $this->view->editedTodos = $editedTodos; $this->view->times = date::buildTimeList($this->config->todo->times->begin, $this->config->todo->times->end, $this->config->todo->times->delta); $this->view->time = date::now(); diff --git a/module/todo/css/edit.css b/module/todo/css/edit.css index 1257d9eda4..e0aaae4a84 100644 --- a/module/todo/css/edit.css +++ b/module/todo/css/edit.css @@ -2,3 +2,6 @@ .dateSwitcher {margin-top: 6px;} .form-horizontal .required::after{right: -10px;} .tab-content .tab-pane .input-group{padding:5px 0px; width:380px} +.nameBox{display: grid;} +.chosen-container-single .chosen-single{height: 34px;} +#begin_chosen .chosen-single{border-right-width: 0px;} diff --git a/module/todo/model.php b/module/todo/model.php index d753cb10bc..9150d90087 100644 --- a/module/todo/model.php +++ b/module/todo/model.php @@ -170,21 +170,21 @@ class todoModel extends model public function update($todoID) { $oldTodo = $this->dao->findById((int)$todoID)->from(TABLE_TODO)->fetch(); - if(in_array($oldTodo->type, array('bug', 'task', 'story'))) $oldTodo->name = ''; + if(in_array($oldTodo->type, array('bug', 'task', 'story', 'issue', 'risk', 'review', 'testtask', 'feedback'))) $oldTodo->name = ''; + + $objectType = $this->post->type; + $hasObject = in_array($objectType, array('bug', 'task', 'story', 'issue', 'risk', 'review', 'testtask', 'feedback')); $todo = fixer::input('post') ->cleanInt('pri, begin, end, private') ->add('account', $oldTodo->account) ->setIF(in_array($this->post->type, array('bug', 'task', 'story')), 'name', '') - ->setIF($this->post->type == 'bug' and $this->post->bug, 'idvalue', $this->post->bug) - ->setIF($this->post->type == 'task' and $this->post->task, 'idvalue', $this->post->task) - ->setIF($this->post->type == 'story' and $this->post->story, 'idvalue', $this->post->story) - ->setIF($this->post->type == 'feedback' and $this->post->feedback, 'idvalue', $this->post->feedback) + ->setIF($hasObject && $objectType, 'idvalue', $this->post->$objectType) ->setIF($this->post->date == false, 'date', '2030-01-01') ->setIF($this->post->begin == false, 'begin', '2400') ->setIF($this->post->end == false, 'end', '2400') ->setDefault('private', 0) ->stripTags($this->config->todo->editor->edit['id'], $this->config->allowedTags) - ->remove('bug, task, story, feedback, uid') + ->remove('bug, task, story, feedback, issue, risk, review, testtask, feedback, uid') ->get(); if($todo->end < $todo->begin) @@ -223,10 +223,7 @@ class todoModel extends model $this->dao->update(TABLE_TODO)->data($todo) ->autoCheck() ->checkIF($todo->type == 'custom', $this->config->todo->edit->requiredFields, 'notempty') - ->checkIF($todo->type == 'bug' and $todo->idvalue == 0, 'idvalue', 'notempty') - ->checkIF($todo->type == 'task' and $todo->idvalue == 0, 'idvalue', 'notempty') - ->checkIF($todo->type == 'story' and $todo->idvalue == 0, 'idvalue', 'notempty') - ->checkIF($todo->type == 'feedback' and $todo->idvalue == 0, 'idvalue', 'notempty') + ->checkIF($hasObject && $todo->idvalue == 0, 'idvalue', 'notempty') ->where('id')->eq($todoID) ->exec(); if(!dao::isError()) @@ -263,9 +260,14 @@ class todoModel extends model $todo->name = ($todo->type == 'custom' or $todo->type == 'cycle') ? $data->names[$todoID] : ''; $todo->begin = isset($data->begins[$todoID]) ? $data->begins[$todoID] : 2400; $todo->end = isset($data->ends[$todoID]) ? $data->ends[$todoID] : 2400; - if($todo->type == 'task') $todo->idvalue = isset($data->tasks[$todoID]) ? $data->tasks[$todoID] : 0; - if($todo->type == 'bug') $todo->idvalue = isset($data->bugs[$todoID]) ? $data->bugs[$todoID] : 0; - if($todo->type == 'story')$todo->idvalue = isset($data->storys[$todoID]) ? $data->storys[$todoID] : 0; + if($todo->type == 'task') $todo->idvalue = isset($data->tasks[$todoID]) ? $data->tasks[$todoID] : 0; + if($todo->type == 'bug') $todo->idvalue = isset($data->bugs[$todoID]) ? $data->bugs[$todoID] : 0; + if($todo->type == 'story') $todo->idvalue = isset($data->storys[$todoID]) ? $data->storys[$todoID] : 0; + if($todo->type == 'issue') $todo->idvalue = isset($data->issues[$todoID]) ? $data->issues[$todoID] : 0; + if($todo->type == 'risk') $todo->idvalue = isset($data->risks[$todoID]) ? $data->risks[$todoID] : 0; + if($todo->type == 'review') $todo->idvalue = isset($data->reviews[$todoID]) ? $data->reviews[$todoID] : 0; + if($todo->type == 'testtask') $todo->idvalue = isset($data->testtasks[$todoID]) ? $data->testtasks[$todoID] : 0; + if($todo->type == 'feedback') $todo->idvalue = isset($data->feedbacks[$todoID]) ? $data->feedbacks[$todoID] : 0; if($todo->end < $todo->begin) die(js::alert(sprintf($this->lang->error->gt, $this->lang->todo->end, $this->lang->todo->begin))); @@ -283,6 +285,10 @@ class todoModel extends model ->checkIF($todo->type == 'bug' and $todo->idvalue == 0, 'idvalue', 'notempty') ->checkIF($todo->type == 'task' and $todo->idvalue == 0, 'idvalue', 'notempty') ->checkIF($todo->type == 'story' and $todo->idvalue == 0, 'idvalue', 'notempty') + ->checkIF($todo->type == 'issue' and $todo->idvalue == 0, 'idvalue', 'notempty') + ->checkIF($todo->type == 'risk' and $todo->idvalue == 0, 'idvalue', 'notempty') + ->checkIF($todo->type == 'review' and $todo->idvalue == 0, 'idvalue', 'notempty') + ->checkIF($todo->type == 'testtask' and $todo->idvalue == 0, 'idvalue', 'notempty') ->checkIF($todo->type == 'feedback' and $todo->idvalue == 0, 'idvalue', 'notempty') ->where('id')->eq($todoID) ->exec(); @@ -748,6 +754,8 @@ class todoModel extends model $projectIdList[$type] = array(); continue; } + + $todoIdList = array_unique($todoIdList); if($type == 'task') $projectIdList[$type] = $this->dao->select('id,PRJ')->from(TABLE_TASK)->where('id')->in($todoIdList)->fetchPairs('id', 'PRJ'); if($type == 'bug') $projectIdList[$type] = $this->dao->select('id,PRJ')->from(TABLE_BUG)->where('id')->in($todoIdList)->fetchPairs('id', 'PRJ'); if($type == 'issue') $projectIdList[$type] = $this->dao->select('id,PRJ')->from(TABLE_ISSUE)->where('id')->in($todoIdList)->fetchPairs('id', 'PRJ'); diff --git a/module/todo/view/batchedit.html.php b/module/todo/view/batchedit.html.php index 8f3ff55953..3c1a61ba59 100644 --- a/module/todo/view/batchedit.html.php +++ b/module/todo/view/batchedit.html.php @@ -83,6 +83,22 @@ { echo html::select("storys[$todo->id]", $storys, $todo->idvalue, 'class="form-control chosen"'); } + elseif($todo->type == 'issue') + { + echo html::select("issues[$todo->id]", $issues, $todo->idvalue, 'class="form-control chosen"'); + } + elseif($todo->type == 'risk') + { + echo html::select("risks[$todo->id]", $risks, $todo->idvalue, 'class="form-control chosen"'); + } + elseif($todo->type == 'review') + { + echo html::select("reviews[$todo->id]", $reviews, $todo->idvalue, 'class="form-control chosen"'); + } + elseif($todo->type == 'testtask') + { + echo html::select("testtasks[$todo->id]", $testtasks, $todo->idvalue, 'class="form-control chosen"'); + } ?> diff --git a/module/todo/view/create.html.php b/module/todo/view/create.html.php index b23c7e7176..746c8b9632 100644 --- a/module/todo/view/create.html.php +++ b/module/todo/view/create.html.php @@ -142,7 +142,10 @@ todo->beginAndEnd;?>
    - +
    diff --git a/module/upgrade/model.php b/module/upgrade/model.php index 041cdab3bc..684f6623b2 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -657,6 +657,7 @@ class upgradeModel extends model $this->appendExec('20_0_beta1'); case '20_0_beta2': $this->saveLogs('Execute 20_0_beta2'); + $this->execSQL($this->getUpgradeFile('20.0.beta2')); $this->adjustBudget(); $this->appendExec('20_0_beta2'); } diff --git a/www/js/zui/min.js b/www/js/zui/min.js index a4aa9edc1e..f89c9327ab 100644 --- a/www/js/zui/min.js +++ b/www/js/zui/min.js @@ -1,5 +1,5 @@ /*! - * ZUI: ZUI for Zentao20 - v1.9.2 - 2021-01-06 + * ZUI: ZUI for Zentao20 - v1.9.2 - 2021-01-08 * http://openzui.com * GitHub: https://github.com/easysoft/zui.git * Copyright (c) 2021 cnezsoft.com; Licensed MIT @@ -16,7 +16,7 @@ function(t,e,i){"$:nomunge";function n(){o=e[r](function(){a.each(function(){var * Copyright 2006, 2014 Klaus Hartl * Released under the MIT license */ -function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t("object"==typeof exports?require("jquery"):jQuery)}(function(t){function e(t){return r.raw?t:encodeURIComponent(t)}function i(t){return r.raw?t:decodeURIComponent(t)}function n(t){return e(r.json?JSON.stringify(t):String(t))}function o(t){0===t.indexOf('"')&&(t=t.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{return t=decodeURIComponent(t.replace(s," ")),r.json?JSON.parse(t):t}catch(e){}}function a(t,e){var i=r.raw?t:o(t);return"function"==typeof e?e(i):i}var s=/\+/g,r=t.cookie=function(o,s,l){if(void 0!==s&&"function"!=typeof s){if(l=t.extend({},r.defaults,l),"number"==typeof l.expires){var h=l.expires,c=l.expires=new Date;c.setTime(+c+864e5*h)}return document.cookie=[e(o),"=",n(s),l.expires?"; expires="+l.expires.toUTCString():"",l.path?"; path="+l.path:"",l.domain?"; domain="+l.domain:"",l.secure?"; secure":""].join("")}for(var d=o?void 0:{},u=document.cookie?document.cookie.split("; "):[],f=0,p=u.length;f=0;t--)delete this.page[i[t]];this.set(a,this.page)}},s.prototype.pageRemove=function(t){"undefined"!=typeof this.page[t]&&(this.page[t]=null,this.pageSave())},s.prototype.pageClear=function(){this.page={},this.pageSave()},s.prototype.pageGet=function(t,e){var i=this.page[t];return void 0===e||null!==i&&void 0!==i?i:e},s.prototype.pageSet=function(t,i){e.isPlainObject(t)?e.extend(!0,this.page,t):this.page[this.serialize(t)]=i,this.pageSave()},s.prototype.check=function(){if(!this.enable&&!this.silence)throw new Error("Browser not support localStorage or enable status been set true.");return this.enable},s.prototype.length=function(){return this.check()?i.getLength?i.getLength():i.length:0},s.prototype.removeItem=function(t){return i.removeItem(t),this},s.prototype.remove=function(t){return this.removeItem(t)},s.prototype.getItem=function(t){return i.getItem(t)},s.prototype.get=function(t,e){var i=this.deserialize(this.getItem(t));return"undefined"!=typeof i&&null!==i||"undefined"==typeof e?i:e},s.prototype.key=function(t){return i.key(t)},s.prototype.setItem=function(t,e){return i.setItem(t,e),this},s.prototype.set=function(t,e){return void 0===e?this.remove(t):(this.setItem(t,this.serialize(e)),this)},s.prototype.clear=function(){return i.clear(),this},s.prototype.forEach=function(t){for(var e=this.length(),n=e-1;n>=0;n--){var o=i.key(n);t(o,this.get(o))}return this},s.prototype.getAll=function(){var t={};return this.forEach(function(e,i){t[e]=i}),t},s.prototype.serialize=function(t){return"string"==typeof t?t:JSON.stringify(t)},s.prototype.deserialize=function(t){if("string"==typeof t)try{return JSON.parse(t)}catch(e){return t||void 0}},e.zui({store:new s})}(window,jQuery),function(t){"use strict";var e="zui.searchBox",i=function(e,n){var o=this;o.name=name,o.$=t(e),o.options=n=t.extend({},i.DEFAULTS,o.$.data(),n);var a=o.$.is(n.inputSelector)?o.$:o.$.find(n.inputSelector);if(a.length){var s=function(){o.changeTimer&&(clearTimeout(o.changeTimer),o.changeTimer=null)},r=function(){s();var t=o.getSearch();if(t!==o.lastValue){var e=""===t;a.toggleClass("empty",e),o.$.callComEvent(o,"onSearchChange",[t,e]),o.lastValue=t}};o.$input=a=a.first(),a.on(n.listenEvent,function(t){o.changeTimer=setTimeout(function(){r()},n.changeDelay)}).on("focus",function(t){a.addClass("focus"),o.$.callComEvent(o,"onFocus",[t])}).on("blur",function(t){a.removeClass("focus"),o.$.callComEvent(o,"onBlur",[t])}).on("keydown",function(t){var e=0,i=t.which;27===i&&n.escToClear?(this.setSearch("",!0),r(),e=1):13===i&&n.onPressEnter&&(r(),o.$.callComEvent(o,"onPressEnter",[t]));var a=o.$.callComEvent(o,"onKeyDown",[t]);a===!1&&(e=1),e&&t.preventDefault()}),o.$.on("click",".search-clear-btn",function(t){o.setSearch("",!0),r(),o.focus(),t.preventDefault()}),r()}else console.error("ZUI: search box init error, cannot find search box input element.")};i.DEFAULTS={inputSelector:'input[type="search"],input[type="text"]',listenEvent:"change input paste",changeDelay:500},i.prototype.getSearch=function(){return this.$input&&t.trim(this.$input.val())},i.prototype.setSearch=function(t,e){var i=this.$input;i&&(i.val(t),e||i.trigger("change"))},i.prototype.focus=function(){this.$input&&this.$input.focus()},t.fn.searchBox=function(n){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof n&&n;a||o.data(e,a=new i(this,s)),"string"==typeof n&&a[n]()})},i.NAME=e,t.fn.searchBox.Constructor=i}(jQuery),function(t,e){"use strict";var i="zui.draggable",n={container:"body",move:!0},o=0,a=function(e,i){var a=this;a.$=t(e),a.id=o++,a.options=t.extend({},n,a.$.data(),i),a.init()};a.DEFAULTS=n,a.NAME=i,a.prototype.init=function(){var n,o,a,s,r,l=this,h=l.$,c="before",d="drag",u="finish",f="."+i+"."+l.id,p="mousedown"+f,g="mouseup"+f,m="mousemove"+f,v=l.options,y=v.selector,b=v.handle,w=h,x="function"==typeof v.move,C=function(t){var e=t.pageX,i=t.pageY;r=!0;var o={left:e-a.x,top:i-a.y};w.removeClass("drag-ready").addClass("dragging"),v.move&&(x?v.move(o,w):w.css(o)),v[d]&&v[d]({event:t,element:w,startOffset:a,pos:o,offset:{x:e-n.x,y:i-n.y},smallOffset:{x:e-s.x,y:i-s.y}}),s.x=e,s.y=i,v.stopPropagation&&t.stopPropagation()},_=function(i){if(t(e).off(f),!r)return void w.removeClass("drag-ready");var o={left:i.pageX-a.x,top:i.pageY-a.y};w.removeClass("drag-ready dragging"),v.move&&(x?v.move(o,w):w.css(o)),v[u]&&v[u]({event:i,element:w,startOffset:a,pos:o,offset:{x:i.pageX-n.x,y:i.pageY-n.y},smallOffset:{x:i.pageX-s.x,y:i.pageY-s.y}}),i.preventDefault(),v.stopPropagation&&i.stopPropagation()},k=function(i){var l=t.zui.getMouseButtonCode(v.mouseButton);if(!(l>-1&&i.button!==l)){var h=t(this);if(y&&(w=b?h.closest(y):h),v[c]){var d=v[c]({event:i,element:w});if(d===!1)return}var u=t(v.container),f=w.offset();o=u.offset(),n={x:i.pageX,y:i.pageY},a={x:i.pageX-f.left+o.left,y:i.pageY-f.top+o.top},s=t.extend({},n),r=!1,w.addClass("drag-ready"),i.preventDefault(),v.stopPropagation&&i.stopPropagation(),t(e).on(m,C).on(g,_)}};b?h.on(p,b,k):y?h.on(p,y,k):h.on(p,k)},a.prototype.destroy=function(){var n="."+i+"."+this.id;this.$.off(n),t(e).off(n),this.$.data(i,null)},t.fn.draggable=function(e){return this.each(function(){var n=t(this),o=n.data(i),s="object"==typeof e&&e;o||n.data(i,o=new a(this,s)),"string"==typeof e&&o[e]()})},t.fn.draggable.Constructor=a}(jQuery,document),function(t,e,i){"use strict";var n="zui.droppable",o={target:".droppable-target",deviation:5,sensorOffsetX:0,sensorOffsetY:0,dropToClass:"drop-to"},a=0,s=function(e,i){var n=this;n.id=a++,n.$=t(e),n.options=t.extend({},o,n.$.data(),i),n.init()};s.DEFAULTS=o,s.NAME=n,s.prototype.trigger=function(e,i){return t.zui.callEvent(this.options[e],i,this)},s.prototype.init=function(){var o,a,s,r,l,h,c,d,u,f,p,g,m,v=this,y=v.$,b=v.options,w=b.deviation,x="."+n+"."+v.id,C="mousedown"+x,_="mouseup"+x,k="mousemove"+x,T=b.selector,S=b.handle,D=b.flex,M=b.container,P=b.canMoveHere,z=b.dropToClass,L=y,I=!1,F=M?t(b.container).first():T?y:t("body"),$=function(e){if(I&&(p={left:e.pageX,top:e.pageY},!(i.abs(p.left-d.left)a&&p.top>s&&p.left-1&&i.button!==n)){var p=t(this);T&&(L=S?p.closest(T):p),L.hasClass("drag-shadow")||b.before&&b.before({event:i,element:L})===!1||(I=!0,o="function"==typeof b.target?b.target(L,y):F.find(b.target),a=null,s=null,r=!1,l=!0,h=null,c=L.offset(),u=F.offset(),u.top=u.top-F.scrollTop(),u.left=u.left-F.scrollLeft(),d={left:i.pageX,top:i.pageY},g=t.extend({},d),f={left:d.left-c.left,top:d.top-c.top},L.addClass("drag-from"),t(e).on(k,$).on(_,A),m=setTimeout(function(){t(e).on(C,A)},10),i.preventDefault(),b.stopPropagation&&i.stopPropagation())}};S?y.on(C,S,E):T?y.on(C,T,E):y.on(C,E)},s.prototype.destroy=function(){var i="."+n+"."+this.id;this.$.off(i),t(e).off(i),this.$.data(n,null)},s.prototype.reset=function(){this.destroy(),this.init()},t.fn.droppable=function(e){return this.each(function(){var i=t(this),o=i.data(n),a="object"==typeof e&&e;o||i.data(n,o=new s(this,a)),"string"==typeof e&&o[e]()})},t.fn.droppable.Constructor=s}(jQuery,document,Math),+function(t,e){"use strict";function i(e,i,a){return this.each(function(){var s=t(this),r=s.data(n),l=t.extend({},o.DEFAULTS,s.data(),"object"==typeof e&&e);r||s.data(n,r=new o(this,l)),"string"==typeof e?r[e](i,a):l.show&&r.show(i,a)})}var n="zui.modal",o=function(i,o){var a=this;a.options=o,a.$body=t(document.body),a.$element=t(i),a.$backdrop=a.isShown=null,a.scrollbarWidth=0,o.moveable===e&&(a.options.moveable=a.$element.hasClass("modal-moveable")),o.remote&&a.$element.find(".modal-content").load(o.remote,function(){a.$element.trigger("loaded."+n)}),o.scrollInside&&t(window).on("resize."+n,function(){a.isShown&&a.adjustPosition(e,100)})};o.VERSION="3.2.0",o.TRANSITION_DURATION=300,o.BACKDROP_TRANSITION_DURATION=150,o.DEFAULTS={backdrop:!0,keyboard:!0,show:!0,position:"fit"};var a=function(e,i){var n=t(window);i.left=Math.max(0,Math.min(i.left,n.width()-e.outerWidth())),i.top=Math.max(0,Math.min(i.top,n.height()-e.outerHeight())),e.css(i)};o.prototype.toggle=function(t,e){return this.isShown?this.hide():this.show(t,e)},o.prototype.adjustPosition=function(i,o){var s=this;if(clearTimeout(s.reposTask),o)return void(s.reposTask=setTimeout(s.adjustPosition.bind(s,i,0),o));var r=s.options;if(i===e&&(i=r.position),i!==e&&null!==i){"function"==typeof i&&(i=i(s));var l=s.$element.find(".modal-dialog"),h=t(window).height(),c={maxHeight:"initial",overflow:"visible"},d=l.find(".modal-body").css(c);if(r.scrollInside&&d.length){var u=r.headerHeight,f=r.footerHeight,p=l.find(".modal-header"),g=l.find(".modal-footer");"number"!=typeof u&&(u=p.length?p.outerHeight():"function"==typeof u?u(p):0),"number"!=typeof f&&(f=g.length?g.outerHeight():"function"==typeof f?f(g):0),c.maxHeight=h-u-f,c.overflow=d[0].scrollHeight>c.maxHeight?"auto":"visible",d.css(c)}var m=Math.max(0,(h-l.outerHeight())/2);if("fit"===i?i={top:m>50?Math.floor(2*m/3):m}:"center"===i?i={top:m}:t.isPlainObject(i)||(i={top:i}),l.hasClass("modal-moveable")){var v=null,y=r.rememberPos;y&&(y===!0?v=s.$element.data("modal-pos"):t.zui.store&&(v=t.zui.store.pageGet(n+".rememberPos."+y))),i=t.extend(i,{left:Math.max(0,(t(window).width()-l.outerWidth())/2)},v),"inside"===r.moveable?a(l,i):l.css(i)}else l.css(i)}},o.prototype.setMoveable=function(){t.fn.draggable||console.error("Moveable modal requires draggable.js.");var e=this,i=e.options,o=e.$element.find(".modal-dialog").removeClass("modal-dragged");o.toggleClass("modal-moveable",!!i.moveable),e.$element.data("modal-moveable-setup")||o.draggable({container:e.$element,handle:".modal-header",before:function(){var t=o.css("margin-top");t&&"0px"!==t&&o.css("top",t).css("margin-top","").addClass("modal-dragged")},finish:function(o){var a=i.rememberPos;a&&(e.$element.data("modal-pos",o.pos),t.zui.store&&a!==!0&&t.zui.store.pageSet(n+".rememberPos."+a,o.pos))},move:"inside"!==i.moveable||function(t){a(o,t)}})},o.prototype.show=function(e,i){var a=this,s=t.Event("show."+n,{relatedTarget:e});a.$element.trigger(s),a.$element.toggleClass("modal-scroll-inside",!!a.options.scrollInside),a.isShown||s.isDefaultPrevented()||(a.isShown=!0,a.options.moveable&&a.setMoveable(),a.options.backdrop!==!1&&(a.setScrollbar(),a.$body.addClass("modal-open")),a.escape(),a.$element.on("click.dismiss."+n,'[data-dismiss="modal"]',function(t){a.hide(),t.stopPropagation()}),a.backdrop(function(){var s=t.support.transition&&a.$element.hasClass("fade");a.$element.parent().length||a.$element.appendTo(a.$body),a.$element.show().scrollTop(0),s&&a.$element[0].offsetWidth,a.$element.addClass("in").attr("aria-hidden",!1),a.adjustPosition(i),a.enforceFocus();var r=t.Event("shown."+n,{relatedTarget:e});s?a.$element.find(".modal-dialog").one("bsTransitionEnd",function(){a.$element.trigger("focus").trigger(r)}).emulateTransitionEnd(o.TRANSITION_DURATION):a.$element.trigger("focus").trigger(r)}))},o.prototype.hide=function(e){e&&e.preventDefault&&e.preventDefault();var i=this;e=t.Event("hide."+n),i.$element.trigger(e),i.isShown&&!e.isDefaultPrevented()&&(i.isShown=!1,i.options.backdrop!==!1&&(i.$body.removeClass("modal-open"),i.resetScrollbar()),i.escape(),t(document).off("focusin."+n),i.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss."+n),t.support.transition&&i.$element.hasClass("fade")?i.$element.one("bsTransitionEnd",i.hideModal.bind(i)).emulateTransitionEnd(o.TRANSITION_DURATION):i.hideModal())},o.prototype.enforceFocus=function(){t(document).off("focusin."+n).on("focusin."+n,function(t){this.$element[0]===t.target||this.$element.has(t.target).length||this.$element.trigger("focus")}.bind(this))},o.prototype.escape=function(){this.isShown&&this.options.keyboard?t(document).on("keydown.dismiss."+n,function(i){if(27==i.which){var o=t.Event("escaping."+n),a=this.$element.triggerHandler(o,"esc");if(a!=e&&!a)return;this.hide()}}.bind(this)):this.isShown||t(document).off("keydown.dismiss."+n)},o.prototype.hideModal=function(){var t=this;this.$element.hide(),this.backdrop(function(){t.$element.trigger("hidden."+n)})},o.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},o.prototype.backdrop=function(e){var i=this,a=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var s=t.support.transition&&a;if(this.$backdrop=t('