diff --git a/VERSION b/VERSION index 6060b96fa1..c9333734bd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -17.5 +17.6 diff --git a/api/v1/entries/execution.php b/api/v1/entries/execution.php index cc9add74e9..3d66f624a0 100644 --- a/api/v1/entries/execution.php +++ b/api/v1/entries/execution.php @@ -20,9 +20,8 @@ class executionEntry extends Entry */ public function get($executionID) { - $fields = $this->param('fields'); - $productID = $this->param('productID'); - $status = $this->param('status', 'all'); + $fields = $this->param('fields'); + $status = $this->param('status', 'all'); $control = $this->loadController('execution', 'view'); $control->view($executionID); @@ -47,8 +46,8 @@ class executionEntry extends Entry foreach($executionProduct->plans as $planID) { $plan = new stdclass(); - $plan->id = $planID; - $plan->name = $data->data->planGroups->{$productID}->{$planID}; + $plan->id = trim($planID, ','); + $plan->name = $data->data->planGroups->{$productID}->{$plan->id}; $product->plans[] = $plan; } $execution->products[] = $product; diff --git a/api/v1/entries/program.php b/api/v1/entries/program.php index 22a9469687..e7394f9d45 100644 --- a/api/v1/entries/program.php +++ b/api/v1/entries/program.php @@ -60,7 +60,7 @@ class programEntry extends Entry public function delete($programID) { $control = $this->loadController('program', 'delete'); - $control->delete(0, $programID, 'true'); + $control->delete($programID, 'true'); $data = $this->getData(); if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message); diff --git a/api/v1/entries/tabs.php b/api/v1/entries/tabs.php index 9078299d8c..af0c938f46 100644 --- a/api/v1/entries/tabs.php +++ b/api/v1/entries/tabs.php @@ -29,7 +29,7 @@ class tabsEntry extends baseEntry foreach($tabs as $menuKey) { if(!isset($this->lang->my->$menuKey)) continue; - if(!common::hasPriv('my', $menuKey)) continue; + if(!common::hasPriv('my', 'work')) continue; $label = $this->lang->my->$menuKey; if($menuKey == 'calendar') $label = $this->lang->my->calendarAction; diff --git a/api/v1/entries/user.php b/api/v1/entries/user.php index 5a77a6b2af..8940d9ee05 100644 --- a/api/v1/entries/user.php +++ b/api/v1/entries/user.php @@ -254,7 +254,7 @@ class userEntry extends Entry if(!common::hasPriv('my', 'todo')) break; $control = $this->loadController('my', 'todo'); - $control->todo($this->param('date', 'all'), '', 'all', 'date_desc', 0, 0, $this->param('limit', 5), 1); + $control->todo($this->param('date', 'before'), '', 'all', 'date_desc', 0, $this->param('limit', 5), 1); $data = $this->getData(); if($data->status == 'success') @@ -313,7 +313,7 @@ class userEntry extends Entry { $this->config->openMethods[] = 'my.risk'; $control = $this->loadController('my', 'risk'); - $control->risk('createdBy', 0, 'id_desc', 0, $this->param('limit', 5), 1); + $control->risk('assignedTo', 0, 'id_desc', 0, $this->param('limit', 5), 1); $data = $this->getData(); if($data->status == 'success') @@ -331,7 +331,7 @@ class userEntry extends Entry { $this->config->openMethods[] = 'my.myMeeting'; $control = $this->loadController('my', 'myMeeting'); - $control->myMeeting('all', '', 'id_desc', 0, $this->param('limit', 5), 1); + $control->myMeeting('futureMeeting', '', 'id_desc', 0, $this->param('limit', 5), 1); $data = $this->getData(); if($data->status == 'success') diff --git a/bin/ztcli b/bin/ztcli index 38252d263b..b6352cf9e9 100755 --- a/bin/ztcli +++ b/bin/ztcli @@ -50,7 +50,7 @@ if($config->requestType == 'PATH_INFO') { $_SERVER['PATH_INFO'] = $path['basename']; } - else + else { /* url like http://pms.zentao.net/zentao/my/, PATH_INFO is 'my'. */ if(is_dir('./module/' . $path['basename'])) diff --git a/config/config.php b/config/config.php index 29e435d02b..e8d0dbd010 100644 --- a/config/config.php +++ b/config/config.php @@ -16,7 +16,7 @@ if(!class_exists('config')){class config{}} if(!function_exists('getWebRoot')){function getWebRoot(){}} /* 基本设置。Basic settings. */ -$config->version = '17.5'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it. +$config->version = '17.6'; // ZenTaoPHP的版本。 The version of ZenTaoPHP. Don't change it. $config->liteVersion = '1.2'; // 迅捷版版本。 The version of Lite. $config->charset = 'UTF-8'; // ZenTaoPHP的编码。 The encoding of ZenTaoPHP. $config->cookieLife = time() + 2592000; // Cookie的生存时间。The cookie life time. diff --git a/config/zentaopms.php b/config/zentaopms.php index a59c81cb38..a10d6a941c 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -398,3 +398,6 @@ $config->programPriv->waterfall = array_merge($config->programPriv->scrum, array $config->waterfallModules = array('workestimation', 'durationestimation', 'budget', 'programplan', 'review', 'reviewissue', 'weekly', 'cm', 'milestone', 'design', 'opportunity', 'auditplan', 'trainplan', 'gapanalysis', 'pssp', 'researchplan', 'researchreport'); $config->showMainMenu = true; +$config->maxPriValue = '256'; + +$config->importWhiteList = array('user', 'task', 'story', 'bug', 'testcase', 'feedback'); \ No newline at end of file diff --git a/db/demo.sql b/db/demo.sql index d2d0550d63..2277a6a1d4 100644 --- a/db/demo.sql +++ b/db/demo.sql @@ -15,7 +15,7 @@ INSERT INTO `zt_action` (`id`, `objectType`, `objectID`, `product`, `project`, ` (11, 'story', 1, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:09:49', '', '', '0'), (12, 'story', 2, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:16:37', '', '', '0'), (13, 'story', 3, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:18:10', '', '', '0'), -(14, 'story', 3, ',1,', 0, 0, 'productManager', 'changed', '2012-06-05 10:19:06', '', '', '0'), +(14, 'story', 3, ',1,', 0, 0, 'productManager', 'changing', '2012-06-05 10:19:06', '', '', '0'), (15, 'story', 4, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:20:16', '', '', '0'), (16, 'story', 5, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:21:39', '', '', '0'), (17, 'story', 6, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:23:11', '', '', '0'), @@ -589,9 +589,9 @@ INSERT INTO `zt_story` (`id`, `parent`, `product`, `branch`, `module`, `plan`, ` (2, 0, 1, 0, 2, '1', 'po', '', 0, '新闻中心的设计和开发。', '', 'story', 1, 1, 'active', '', '', 'projected', '', '', 'productManager', '2012-06-05 10:16:37', 'productManager', '2012-06-05 10:16:37', 'productManager', '2012-06-05 10:25:33', 'productManager, ', '2012-06-05 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'), (3, 0, 1, 0, 3, '1', 'po', '', 0, '成果展示的设计和开发', '', 'story', 1, 0, 'active', '', '', 'developing', '', '', 'productManager', '2012-06-05 10:18:10', 'productManager', '2012-06-05 10:18:10', 'productManager', '2012-06-05 10:25:38', 'productManager, ', '2012-06-05 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 2, '0', '0'), (4, 0, 1, 0, 4, '1', 'po', '', 0, '售后服务的设计和开发', '', 'story', 1, 1, 'active', '', '', 'developed', '', '', 'productManager', '2012-06-05 10:20:16', 'productManager', '2012-06-05 10:20:16', 'productManager', '2012-06-05 10:25:42', 'productManager, ', '2012-06-05 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'), -(5, 0, 1, 0, 5, '1', 'po', '', 0, '诚聘英才的设计和开发', '', 'story', 1, 1, 'draft', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:21:39', 'productManager', '2012-06-05 10:21:39', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'), -(6, 0, 1, 0, 6, '1', 'po', '', 0, '合作洽谈的设计和开发', '', 'story', 1, 1, 'draft', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:23:11', 'productManager', '2012-06-05 10:23:11', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'), -(7, 0, 1, 0, 7, '1', 'po', '', 0, '关于我们的设计和开发', '', 'story', 1, 1, 'draft', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:24:19', 'productManager', '2012-06-05 10:24:19', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'); +(5, 0, 1, 0, 5, '1', 'po', '', 0, '诚聘英才的设计和开发', '', 'story', 1, 1, 'reviewing', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:21:39', 'productManager', '2012-06-05 10:21:39', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'), +(6, 0, 1, 0, 6, '1', 'po', '', 0, '合作洽谈的设计和开发', '', 'story', 1, 1, 'reviewing', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:23:11', 'productManager', '2012-06-05 10:23:11', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'), +(7, 0, 1, 0, 7, '1', 'po', '', 0, '关于我们的设计和开发', '', 'story', 1, 1, 'reviewing', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:24:19', 'productManager', '2012-06-05 10:24:19', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'); INSERT INTO `zt_storyspec` (`story`, `version`, `title`, `spec`, `verify`) VALUES (1, 1, '首页设计和开发', '作为一名本公司的用户,我希望可以在首页看到该公司网站的基本内容,例如最新动态、部分成果展示、联系信息、工商信息等。
', '开发并通过验收
'), (2, 1, '新闻中心的设计和开发。', '作为一名本公司的用户,我希望可以在新闻中心看到该公司网站的企业新闻,这样可以通过新闻了解企业的最新动态。
', ''), diff --git a/db/endemo.sql b/db/endemo.sql index d2d0550d63..2277a6a1d4 100644 --- a/db/endemo.sql +++ b/db/endemo.sql @@ -15,7 +15,7 @@ INSERT INTO `zt_action` (`id`, `objectType`, `objectID`, `product`, `project`, ` (11, 'story', 1, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:09:49', '', '', '0'), (12, 'story', 2, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:16:37', '', '', '0'), (13, 'story', 3, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:18:10', '', '', '0'), -(14, 'story', 3, ',1,', 0, 0, 'productManager', 'changed', '2012-06-05 10:19:06', '', '', '0'), +(14, 'story', 3, ',1,', 0, 0, 'productManager', 'changing', '2012-06-05 10:19:06', '', '', '0'), (15, 'story', 4, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:20:16', '', '', '0'), (16, 'story', 5, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:21:39', '', '', '0'), (17, 'story', 6, ',1,', 0, 0, 'productManager', 'opened', '2012-06-05 10:23:11', '', '', '0'), @@ -589,9 +589,9 @@ INSERT INTO `zt_story` (`id`, `parent`, `product`, `branch`, `module`, `plan`, ` (2, 0, 1, 0, 2, '1', 'po', '', 0, '新闻中心的设计和开发。', '', 'story', 1, 1, 'active', '', '', 'projected', '', '', 'productManager', '2012-06-05 10:16:37', 'productManager', '2012-06-05 10:16:37', 'productManager', '2012-06-05 10:25:33', 'productManager, ', '2012-06-05 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'), (3, 0, 1, 0, 3, '1', 'po', '', 0, '成果展示的设计和开发', '', 'story', 1, 0, 'active', '', '', 'developing', '', '', 'productManager', '2012-06-05 10:18:10', 'productManager', '2012-06-05 10:18:10', 'productManager', '2012-06-05 10:25:38', 'productManager, ', '2012-06-05 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 2, '0', '0'), (4, 0, 1, 0, 4, '1', 'po', '', 0, '售后服务的设计和开发', '', 'story', 1, 1, 'active', '', '', 'developed', '', '', 'productManager', '2012-06-05 10:20:16', 'productManager', '2012-06-05 10:20:16', 'productManager', '2012-06-05 10:25:42', 'productManager, ', '2012-06-05 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'), -(5, 0, 1, 0, 5, '1', 'po', '', 0, '诚聘英才的设计和开发', '', 'story', 1, 1, 'draft', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:21:39', 'productManager', '2012-06-05 10:21:39', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'), -(6, 0, 1, 0, 6, '1', 'po', '', 0, '合作洽谈的设计和开发', '', 'story', 1, 1, 'draft', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:23:11', 'productManager', '2012-06-05 10:23:11', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'), -(7, 0, 1, 0, 7, '1', 'po', '', 0, '关于我们的设计和开发', '', 'story', 1, 1, 'draft', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:24:19', 'productManager', '2012-06-05 10:24:19', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'); +(5, 0, 1, 0, 5, '1', 'po', '', 0, '诚聘英才的设计和开发', '', 'story', 1, 1, 'reviewing', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:21:39', 'productManager', '2012-06-05 10:21:39', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'), +(6, 0, 1, 0, 6, '1', 'po', '', 0, '合作洽谈的设计和开发', '', 'story', 1, 1, 'reviewing', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:23:11', 'productManager', '2012-06-05 10:23:11', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'), +(7, 0, 1, 0, 7, '1', 'po', '', 0, '关于我们的设计和开发', '', 'story', 1, 1, 'reviewing', '', '', 'planned', '', '', 'productManager', '2012-06-05 10:24:19', 'productManager', '2012-06-05 10:24:19', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', '0000-00-00 00:00:00', '', 0, '', '', 0, 1, '0', '0'); INSERT INTO `zt_storyspec` (`story`, `version`, `title`, `spec`, `verify`) VALUES (1, 1, '首页设计和开发', '作为一名本公司的用户,我希望可以在首页看到该公司网站的基本内容,例如最新动态、部分成果展示、联系信息、工商信息等。
', '开发并通过验收
'), (2, 1, '新闻中心的设计和开发。', '作为一名本公司的用户,我希望可以在新闻中心看到该公司网站的企业新闻,这样可以通过新闻了解企业的最新动态。
', ''), diff --git a/db/update17.5.sql b/db/update17.5.sql index f985aa8c85..8b3f2aafd5 100644 --- a/db/update17.5.sql +++ b/db/update17.5.sql @@ -1,3 +1,7 @@ +ALTER TABLE `zt_story` MODIFY `status` enum('','changed','active','draft','closed','reviewing') NOT NULL DEFAULT '' AFTER `estimate`; +UPDATE `zt_story` SET `status` = 'reviewing' WHERE `status` = 'changed'; +ALTER TABLE `zt_story` MODIFY `status` enum('','changing','active','draft','closed','reviewing') NOT NULL DEFAULT '' AFTER `estimate`; + ALTER TABLE `zt_feedback` ADD `repeatFeedback` mediumint(8) NOT NULL DEFAULT 0 AFTER `feedbackBy`; ALTER TABLE `zt_assetlib` ADD `order` SMALLINT UNSIGNED NOT NULL DEFAULT '0' AFTER `desc`; diff --git a/db/zentao.sql b/db/zentao.sql index 155d4056cf..ac6389009a 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -791,6 +791,7 @@ CREATE TABLE IF NOT EXISTS `zt_job` ( `lastExec` datetime DEFAULT NULL, `lastStatus` varchar(255) DEFAULT NULL, `lastTag` varchar(255) DEFAULT NULL, + `lastSyncDate` datetime DEFAULT NULL, `deleted` enum('0','1') NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -1442,7 +1443,7 @@ CREATE TABLE IF NOT EXISTS `zt_story` ( `category` varchar(30) NOT NULL default 'feature', `pri` tinyint(3) unsigned NOT NULL default '3', `estimate` float unsigned NOT NULL, - `status` enum('','changed','active','draft','closed') NOT NULL default '', + `status` enum('','changing','active','draft', 'reviewing', 'closed') NOT NULL default '', `subStatus` varchar(30) NOT NULL default '', `color` char(7) NOT NULL, `stage` enum('','wait','planned','projected','developing','developed','testing','tested','verified','released', 'closed') NOT NULL DEFAULT 'wait', @@ -1908,7 +1909,8 @@ INSERT INTO `zt_cron` (`m`, `h`, `dom`, `mon`, `dow`, `command`, `remark`, `type ('1', '0', '*', '*', '*', 'moduleName=ci&methodName=initQueue', '创建周期性任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), ('*/5', '*', '*', '*', '*', 'moduleName=ci&methodName=checkCompileStatus', '同步DevOps构建任务状态', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), ('*/5', '*', '*', '*', '*', 'moduleName=ci&methodName=exec', '执行DevOps构建任务', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), -('*/5', '*', '*', '*', '*', 'moduleName=mr&methodName=syncMR', '定时同步GitLab合并数据到禅道数据库', 'zentao', 1, 'normal', '0000-00-00 00:00:00'); +('*/5', '*', '*', '*', '*', 'moduleName=mr&methodName=syncMR', '定时同步GitLab合并数据到禅道数据库', 'zentao', 1, 'normal', '0000-00-00 00:00:00'), +('*/5', '*', '*', '*', '*', 'moduleName=compile&methodName=syncCompile', '定时同步构建记录', 'zentao', 1, 'normal', '0000-00-00 00:00:00'); INSERT INTO `zt_group` (`id`, `vision`, `name`, `role`, `desc`) VALUES (1, 'rnd', 'ADMIN', 'admin', 'for administrator'), @@ -7089,6 +7091,7 @@ CREATE TABLE IF NOT EXISTS `zt_feedback` ( `assignedTo` varchar(255) NOT NULL, `assignedDate` datetime NOT NULL, `feedbackBy` varchar(100) NOT NULL, + `repeatFeedback` mediumint(8) NOT NULL DEFAULT 0, `mailto` varchar(255) NOT NULL, `deleted` enum('0','1') NOT NULL DEFAULT '0', PRIMARY KEY (`id`) diff --git a/doc/CHANGELOG b/doc/CHANGELOG index f701b65279..eacaf00de5 100644 --- a/doc/CHANGELOG +++ b/doc/CHANGELOG @@ -1,3 +1,124 @@ +2022-08-25 17.6 +完成的需求 +开源版: +30520 用户需求和研发需求权限区分 +30718 我的地盘软件需求列表区块软件需求列表中将草稿状态调整为评审中,新增草稿状态的需求展示 +30721 贡献列表中用户需求和软件需求列表中将草稿状态调整为评审中 +30722 提软件需求和提用户需求页面中增加存为草稿按钮 +30724 草稿状态的需求详情中增加提交评审操作 +30725 软件需求和用户需求列表筛选标签中将草稿标签调整为评审中 +30726 软件需求和用户需求列表筛选标签中增加草稿标签 +30727 计划关联需求时搜索列表中将草稿调整为评审中 +30729 需求报表中按状态进行统计表中将草稿调整为评审中,新增草稿状态的统计 +30730 release关联需求时过滤掉草稿和评审中状态的需求 +30731 项目关联需求时过滤掉草稿和评审中状态的需求 +30732 项目需求列表中通过新增需求,可以展示草稿和评审中的需求 +30733 执行关联需求时过滤掉草稿和评审中状态的需求 +30734 执行需求列表中通过新增需求后可以展示草稿和评审中状态的需求 +30735 Scrum看板的需求类泳道中通过新增需求可以展示草稿和评审中状态的需求 +30736 专业研发看板的需求类泳道中通过新增需求可以展示草稿和评审中状态的需求 +30737 build关联需求时过滤掉草稿和评审中状态的需求 +30738 年度总结报表中需求状态分布中将草稿状态调整为评审中,新增草稿状态 +30739 产品统计报表中产品汇总表中将草稿状态调整为评审中,新增草稿状态 +30740 产品统计报表中产品需求状态分布表中将草稿状态调整为评审中,新增草稿状态 +30741 项目统计报表中项目需求状态分布表中将草稿状态调整为评审中,新增草稿状态 +30743 草稿状态对应需求阶段的规则 +31134 新增的草稿状态需求不受强制评审流程控制 +31251 实现草稿状态需求的提交评审功能 +34650 产品列表中用户需求和研发需求增加评审中状态 +34651 产品概况中其他信息模块软需维度优化 +34896 软件需求状态“已变更”调整为“变更中” +34897 用户需求状态“已变更”调整为“变更中” +34898 已关闭的软件需求激活后状态可以选择“激活”或者关闭前的状态 +34899 已关闭的用户需求激活后状态可以选择“激活”或者关闭前的状态 +34900 软需从草稿提交评审,根据不同评审结果进行后续处理 +34901 用需从草稿提交评审,根据不同评审结果进行后续处理 +34902 软件需求草稿状态时按钮调整 +34903 软件需求评审中状态时按钮调整 +34904 软件需求变更中状态时按钮调整 +34922 软件需求激活状态时按钮调整 +34924 用户需求草稿状态时按钮调整 +34925 用户需求评审中状态时按钮调整 +34926 用户需求变更中状态时按钮调整 +34927 用户需求激活状态时按钮调整 +34931 Bug转需求时可以保存为草稿 +34933 已关闭的需求激活后指派人不能选择closed +34934 需求变更评审时,系统根据需求不同评审结果进行后续处理 +34935 草稿需求评审时,评审人可选择确认通过、有待明确、拒绝 +35080 创建bug页面操作系统、浏览器支持多选 +35278 执行中转入任务页面增加分页展示 +35301 回收站的执行列表中增加所属项目字段 +35320 需求草稿状态时可以修改草稿内容 +35321 发起人对变更流程提交至”评审中“的需求选择撤销后需求根据状态回溯到不同内容 +35356 父阶段状态跟随子阶段状态自动更改 +35413 文档切换所属文档库时需要同步附件 +35821 回收站的任务列表中增加所属执行字段 +35887 关闭的bug指派人显示closed,不可编辑 +35908 在搜索表单中通过日期字段检索时去掉00:00:00的格式 +35935 修改零用例软需和矩阵的权限位置 +35998 更新bug中操作系统码值 +35999 更新bug中浏览器码值 +36111 bug编辑页面可以关联用例 +36184 测试单列表增加项目信息展示 +36188 需求按照优先级排序时,空值放最后 +36189 Bug按照优先级或严重程度排序时,空值放最后 +36190 用例关联bug和用例页增加分页 +36522 注册系统管理员的密码规则同系统中中级密码强度 +企业版: +28045 反馈关闭原因为重复时,增加重复反馈输入的选项 +30523 反馈转Bug时取消选择项目弹窗直接进入提Bug页面 +30912 地盘日志列表新建日志时可以搜索该用户参与的所有执行 +31984 反馈增加批量导入功能 +33940 反馈增加导出模板功能 +34296 提交反馈默认公开 +34844 组织日志菜单下增加增加未填写日志成员的选项 +34998 反馈导出时的时间支持精确到分秒 +35024 用户需求和研发需求的导出数据增加类别字段 +35083 执行甘特图支持在图上用连接的方式维护任务关系 +35861 甘特图全屏样式优化 +36185 执行甘特图查看任务关系维护按钮、设置按钮、甘特图按钮优化 +36581 任务工时明细表的横向滚动条置顶显示 +36618 有编辑他人反馈权限,可以批量编辑他人反馈 +旗舰版: +30432 瀑布项目设计功能类型支持自定义功能 +34682 资产库可以排序 +修复的Bug +26232 执行软件需求列表简单表格下横向滚动条显示遮挡 +26272 地盘待处理/贡献研发需求列表中,子需求的名称和所属产品未显示title +26380 复制项目时项目计划起止日期还是受项目集计划起止日期限制 +26448 列表设置弹窗界面高度需要优化 +26614 编辑项目页面计划起止日期/预算提示文案样式优化 +26618 创建测试任务时可以选择到已创建测试任务的需求 +26644 超出项目集计划起止日期提示换行 +26645 鼠标悬浮在附上时页面抖动 +25925 执行信息确认页面,日期选择后控件没有自动收起 +25929 敏捷项目和迭代设置中的白名单列表没有被复制 +25969 阶段信息确认页面没有显示已有的阶段负责人和阶段类型 +25974 阶段信息确认页面修改负责人后,没有按照修改后的负责人进行显示 +25989 英文下迭代信息确认页面表头显示优化 +25996 复制项目时,执行信息确认页面执行的状态默认设置应该为未开始 +25999 复制项目时,执行信息确认页面没有校验计划开始结束时间的先后 +26032 项目中发起评审,弹窗字段未居中 +26034 英文下项目中发起审批,文本换行 +26054 英德法下甘特图页面报错 +26057 英德法下甘特图页面没有显示分组选项 +26303 复制迭代时间控件一直显示 +26326 甘特图阶段工期计算错误 +26327 阶段甘特图中任务工期计算错误 +26365 项目计划评审页面自定义表单设置样式问题 +26580 评审项目计划页面甘特图切换为按指派给分组跳转到了阶段甘特图页面 +26638 甘特图拖动排序历史记录没有写中文语言项 +26655 瀑布项目设计三级导航不高亮了 +25961 迅捷页面用户授权异常 +26200 自定义库目录修改所属文档库到wiki库不能查看 +26221 导出数据的excel中,“抄送给”显示成了用户名 +26265 导入大数据测试用例页面有报错 +26278 导入文件超出PHP最大上传大小时没有提示 +26364 编辑项目页面有代码报错 +26371 导出的需求,用户名的显示不一致 +26424 导入用例页面无影响,提示PHPExcel原因 +26657 不能批量编辑他人反馈 + 2022-08-11 17.5 完成的需求 开源版: diff --git a/extension/lite/group/ext/lang/resource.php b/extension/lite/group/ext/lang/resource.php index 7fe9577dbd..45d77bcd6f 100644 --- a/extension/lite/group/ext/lang/resource.php +++ b/extension/lite/group/ext/lang/resource.php @@ -261,6 +261,7 @@ $lang->resource->story->delete = 'deleteAction'; $lang->resource->story->view = 'view'; $lang->resource->story->change = 'changeAction'; $lang->resource->story->review = 'reviewAction'; +$lang->resource->story->submitReview = 'submitReview'; $lang->resource->story->batchReview = 'batchReview'; $lang->resource->story->recall = 'recall'; $lang->resource->story->assignTo = 'assignAction'; @@ -289,6 +290,7 @@ $lang->story->methodOrder[25] = 'delete'; $lang->story->methodOrder[30] = 'view'; $lang->story->methodOrder[35] = 'change'; $lang->story->methodOrder[40] = 'review'; +$lang->story->methodOrder[44] = 'submitReview'; $lang->story->methodOrder[45] = 'batchReview'; $lang->story->methodOrder[50] = 'recall'; $lang->story->methodOrder[55] = 'close'; diff --git a/extension/lite/my/ext/view/task.html.php b/extension/lite/my/ext/view/task.html.php index 032ccfee7a..01f53c561d 100644 --- a/extension/lite/my/ext/view/task.html.php +++ b/extension/lite/my/ext/view/task.html.php @@ -95,8 +95,9 @@ } else { - $class = ($task->executionType == 'kanban') ? 'iframe' : ''; - echo html::a($this->createLink('task', 'view', "taskID=$task->id", '', true, $task->project), $task->name, null, "class='$class' data-width='80%' style='color: $task->color'"); + $onlybody = $task->executionType == 'kanban' ? true : ''; + $class = $task->executionType == 'kanban' ? 'iframe' : ''; + echo html::a($this->createLink('task', 'view', "taskID=$task->id", '', $onlybody, $task->project), $task->name, null, "class='$class' data-width='80%' style='color: $task->color'"); } ?> children)) echo '';?> diff --git a/extension/lite/story/ext/view/batchcreate.html.php b/extension/lite/story/ext/view/batchcreate.html.php index 99a33b5476..d94de7cee7 100644 --- a/extension/lite/story/ext/view/batchcreate.html.php +++ b/extension/lite/story/ext/view/batchcreate.html.php @@ -85,7 +85,8 @@ - save);?> + save, "id='saveButton'", 'btn btn-primary btn-wide');?> + story->saveDraft, "id='saveDraftButton'", 'btn btn-secondary btn-wide');?> diff --git a/extension/lite/story/ext/view/create.html.php b/extension/lite/story/ext/view/create.html.php index b2a5b6c85c..a918915f17 100644 --- a/extension/lite/story/ext/view/create.html.php +++ b/extension/lite/story/ext/view/create.html.php @@ -24,13 +24,21 @@

story->create;?>

+ story->checkForceReview()):?> +
+
+ /> + +
+
+
- - @@ -134,10 +134,6 @@ noticePasteImg) . "'");?> - - - - printExtendFields('', 'table', 'columns=4');?> @@ -147,7 +143,7 @@ @@ -162,10 +158,12 @@ diff --git a/extension/lite/story/ext/view/edit.html.php b/extension/lite/story/ext/view/edit.html.php index fa7458cbc8..bf24a2e266 100644 --- a/extension/lite/story/ext/view/edit.html.php +++ b/extension/lite/story/ext/view/edit.html.php @@ -14,14 +14,16 @@ app->getModuleRoot() . 'common/view/kindeditor.html.php';?> product);?> +id);?> children));?> story->moveChildrenTips);?> app->rawModule);?> story->module);?> - +story->notice->reviewerNotEmpty);?> story->feedbackSource); ?> +status);?>
@@ -34,7 +36,7 @@
-
+
@@ -43,12 +45,40 @@
- title, 'class="form-control disabled story-title" disabled="disabled"');?> + title, 'class="form-control disabled story-title"' . (strpos('draft,changing', $story->status) !== false ? '' : ' disabled="disabled"'));?>
+ status) !== false):?> +
+
story->reviewers;?>
+
+
+ story->checkForceReview()):?> +
+ +
+
+ +
+ /> + +
+
+
+ +
+ +
+ +
+
+
+
story->legendSpec;?>
-
spec;?>
+
+ status) !== false ? html::textarea('spec', htmlSpecialString($story->spec), "rows='5' class='form-control'") : $story->spec;?> +
printExtendFields($story, 'div', 'position=left');?>
@@ -61,7 +91,15 @@ lastEditedDate); echo html::hidden('product', $story->product); - echo html::submitButton($lang->save); + if(strpos('draft,changing', $story->status) !== false) + { + echo html::commonButton($lang->save, "id='saveButton'", 'btn btn-primary btn-wide'); + echo html::commonButton($story->status == 'changing' ? $lang->story->doNotSubmit : $lang->story->saveDraft, "id='saveDraftButton'", 'btn btn-secondary btn-wide'); + } + else + { + echo html::submitButton($lang->save); + } if(!isonlybody()) echo html::backButton(); ?>
@@ -85,7 +123,7 @@ echo ""; echo html::a($this->createLink('tree', 'browse', "rootID=$story->product&view=story¤tModuleID=0&branch=$story->branch", '', true), $lang->tree->manage, '', "class='text-primary' data-toggle='modal' data-type='iframe' data-width='95%'"); echo '  '; - echo html::a("javascript:void(0)", $lang->refresh, '', "class='refresh' onclick='loadProductModules($story->product)'"); + echo html::a("javascript:void(0)", $lang->refreshIcon, '', "class='refresh' title='$lang->refresh' onclick='loadProductModules($story->product)'"); echo ''; } ?> @@ -129,7 +167,7 @@
@@ -145,12 +183,13 @@ - + status == 'closed' ? $users + array('closed' => 'Closed') : $users;?> + - + status == 'reviewing'):?> - + status == 'closed'):?> diff --git a/extension/lite/story/ext/view/view.html.php b/extension/lite/story/ext/view/view.html.php index 894e92145c..c002b4c445 100644 --- a/extension/lite/story/ext/view/view.html.php +++ b/extension/lite/story/ext/view/view.html.php @@ -108,7 +108,14 @@ - +
story->module;?> +
"; echo html::a($this->createLink('tree', 'browse', "rootID=$productID&view=story¤tModuleID=0&branch=$branch", '', true), $lang->tree->manage, '', "class='text-primary' data-toggle='modal' data-type='iframe' data-width='90%'"); echo '  '; - echo html::a("javascript:void(0)", $lang->refresh, '', "class='refresh' onclick='loadProductModules($productID)'"); + echo html::a("javascript:void(0)", $lang->refreshIcon, '', "class='refresh' title='refresh' onclick='loadProductModules($productID)'"); echo '
'; } ?> @@ -48,21 +56,13 @@
story->reviewedBy;?>' id='reviewerBox'> +
+ story->checkForceReview() ? 'required' : '';?> + story->checkForceReview() ? '' : html::hidden('needNotReview', 1);?>
- PO : '', "class='form-control chosen' multiple");?> + PO : '', "class='form-control picker-select' multiple $required");?>
- story->checkForceReview()):?> -
- -
- /> - -
-
-
-
story->status;?>
story->legendAttatch;?>story->mailto;?>
- chooseUsersToMail}' multiple");?> + chooseUsersToMail}' multiple");?> fetch('my', 'buildContactLists');?>
- + + save, "id='saveButton'", 'btn btn-primary btn-wide');?> + story->saveDraft, "id='saveDraftButton'", 'btn btn-secondary btn-wide');?>
story->mailto;?>
- mailto), "class='form-control chosen' multiple");?> + mailto), "class='form-control picker-select' multiple");?> fetch('my', 'buildContactLists');?>
story->assignedTo;?>assignedTo, 'class="form-control chosen"');?>assignedTo, 'class="form-control chosen"');?>
story->reviewers;?>
id", $child, 'list', 'alter'); - common::printIcon('story', 'review', "storyID=$child->id", $child, 'list', 'search', '', 'iframe showinonlybody', true); + if(strpos('draft,changing', $child->status) !== false) + { + common::printIcon('story', 'submitReview', "storyID=$child->id", $child, 'list', 'sub-review', '', 'iframe showinonlybody', true); + } + else + { + common::printIcon('story', 'review', "storyID=$child->id", $child, 'list', 'search', '', 'iframe showinonlybody', true); + } common::printIcon('story', 'assignTo', "storyID=$child->id", $child, 'list', '', '', 'iframe showinonlybody', true); common::printIcon('story', 'close', "storyID=$child->id", $child, 'list', '', '', 'iframe showinonlybody', true); common::printIcon('story', 'activate', "storyID=$child->id", $child, 'list', '', '', 'iframe showinonlybody', true); @@ -134,7 +141,14 @@ deleted):?> id", $story, 'button', 'alter', '', 'showinonlybody'); - common::printIcon('story', 'review', "storyID=$story->id", $story, 'button', 'search', '', 'showinonlybody'); + if(strpos('draft,changing', $story->status) !== false) + { + common::printIcon('story', 'submitReview', "storyID=$story->id", $story, 'button', 'sub-review', '', 'iframe showinonlybody', true); + } + else + { + common::printIcon('story', 'review', "storyID=$story->id", $story, 'button', 'search', '', 'iframe showinonlybody', true); + } if($story->status == 'active' and $story->stage == 'wait' and $story->parent <= 0 and !isonlybody()) { $divideLang = $lang->story->subdivide; @@ -147,7 +161,7 @@ common::printIcon('story', 'close', "storyID=$story->id", $story, 'button', '', '', 'iframe showinonlybody', true); common::printIcon('story', 'activate', "storyID=$story->id", $story, 'button', '', '', 'iframe showinonlybody', true); - if($from == 'execution' and strpos('draft,closed', $story->status) === false) common::printIcon('task', 'create', "execution=$param&storyID=$story->id&moduleID=$story->module", $story, 'button', 'plus', '', 'showinonlybody'); + if($from == 'execution' and strpos('draft,reviewing,closed', $story->status) === false) common::printIcon('task', 'create', "execution=$param&storyID=$story->id&moduleID=$story->module", $story, 'button', 'plus', '', 'showinonlybody'); echo "
"; common::printIcon('story', 'edit', "storyID=$story->id", $story); @@ -221,7 +235,18 @@
story->legendMailto;?>mailto); foreach($mailto as $account) {if(empty($account)) continue; echo "" . zget($users, trim($account)) . '  '; }?> + mailto)) + { + foreach(explode(',', $story->mailto) as $account) + { + if(empty($account)) continue; + echo "" . zget($users, trim($account)) . '  '; + } + } + ?> +
diff --git a/framework/base/router.class.php b/framework/base/router.class.php index 224b8a4629..5df2970834 100644 --- a/framework/base/router.class.php +++ b/framework/base/router.class.php @@ -1461,6 +1461,17 @@ class baseRouter chdir(dirname($file2Included)); helper::import($file2Included); + /* Check file is encode by ioncube. */ + $isEncrypted = false; + if($isExt) + { + $fp = fopen($file2Included, 'r'); + $line1 = fgets($fp); + $line2 = fgets($fp); + fclose($fp); + if(strpos($line1, 'isDefaultValueAvailable()) + elseif(!$isEncrypted and $param->isDefaultValueAvailable()) { $default = $param->getDefaultValue(); } @@ -1540,11 +1551,12 @@ class baseRouter $_COOKIE = validater::filterParam($_COOKIE, 'cookie'); } } - + return true; } catch(EndResponseException $endResponseException) { echo $endResponseException->getContent(); + return false; } } @@ -2146,6 +2158,8 @@ class baseRouter public function loadModule() { try { + if(is_null($this->params) and !$this->setParams()) return false; + /* 调用该方法 Call the method. */ $module = $this->control; @@ -3190,6 +3204,7 @@ class ztSessionHandler implements SessionHandlerInterface * @access public * @return bool */ + #[\ReturnTypeWillChange] public function open($savePath, $sessionName) { $this->sessSavePath = $savePath; @@ -3202,6 +3217,7 @@ class ztSessionHandler implements SessionHandlerInterface * @access public * @return bool */ + #[\ReturnTypeWillChange] public function close() { return true; @@ -3214,6 +3230,7 @@ class ztSessionHandler implements SessionHandlerInterface * @access public * @return bool */ + #[\ReturnTypeWillChange] public function read($id) { $sessFile = $this->getSessionFile($id); @@ -3233,6 +3250,7 @@ class ztSessionHandler implements SessionHandlerInterface * @access public * @return bool */ + #[\ReturnTypeWillChange] public function write($id, $sessData) { $sessFile = $this->getSessionFile($id); @@ -3263,6 +3281,7 @@ class ztSessionHandler implements SessionHandlerInterface * @access public * @return bool */ + #[\ReturnTypeWillChange] public function destroy($id) { $sessFile = $this->getSessionFile($id); @@ -3279,6 +3298,7 @@ class ztSessionHandler implements SessionHandlerInterface * @access public * @return bool */ + #[\ReturnTypeWillChange] public function gc($maxlifeTime) { $time = time(); diff --git a/lib/front/front.class.php b/lib/front/front.class.php index 2d68563605..a2026338ac 100644 --- a/lib/front/front.class.php +++ b/lib/front/front.class.php @@ -57,6 +57,7 @@ class html extends baseHTML { $id = "id='$name'"; if(strpos($attrib, 'id=') !== false) $id = ''; + if(is_null($value)) $value = ''; $value = str_replace("'", ''', $value); $autocomplete = $autocomplete ? 'autocomplete="on"' : 'autocomplete="off"'; return "\n"; diff --git a/module/action/control.php b/module/action/control.php index 6edd4aed0d..4613347f2f 100755 --- a/module/action/control.php +++ b/module/action/control.php @@ -115,6 +115,33 @@ class action extends control $preferredType = $preferredType + $toPreferredType; } + /* Get the projects name of executions. */ + if($browseType == 'execution') + { + $this->loadModel('project'); + $projectIdList = array(); + foreach($trashes as $trash) $projectIdList[] = $trash->project; + $this->view->projectList = $this->project->getByIdList($projectIdList, 'all'); + } + + /* Get the products name of story. */ + if(strpos(',story,requirement,', ",$browseType,") !== false) + { + $this->loadModel('story'); + $storyIdList = array(); + foreach($trashes as $trash) $storyIdList[] = $trash->objectID; + $this->view->productList = $this->story->getByList($storyIdList, 'story', 'all'); + } + + /* Get the executions name of task. */ + if($browseType == 'task') + { + $this->app->loadLang('task'); + $this->loadModel('execution'); + $executionIdList = array(); + foreach($trashes as $trash) $executionIdList[] = $trash->execution; + $this->view->executionList = $this->execution->getByIdList($executionIdList, 'all'); + } /* Title and position. */ $this->view->title = $this->lang->action->trash; $this->view->position[] = $this->lang->action->trash; diff --git a/module/action/css/trash.css b/module/action/css/trash.css index e5b7a61042..2c21a2cced 100755 --- a/module/action/css/trash.css +++ b/module/action/css/trash.css @@ -6,3 +6,9 @@ .dropdown-menu .btn-active-text:hover .text:after {border-bottom: 0px;} #querybox #searchform{border-bottom: 1px solid #ddd; margin-bottom: 20px;} +td.flex {display: flex; flex-flow: row nowrap; justify-content: flex-start; align-items: center; margin-bottom: 0px;} +.flex span.label-danger {margin-left: 5px; min-width: 50px;} +[lang^=en] .flex span.label-danger {min-width: 52px;} +[lang^=de] .flex span.label-danger {min-width: 58px;} +[lang^=fr] .flex span.label-danger {min-width: 63px;} +.c-name > .text-ellipsis {text-overflow: clip;} diff --git a/module/action/lang/de.php b/module/action/lang/de.php index 86e6b08025..b0b3eed13b 100644 --- a/module/action/lang/de.php +++ b/module/action/lang/de.php @@ -221,6 +221,8 @@ $lang->action->desc->updatetolib = '$date, updated to ' . $lang->testca $lang->action->desc->adjusttasktowait = '$date, System Reminder: The task status will be set to Not Started as the consumed work hour is adjusted to 0. ' . "\n"; $lang->action->desc->reopen = '$date, reopened by $actor .' . "\n"; $lang->action->desc->merged = '$date, merged by $actor .' . "\n"; +$lang->action->desc->submitreview = '$date, submitted for review by $actor.' . "\n"; +$lang->action->desc->ganttmove = '$date, sort by $actor .' . "\n"; /* Used to describe the history of operations related to parent-child tasks. */ $lang->action->desc->createchildren = '$date, $actor created a child task $extra。' . "\n"; @@ -274,6 +276,7 @@ $lang->action->label->blocked = 'blocked '; $lang->action->label->resolved = 'resolved '; $lang->action->label->reviewed = 'reviewed '; $lang->action->label->recalled = 'recalled'; +$lang->action->label->recalledchange = 'undo changes'; $lang->action->label->moved = 'moved '; $lang->action->label->confirmed = 'Confirm Story'; $lang->action->label->bugconfirmed = 'Confirmed'; @@ -386,6 +389,7 @@ $lang->action->label->unlinkbug = 'unlink bugs from'; $lang->action->label->tolib = 'imported'; $lang->action->label->updatetolib = 'updated'; $lang->action->label->ganttmove = 'sorted'; +$lang->action->label->submitreview = 'submitted'; /* Dynamic information is grouped by object. */ $lang->action->dynamicAction = new stdclass; diff --git a/module/action/lang/en.php b/module/action/lang/en.php index f6c1e1ad00..57e0473102 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -221,6 +221,8 @@ $lang->action->desc->updatetolib = '$date, updated to ' . $lang->testca $lang->action->desc->adjusttasktowait = '$date, System Reminder: The task status will be set to Not Started as the consumed work hour is adjusted to 0. ' . "\n"; $lang->action->desc->reopen = '$date, reopened by $actor .' . "\n"; $lang->action->desc->merged = '$date, merged by $actor .' . "\n"; +$lang->action->desc->submitreview = '$date, submitted for review by $actor.' . "\n"; +$lang->action->desc->ganttmove = '$date, sort by $actor .' . "\n"; /* Used to describe the history of operations related to parent-child tasks. */ $lang->action->desc->createchildren = '$date, $actor created a child task $extra。' . "\n"; @@ -274,6 +276,7 @@ $lang->action->label->blocked = 'blocked '; $lang->action->label->resolved = 'resolved '; $lang->action->label->reviewed = 'reviewed '; $lang->action->label->recalled = 'recalled'; +$lang->action->label->recalledchange = 'undo changes'; $lang->action->label->moved = 'moved '; $lang->action->label->confirmed = 'confirmed Story '; $lang->action->label->bugconfirmed = 'confirmed'; @@ -386,6 +389,7 @@ $lang->action->label->unlinkbug = 'unlink bugs from'; $lang->action->label->tolib = 'imported'; $lang->action->label->updatetolib = 'updated'; $lang->action->label->ganttmove = 'sorted'; +$lang->action->label->submitreview = 'submitted'; /* Dynamic information is grouped by object. */ $lang->action->dynamicAction = new stdclass; diff --git a/module/action/lang/fr.php b/module/action/lang/fr.php index 3a2db412b6..fd061e4dee 100644 --- a/module/action/lang/fr.php +++ b/module/action/lang/fr.php @@ -221,6 +221,8 @@ $lang->action->desc->updatetolib = '$date, MàJ de ' . $lang->testcase- $lang->action->desc->adjusttasktowait = '$date, System Reminder: The task status will be set to Not Started as the consumed work hour is adjusted to 0. ' . "\n"; $lang->action->desc->reopen = '$date, reopened by $actor .' . "\n"; $lang->action->desc->merged = '$date, merged by $actor .' . "\n"; +$lang->action->desc->submitreview = '$date, submitted for review by $actor.' . "\n"; +$lang->action->desc->ganttmove = '$date, sort by $actor .' . "\n"; /* Used to describe the history of operations related to parent-child tasks. */ $lang->action->desc->createchildren = '$date, $actor a créé un sous-tâche $extra。' . "\n"; @@ -274,6 +276,7 @@ $lang->action->label->blocked = 'a bloqué '; $lang->action->label->resolved = 'a résolu '; $lang->action->label->reviewed = 'a revu '; $lang->action->label->recalled = 'recalled'; +$lang->action->label->recalledchange = 'undo changes'; $lang->action->label->moved = 'a déplacé '; $lang->action->label->confirmed = 'a confirmé Story '; $lang->action->label->bugconfirmed = 'a confirmé le Bug '; @@ -386,6 +389,7 @@ $lang->action->label->unlinkbug = 'unlink bugs from'; $lang->action->label->tolib = 'Importé'; $lang->action->label->updatetolib = 'MàJ'; $lang->action->label->ganttmove = 'sorted'; +$lang->action->label->submitreview = 'submitted'; /* Dynamic information is grouped by object. */ $lang->action->dynamicAction = new stdclass(); diff --git a/module/action/lang/vi.php b/module/action/lang/vi.php index fdaccee1bb..93814e6516 100644 --- a/module/action/lang/vi.php +++ b/module/action/lang/vi.php @@ -183,6 +183,7 @@ $lang->action->desc->syncproject = '$date, starting the execution sets the p $lang->action->desc->syncexecution = '$date, starting the task sets the execution status as Ongoing.' . "\n"; $lang->action->desc->reopen = '$date, reopened by $actor .' . "\n"; $lang->action->desc->merged = '$date, merged by $actor .' . "\n"; +$lang->action->desc->submitreview = '$date, submitted for review by $actor.' . "\n"; /* Used to describe the history of operations related to parent-child tasks. */ $lang->action->desc->createchildren = '$date, $actor created a child task $extra。' . "\n"; @@ -228,6 +229,7 @@ $lang->action->label->blocked = 'blocked '; $lang->action->label->resolved = 'resolved '; $lang->action->label->reviewed = 'reviewed '; $lang->action->label->recalled = 'recalled'; +$lang->action->label->recalledchange = 'undo changes'; $lang->action->label->moved = 'moved '; $lang->action->label->confirmed = 'confirmed Story '; $lang->action->label->bugconfirmed = 'Đã xác nhận'; @@ -303,6 +305,7 @@ $lang->action->label->syncprogram = 'start'; $lang->action->label->syncproject = 'start'; $lang->action->label->syncexecution = 'start'; $lang->action->label->startProgram = '(The start of the project sets the status of the program as Ongoing)'; +$lang->action->label->submitreview = 'submitted'; /* Dynamic information is grouped by object. */ $lang->action->dynamicAction = new stdclass; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index dee6daa7ef..60fc4a7905 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -221,6 +221,8 @@ $lang->action->desc->updatetolib = '$date, 由 $actor $lang->action->desc->adjusttasktowait = '$date, 系统判断由于消耗工时调整为0,将任务状态置为未开始。' . "\n"; $lang->action->desc->reopen = '$date, 由 $actor 重新打开。' . "\n"; $lang->action->desc->merged = '$date, 由 $actor 合并。' . "\n"; +$lang->action->desc->submitreview = '$date, 由 $actor 提交评审。' . "\n"; +$lang->action->desc->ganttmove = '$date, 由 $actor 排序。' . "\n"; /* 用来描述和父子任务相关的操作历史记录。*/ $lang->action->desc->createchildren = '$date, 由 $actor 创建子任务 $extra。' . "\n"; @@ -274,6 +276,7 @@ $lang->action->label->blocked = '阻塞了'; $lang->action->label->resolved = '解决了'; $lang->action->label->reviewed = '评审了'; $lang->action->label->recalled = '撤销评审'; +$lang->action->label->recalledchange = '撤销变更'; $lang->action->label->moved = '移动了'; $lang->action->label->confirmed = "确认了{$lang->SRCommon}"; $lang->action->label->bugconfirmed = '确认了'; @@ -386,6 +389,7 @@ $lang->action->label->unlinkbug = '移除BUG从'; $lang->action->label->tolib = '导入了'; $lang->action->label->updatetolib = '更新了'; $lang->action->label->ganttmove = '排序了'; +$lang->action->label->submitreview = '提交了评审'; /* 动态信息按照对象分组 */ $lang->action->dynamicAction = new stdclass(); diff --git a/module/action/model.php b/module/action/model.php index e6bc4c8142..f9d2155fee 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -510,7 +510,8 @@ class actionModel extends model elseif(($actionName == 'closed' and $action->objectType == 'story') or ($actionName == 'resolved' and $action->objectType == 'bug')) { $action->appendLink = ''; - if(strpos($action->extra, ':')!== false) + if(strpos($action->extra, '|') !== false) $action->extra = substr($action->extra, 0, strpos($action->extra, '|')); + if(strpos($action->extra, ':') !== false) { list($extra, $id) = explode(':', $action->extra); $action->extra = $extra; @@ -996,10 +997,10 @@ class actionModel extends model { $productCondition = ''; foreach(explode(',', $authedProducts) as $product) $productCondition = empty($productCondition) ? "(execution = '0' and project = '0' and (product LIKE '%,$product,%'" : "$productCondition OR product LIKE '%,$product,%'"; - $productCondition .= '))'; + if(!empty($productCondition)) $productCondition .= '))'; $projectCondition = "(execution = '0' and project != '0' and project " . helper::dbIN($authedProjects) . ')'; - $executionCondition = isset($authedExecutions) ? "(execution != 0 and execution " . helper::dbIN($authedExecutions) . ')' : ''; + $executionCondition = isset($authedExecutions) ? "(execution != 0 and execution " . helper::dbIN($authedExecutions) . ')' : "(execution != 0 and execution = '$executionID')"; } elseif($productID == 'all' and is_numeric($projectID)) { @@ -1010,7 +1011,7 @@ class actionModel extends model $productCondition = ''; foreach(array_keys($products) as $product) $productCondition = empty($productCondition) ? "(execution = '0' and project = '0' and (product LIKE '%,$product,%'" : "$productCondition OR product LIKE '%,$product,%'"; - $productCondition .= '))'; + if(!empty($productCondition)) $productCondition .= '))'; $projectCondition = "(execution = '0' and project = '$projectID')"; $executionCondition = "(execution != '0' and execution " . helper::dbIN($authedExecutions) . ')'; @@ -1024,7 +1025,7 @@ class actionModel extends model $authedProjects = array_intersect(array_keys($projects), explode(',', $authedProjects)); $authedExecutions = isset($authedExecutions) ? array_intersect(array_keys($executions), explode(',', $authedExecutions)) : array_keys($executions); - $productCondition = "product like '%,$productID,%'"; + $productCondition = "(execution = '0' and project = '0' and product like '%,$productID,%')"; $projectCondition = "(execution = '0' and project != '0' and project " . helper::dbIN($authedProjects) . ')'; $executionCondition = "(execution != '0' and execution " . helper::dbIN($authedExecutions) . ')'; } @@ -1539,7 +1540,11 @@ class actionModel extends model if($action->objectType == 'story') { $story = $this->loadModel('story')->getByID($action->objectID); - if(!empty($story)) $moduleName = $story->type; + if(!empty($story)) + { + $moduleName = $story->type; + $action->objectLink = helper::createLink('story', 'view', "id=$story->id&version=0¶m=0&storyType=$story->type"); + } } if($action->objectType == 'doclib') diff --git a/module/action/view/trash.html.php b/module/action/view/trash.html.php index 51ba347510..a4cc1ffe9e 100755 --- a/module/action/view/trash.html.php +++ b/module/action/view/trash.html.php @@ -82,6 +82,15 @@ action->objectType);?> idAB);?> action->objectName;?> + systemMode == 'new' and $currentObjectType == 'execution'):?> + lang->project->project;?> + + + lang->story->product;?> + + + lang->task->execution;?> + action->actor);?> action->date);?> actions;?> @@ -137,6 +146,30 @@ } ?> + systemMode == 'new' and $currentObjectType == 'execution'):?> + + project]->name;?> + project]->deleted):?> + lang->project->deleted;?> + + + + + + objectID]->productTitle;?> + objectID]->productDeleted):?> + lang->story->deleted;?> + + + + + + execution]->name;?> + execution]->deleted):?> + lang->execution->deleted;?> + + + actor);?> date;?> diff --git a/module/block/control.php b/module/block/control.php index 224ca9b8b4..e88e1bfca3 100644 --- a/module/block/control.php +++ b/module/block/control.php @@ -778,8 +778,9 @@ class block extends control */ public function printReleaseBlock() { - $this->session->set('releaseList', $this->app->getURI(true), 'product'); - $this->session->set('buildList', $this->app->getURI(true), 'execution'); + $uri = $this->createLink('my', 'index'); + $this->session->set('releaseList', $uri, 'product'); + $this->session->set('buildList', $uri, 'execution'); $this->app->loadLang('release'); $this->view->releases = $this->dao->select('t1.*,t2.name as productName,t3.name as buildName')->from(TABLE_RELEASE)->alias('t1') @@ -801,7 +802,7 @@ class block extends control */ public function printBuildBlock() { - $this->session->set('buildList', $this->app->getURI(true), 'execution'); + $this->session->set('buildList', $this->createLink('my', 'index'), 'execution'); $this->app->loadLang('build'); $builds = $this->dao->select('t1.*, t2.name as productName')->from(TABLE_BUILD)->alias('t1') diff --git a/module/block/view/taskblock.html.php b/module/block/view/taskblock.html.php index aacaca3a69..dc8423c01e 100644 --- a/module/block/view/taskblock.html.php +++ b/module/block/view/taskblock.html.php @@ -44,8 +44,11 @@ id);?> task->priList, $task->pri, $task->pri)?> - executionType == 'kanban') ? 'iframe' : '';?> - createLink('task', 'view', "taskID=$task->id", '', true, $task->project), $task->name, null, "class='$class' data-width='80%' data-toggle='modal'")?> + executionType == 'kanban' ? true : ''; + $class = $task->executionType == 'kanban' ? "class='iframe' data-toggle='modal'" : ''; + ?> + createLink('task', 'view', "taskID=$task->id", '', $onlybody, $task->project), $task->name, null, "$class data-width='80%'")?> estimate . $lang->execution->workHourUnit;?> deadline, 0, 4) > 0) echo $task->deadline;?> diff --git a/module/bug/control.php b/module/bug/control.php index bb3f353043..fd6740cc13 100755 --- a/module/bug/control.php +++ b/module/bug/control.php @@ -1152,16 +1152,20 @@ class bug extends control } if($bug->status == 'closed') $assignedToList['closed'] = 'Closed'; + $branch = $product->type == 'branch' ? ($bug->branch > 0 ? $bug->branch . ',0' : '0') : ''; + $productBugs = $this->bug->getProductBugPairs($productID, $branch); + $this->view->bug = $bug; $this->view->productID = $productID; $this->view->product = $product; + $this->view->productBugs = $productBugs; $this->view->productName = $this->products[$productID]; $this->view->plans = $this->loadModel('productplan')->getPairs($productID, $bug->branch, '', true); $this->view->projects = array(0 => '') + $this->product->getProjectPairsByProduct($productID, $bug->branch, $bug->project); $this->view->moduleOptionMenu = $moduleOptionMenu; $this->view->currentModuleID = $currentModuleID; $this->view->executions = array(0 => '') + $this->product->getExecutionPairsByProduct($bug->product, $bug->branch, 'id_desc', $bug->project); - $this->view->stories = $bug->execution ? $this->story->getExecutionStoryPairs($bug->execution) : $this->story->getProductStoryPairs($bug->product, $bug->branch); + $this->view->stories = $bug->execution ? $this->story->getExecutionStoryPairs($bug->execution) : $this->story->getProductStoryPairs($bug->product, $bug->branch, 0, 'all', 'id_desc', 0, 'full', 'story', false); $this->view->branchOption = $branchOption; $this->view->branchTagOption = $branchTagOption; $this->view->tasks = $this->task->getExecutionTaskPairs($bug->execution); @@ -1301,6 +1305,7 @@ class bug extends control $branchIdList = array(); $projectIdList = array(); $executionIdList = array(); + $productBugList = array(); foreach($bugs as $bug) { $projectIdList[$bug->project] = $bug->project; @@ -1309,6 +1314,10 @@ class bug extends control $branchIdList[$bug->product][$bug->branch] = $bug->branch; if(!isset($modules[$bug->product][$bug->branch]) and isset($modules[$bug->product])) $modules[$bug->product][$bug->branch] = $modules[$bug->product][0] + $this->tree->getModulesName($bug->module); + + $bugProduct = isset($productList) ? $productList[$bug->product] : $product; + $branch = $bugProduct->type == 'branch' ? ($bug->branch > 0 ? $bug->branch . ',0' : '0') : ''; + if(!isset($productBugList[$bug->product][$bug->branch])) $productBugList[$bug->product][$bug->branch] = $this->bug->getProductBugPairs($bug->product, $branch); } /* Get assigned to member. */ @@ -1388,6 +1397,7 @@ class bug extends control $this->view->users = $users; $this->view->modules = $modules; $this->view->branchTagOption = $branchTagOption; + $this->view->productBugList = $productBugList; $this->display(); } @@ -1797,17 +1807,22 @@ class bug extends control if(!isset($users[$assignedTo])) $assignedTo = $this->bug->getModuleOwner($bug->module, $productID); unset($this->lang->bug->resolutionList['tostory']); + $product = $this->loadModel('product')->getById($productID); + $branch = $product->type == 'branch' ? ($bug->branch > 0 ? $bug->branch . ',0' : '0') : ''; + $productBugs = $this->bug->getProductBugPairs($productID, $branch); + $this->bug->checkBugExecutionPriv($bug); $this->qa->setMenu($this->products, $productID, $bug->branch); - $this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->resolve; - $this->view->bug = $bug; - $this->view->users = $users; - $this->view->assignedTo = $assignedTo; - $this->view->executions = $this->loadModel('product')->getExecutionPairsByProduct($productID, $bug->branch ? "0,{$bug->branch}" : 0, 'id_desc', $projectID); - $this->view->builds = $this->loadModel('build')->getBuildPairs($productID, $bug->branch, 'withbranch'); - $this->view->actions = $this->action->getList('bug', $bugID); - $this->view->execution = isset($execution) ? $execution : ''; + $this->view->title = $this->products[$productID] . $this->lang->colon . $this->lang->bug->resolve; + $this->view->bug = $bug; + $this->view->users = $users; + $this->view->assignedTo = $assignedTo; + $this->view->productBugs = $productBugs; + $this->view->executions = $this->loadModel('product')->getExecutionPairsByProduct($productID, $bug->branch ? "0,{$bug->branch}" : 0, 'id_desc', $projectID); + $this->view->builds = $this->loadModel('build')->getBuildPairs($productID, $bug->branch, 'withbranch'); + $this->view->actions = $this->action->getList('bug', $bugID); + $this->view->execution = isset($execution) ? $execution : ''; $this->display(); } diff --git a/module/bug/css/view.css b/module/bug/css/view.css index 00eb876f92..9c7f59111b 100644 --- a/module/bug/css/view.css +++ b/module/bug/css/view.css @@ -7,3 +7,4 @@ .select-project-modal .modal-body {right: 15px;} .osContent, .browserContent {margin: 0 0 5px;} .browserContent {margin-left: -4px;} +.resolution {white-space: nowrap; overflow: hidden;} diff --git a/module/bug/js/batchedit.js b/module/bug/js/batchedit.js index 42770c7cfc..0b15187841 100644 --- a/module/bug/js/batchedit.js +++ b/module/bug/js/batchedit.js @@ -77,4 +77,10 @@ $(function() { hiddenRequireFields(); }); + + $('select[id^="duplicateBugs"]').picker( + { + disableEmptySearch : true, + dropWidth : 'auto' + }); }); diff --git a/module/bug/js/common.js b/module/bug/js/common.js index 3ddab97a57..e6e93f396c 100644 --- a/module/bug/js/common.js +++ b/module/bug/js/common.js @@ -678,7 +678,7 @@ function setStories(moduleID, productID, storyID) if(typeof(branch) == 'undefined') branch = 0; var executionID = $('#execution').val(); if(typeof(executionID) == 'undefined') executionID = 0; - link = createLink('story', 'ajaxGetProductStories', 'productID=' + productID + '&branch=' + branch + '&moduleID=' + moduleID + '&storyID=' + storyID + '&onlyOption=false&status=&limit=0&type=full&hasParent=1&executionID=' + executionID); + link = createLink('story', 'ajaxGetProductStories', 'productID=' + productID + '&branch=' + branch + '&moduleID=' + moduleID + '&storyID=' + storyID + '&onlyOption=false&status=&limit=0&type=full&hasParent=0&executionID=' + executionID); $.get(link, function(stories) { if(!stories) stories = ''; diff --git a/module/bug/js/edit.js b/module/bug/js/edit.js index 2669cde048..f9003597c9 100644 --- a/module/bug/js/edit.js +++ b/module/bug/js/edit.js @@ -19,6 +19,12 @@ $(function() } }); } + + $('#duplicateBug').picker( + { + disableEmptySearch : true, + dropWidth : 'auto' + }); }); /** diff --git a/module/bug/js/resolve.js b/module/bug/js/resolve.js index 884490f541..8afea5743c 100644 --- a/module/bug/js/resolve.js +++ b/module/bug/js/resolve.js @@ -45,4 +45,10 @@ $(function() $('#newBuildExecutionBox').addClass('hidden'); } }) + + $('#duplicateBug').picker( + { + disableEmptySearch : true, + dropWidth : 'auto' + }); }) diff --git a/module/bug/lang/de.php b/module/bug/lang/de.php index 4a4999204f..ae67b3dac0 100644 --- a/module/bug/lang/de.php +++ b/module/bug/lang/de.php @@ -176,6 +176,7 @@ $lang->bug->labelPostponed = 'Postponed'; $lang->bug->changed = 'Changed'; $lang->bug->storyChanged = 'Story Changed'; $lang->bug->linkMR = 'Related MRs'; +$lang->bug->duplicateTip = 'Please enter keyword search'; /* Page tags. */ $lang->bug->lblAssignedTo = 'Bearbeiter'; @@ -416,6 +417,7 @@ $lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed; $lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe; $lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe; $lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe; + $lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved; $lang->bug->featureBar['browse']['more'] = $lang->more; diff --git a/module/bug/lang/en.php b/module/bug/lang/en.php index 9a67e54d8c..f29895386a 100644 --- a/module/bug/lang/en.php +++ b/module/bug/lang/en.php @@ -77,7 +77,7 @@ $lang->bug->deadlineAB = 'Deadline'; $lang->bug->plan = 'Plan'; $lang->bug->closedBy = 'ClosedBy'; $lang->bug->closedDate = 'ClosedDate'; -$lang->bug->duplicateBug = 'Duplicated Bug ID'; +$lang->bug->duplicateBug = 'Duplicated Bug'; $lang->bug->lastEditedBy = 'EditedBy'; $lang->bug->linkBug = 'Linked Bugs'; $lang->bug->linkBugs = 'Link Bug'; @@ -176,6 +176,7 @@ $lang->bug->labelPostponed = 'Postponed'; $lang->bug->changed = 'Changed'; $lang->bug->storyChanged = 'Story Changed'; $lang->bug->linkMR = 'Related MRs'; +$lang->bug->duplicateTip = 'Please enter keyword search'; /* Page tags. */ $lang->bug->lblAssignedTo = 'AssignTo'; @@ -416,6 +417,7 @@ $lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed; $lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe; $lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe; $lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe; + $lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved; $lang->bug->featureBar['browse']['more'] = $lang->more; diff --git a/module/bug/lang/fr.php b/module/bug/lang/fr.php index 6ea57d780c..1d8df84e71 100644 --- a/module/bug/lang/fr.php +++ b/module/bug/lang/fr.php @@ -77,7 +77,7 @@ $lang->bug->deadlineAB = 'Butoir'; $lang->bug->plan = 'Plan'; $lang->bug->closedBy = 'Fermé par'; $lang->bug->closedDate = 'Date Fermeture'; -$lang->bug->duplicateBug = 'Bug ID en doublon'; +$lang->bug->duplicateBug = 'Bug en doublon'; $lang->bug->lastEditedBy = 'Edité par'; $lang->bug->linkBug = 'Bugs Liés'; $lang->bug->linkBugs = 'Associer Bug'; @@ -176,6 +176,7 @@ $lang->bug->labelPostponed = 'Postponed'; $lang->bug->changed = 'Changed'; $lang->bug->storyChanged = 'Story Changed'; $lang->bug->linkMR = 'Related MRs'; +$lang->bug->duplicateTip = 'Please enter keyword search'; /* Page tags. */ $lang->bug->lblAssignedTo = 'Affecté à'; @@ -416,6 +417,7 @@ $lang->bug->featureBar['browse']['unclosed'] = $lang->bug->unclosed; $lang->bug->featureBar['browse']['openedbyme'] = $lang->bug->openedByMe; $lang->bug->featureBar['browse']['assigntome'] = $lang->bug->assignToMe; $lang->bug->featureBar['browse']['resolvedbyme'] = $lang->bug->resolvedByMe; + $lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved; $lang->bug->featureBar['browse']['more'] = $lang->more; diff --git a/module/bug/lang/zh-cn.php b/module/bug/lang/zh-cn.php index e4ea8310b7..9a6ad14c53 100644 --- a/module/bug/lang/zh-cn.php +++ b/module/bug/lang/zh-cn.php @@ -77,7 +77,7 @@ $lang->bug->deadlineAB = '截止'; $lang->bug->plan = '所属' . '计划'; $lang->bug->closedBy = '由谁关闭'; $lang->bug->closedDate = '关闭日期'; -$lang->bug->duplicateBug = '重复ID'; +$lang->bug->duplicateBug = '重复Bug'; $lang->bug->lastEditedBy = '最后修改者'; $lang->bug->linkBug = '相关Bug'; $lang->bug->linkBugs = '关联相关Bug'; @@ -176,6 +176,7 @@ $lang->bug->labelPostponed = '被延期'; $lang->bug->changed = '已变动'; $lang->bug->storyChanged = '需求变动'; $lang->bug->linkMR = '相关合并请求'; +$lang->bug->duplicateTip = '请输入关键字'; /* 页面标签。*/ $lang->bug->lblAssignedTo = '当前指派'; @@ -420,6 +421,7 @@ $lang->bug->featureBar['browse']['assignedbyme'] = $lang->bug->assignedByMe; $lang->bug->featureBar['browse']['unresolved'] = $lang->bug->unResolved; $lang->bug->featureBar['browse']['more'] = $lang->more; + $lang->bug->moreSelects['unconfirmed'] = $lang->bug->unconfirmed; $lang->bug->moreSelects['assigntonull'] = $lang->bug->assignToNull; $lang->bug->moreSelects['longlifebugs'] = $lang->bug->longLifeBugs; diff --git a/module/bug/model.php b/module/bug/model.php index 1ea50fc5a5..66472d082b 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -384,6 +384,9 @@ class bugModel extends model $browseType = ($browseType == 'bymodule' and $this->session->bugBrowseType and $this->session->bugBrowseType != 'bysearch') ? $this->session->bugBrowseType : $browseType; $browseType = $browseType == 'bybranch' ? 'bymodule' : $browseType; + if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort); + if(strpos($sort, 'severity_') !== false) $sort = str_replace('severity_', 'severityOrder_', $sort); + /* Get bugs by browse type. */ $bugs = array(); if($browseType == 'all') $bugs = $this->getAllBugs($productIDList, $branch, $modules, $executions, $sort, $pager, $projectID); @@ -483,7 +486,7 @@ class bugModel extends model */ public function getModuleBugs($productIDList, $branch = 0, $moduleIdList = 0, $executions = array(), $orderBy = 'id_desc', $pager = null, $projectID = 0) { - return $this->dao->select('*')->from(TABLE_BUG) + return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG) ->where('product')->in($productIDList) ->beginIF($branch !== 'all')->andWhere('branch')->eq($branch)->fi() ->beginIF(!empty($moduleIdList))->andWhere('module')->in($moduleIdList)->fi() @@ -506,7 +509,8 @@ class bugModel extends model */ public function getPlanBugs($planID, $status = 'all', $orderBy = 'id_desc', $pager = null) { - $bugs = $this->dao->select('*')->from(TABLE_BUG) + if(strpos($orderBy, 'pri_') !== false) $orderBy = str_replace('pri_', 'priOrder_', $orderBy); + $bugs = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder")->from(TABLE_BUG) ->where('plan')->eq((int)$planID) ->beginIF(!$this->app->user->admin)->andWhere('execution')->in('0,' . $this->app->user->view->sprints)->fi() ->beginIF($status != 'all')->andWhere('status')->in($status)->fi() @@ -1125,6 +1129,7 @@ class bugModel extends model ->setDefault('assignedDate', $now) ->setDefault('resolvedDate', $now) ->setDefault('assignedTo', $oldBug->openedBy) + ->setDefault('duplicateBug', 0) ->removeIF($this->post->resolution != 'duplicate', 'duplicateBug') ->stripTags($this->config->bug->editor->resolve['id'], $this->config->allowedTags) ->remove('files,labels') @@ -1565,7 +1570,6 @@ class bugModel extends model $bugCount = $this->dao->select("count(id) as num, date_format($field, '%m/%d') as date")->from(TABLE_BUG) ->where('product')->eq($productID) ->andWhere($field)->ne('0000-00-00 00:00:00') - ->andWhere($field)->ne('') ->andWhere('deleted')->eq(0) ->andWhere($field)->between($startDate, $endDate . ' 23:50:59') ->groupBy('date') @@ -1713,8 +1717,7 @@ class bugModel extends model $moduleName = $this->app->rawMethod == 'work' ? 'workBug' : 'contributeBug'; $queryName = $moduleName . 'Query'; $formName = $moduleName . 'Form'; - - $bugIDList = array(); + $bugIDList = array(); if($moduleName == 'contributeBug') { $bugsAssignedByMe = $this->loadModel('my')->getAssignedByMe($account, 0, '', $orderBy, 'bug'); @@ -1742,7 +1745,7 @@ class bugModel extends model $query = preg_replace('/`(\w+)`/', 't1.`$1`', $query); if($type != 'bySearch' and !$this->loadModel('common')->checkField(TABLE_BUG, $type)) return array(); - return $this->dao->select('t1.*,t2.name as productName')->from(TABLE_BUG)->alias('t1') + return $this->dao->select("t1.*,t2.name as productName, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, IF(t1.`severity` = 0, {$this->config->maxPriValue}, t1.`severity`) as severityOrder")->from(TABLE_BUG)->alias('t1') ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') ->where('t1.deleted')->eq(0) ->andWhere('t2.deleted')->eq('0') @@ -1823,6 +1826,9 @@ class bugModel extends model public function getProjectBugs($projectID, $productID = 0, $branchID = 0, $build = 0, $type = '', $param = 0, $orderBy = 'id_desc', $excludeBugs = '', $pager = null) { $type = strtolower($type); + if(strpos($orderBy, 'pri_') !== false) $orderBy = str_replace('pri_', 'priOrder_', $orderBy); + if(strpos($orderBy, 'severity_') !== false) $orderBy = str_replace('severity_', 'severityOrder_', $orderBy); + if($type == 'bysearch') { $queryID = (int)$param; @@ -1839,7 +1845,7 @@ class bugModel extends model $bugQuery = $this->getBugQuery($this->session->projectBugQuery); - $bugs = $this->dao->select('*')->from(TABLE_BUG) + $bugs = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG) ->where($bugQuery) ->andWhere('project')->eq((int)$projectID) ->andWhere('deleted')->eq(0) @@ -1852,7 +1858,7 @@ class bugModel extends model } else { - $bugs = $this->dao->select('t1.*')->from(TABLE_BUG)->alias('t1') + $bugs = $this->dao->select("t1.*, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, IF(t1.`severity` = 0, {$this->config->maxPriValue}, t1.`severity`) as severityOrder")->from(TABLE_BUG)->alias('t1') ->leftJoin(TABLE_MODULE)->alias('t2')->on('t1.module=t2.id') ->where('t1.deleted')->eq(0) ->beginIF(empty($build))->andWhere('t1.project')->eq($projectID)->fi() @@ -1891,6 +1897,9 @@ class bugModel extends model public function getExecutionBugs($executionID, $productID = 0, $branchID = 'all', $build = 0, $type = '', $param = 0, $orderBy = 'id_desc', $excludeBugs = '', $pager = null) { $type = strtolower($type); + if(strpos($orderBy, 'pri_') !== false) $orderBy = str_replace('pri_', 'priOrder_', $orderBy); + if(strpos($orderBy, 'severity_') !== false) $orderBy = str_replace('severity_', 'severityOrder_', $orderBy); + if($type == 'bysearch') { $queryID = (int)$param; @@ -1907,7 +1916,7 @@ class bugModel extends model $bugQuery = $this->getBugQuery($this->session->executionBugQuery); - $bugs = $this->dao->select('*')->from(TABLE_BUG) + $bugs = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG) ->where($bugQuery) ->andWhere('execution')->eq((int)$executionID) ->andWhere('deleted')->eq(0) @@ -1920,7 +1929,7 @@ class bugModel extends model } else { - $bugs = $this->dao->select('t1.*')->from(TABLE_BUG)->alias('t1') + $bugs = $this->dao->select("t1.*, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, IF(t1.`severity` = 0, {$this->config->maxPriValue}, t1.`severity`) as severityOrder")->from(TABLE_BUG)->alias('t1') ->leftJoin(TABLE_MODULE)->alias('t2')->on('t1.module=t2.id') ->where('t1.deleted')->eq(0) ->beginIF(!empty($productID) and $branchID !== 'all')->andWhere('t1.branch')->eq($branchID)->fi() @@ -1985,16 +1994,18 @@ class bugModel extends model /** * get Product Bug Pairs * - * @param int $productID + * @param int $productID + * @param int|string $branch * @access public * @return void */ - public function getProductBugPairs($productID) + public function getProductBugPairs($productID, $branch = '') { $bugs = array('' => ''); $data = $this->dao->select('id, title')->from(TABLE_BUG) ->where('product')->eq((int)$productID) ->beginIF(!$this->app->user->admin)->andWhere('execution')->in('0,' . $this->app->user->view->sprints)->fi() + ->beginIF($branch !== '')->andWhere('branch')->in($branch)->fi() ->andWhere('deleted')->eq(0) ->orderBy('id desc') ->fetchAll(); @@ -2542,7 +2553,7 @@ class bugModel extends model */ public function getAllBugs($productIDList, $branch, $modules, $executions, $orderBy, $pager = null, $projectID = 0) { - $bugs = $this->dao->select('t1.*, t2.title as planTitle')->from(TABLE_BUG)->alias('t1') + $bugs = $this->dao->select("t1.*, t2.title as planTitle, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, IF(t1.`severity` = 0, {$this->config->maxPriValue}, t1.`severity`) as severityOrder")->from(TABLE_BUG)->alias('t1') ->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id') ->where('t1.product')->in($productIDList) ->andWhere('t1.execution')->in(array_keys($executions)) @@ -2573,7 +2584,9 @@ class bugModel extends model */ public function getByAssigntome($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID) { - return $this->dao->findByAssignedTo($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->in($productIDList) + return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG) + ->where('assignedTo')->eq($this->app->user->account) + ->andWhere('product')->in($productIDList) ->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi() ->beginIF($modules)->andWhere('module')->in($modules)->fi() ->beginIF($projectID)->andWhere('project')->eq($projectID)->fi() @@ -2598,7 +2611,9 @@ class bugModel extends model */ public function getByOpenedbyme($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID) { - return $this->dao->findByOpenedBy($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->in($productIDList) + return $this->dao->select("*,IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG) + ->where('openedBy')->eq($this->app->user->account) + ->andWhere('product')->in($productIDList) ->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi() ->beginIF($modules)->andWhere('module')->in($modules)->fi() ->beginIF($projectID)->andWhere('project')->eq($projectID)->fi() @@ -2623,7 +2638,9 @@ class bugModel extends model */ public function getByResolvedbyme($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID) { - return $this->dao->findByResolvedBy($this->app->user->account)->from(TABLE_BUG)->andWhere('product')->in($productIDList) + return $this->dao->select("*,IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG) + ->where('resolvedBy')->eq($this->app->user->account) + ->andWhere('product')->in($productIDList) ->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi() ->beginIF($modules)->andWhere('module')->in($modules)->fi() ->beginIF($projectID)->andWhere('project')->eq($projectID)->fi() @@ -2649,7 +2666,9 @@ class bugModel extends model public function getByAssigntonull($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID) { - return $this->dao->findByAssignedTo('')->from(TABLE_BUG)->andWhere('product')->in($productIDList) + return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG) + ->where('assignedTo')->eq('') + ->andWhere('product')->in($productIDList) ->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi() ->beginIF($modules)->andWhere('module')->in($modules)->fi() ->beginIF($projectID)->andWhere('project')->eq($projectID)->fi() @@ -2674,7 +2693,7 @@ class bugModel extends model */ public function getUnconfirmed($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID) { - return $this->dao->select('*')->from(TABLE_BUG) + return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG) ->where('product')->in($productIDList) ->andWhere('execution')->in(array_keys($executions)) ->andWhere('deleted')->eq(0) @@ -2702,7 +2721,7 @@ class bugModel extends model */ public function getOverdueBugs($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID) { - return $this->dao->select('*')->from(TABLE_BUG) + return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG) ->where('product')->in($productIDList) ->andWhere('execution')->in(array_keys($executions)) ->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi() @@ -2732,7 +2751,7 @@ class bugModel extends model */ public function getByStatus($productIDList, $branch, $modules, $executions, $status, $orderBy, $pager, $projectID) { - return $this->dao->select('*')->from(TABLE_BUG) + return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG) ->where('product')->in($productIDList) ->andWhere('execution')->in(array_keys($executions)) ->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi() @@ -2763,7 +2782,9 @@ class bugModel extends model public function getByLonglifebugs($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID) { $lastEditedDate = date(DT_DATE1, time() - $this->config->bug->longlife * 24 * 3600); - return $this->dao->findByLastEditedDate("<", $lastEditedDate)->from(TABLE_BUG)->andWhere('product')->in($productIDList) + return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG) + ->where('lastEditedDate')->lt($lastEditedDate) + ->andWhere('product')->in($productIDList) ->andWhere('execution')->in(array_keys($executions)) ->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi() ->beginIF($modules)->andWhere('module')->in($modules)->fi() @@ -2789,7 +2810,9 @@ class bugModel extends model */ public function getByPostponedbugs($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID) { - return $this->dao->findByResolution('postponed')->from(TABLE_BUG)->andWhere('product')->in($productIDList) + return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG) + ->where('resolution')->eq('postponed') + ->andWhere('product')->in($productIDList) ->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi() ->beginIF($modules)->andWhere('module')->in($modules)->fi() ->beginIF($projectID)->andWhere('project')->eq($projectID)->fi() @@ -2814,7 +2837,7 @@ class bugModel extends model */ public function getByNeedconfirm($productIDList, $branch, $modules, $executions, $orderBy, $pager, $projectID) { - return $this->dao->select('t1.*, t2.title AS storyTitle')->from(TABLE_BUG)->alias('t1') + return $this->dao->select("t1.*, t2.title AS storyTitle, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, IF(t1.`severity` = 0, {$this->config->maxPriValue}, t1.`severity`) as severityOrder")->from(TABLE_BUG)->alias('t1') ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') ->where("t2.status = 'active'") ->andWhere('t1.product')->in($productIDList) @@ -2846,7 +2869,7 @@ class bugModel extends model public function getByAssignedbyme($productIDList, $branch, $modules, $executions, $sort, $pager, $projectID) { $actionIDList = $this->dao->select('objectID')->from(TABLE_ACTION)->where('objectType')->eq('bug')->andWhere('action')->eq('assigned')->andWhere('actor')->eq($this->app->user->account)->fetchPairs('objectID', 'objectID'); - return $this->dao->select('*')->from(TABLE_BUG) + return $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG) ->where('product')->in($productIDList) ->beginIF($branch !== 'all')->andWhere('branch')->in($branch)->fi() ->beginIF($modules)->andWhere('module')->in($modules)->fi() @@ -2918,7 +2941,7 @@ class bugModel extends model if($branch !== 'all' and strpos($bugQuery, '`branch` =') === false) $bugQuery .= " AND `branch` in('0','$branch')"; if(strpos($bugQuery, $allBranch) !== false) $bugQuery = str_replace($allBranch, '1', $bugQuery); - $bugs = $this->dao->select('*')->from(TABLE_BUG)->where($bugQuery) + $bugs = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)->where($bugQuery) ->beginIF(!$this->app->user->admin)->andWhere('execution')->in('0,' . $this->app->user->view->sprints)->fi() ->beginIF($excludeBugs)->andWhere('id')->notIN($excludeBugs)->fi() @@ -2950,7 +2973,7 @@ class bugModel extends model */ public function getReviewBugs($productIDList, $branch, $modules, $executions, $orderBy, $pager = null, $projectID = 0) { - $bugs = $this->dao->select('t1.*, t2.title as planTitle')->from(TABLE_BUG)->alias('t1') + $bugs = $this->dao->select("t1.*, t2.title as planTitle, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG)->alias('t1') ->leftJoin(TABLE_PRODUCTPLAN)->alias('t2')->on('t1.plan = t2.id') ->where('t1.product')->in($productIDList) ->andWhere('t1.execution')->in(array_keys($executions)) diff --git a/module/bug/view/batchedit.html.php b/module/bug/view/batchedit.html.php index 533edde8db..f1e9c9c348 100644 --- a/module/bug/view/batchedit.html.php +++ b/module/bug/view/batchedit.html.php @@ -139,11 +139,11 @@ >keywords, 'class=form-control');?> ' style='overflow:visible'>resolvedBy, "class='form-control picker-select' data-drop-width='auto'");?> > - +
resolution, "class='form-control' onchange=setDuplicate(this.value,$bugID)");?> ' resolution != 'duplicate') echo "style='display:none'";?>> - bug->duplicateBug}'");?> + product][$bug->branch], $bug->duplicateBug, "class='form-control' placeholder='{$lang->bug->duplicateTip}'");?>
diff --git a/module/bug/view/browse.html.php b/module/bug/view/browse.html.php index 248a4d7f4a..79c85912a5 100644 --- a/module/bug/view/browse.html.php +++ b/module/bug/view/browse.html.php @@ -71,16 +71,16 @@ $currentBrowseType = isset($lang->bug->mySelects[$browseType]) && in_array($brow { $moreLabel = $lang->more; $moreLabelActive = ''; - if(isset($lang->bug->moreSelects[$browseType])) + if(isset($lang->bug->moreSelects[$this->session->bugBrowseType])) { - $moreLabel = "{$lang->bug->moreSelects[$browseType]} {$pager->recTotal}"; + $moreLabel = "{$lang->bug->moreSelects[$this->session->bugBrowseType]} {$pager->recTotal}"; $moreLabelActive = 'btn-active-text'; } echo "
{$moreLabel} "; echo "
'; diff --git a/module/bug/view/edit.html.php b/module/bug/view/edit.html.php index 6e41532080..23aaf191cf 100644 --- a/module/bug/view/edit.html.php +++ b/module/bug/view/edit.html.php @@ -265,7 +265,7 @@ if($this->app->tab == 'project') js::set('objectID', $bug->project); resolution != 'duplicate') echo "style='display:none'";?>> bug->duplicateBug;?> - duplicateBug, 'class=form-control');?> + duplicateBug, "class='form-control' placeholder='{$lang->bug->duplicateTip}'");?> bug->closedBy;?> diff --git a/module/bug/view/resolve.html.php b/module/bug/view/resolve.html.php index e665c4c250..12e1e27e31 100644 --- a/module/bug/view/resolve.html.php +++ b/module/bug/view/resolve.html.php @@ -38,7 +38,7 @@ js::set('productID' , $bug->product); bug->duplicateBug;?> - + bug->duplicateTip}'");?> bug->resolvedBuild;?> diff --git a/module/bug/view/view.html.php b/module/bug/view/view.html.php index 2b78e900a7..02a731de39 100644 --- a/module/bug/view/view.html.php +++ b/module/bug/view/view.html.php @@ -262,7 +262,14 @@ bug->mailto;?> - mailto)); foreach($mailto as $account) echo ' ' . zget($users, $account); ?> + + mailto)) + { + foreach(explode(',', str_replace(' ', '', $bug->mailto)) as $account) echo ' ' . zget($users, $account); + } + ?> + @@ -348,10 +355,10 @@ bug->resolution;?> - + bug->resolutionList[$bug->resolution]) ? $lang->bug->resolutionList[$bug->resolution] : $bug->resolution; - if(isset($bug->duplicateBugTitle)) echo " #$bug->duplicateBug:" . html::a($this->createLink('bug', 'view', "bugID=$bug->duplicateBug", '', true), $bug->duplicateBugTitle, '', "class='iframe' data-width='80%'"); + if(isset($bug->duplicateBugTitle)) echo " #$bug->duplicateBug:" . html::a($this->createLink('bug', 'view', "bugID=$bug->duplicateBug", '', true), $bug->duplicateBugTitle, '', "title='{$bug->duplicateBugTitle}' class='iframe' data-width='80%'"); ?> diff --git a/module/build/control.php b/module/build/control.php index 9dc99dcb18..182eace820 100644 --- a/module/build/control.php +++ b/module/build/control.php @@ -233,22 +233,27 @@ class build extends control $this->app->loadClass('pager', $static = true); if($this->app->getViewType() == 'mhtml') $recPerPage = 10; + $sort = common::appendOrder($orderBy); + if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort); + /* Get product and bugs. */ $product = $this->loadModel('product')->getById($build->product); if($product->type != 'normal') $this->lang->product->branch = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]); $bugPager = new pager($type == 'bug' ? $recTotal : 0, $recPerPage, $type == 'bug' ? $pageID : 1); - $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($build->bugs)->andWhere('deleted')->eq(0) - ->beginIF($type == 'bug')->orderBy($orderBy)->fi() + $bugs = $this->dao->select('*')->from(TABLE_BUG) + ->where('id')->in($build->bugs) + ->andWhere('deleted')->eq(0) + ->beginIF($type == 'bug')->orderBy($sort)->fi() ->page($bugPager) ->fetchAll(); /* Get stories and stages. */ $storyPager = new pager($type == 'story' ? $recTotal : 0, $recPerPage, $type == 'story' ? $pageID : 1); - $stories = $this->dao->select('*')->from(TABLE_STORY) + $stories = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder")->from(TABLE_STORY) ->where('id')->in($build->stories) ->andWhere('deleted')->eq(0) - ->beginIF($type == 'story')->orderBy($orderBy)->fi() + ->beginIF($type == 'story')->orderBy($sort)->fi() ->page($storyPager) ->fetchAll('id'); @@ -273,7 +278,7 @@ class build extends control $this->view->storyPager = $storyPager; $generatedBugPager = new pager($type == 'generatedBug' ? $recTotal : 0, $recPerPage, $type == 'generatedBug' ? $pageID : 1); - $this->view->generatedBugs = $this->bug->getExecutionBugs($build->execution, $build->product, 'all', $build->id, $type, $param, $type == 'generatedBug' ? $orderBy : 'status_desc,id_desc', '', $generatedBugPager); + $this->view->generatedBugs = $this->bug->getExecutionBugs($build->execution, $build->product, 'all', $build->id, $type, $param, $type == 'generatedBug' ? $sort : 'status_desc,id_desc', '', $generatedBugPager); $this->view->generatedBugPager = $generatedBugPager; $this->executeHooks($buildID); @@ -586,21 +591,6 @@ class build extends control { $this->build->unlinkStory($buildID, $storyID); - /* if ajax request, send result. */ - if($this->server->ajax) - { - if(dao::isError()) - { - $response['result'] = 'fail'; - $response['message'] = dao::getError(); - } - else - { - $response['result'] = 'success'; - $response['message'] = ''; - } - return $this->send($response); - } return print(js::reload('parent')); } diff --git a/module/build/view/view.html.php b/module/build/view/view.html.php index 50726da216..ea39390fb3 100644 --- a/module/build/view/view.html.php +++ b/module/build/view/view.html.php @@ -131,7 +131,7 @@ tbody tr td:first-child input {display: none;} if($canBeChanged and common::hasPriv('build', 'unlinkStory')) { $unlinkURL = inlink('unlinkStory', "buildID=$build->id&story=$story->id"); - echo html::a("###", '', '', "onclick='ajaxDelete(\"$unlinkURL\", \"storyList\", confirmUnlinkStory)' class='btn' title='{$lang->build->unlinkStory}'"); + echo html::a($unlinkURL, '', 'hiddenwin', "class='btn' title='{$lang->build->unlinkStory}'"); } ?> diff --git a/module/common/model.php b/module/common/model.php index d86b3d4831..bae5456a5c 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -1335,28 +1335,31 @@ class commonModel extends model $label = $menuItem->text; $dropMenu = ''; + /* Print sub menus. */ if(isset($menuItem->dropMenu)) { - foreach($menuItem->dropMenu as $dropMenuItem) + foreach($menuItem->dropMenu as $dropMenuKey => $dropMenuItem) { - if($dropMenuItem->hidden) continue; + if(isset($dropMenuItem->hidden) and $dropMenuItem->hidden) continue; $subActive = ''; $subModule = ''; $subMethod = ''; $subParams = ''; - $subLabel = $dropMenuItem->text; - if(isset($dropMenuItem->link['module'])) $subModule = $dropMenuItem->link['module']; - if(isset($dropMenuItem->link['method'])) $subMethod = $dropMenuItem->link['method']; - if(isset($dropMenuItem->link['vars'])) $subParams = $dropMenuItem->link['vars']; + $subLabel = ''; + list($dropMenuName, $dropMenuModule, $dropMenuMethod, $dropMenuParams) = explode('|', $dropMenuItem['link']); + if(isset($dropMenuModule)) $subModule = $dropMenuModule; + if(isset($dropMenuMethod)) $subMethod = $dropMenuMethod; + if(isset($dropMenuParams)) $subParams = $dropMenuParams; + if(isset($dropMenuName)) $subLabel = $dropMenuName; $subLink = helper::createLink($subModule, $subMethod, $subParams); if($currentModule == strtolower($subModule) and $currentMethod == strtolower($subMethod)) $subActive = 'active'; $misc = (isset($lang->navGroup->$subModule) and $tab != $lang->navGroup->$subModule) ? "data-app='$tab'" : ''; - $dropMenu .= "
  • " . html::a($subLink, $subLabel, '', $misc) . '
  • '; + $dropMenu .= "
  • " . html::a($subLink, $subLabel, '', $misc) . '
  • '; } if(empty($dropMenu)) continue; @@ -2111,9 +2114,12 @@ EOD; $table = $this->config->objectTables[$type]; $orderBy = $type . 'OrderBy'; $orderBy = $this->session->$orderBy; + $select = ''; if($this->session->$typeOnlyCondition) { - $sql = $this->dao->select('*')->from($table) + if(strpos($orderBy, 'priOrder') !== false) $select .= ", IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder"; + if(strpos($orderBy, 'severityOrder') !== false) $select .= ", IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder"; + $sql = $this->dao->select("*$select")->from($table) ->where($queryCondition) ->beginIF($orderBy != false)->orderBy($orderBy)->fi() ->get(); @@ -2495,6 +2501,7 @@ EOD; if($module == 'story' and !empty($params['storyType']) and strpos(",story,requirement,", ",{$params['storyType']},") !== false) $module = $params['storyType']; if($module == 'product' and $method == 'browse' and !empty($app->params['storyType']) and $app->params['storyType'] == 'requirement') $method = 'requirement'; if($module == 'product' and $method == 'browse' and !empty($params['storyType']) and $params['storyType'] == 'requirement') $method = 'requirement'; + if($module == 'story' and $method == 'linkrequirements') $module = 'requirement'; /* If the user is doing a tutorial, have all tutorial privs. */ if(defined('TUTORIAL')) @@ -2533,7 +2540,7 @@ EOD; $acls = $app->user->rights['acls']; /* White list of import method. */ - if(in_array($module, array('user', 'task', 'story', 'bug', 'testcase')) and $method == 'showimport') + if(in_array($module, $app->config->importWhiteList) and $method == 'showimport') { if(isset($rights[$module]['import']) and commonModel::hasDBPriv($object, $module, 'import')) return true; } diff --git a/module/common/view/datatable.fix.html.php b/module/common/view/datatable.fix.html.php index 48a26082c2..1181adb8f6 100644 --- a/module/common/view/datatable.fix.html.php +++ b/module/common/view/datatable.fix.html.php @@ -99,7 +99,7 @@ $(function() - + moduleName == 'execution' and $app->methodName == 'task' and $this->config->vision != 'lite'):?> diff --git a/module/datatable/lang/de.php b/module/datatable/lang/de.php index 55aafa1a75..3034fb390d 100644 --- a/module/datatable/lang/de.php +++ b/module/datatable/lang/de.php @@ -23,7 +23,7 @@ $lang->datatable->displaySetting = 'Set list'; $lang->datatable->showModule = 'Anzeigen/Verstecken des Modul Names'; $lang->datatable->showBranch = 'Show branches in the list'; $lang->datatable->showAllModule = 'Show product modules'; -$lang->datatable->showModuleList[] = 'N/A'; +$lang->datatable->showModuleList['0'] = 'N/A'; $lang->datatable->showModuleList['base'] = 'Basisknoten'; $lang->datatable->showModuleList['end'] = 'Endknoten'; $lang->datatable->showAllModuleList[0] = 'Hide'; diff --git a/module/datatable/lang/en.php b/module/datatable/lang/en.php index e5ab3098df..9c4b86de8d 100644 --- a/module/datatable/lang/en.php +++ b/module/datatable/lang/en.php @@ -23,7 +23,7 @@ $lang->datatable->displaySetting = 'Set List'; $lang->datatable->showModule = 'Show modules in the list'; $lang->datatable->showBranch = 'Show branches in the list'; $lang->datatable->showAllModule = 'Show product modules'; -$lang->datatable->showModuleList[] = 'N/A'; +$lang->datatable->showModuleList['0'] = 'N/A'; $lang->datatable->showModuleList['base'] = 'Base Node'; $lang->datatable->showModuleList['end'] = 'End Node'; $lang->datatable->showAllModuleList[0] = 'Hide'; diff --git a/module/datatable/lang/fr.php b/module/datatable/lang/fr.php index 6ced0da225..33a98bd90a 100644 --- a/module/datatable/lang/fr.php +++ b/module/datatable/lang/fr.php @@ -23,7 +23,7 @@ $lang->datatable->displaySetting = 'Set list'; $lang->datatable->showModule = 'Montrer les noms des modules dans la page de listes'; $lang->datatable->showBranch = 'Show branches in the list'; $lang->datatable->showAllModule = 'Afficher les modules de produits'; -$lang->datatable->showModuleList[] = 'N/A'; +$lang->datatable->showModuleList['0'] = 'N/A'; $lang->datatable->showModuleList['base'] = 'Base Node'; $lang->datatable->showModuleList['end'] = 'End Node'; $lang->datatable->showAllModuleList[0] = 'Cacher'; diff --git a/module/datatable/lang/zh-cn.php b/module/datatable/lang/zh-cn.php index 8da7db89b1..b4d63aeb80 100644 --- a/module/datatable/lang/zh-cn.php +++ b/module/datatable/lang/zh-cn.php @@ -23,7 +23,7 @@ $lang->datatable->displaySetting = '显示设置'; $lang->datatable->showModule = '列表页是否显示模块名'; $lang->datatable->showBranch = '列表页是否显示%s名'; $lang->datatable->showAllModule = '是否显示完整产品模块'; -$lang->datatable->showModuleList[] = '不显示'; +$lang->datatable->showModuleList['0'] = '不显示'; $lang->datatable->showModuleList['base'] = '只显示一级模块'; $lang->datatable->showModuleList['end'] = '只显示最后一级模块'; $lang->datatable->showAllModuleList[0] = '不显示'; diff --git a/module/design/js/browse.js b/module/design/js/browse.js index 472e4d5704..9abbb03273 100644 --- a/module/design/js/browse.js +++ b/module/design/js/browse.js @@ -1,15 +1,28 @@ $(function() { - $('#subNavbar .nav li').removeClass('active'); + $('#subNavbar .nav li').removeClass('active'); $('#subNavbar .nav li[data-id=' + type + ']').addClass('active'); $('#subNavbar .nav li > a').each(function() { var type = $(this).parent().attr('data-id'); if(type == 'bysearch') return; + if(type == 'more') + { + $(this).attr('href', '###'); + return; + } - type = type == 'all' ? type : type.toUpperCase(); + type = type == 'all' ? type : type.toLowerCase(); var href = createLink('design', 'browse', 'projectID=' + projectID + '&productID=' + productID + '&type=' + type); $(this).attr('href', href); }); + + if($('#subNavbar .dropdown-menu li[data-id=' + type +']').hasClass('active')) + { + var typeName = $('#subNavbar li[data-id=' + type +'] > a').html(); + + $('#subNavbar').find(".dropdown-hover > a").html(typeName + ""); + $("#subNavbar li[data-id='more']").addClass('active'); + } }) diff --git a/module/design/lang/de.php b/module/design/lang/de.php index d78d2bc6ab..8dc1c11869 100644 --- a/module/design/lang/de.php +++ b/module/design/lang/de.php @@ -37,6 +37,7 @@ $lang->design->createdDate = 'CreatedDate'; $lang->design->basicInfo = 'Basic Information'; $lang->design->noAssigned = 'Unassigned'; $lang->design->comment = 'Comment'; +$lang->design->more = 'Mehr'; /* 动作列表. */ $lang->design->common = 'Design'; diff --git a/module/design/lang/en.php b/module/design/lang/en.php index 9a25dfdb79..f006c2c840 100644 --- a/module/design/lang/en.php +++ b/module/design/lang/en.php @@ -37,6 +37,7 @@ $lang->design->createdDate = 'CreatedDate'; $lang->design->basicInfo = 'Basic Information'; $lang->design->noAssigned = 'Unassigned'; $lang->design->comment = 'Comment'; +$lang->design->more = 'More'; /* 动作列表. */ $lang->design->common = 'Design'; diff --git a/module/design/lang/fr.php b/module/design/lang/fr.php index d78d2bc6ab..0e3e8da8a8 100644 --- a/module/design/lang/fr.php +++ b/module/design/lang/fr.php @@ -37,6 +37,7 @@ $lang->design->createdDate = 'CreatedDate'; $lang->design->basicInfo = 'Basic Information'; $lang->design->noAssigned = 'Unassigned'; $lang->design->comment = 'Comment'; +$lang->design->more = 'Suite'; /* 动作列表. */ $lang->design->common = 'Design'; diff --git a/module/design/lang/zh-cn.php b/module/design/lang/zh-cn.php index d96bd18f15..cab82e4748 100644 --- a/module/design/lang/zh-cn.php +++ b/module/design/lang/zh-cn.php @@ -37,6 +37,7 @@ $lang->design->createdDate = '创建时间'; $lang->design->basicInfo = '基本信息'; $lang->design->noAssigned = '未指派'; $lang->design->comment = '注释'; +$lang->design->more = '更多'; /* 动作列表. */ $lang->design->common = '设计'; diff --git a/module/design/model.php b/module/design/model.php index 7fa9c33108..25be18689e 100644 --- a/module/design/model.php +++ b/module/design/model.php @@ -406,9 +406,20 @@ class designModel extends model /* Show custom design types. */ $this->lang->waterfall->menu->design['subMenu'] = new stdclass(); $this->lang->waterfall->menu->design['subMenu']->all = array('link' => "{$this->lang->all}|design|browse|projectID=%s&productID=0&browseType=all"); + $count = 1; foreach(array_filter($this->lang->design->typeList) as $key => $value) { - $this->lang->waterfall->menu->design['subMenu']->$key = array('link' => "{$value}|design|browse|projectID=%s&productID=0&browseType={$key}"); + $key = strtolower($key); + + if($count <= 4) $this->lang->waterfall->menu->design['subMenu']->$key = array('link' => "{$value}|design|browse|projectID=%s&productID=0&browseType={$key}"); + if($count == 5) + { + $this->lang->waterfall->menu->design['subMenu']->more = array('link' => "{$this->lang->design->more}|design|browse|projectID=%s&productID=0&browseType={$key}", 'class' => 'dropdown dropdown-hover'); + $this->lang->waterfall->menu->design['subMenu']->more['dropMenu'] = new stdclass(); + } + if($count >= 5) $this->lang->waterfall->menu->design['subMenu']->more['dropMenu']->$key = array('link' => "{$value}|design|browse|projectID=%s&productID=0&browseType={$key}"); + + $count ++; } if($this->app->rawMethod == 'browse') $this->lang->waterfall->menu->design['subMenu']->bysearch = array('link' => ' ' . $this->lang->searchAB . ''); diff --git a/module/design/view/view.html.php b/module/design/view/view.html.php index 777eca48e3..38299bb95c 100644 --- a/module/design/view/view.html.php +++ b/module/design/view/view.html.php @@ -16,7 +16,7 @@ project);?> $value) { - $this->story->printCell($value, $story, $users, $branchOption, $storyStages, $modulePairs, $storyTasks, $storyBugs, $storyCases, $useDatatable ? 'datatable' : 'table', '', $execution, $showBranch); + $this->story->printCell($value, $story, $users, $branchOption, $storyStages, $modulePairs, $storyTasks, $storyBugs, $storyCases, $useDatatable ? 'datatable' : 'table', 'story', $execution, $showBranch); } ?> diff --git a/module/file/control.php b/module/file/control.php index 36e29ae62e..c8230031b6 100755 --- a/module/file/control.php +++ b/module/file/control.php @@ -314,6 +314,7 @@ class file extends control $this->view->files = $files; $this->view->fieldset = $fieldset; $this->view->object = $object; + $this->view->method = $method; if($method == 'view') return $this->display('file', 'viewfiles'); $this->display(); diff --git a/module/file/lang/de.php b/module/file/lang/de.php index d157e6e28d..9fce4814f3 100755 --- a/module/file/lang/de.php +++ b/module/file/lang/de.php @@ -70,3 +70,9 @@ $lang->file->errorSuffix = 'Format ist falsch. Nur .zip Dateien!'; $lang->file->errorExtract = 'Entpacken fehlgeschlagen. Die Datei ist vermutlich defekt.'; $lang->file->fileNotFound = 'The file was not found. The physical file might have been deleted!'; $lang->file->fileContentEmpty = 'The file is empty. Check the file and upload it again.'; + +$lang->file->uploadError[1] = 'The uploaded filesize exceeds the limit. Please change the upload_max_filesize and post_max_size options in php.ini'; +$lang->file->uploadError[2] = 'The size of the uploaded file exceeds the value specified by the MAX_FILE_SIZE option in the HTML form'; +$lang->file->uploadError[3] = 'Only part of the file has been uploaded, please re-upload'; +$lang->file->uploadError[4] = 'No files have been uploaded'; +$lang->file->uploadError[5] = 'The size of the file is 0. Please upload the file again'; diff --git a/module/file/lang/en.php b/module/file/lang/en.php index 78495f78de..ce9e2af939 100755 --- a/module/file/lang/en.php +++ b/module/file/lang/en.php @@ -70,3 +70,9 @@ $lang->file->errorSuffix = 'Format is incorrect. .zip files ONLY!'; $lang->file->errorExtract = 'Extracting files failed. Files might be damaged or there might be invalid files in the zip package.'; $lang->file->fileNotFound = 'The file was not found. The physical file might have been deleted!'; $lang->file->fileContentEmpty = 'The file is empty. Check the file and upload it again.'; + +$lang->file->uploadError[1] = 'The uploaded filesize exceeds the limit. Please change the upload_max_filesize and post_max_size options in php.ini'; +$lang->file->uploadError[2] = 'The size of the uploaded file exceeds the value specified by the MAX_FILE_SIZE option in the HTML form'; +$lang->file->uploadError[3] = 'Only part of the file has been uploaded, please re-upload'; +$lang->file->uploadError[4] = 'No files have been uploaded'; +$lang->file->uploadError[5] = 'The size of the file is 0. Please upload the file again'; diff --git a/module/file/lang/fr.php b/module/file/lang/fr.php index 6b29ba71f9..8740450ca8 100755 --- a/module/file/lang/fr.php +++ b/module/file/lang/fr.php @@ -70,3 +70,9 @@ $lang->file->errorSuffix = 'Format incorrect. Fichiers .zip SEULEMENT !'; $lang->file->errorExtract = "Echec de l'extraction des fichiers. Les fichiers peuvent être endommagé ou il y a un fichier invalide dans le zip."; $lang->file->fileNotFound = 'Fichier non trouvé. Le fichier physique a peut-être été supprimé par innadvertance !'; $lang->file->fileContentEmpty = 'The file is empty. Check the file and upload it again.'; + +$lang->file->uploadError[1] = 'The uploaded filesize exceeds the limit. Please change the upload_max_filesize and post_max_size options in php.ini'; +$lang->file->uploadError[2] = 'The size of the uploaded file exceeds the value specified by the MAX_FILE_SIZE option in the HTML form'; +$lang->file->uploadError[3] = 'Only part of the file has been uploaded, please re-upload'; +$lang->file->uploadError[4] = 'No files have been uploaded'; +$lang->file->uploadError[5] = 'The size of the file is 0. Please upload the file again'; diff --git a/module/file/lang/vi.php b/module/file/lang/vi.php index 3a11441b1b..0c9b409d95 100755 --- a/module/file/lang/vi.php +++ b/module/file/lang/vi.php @@ -65,3 +65,9 @@ $lang->file->errorSuffix = 'Format is incorrect. .zip files ONLY!'; $lang->file->errorExtract = 'Extracting files failed. Files might be damaged or there might be invalid files in the zip package.'; $lang->file->fileNotFound = 'Tập tin was not found. The physical file might have been deleted!'; $lang->file->fileContentEmpty = 'The file is empty. Check the file and upload it again.'; + +$lang->file->uploadError[1] = 'The uploaded filesize exceeds the limit. Please change the upload_max_filesize and post_max_size options in php.ini'; +$lang->file->uploadError[2] = 'The size of the uploaded file exceeds the value specified by the MAX_FILE_SIZE option in the HTML form'; +$lang->file->uploadError[3] = 'Only part of the file has been uploaded, please re-upload'; +$lang->file->uploadError[4] = 'No files have been uploaded'; +$lang->file->uploadError[5] = 'The size of the file is 0. Please upload the file again'; diff --git a/module/file/lang/zh-cn.php b/module/file/lang/zh-cn.php index d44c794fd5..972cfc1a13 100755 --- a/module/file/lang/zh-cn.php +++ b/module/file/lang/zh-cn.php @@ -70,3 +70,9 @@ $lang->file->errorSuffix = '压缩包格式错误,只能上传zip压缩 $lang->file->errorExtract = '解压缩失败!可能文件已经损坏,或压缩包里含有非法上传文件。'; $lang->file->fileNotFound = '未找到该文件,可能物理文件已被删除!'; $lang->file->fileContentEmpty = '上传文件内容为空,请检查后重新上传。'; + +$lang->file->uploadError[1] = "上传的文件大小超过了限制,请修改 php.ini 中 upload_max_filesize 与 post_max_size 选项限制的值"; +$lang->file->uploadError[2] = '上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值'; +$lang->file->uploadError[3] = '文件只有部分被上传,请重新上传'; +$lang->file->uploadError[4] = '没有文件被上传'; +$lang->file->uploadError[5] = '上传文件大小为0,请重新上传'; diff --git a/module/file/model.php b/module/file/model.php index aaf8813c45..72d4a1d828 100755 --- a/module/file/model.php +++ b/module/file/model.php @@ -167,6 +167,8 @@ class fileModel extends model $files = array(); if(!isset($_FILES[$htmlTagName])) return $files; + if(!is_array($_FILES[$htmlTagName]['error']) and $_FILES[$htmlTagName]['error'] != 0) return $_FILES[$htmlTagName]; + $this->app->loadClass('purifier', true); $config = HTMLPurifier_Config::createDefault(); $config->set('Cache.DefinitionImpl', null); diff --git a/module/file/view/printfiles.html.php b/module/file/view/printfiles.html.php index ee78a6ecc0..2c621c7413 100644 --- a/module/file/view/printfiles.html.php +++ b/module/file/view/printfiles.html.php @@ -92,7 +92,7 @@ if(common::hasPriv($objectType, 'edit', $object)) { echo "  "; - common::printLink('file', 'edit', "fileID=$file->id", $lang->file->edit, '', "data-width='400' class='fileAction btn btn-link edit iframe text-primary' title='{$lang->file->edit}'"); + if($method != 'storyChange') common::printLink('file', 'edit', "fileID=$file->id", $lang->file->edit, '', "data-width='400' class='fileAction btn btn-link edit iframe text-primary' title='{$lang->file->edit}'"); if(common::hasPriv('file', 'delete')) echo html::a('###', $lang->delete, '', "class='fileAction btn btn-link text-primary' onclick='deleteFile($file->id)' title='$lang->delete'"); echo ''; } diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index d26b0ac941..a0ff9f225b 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -491,15 +491,16 @@ $lang->resource->story = new stdclass(); $lang->resource->story->create = 'create'; $lang->resource->story->batchCreate = 'batchCreate'; $lang->resource->story->edit = 'editAction'; -$lang->resource->story->linkStory = 'linkStory'; +if($config->URAndSR) $lang->resource->story->linkStory = 'linkStory'; $lang->resource->story->batchEdit = 'batchEdit'; $lang->resource->story->export = 'exportAction'; $lang->resource->story->delete = 'deleteAction'; $lang->resource->story->view = 'view'; $lang->resource->story->change = 'changeAction'; $lang->resource->story->review = 'reviewAction'; +$lang->resource->story->submitReview = 'submitReview'; $lang->resource->story->batchReview = 'batchReview'; -$lang->resource->story->recall = 'recall'; +$lang->resource->story->recall = 'recallAction'; $lang->resource->story->assignTo = 'assignAction'; $lang->resource->story->close = 'closeAction'; $lang->resource->story->batchClose = 'batchClose'; @@ -525,6 +526,7 @@ $lang->story->methodOrder[25] = 'delete'; $lang->story->methodOrder[30] = 'view'; $lang->story->methodOrder[35] = 'change'; $lang->story->methodOrder[40] = 'review'; +$lang->story->methodOrder[44] = 'submitReview'; $lang->story->methodOrder[45] = 'batchReview'; $lang->story->methodOrder[50] = 'recall'; $lang->story->methodOrder[55] = 'close'; @@ -538,7 +540,7 @@ $lang->story->methodOrder[90] = 'tasks'; $lang->story->methodOrder[95] = 'bugs'; $lang->story->methodOrder[100] = 'cases'; $lang->story->methodOrder[105] = 'report'; -$lang->story->methodOrder[110] = 'linkStory'; +if($config->URAndSR) $lang->story->methodOrder[110] = 'linkStory'; $lang->story->methodOrder[115] = 'batchChangeBranch'; $lang->story->methodOrder[120] = 'batchChangeModule'; $lang->story->methodOrder[125] = 'batchToTask'; @@ -552,12 +554,14 @@ if($config->URAndSR) $lang->resource->requirement->create = 'create'; $lang->resource->requirement->batchCreate = 'batchCreate'; $lang->resource->requirement->edit = 'editAction'; + $lang->resource->requirement->linkStory = 'linkStory'; $lang->resource->requirement->batchEdit = 'batchEdit'; $lang->resource->requirement->export = 'exportAction'; $lang->resource->requirement->delete = 'deleteAction'; $lang->resource->requirement->view = 'view'; $lang->resource->requirement->change = 'changeAction'; $lang->resource->requirement->review = 'reviewAction'; + $lang->resource->requirement->submitReview = 'submitReview'; $lang->resource->requirement->batchReview = 'batchReview'; $lang->resource->requirement->recall = 'recall'; $lang->resource->requirement->assignTo = 'assignAction'; @@ -570,25 +574,27 @@ if($config->URAndSR) $lang->resource->requirement->batchChangeModule = 'batchChangeModule'; $lang->resource->requirement->linkRequirements = 'linkRequirementsAB'; - $lang->requirement->methodOrder[5] = 'create'; - $lang->requirement->methodOrder[10] = 'batchCreate'; - $lang->requirement->methodOrder[15] = 'edit'; - $lang->requirement->methodOrder[20] = 'export'; - $lang->requirement->methodOrder[25] = 'delete'; - $lang->requirement->methodOrder[30] = 'view'; - $lang->requirement->methodOrder[35] = 'change'; - $lang->requirement->methodOrder[40] = 'review'; - $lang->requirement->methodOrder[45] = 'batchReview'; - $lang->requirement->methodOrder[50] = 'recall'; - $lang->requirement->methodOrder[55] = 'close'; - $lang->requirement->methodOrder[60] = 'batchClose'; - $lang->requirement->methodOrder[65] = 'assignTo'; - $lang->requirement->methodOrder[70] = 'batchAssignTo'; - $lang->requirement->methodOrder[75] = 'activate'; - $lang->requirement->methodOrder[80] = 'report'; - $lang->requirement->methodOrder[85] = 'batchChangeBranch'; - $lang->requirement->methodOrder[90] = 'batchChangeModule'; - $lang->requirement->methodOrder[95] = 'linkRequirements'; + $lang->requirement->methodOrder[5] = 'create'; + $lang->requirement->methodOrder[10] = 'batchCreate'; + $lang->requirement->methodOrder[15] = 'edit'; + $lang->requirement->methodOrder[20] = 'export'; + $lang->requirement->methodOrder[25] = 'delete'; + $lang->requirement->methodOrder[30] = 'view'; + $lang->requirement->methodOrder[35] = 'change'; + $lang->requirement->methodOrder[40] = 'review'; + $lang->requirement->methodOrder[44] = 'submitReview'; + $lang->requirement->methodOrder[45] = 'batchReview'; + $lang->requirement->methodOrder[50] = 'recall'; + $lang->requirement->methodOrder[55] = 'close'; + $lang->requirement->methodOrder[60] = 'batchClose'; + $lang->requirement->methodOrder[65] = 'assignTo'; + $lang->requirement->methodOrder[70] = 'batchAssignTo'; + $lang->requirement->methodOrder[75] = 'activate'; + $lang->requirement->methodOrder[80] = 'report'; + $lang->requirement->methodOrder[85] = 'linkStory'; + $lang->requirement->methodOrder[90] = 'batchChangeBranch'; + $lang->requirement->methodOrder[95] = 'batchChangeModule'; + $lang->requirement->methodOrder[100] = 'linkRequirements'; } /* Product plan. */ diff --git a/module/kanban/model.php b/module/kanban/model.php index a0e0f05747..50bca7f45d 100755 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -3868,7 +3868,7 @@ class kanbanModel extends model { $menu = array(); - $toTaskPriv = strpos('draft,closed', $story->status) !== false ? false : true; + $toTaskPriv = strpos('draft,reviewing,closed', $story->status) !== false ? false : true; if(common::hasPriv('story', 'edit') and $this->story->isClickable($story, 'edit')) $menu[] = array('label' => $this->lang->story->edit, 'icon' => 'edit', 'url' => helper::createLink('story', 'edit', "storyID=$story->id", '', true), 'size' => '95%'); if(common::hasPriv('story', 'change') and $this->story->isClickable($story, 'change')) $menu[] = array('label' => $this->lang->story->change, 'icon' => 'alter', 'url' => helper::createLink('story', 'change', "storyID=$story->id", '', true), 'size' => '95%'); if(common::hasPriv('story', 'review') and $this->story->isClickable($story, 'review')) $menu[] = array('label' => $this->lang->story->review, 'icon' => 'search', 'url' => helper::createLink('story', 'review', "storyID=$story->id", '', true), 'size' => '95%'); diff --git a/module/message/model.php b/module/message/model.php index b640916bc4..1dd601e02c 100755 --- a/module/message/model.php +++ b/module/message/model.php @@ -155,10 +155,11 @@ class messageModel extends model $moduleName = $objectType == 'case' ? 'testcase' : $objectType; $moduleName = $objectType == 'kanbancard' ? 'kanban' : $objectType; - $space = common::checkNotCN() ? ' ' : ''; - $data = $user->realname . $space . $this->lang->action->label->$actionType . $space . $this->lang->action->objectTypes[$objectType]; - $dataID = $objectType == 'kanbancard' ? $object->kanban : $objectID; - $data .= ' ' . html::a($sysURL . helper::createLink($moduleName, 'view', "id=$dataID"), "[#{$objectID}::{$object->$field}]"); + $space = common::checkNotCN() ? ' ' : ''; + $data = $user->realname . $space . $this->lang->action->label->$actionType . $space . $this->lang->action->objectTypes[$objectType]; + $dataID = $objectType == 'kanbancard' ? $object->kanban : $objectID; + $url = helper::createLink($moduleName, 'view', "id=$dataID"); + $data .= ' ' . html::a((strpos($url, $sysURL) === 0 ? '' : $sysURL) . $url, "[#{$objectID}::{$object->$field}]"); if($isonlybody) $_GET['onlybody'] = 'yes'; diff --git a/module/mr/control.php b/module/mr/control.php index 37fde7fcb8..310c1990fa 100644 --- a/module/mr/control.php +++ b/module/mr/control.php @@ -639,7 +639,7 @@ class mr extends control } else { - $allStories = $this->story->getProductStories($productID, 0, '0', 'draft,active,changed', 'story', 'id_desc', false, array_keys($linkedStories), $pager); + $allStories = $this->story->getProductStories($productID, 0, '0', 'draft,reviewing,active,changing', 'story', 'id_desc', false, array_keys($linkedStories), $pager); } $this->view->modules = $modules; diff --git a/module/my/control.php b/module/my/control.php index 967ff2e724..410145f572 100755 --- a/module/my/control.php +++ b/module/my/control.php @@ -332,15 +332,16 @@ EOF; /* Append id for secend sort. */ $sort = common::appendOrder($orderBy); + if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort); $queryID = ($type == 'bysearch') ? (int)$param : 0; if($type == 'assignedBy') { - $stories = $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, 'story'); + $stories = $this->my->getAssignedByMe($this->app->user->account, '', $pager, $sort, 'story'); } elseif($type == 'bysearch') { - $stories = $this->my->getStoriesBySearch($queryID, $this->app->rawMethod, $orderBy, $pager); + $stories = $this->my->getStoriesBySearch($queryID, $this->app->rawMethod, $sort, $pager); } else { @@ -396,15 +397,16 @@ EOF; /* Append id for secend sort. */ $sort = common::appendOrder($orderBy); + if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort); $queryID = ($type == 'bysearch') ? (int)$param : 0; if($type == 'assignedBy') { - $stories = $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, 'requirement'); + $stories = $this->my->getAssignedByMe($this->app->user->account, '', $pager, $sort, 'requirement'); } elseif($type == 'bysearch') { - $stories = $this->my->getRequirementsBySearch($queryID, $this->app->rawMethod, $orderBy, $pager); + $stories = $this->my->getRequirementsBySearch($queryID, $this->app->rawMethod, $sort, $pager); } else { @@ -569,9 +571,11 @@ EOF; /* Append id for secend sort. */ $sort = common::appendOrder($orderBy); + if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort); + if(strpos($sort, 'severity_') !== false) $sort = str_replace('severity_', 'severityOrder_', $sort); if($type == 'assignedBy') { - $bugs = $this->loadModel('my')->getAssignedByMe($this->app->user->account, '', $pager, $orderBy, 'bug'); + $bugs = $this->my->getAssignedByMe($this->app->user->account, '', $pager, $sort, 'bug'); } else { diff --git a/module/my/css/requirement.css b/module/my/css/requirement.css index 13919b8117..c0389382d5 100644 --- a/module/my/css/requirement.css +++ b/module/my/css/requirement.css @@ -10,3 +10,4 @@ .table td.c-hours {padding-right: 12px;} .main-table tbody > tr.table-children > td:first-child::before {width: 3px;} @-moz-document url-prefix() {.main-table tbody > tr.table-children > td:first-child::before {width: 4px;};} +.c-span {margin-left: 22px;} diff --git a/module/my/css/testtask.css b/module/my/css/testtask.css index 124ef6e446..4c9d612635 100644 --- a/module/my/css/testtask.css +++ b/module/my/css/testtask.css @@ -1 +1,4 @@ -.c-execution, .c-build {width: 120px;} +.c-execution {width: 200px} +.c-build {width: 120px;} +.c-id {width: 60px;} +.c-status {width: 80px;} diff --git a/module/my/model.php b/module/my/model.php index 80a9cf47ce..89101f568a 100644 --- a/module/my/model.php +++ b/module/my/model.php @@ -336,24 +336,27 @@ class myModel extends model if($objectType == 'task') { - $objectList = $this->dao->select('t1.*, t2.name as executionName')->from($this->config->objectTables[$module])->alias('t1') + $orderBy = strpos($orderBy, 'pri_') !== false ? str_replace('pri_', 'priOrder_', $orderBy) : 't1.' . $orderBy; + $objectList = $this->dao->select("t1.*, t2.name as executionName, t2.type as executionType, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder")->from($this->config->objectTables[$module])->alias('t1') ->leftJoin(TABLE_EXECUTION)->alias('t2')->on("t1.execution = t2.id") ->where('t1.deleted')->eq(0) ->andWhere('t2.deleted')->eq(0) ->andWhere('t1.id')->in(array_keys($objectIDList)) - ->orderBy('t1.' . $orderBy) + ->orderBy($orderBy) ->page($pager) ->fetchAll('id'); } elseif($objectType == 'requirement' or $objectType == 'story' or $objectType == 'bug') { - $objectList = $this->dao->select('t1.*')->from($this->config->objectTables[$module])->alias('t1') + $orderBy = (strpos($orderBy, 'priOrder') !== false or strpos($orderBy, 'severityOrder') !== false) ? $orderBy : "t1.$orderBy"; + $select = strpos($orderBy, 'severity') !== false ? "t1.*,IF(t1.`severity` = 0, {$this->config->maxPriValue}, t1.`severity`) as severityOrder" : "t1.*,IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder"; + $objectList = $this->dao->select($select)->from($this->config->objectTables[$module])->alias('t1') ->leftJoin(TABLE_PRODUCT)->alias('t2')->on("t1.product = t2.id") ->where('t1.deleted')->eq(0) ->andWhere('t2.deleted')->eq(0) ->andWhere('t1.id')->in(array_keys($objectIDList)) ->beginIF($objectType == 'requirement' or $objectType == 'story')->andWhere('t1.type')->eq($objectType)->fi() - ->orderBy('t1.' . $orderBy) + ->orderBy($orderBy) ->page($pager) ->fetchAll('id'); } @@ -504,7 +507,6 @@ class myModel extends model { $rawMethod = $this->app->rawMethod; $this->loadModel('execution'); - $this->app->loadConfig('execution'); $this->config->execution->search['module'] = $rawMethod . 'Task'; $this->config->execution->search['actionURL'] = $actionURL; @@ -580,7 +582,8 @@ class myModel extends model $query = preg_replace('/`(\w+)`/', 't1.`$1`', $query); $query = str_replace('t1.`project`', 't2.`project`', $query); - $tasks = $this->dao->select('t1.*, t2.id as executionID, t2.name as executionName, t2.type as executionType, t3.id as storyID, t3.title as storyTitle, t3.status AS storyStatus, t3.version AS latestStoryVersion') + $orderBy = str_replace('pri_', 'priOrder_', $orderBy); + $tasks = $this->dao->select("t1.*, t2.id as executionID, t2.name as executionName, t2.type as executionType, t3.id as storyID, t3.title as storyTitle, t3.status AS storyStatus, t3.version AS latestStoryVersion, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder") ->from(TABLE_TASK)->alias('t1') ->leftJoin(TABLE_EXECUTION)->alias('t2')->on("t1.execution = t2.id") ->leftJoin(TABLE_STORY)->alias('t3')->on('t1.story = t3.id') @@ -827,7 +830,7 @@ class myModel extends model $storyIDList[$storyID] = $storyID; } - $stories = $this->dao->select('distinct t1.*, t2.name as productTitle, t4.title as planTitle')->from(TABLE_STORY)->alias('t1') + $stories = $this->dao->select("distinct t1.*, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, t2.name as productTitle, t4.title as planTitle")->from(TABLE_STORY)->alias('t1') ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') ->leftJoin(TABLE_PLANSTORY)->alias('t3')->on('t1.id = t3.plan') ->leftJoin(TABLE_PRODUCTPLAN)->alias('t4')->on('t3.plan = t4.id') @@ -846,7 +849,7 @@ class myModel extends model } else { - $stories = $this->dao->select('distinct t1.*, t2.name as productTitle, t4.title as planTitle')->from(TABLE_STORY)->alias('t1') + $stories = $this->dao->select("distinct t1.*, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, t2.name as productTitle, t4.title as planTitle")->from(TABLE_STORY)->alias('t1') ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') ->leftJoin(TABLE_PLANSTORY)->alias('t3')->on('t1.id = t3.plan') ->leftJoin(TABLE_PRODUCTPLAN)->alias('t4')->on('t3.plan = t4.id') @@ -946,7 +949,7 @@ class myModel extends model $requirementIDList[$requirementID] = $requirementID; } - $requirements = $this->dao->select('distinct t1.*, t2.name as productTitle')->from(TABLE_STORY)->alias('t1') + $requirements = $this->dao->select("distinct t1.*, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, t2.name as productTitle")->from(TABLE_STORY)->alias('t1') ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') ->leftJoin(TABLE_STORYREVIEW)->alias('t3')->on('t1.id = t3.story') ->where($myRequirementQuery) @@ -963,7 +966,7 @@ class myModel extends model } else { - $requirements = $this->dao->select('distinct t1.*, t2.name as productTitle')->from(TABLE_STORY)->alias('t1') + $requirements = $this->dao->select("distinct t1.*, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, t2.name as productTitle")->from(TABLE_STORY)->alias('t1') ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') ->leftJoin(TABLE_STORYREVIEW)->alias('t3')->on('t1.id = t3.story') ->where($myRequirementQuery) diff --git a/module/my/view/requirement.html.php b/module/my/view/requirement.html.php index b26b4eec70..8472470c53 100644 --- a/module/my/view/requirement.html.php +++ b/module/my/view/requirement.html.php @@ -76,6 +76,7 @@ createLink('story', 'view', "id=$story->id"); $canBeChanged = common::canBeChanged('story', $story); + $spanClass = $canBatchAction ? 'c-span' : ''; ?> - + @@ -103,7 +104,15 @@ { $vars = "story={$story->id}"; echo common::buildIconButton('story', 'change', "$vars&from=&storyType=requirement", $story, 'list', 'alter', '', 'iframe', true); - echo common::buildIconButton('story', 'review', "$vars&from=product&storyType=requirement", $story, 'list', 'search', '', 'iframe', true); + + if(strpos('draft,changing', $story->status) !== false) + { + echo common::buildIconButton('story', 'submitReview', "$vars&storyType=requirement", $story, 'list', 'sub-review', '', 'iframe', true); + } + else + { + echo common::buildIconButton('story', 'review', "$vars&from=product&storyType=requirement", $story, 'list', 'search', '', 'iframe', true); + } echo common::buildIconButton('story', 'recall', "$vars&from=list&storyType=requirement", $story, 'list', 'undo', 'hiddenwin', '', '', '', $lang->story->recall); echo common::buildIconButton('story', 'close', "$vars&from=&storyType=requirement", $story, 'list', '', '', 'iframe', true); echo common::buildIconButton('story', 'edit', "$vars&from=default&storyType=requirement", $story, 'list', '', '', 'iframe', true, "data-width='95%'"); @@ -119,19 +128,14 @@ children)) ? ' table-child-bottom' : '';?> - + @@ -147,11 +151,20 @@ } else { - common::printIcon('story', 'change', $vars, $child, 'list', 'alter'); - common::printIcon('story', 'review', $vars, $child, 'list', 'search'); - common::printIcon('story', 'close', $vars, $child, 'list', '', '', 'iframe', true); - common::printIcon('story', 'edit', $vars, $child, 'list'); - common::printIcon('story', 'createCase', "productID=$child->product&branch=$child->branch&module=0&from=¶m=0&$vars", $child, 'list', 'sitemap'); + common::printIcon('story', 'change', "$vars&from=&storyType=story", $child, 'list', 'alter', '', 'iframe', true); + + if(strpos('draft,changing', $child->status) !== false) + { + common::printIcon('story', 'submitReview', "$vars&storyType=story", $child, 'list', 'sub-review', '', 'iframe', true); + } + else + { + common::printIcon('story', 'review', "$vars&from=product&storyType=story", $child, 'list', 'search', '', 'iframe', true); + } + + common::printIcon('story', 'recall', "$vars&from=list&storyType=story", $child, 'list', 'undo', 'hiddenwin', '', '', '', $lang->story->recall); + common::printIcon('story', 'close', "$vars&from=&storyType=story", $child, 'list', '', '', 'iframe', true); + common::printIcon('story', 'edit', "$vars&from=default&storyType=story", $child, 'list'); } } ?> @@ -185,7 +198,7 @@ unset($lang->story->reviewResultList['revert']); foreach($lang->story->reviewResultList as $key => $result) { - $actionLink = $this->createLink('story', 'batchReview', "result=$key"); + $actionLink = $this->createLink('story', 'batchReview', "result=$key&reason=&storyType=requirement"); if($key == 'reject') { echo "
  • "; echo html::a('#', $reason, '', "onclick=\"setFormAction('$actionLink', 'hiddenwin')\""); echo "
  • "; @@ -218,7 +231,7 @@ 10; - $actionLink = $this->createLink('story', 'batchAssignTo'); + $actionLink = $this->createLink('story', 'batchAssignTo', 'storyType=requirement'); echo html::select('assignedTo', $users, '', 'class="hidden"'); if($withSearch) { diff --git a/module/my/view/story.html.php b/module/my/view/story.html.php index 192f898a06..e19a82ece3 100644 --- a/module/my/view/story.html.php +++ b/module/my/view/story.html.php @@ -105,7 +105,16 @@ { $vars = "story={$story->id}"; echo common::buildIconButton('story', 'change', $vars, $story, 'list', 'alter', '', 'iframe', true); - echo common::buildIconButton('story', 'review', $vars, $story, 'list', 'search', '', 'iframe', true); + + if(strpos('draft,changing', $story->status) !== false) + { + echo common::buildIconButton('story', 'submitReview', $vars, $story, 'list', 'sub-review', '', 'iframe', true); + } + else + { + echo common::buildIconButton('story', 'review', $vars, $story, 'list', 'search', '', 'iframe', true); + } + echo common::buildIconButton('story', 'recall', $vars, $story, 'list', 'undo', 'hiddenwin', '', '', '', $lang->story->recall); echo common::buildIconButton('story', 'close', $vars, $story, 'list', '', '', 'iframe', true); echo common::buildIconButton('story', 'edit', $vars, $story, 'list', '', '', 'iframe', true, "data-width='95%'"); @@ -145,8 +154,17 @@ if($canBeChanged) { $vars = "story={$child->id}"; - common::printIcon('story', 'change', $vars, $child, 'list', 'alter', '', 'iframe', true); - common::printIcon('story', 'review', $vars, $child, 'list', 'search', '', 'iframe', true); + common::printIcon('story', 'change', $vars, $child, 'list', 'alter', '', 'iframe', true); + + if(strpos('draft,changing', $child->status) !== false) + { + common::printIcon('story', 'submitReview', $vars, $child, 'list', 'sub-review', '', 'iframe', true); + } + else + { + common::printIcon('story', 'review', $vars, $child, 'list', 'search', '', 'iframe', true); + } + common::printIcon('story', 'recall', $vars, $child, 'list', 'undo', 'hiddenwin', '', '', '', $lang->story->recall); common::printIcon('story', 'close', $vars, $child, 'list', '', '', 'iframe', true); common::printIcon('story', 'edit', $vars, $child, 'list', '', '', 'iframe', true, "data-width='95%'"); common::printIcon('story', 'createCase', "productID=$child->product&branch=$child->branch&module=0&from=¶m=0&$vars", $child, 'list', 'sitemap', '', 'iframe', true, "data-width='95%'"); diff --git a/module/my/view/task.html.php b/module/my/view/task.html.php index 14af9270fd..69b47b7bfc 100644 --- a/module/my/view/task.html.php +++ b/module/my/view/task.html.php @@ -108,8 +108,9 @@ } else { - $class = ($task->executionType == 'kanban') ? 'iframe' : ''; - echo html::a($this->createLink('task', 'view', "taskID=$task->id", '', true, $task->project), $task->name, null, "class='$class' data-width='80%' style='color: $task->color'"); + $onlybody = $task->executionType == 'kanban' ? true : ''; + $class = $task->executionType == 'kanban' ? 'iframe' : ''; + echo html::a($this->createLink('task', 'view', "taskID=$task->id", '', $onlybody, $task->project), $task->name, null, "class='$class' data-width='80%' style='color: $task->color'"); } ?> children)) echo '';?> diff --git a/module/my/view/testtask.html.php b/module/my/view/testtask.html.php index 4c7e9b1a19..9df1becf44 100644 --- a/module/my/view/testtask.html.php +++ b/module/my/view/testtask.html.php @@ -47,12 +47,12 @@ - - - + + + - + + - + @@ -68,11 +68,13 @@ + + @@ -113,12 +115,14 @@ config->URAndSR):?> - + + - + + @@ -158,12 +162,14 @@ config->URAndSR):?> - + + - + + @@ -179,8 +185,8 @@ $product):?> stories['active'] + $product->stories['closed'] + $product->stories['draft'] + $product->stories['changed']; - $totalRequirements = $product->requirements['active'] + $product->requirements['closed'] + $product->requirements['draft'] + $product->requirements['changed']; + $totalStories = $product->stories['active'] + $product->stories['closed'] + $product->stories['draft'] + $product->stories['changing'] + $product->stories['reviewing']; + $totalRequirements = $product->requirements['active'] + $product->requirements['closed'] + $product->requirements['draft'] + $product->requirements['changing'] + $product->requirements['reviewing']; $trClass = ''; if($product->line) @@ -217,12 +223,14 @@ config->URAndSR):?> - + + - + + diff --git a/module/product/view/browse.html.php b/module/product/view/browse.html.php index 6e21e3e6c8..f234bbdbfd 100644 --- a/module/product/view/browse.html.php +++ b/module/product/view/browse.html.php @@ -290,14 +290,14 @@ $projectIDParam = $isProjectStory ? "projectID=$projectID&" : ''; $canBatchClose = (common::hasPriv($storyType, 'batchClose') and strtolower($browseType) != 'closedbyme' and strtolower($browseType) != 'closedstory'); $canBatchReview = ($canBeChanged and common::hasPriv($storyType, 'batchReview')); $canBatchChangeStage = ($canBeChanged and common::hasPriv('story', 'batchChangeStage') and $storyType == 'story'); - $canBatchChangeBranch = ($canBeChanged and common::hasPriv($storyType, 'batchChangeBranch')); + $canBatchChangeBranch = ($canBeChanged and common::hasPriv($storyType, 'batchChangeBranch') and $this->session->currentProductType and $this->session->currentProductType != 'normal' and $productID); $canBatchChangeModule = ($canBeChanged and common::hasPriv($storyType, 'batchChangeModule')); $canBatchChangePlan = ($canBeChanged and common::hasPriv('story', 'batchChangePlan') and $storyType == 'story'); $canBatchAssignTo = ($canBeChanged and common::hasPriv($storyType, 'batchAssignTo')); $canBatchUnlink = ($canBeChanged and $this->app->tab == 'project' and common::hasPriv('projectstory', 'batchUnlinkStory')); $canBatchImportToLib = ($canBeChanged and $this->app->tab == 'project' and isset($this->config->maxVersion) and common::hasPriv('story', 'batchImportToLib')); - $canBatchAction = ($canBatchEdit or $canBatchClose or $canBatchReview or $canBatchChangeStage or $canBatchChangeModule or $canBatchChangePlan or $canBatchAssignTo or $canBatchUnlink or $canBatchImportToLib); + $canBatchAction = ($canBatchEdit or $canBatchClose or $canBatchReview or $canBatchChangeStage or $canBatchChangeModule or $canBatchChangePlan or $canBatchAssignTo or $canBatchUnlink or $canBatchImportToLib or $canBatchChangeBranch); ?> ';?>
    datatable->showModule;?>datatable->showModuleList, isset($config->datatable->$datatableId->showModule) ? $config->datatable->$datatableId->showModule : '');?>datatable->showModuleList, isset($config->datatable->$datatableId->showModule) ? $config->datatable->$datatableId->showModule : '0');?>
    @@ -89,10 +90,10 @@ pri;?>' title='story->priList, $story->pri, $story->pri);?>'>story->priList, $story->pri, $story->pri);?> - title, null, "style='color: $story->color' data-group='product'") : "$story->title";?> + title, null, "style='color: $story->color' data-group='product' title='$story->title'") : "$story->title";?> children)) echo '';?> productTitle;?>productTitle;?> openedBy);?> estimate . $config->hourUnit;?> processStatus('story', $story);?>
    - -
    - - -
    - + id);?>
    pri;?>' title='story->priList, $child->pri, $child->pri);?>'>story->priList, $child->pri, $child->pri);?> - lang->story->children .'">SR ' . (common::hasPriv('story', 'view') ? html::a($storyLink, $child->title, null, "style='color: $child->color' data-group='product'") : $child->title);?> + lang->story->children .'">SR ' . (common::hasPriv('story', 'view') ? html::a($storyLink, $child->title, null, "style='color: $child->color' data-group='product' title='$child->title'") : $child->title);?> productTitle;?>productTitle;?> openedBy);?> estimate . $config->hourUnit;?> URChanged ? "{$this->lang->story->URChanged}" : "" . $this->processStatus('story', $child) . ''?>
    id);?>createLink('testtask', 'view', "taskID=$task->id"), $task->name);?>executionName?>build == 'trunk' ? print($lang->trunk) : print(html::a($this->createLink('build', 'view', "buildID=$task->build"), $task->buildName));?>createLink('testtask', 'view', "taskID=$task->id"), $task->name);?>executionName;?>trunk : $task->buildName;?>'>build == 'trunk' ? print($lang->trunk) : print(html::a($this->createLink('build', 'view', "buildID=$task->build"), $task->buildName));?> begin?> end?>processStatus('testtask', $task);?>'>processStatus('testtask', $task);?> id", $task, 'list', 'sitemap', '', '', '', "data-app='qa'"); diff --git a/module/port/config.php b/module/port/config.php index 2b6ead6da0..98b61d8877 100644 --- a/module/port/config.php +++ b/module/port/config.php @@ -17,7 +17,7 @@ $config->port->datetimeFeilds = ''; $config->port->listFields = ''; $config->port->sysLangFields = ',pri,status,type,mode,severity,os,browser,resolution,confirmed,source,reviewResult,stage,change,category'; $config->port->sysDataFields = 'execution,product,user'; -$config->port->userFields = 'assignedTo,openedBy,finishedBy,canceledBy,closedBy,lastEditedBy,lastRunner,resolvedBy,reviewedBy'; +$config->port->userFields = 'assignedTo,openedBy,finishedBy,canceledBy,closedBy,lastEditedBy,lastRunner,resolvedBy,reviewedBy,mailto'; $config->port->defaultZeroField = 'severity,pri'; $config->port->defaultEmptyField = ''; diff --git a/module/port/control.php b/module/port/control.php index bc8edac653..39257735fb 100644 --- a/module/port/control.php +++ b/module/port/control.php @@ -102,6 +102,9 @@ class port extends control if($_FILES) { $file = $this->loadModel('file')->getUpload('file'); + + if(!empty($file['error'])) return print(js::confirm($this->lang->file->uploadError[$file['error']])); + $file = $file[0]; $shortName = $this->file->getSaveName($file['pathname']); diff --git a/module/port/model.php b/module/port/model.php index 1112e36cba..f93951a470 100644 --- a/module/port/model.php +++ b/module/port/model.php @@ -269,6 +269,12 @@ class portModel extends model $modelFieldList['values'] = $this->initValues($model, $field, $modelFieldList, $withKey); $fieldList[$field] = $modelFieldList; } + + if(!empty($fieldList['mailto'])) + { + $fieldList['mailto']['control'] = 'multiple'; + $fieldList['mailto']['values'] = $this->portConfig->sysDataList['user']; + } return $fieldList; } @@ -403,7 +409,11 @@ class portModel extends model $sysDataFields = explode(',', $this->portConfig->sysDataFields); - foreach($sysDataFields as $field) $dataList[$field] = $this->loadModel($field)->getPairs(); + foreach($sysDataFields as $field) + { + $dataList[$field] = $this->loadModel($field)->getPairs(); + if($field == 'user') $dataList[$field] = $this->loadModel($field)->getPairs('noclosed|nodeleted|noletter'); + } return $dataList; } @@ -479,7 +489,7 @@ class portModel extends model { $getParams = $this->session->{$model . 'PortParams'}; - if($params and $getParams) + if($params) { $params = explode('&', $params); foreach($params as $param => $value) @@ -560,9 +570,12 @@ class portModel extends model { if($fieldList[$field]['control'] == 'multiple') { - $multiple = ''; + $multiple = ''; + $separator = $field == 'mailto' ? ',' : "\n"; $multipleLsit = explode(',', $value); - foreach($multipleLsit as $tmpValue) $multiple .= "\n" . zget($exportDatas[$field], $tmpValue); + + foreach($multipleLsit as $key => $tmpValue) $multipleLsit[$key] = zget($exportDatas[$field], $tmpValue); + $multiple = join($separator, $multipleLsit); $rows[$id]->$field = $multiple; } else @@ -767,9 +780,12 @@ class portModel extends model if(strpos($queryCondition, "`{$this->config->db->prefix}$model` AS t2") !== false) $selectKey = 't2.id'; $stmt = $this->dbh->query($queryCondition . ($this->post->exportType == 'selected' ? " AND $selectKey IN({$this->cookie->checkedItem})" : '')); - while($row = $stmt->fetch()) $modelDatas[$row->id] = $row; + while($row = $stmt->fetch()) + { + if($selectKey !== 't1.id' and isset($row->$model) and isset($row->id)) $row->id = $row->$model; + $modelDatas[$row->id] = $row; + } } - return $modelDatas; } @@ -1273,7 +1289,7 @@ class portModel extends model $control = $value['control']; $values = $value['values']; $name = "{$field}[$row]"; - $selected = !empty($object->$field) ? $object->$field : ''; + $selected = isset($object->$field) ? $object->$field : ''; if($model) { if($control == 'hidden' and isset($this->session->{$model.'PortParams'}[$field. 'ID'])) $selected = $this->session->{$model . 'PortParams'}[$field. 'ID']; diff --git a/module/product/config.php b/module/product/config.php index c86e3890e7..bb08427abd 100644 --- a/module/product/config.php +++ b/module/product/config.php @@ -149,8 +149,8 @@ $config->product->report->planLabels = array(); $config->product->report->planLabels[] = ''; $config->product->statisticFields = array(); -$config->product->statisticFields['requirements'] = array('draftRequirements', 'activeRequirements', 'changedRequirements', 'closedRequirements'); -$config->product->statisticFields['stories'] = array('draftStories', 'activeStories', 'changedStories', 'closedStories'); +$config->product->statisticFields['requirements'] = array('draftRequirements', 'activeRequirements', 'changingRequirements', 'reviewingRequirements', 'closedRequirements'); +$config->product->statisticFields['stories'] = array('draftStories', 'activeStories', 'changingStories', 'reviewingStories', 'closedStories'); $config->product->statisticFields['bugs'] = array('unResolvedBugs', 'closedBugs', 'fixedBugs'); $config->product->statisticFields['plans'] = array('plans'); $config->product->statisticFields['releases'] = array('releases'); diff --git a/module/product/control.php b/module/product/control.php index 8774ee920f..ee3d3e1427 100644 --- a/module/product/control.php +++ b/module/product/control.php @@ -223,6 +223,7 @@ class product extends control /* Append id for secend sort. */ $sort = common::appendOrder($orderBy); + if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort); /* Load pager. */ $this->app->loadClass('pager', $static = true); @@ -443,7 +444,6 @@ class product extends control /* Init vars. */ $product = $this->product->getById($productID); - if($product->bind) $this->config->product->edit->requiredFields = 'name'; $unmodifiableProjects = array(); $canChangeProgram = true; @@ -1450,27 +1450,27 @@ class product extends control $productStats = $this->product->getStats('program_desc,line_desc,' . $orderBy, null, $status); foreach($productStats as $i => $product) { - $product->line = zget($lines, $product->line, ''); + $product->line = zget($lines, $product->line, ''); if($this->config->URAndSR) { $product->activeRequirements = (int) $product->requirements['active']; - $product->changedRequirements = (int) $product->requirements['changed']; + $product->changedRequirements = (int) $product->requirements['changing']; $product->draftRequirements = (int) $product->requirements['draft']; $product->closedRequirements = (int) $product->requirements['closed']; $product->totalRequirements = $product->activeRequirements + $product->changedRequirements + $product->draftRequirements + $product->closedRequirements; $product->requireCompleteRate = ($product->totalRequirements == 0 ? 0 : round($product->closedRequirements / $product->totalRequirements, 3) * 100) . '%'; } - $product->activeStories = (int)$product->stories['active']; - $product->changedStories = (int)$product->stories['changed']; - $product->draftStories = (int)$product->stories['draft']; - $product->closedStories = (int)$product->stories['closed']; - $product->totalStories = $product->activeStories + $product->changedStories + $product->draftStories + $product->closedStories; - $product->storyCompleteRate = ($product->totalStories == 0 ? 0 : round($product->closedStories / $product->totalStories, 3) * 100) . '%'; - $product->unResolvedBugs = (int)$product->unResolved; - $product->assignToNullBugs = (int)$product->assignToNull; - $product->closedBugs = (int)$product->closedBugs; - $product->bugFixedRate = (($product->unResolved + $product->fixedBugs) == 0 ? 0 : round($product->fixedBugs / ($product->unResolved + $product->fixedBugs), 3) * 100) . '%'; - $product->program = $product->programName; + $product->activeStories = (int)$product->stories['active']; + $product->changedStories = (int)$product->stories['changing']; + $product->draftStories = (int)$product->stories['draft']; + $product->closedStories = (int)$product->stories['closed']; + $product->totalStories = $product->activeStories + $product->changedStories + $product->draftStories + $product->closedStories; + $product->storyCompleteRate = ($product->totalStories == 0 ? 0 : round($product->closedStories / $product->totalStories, 3) * 100) . '%'; + $product->unResolvedBugs = (int)$product->unResolved; + $product->assignToNullBugs = (int)$product->assignToNull; + $product->closedBugs = (int)$product->closedBugs; + $product->bugFixedRate = (($product->unResolved + $product->fixedBugs) == 0 ? 0 : round($product->fixedBugs / ($product->unResolved + $product->fixedBugs), 3) * 100) . '%'; + $product->program = $product->programName; /* get rowspan data */ if($lastProgram == '' or $product->program != $lastProgram) diff --git a/module/product/css/browse.css b/module/product/css/browse.css index 1c3707a691..c2a8328f56 100644 --- a/module/product/css/browse.css +++ b/module/product/css/browse.css @@ -39,3 +39,4 @@ a.removeModule:hover {color: red;} #batchUnlinkStoryTip .table th:first-child {width: 460px;} #mainMenu .dropdown-menu>li>a>.icon {top: 4px;} #productStoryForm tbody tr td .label {max-width: 100px; text-overflow: unset;} +.c-span {margin-left: 19px;} diff --git a/module/product/lang/de.php b/module/product/lang/de.php index e6f048368b..a9adf7e665 100644 --- a/module/product/lang/de.php +++ b/module/product/lang/de.php @@ -134,21 +134,22 @@ $lang->product->createdDate = 'Created Date'; $lang->product->createdVersion = 'Created Version'; $lang->product->mailto = 'Mailto'; -$lang->product->searchStory = 'Suche'; -$lang->product->assignedToMe = 'Mir zuweisen'; -$lang->product->openedByMe = 'Von mir erstellt'; -$lang->product->reviewedByMe = 'Von mir geprüft'; -$lang->product->reviewByMe = 'ReviewByMe'; -$lang->product->closedByMe = 'Von mir geschlossen'; -$lang->product->draftStory = 'Entwurf'; -$lang->product->activeStory = 'Aktiviert'; -$lang->product->changedStory = 'Geändert'; -$lang->product->willClose = 'Zu schließen'; -$lang->product->closedStory = 'Geschlossen'; -$lang->product->unclosed = 'Offen'; -$lang->product->unplan = 'Warten'; -$lang->product->viewByUser = 'By User'; -$lang->product->assignedByMe = 'AssignedByMe'; +$lang->product->searchStory = 'Suche'; +$lang->product->assignedToMe = 'Mir zuweisen'; +$lang->product->openedByMe = 'Von mir erstellt'; +$lang->product->reviewedByMe = 'Von mir geprüft'; +$lang->product->reviewByMe = 'ReviewByMe'; +$lang->product->closedByMe = 'Von mir geschlossen'; +$lang->product->draftStory = 'Entwurf'; +$lang->product->activeStory = 'Aktiviert'; +$lang->product->changingStory = 'Ändern'; +$lang->product->reviewingStory = 'Wird geprüft'; +$lang->product->willClose = 'Zu schließen'; +$lang->product->closedStory = 'Geschlossen'; +$lang->product->unclosed = 'Offen'; +$lang->product->unplan = 'Warten'; +$lang->product->viewByUser = 'By User'; +$lang->product->assignedByMe = 'AssignedByMe'; /* Product Kanban. */ $lang->product->myProduct = 'Products Ownedbyme'; @@ -219,9 +220,10 @@ $lang->product->featureBar['all']['all'] = $lang->product->allProduct; $lang->product->featureBar['all']['noclosed'] = $lang->product->unclosed; $lang->product->featureBar['all']['closed'] = $lang->product->statusList['closed']; -$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe; -$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe; -$lang->product->moreSelects['activestory'] = $lang->product->activeStory; -$lang->product->moreSelects['changedstory'] = $lang->product->changedStory; -$lang->product->moreSelects['willclose'] = $lang->product->willClose; -$lang->product->moreSelects['closedstory'] = $lang->product->closedStory; +$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe; +$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe; +$lang->product->moreSelects['activestory'] = $lang->product->activeStory; +$lang->product->moreSelects['changingstory'] = $lang->product->changingStory; +$lang->product->moreSelects['reviewingstory'] = $lang->product->reviewingStory; +$lang->product->moreSelects['willclose'] = $lang->product->willClose; +$lang->product->moreSelects['closedstory'] = $lang->product->closedStory; diff --git a/module/product/lang/en.php b/module/product/lang/en.php index 0de635095b..5f07eb8736 100644 --- a/module/product/lang/en.php +++ b/module/product/lang/en.php @@ -134,21 +134,22 @@ $lang->product->createdDate = 'createdDate'; $lang->product->createdVersion = 'Created Version'; $lang->product->mailto = 'Mailto'; -$lang->product->searchStory = 'Search'; -$lang->product->assignedToMe = 'AssignedToMe'; -$lang->product->openedByMe = 'CreatedByMe'; -$lang->product->reviewedByMe = 'ReviewedByMe'; -$lang->product->reviewByMe = 'ReviewByMe'; -$lang->product->closedByMe = 'ClosedByMe'; -$lang->product->draftStory = 'Draft'; -$lang->product->activeStory = 'Activated'; -$lang->product->changedStory = 'Changed'; -$lang->product->willClose = 'ToBeClosed'; -$lang->product->closedStory = 'Closed'; -$lang->product->unclosed = 'Open'; -$lang->product->unplan = 'Unplanned'; -$lang->product->viewByUser = 'By User'; -$lang->product->assignedByMe = 'AssignedByMe'; +$lang->product->searchStory = 'Search'; +$lang->product->assignedToMe = 'AssignedToMe'; +$lang->product->openedByMe = 'CreatedByMe'; +$lang->product->reviewedByMe = 'ReviewedByMe'; +$lang->product->reviewByMe = 'ReviewByMe'; +$lang->product->closedByMe = 'ClosedByMe'; +$lang->product->draftStory = 'Draft'; +$lang->product->activeStory = 'Activated'; +$lang->product->changingStory = 'Changing'; +$lang->product->reviewingStory = 'Reviewing'; +$lang->product->willClose = 'ToBeClosed'; +$lang->product->closedStory = 'Closed'; +$lang->product->unclosed = 'Open'; +$lang->product->unplan = 'Unplanned'; +$lang->product->viewByUser = 'By User'; +$lang->product->assignedByMe = 'AssignedByMe'; /* Product Kanban. */ $lang->product->myProduct = 'Products Ownedbyme'; @@ -219,9 +220,10 @@ $lang->product->featureBar['all']['all'] = $lang->product->allProduct; $lang->product->featureBar['all']['noclosed'] = $lang->product->unclosed; $lang->product->featureBar['all']['closed'] = $lang->product->statusList['closed']; -$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe; -$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe; -$lang->product->moreSelects['activestory'] = $lang->product->activeStory; -$lang->product->moreSelects['changedstory'] = $lang->product->changedStory; -$lang->product->moreSelects['willclose'] = $lang->product->willClose; -$lang->product->moreSelects['closedstory'] = $lang->product->closedStory; +$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe; +$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe; +$lang->product->moreSelects['activestory'] = $lang->product->activeStory; +$lang->product->moreSelects['changingstory'] = $lang->product->changingStory; +$lang->product->moreSelects['reviewingstory'] = $lang->product->reviewingStory; +$lang->product->moreSelects['willclose'] = $lang->product->willClose; +$lang->product->moreSelects['closedstory'] = $lang->product->closedStory; diff --git a/module/product/lang/fr.php b/module/product/lang/fr.php index 822e86edda..fc9b29549d 100644 --- a/module/product/lang/fr.php +++ b/module/product/lang/fr.php @@ -134,21 +134,22 @@ $lang->product->createdDate = 'Créé le'; $lang->product->createdVersion = 'Created Version'; $lang->product->mailto = 'Mailto'; -$lang->product->searchStory = 'Recherche'; -$lang->product->assignedToMe = 'Affectées à Moi'; -$lang->product->openedByMe = 'Créées par Moi'; -$lang->product->reviewedByMe = 'Validées par Moi'; -$lang->product->reviewByMe = 'ReviewByMe'; -$lang->product->closedByMe = 'Fermées par Moi'; -$lang->product->draftStory = 'A étudier'; -$lang->product->activeStory = 'Actives'; -$lang->product->changedStory = 'Changées'; -$lang->product->willClose = 'A Fermer'; -$lang->product->closedStory = 'Fermées'; -$lang->product->unclosed = 'Ouvertes'; -$lang->product->unplan = 'Non planifiées'; -$lang->product->viewByUser = 'Par Utilisateur'; -$lang->product->assignedByMe = 'AssignedByMe'; +$lang->product->searchStory = 'Recherche'; +$lang->product->assignedToMe = 'Affectées à Moi'; +$lang->product->openedByMe = 'Créées par Moi'; +$lang->product->reviewedByMe = 'Validées par Moi'; +$lang->product->reviewByMe = 'ReviewByMe'; +$lang->product->closedByMe = 'Fermées par Moi'; +$lang->product->draftStory = 'A étudier'; +$lang->product->activeStory = 'Actives'; +$lang->product->changingStory = 'Changement en cours'; +$lang->product->reviewingStory = 'Examen en cours'; +$lang->product->willClose = 'A Fermer'; +$lang->product->closedStory = 'Fermées'; +$lang->product->unclosed = 'Ouvertes'; +$lang->product->unplan = 'Non planifiées'; +$lang->product->viewByUser = 'Par Utilisateur'; +$lang->product->assignedByMe = 'AssignedByMe'; /* Product Kanban. */ $lang->product->myProduct = 'Products Ownedbyme'; @@ -219,9 +220,10 @@ $lang->product->featureBar['all']['all'] = $lang->product->allProduct; $lang->product->featureBar['all']['noclosed'] = $lang->product->unclosed; $lang->product->featureBar['all']['closed'] = $lang->product->statusList['closed']; -$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe; -$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe; -$lang->product->moreSelects['activestory'] = $lang->product->activeStory; -$lang->product->moreSelects['changedstory'] = $lang->product->changedStory; -$lang->product->moreSelects['willclose'] = $lang->product->willClose; -$lang->product->moreSelects['closedstory'] = $lang->product->closedStory; +$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe; +$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe; +$lang->product->moreSelects['activestory'] = $lang->product->activeStory; +$lang->product->moreSelects['changingstory'] = $lang->product->changingStory; +$lang->product->moreSelects['reviewingstory'] = $lang->product->reviewingStory; +$lang->product->moreSelects['willclose'] = $lang->product->willClose; +$lang->product->moreSelects['closedstory'] = $lang->product->closedStory; diff --git a/module/product/lang/vi.php b/module/product/lang/vi.php index 126ea41ec2..718c9a68a6 100644 --- a/module/product/lang/vi.php +++ b/module/product/lang/vi.php @@ -115,19 +115,20 @@ $lang->product->iterationView = 'Chi tiết'; $lang->product->createdBy = 'Người tạo'; $lang->product->createdDate = 'Ngày tạo'; -$lang->product->searchStory = 'Tìm kiếm'; -$lang->product->assignedToMe = 'Giao cho bạn'; -$lang->product->openedByMe = 'Tạo bởi bạn'; -$lang->product->reviewedByMe = 'Duyệt bởi bạn'; -$lang->product->closedByMe = 'Đóng bởi bạn'; -$lang->product->draftStory = 'Nháp'; -$lang->product->activeStory = 'Đã kích hoạt'; -$lang->product->changedStory = 'Đã thay đổi'; -$lang->product->willClose = 'Đã đóng'; -$lang->product->closedStory = 'Đã đóng'; -$lang->product->unclosed = 'Mở'; -$lang->product->unplan = 'Chưa kế hoạch'; -$lang->product->viewByUser = 'Theo người dùng'; +$lang->product->searchStory = 'Tìm kiếm'; +$lang->product->assignedToMe = 'Giao cho bạn'; +$lang->product->openedByMe = 'Tạo bởi bạn'; +$lang->product->reviewedByMe = 'Duyệt bởi bạn'; +$lang->product->closedByMe = 'Đóng bởi bạn'; +$lang->product->draftStory = 'Nháp'; +$lang->product->activeStory = 'Đã kích hoạt'; +$lang->product->changingStory = 'Biến'; +$lang->product->reviewingStory = 'Đang xem xét'; +$lang->product->willClose = 'Đã đóng'; +$lang->product->closedStory = 'Đã đóng'; +$lang->product->unclosed = 'Mở'; +$lang->product->unplan = 'Chưa kế hoạch'; +$lang->product->viewByUser = 'Theo người dùng'; $lang->product->allStory = 'Tất cả '; $lang->product->allProduct = 'Tất cả'; @@ -177,8 +178,9 @@ $lang->product->featureBar['all']['all'] = $lang->product->allProduct; $lang->product->featureBar['all']['noclosed'] = $lang->product->unclosed; $lang->product->featureBar['all']['closed'] = $lang->product->statusList['closed']; -$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe; -$lang->product->moreSelects['activestory'] = $lang->product->activeStory; -$lang->product->moreSelects['changedstory'] = $lang->product->changedStory; -$lang->product->moreSelects['willclose'] = $lang->product->willClose; -$lang->product->moreSelects['closedstory'] = $lang->product->closedStory; +$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe; +$lang->product->moreSelects['activestory'] = $lang->product->activeStory; +$lang->product->moreSelects['changingstory'] = $lang->product->changingStory; +$lang->product->moreSelects['reviewingstory'] = $lang->product->reviewingStory; +$lang->product->moreSelects['willclose'] = $lang->product->willClose; +$lang->product->moreSelects['closedstory'] = $lang->product->closedStory; diff --git a/module/product/lang/zh-cn.php b/module/product/lang/zh-cn.php index 65124c9a9d..e5c1184c44 100644 --- a/module/product/lang/zh-cn.php +++ b/module/product/lang/zh-cn.php @@ -134,21 +134,22 @@ $lang->product->createdDate = '创建日期'; $lang->product->createdVersion = '创建版本'; $lang->product->mailto = '抄送给'; -$lang->product->searchStory = '搜索'; -$lang->product->assignedToMe = '指给我'; -$lang->product->openedByMe = '我创建'; -$lang->product->reviewedByMe = '我评审'; -$lang->product->reviewByMe = '待我评审'; -$lang->product->closedByMe = '我关闭'; -$lang->product->draftStory = '草稿'; -$lang->product->activeStory = '激活'; -$lang->product->changedStory = '已变更'; -$lang->product->willClose = '待关闭'; -$lang->product->closedStory = '已关闭'; -$lang->product->unclosed = '未关闭'; -$lang->product->unplan = "未计划"; -$lang->product->viewByUser = '按用户查看'; -$lang->product->assignedByMe = '我指派'; +$lang->product->searchStory = '搜索'; +$lang->product->assignedToMe = '指给我'; +$lang->product->openedByMe = '我创建'; +$lang->product->reviewedByMe = '我评审'; +$lang->product->reviewByMe = '待我评审'; +$lang->product->closedByMe = '我关闭'; +$lang->product->draftStory = '草稿'; +$lang->product->activeStory = '激活'; +$lang->product->changingStory = '变更中'; +$lang->product->reviewingStory = '评审中'; +$lang->product->willClose = '待关闭'; +$lang->product->closedStory = '已关闭'; +$lang->product->unclosed = '未关闭'; +$lang->product->unplan = "未计划"; +$lang->product->viewByUser = '按用户查看'; +$lang->product->assignedByMe = '我指派'; /* Product Kanban. */ $lang->product->myProduct = '我负责的' . $lang->productCommon; @@ -219,9 +220,10 @@ $lang->product->featureBar['all']['all'] = '所有' . $lang->productCommon; $lang->product->featureBar['all']['noclosed'] = $lang->product->unclosed; $lang->product->featureBar['all']['closed'] = $lang->product->statusList['closed']; -$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe; -$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe; -$lang->product->moreSelects['activestory'] = $lang->product->activeStory; -$lang->product->moreSelects['changedstory'] = $lang->product->changedStory; -$lang->product->moreSelects['willclose'] = $lang->product->willClose; -$lang->product->moreSelects['closedstory'] = $lang->product->closedStory; +$lang->product->moreSelects['assignedbyme'] = $lang->product->assignedByMe; +$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe; +$lang->product->moreSelects['activestory'] = $lang->product->activeStory; +$lang->product->moreSelects['changingstory'] = $lang->product->changingStory; +$lang->product->moreSelects['reviewingstory'] = $lang->product->reviewingStory; +$lang->product->moreSelects['willclose'] = $lang->product->willClose; +$lang->product->moreSelects['closedstory'] = $lang->product->closedStory; diff --git a/module/product/lang/zh-tw.php b/module/product/lang/zh-tw.php index 1e7d868f2b..7b568db8e5 100644 --- a/module/product/lang/zh-tw.php +++ b/module/product/lang/zh-tw.php @@ -126,20 +126,20 @@ $lang->product->createdDate = '創建日期'; $lang->product->createdVersion = '創建版本'; $lang->product->mailto = '抄送給'; -$lang->product->searchStory = '搜索'; -$lang->product->assignedToMe = '指給我'; -$lang->product->openedByMe = '我創建'; -$lang->product->reviewedByMe = '我評審'; -$lang->product->reviewByMe = '待我評審'; -$lang->product->closedByMe = '我關閉'; -$lang->product->draftStory = '草稿'; -$lang->product->activeStory = '激活'; -$lang->product->changedStory = '已變更'; -$lang->product->willClose = '待關閉'; -$lang->product->closedStory = '已關閉'; -$lang->product->unclosed = '未關閉'; -$lang->product->unplan = "未計劃"; -$lang->product->viewByUser = '按用戶查看'; +$lang->product->searchStory = '搜索'; +$lang->product->assignedToMe = '指給我'; +$lang->product->openedByMe = '我創建'; +$lang->product->reviewedByMe = '我評審'; +$lang->product->reviewByMe = '待我評審'; +$lang->product->closedByMe = '我關閉'; +$lang->product->draftStory = '草稿'; +$lang->product->activeStory = '激活'; +$lang->product->changingStory = '變更中'; +$lang->product->willClose = '待關閉'; +$lang->product->closedStory = '已關閉'; +$lang->product->unclosed = '未關閉'; +$lang->product->unplan = "未計劃"; +$lang->product->viewByUser = '按用戶查看'; /* Product Kanban. */ $lang->product->myProduct = '我負責的' . $lang->productCommon; @@ -210,8 +210,8 @@ $lang->product->featureBar['all']['all'] = '所有' . $lang->productCommon; $lang->product->featureBar['all']['noclosed'] = $lang->product->unclosed; $lang->product->featureBar['all']['closed'] = $lang->product->statusList['closed']; -$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe; -$lang->product->moreSelects['activestory'] = $lang->product->activeStory; -$lang->product->moreSelects['changedstory'] = $lang->product->changedStory; -$lang->product->moreSelects['willclose'] = $lang->product->willClose; -$lang->product->moreSelects['closedstory'] = $lang->product->closedStory; +$lang->product->moreSelects['closedbyme'] = $lang->product->closedByMe; +$lang->product->moreSelects['activestory'] = $lang->product->activeStory; +$lang->product->moreSelects['changingstory'] = $lang->product->changingStory; +$lang->product->moreSelects['willclose'] = $lang->product->willClose; +$lang->product->moreSelects['closedstory'] = $lang->product->closedStory; diff --git a/module/product/model.php b/module/product/model.php index 3dbd62f65c..84d41ea26e 100644 --- a/module/product/model.php +++ b/module/product/model.php @@ -754,7 +754,6 @@ class productModel extends model { $productID = (int)$productID; $oldProduct = $this->dao->findById($productID)->from(TABLE_PRODUCT)->fetch(); - if($oldProduct->bind) $this->config->product->edit->requiredFields = 'name'; $product = fixer::input('post') ->add('id', $productID) @@ -1019,7 +1018,8 @@ class productModel extends model if($browseType == 'closedbyme') $stories = $this->story->getByClosedBy($productID, $branch, $modules, $this->app->user->account, $type, $sort, $pager); if($browseType == 'draftstory') $stories = $this->story->getByStatus($productID, $branch, $modules, 'draft', $type, $sort, $pager); if($browseType == 'activestory') $stories = $this->story->getByStatus($productID, $branch, $modules, 'active', $type, $sort, $pager); - if($browseType == 'changedstory') $stories = $this->story->getByStatus($productID, $branch, $modules, 'changed', $type, $sort, $pager); + if($browseType == 'changingstory') $stories = $this->story->getByStatus($productID, $branch, $modules, 'changing', $type, $sort, $pager); + if($browseType == 'reviewingstory') $stories = $this->story->getByStatus($productID, $branch, $modules, 'reviewing', $type, $sort, $pager); if($browseType == 'willclose') $stories = $this->story->get2BeClosed($productID, $branch, $modules, $type, $sort, $pager); if($browseType == 'closedstory') $stories = $this->story->getByStatus($productID, $branch, $modules, 'closed', $type, $sort, $pager); if($browseType == 'assignedbyme') $stories = $this->story->getByAssignedBy($productID, $branch, $modules, $this->app->user->account, $type, $sort, $pager); @@ -1077,7 +1077,7 @@ class productModel extends model $modules = array(); $branchList = $this->loadModel('branch')->getPairs($productID, '', $projectID); $branchModuleList = $this->tree->getOptionMenu($productID, 'story', 0, array_keys($branchList)); - foreach($branchModuleList as $branchID => $branchModules) $modules[] = $branchModules; + foreach($branchModuleList as $branchID => $branchModules) $modules = array_merge($modules, $branchModules); } else { @@ -2421,6 +2421,8 @@ class productModel extends model $this->lang->product->menu->settings['subMenu']->branch['link'] = str_replace('@branch@', $this->lang->product->branchName[$product->type], $branchLink); $this->lang->product->branch = sprintf($this->lang->product->branch, $this->lang->product->branchName[$product->type]); } + + if(strpos($extra, 'requirement') !== false) unset($this->lang->product->moreSelects['willclose']); } /** diff --git a/module/product/view/all.html.php b/module/product/view/all.html.php index d22acc3ac8..9e5ece751d 100644 --- a/module/product/view/all.html.php +++ b/module/product/view/all.html.php @@ -51,9 +51,9 @@ product->name);?> config->URAndSR):?> - story->requirement;?>story->requirement;?> story->story;?>story->story;?> bug->common;?> product->plan;?> product->release;?>story->draft;?> story->activate;?> story->change;?>story->statusList['reviewing'];?>
    story->completeRate;?>
    story->draft;?> story->activate;?> story->change;?>story->statusList['reviewing'];?>
    story->completeRate;?>
    bug->activate;?> close;?> % % % % requirements['draft'];?> requirements['active'];?>requirements['changed'];?>requirements['changing'];?>requirements['reviewing'];?> requirements['closed'] / $totalRequirements, 3) * 100;?>% stories['draft'];?> stories['active'];?>stories['changed'];?>stories['changing'];?>stories['reviewing'];?> stories['closed'] / $totalStories, 3) * 100;?>% unResolved;?> closedBugs;?>
    ' id='storyList' data-fixed-left-width='' data-fixed-right-width=''> @@ -388,8 +388,10 @@ $projectIDParam = $isProjectStory ? "projectID=$projectID&" : ''; $disabled = $canBatchEdit ? '' : "disabled='disabled'"; $actionLink = $this->createLink('story', 'batchEdit', "productID=$productID&projectID=$projectID&branch=$branch&storyType=$storyType"); ?> - edit, "data-form-action='$actionLink' $disabled");?> + edit, "data-form-action='$actionLink' $disabled");?> + + - - - - - - - - @@ -158,8 +150,16 @@ - - + + + + + + + + + + systemMode == 'new'):?> diff --git a/module/productplan/control.php b/module/productplan/control.php index d2e5ef4203..559c0d5c85 100644 --- a/module/productplan/control.php +++ b/module/productplan/control.php @@ -421,6 +421,7 @@ class productplan extends control /* Append id for secend sort. */ $orderBy = ($type == 'bug' and $orderBy == 'order_desc') ? 'id_desc' : $orderBy; $sort = common::appendOrder($orderBy); + if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort); $this->commonAction($plan->product, $plan->branch); $products = $this->product->getProductPairsByProject($this->session->project); @@ -688,7 +689,7 @@ class productplan extends control } else { - $allStories = $this->story->getProductStories($this->view->product->id, $plan->branch ? "0,{$plan->branch}" : 0, $moduleID = '0', $status = 'draft,active,changed', 'story', 'id_desc', $hasParent = false, array_keys($planStories), $pager); + $allStories = $this->story->getProductStories($this->view->product->id, $plan->branch ? "0,{$plan->branch}" : 0, '0', 'draft,reviewing,active,changing', 'story', 'id_desc', $hasParent = false, array_keys($planStories), $pager); } $modules = $this->loadModel('tree')->getOptionMenu($plan->product, 'story', 0, 'all'); @@ -724,29 +725,14 @@ class productplan extends control { if($confirm == 'no') { - return print(js::confirm($this->lang->productplan->confirmUnlinkStory, $this->createLink('productplan', 'unlinkstory', "storyID=$storyID&planID=$planID&confirm=yes"))); + return print(js::confirm($this->lang->productplan->confirmUnlinkStory, inlink('unlinkstory', "storyID=$storyID&planID=$planID&confirm=yes"))); } else { $this->productplan->unlinkStory($storyID, $planID); $this->loadModel('action')->create('productplan', $planID, 'unlinkstory', '', $storyID); - /* if ajax request, send result. */ - if($this->server->ajax) - { - if(dao::isError()) - { - $response['result'] = 'fail'; - $response['message'] = dao::getError(); - } - else - { - $response['result'] = 'success'; - $response['message'] = ''; - } - return $this->send($response); - } - return print(js::reload('parent')); + return print(js::locate($this->createLink('productplan', 'view', "planID=$planID&type=story"), 'parent')); } } @@ -763,7 +749,7 @@ class productplan extends control { foreach($this->post->storyIdList as $storyID) $this->productplan->unlinkStory($storyID, $planID); $this->loadModel('action')->create('productplan', $planID, 'unlinkstory', '', implode(',', $this->post->storyIdList)); - echo js::locate($this->createLink('productplan', 'view', "planID=$planID&type=story&orderBy=$orderBy"), 'parent'); + return print(js::locate($this->createLink('productplan', 'view', "planID=$planID&type=story&orderBy=$orderBy"), 'parent')); } /** @@ -866,28 +852,13 @@ class productplan extends control { if($confirm == 'no') { - return print(js::confirm($this->lang->productplan->confirmUnlinkBug, $this->createLink('productplan', 'unlinkbug', "bugID=$bugID&confirm=yes"))); + return print(js::confirm($this->lang->productplan->confirmUnlinkBug, inlink('unlinkbug', "bugID=$bugID&planID=$planID&confirm=yes"))); } else { $this->productplan->unlinkBug($bugID); $this->loadModel('action')->create('productplan', $planID, 'unlinkbug', '', $bugID); - /* if ajax request, send result. */ - if($this->server->ajax) - { - if(dao::isError()) - { - $response['result'] = 'fail'; - $response['message'] = dao::getError(); - } - else - { - $response['result'] = 'success'; - $response['message'] = ''; - } - return $this->send($response); - } return print(js::reload('parent')); } } @@ -905,7 +876,7 @@ class productplan extends control { foreach($this->post->bugIDList as $bugID) $this->productplan->unlinkBug($bugID); $this->loadModel('action')->create('productplan', $planID, 'unlinkbug', '', implode(',', $this->post->bugIDList)); - echo js::locate($this->createLink('productplan', 'view', "planID=$planID&type=bug&orderBy=$orderBy"), 'parent'); + return print(js::locate($this->createLink('productplan', 'view', "planID=$planID&type=bug&orderBy=$orderBy"), 'parent')); } /** diff --git a/module/productplan/model.php b/module/productplan/model.php index 81e5f7ac69..54ff91e7b5 100644 --- a/module/productplan/model.php +++ b/module/productplan/model.php @@ -1025,7 +1025,7 @@ class productplanModel extends model { foreach($planStory as $id => $story) { - if($story->status == 'draft') + if($story->status == 'draft' or $story->status == 'reviewing') { unset($planStory[$id]); continue; diff --git a/module/productplan/view/view.html.php b/module/productplan/view/view.html.php index 815900cdc4..dfc20fdf79 100644 --- a/module/productplan/view/view.html.php +++ b/module/productplan/view/view.html.php @@ -205,8 +205,8 @@ createLink('productplan', 'unlinkStory', "story=$story->id&plan=$plan->id&confirm=yes"); - echo html::a("javascript:ajaxDelete(\"$unlinkURL\", \"storyList\", confirmUnlinkStory)", '', '', "class='btn' title='{$lang->productplan->unlinkStory}'"); + $unlinkURL = $this->createLink('productplan', 'unlinkStory', "story=$story->id&plan=$plan->id"); + echo html::a($unlinkURL, '', 'hiddenwin', "class='btn' title='{$lang->productplan->unlinkStory}'"); } ?> @@ -473,8 +473,8 @@ createLink('productplan', 'unlinkBug', "bugID=$bug->id&planID=$plan->id&confirm=yes"); - echo html::a("javascript:ajaxDelete(\"$unlinkURL\", \"bugList\", confirmUnlinkBug)", '', '', "class='btn' title='{$lang->productplan->unlinkBug}'"); + $unlinkURL = $this->createLink('productplan', 'unlinkBug', "bugID=$bug->id&planID=$plan->id"); + echo html::a($unlinkURL, '', 'hiddenwin', "class='btn' title='{$lang->productplan->unlinkBug}'"); } ?> diff --git a/module/program/js/common.js b/module/program/js/common.js index 17b3a4acf1..46541b6234 100644 --- a/module/program/js/common.js +++ b/module/program/js/common.js @@ -283,7 +283,7 @@ $(function() if($(this).prop('checked')) { $('#budget').val('').attr('disabled', 'disabled'); - if($('#beyondBudgetTip').length > 0) $('#beyondBudgetTip').remove(); + if($('#beyondBudgetTip').length > 0) $('#beyondBudgetTip').parent().parent().remove(); } else { @@ -362,14 +362,15 @@ function compareChildDate() var dateTip = ''; if(programBegin > childBegin) { - dateTip = "

    " + beginGreateChild + childInfo.minChildBegin + "

    " + ignore + "

    "; + dateTip = ""; } else if(programEnd < childEnd) { - dateTip = "

    " + endLetterChild + childInfo.maxChildEnd + "

    " + ignore + "

    "; + dateTip = ""; } - $('#dateBox').after(dateTip); + $('#dateBox').parent().parent().after(dateTip); + $('#dateTip').parent().css('line-height', '0'); }); } } @@ -386,7 +387,7 @@ function outOfDateTip() var end = $('#end').val(); var begin = $('#begin').val(); - if($('#dateTip').length > 0) $('#dateTip').remove(); + if($('#dateTip').length > 0) $('#dateTip').parent().parent().remove(); if(end == longTime) end = LONG_TIME; if(end.length > 0 && begin.length > 0) @@ -417,14 +418,15 @@ function outOfDateTip() if(programBegin < parentBegin) { - dateTip = "

    " + beginLetterParent + data.selectedProgramBegin + "

    " + ignore + "

    "; + dateTip = ""; } else if(programEnd > parentEnd) { - dateTip = "

    " + endGreaterParent + data.selectedProgramEnd + "

    " + ignore + "

    "; + dateTip = ""; } - $('#dateBox').after(dateTip); + $('#dateBox').parent().parent().after(dateTip); + $('#dateTip').parent().css('line-height', '0'); }); } } @@ -443,7 +445,7 @@ function budgetOverrunTips() var budget = $('#budget').val(); if(selectedProgramID == 0) { - if($('#beyondBudgetTip').length > 0) $('#beyondBudgetTip').remove(); + if($('#beyondBudgetTip').length > 0) $('#beyondBudgetTip').parent().parent().remove(); return false; } @@ -453,9 +455,10 @@ function budgetOverrunTips() var data = JSON.parse(data); var tip = ""; - if(budget !=0 && budget !== null && budget > data.availableBudget) var tip = "

    " + budgetOverrun + currencySymbol[data.budgetUnit] + data.availableBudget + "

    " + ignore + "

    " - if($('#beyondBudgetTip').length > 0) $('#beyondBudgetTip').remove(); - $('#budgetBox').after(tip); + if(budget !=0 && budget !== null && budget > data.availableBudget) var tip = "" + if($('#beyondBudgetTip').length > 0) $('#beyondBudgetTip').parent().parent().remove(); + $('#budgetBox').parent().parent().after(tip); + $('#beyondBudgetTip').parent().css('line-height', '0'); }); } diff --git a/module/program/model.php b/module/program/model.php index 7d051e6e65..31e2a26a72 100644 --- a/module/program/model.php +++ b/module/program/model.php @@ -1570,10 +1570,10 @@ class programModel extends model $menu .= "
    "; $menu .= ""; $menu .= "
    stories['active'] + $product->stories['closed'] + $product->stories['draft'] + $product->stories['changed']; - $totalRequirements = $product->requirements['active'] + $product->requirements['closed'] + $product->requirements['draft'] + $product->requirements['changed']; + $totalStories = $product->stories['active'] + $product->stories['closed'] + $product->stories['draft'] + $product->stories['changing']; + $totalRequirements = $product->requirements['active'] + $product->requirements['closed'] + $product->requirements['draft'] + $product->requirements['changing']; ?> - + - + diff --git a/module/programplan/lang/de.php b/module/programplan/lang/de.php index baf6b38a65..cdeca0b092 100644 --- a/module/programplan/lang/de.php +++ b/module/programplan/lang/de.php @@ -99,3 +99,7 @@ $lang->programplan->error->parentWorkload = 'The sum of the workload of the chi $lang->programplan->error->parentDuration = 'The planned start and planned completion of the child phase cannot exceed the parent phase.'; $lang->programplan->error->sameName = 'Stage name cannot be the same!'; $lang->programplan->error->taskDrag = 'The %s task cannot be dragged'; +$lang->programplan->error->planDrag = 'The %s stage cannot be dragged'; + +$lang->programplan->ganttBrowseType['gantt'] = 'Group by Stage'; +$lang->programplan->ganttBrowseType['assignedTo'] = 'Group by AssignedTo'; diff --git a/module/programplan/lang/en.php b/module/programplan/lang/en.php index b8671eb7c9..faf009d05a 100644 --- a/module/programplan/lang/en.php +++ b/module/programplan/lang/en.php @@ -99,3 +99,7 @@ $lang->programplan->error->parentWorkload = 'The sum of the workload in the sub $lang->programplan->error->parentDuration = 'The planned start and planned completion of the child phase cannot exceed the parent phase.'; $lang->programplan->error->sameName = 'Stage name cannot be the same!'; $lang->programplan->error->taskDrag = 'The %s task cannot be dragged'; +$lang->programplan->error->planDrag = 'The %s stage cannot be dragged'; + +$lang->programplan->ganttBrowseType['gantt'] = 'Group by Stage'; +$lang->programplan->ganttBrowseType['assignedTo'] = 'Group by AssignedTo'; diff --git a/module/programplan/lang/fr.php b/module/programplan/lang/fr.php index baf6b38a65..cdeca0b092 100644 --- a/module/programplan/lang/fr.php +++ b/module/programplan/lang/fr.php @@ -99,3 +99,7 @@ $lang->programplan->error->parentWorkload = 'The sum of the workload of the chi $lang->programplan->error->parentDuration = 'The planned start and planned completion of the child phase cannot exceed the parent phase.'; $lang->programplan->error->sameName = 'Stage name cannot be the same!'; $lang->programplan->error->taskDrag = 'The %s task cannot be dragged'; +$lang->programplan->error->planDrag = 'The %s stage cannot be dragged'; + +$lang->programplan->ganttBrowseType['gantt'] = 'Group by Stage'; +$lang->programplan->ganttBrowseType['assignedTo'] = 'Group by AssignedTo'; diff --git a/module/programplan/lang/zh-cn.php b/module/programplan/lang/zh-cn.php index 381220a10e..52b3a1bcef 100644 --- a/module/programplan/lang/zh-cn.php +++ b/module/programplan/lang/zh-cn.php @@ -101,6 +101,5 @@ $lang->programplan->error->sameName = '阶段名称不能相同!'; $lang->programplan->error->taskDrag = '%s的任务不可以拖动'; $lang->programplan->error->planDrag = '%s的阶段不可以拖动'; - $lang->programplan->ganttBrowseType['gantt'] = '按阶段分组'; $lang->programplan->ganttBrowseType['assignedTo'] = '按指派给分组'; diff --git a/module/programplan/model.php b/module/programplan/model.php index 2119433318..61d186ffdf 100755 --- a/module/programplan/model.php +++ b/module/programplan/model.php @@ -205,7 +205,7 @@ class programplanModel extends model $data->textColor = $this->lang->execution->gantt->stage->textColor; $data->bar_height = $this->lang->execution->gantt->bar_height; - if($data->endDate > $data->start_date) $data->duration = helper::diffDate($data->endDate, $data->start_date) + 1; + if($data->endDate > $data->start_date) $data->duration = helper::diffDate(substr($data->endDate, 0, 10), substr($data->start_date, 0, 10)) + 1; if($data->start_date) $data->start_date = date('d-m-Y', strtotime($data->start_date)); if($data->start_date == '' or $data->endDate == '') $data->duration = 1; @@ -294,7 +294,7 @@ class programplanModel extends model $data->owner_id = join(',', $assigneds); } - if($data->endDate > $data->start_date) $data->duration = helper::diffDate($data->endDate, $data->start_date) + 1; + if($data->endDate > $data->start_date) $data->duration = helper::diffDate(substr($data->endDate, 0, 10), substr($data->start_date, 0, 10)) + 1; if($data->start_date) $data->start_date = date('d-m-Y', strtotime($data->start_date)); if($data->start_date == '' or $data->endDate == '') $data->duration = 1; diff --git a/module/project/control.php b/module/project/control.php index 85af2716bf..887b3d90f4 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -476,7 +476,7 @@ class project extends control { foreach($planStory as $id => $story) { - if($story->status == 'draft') + if($story->status == 'draft' or $story->status == 'reviewing') { unset($planStory[$id]); continue; diff --git a/module/project/js/common.js b/module/project/js/common.js index ce90160378..a0c7b3c6fc 100644 --- a/module/project/js/common.js +++ b/module/project/js/common.js @@ -2,6 +2,7 @@ window.ignoreTips = { 'beyondBudgetTip' : false, 'dateTip' : false }; +var batchEditDateTips = new Array(); /** * Access rights are equal to private, and the white list settings are displayed. @@ -295,7 +296,7 @@ $(function() if($(this).prop('checked')) { $('#budget').val('').attr('disabled', 'disabled'); - if($('#beyondBudgetTip').length > 0) $('#beyondBudgetTip').remove(); + if($('#beyondBudgetTip').length > 0) $('#beyondBudgetTip').parent().parent().remove(); } else { @@ -340,7 +341,7 @@ function budgetOverrunTips() if(selectedProgramID == 0) { - if($('#beyondBudgetTip').length > 0) $('#beyondBudgetTip').remove(); + if($('#beyondBudgetTip').length > 0) $('#beyondBudgetTip').parent().parent().remove(); return false; } @@ -351,9 +352,10 @@ function budgetOverrunTips() if(typeof(data.availableBudget) == 'undefined') return; var tip = ""; - if(budget != 0 && budget !== null && budget > data.availableBudget) tip = "

    " + budgetOverrun + currencySymbol[data.budgetUnit] + data.availableBudget.toFixed(2) + "

    " + ignore + "

    " - if($('#beyondBudgetTip').length > 0) $('#beyondBudgetTip').remove(); - $('#budgetBox').after(tip); + if(budget != 0 && budget !== null && budget > data.availableBudget) tip = "" + if($('#beyondBudgetTip').length > 0) $('#beyondBudgetTip').parent().parent().remove(); + $('#budgetBox').parent().parent().after(tip); + $('#beyondBudgetTip').parent().css('line-height', '0'); var placeholder = ''; if(selectedProgramID) placeholder = parentBudget + currencySymbol[data.budgetUnit] + data.availableBudget.toFixed(2); @@ -365,16 +367,18 @@ function budgetOverrunTips() /** *The date is out of the range of the parent project set, and a prompt is given. * - * @param int $currentID + * @param string $currentID * @access public * @return void */ -function outOfDateTip(currentID = 0) +function outOfDateTip(currentID) { if(window.ignoreTips['dateTip']) return; + if(batchEditDateTips.includes(Number(currentID))) return; + var end = currentID ? $('#ends\\[' + currentID + '\\]').val() : $('#end').val(); var begin = currentID ? $('#begins\\[' + currentID + '\\]').val() : $('#begin').val(); - if($('#dateTip.text-remind').length > 0) $('#dateTip').remove(); + if($('#dateTip.text-remind').length > 0) $('#dateTip').parent().parent().remove(); if(currentID) $('#dateTip\\[' + currentID + '\\]').remove(); if(end == longTime) end = LONG_TIME; @@ -402,20 +406,22 @@ function outOfDateTip(currentID = 0) var dateTip = ""; if(projectBegin < parentBegin) { - dateTip = currentID ? beginLetterParentTip + "'>" + beginLetterParentTip : beginLetterParentTip; + dateTip = currentID ? beginLetterParentTip + "'>

    " + beginLetterParentTip : beginLetterParentTip; } else if(projectEnd > parentEnd) { - dateTip = currentID ? endGreaterParentTip + "'>" + endGreaterParentTip : endGreaterParentTip; + dateTip = currentID ? endGreaterParentTip + "'>

    " + endGreaterParentTip : endGreaterParentTip; } if(currentID) { - $("#projects\\[" + currentID + "\\]").after("

    "); + $('#dateTip'+ currentID).parent().css('line-height', '0') } else { - $('#dateBox').after("

    " + dateTip + "

    " + ignore + "

    "); + $('#dateRange').parent().after(""); + $('#dateTip').parent().css('line-height', '0') } }); } @@ -425,14 +431,16 @@ function outOfDateTip(currentID = 0) * Make this prompt no longer appear. * * @param string $obj + * @param string $currentID * @access public * @return void */ -function ignoreTip(obj) +function ignoreTip(obj, currentID) { var parentID = obj.parentNode.id; - $('#' + parentID).addClass('hidden'); + currentID ? $('#dateTip' + currentID).parent().parent().remove() : $('#' + parentID).parent().parent().remove(); if(parentID == 'dateTip') window.ignoreTips['dateTip'] = true; + if(parentID == 'dateTip' + currentID) batchEditDateTips.push(currentID); if(parentID == 'beyondBudgetTip') window.ignoreTips['beyondBudgetTip'] = true; } diff --git a/module/project/lang/de.php b/module/project/lang/de.php index 1c678d1312..17b7fd1bc2 100644 --- a/module/project/lang/de.php +++ b/module/project/lang/de.php @@ -48,7 +48,7 @@ $lang->project->errorSamePlans = 'Project cannot be associated with multiple $lang->project->errorNoProducts = 'At least one product is associated'; $lang->project->copyNoProject = 'There are no items available to copy.'; $lang->project->searchByName = 'Enter the project name to search'; -$lang->project->deleted = 'Deleted'; +$lang->project->deleted = 'Gelöscht'; $lang->project->linkedProducts = "Linked {$lang->productCommon}s"; $lang->project->unlinkedProducts = "Unlinked {$lang->productCommon}s"; $lang->project->testreport = 'Testreport'; diff --git a/module/project/lang/fr.php b/module/project/lang/fr.php index 1d650086f8..172369bcb4 100644 --- a/module/project/lang/fr.php +++ b/module/project/lang/fr.php @@ -48,7 +48,7 @@ $lang->project->errorSamePlans = 'Project cannot be associated with multiple $lang->project->errorNoProducts = 'At least one product is associated'; $lang->project->copyNoProject = 'There are no items available to copy.'; $lang->project->searchByName = 'Enter the project name to retrieve'; -$lang->project->deleted = 'Deleted'; +$lang->project->deleted = 'Supprimé'; $lang->project->linkedProducts = "Linked {$lang->productCommon}s"; $lang->project->unlinkedProducts = "Unlinked {$lang->productCommon}s"; $lang->project->testreport = 'Testreport'; diff --git a/module/project/model.php b/module/project/model.php index 1bd12fd0cb..f1df79b9c8 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -350,7 +350,7 @@ class projectModel extends model */ public function getTotalStoriesByProject($projectIdList = 0) { - return $this->dao->select("t1.project, count(t2.id) as allStories, count(if(t2.status = 'active' or t2.status = 'changed', 1, null)) as leftStories, count(if(t2.status = 'closed' and t2.closedReason = 'done', 1, null)) as doneStories")->from(TABLE_PROJECTSTORY)->alias('t1') + return $this->dao->select("t1.project, count(t2.id) as allStories, count(if(t2.status = 'active' or t2.status = 'changing', 1, null)) as leftStories, count(if(t2.status = 'closed' and t2.closedReason = 'done', 1, null)) as doneStories")->from(TABLE_PROJECTSTORY)->alias('t1') ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id') ->where('t1.project')->in($projectIdList) ->andWhere('t2.type')->eq('story') @@ -758,7 +758,7 @@ class projectModel extends model ->where('type')->eq('project') ->andWhere('deleted')->eq(0) ->andWhere('vision')->eq($this->config->vision) - ->beginIF($programID !== '')->andWhere('parent')->eq($programID)->fi() + ->beginIF($programID !== '')->andWhere('path')->like("%,$programID,%")->fi() ->beginIF($status != 'all' and $status != 'noclosed')->andWhere('status')->eq($status)->fi() ->beginIF($excludedModel)->andWhere('model')->ne($excludedModel)->fi() ->beginIF($model)->andWhere('model')->eq($model)->fi() @@ -797,16 +797,17 @@ class projectModel extends model /** * Get project by id list. * - * @param array $projectIdList + * @param array $projectIdList + * @param string $mode all * @access public * @return object */ - public function getByIdList($projectIdList = array()) + public function getByIdList($projectIdList = array(), $mode = '') { return $this->dao->select('*')->from(TABLE_PROJECT) ->where('type')->eq('project') ->andWhere('id')->in($projectIdList) - ->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->projects)->fi() + ->beginIF(!$this->app->user->admin and $mode != 'all')->andWhere('id')->in($this->app->user->view->projects)->fi() ->fetchAll('id'); } diff --git a/module/projectrelease/control.php b/module/projectrelease/control.php index 572b0b934a..993f8fab5c 100644 --- a/module/projectrelease/control.php +++ b/module/projectrelease/control.php @@ -230,30 +230,37 @@ class projectrelease extends control return print(js::error($this->lang->notFound) . js::locate('back')); } + $sort = common::appendOrder($orderBy); + if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort); + $storyPager = new pager($type == 'story' ? $recTotal : 0, $recPerPage, $type == 'story' ? $pageID : 1); - $stories = $this->dao->select('*')->from(TABLE_STORY) + $stories = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder")->from(TABLE_STORY) ->where('id')->in($release->stories) ->andWhere('deleted')->eq(0) - ->beginIF($type == 'story')->orderBy($orderBy)->fi() + ->beginIF($type == 'story')->orderBy($sort)->fi() ->page($storyPager) ->fetchAll('id'); + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story'); $stages = $this->dao->select('*')->from(TABLE_STORYSTAGE)->where('story')->in(array_keys($stories))->andWhere('branch')->eq($release->branch)->fetchPairs('story', 'stage'); foreach($stages as $storyID => $stage) $stories[$storyID]->stage = $stage; - - $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story'); - $bugPager = new pager($type == 'bug' ? $recTotal : 0, $recPerPage, $type == 'bug' ? $pageID : 1); - $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($release->bugs)->andWhere('deleted')->eq(0) - ->beginIF($type == 'bug')->orderBy($orderBy)->fi() + $bugs = $this->dao->select('*')->from(TABLE_BUG) + ->where('id')->in($release->bugs) + ->andWhere('deleted')->eq(0) + ->beginIF($type == 'bug')->orderBy($sort)->fi() ->page($bugPager) ->fetchAll(); $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'linkedBug'); $leftBugPager = new pager($type == 'leftBug' ? $recTotal : 0, $recPerPage, $type == 'leftBug' ? $pageID : 1); - $leftBugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($release->leftBugs)->andWhere('deleted')->eq(0) - ->beginIF($type == 'leftBug')->orderBy($orderBy)->fi() + if($type == 'leftBug' and strpos($orderBy, 'severity_') !== false) $sort = str_replace('severity_', 'severityOrder_', $sort); + + $leftBugs = $this->dao->select("*, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG) + ->where('id')->in($release->leftBugs) + ->andWhere('deleted')->eq(0) + ->beginIF($type == 'leftBug')->orderBy($sort)->fi() ->page($leftBugPager) ->fetchAll(); $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'leftBugs'); diff --git a/module/projectstory/lang/de.php b/module/projectstory/lang/de.php index 0af31fe975..85d9e04cb9 100644 --- a/module/projectstory/lang/de.php +++ b/module/projectstory/lang/de.php @@ -26,7 +26,9 @@ global $app; $app->loadLang('product'); $lang->projectstory->featureBar['story']['allstory'] = $lang->product->allStory; $lang->projectstory->featureBar['story']['unclosed'] = $lang->product->unclosed; -$lang->projectstory->featureBar['story']['changed'] = $lang->product->changedStory; +$lang->projectstory->featureBar['story']['draft'] = $lang->product->draftStory; +$lang->projectstory->featureBar['story']['reviewing'] = $lang->product->reviewingStory; +$lang->projectstory->featureBar['story']['changing'] = $lang->product->changingStory; $lang->projectstory->featureBar['story']['closed'] = $lang->product->closedStory; $lang->projectstory->featureBar['story']['linkedExecution'] = 'Linked ' . $lang->execution->common; $lang->projectstory->featureBar['story']['unlinkedExecution'] = 'Unlinked ' . $lang->execution->common; diff --git a/module/projectstory/lang/en.php b/module/projectstory/lang/en.php index 839aa7ab88..46d47f3073 100644 --- a/module/projectstory/lang/en.php +++ b/module/projectstory/lang/en.php @@ -26,7 +26,9 @@ global $app; $app->loadLang('product'); $lang->projectstory->featureBar['story']['allstory'] = $lang->product->allStory; $lang->projectstory->featureBar['story']['unclosed'] = $lang->product->unclosed; -$lang->projectstory->featureBar['story']['changed'] = $lang->product->changedStory; +$lang->projectstory->featureBar['story']['draft'] = $lang->product->draftStory; +$lang->projectstory->featureBar['story']['reviewing'] = $lang->product->reviewingStory; +$lang->projectstory->featureBar['story']['changing'] = $lang->product->changingStory; $lang->projectstory->featureBar['story']['closed'] = $lang->product->closedStory; $lang->projectstory->featureBar['story']['linkedExecution'] = 'Linked ' . $lang->execution->common; $lang->projectstory->featureBar['story']['unlinkedExecution'] = 'Unlinked ' . $lang->execution->common; diff --git a/module/projectstory/lang/fr.php b/module/projectstory/lang/fr.php index 0af31fe975..85d9e04cb9 100644 --- a/module/projectstory/lang/fr.php +++ b/module/projectstory/lang/fr.php @@ -26,7 +26,9 @@ global $app; $app->loadLang('product'); $lang->projectstory->featureBar['story']['allstory'] = $lang->product->allStory; $lang->projectstory->featureBar['story']['unclosed'] = $lang->product->unclosed; -$lang->projectstory->featureBar['story']['changed'] = $lang->product->changedStory; +$lang->projectstory->featureBar['story']['draft'] = $lang->product->draftStory; +$lang->projectstory->featureBar['story']['reviewing'] = $lang->product->reviewingStory; +$lang->projectstory->featureBar['story']['changing'] = $lang->product->changingStory; $lang->projectstory->featureBar['story']['closed'] = $lang->product->closedStory; $lang->projectstory->featureBar['story']['linkedExecution'] = 'Linked ' . $lang->execution->common; $lang->projectstory->featureBar['story']['unlinkedExecution'] = 'Unlinked ' . $lang->execution->common; diff --git a/module/projectstory/lang/vi.php b/module/projectstory/lang/vi.php index c6a62b731d..e41803b496 100644 --- a/module/projectstory/lang/vi.php +++ b/module/projectstory/lang/vi.php @@ -18,7 +18,11 @@ $lang->projectstory->batchUnlinkTip = 'Other requirements are removed. The follo global $app; $app->loadLang('product'); -$lang->projectstory->featureBar['story']['allstory'] = $lang->product->allStory; -$lang->projectstory->featureBar['story']['unclosed'] = $lang->product->unclosed; -$lang->projectstory->featureBar['story']['changed'] = $lang->product->changedStory; -$lang->projectstory->featureBar['story']['closed'] = $lang->product->closedStory; +$lang->projectstory->featureBar['story']['allstory'] = $lang->product->allStory; +$lang->projectstory->featureBar['story']['unclosed'] = $lang->product->unclosed; +$lang->projectstory->featureBar['story']['draft'] = $lang->product->draftStory; +$lang->projectstory->featureBar['story']['reviewing'] = $lang->product->reviewingStory; +$lang->projectstory->featureBar['story']['changing'] = $lang->product->changingStory; +$lang->projectstory->featureBar['story']['closed'] = $lang->product->closedStory; +$lang->projectstory->featureBar['story']['linkedExecution'] = 'Linked ' . $lang->execution->common; +$lang->projectstory->featureBar['story']['unlinkedExecution'] = 'Unlinked ' . $lang->execution->common; diff --git a/module/projectstory/lang/zh-cn.php b/module/projectstory/lang/zh-cn.php index 3df6b06ba2..567ac9cbd0 100644 --- a/module/projectstory/lang/zh-cn.php +++ b/module/projectstory/lang/zh-cn.php @@ -26,7 +26,9 @@ global $app; $app->loadLang('product'); $lang->projectstory->featureBar['story']['allstory'] = $lang->product->allStory; $lang->projectstory->featureBar['story']['unclosed'] = $lang->product->unclosed; -$lang->projectstory->featureBar['story']['changed'] = $lang->product->changedStory; +$lang->projectstory->featureBar['story']['draft'] = $lang->product->draftStory; +$lang->projectstory->featureBar['story']['reviewing'] = $lang->product->reviewingStory; +$lang->projectstory->featureBar['story']['changing'] = $lang->product->changingStory; $lang->projectstory->featureBar['story']['closed'] = $lang->product->closedStory; $lang->projectstory->featureBar['story']['linkedExecution'] = '已关联' . $lang->execution->common; $lang->projectstory->featureBar['story']['unlinkedExecution'] = '未关联' . $lang->execution->common; diff --git a/module/projectstory/lang/zh-tw.php b/module/projectstory/lang/zh-tw.php index 7f678d39cd..ebea653298 100644 --- a/module/projectstory/lang/zh-tw.php +++ b/module/projectstory/lang/zh-tw.php @@ -26,7 +26,7 @@ global $app; $app->loadLang('product'); $lang->projectstory->featureBar['story']['allstory'] = $lang->product->allStory; $lang->projectstory->featureBar['story']['unclosed'] = $lang->product->unclosed; -$lang->projectstory->featureBar['story']['changed'] = $lang->product->changedStory; +$lang->projectstory->featureBar['story']['changing'] = $lang->product->changingStory; $lang->projectstory->featureBar['story']['closed'] = $lang->product->closedStory; $lang->projectstory->featureBar['story']['linkedExecution'] = '已關聯' . $lang->execution->common; $lang->projectstory->featureBar['story']['unlinkedExecution'] = '未關聯' . $lang->execution->common; diff --git a/module/release/control.php b/module/release/control.php index 3c4c58a27d..1ff6c453b6 100644 --- a/module/release/control.php +++ b/module/release/control.php @@ -190,28 +190,40 @@ class release extends control $this->app->loadClass('pager', $static = true); if($this->app->getViewType() == 'mhtml') $recPerPage = 10; + $sort = common::appendOrder($orderBy); + if(strpos($sort, 'pri_') !== false) $sort = str_replace('pri_', 'priOrder_', $sort); + $storyPager = new pager($type == 'story' ? $recTotal : 0, $recPerPage, $type == 'story' ? $pageID : 1); - $stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($release->stories)->andWhere('deleted')->eq(0) - ->beginIF($type == 'story')->orderBy($orderBy)->fi() - ->page($storyPager) - ->fetchAll('id'); + $stories = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder")->from(TABLE_STORY) + ->where('id')->in($release->stories) + ->andWhere('deleted')->eq(0) + ->beginIF($type == 'story')->orderBy($sort)->fi() + ->page($storyPager) + ->fetchAll('id'); $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'story'); $stages = $this->dao->select('*')->from(TABLE_STORYSTAGE)->where('story')->in(array_keys($stories))->andWhere('branch')->eq($release->branch)->fetchPairs('story', 'stage'); foreach($stages as $storyID => $stage)$stories[$storyID]->stage = $stage; $bugPager = new pager($type == 'bug' ? $recTotal : 0, $recPerPage, $type == 'bug' ? $pageID : 1); - $bugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($release->bugs)->andWhere('deleted')->eq(0) - ->beginIF($type == 'bug')->orderBy($orderBy)->fi() + $bugs = $this->dao->select('*')->from(TABLE_BUG) + ->where('id')->in($release->bugs) + ->andWhere('deleted')->eq(0) + ->beginIF($type == 'bug')->orderBy($sort)->fi() ->page($bugPager) ->fetchAll(); $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'linkedBug'); $leftBugPager = new pager($type == 'leftBug' ? $recTotal : 0, $recPerPage, $type == 'leftBug' ? $pageID : 1); - $leftBugs = $this->dao->select('*')->from(TABLE_BUG)->where('id')->in($release->leftBugs)->andWhere('deleted')->eq(0) - ->beginIF($type == 'leftBug')->orderBy($orderBy)->fi() + if($type == 'leftBug' and strpos($orderBy, 'severity_') !== false) $sort = str_replace('severity_', 'severityOrder_', $sort); + + $leftBugs = $this->dao->select("*, IF(`severity` = 0, {$this->config->maxPriValue}, `severity`) as severityOrder")->from(TABLE_BUG) + ->where('id')->in($release->leftBugs) + ->andWhere('deleted')->eq(0) + ->beginIF($type == 'leftBug')->orderBy($sort)->fi() ->page($leftBugPager) ->fetchAll(); + $this->loadModel('common')->saveQueryCondition($this->dao->get(), 'leftBugs'); $this->commonAction($release->product); diff --git a/module/release/view/sendmail.html.php b/module/release/view/sendmail.html.php index bab8e63a57..dbd2acf707 100644 --- a/module/release/view/sendmail.html.php +++ b/module/release/view/sendmail.html.php @@ -13,6 +13,7 @@ id . ' ' . $release->name;?> app->tab == 'product' ? 'release' : 'projectrelease';?> app->getWebRoot(); $onlybody = isonlybody() ? true : false; if($onlybody) $_GET['onlybody'] = 'no'; ?> @@ -55,7 +56,7 @@ if($onlybody) $_GET['onlybody'] = 'no'; @@ -81,7 +82,7 @@ if($onlybody) $_GET['onlybody'] = 'no'; @@ -107,7 +108,7 @@ if($onlybody) $_GET['onlybody'] = 'no'; diff --git a/module/report/view/productsummary.html.php b/module/report/view/productsummary.html.php index 16ea2e1e5c..e4438f2a86 100644 --- a/module/report/view/productsummary.html.php +++ b/module/report/view/productsummary.html.php @@ -48,8 +48,9 @@ + - + @@ -71,16 +72,18 @@ status['draft']) ? $plan->status['draft'] : 0; - $activeCount = isset($plan->status['active']) ? $plan->status['active'] : 0; - $changedCount = isset($plan->status['changed']) ? $plan->status['changed'] : 0; - $closedCount = isset($plan->status['closed']) ? $plan->status['closed'] : 0; + $draftCount = isset($plan->status['draft']) ? $plan->status['draft'] : 0; + $reviewingCount = isset($plan->status['reviewing']) ? $plan->status['reviewing'] : 0; + $activeCount = isset($plan->status['active']) ? $plan->status['active'] : 0; + $changedCount = isset($plan->status['changing']) ? $plan->status['changing'] : 0; + $closedCount = isset($plan->status['closed']) ? $plan->status['closed'] : 0; ?> + - + "?> @@ -95,6 +98,7 @@ + diff --git a/module/story/config.php b/module/story/config.php index 1dcf62aacc..c3f2cf57cc 100644 --- a/module/story/config.php +++ b/module/story/config.php @@ -22,7 +22,7 @@ $config->story->review->requiredFields = ''; $config->story->editor = new stdclass(); $config->story->editor->create = array('id' => 'spec,verify', 'tools' => 'simpleTools'); $config->story->editor->change = array('id' => 'spec,verify,comment', 'tools' => 'simpleTools'); -$config->story->editor->edit = array('id' => 'comment', 'tools' => 'simpleTools'); +$config->story->editor->edit = array('id' => 'spec,verify,comment', 'tools' => 'simpleTools'); $config->story->editor->view = array('id' => 'comment,lastComment', 'tools' => 'simpleTools'); $config->story->editor->close = array('id' => 'comment', 'tools' => 'simpleTools'); $config->story->editor->review = array('id' => 'comment', 'tools' => 'simpleTools'); @@ -43,7 +43,7 @@ $config->story->list->customCreateFields = 'source,verify,pri,estimate,mail $config->story->list->customBatchCreateFields = 'plan,spec,source,verify,pri,estimate,review,keywords'; $config->story->list->customBatchEditFields = 'branch,plan,estimate,pri,assignedTo,source,stage,closedBy,closedReason,keywords'; -$config->story->list->actionsOpratedParentStory = ',edit,batchcreate,change,review,recall,'; +$config->story->list->actionsOpratedParentStory = ',edit,batchcreate,change,review,recall,submitreview,'; $config->story->custom = new stdclass(); $config->story->custom->createFields = $config->story->list->customCreateFields; diff --git a/module/story/control.php b/module/story/control.php index 439e2f97f5..3a82686bd1 100644 --- a/module/story/control.php +++ b/module/story/control.php @@ -137,7 +137,7 @@ class story extends control $response['message'] = sprintf($this->lang->duplicate, $this->lang->story->common); if($objectID == 0) { - $response['locate'] = $this->createLink('story', 'view', "storyID={$storyID}"); + $response['locate'] = $this->createLink('story', 'view', "storyID={$storyID}&version=0¶m=0&storyType=$storyType"); } else { @@ -189,7 +189,7 @@ class story extends control $message = $this->executeHooks($storyID); if($message) $this->lang->saveSuccess = $message; - $response['message'] = $this->lang->saveSuccess; + $response['message'] = $this->post->status == 'draft' ? $this->lang->story->saveDraftSuccess : $this->lang->saveSuccess; if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'id' => $storyID)); @@ -563,7 +563,7 @@ class story extends control if($storyID) { - return print(js::locate(inlink('view', "storyID=$storyID"), 'parent')); + return print(js::locate(inlink('view', "storyID=$storyID&version=0¶m=0&storyType=$storyType"), 'parent')); } elseif($executionID) { @@ -747,6 +747,9 @@ class story extends control */ public function edit($storyID, $kanbanGroup = 'default', $storyType = 'story') { + $this->app->loadLang('bug'); + $story = $this->story->getById($storyID, 0, true); + if(!empty($_POST)) { $changes = $this->story->update($storyID); @@ -757,8 +760,8 @@ class story extends control $actionID = $this->action->create('story', $storyID, $action, $this->post->comment); $this->action->logHistory($actionID, $changes); - $story = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch(); - if(isset($_POST['reviewer'])) $this->story->recordReviewAction($story); + $editedStory = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch(); + if(isset($_POST['reviewer']) and $story->status == 'reviewing') $this->story->recordReviewAction($editedStory); } $this->executeHooks($storyID); @@ -794,7 +797,8 @@ class story extends control } } if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success', 'data' => $storyID)); - return print(js::locate($this->createLink($this->app->rawModule, 'view', "storyID=$storyID"), 'parent')); + $params = $this->app->rawModule == 'story' ? "storyID=$storyID&version=0¶m=0&storyType=$storyType" : "storyID=$storyID"; + return print(js::locate($this->createLink($this->app->rawModule, 'view', $params), 'parent')); } $this->commonAction($storyID); @@ -813,7 +817,6 @@ class story extends control $products = $myProducts + $othersProducts; /* Assign. */ - $story = $this->story->getById($storyID, 0, true); $product = $this->product->getById($story->product); $stories = $this->story->getParentStoryPairs($story->product, $story->parent); if(isset($stories[$storyID])) unset($stories[$storyID]); @@ -821,15 +824,6 @@ class story extends control /* Get users. */ $users = $this->user->getPairs('pofirst|nodeleted|noclosed', "$story->assignedTo,$story->openedBy,$story->closedBy"); - $isShowReviewer = false; - $reviewerList = $this->story->getReviewerPairs($story->id, $story->version); - $reviewerList = array_keys($reviewerList); - $reviewedBy = explode(',', trim($story->reviewedBy, ',')); - if(array_diff($reviewerList, $reviewedBy) and strpos('draft,changed', $story->status) !== false) $isShowReviewer = true; - - $reviewedReviewer = array(); - foreach($reviewedBy as $reviewer) $reviewedReviewer[] = zget($users, $reviewer); - if($this->app->tab == 'project' or $this->app->tab == 'execution') { $objectID = $this->app->tab == 'project' ? $this->session->project : $this->session->execution; @@ -847,6 +841,12 @@ class story extends control $branchTagOption[$branchInfo->id] = $branchInfo->name . ($branchInfo->status == 'closed' ? ' (' . $this->lang->branch->statusList['closed'] . ')' : ''); } + /* Get story reviewers. */ + $reviewedReviewer = array(); + $reviewerList = $this->story->getReviewerPairs($story->id, $story->version); + $reviewedBy = explode(',', trim($story->reviewedBy, ',')); + foreach($reviewedBy as $reviewer) $reviewedReviewer[] = zget($users, $reviewer); + /* Get product reviewers. */ $productReviewers = $product->reviewer; if(!$productReviewers and $product->acl != 'open') $productReviewers = $this->loadModel('user')->getProductViewListUsers($product, '', '', '', ''); @@ -854,6 +854,9 @@ class story extends control /* Process the module when branch products are switched to normal products. */ if($product->type == 'normal' and !empty($story->branch)) $this->view->moduleOptionMenu += $this->tree->getModulesName($story->module); + $branch = $product->type == 'branch' ? ($story->branch > 0 ? $story->branch : '0') : 'all'; + $productStories = $this->story->getProductStoryPairs($story->product, $branch, 0, 'all', 'id_desc', 0, ''); + $this->view->title = $this->lang->story->edit . "STORY" . $this->lang->colon . $this->view->story->title; $this->view->position[] = $this->lang->story->edit; $this->view->story = $story; @@ -862,12 +865,13 @@ class story extends control $this->view->product = $product; $this->view->plans = $this->loadModel('productplan')->getPairsForStory($story->product, $story->branch == 0 ? 'all' : $story->branch, 'skipParent'); $this->view->products = $products; + $this->view->productStories = $productStories; $this->view->branchOption = $branchOption; $this->view->branchTagOption = $branchTagOption; - $this->view->reviewers = implode(',', $reviewerList); + $this->view->reviewers = array_keys($reviewerList); $this->view->reviewedReviewer = $reviewedReviewer; - $this->view->productReviewers = $this->user->getPairs('noclosed|nodeleted', $reviewerList, 0, $productReviewers); - $this->view->isShowReviewer = $isShowReviewer; + $this->view->productReviewers = $this->user->getPairs('noclosed|nodeleted', array_keys($reviewerList), 0, $productReviewers); + $this->display(); } @@ -1025,7 +1029,8 @@ class story extends control if($showSuhosinInfo) $this->view->suhosinInfo = extension_loaded('suhosin') ? sprintf($this->lang->suhosinInfo, $countInputVars) : sprintf($this->lang->maxVarsInfo, $countInputVars); /* Append module when change product type. */ - $moduleList = array(0 => '/'); + $moduleList = array(0 => '/'); + $productStoryList = array(); foreach($stories as $story) { if(isset($modules[$story->product][$story->branch])) @@ -1036,6 +1041,13 @@ class story extends control { $moduleList[$story->id] = $modules[$story->product][0] + $this->tree->getModulesName($story->module); } + + if($story->status == 'closed') + { + $storyProduct = $products[$story->product]; + $branch = $storyProduct->type == 'branch' ? ($story->branch > 0 ? $story->branch : '0') : 'all'; + if(!isset($productStoryList[$story->product][$story->branch])) $productStoryList[$story->product][$story->branch] = $this->story->getProductStoryPairs($story->product, $branch, 0, 'all', 'id_desc', 0, '', $story->type); + } } $this->view->position[] = $this->lang->story->common; @@ -1057,6 +1069,7 @@ class story extends control $this->view->executionID = $executionID; $this->view->branchTagOption = $branchTagOption; $this->view->moduleList = $moduleList; + $this->view->productStoryList = $productStoryList; $this->display(); } @@ -1129,7 +1142,8 @@ class story extends control } if(defined('RUN_MODE') && RUN_MODE == 'api') return $this->send(array('status' => 'success')); - return print(js::locate($this->createLink($module, 'view', "storyID=$storyID"), 'parent')); + $params = $module == 'story' ? "storyID=$storyID&version=0¶m=0&storyType=$storyType" : "storyID=$storyID"; + return print(js::locate($this->createLink($module, 'view', $params), 'parent')); } $this->commonAction($storyID); @@ -1151,7 +1165,7 @@ class story extends control $this->view->title = $this->lang->story->change . "STORY" . $this->lang->colon . $this->view->story->title; $this->view->users = $this->user->getPairs('pofirst|nodeleted|noclosed', $this->view->story->assignedTo); $this->view->position[] = $this->lang->story->change; - $this->view->needReview = ($this->app->user->account == $this->view->product->PO || $this->config->story->needReview == 0) ? "checked='checked'" : ""; + $this->view->needReview = (($this->app->user->account == $this->view->product->PO or $this->config->story->needReview == 0) and empty($reviewer)) ? "checked='checked'" : ""; $this->view->reviewer = implode(',', array_keys($reviewer)); $this->view->productReviewers = $this->user->getPairs('noclosed|nodeleted', $reviewer, 0, $productReviewers); $this->view->files = $this->loadModel('file')->getByObject($story->type, $storyID); @@ -1200,14 +1214,14 @@ class story extends control return print(js::closeModal('parent.parent', 'this')); } } - return print(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent')); + return print(js::locate($this->createLink('story', 'view', "storyID=$storyID&version=0¶m=0&storyType=$storyType"), 'parent')); } $this->commonAction($storyID); /* Assign. */ $this->view->title = $this->lang->story->activate . "STORY" . $this->lang->colon . $this->view->story->title; - $this->view->users = $this->user->getPairs('pofirst|nodeleted', $this->view->story->closedBy); + $this->view->users = $this->user->getPairs('pofirst|nodeleted|noclosed', $this->view->story->closedBy); $this->view->position[] = $this->lang->story->activate; $this->display(); } @@ -1229,7 +1243,6 @@ class story extends control $buildApp = $tab == 'product' ? 'project' : $tab; $releaseApp = $tab == 'execution' ? 'product' : $tab; $this->session->set('productList', $uri . "#app={$tab}", 'product'); - $this->session->set('releaseList', $uri, $releaseApp); $this->session->set('buildList', $uri, $buildApp); $storyID = (int)$storyID; @@ -1332,7 +1345,7 @@ class story extends control if($confirm == 'no') { - return print(js::confirm($this->lang->story->confirmDelete, $this->createLink('story', 'delete', "story=$storyID&confirm=yes&from=$from"), '')); + return print(js::confirm($this->lang->story->confirmDelete, $this->createLink('story', 'delete', "story=$storyID&confirm=yes&from=$from&storyType=$storyType"), '')); } else { @@ -1427,7 +1440,8 @@ class story extends control $module = $from == 'project' ? 'projectstory' : 'story'; if(defined('RUN_MODE') and RUN_MODE == 'api') return $this->send(array('status' => 'success', 'data' => $storyID)); - return print(js::locate($this->createLink($module, 'view', "storyID=$storyID"), 'parent')); + $params = $module == 'story' ? "storyID=$storyID&version=0¶m=0&storyType=$storyType" : "storyID=$storyID"; + return print(js::locate($this->createLink($module, 'view', $params), 'parent')); } /* Get story and product. */ @@ -1454,9 +1468,9 @@ class story extends control $reviewers = $this->story->getReviewerPairs($storyID, $story->version); $this->lang->story->resultList = $this->lang->story->reviewResultList; - if($story->status == 'draft' and $story->version == 1) unset($this->lang->story->resultList['revert']); + if($story->status == 'reviewing' and $story->version == 1) unset($this->lang->story->resultList['revert']); - if($story->status == 'changed') unset($this->lang->story->resultList['reject']); + if($story->status == 'changing') unset($this->lang->story->resultList['reject']); if(count($reviewers) > 1) unset($this->lang->story->resultList['revert']); @@ -1470,6 +1484,7 @@ class story extends control $this->view->actions = $this->action->getList('story', $storyID); $this->view->users = $this->loadModel('user')->getPairs('nodeleted|noletter', "$story->lastEditedBy,$story->openedBy"); $this->view->reviewers = $reviewers; + $this->view->isLastOne = count(array_diff(array_keys($reviewers), explode(',', $story->reviewedBy))) == 1 ? true : false; /* Get the affcected things. */ $this->story->getAffectedScope($this->view->story); @@ -1503,24 +1518,86 @@ class story extends control } /** - * Recall the story review. + * Recall the story review or story change. * * @param int $storyID - * @param string $from + * @param string $from list + * @param string $confirm no|yes * @param string $storyType story|requirement * @access public * @return void */ - public function recall($storyID, $from = 'list', $storyType = 'story') + public function recall($storyID, $from = 'list', $confirm = 'no', $storyType = 'story') { $story = $this->story->getById($storyID); - $this->story->recall($storyID); - $this->loadModel('action')->create('story', $storyID, 'Recalled'); - if($from == 'view') return print(js::locate($this->createLink('story', 'view', "storyID={$storyID}&from=view"))); + if($confirm == 'no') + { + $confirmTips = $story->status == 'changing' ? $this->lang->story->confirmRecallChange : $this->lang->story->confirmRecallReview; + return print(js::confirm($confirmTips, $this->createLink('story', 'recall', "storyID=$storyID&from=$from&confirm=yes&storyType=$storyType"))); + } + else + { + if($story->status == 'changing') $this->story->recallChange($storyID); + if($story->status == 'reviewing') $this->story->recallReview($storyID); - $locateLink = $this->session->storyList ? $this->session->storyList : $this->createLink('product', 'browse', "productID={$story->product}"); - echo js::locate($locateLink, 'parent'); + $action = $story->status == 'changing' ? 'recalledChange' : 'Recalled'; + $this->loadModel('action')->create('story', $storyID, $action); + + if($from == 'view') return print(js::locate($this->createLink('story', 'view', "storyID=$storyID&version=0¶m=0&storyType=$storyType"), 'parent')); + + $locateLink = $this->session->storyList ? $this->session->storyList : $this->createLink('product', 'browse', "productID={$story->product}"); + return print(js::locate($locateLink, 'parent')); + } + } + + /** + * Submit review. + * + * @param int $storyID + * @param string $storyType story|requirement + * @access public + * @return void + */ + public function submitReview($storyID, $storyType = 'story') + { + if($_POST) + { + $changes = $this->story->submitReview($storyID); + if(dao::isError()) return print(js::error(dao::getError())); + + if($changes) + { + $actionID = $this->loadModel('action')->create('story', $storyID, 'submitReview'); + $this->action->logHistory($actionID, $changes); + } + + if(isonlybody()) return print(js::closeModal('parent.parent', 'this')); + return print(js::locate($this->createLink('story', 'view', "storyID=$storyID&version=0¶m=0&storyType=$storyType"), 'parent')); + } + + /* Get story and product. */ + $story = $this->story->getById($storyID); + $product = $this->product->getById($story->product); + + /* Set menu. */ + $this->product->setMenu($story->product, $story->branch); + + /* Get reviewers. */ + $reviewers = $product->reviewer; + if(!$reviewers and $product->acl != 'open') $reviewers = $this->loadModel('user')->getProductViewListUsers($product, '', '', '', ''); + + /* Get story reviewer. */ + $reviewerList = $this->story->getReviewerPairs($story->id, $story->version); + $story->reviewer = array_keys($reviewerList); + + $this->view->story = $story; + $this->view->actions = $this->action->getList('story', $storyID); + $this->view->reviewers = $this->user->getPairs('noclosed|nodeleted', '', 0, $reviewers); + $this->view->users = $this->user->getPairs('noclosed|noletter'); + $this->view->needReview = (($this->app->user->account == $product->PO || $this->config->story->needReview == 0) and empty($story->reviewer)) ? "checked='checked'" : ""; + + $this->display(); } /** @@ -1534,6 +1611,9 @@ class story extends control */ public function close($storyID, $from = '', $storyType = 'story') { + $this->app->loadLang('bug'); + $story = $this->story->getById($storyID); + if(!empty($_POST)) { $changes = $this->story->close($storyID); @@ -1542,7 +1622,11 @@ class story extends control if($changes) { - $actionID = $this->action->create('story', $storyID, 'Closed', $this->post->comment, ucfirst($this->post->closedReason) . ($this->post->duplicateStory ? ':' . (int)$this->post->duplicateStory : '')); + $preStatus = $story->status; + $isChanged = $story->changedBy ? true : false; + if($preStatus == 'reviewing') $preStatus = $isChanged ? 'changing' : 'draft'; + + $actionID = $this->action->create('story', $storyID, 'Closed', $this->post->comment, ucfirst($this->post->closedReason) . ($this->post->duplicateStory ? ':' . (int)$this->post->duplicateStory : '') . "|$preStatus"); $this->action->logHistory($actionID, $changes); } @@ -1583,13 +1667,12 @@ class story extends control } else { - return print(js::locate(inlink('view', "storyID=$storyID"), 'parent')); + return print(js::locate(inlink('view', "storyID=$storyID&version=0¶m=0&storyType=$storyType"), 'parent')); } } /* Get story and product. */ - $story = $this->story->getById($storyID); - $product = $this->dao->findById($story->product)->from(TABLE_PRODUCT)->fields('name, id')->fetch(); + $product = $this->dao->findById($story->product)->from(TABLE_PRODUCT)->fields('name, id, type')->fetch(); $this->story->replaceURLang($story->type); @@ -1597,19 +1680,24 @@ class story extends control $this->product->setMenu($product->id, $story->branch); /* Set the closed reason options and remove subdivided options. */ - if($story->status == 'draft') unset($this->lang->story->reasonList['cancel']); - unset($this->lang->story->reasonList['subdivided']); + $reasonList = $this->lang->story->reasonList; + if($story->status == 'draft') unset($reasonList['cancel']); + unset($reasonList['subdivided']); + + $branch = $product->type == 'branch' ? ($story->branch > 0 ? $story->branch : '0') : 'all'; + $productStories = $this->story->getProductStoryPairs($story->product, $branch, 0, 'all', 'id_desc', 0, '', $storyType); $this->view->title = $this->lang->story->close . "STORY" . $this->lang->colon . $story->title; $this->view->position[] = html::a($this->createLink('product', 'browse', "product=$product->id&branch=$story->branch"), $product->name); $this->view->position[] = $this->lang->story->common; $this->view->position[] = $this->lang->story->close; - $this->view->product = $product; - $this->view->story = $story; - $this->view->actions = $this->action->getList('story', $storyID); - $this->view->users = $this->loadModel('user')->getPairs(); - $this->view->reasonList = $this->lang->story->reasonList; + $this->view->product = $product; + $this->view->story = $story; + $this->view->productStories = $productStories; + $this->view->actions = $this->action->getList('story', $storyID); + $this->view->users = $this->loadModel('user')->getPairs(); + $this->view->reasonList = $reasonList; $this->display(); } @@ -1625,30 +1713,15 @@ class story extends control */ public function batchClose($productID = 0, $executionID = 0, $storyType = 'story', $from = '') { - if($this->post->comments) - { - $data = fixer::input('post')->get(); - $allChanges = $this->story->batchClose(); - - if($allChanges) - { - foreach($allChanges as $storyID => $changes) - { - $actionID = $this->action->create('story', $storyID, 'Closed', htmlSpecialString($this->post->comments[$storyID]), ucfirst($this->post->closedReasons[$storyID]) . ($this->post->duplicateStoryIDList[$storyID] ? ':' . (int)$this->post->duplicateStoryIDList[$storyID] : '')); - $this->action->logHistory($actionID, $changes); - } - } - - if(!dao::isError()) $this->loadModel('score')->create('ajax', 'batchOther'); - return print(js::locate($this->session->storyList, 'parent')); - } - + $this->app->loadLang('bug'); if(!$this->post->storyIdList) return print(js::locate($this->session->storyList, 'parent')); $storyIdList = $this->post->storyIdList; $storyIdList = array_unique($storyIdList); /* Get edited stories. */ - $stories = $this->dao->select('*')->from(TABLE_STORY)->where('id')->in($storyIdList)->fetchAll('id'); + $stories = $this->story->getByList($storyIdList); + $productStoryList = array(); + $productList = array(); foreach($stories as $story) { if($story->parent == -1) @@ -1661,6 +1734,32 @@ class story extends control $closedStory[] = $story->id; unset($stories[$story->id]); } + + $storyProduct = isset($productList[$story->product]) ? $productList[$story->product] : $this->product->getByID($story->product); + $branch = $storyProduct->type == 'branch' ? ($story->branch > 0 ? $story->branch : '0') : 'all'; + if(!isset($productStoryList[$story->product][$story->branch])) $productStoryList[$story->product][$story->branch] = $this->story->getProductStoryPairs($story->product, $branch, 0, 'all', 'id_desc', 0, '', $story->type); + } + + if($this->post->comments) + { + $data = fixer::input('post')->get(); + $allChanges = $this->story->batchClose(); + + if($allChanges) + { + foreach($allChanges as $storyID => $changes) + { + $preStatus = $stories[$storyID]->status; + $isChanged = $stories[$storyID]->changedBy ? true : false; + if($preStatus == 'reviewing') $preStatus = $isChanged ? 'changing' : 'draft'; + + $actionID = $this->action->create('story', $storyID, 'Closed', htmlSpecialString($this->post->comments[$storyID]), ucfirst($this->post->closedReasons[$storyID]) . ($this->post->duplicateStoryIDList[$storyID] ? ':' . (int)$this->post->duplicateStoryIDList[$storyID] : '') . "|$preStatus"); + $this->action->logHistory($actionID, $changes); + } + } + + if(!dao::isError()) $this->loadModel('score')->create('ajax', 'batchOther'); + return print(js::locate($this->session->storyList, 'parent')); } $errorTips = ''; @@ -1722,6 +1821,7 @@ class story extends control $this->view->storyIdList = $storyIdList; $this->view->storyType = $storyType; $this->view->reasonList = $this->lang->story->reasonList; + $this->view->productStoryList = $productStoryList; $this->display(); } @@ -1960,7 +2060,7 @@ class story extends control return print(js::closeModal('parent.parent', 'this', 'function(){parent.parent.$(\'[data-ride="searchList"]\').searchList();}')); } } - return print(js::locate($this->createLink('story', 'view', "storyID=$storyID"), 'parent')); + return print(js::locate($this->createLink('story', 'view', "storyID=$storyID&version=0¶m=0&storyType=$storyType"), 'parent')); } /* Get story and product. */ @@ -2058,11 +2158,12 @@ class story extends control * @param int $storyID * @param string $type * @param string $browseType - * @param int $param + * @param int $queryID + * @param string $storyType story|requirement * @access public * @return void */ - public function linkStory($storyID, $type = 'linkStories', $linkedStoryID = 0, $browseType = '', $queryID = 0) + public function linkStory($storyID, $type = 'linkStories', $linkedStoryID = 0, $browseType = '', $queryID = 0, $storyType = 'story') { $this->commonAction($storyID); @@ -2096,7 +2197,7 @@ class story extends control } /* Build search form. */ - $actionURL = $this->createLink('story', 'linkStory', "storyID=$storyID&type=$type&linkedStoryID=$linkedStoryID&browseType=bySearch&queryID=myQueryID", '', true); + $actionURL = $this->createLink('story', 'linkStory', "storyID=$storyID&type=$type&linkedStoryID=$linkedStoryID&browseType=bySearch&queryID=myQueryID&storyType=$storyType", '', true); $this->product->buildSearchForm($story->product, $products, $queryID, $actionURL); /* Get stories to link. */ @@ -2137,9 +2238,10 @@ class story extends control $products = $this->product->getPairs(); $queryID = ($browseType == 'bySearch') ? (int)$param : 0; $type = $story->type == 'story' ? 'linkRelateSR' : 'linkRelateUR'; + $method = $story->type == 'story' ? 'linkStories' : 'linkRequirements'; /* Build search form. */ - $actionURL = $this->createLink('story', 'linkStories', "storyID=$storyID&browseType=bySearch&excludeStories=$excludeStories&queryID=myQueryID", '', true); + $actionURL = $this->createLink('story', $method, "storyID=$storyID&browseType=bySearch&excludeStories=$excludeStories&queryID=myQueryID", '', true); $this->product->buildSearchForm($story->product, $products, $queryID, $actionURL); $this->view->story = $story; @@ -2513,9 +2615,9 @@ class story extends control { $oldStory = $this->dao->findById((int)$params['storyID'])->from(TABLE_STORY)->fetch(); $status = $oldStory->status; - if($params['changed'] and $oldStory->status == 'active' and empty($params['needNotReview'])) $status = 'changed'; - if($params['changed'] and $oldStory->status == 'active' and $this->story->checkForceReview()) $status = 'changed'; - if($params['changed'] and $oldStory->status == 'draft' and $params['needNotReview']) $status = 'active'; + if($params['changing'] and $oldStory->status == 'active' and empty($params['needNotReview'])) $status = 'changing'; + if($params['changing'] and $oldStory->status == 'active' and $this->story->checkForceReview()) $status = 'changing'; + if($params['changing'] and $oldStory->status == 'draft' and $params['needNotReview']) $status = 'active'; } elseif($method == 'review') { @@ -2538,7 +2640,7 @@ class story extends control */ public function ajaxGetAssignedTo($type = '', $storyID = 0, $assignees = '') { - $users = $this->loadModel('user')->getPairs('noletter|noclosed'); + $users = $this->loadModel('user')->getPairs('noclosed'); if($type == 'create') { diff --git a/module/story/css/close.zh-cn.css b/module/story/css/close.zh-cn.css index 76da72e24c..9dfc0a5865 100644 --- a/module/story/css/close.zh-cn.css +++ b/module/story/css/close.zh-cn.css @@ -1 +1 @@ -.thWidth {width: 80px !important;} +.thWidth {width: 95px !important;} diff --git a/module/story/css/create.css b/module/story/css/create.css index 1e646d9c98..c9854e8d17 100644 --- a/module/story/css/create.css +++ b/module/story/css/create.css @@ -9,7 +9,7 @@ #product + .picker{min-width: 400px} #dataform .priBox, #dataform .estimateBox {width: 120px;} #dataform .categoryBox {width: 150px;} -#dataform .needNotReviewBox {width: 130px;} +.needNotReviewBox {width: 130px; display: inline-block; padding: 7px;} .input-group-addon.assignedTo {min-width: 77px;} .input-group .source {display: flex; width: 50%;} .input-group .sourceNote {display: flex; width: 50%;} diff --git a/module/story/css/edit.css b/module/story/css/edit.css index 81268bed5e..2bae76d3c1 100644 --- a/module/story/css/edit.css +++ b/module/story/css/edit.css @@ -1,3 +1,6 @@ -#product_chosen .chosen-single{border-right-width:1px} +#product_chosen .chosen-single {border-right-width: 1px} .linkStoryTitle {white-space: nowrap; text-overflow: ellipsis;} .linkStoryTd > ul {margin-top: -10px;} +.titleBox {margin: 0px 10px 10px 10px;} +.needNotReviewBox {width: 130px;} +.needNotReviewBox span.input-group-addon {border: 1px solid #dcdcdc; border-left-width: 0px;} diff --git a/module/story/css/submitreview.css b/module/story/css/submitreview.css new file mode 100644 index 0000000000..b9ff94d49c --- /dev/null +++ b/module/story/css/submitreview.css @@ -0,0 +1,3 @@ +.needNotReviewBox {width: 130px;} +.needNotReviewBox span.input-group-addon {border: 1px solid #dcdcdc; border-left-width: 0px;} +.table > tbody > tr > th {vertical-align: top; padding-top: 13px;} diff --git a/module/story/css/view.css b/module/story/css/view.css index f671114a5e..782054d7ad 100644 --- a/module/story/css/view.css +++ b/module/story/css/view.css @@ -12,3 +12,4 @@ .linkStoryTr > th {width: 90px;} .linkStoryTr > td {padding-left: 0px !important;} .removeButton {margin-left: -10px;} +.resolution {white-space: nowrap; overflow: hidden;} diff --git a/module/story/js/batchclose.js b/module/story/js/batchclose.js index 45150d3088..fcce7e7768 100755 --- a/module/story/js/batchclose.js +++ b/module/story/js/batchclose.js @@ -1,7 +1,7 @@ /** * Set duplicate field. - * - * @param string $resolution + * + * @param string $resolution * @param int $storyID * @access public * @return void @@ -24,3 +24,12 @@ function setDuplicateAndChild(resolution, storyID) $('#childStoryBox' + storyID).hide(); } } + +$(function() +{ + $('select[id^="duplicateStoryIDList"]').picker( + { + disableEmptySearch : true, + dropWidth : 'auto' + }); +}); diff --git a/module/story/js/batchcreate.js b/module/story/js/batchcreate.js index c4de3579a9..66e70dfda8 100644 --- a/module/story/js/batchcreate.js +++ b/module/story/js/batchcreate.js @@ -14,6 +14,21 @@ $(function() saveCustomFields('batchCreateFields', 8, $name, 200); return false; }); + + $('#saveButton').on('click', function() + { + $('#saveButton').attr('disabled', true); + $('#saveDraftButton').attr('disabled', true); + $('#batchCreateForm').submit(); + }); + + $('#saveDraftButton').on('click', function() + { + $('#saveButton').attr('disabled', true); + $('#saveDraftButton').attr('disabled', true); + $('').attr('type', 'hidden').attr('name', 'status').attr('value', 'draft').appendTo('#batchCreateForm'); + $('#batchCreateForm').submit(); + }); }); $(document).on('click', '.chosen-with-drop', function() diff --git a/module/story/js/batchedit.js b/module/story/js/batchedit.js index 63eaea8a5d..5a92791404 100644 --- a/module/story/js/batchedit.js +++ b/module/story/js/batchedit.js @@ -51,6 +51,12 @@ $(function() { hiddenRequireFields(); }); + + $('select[id^="duplicateStoryIDList"]').picker( + { + disableEmptySearch : true, + dropWidth : 'auto' + }); }); $(document).on('click', '.chosen-with-drop', function(){oldValue = $(this).prev('select').val();})//Save old value. diff --git a/module/story/js/change.js b/module/story/js/change.js index 3d075f1112..26c5e8c194 100644 --- a/module/story/js/change.js +++ b/module/story/js/change.js @@ -2,7 +2,7 @@ $(function() { $('#needNotReview').on('change', function() { - $('#reviewer').attr('disabled', $(this).is(':checked') ? 'disabled' : null).trigger('chosen:updated'); + $('#reviewer').text('').attr('disabled', $(this).is(':checked') ? 'disabled' : null).trigger('chosen:updated'); if($(this).is(':checked')) { $('.input-group-addon').removeClass('required'); @@ -11,41 +11,8 @@ $(function() { $('.input-group-addon').addClass('required'); } - - loadAssignedTo(); }); - $('#needNotReview').change(); - - if($('#reviewer').val()) loadAssignedTo(); + if(!$('#reviewer').val()) $('#needNotReview').change(); if($('.tabs .tab-content .tab-pane.active').children().length == 0) $('.tabs .nav-tabs li.active').css('border-bottom', '1px solid #ccc'); }); - -/** - * Load assignedTo. - * - * @access public - * @return void - */ -function loadAssignedTo() -{ - var assignees = $('#reviewer').val(); - var link = createLink('story', 'ajaxGetAssignedTo', 'type=change&storyID=' + storyID + '&assignees=' + assignees); - $.post(link, function(data) - { - $('#assignedTo').replaceWith(data); - $('#assignedToBox .picker').remove(); - $('#assignedTo').picker(); - }); - - if($('#needNotReview').is(':checked')) - { - $('#assignedToBox').removeClass('hidden'); - $('#reviewerBox').attr('colspan', 1); - } - else - { - $('#assignedToBox').addClass('hidden'); - $('#reviewerBox').attr('colspan', 2); - } -} diff --git a/module/story/js/close.js b/module/story/js/close.js index 73b0e1988a..4a8e9ffe28 100644 --- a/module/story/js/close.js +++ b/module/story/js/close.js @@ -16,3 +16,12 @@ function setStory(reason) $('#childStoriesBox').hide(); } } + +$(function() +{ + $('#duplicateStory').picker( + { + disableEmptySearch : true, + dropWidth : 'auto' + }); +}); diff --git a/module/story/js/common.js b/module/story/js/common.js index 191033a664..ce4a67d484 100644 --- a/module/story/js/common.js +++ b/module/story/js/common.js @@ -11,6 +11,40 @@ $(function() $("#navbar .nav li[data-id=" + storyType + ']').addClass('active'); $('#subNavbar li[data-id="' + storyType + '"]').addClass('active'); } + + $('#saveButton').on('click', function() + { + $('#saveButton').attr('disabled', true); + $('#saveDraftButton').attr('disabled', true); + + var storyStatus = !$('#reviewer').val() || $('#needNotReview').is(':checked') ? 'active' : 'reviewing'; + $('').attr('type', 'hidden').attr('name', 'status').attr('value', storyStatus).appendTo('#dataform'); + $('#dataform').submit(); + + setTimeout(function() + { + $('#saveButton').removeAttr('disabled'); + $('#saveDraftButton').removeAttr('disabled'); + }, 1000); + }); + + $('#saveDraftButton').on('click', function() + { + $('#saveButton').attr('disabled', true); + $('#saveDraftButton').attr('disabled', true); + + storyStatus = 'draft'; + if(typeof(page) != 'undefined' && page == 'change') storyStatus = 'changing'; + if(typeof(page) !== 'undefined' && page == 'edit' && $('#status').val() == 'changing') storyStatus = 'changing'; + $('').attr('type', 'hidden').attr('name', 'status').attr('value', storyStatus).appendTo('#dataform'); + $('#dataform').submit(); + + setTimeout(function() + { + $('#saveButton').removeAttr('disabled'); + $('#saveDraftButton').removeAttr('disabled'); + }, 1000); + }); }) /** diff --git a/module/story/js/create.js b/module/story/js/create.js index 979300b4bb..698eb0e085 100644 --- a/module/story/js/create.js +++ b/module/story/js/create.js @@ -2,23 +2,25 @@ $(function() { $('#needNotReview').on('change', function() { - $('#reviewer').text('').attr('disabled', $(this).is(':checked') ? 'disabled' : null).trigger('chosen:updated'); + $('#reviewer').attr('disabled', $(this).is(':checked') ? 'disabled' : null).trigger('chosen:updated'); + if($(this).is(':checked')) { + $('#reviewerBox').closest('tr').addClass('hidden'); $('#reviewerBox').removeClass('required'); + $('#dataform #needNotReview').val(1); } else { + $('#reviewerBox').closest('tr').removeClass('hidden'); $('#reviewerBox').addClass('required'); + $('#dataform #needNotReview').val(0); } - loadAssignedTo(); getStatus('create', "product=" + $('#product').val() + ",execution=" + executionID + ",needNotReview=" + ($(this).prop('checked') ? 1 : 0)); }); $('#needNotReview').change(); - if($('#reviewer').val()) loadAssignedTo(); - // init pri selector $('#pri').on('change', function() { @@ -36,14 +38,12 @@ $(function() if($.inArray(source, feedbackSource) != -1) { $('#feedbackBox').removeClass('hidden'); - $('#reviewerBox').attr('colspan', $('#assignedToBox').hasClass('hidden') ? 2 : 1); - $('#assignedToBox').attr('colspan', 1); + $('#source, #sourceNoteBox').closest('td').attr('colspan', 1); } else { $('#feedbackBox').addClass('hidden'); - $('#reviewerBox').attr('colspan', $('#assignedToBox').hasClass('hidden') ? 4 : 2); - $('#assignedToBox').attr('colspan', 2); + $('#source, #sourceNoteBox').closest('td').attr('colspan', 2); } }); @@ -56,22 +56,6 @@ $(function() $('#formSettingForm .btn-primary').click(function() { saveCustomFields('createFields'); - - setTimeout(function() - { - var showFieldList = showFields + ','; - if(showFieldList.indexOf(',source,') >= 0) - { - $('#source').trigger("change"); - } - else - { - $('#feedbackBox').addClass('hidden'); - $('#reviewerBox').attr('colspan', $('#assignedToBox').hasClass('hidden') ? 4 : 2); - $('#assignedToBox').attr('colspan', 2); - } - }, 100); - return false; }); }); @@ -92,18 +76,6 @@ function loadAssignedTo() $('#assignedToBox .picker').remove(); $('#assignedTo').picker(); }); - - var colspan = $('#assignedToBox').attr('colspan'); - if($('#needNotReview').is(':checked')) - { - $('#assignedToBox').removeClass('hidden'); - $('#reviewerBox').attr('colspan', colspan); - } - else - { - $('#assignedToBox').addClass('hidden'); - $('#reviewerBox').attr('colspan', colspan * 2); - } } function refreshPlan() diff --git a/module/story/js/edit.js b/module/story/js/edit.js index f3b8ffb683..8f012085db 100644 --- a/module/story/js/edit.js +++ b/module/story/js/edit.js @@ -1,24 +1,49 @@ $(function() { $('.main-side #branch').closest('td').find('#product_chosen .chosen-single').css('width', '153px'); - $('#reviewer_chosen .search-choice').each(function() - { - if(reviewedReviewer.indexOf($(this).find('span').text()) != -1) $(this).css('pointer-events', 'none'); - }) - $('#reviewer').change(function() + if(storyStatus == 'reviewing') { - if($('#reviewer_chosen .search-choice').length === 1) + $('#reviewer').next().find('.picker-selection').each(function() { - alert(reviewerNotEmpty); - $('#reviewer').val(reviewers); - $('#reviewer').trigger('chosen:updated'); + if(reviewedReviewer.indexOf($(this).find('span').text()) != -1) $(this).css('pointer-events', 'none'); + }); + + $('#reviewer').change(function() + { + if($('#reviewer').next().find('.picker-selection').length === 0) + { + alert(reviewerNotEmpty); + $('#reviewer').val(reviewers); + $('#reviewer').trigger('chosen:updated'); + } + else + { + reviewers = $('#reviewer').val(); + } + }); + } + else + { + $('#reviewer').change(function() + { + if(!$('#reviewer').val()) $('#needNotReview').attr('checked', true).change(); + }); + } + + $('#needNotReview').on('change', function() + { + $('#reviewer').text('').attr('disabled', $(this).is(':checked') ? 'disabled' : null).trigger('chosen:updated'); + if($(this).is(':checked')) + { + $('#reviewerBox').removeClass('required'); } else { - reviewers = $('#reviewer').val(); + $('#reviewerBox').addClass('required'); } - }) + }); + if(!$('#reviewer').val()) $('#needNotReview').change(); $('#source').on('change', function() { @@ -54,4 +79,10 @@ $(function() var modalTrigger = new $.zui.ModalTrigger({type: 'iframe', width: '95%', url: link}); modalTrigger.show(); }); + + $('#duplicateStory').picker( + { + disableEmptySearch : true, + dropWidth : 'auto' + }); }) diff --git a/module/story/js/review.js b/module/story/js/review.js index afac5139c7..682d532c83 100644 --- a/module/story/js/review.js +++ b/module/story/js/review.js @@ -7,11 +7,6 @@ function switchShow(result) $('#rejectedReasonBox').show(); $('#preVersionBox').hide(); $('#assignedToBox').hide(); - if(isMultiple) - { - $('#assignedToBox').show(); - loadAssignedTo(); - } } else if(result == 'revert') { @@ -19,8 +14,7 @@ function switchShow(result) $('#rejectedReasonBox').hide(); $('#duplicateStoryBox').hide(); $('#childStoriesBox').hide(); - $('#assignedToBox').show(); - loadAssignedTo(); + if(isLastOne) $('#assignedToBox').show(); } else if(result == 'clarify') { @@ -29,8 +23,7 @@ function switchShow(result) $('#duplicateStoryBox').hide(); $('#childStoriesBox').hide(); $('#rejectedReasonBox').hide(); - $('#assignedToBox').show(); - loadAssignedTo(); + if(isLastOne) $('#assignedToBox').show(); } else { @@ -39,13 +32,11 @@ function switchShow(result) $('#duplicateStoryBox').hide(); $('#childStoriesBox').hide(); $('#rejectedReasonBox').hide(); - $('#assignedToBox').hide(); + if(isLastOne) $('#assignedToBox').show(); if(result == 'pass') { $('#priBox').show(); $('#estimateBox').show(); - $('#assignedToBox').show(); - loadAssignedTo(); } } diff --git a/module/story/js/submitreview.js b/module/story/js/submitreview.js new file mode 100644 index 0000000000..3734ca5b4e --- /dev/null +++ b/module/story/js/submitreview.js @@ -0,0 +1,16 @@ +$(function() +{ + $('#needNotReview').on('change', function() + { + $('#reviewer').text('').attr('disabled', $(this).is(':checked') ? 'disabled' : null).trigger('chosen:updated'); + if($(this).is(':checked')) + { + $('#reviewerBox').removeClass('required'); + } + else + { + $('#reviewerBox').addClass('required'); + } + }); + if(!$('#reviewer').val()) $('#needNotReview').change(); +}); diff --git a/module/story/lang/de.php b/module/story/lang/de.php index 2f4a09e28c..d68a60cd42 100644 --- a/module/story/lang/de.php +++ b/module/story/lang/de.php @@ -23,10 +23,14 @@ $lang->story->change = "Ändern"; $lang->story->changed = 'Geändert'; $lang->story->assignTo = 'Assign'; $lang->story->review = 'Prüfen'; +$lang->story->submitReview = "Submit Review"; $lang->story->recall = 'Revoke'; +$lang->story->recallChange = 'Undo Changes'; +$lang->story->recallAction = 'Undo'; $lang->story->needReview = 'Need Review'; $lang->story->batchReview = 'Mehere prüfen'; $lang->story->edit = "Bearbeiten"; +$lang->story->editDraft = "Entwurf bearbeiten"; $lang->story->batchEdit = "Mehere bearbeiten"; $lang->story->subdivide = 'Aufteilen'; $lang->story->link = 'Link'; @@ -50,7 +54,7 @@ $lang->story->caseCount = 'Fälle'; $lang->story->taskCountAB = 'T'; $lang->story->bugCountAB = 'B'; $lang->story->caseCountAB = 'C'; -$lang->story->linkStory = 'Verküpfen'; +$lang->story->linkStory = 'Link Requirement'; $lang->story->unlinkStory = 'Verknüpfung aufheben'; $lang->story->linkStoriesAB = "Link {$lang->SRCommon}"; $lang->story->linkRequirementsAB = "Link {$lang->URCommon}"; @@ -70,6 +74,8 @@ $lang->story->batchToTask = 'Batch Convert to Task'; $lang->story->convertRelations = 'Convert Relations'; $lang->story->undetermined = 'undetermined'; $lang->story->order = 'Order'; +$lang->story->saveDraft = 'Save as draft'; +$lang->story->doNotSubmit = 'Do Not Submit'; $lang->story->editAction = "Edit {$lang->SRCommon}"; $lang->story->changeAction = "Change Story"; @@ -82,12 +88,13 @@ $lang->story->deleteAction = "Delete Story"; $lang->story->exportAction = "Export Story"; $lang->story->reportAction = "Story Report"; -$lang->story->skipStory = '%s is a parent story. It cannot be closed.'; -$lang->story->closedStory = 'Story %s is closed and will not be closed.'; -$lang->story->batchToTaskTips = "The closed {$lang->SRCommon} will not be converted into tasks."; -$lang->story->successToTask = "Converted to task."; -$lang->story->storyRound = '%s time estimation'; -$lang->story->float = "『%s』should be positive number, decimals included."; +$lang->story->skipStory = '%s is a parent story. It cannot be closed.'; +$lang->story->closedStory = 'Story %s is closed and will not be closed.'; +$lang->story->batchToTaskTips = "The closed {$lang->SRCommon} will not be converted into tasks."; +$lang->story->successToTask = "Converted to task."; +$lang->story->storyRound = '%s time estimation'; +$lang->story->float = "『%s』should be positive number, decimals included."; +$lang->story->saveDraftSuccess = 'Save as draft succeeded.'; $lang->story->id = 'ID'; $lang->story->parent = 'Parent'; @@ -130,6 +137,8 @@ $lang->story->closedBy = 'Geschlossen von'; $lang->story->closedDate = 'Geschlossen am'; $lang->story->closedReason = 'Geschlossen weil'; $lang->story->rejectedReason = 'Abgelehnt weil'; +$lang->story->changedBy = 'ChangedBy'; +$lang->story->changedDate = 'ChangedDate'; $lang->story->reviewedBy = 'Prüfer'; $lang->story->reviewer = $lang->story->reviewedBy; $lang->story->reviewers = 'Reviewers'; @@ -146,7 +155,7 @@ $lang->story->childrenAB = "C"; $lang->story->linkStories = 'Story verknüpfen'; $lang->story->linkRequirements = "Linked {$lang->URCommon}"; $lang->story->childStories = 'Story aufteilen'; -$lang->story->duplicateStory = 'Story ID kopieren'; +$lang->story->duplicateStory = 'Story kopieren'; $lang->story->reviewResult = 'Ergbnis prüfen'; $lang->story->reviewResultAB = 'Bewertungsergebnisse'; $lang->story->preVersion = 'Frühere Version'; @@ -182,11 +191,12 @@ $lang->story->needNotReviewList[1] = 'Need Not Review'; $lang->story->useList[0] = 'Ja'; $lang->story->useList[1] = 'Nein'; -$lang->story->statusList[''] = ''; -$lang->story->statusList['draft'] = 'Entwurf'; -$lang->story->statusList['active'] = 'Aktiv'; -$lang->story->statusList['closed'] = 'Geschlossen'; -$lang->story->statusList['changed'] = 'Geändert'; +$lang->story->statusList[''] = ''; +$lang->story->statusList['draft'] = 'Entwurf'; +$lang->story->statusList['reviewing'] = 'Wird geprüft'; +$lang->story->statusList['active'] = 'Aktiv'; +$lang->story->statusList['closed'] = 'Geschlossen'; +$lang->story->statusList['changing'] = 'Geändert'; $lang->story->stageList[''] = ''; $lang->story->stageList['wait'] = 'Wartend'; @@ -295,6 +305,8 @@ $lang->story->estimateMustBePlus = 'Estimated value cannot be negative'; $lang->story->confirmChangeBranch = $lang->SRCommon . ' %s is linked to the plan of its linked branch. If the branch is edited, ' . $lang->SRCommon . ' will be removed from the plan of its linked branch. Do you want to continue edit ' . $lang->SRCommon . '?'; $lang->story->confirmChangePlan = $lang->SRCommon . ' %s is linked to the branch of its plan. If the branch is edited, ' . $lang->SRCommon . ' will be removed from the plan. Do you want to continue edit branch ?'; $lang->story->errorDuplicateStory = $lang->SRCommon . '%s not exist'; +$lang->story->confirmRecallChange = "After undo the change, the story content will revert to the version before the change. Are you sure you want to undo?"; +$lang->story->confirmRecallReview = "Are you sure you want to withdraw the review?"; $lang->story->form = new stdclass(); $lang->story->form->area = 'Story Bereich'; @@ -325,6 +337,7 @@ $lang->story->action->linkrelatedstory = array('main' => '$date, verknüpft $lang->story->action->subdividestory = array('main' => '$date, aufgeteilt von $actor mit Story $extra.'); $lang->story->action->unlinkrelatedstory = array('main' => '$date, Verknüpfung aufgelöst durch $actor von Story $extra.'); $lang->story->action->unlinkchildstory = array('main' => '$date, Verknüpfung aufgelöst durch $actor Story $extra.'); +$lang->story->action->recalledchange = array('main' => '$date, Undo changes by \$actor.'); /* Statistical statement. */ $lang->story->report = new stdclass(); @@ -452,6 +465,8 @@ $lang->story->subDivideTip['notActive'] = 'The Story is not active and cannot be $lang->story->featureBar['browse']['all'] = $lang->all; $lang->story->featureBar['browse']['unclosed'] = $lang->story->unclosed; +$lang->story->featureBar['browse']['draft'] = $lang->story->statusList['draft']; +$lang->story->featureBar['browse']['reviewing'] = $lang->story->statusList['reviewing']; $lang->requirement->common = $lang->URCommon; $lang->requirement->create = 'Create Requirement'; @@ -466,7 +481,7 @@ $lang->requirement->activateAction = "Activate {$lang->URCommon}"; $lang->requirement->deleteAction = "Delete {$lang->URCommon}"; $lang->requirement->exportAction = "Export {$lang->URCommon}"; $lang->requirement->reportAction = "Report"; -$lang->requirement->recall = 'Revoke'; +$lang->requirement->recall = $lang->story->recallAction; $lang->requirement->batchReview = 'Batch Review'; $lang->requirement->batchEdit = "Batch Edit"; $lang->requirement->batchClose = 'Batch Close'; @@ -475,3 +490,5 @@ $lang->requirement->linkRequirementsAB = "Link {$lang->URCommon}"; $lang->requirement->batchChangeBranch = "Batch Change Branches"; $lang->requirement->batchAssignTo = "Batch Assign"; $lang->requirement->batchChangeModule = "Batch Change Modules"; +$lang->requirement->submitReview = $lang->story->submitReview; +$lang->requirement->linkStory = 'Link Story'; diff --git a/module/story/lang/en.php b/module/story/lang/en.php index bacb2482ad..8001b3e6e7 100644 --- a/module/story/lang/en.php +++ b/module/story/lang/en.php @@ -23,10 +23,14 @@ $lang->story->change = "Change"; $lang->story->changed = 'Change'; $lang->story->assignTo = 'Assign'; $lang->story->review = 'Review'; +$lang->story->submitReview = "Submit Review"; $lang->story->recall = 'Revoke'; +$lang->story->recallChange = 'Undo Changes'; +$lang->story->recallAction = 'Undo'; $lang->story->needReview = 'Need Review'; $lang->story->batchReview = 'Batch Review'; $lang->story->edit = "Edit Story"; +$lang->story->editDraft = "Edit Draft"; $lang->story->batchEdit = "Batch Edit"; $lang->story->subdivide = 'Decompose'; $lang->story->link = 'Link'; @@ -50,7 +54,7 @@ $lang->story->caseCount = 'Cases'; $lang->story->taskCountAB = 'T'; $lang->story->bugCountAB = 'B'; $lang->story->caseCountAB = 'C'; -$lang->story->linkStory = 'Link Story'; +$lang->story->linkStory = 'Link Requirement'; $lang->story->unlinkStory = 'UnLinked'; $lang->story->linkStoriesAB = "Link {$lang->SRCommon}"; $lang->story->linkRequirementsAB = "Link {$lang->URCommon}"; @@ -70,6 +74,8 @@ $lang->story->batchToTask = 'Batch Convert to Task'; $lang->story->convertRelations = 'Convert Relations'; $lang->story->undetermined = 'undetermined'; $lang->story->order = 'Order'; +$lang->story->saveDraft = 'Save as draft'; +$lang->story->doNotSubmit = 'Do Not Submit'; $lang->story->editAction = "Edit {$lang->SRCommon}"; $lang->story->changeAction = "Change {$lang->SRCommon}"; @@ -82,12 +88,13 @@ $lang->story->deleteAction = "Delete {$lang->SRCommon}"; $lang->story->exportAction = "Export {$lang->SRCommon}"; $lang->story->reportAction = "Report"; -$lang->story->skipStory = '%s is a parent story. It cannot be closed.'; -$lang->story->closedStory = 'Story %s is closed and will not be closed.'; -$lang->story->batchToTaskTips = "The closed {$lang->SRCommon} will not be converted into tasks."; -$lang->story->successToTask = "Converted to task."; -$lang->story->storyRound = '%s time estimation'; -$lang->story->float = "『%s』should have positive number, or decimals."; +$lang->story->skipStory = '%s is a parent story. It cannot be closed.'; +$lang->story->closedStory = 'Story %s is closed and will not be closed.'; +$lang->story->batchToTaskTips = "The closed {$lang->SRCommon} will not be converted into tasks."; +$lang->story->successToTask = "Converted to task."; +$lang->story->storyRound = '%s time estimation'; +$lang->story->float = "『%s』should have positive number, or decimals."; +$lang->story->saveDraftSuccess = 'Save as draft succeeded.'; $lang->story->id = 'ID'; $lang->story->parent = 'Parent'; @@ -130,6 +137,8 @@ $lang->story->closedBy = 'ClosedBy'; $lang->story->closedDate = 'ClosedDate'; $lang->story->closedReason = 'Reason'; $lang->story->rejectedReason = 'Reject Reason'; +$lang->story->changedBy = 'ChangedBy'; +$lang->story->changedDate = 'ChangedDate'; $lang->story->reviewedBy = 'ReviewedBy'; $lang->story->reviewer = $lang->story->reviewedBy; $lang->story->reviewers = 'Reviewers'; @@ -146,7 +155,7 @@ $lang->story->childrenAB = "C"; $lang->story->linkStories = 'Linked Story'; $lang->story->linkRequirements = "Linked {$lang->URCommon}"; $lang->story->childStories = 'Decomposed Story'; -$lang->story->duplicateStory = 'Duplicated Story ID'; +$lang->story->duplicateStory = 'Duplicated Story'; $lang->story->reviewResult = 'Review Result'; $lang->story->reviewResultAB = 'Assessment results'; $lang->story->preVersion = 'Last Version'; @@ -182,11 +191,12 @@ $lang->story->needNotReviewList[1] = 'No Review'; $lang->story->useList[0] = 'Yes'; $lang->story->useList[1] = 'No'; -$lang->story->statusList[''] = ''; -$lang->story->statusList['draft'] = 'Draft'; -$lang->story->statusList['active'] = 'Active'; -$lang->story->statusList['closed'] = 'Closed'; -$lang->story->statusList['changed'] = 'Changed'; +$lang->story->statusList[''] = ''; +$lang->story->statusList['draft'] = 'Draft'; +$lang->story->statusList['reviewing'] = 'Reviewing'; +$lang->story->statusList['active'] = 'Active'; +$lang->story->statusList['closed'] = 'Closed'; +$lang->story->statusList['changing'] = 'Changing'; $lang->story->stageList[''] = ''; $lang->story->stageList['wait'] = 'Waiting'; @@ -295,6 +305,8 @@ $lang->story->estimateMustBePlus = 'Estimated value cannot be negative'; $lang->story->confirmChangeBranch = $lang->SRCommon . ' %s is linked to the plan of its linked branch. If the branch is edited, ' . $lang->SRCommon . ' will be removed from the plan of its linked branch. Do you want to continue edit ' . $lang->SRCommon . '?'; $lang->story->confirmChangePlan = $lang->SRCommon . ' %s is linked to the branch of its plan. If the branch is edited, ' . $lang->SRCommon . ' will be removed from the plan. Do you want to continue edit branch ?'; $lang->story->errorDuplicateStory = $lang->SRCommon . '%s not exist'; +$lang->story->confirmRecallChange = "After undo the change, the story content will revert to the version before the change. Are you sure you want to undo?"; +$lang->story->confirmRecallReview = "Are you sure you want to withdraw the review?"; $lang->story->form = new stdclass(); $lang->story->form->area = 'Scope'; @@ -325,6 +337,7 @@ $lang->story->action->linkrelatedstory = array('main' => '$date, linked by $lang->story->action->subdividestory = array('main' => '$date, decomposed by $actor to Story $extra.'); $lang->story->action->unlinkrelatedstory = array('main' => '$date, unlinked by $actor from Story $extra.'); $lang->story->action->unlinkchildstory = array('main' => '$date, unlinked by $actor Decomposed Story $extra.'); +$lang->story->action->recalledchange = array('main' => '$date, Undo changes by \$actor.'); /* Statistical statement. */ $lang->story->report = new stdclass(); @@ -452,6 +465,8 @@ $lang->story->subDivideTip['notActive'] = 'The Story is not active and cannot be $lang->story->featureBar['browse']['all'] = $lang->all; $lang->story->featureBar['browse']['unclosed'] = $lang->story->unclosed; +$lang->story->featureBar['browse']['draft'] = $lang->story->statusList['draft']; +$lang->story->featureBar['browse']['reviewing'] = $lang->story->statusList['reviewing']; $lang->requirement->common = $lang->URCommon; $lang->requirement->create = 'Create Requirement'; @@ -466,7 +481,7 @@ $lang->requirement->activateAction = "Activate {$lang->URCommon}"; $lang->requirement->deleteAction = "Delete {$lang->URCommon}"; $lang->requirement->exportAction = "Export {$lang->URCommon}"; $lang->requirement->reportAction = "Report"; -$lang->requirement->recall = 'Revoke'; +$lang->requirement->recall = $lang->story->recallAction; $lang->requirement->batchReview = 'Batch Review'; $lang->requirement->batchEdit = "Batch Edit"; $lang->requirement->batchClose = 'Batch Close'; @@ -475,3 +490,5 @@ $lang->requirement->linkRequirementsAB = "Link {$lang->URCommon}"; $lang->requirement->batchChangeBranch = "Batch Change Branches"; $lang->requirement->batchAssignTo = "Batch Assign"; $lang->requirement->batchChangeModule = "Batch Change Modules"; +$lang->requirement->submitReview = $lang->story->submitReview; +$lang->requirement->linkStory = 'Link Story'; diff --git a/module/story/lang/fr.php b/module/story/lang/fr.php index c5fa55f6d6..573de4d391 100644 --- a/module/story/lang/fr.php +++ b/module/story/lang/fr.php @@ -23,10 +23,14 @@ $lang->story->change = "Changer"; $lang->story->changed = 'Changée'; $lang->story->assignTo = 'Affecter'; $lang->story->review = 'Valider'; +$lang->story->submitReview = "Submit Review"; $lang->story->recall = 'Revoke'; +$lang->story->recallChange = 'Undo Changes'; +$lang->story->recallAction = 'Undo'; $lang->story->needReview = 'Validation requise'; $lang->story->batchReview = 'Validation par lot'; $lang->story->edit = "Editer Story"; +$lang->story->editDraft = "Modifier le projet"; $lang->story->batchEdit = "Editer par Lot"; $lang->story->subdivide = 'Décomposer'; $lang->story->link = 'Link'; @@ -50,7 +54,7 @@ $lang->story->caseCount = 'CasTests'; $lang->story->taskCountAB = 'T'; $lang->story->bugCountAB = 'B'; $lang->story->caseCountAB = 'C'; -$lang->story->linkStory = 'Lier Story'; +$lang->story->linkStory = 'Lier Requirement'; $lang->story->unlinkStory = 'Dissocier'; $lang->story->linkStoriesAB = "Lier {$lang->SRCommon}"; $lang->story->linkRequirementsAB = "Lier {$lang->URCommon}"; @@ -70,6 +74,8 @@ $lang->story->batchToTask = 'Batch Convert to Task'; $lang->story->convertRelations = 'Convert Relations'; $lang->story->undetermined = 'undetermined'; $lang->story->order = 'Order'; +$lang->story->saveDraft = 'Save as draft'; +$lang->story->doNotSubmit = 'Do Not Submit'; $lang->story->editAction = "Edit {$lang->SRCommon}"; $lang->story->changeAction = "Changer Story"; @@ -82,12 +88,13 @@ $lang->story->deleteAction = "Supprimer Story"; $lang->story->exportAction = "Exporter Story"; $lang->story->reportAction = "Rapport de Story"; -$lang->story->skipStory = '%s is a parent story. It cannot be closed.'; -$lang->story->closedStory = 'Story %s is closed and will not be closed.'; -$lang->story->batchToTaskTips = "The closed {$lang->SRCommon} will not be converted into tasks."; -$lang->story->successToTask = "Converted to task."; -$lang->story->storyRound = '%s time estimation'; -$lang->story->float = "『 %s 』doit avoir des nombres positifs ou décimaux."; +$lang->story->skipStory = '%s is a parent story. It cannot be closed.'; +$lang->story->closedStory = 'Story %s is closed and will not be closed.'; +$lang->story->batchToTaskTips = "The closed {$lang->SRCommon} will not be converted into tasks."; +$lang->story->successToTask = "Converted to task."; +$lang->story->storyRound = '%s time estimation'; +$lang->story->float = "『 %s 』doit avoir des nombres positifs ou décimaux."; +$lang->story->saveDraftSuccess = 'Save as draft succeeded.'; $lang->story->id = 'ID'; $lang->story->parent = 'Parent'; @@ -130,6 +137,8 @@ $lang->story->closedBy = 'Fermée par'; $lang->story->closedDate = 'Date Fermeture'; $lang->story->closedReason = 'Raison'; $lang->story->rejectedReason = 'Raison du Rejet'; +$lang->story->changedBy = 'ChangedBy'; +$lang->story->changedDate = 'ChangedDate'; $lang->story->reviewedBy = 'Validée par'; $lang->story->reviewer = $lang->story->reviewedBy; $lang->story->reviewers = 'Reviewers'; @@ -146,7 +155,7 @@ $lang->story->childrenAB = "C"; $lang->story->linkStories = 'Stories Liées'; $lang->story->linkRequirements = "{$lang->URCommon} Lié es"; $lang->story->childStories = 'Stories Décomposées'; -$lang->story->duplicateStory = 'Story ID Dupliquées'; +$lang->story->duplicateStory = 'Story Dupliquées'; $lang->story->reviewResult = 'Résultat Validation'; $lang->story->reviewResultAB = 'Résultats de lévaluation'; $lang->story->preVersion = 'Dernière Version'; @@ -158,7 +167,7 @@ $lang->story->copy = "Copier Story"; $lang->story->total = "Stories Total"; $lang->story->draft = 'Brouillon'; $lang->story->unclosed = 'Non Fermées'; -$lang->story->deleted = 'Supprimée'; +$lang->story->deleted = 'Supprimé'; $lang->story->released = 'Stories Versionnées'; $lang->story->URChanged = 'Requirement Changed'; $lang->story->design = 'Designs'; @@ -182,11 +191,12 @@ $lang->story->needNotReviewList[1] = 'Need Not Review'; $lang->story->useList[0] = 'Oui'; $lang->story->useList[1] = 'Non'; -$lang->story->statusList[''] = ''; -$lang->story->statusList['draft'] = 'Brouillon'; -$lang->story->statusList['active'] = 'Active'; -$lang->story->statusList['closed'] = 'Fermée'; -$lang->story->statusList['changed'] = 'Changée'; +$lang->story->statusList[''] = ''; +$lang->story->statusList['draft'] = 'Brouillon'; +$lang->story->statusList['reviewing'] = 'Examen en cours'; +$lang->story->statusList['active'] = 'Active'; +$lang->story->statusList['closed'] = 'Fermée'; +$lang->story->statusList['changing'] = 'Changée'; $lang->story->stageList[''] = ''; $lang->story->stageList['wait'] = 'En Attente'; @@ -295,6 +305,8 @@ $lang->story->estimateMustBePlus = 'Estimated value cannot be negative'; $lang->story->confirmChangeBranch = $lang->SRCommon . ' %s is linked to the plan of its linked branch. If the branch is edited, ' . $lang->SRCommon . ' will be removed from the plan of its linked branch. Do you want to continue edit ' . $lang->SRCommon . '?'; $lang->story->confirmChangePlan = $lang->SRCommon . ' %s is linked to the branch of its plan. If the branch is edited, ' . $lang->SRCommon . ' will be removed from the plan. Do you want to continue edit branch ?'; $lang->story->errorDuplicateStory = $lang->SRCommon . '%s not exist'; +$lang->story->confirmRecallChange = "After undo the change, the story content will revert to the version before the change. Are you sure you want to undo?"; +$lang->story->confirmRecallReview = "Are you sure you want to withdraw the review?"; $lang->story->form = new stdclass(); $lang->story->form->area = 'Périmètre'; @@ -325,6 +337,7 @@ $lang->story->action->linkrelatedstory = array('main' => '$date, associée $lang->story->action->subdividestory = array('main' => '$date, décomposée par $actor en Story $extra.'); $lang->story->action->unlinkrelatedstory = array('main' => '$date, dissociée par $actor de la Story $extra.'); $lang->story->action->unlinkchildstory = array('main' => '$date, dissociée par $actor de la sous-Story $extra.'); +$lang->story->action->recalledchange = array('main' => '$date, Undo changes by \$actor.'); /* Statistical statement. */ $lang->story->report = new stdclass(); @@ -450,8 +463,10 @@ $lang->story->subDivideTip['planned'] = 'Cette Story est planifiée et ne peut $lang->story->subDivideTip['projected'] = 'Cette Story a été créée et ne peut être subdivisée.'; $lang->story->subDivideTip['notActive'] = "Cette Story n'est pas active et ne peut être subdivisée."; -$lang->story->featureBar['browse']['all'] = $lang->all; -$lang->story->featureBar['browse']['unclosed'] = $lang->story->unclosed; +$lang->story->featureBar['browse']['all'] = $lang->all; +$lang->story->featureBar['browse']['unclosed'] = $lang->story->unclosed; +$lang->story->featureBar['browse']['draft'] = $lang->story->statusList['draft']; +$lang->story->featureBar['browse']['reviewing'] = $lang->story->statusList['reviewing']; $lang->requirement->common = $lang->URCommon; $lang->requirement->create = 'Create Requirement'; @@ -466,7 +481,7 @@ $lang->requirement->activateAction = "Activate {$lang->URCommon}"; $lang->requirement->deleteAction = "Delete {$lang->URCommon}"; $lang->requirement->exportAction = "Export {$lang->URCommon}"; $lang->requirement->reportAction = "Report"; -$lang->requirement->recall = 'Revoke'; +$lang->requirement->recall = $lang->story->recallAction; $lang->requirement->batchReview = 'Batch Review'; $lang->requirement->batchEdit = "Batch Edit"; $lang->requirement->batchClose = 'Batch Close'; @@ -475,3 +490,5 @@ $lang->requirement->linkRequirementsAB = "Link {$lang->URCommon}"; $lang->requirement->batchChangeBranch = "Batch Change Branches"; $lang->requirement->batchAssignTo = "Batch Assign"; $lang->requirement->batchChangeModule = "Batch Change Modules"; +$lang->requirement->submitReview = $lang->story->submitReview; +$lang->requirement->linkStory = 'Lier Story'; diff --git a/module/story/lang/vi.php b/module/story/lang/vi.php index d650626784..9226a926c0 100644 --- a/module/story/lang/vi.php +++ b/module/story/lang/vi.php @@ -23,10 +23,14 @@ $lang->story->change = "Thay đổi"; $lang->story->changed = "Đã đổi"; $lang->story->assignTo = 'Giao cho'; $lang->story->review = 'Xét duyệt'; +$lang->story->submitReview = "Submit Review"; $lang->story->recall = 'Revoke'; +$lang->story->recallChange = 'Undo Changes'; +$lang->story->recallAction = 'Undo'; $lang->story->needReview = 'Duyệt nhu cầu'; $lang->story->batchReview = 'Duyệt hàng loạt'; $lang->story->edit = "Sửa câu chuyện"; +$lang->story->editDraft = "Sửa soạn thảo"; $lang->story->batchEdit = "Sửa hàng loạt"; $lang->story->subdivide = 'Phân rã'; $lang->story->link = 'Link'; @@ -68,6 +72,8 @@ $lang->story->batchToTask = 'Batch Convert to Task'; $lang->story->convertRelations = 'Convert Relations'; $lang->story->undetermined = 'undetermined'; $lang->story->order = 'Order'; +$lang->story->saveDraft = 'Save as draft'; +$lang->story->doNotSubmit = 'Do Not Submit'; $lang->story->editAction = "Edit {$lang->SRCommon}"; $lang->story->changeAction = "Change {$lang->SRCommon}"; @@ -80,11 +86,13 @@ $lang->story->deleteAction = "Delete {$lang->SRCommon}"; $lang->story->exportAction = "Export {$lang->SRCommon}"; $lang->story->reportAction = "Report"; -$lang->story->skipStory = '%s is a parent story. It cannot be closed.'; -$lang->story->closedStory = 'Story %s is closed and will not be closed.'; -$lang->story->batchToTaskTips = "This action will create a task with the same name as the selected {$lang->SRCommon} and link {$lang->SRCommon} to the task. The closed {$lang->SRCommon} will not be converted into tasks."; -$lang->story->successToTask = "Converted to task."; -$lang->story->storyRound = '%s time estimation'; +$lang->story->skipStory = '%s is a parent story. It cannot be closed.'; +$lang->story->closedStory = 'Story %s is closed and will not be closed.'; +$lang->story->batchToTaskTips = "This action will create a task with the same name as the selected {$lang->SRCommon} and link {$lang->SRCommon} to the task. The closed {$lang->SRCommon} will not be converted into tasks."; +$lang->story->successToTask = "Converted to task."; +$lang->story->storyRound = '%s time estimation'; +$lang->story->float = "『%s』should be positive number, decimals included."; +$lang->story->saveDraftSuccess = 'Save as draft succeeded.'; $lang->story->id = 'ID'; $lang->story->parent = 'Mẹ'; @@ -124,6 +132,8 @@ $lang->story->closedBy = 'Người đóng'; $lang->story->closedDate = 'Ngày đóng'; $lang->story->closedReason = 'Lý do'; $lang->story->rejectedReason = 'Lý do từ chối'; +$lang->story->changedBy = 'ChangedBy'; +$lang->story->changedDate = 'ChangedDate'; $lang->story->reviewedBy = 'Người duyệt'; $lang->story->reviewer = $lang->story->reviewedBy; $lang->story->reviewers = 'Reviewers'; @@ -175,11 +185,12 @@ $lang->story->needNotReviewList[1] = 'Need Not Review'; $lang->story->useList[0] = 'Có'; $lang->story->useList[1] = 'Không'; -$lang->story->statusList[''] = ''; -$lang->story->statusList['draft'] = 'Nháp'; -$lang->story->statusList['active'] = 'Kích hoạt'; -$lang->story->statusList['closed'] = 'Đã đóng'; -$lang->story->statusList['changed'] = 'Đã thay đổi'; +$lang->story->statusList[''] = ''; +$lang->story->statusList['draft'] = 'Nháp'; +$lang->story->statusList['reviewing'] = 'Đang xem xét'; +$lang->story->statusList['active'] = 'Kích hoạt'; +$lang->story->statusList['closed'] = 'Đã đóng'; +$lang->story->statusList['changing'] = 'Đã thay đổi'; $lang->story->stageList[''] = ''; $lang->story->stageList['wait'] = 'Đang đợi'; @@ -286,6 +297,8 @@ $lang->story->estimateMustBePlus = 'Estimated value cannot be negative'; $lang->story->confirmChangeBranch = $lang->SRCommon . ' %s is linked to the plan of its linked branch. If the branch is edited, ' . $lang->SRCommon . ' will be removed from the plan of its linked branch. Do you want to continue edit ' . $lang->SRCommon . '?'; $lang->story->confirmChangePlan = $lang->SRCommon . ' %s is linked to the branch of its plan. If the branch is edited, ' . $lang->SRCommon . ' will be removed from the plan. Do you want to continue edit branch ?'; $lang->story->errorDuplicateStory = $lang->SRCommon . '%s not exist'; +$lang->story->confirmRecallChange = "After undo the change, the story content will revert to the version before the change. Are you sure you want to undo?"; +$lang->story->confirmRecallReview = "Are you sure you want to withdraw the review?"; $lang->story->form = new stdclass(); $lang->story->form->area = 'Phạm vi'; @@ -316,6 +329,7 @@ $lang->story->action->linkrelatedstory = array('main' => '$date, liên kế $lang->story->action->subdividestory = array('main' => '$date, được phân rã bởi $actor tới Câu chuyện $extra.'); $lang->story->action->unlinkrelatedstory = array('main' => '$date, bị hủy bởi $actor từ Câu chuyện $extra.'); $lang->story->action->unlinkchildstory = array('main' => '$date, bị hủy bởi $actor Câu chuyện được phân rã $extra.'); +$lang->story->action->recalledchange = array('main' => '$date, Undo changes by \$actor.'); /* Statistical statement. */ $lang->story->report = new stdclass(); @@ -441,5 +455,7 @@ $lang->story->subDivideTip['planned'] = 'The Story has been planned and cannot $lang->story->subDivideTip['projected'] = 'The Story has been initiated and cannot be subdivided.'; $lang->story->subDivideTip['notActive'] = 'The Story is not active and cannot be subdivided.'; -$lang->story->featureBar['browse']['all'] = $lang->all; -$lang->story->featureBar['browse']['unclosed'] = $lang->story->unclosed; +$lang->story->featureBar['browse']['all'] = $lang->all; +$lang->story->featureBar['browse']['unclosed'] = $lang->story->unclosed; +$lang->story->featureBar['browse']['draft'] = $lang->story->statusList['draft']; +$lang->story->featureBar['browse']['reviewing'] = $lang->story->statusList['reviewing']; diff --git a/module/story/lang/zh-cn.php b/module/story/lang/zh-cn.php index fbd2017f45..b694c39596 100644 --- a/module/story/lang/zh-cn.php +++ b/module/story/lang/zh-cn.php @@ -23,10 +23,14 @@ $lang->story->change = "变更"; $lang->story->changed = "{$lang->SRCommon}变更"; $lang->story->assignTo = '指派'; $lang->story->review = '评审'; +$lang->story->submitReview = "提交评审"; $lang->story->recall = '撤销评审'; +$lang->story->recallChange = '撤销变更'; +$lang->story->recallAction = '撤销'; $lang->story->needReview = '需要评审'; $lang->story->batchReview = '批量评审'; $lang->story->edit = "编辑"; +$lang->story->editDraft = "编辑草稿"; $lang->story->batchEdit = "批量编辑"; $lang->story->subdivide = '细分'; $lang->story->link = '关联'; @@ -50,7 +54,7 @@ $lang->story->caseCount = '用例数'; $lang->story->taskCountAB = 'T'; $lang->story->bugCountAB = 'B'; $lang->story->caseCountAB = 'C'; -$lang->story->linkStory = "关联{$lang->SRCommon}"; +$lang->story->linkStory = "关联{$lang->URCommon}"; $lang->story->unlinkStory = "移除相关{$lang->SRCommon}"; $lang->story->linkStoriesAB = "关联相关{$lang->SRCommon}"; $lang->story->linkRequirementsAB = "关联相关{$lang->URCommon}"; @@ -70,6 +74,8 @@ $lang->story->batchToTask = '批量转任务'; $lang->story->convertRelations = '换算关系'; $lang->story->undetermined = '待定'; $lang->story->order = '排序'; +$lang->story->saveDraft = '存为草稿'; +$lang->story->doNotSubmit = '保存暂不提交'; $lang->story->editAction = "编辑{$lang->SRCommon}"; $lang->story->changeAction = "变更{$lang->SRCommon}"; @@ -82,12 +88,13 @@ $lang->story->deleteAction = "删除{$lang->SRCommon}"; $lang->story->exportAction = "导出{$lang->SRCommon}"; $lang->story->reportAction = "统计报表"; -$lang->story->skipStory = '需求:%s 为父需求,将不会被关闭。'; -$lang->story->closedStory = '需求:%s 已关闭,将不会被关闭。'; -$lang->story->batchToTaskTips = "已关闭的需求不会转为任务。"; -$lang->story->successToTask = '批量转任务成功'; -$lang->story->storyRound = '第 %s 轮估算'; -$lang->story->float = "『%s』应当是正数,可以是小数。"; +$lang->story->skipStory = '需求:%s 为父需求,将不会被关闭。'; +$lang->story->closedStory = '需求:%s 已关闭,将不会被关闭。'; +$lang->story->batchToTaskTips = "已关闭的需求不会转为任务。"; +$lang->story->successToTask = '批量转任务成功'; +$lang->story->storyRound = '第 %s 轮估算'; +$lang->story->float = "『%s』应当是正数,可以是小数。"; +$lang->story->saveDraftSuccess = '存为草稿成功'; $lang->story->id = '编号'; $lang->story->parent = '父需求'; @@ -130,6 +137,8 @@ $lang->story->closedBy = '由谁关闭'; $lang->story->closedDate = '关闭日期'; $lang->story->closedReason = '关闭原因'; $lang->story->rejectedReason = '拒绝原因'; +$lang->story->changedBy = '由谁变更'; +$lang->story->changedDate = '变更时间'; $lang->story->reviewedBy = '由谁评审'; $lang->story->reviewer = $lang->story->reviewedBy; $lang->story->reviewers = '评审人员'; @@ -145,8 +154,8 @@ $lang->story->children = "子需求"; $lang->story->childrenAB = "子"; $lang->story->linkStories = "相关{$lang->SRCommon}"; $lang->story->linkRequirements = "相关{$lang->URCommon}"; -$lang->story->childStories = "细分需求"; -$lang->story->duplicateStory = "重复需求ID"; +$lang->story->childStories = "细分{$lang->SRCommon}"; +$lang->story->duplicateStory = "重复{$lang->SRCommon}"; $lang->story->reviewResult = '评审意见'; $lang->story->reviewResultAB = '评审结果'; $lang->story->preVersion = '之前版本'; @@ -182,11 +191,12 @@ $lang->story->needNotReviewList[1] = '不需要评审'; $lang->story->useList[0] = '不使用'; $lang->story->useList[1] = '使用'; -$lang->story->statusList[''] = ''; -$lang->story->statusList['draft'] = '草稿'; -$lang->story->statusList['active'] = '激活'; -$lang->story->statusList['closed'] = '已关闭'; -$lang->story->statusList['changed'] = '已变更'; +$lang->story->statusList[''] = ''; +$lang->story->statusList['draft'] = '草稿'; +$lang->story->statusList['reviewing'] = '评审中'; +$lang->story->statusList['active'] = '激活'; +$lang->story->statusList['closed'] = '已关闭'; +$lang->story->statusList['changing'] = '变更中'; $lang->story->stageList[''] = ''; $lang->story->stageList['wait'] = '未开始'; @@ -295,6 +305,8 @@ $lang->story->estimateMustBePlus = '估算值不能是负数'; $lang->story->confirmChangeBranch = $lang->SRCommon . '%s已关联在之前所属分支的计划中,调整分支后,' . $lang->SRCommon . '将从之前所属分支的计划中移除,请确认是否继续修改上述' . $lang->SRCommon . '的分支。'; $lang->story->confirmChangePlan = $lang->SRCommon . '%s已关联在之前计划的所属分支中,调整分支后,' . $lang->SRCommon . '将会从计划中移除,请确认是否继续修改计划的所属分支。'; $lang->story->errorDuplicateStory = $lang->SRCommon . '%s不存在'; +$lang->story->confirmRecallChange = "撤销变更后,需求内容会回退至变更前的版本,您确定要撤销吗?"; +$lang->story->confirmRecallReview = "您确定要撤回评审吗?"; $lang->story->form = new stdclass(); $lang->story->form->area = "该{$lang->SRCommon}所属范围"; @@ -325,6 +337,7 @@ $lang->story->action->linkrelatedstory = array('main' => "\$date, 由 story->action->subdividestory = array('main' => "\$date, 由 \$actor 细分为{$lang->SRCommon} \$extra。"); $lang->story->action->unlinkrelatedstory = array('main' => "\$date, 由 \$actor 移除相关{$lang->SRCommon} \$extra。"); $lang->story->action->unlinkchildstory = array('main' => "\$date, 由 \$actor 移除细分{$lang->SRCommon} \$extra。"); +$lang->story->action->recalledchange = array('main' => "\$date, 由 \$actor 撤销变更。"); /* 统计报表。*/ $lang->story->report = new stdclass(); @@ -450,8 +463,10 @@ $lang->story->subDivideTip['planned'] = '该需求已计划,无法进行细 $lang->story->subDivideTip['projected'] = '该需求已立项,无法进行细分操作'; $lang->story->subDivideTip['notActive'] = '需求不是激活状态,无法进行细分操作'; -$lang->story->featureBar['browse']['all'] = $lang->all; -$lang->story->featureBar['browse']['unclosed'] = $lang->story->unclosed; +$lang->story->featureBar['browse']['all'] = $lang->all; +$lang->story->featureBar['browse']['unclosed'] = $lang->story->unclosed; +$lang->story->featureBar['browse']['draft'] = $lang->story->statusList['draft']; +$lang->story->featureBar['browse']['reviewing'] = $lang->story->statusList['reviewing']; $lang->requirement->common = $lang->URCommon; $lang->requirement->create = "提{$lang->URCommon}"; @@ -466,7 +481,7 @@ $lang->requirement->activateAction = "激活{$lang->URCommon}"; $lang->requirement->deleteAction = "删除{$lang->URCommon}"; $lang->requirement->exportAction = "导出{$lang->URCommon}"; $lang->requirement->reportAction = "统计报表"; -$lang->requirement->recall = '撤销评审'; +$lang->requirement->recall = $lang->story->recallAction; $lang->requirement->batchReview = '批量评审'; $lang->requirement->batchEdit = "批量编辑"; $lang->requirement->batchClose = '批量关闭'; @@ -475,3 +490,5 @@ $lang->requirement->linkRequirementsAB = "关联相关{$lang->URCommon}"; $lang->requirement->batchChangeBranch = "批量修改分支"; $lang->requirement->batchAssignTo = "批量指派"; $lang->requirement->batchChangeModule = "批量修改模块"; +$lang->requirement->submitReview = $lang->story->submitReview; +$lang->requirement->linkStory = "关联{$lang->SRCommon}"; diff --git a/module/story/lang/zh-tw.php b/module/story/lang/zh-tw.php index 919f53a87a..ca0a846413 100644 --- a/module/story/lang/zh-tw.php +++ b/module/story/lang/zh-tw.php @@ -173,11 +173,12 @@ $lang->story->needNotReviewList[1] = '不需要評審'; $lang->story->useList[0] = '不使用'; $lang->story->useList[1] = '使用'; -$lang->story->statusList[''] = ''; -$lang->story->statusList['draft'] = '草稿'; -$lang->story->statusList['active'] = '激活'; -$lang->story->statusList['closed'] = '已關閉'; -$lang->story->statusList['changed'] = '已變更'; +$lang->story->statusList[''] = ''; +$lang->story->statusList['draft'] = '草稿'; +$lang->story->statusList['reviewing'] = '评审中'; +$lang->story->statusList['active'] = '激活'; +$lang->story->statusList['closed'] = '已關閉'; +$lang->story->statusList['changing'] = '變更中'; $lang->story->stageList[''] = ''; $lang->story->stageList['wait'] = '未開始'; diff --git a/module/story/model.php b/module/story/model.php index 08b5aee805..57159dbed8 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -86,17 +86,18 @@ class storyModel extends model * * @param int|array|string $storyIdList * @param string $type requirement|story + * @param string $mode all * @access public * @return array */ - public function getByList($storyIdList = 0, $type = 'story') + public function getByList($storyIdList = 0, $type = 'story', $mode = '') { - return $this->dao->select('t1.*, t2.spec, t2.verify, t3.name as productTitle') + return $this->dao->select('t1.*, t2.spec, t2.verify, t3.name as productTitle, t3.deleted as productDeleted') ->from(TABLE_STORY)->alias('t1') ->leftJoin(TABLE_STORYSPEC)->alias('t2')->on('t1.id=t2.story') ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t1.product=t3.id') - ->where('t1.deleted')->eq(0) - ->andWhere('t1.version=t2.version') + ->where('t1.version=t2.version') + ->beginIF($mode != 'all')->andWhere('t1.deleted')->eq(0)->fi() ->beginIF($storyIdList)->andWhere('t1.id')->in($storyIdList)->fi() ->beginIF(!$storyIdList)->andWhere('t1.type')->eq($type)->fi() ->fetchAll('id'); @@ -202,7 +203,7 @@ class storyModel extends model if(isset($_POST['reviewer'])) $_POST['reviewer'] = array_filter($_POST['reviewer']); if(!$this->post->needNotReview and empty($_POST['reviewer'])) { - dao::$errors[] = $this->lang->story->errorEmptyReviewedBy; + dao::$errors['reviewer'] = $this->lang->story->errorEmptyReviewedBy; return false; } @@ -211,11 +212,9 @@ class storyModel extends model ->cleanInt('product,module,pri,plan') ->callFunc('title', 'trim') ->add('version', 1) - ->add('status', 'draft') ->setDefault('plan,verify,notifyEmail', '') ->setDefault('openedBy', $this->app->user->account) ->setDefault('openedDate', $now) - ->setIF($this->post->needNotReview, 'status', 'active') ->setIF($this->post->plan > 0, 'stage', 'planned') ->setIF($this->post->estimate, 'estimate', (float)$this->post->estimate) ->setIF(!in_array($this->post->source, $this->config->story->feedbackSource), 'feedbackBy', '') @@ -232,8 +231,8 @@ class storyModel extends model $result = $this->loadModel('common')->removeDuplicate('story', $story, "product={$story->product}"); if(isset($result['stop']) and $result['stop']) return array('status' => 'exists', 'id' => $result['duplicate']); - if($this->checkForceReview()) $story->status = 'draft'; - if($story->status == 'draft') $story->stage = $this->post->plan > 0 ? 'planned' : 'wait'; + if($story->status != 'draft' and $this->checkForceReview()) $story->status = 'reviewing'; + if(strpos('draft,reviewing', $story->status) !== false) $story->stage = $this->post->plan > 0 ? 'planned' : 'wait'; $story = $this->loadModel('file')->processImgURL($story, $this->config->story->editor->create['id'], $this->post->uid); $requiredFields = "," . $this->config->story->create->requiredFields . ","; @@ -285,7 +284,6 @@ class storyModel extends model /* Save the story reviewer to storyreview table. */ if(isset($_POST['reviewer'])) { - $assignedTo = ''; foreach($this->post->reviewer as $reviewer) { if(empty($reviewer)) continue; @@ -295,10 +293,7 @@ class storyModel extends model $reviewData->version = 1; $reviewData->reviewer = $reviewer; $this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec(); - - if(empty($assignedTo)) $assignedTo = $reviewer; } - if($assignedTo) $this->dao->update(TABLE_STORY)->set('assignedTo')->eq($assignedTo)->set('assignedDate')->eq(helper::now())->where('id')->eq($storyID)->exec(); } /* Project or execution linked story. */ @@ -469,6 +464,13 @@ class storyModel extends model $mails = array(); $stories = fixer::input('post')->get(); + $saveDraft = false; + if(isset($stories->status)) + { + if($stories->status == 'draft') $saveDraft = true; + unset($stories->status); + } + $result = $this->loadModel('common')->removeDuplicate('story', $stories, "product={$productID}"); $stories = $result['data']; @@ -510,7 +512,7 @@ class storyModel extends model $story->category = $stories->category[$i]; $story->pri = $stories->pri[$i]; $story->estimate = $stories->estimate[$i]; - $story->status = (empty($stories->reviewer[$i]) and !$forceReview) ? 'active' : 'draft'; + $story->status = $saveDraft ? 'draft' : ((empty($stories->reviewer[$i]) and !$forceReview) ? 'active' : 'reviewing'); $story->stage = ($this->app->tab == 'project' or $this->app->tab == 'execution') ? 'projected' : 'wait'; $story->keywords = $stories->keywords[$i]; $story->sourceNote = $stories->sourceNote[$i]; @@ -606,7 +608,6 @@ class storyModel extends model $this->dao->insert(TABLE_STORYSPEC)->data($specData)->exec(); /* Save the story reviewer to storyreview table. */ - $assignedTo = ''; foreach($_POST['reviewer'][$i] as $reviewer) { if(empty($reviewer)) continue; @@ -616,10 +617,7 @@ class storyModel extends model $reviewData->version = 1; $reviewData->reviewer = $reviewer; $this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec(); - - if(empty($assignedTo)) $assignedTo = $reviewer; } - if($assignedTo) $this->dao->update(TABLE_STORY)->set('assignedTo')->eq($assignedTo)->set('assignedDate')->eq($now)->where('id')->eq($storyID)->exec(); $this->executeHooks($storyID); @@ -695,10 +693,7 @@ class storyModel extends model ->setDefault('lastEditedBy', $this->app->user->account) ->add('id', $storyID) ->add('lastEditedDate', $now) - ->setIF(!$this->post->assignedTo, 'assignedTo', '') ->setIF($specChanged, 'version', $oldStory->version + 1) - ->setIF($specChanged and $oldStory->status == 'active' and $this->post->needNotReview == false, 'status', 'changed') - ->setIF($oldStory->status == 'draft' and $this->post->needNotReview, 'status', 'active') ->setIF($specChanged, 'reviewedBy', '') ->setIF($specChanged, 'changedBy', $this->app->user->account) ->setIF($specChanged, 'changedDate', $now) @@ -706,10 +701,11 @@ class storyModel extends model ->setIF($specChanged, 'closedReason', '') ->setIF($specChanged and $oldStory->reviewedBy, 'reviewedDate', '0000-00-00') ->setIF($specChanged and $oldStory->closedBy, 'closedDate', '0000-00-00') + ->setIF(!$specChanged, 'status', $oldStory->status) ->stripTags($this->config->story->editor->change['id'], $this->config->allowedTags) ->remove('files,labels,reviewer,comment,needNotReview,uid') ->get(); - if($specChanged and isset($story->status) && $story->status == 'active' and $this->checkForceReview()) $story->status = 'changed'; + $story = $this->loadModel('file')->processImgURL($story, $this->config->story->editor->change['id'], $this->post->uid); $this->dao->update(TABLE_STORY)->data($story, 'spec,verify') ->autoCheck() @@ -750,7 +746,6 @@ class storyModel extends model } /* Update the reviewer. */ - $assignedTo = ''; foreach($_POST['reviewer'] as $reviewer) { $reviewData = new stdclass(); @@ -758,16 +753,16 @@ class storyModel extends model $reviewData->version = $story->version; $reviewData->reviewer = $reviewer; $this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec(); - - if(empty($assignedTo)) $assignedTo = $reviewer; } - if($assignedTo and $assignedTo != $oldStory->assignedTo) $this->dao->update(TABLE_STORY)->set('assignedTo')->eq($assignedTo)->set('assignedDate')->eq(helper::now())->where('id')->eq($storyID)->exec(); + + if($reviewerHasChanged) + { + $oldStory->reviewers = implode(',', array_keys($oldStoryReviewers)); + $story->reviewers = implode(',', $_POST['reviewer']); + } } $this->file->updateObjectID($this->post->uid, $storyID, 'story'); - - $oldStory->reviewers = implode(',', array_keys($oldStoryReviewers)); - $story->reviewers = implode(',', $_POST['reviewer']); return common::createChanges($oldStory, $story); } } @@ -789,17 +784,30 @@ class storyModel extends model return false; } + if(strpos('draft,changing', $oldStory->status) !== false and $this->checkForceReview() and empty($_POST['reviewer'])) + { + dao::$errors[] = $this->lang->story->errorEmptyReviewedBy; + return false; + } + + $oldSpec = $this->dao->select('title,spec,verify')->from(TABLE_STORYSPEC)->where('story')->eq((int)$storyID)->andWhere('version')->eq($oldStory->version)->fetch(); + $oldStory->title = isset($oldSpec->title) ? $oldSpec->title : ''; + $oldStory->spec = isset($oldSpec->spec) ? $oldSpec->spec : ''; + $oldStory->verify = isset($oldSpec->verify) ? $oldSpec->verify : ''; + $story = fixer::input('post') ->cleanInt('product,module,pri,duplicateStory') ->cleanFloat('estimate') ->setDefault('assignedDate', $oldStory->assignedDate) ->setDefault('lastEditedBy', $this->app->user->account) ->setDefault('reviewedBy', $oldStory->reviewedBy) + ->setDefault('title', $oldStory->title) + ->setDefault('spec', $oldStory->spec) + ->setDefault('verify', $oldStory->verify) ->setDefault('mailto', '') ->add('id', $storyID) ->add('lastEditedDate', $now) ->setDefault('plan,notifyEmail', '') - ->setDefault('status', $oldStory->status) ->setDefault('product', $oldStory->product) ->setDefault('branch', $oldStory->branch) ->setIF(!$this->post->linkStories, 'linkStories', '') @@ -812,16 +820,16 @@ class storyModel extends model ->setIF(!in_array($this->post->source, $this->config->story->feedbackSource), 'notifyEmail', '') ->setIF(!empty($_POST['plan'][0]) and $oldStory->stage == 'wait', 'stage', 'planned') ->stripTags($this->config->story->editor->edit['id'], $this->config->allowedTags) - ->join('reviewedBy', ',') ->join('mailto', ',') ->join('linkStories', ',') ->join('linkRequirements', ',') ->join('childStories', ',') - ->remove('files,labels,comment,contactListMenu,stages,reviewer') + ->remove('files,labels,comment,contactListMenu,stages,reviewer,needNotReview') ->get(); if($oldStory->type == 'story' and !isset($story->linkStories)) $story->linkStories = ''; if($oldStory->type == 'requirement' and !isset($story->linkRequirements)) $story->linkRequirements = ''; + if($oldStory->status == 'changing' and $story->status == 'draft') $story->status = 'changing'; if(isset($story->plan) and is_array($story->plan)) $story->plan = trim(join(',', $story->plan), ','); if(isset($_POST['branch']) and $_POST['branch'] == 0) $story->branch = 0; @@ -858,9 +866,9 @@ class storyModel extends model if(isset($story->stage) and $oldStory->stage != $story->stage) $story->stagedBy = (strpos('tested|verified|released|closed', $story->stage) !== false) ? $this->app->user->account : ''; $story = $this->loadModel('file')->processImgURL($story, $this->config->story->editor->edit['id'], $this->post->uid); - if(isset($_POST['reviewer'])) + if(isset($_POST['reviewer']) or isset($_POST['needNotReview'])) { - $_POST['reviewer'] = array_filter($_POST['reviewer']); + $_POST['reviewer'] = isset($_POST['needNotReview']) ? array() : array_filter($_POST['reviewer']); $oldReviewer = $this->getReviewerPairs($storyID, $oldStory->version); if(array_diff($_POST['reviewer'], array_keys($oldReviewer)) or array_diff(array_keys($oldReviewer), $_POST['reviewer'])) { @@ -877,8 +885,11 @@ class storyModel extends model $this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec(); } - $story->reviewedBy = $oldStory->reviewedBy; - $story = $this->updateStoryByReview($storyID, $oldStory, $story); + if($story->status == 'reviewing') + { + $story->reviewedBy = $oldStory->reviewedBy; + $story = $this->updateStoryByReview($storyID, $oldStory, $story); + } } $oldStory->reviewers = implode(',', array_keys($oldReviewer)); @@ -886,7 +897,7 @@ class storyModel extends model } $this->dao->update(TABLE_STORY) - ->data($story, 'reviewers') + ->data($story, 'reviewers,spec,verify') ->autoCheck() ->checkIF(isset($story->closedBy), 'closedReason', 'notempty') ->checkIF(isset($story->closedReason) and $story->closedReason == 'done', 'stage', 'notempty') @@ -897,6 +908,15 @@ class storyModel extends model if(!dao::isError()) { + if($story->spec != $oldStory->spec or $story->verify != $oldStory->verify or $story->title != $oldStory->title) + { + $data = new stdclass(); + $data->title = $story->title; + $data->spec = $story->spec; + $data->verify = $story->verify; + $this->dao->update(TABLE_STORYSPEC)->data($data)->where('story')->eq((int)$storyID)->andWhere('version')->eq($oldStory->version)->exec(); + } + if($story->product != $oldStory->product) { $this->updateStoryProduct($storyID, $story->product); @@ -1063,10 +1083,10 @@ class storyModel extends model if(empty($childrenStatus)) return $this->dao->update(TABLE_STORY)->set('parent')->eq('0')->where('id')->eq($parentID)->exec(); $status = $oldParentStory->status; - if(count($childrenStatus) == 1 and $oldParentStory->status != 'changed') + if(count($childrenStatus) == 1 and $oldParentStory->status != 'changing') { $status = current($childrenStatus); - if($status == 'draft' or $status == 'changed') $status = 'active'; + if($status == 'draft' or $status == 'changing') $status = 'active'; } elseif(count($childrenStatus) != 1 and $oldParentStory->status == 'closed') { @@ -1298,7 +1318,7 @@ class storyModel extends model $story->version = $story->title == $oldStory->title ? $oldStory->version : $oldStory->version + 1; if($story->stage != $oldStory->stage) $story->stagedBy = (strpos('tested|verified|released|closed', $story->stage) !== false) ? $this->app->user->account : ''; - if($story->title != $oldStory->title and $story->status != 'draft') $story->status = 'changed'; + if($story->title != $oldStory->title and $story->status != 'draft') $story->status = 'changing'; if($story->closedBy != false and $oldStory->closedDate == '') $story->closedDate = $now; if($story->closedReason != false and $oldStory->closedDate == '') $story->closedDate = $now; if($story->closedBy != false or $story->closedReason != false) $story->status = 'closed'; @@ -1388,8 +1408,6 @@ class storyModel extends model */ public function review($storyID) { - if($this->post->result == 'revert' and $this->post->preVersion == false) return print(js::alert($this->lang->story->mustChoosePreVersion)); - if(strpos($this->config->story->review->requiredFields, 'comment') !== false and !$this->post->comment) { dao::$errors[] = sprintf($this->lang->error->notempty, $this->lang->comment); @@ -1412,15 +1430,16 @@ class storyModel extends model ->setDefault('reviewedDate', $date) ->stripTags($this->config->story->editor->review['id'], $this->config->allowedTags) ->setIF(!$this->post->assignedTo, 'assignedTo', '') - ->setIF($this->post->result == 'revert', 'version', $this->post->preVersion) - ->setIF($this->post->result == 'clarify', 'assignedTo', $oldStory->lastEditedBy ? $oldStory->lastEditedBy : $oldStory->openedBy) + ->setIF($this->post->result == 'revert', 'version', $oldStory->version - 1) ->removeIF($this->post->result != 'reject', 'closedReason, duplicateStory, childStories') ->removeIF($this->post->result == 'reject' and $this->post->closedReason != 'duplicate', 'duplicateStory') ->removeIF($this->post->result == 'reject' and $this->post->closedReason != 'subdivided', 'childStories') ->add('reviewedBy', $oldStory->reviewedBy . ',' . $this->app->user->account) ->add('id', $storyID) - ->remove('result,preVersion,comment') + ->remove('result,comment') ->get(); + + $story->reviewedBy = implode(',', array_unique(explode(',', $story->reviewedBy))); $story = $this->loadModel('file')->processImgURL($story, $this->config->story->editor->review['id'], $this->post->uid); /* Fix bug #671. */ @@ -1447,7 +1466,7 @@ class storyModel extends model ->where('id')->eq($storyID)->exec(); if($this->post->result == 'revert') { - $preTitle = $this->dao->select('title')->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWHere('version')->eq($this->post->preVersion)->fetch('title'); + $preTitle = $this->dao->select('title')->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWHere('version')->eq($oldStory->version - 1)->fetch('title'); $this->dao->update(TABLE_STORY)->set('title')->eq($preTitle)->where('id')->eq($storyID)->exec(); /* Delete versions that is after this version. */ @@ -1488,10 +1507,11 @@ class storyModel extends model foreach($storyIdList as $storyID) { if(!$storyID) continue; - $oldStory = $oldStories[$storyID]; - $isSuperReviewer = strpos(',' . trim(zget($this->config->story, 'superReviewers', ''), ',') . ',', ',' . $this->app->user->account . ','); - if($oldStory->status != 'draft' and $oldStory->status != 'changed') continue; + $isSuperReviewer = strpos(',' . trim(zget($this->config->story, 'superReviewers', ''), ',') . ',', ',' . $this->app->user->account . ','); + $oldStory = $oldStories[$storyID]; + + if($oldStory->status != 'reviewing') continue; if(!in_array($this->app->user->account, array_keys($reviewerList[$storyID])) and $isSuperReviewer === false) continue; if(isset($hasResult[$storyID]) and $hasResult[$storyID]->version == $oldStories[$storyID]->version) continue; @@ -1547,13 +1567,88 @@ class storyModel extends model * @access public * @return void */ - public function recall($storyID) + public function recallReview($storyID) { - $story = $this->getById($storyID); - $this->dao->update(TABLE_STORY)->set('status')->eq('draft')->where('id')->eq($storyID)->exec(); + $story = $this->getById($storyID); + $isChanged = $story->changedBy ? true : false; + $status = $isChanged ? 'changing' : 'draft'; + $this->dao->update(TABLE_STORY)->set('status')->eq($status)->where('id')->eq($storyID)->exec(); $this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->andWhere('version')->eq($story->version)->exec(); } + /** + * Recall the story change. + * + * @param int $storyID + * @access public + * @return void + */ + public function recallChange($storyID) + { + $story = $this->getById($storyID); + $preVersion = $story->version - 1; + + /* Update story title and version and status. */ + $preTitle = $this->dao->select('title')->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWHere('version')->eq($preVersion)->fetch('title'); + $this->dao->update(TABLE_STORY)->set('title')->eq($preTitle)->set('version')->eq($preVersion)->set('status')->eq('active')->where('id')->eq($storyID)->exec(); + + /* Delete versions that is after this version. */ + $this->dao->delete()->from(TABLE_STORYSPEC)->where('story')->eq($storyID)->andWHere('version')->eq($story->version)->exec(); + $this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->andWhere('version')->eq($story->version)->exec(); + + $this->dao->delete()->from(TABLE_FILE)->where('objectType')->eq('story')->andWhere('objectID')->eq($storyID)->andWhere('extra')->eq($story->version)->exec(); + } + + /** + * Submit review. + * + * @param int $storyID + * @access public + * @return array|bool + */ + public function submitReview($storyID) + { + if(isset($_POST['reviewer'])) $_POST['reviewer'] = array_filter($_POST['reviewer']); + if(!$this->post->needNotReview and empty($_POST['reviewer'])) + { + dao::$errors[] = $this->lang->story->errorEmptyReviewedBy; + return false; + } + + $oldStory = $this->dao->findById($storyID)->from(TABLE_STORY)->fetch(); + $reviewerList = $this->getReviewerPairs($oldStory->id, $oldStory->version); + $oldStory->reviewer = implode(',', array_keys($reviewerList)); + + $story = fixer::input('post') + ->setDefault('status', 'active') + ->setDefault('reviewer', '') + ->remove('needNotReview') + ->join('reviewer', ',') + ->get(); + + $this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->andWhere('version')->eq($oldStory->version)->exec(); + + if(isset($_POST['reviewer'])) + { + foreach($this->post->reviewer as $reviewer) + { + if(empty($reviewer)) continue; + + $reviewData = new stdclass(); + $reviewData->story = $storyID; + $reviewData->version = $oldStory->version; + $reviewData->reviewer = $reviewer; + $this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec(); + } + $story->status = 'reviewing'; + } + + $this->dao->update(TABLE_STORY)->set('status')->eq($story->status)->where('id')->eq($storyID)->exec(); + if(!dao::isError()) return common::createChanges($oldStory, $story); + + return false; + } + /** * Subdivide story * @@ -1649,6 +1744,7 @@ class storyModel extends model ->setDefault('closedDate', $now) ->setDefault('closedBy', $this->app->user->account) ->setDefault('assignedDate', $now) + ->setDefault('duplicateStory', 0) ->stripTags($this->config->story->editor->close['id'], $this->config->allowedTags) ->removeIF($this->post->closedReason != 'duplicate', 'duplicateStory') ->removeIF($this->post->closedReason != 'subdivided', 'childStories') @@ -2262,10 +2358,14 @@ class storyModel extends model ->stripTags($this->config->story->editor->activate['id'], $this->config->allowedTags) ->remove('comment') ->get(); + + /* Get status after activation. */ + $story->status = $this->getActivateStatus($storyID); + $story = $this->loadModel('file')->processImgURL($story, $this->config->story->editor->activate['id'], $this->post->uid); $this->dao->update(TABLE_STORY)->data($story)->autoCheck()->checkFlow()->where('id')->eq($storyID)->exec(); - if($this->post->status == 'active') $this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->exec(); + if($story->status == 'active') $this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->exec(); $this->setStage($storyID); @@ -2601,7 +2701,7 @@ class storyModel extends model if(empty($normalProducts) and empty($branchProducts)) $productQuery .= '1 = 1'; $productQuery .= ') '; - $stories = $this->dao->select('*')->from(TABLE_STORY) + $stories = $this->dao->select("*, IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder")->from(TABLE_STORY) ->where('product')->in($productID) ->andWhere($productQuery) ->beginIF(!$hasParent)->andWhere("parent")->ge(0)->fi() @@ -2815,7 +2915,7 @@ class storyModel extends model $actionIDList = array(); if($fieldName == 'assignedBy') $actionIDList = $this->dao->select('objectID')->from(TABLE_ACTION)->where('objectType')->eq('story')->andWhere('action')->eq('assigned')->andWhere('actor')->eq($fieldValue)->fetchPairs('objectID', 'objectID'); - $sql = $this->dao->select('t1.*')->from(TABLE_STORY)->alias('t1'); + $sql = $this->dao->select("t1.*, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder")->from(TABLE_STORY)->alias('t1'); if($fieldName == 'reviewBy') $sql = $sql->leftJoin(TABLE_STORYREVIEW)->alias('t2')->on('t1.id = t2.story and t1.version = t2.version'); $stories = $sql->where('t1.product')->in($productID) @@ -2828,7 +2928,7 @@ class storyModel extends model ->beginIF($fieldName == 'reviewBy') ->andWhere('t2.reviewer')->eq($this->app->user->account) ->andWhere('t2.result')->eq('') - ->andWhere('t1.status')->in('draft,changed') + ->andWhere('t1.status')->eq('reviewing') ->fi() ->beginIF($fieldName == 'assignedBy')->andWhere('t1.id')->in($actionIDList)->andWhere('t1.status')->ne('closed')->fi() ->orderBy($orderBy) @@ -2851,7 +2951,7 @@ class storyModel extends model */ public function get2BeClosed($productID, $branch, $modules, $type = 'story', $orderBy = '', $pager = null) { - $stories = $this->dao->select('*')->from(TABLE_STORY) + $stories = $this->dao->select("*,IF(`pri` = 0, {$this->config->maxPriValue}, `pri`) as priOrder")->from(TABLE_STORY) ->where('product')->in($productID) ->andWhere('type')->eq($type) ->beginIF($branch)->andWhere("branch")->eq($branch)->fi() @@ -2970,6 +3070,7 @@ class storyModel extends model } $storyQuery = preg_replace("/`plan` +LIKE +'%([0-9]+)%'/i", "CONCAT(',', `plan`, ',') LIKE '%,$1,%'", $storyQuery); + return $this->getBySQL($queryProductID, $storyQuery, $orderBy, $pager, $type); } @@ -3027,7 +3128,7 @@ class storyModel extends model } } - $tmpStories = $this->dao->select('DISTINCT t1.*')->from(TABLE_STORY)->alias('t1') + $tmpStories = $this->dao->select("DISTINCT t1.*, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder")->from(TABLE_STORY)->alias('t1') ->leftJoin(TABLE_PROJECTSTORY)->alias('t2')->on('t1.id=t2.story') ->beginIF(strpos($sql, 'result') !== false)->leftJoin(TABLE_STORYREVIEW)->alias('t3')->on('t1.id = t3.story and t1.version = t3.version')->fi() ->where($sql) @@ -3127,7 +3228,7 @@ class storyModel extends model } } - $stories = $this->dao->select('distinct t1.*, t2.*, t3.type as productType, t2.version as version')->from(TABLE_PROJECTSTORY)->alias('t1') + $stories = $this->dao->select("distinct t1.*, t2.*, IF(t2.`pri` = 0, {$this->config->maxPriValue}, t2.`pri`) as priOrder, t3.type as productType, t2.version as version")->from(TABLE_PROJECTSTORY)->alias('t1') ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t2.product = t3.id') ->beginIF(strpos($storyQuery, 'result') !== false)->leftJoin(TABLE_STORYREVIEW)->alias('t4')->on('t2.id = t4.story and t2.version = t4.version')->fi() @@ -3168,7 +3269,7 @@ class storyModel extends model $type = (strpos('bymodule|byproduct', $type) !== false and $this->session->storyBrowseType) ? $this->session->storyBrowseType : $type; - $stories = $this->dao->select('distinct t1.*, t2.*,t3.type as productType,t2.version as version')->from(TABLE_PROJECTSTORY)->alias('t1') + $stories = $this->dao->select("distinct t1.*, t2.*, IF(t2.`pri` = 0, {$this->config->maxPriValue}, t2.`pri`) as priOrder, t3.type as productType, t2.version as version")->from(TABLE_PROJECTSTORY)->alias('t1') ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') ->leftJoin(TABLE_PRODUCT)->alias('t3')->on('t2.product = t3.id') ->where('t1.project')->eq((int)$executionID) @@ -3177,16 +3278,16 @@ class storyModel extends model ->beginIF($execution->type == 'project') ->beginIF(!empty($productID))->andWhere('t1.product')->eq($productID) ->beginIF($type == 'bybranch' and $branchParam !== '')->andWhere('t2.branch')->in("0,$branchParam")->fi() - ->beginIF(strpos('changed|closed', $type) !== false)->andWhere('t2.status')->eq($type)->fi() + ->beginIF(strpos('draft|reviewing|changing|closed', $type) !== false)->andWhere('t2.status')->eq($type)->fi() ->beginIF($type == 'unclosed')->andWhere('t2.status')->in(array_keys($unclosedStatus))->fi() ->beginIF($type == 'linkedexecution')->andWhere('t2.id')->in($storyIdList)->fi() ->beginIF($type == 'unlinkedexecution')->andWhere('t2.id')->notIn($storyIdList)->fi() ->fi() ->beginIF($execution->type != 'project') ->beginIF(!empty($productParam))->andWhere('t1.product')->eq($productParam)->fi() - ->beginIF($this->session->executionStoryBrowseType and strpos('changed|', $this->session->executionStoryBrowseType) !== false)->andWhere('t2.status')->in(array_keys($unclosedStatus))->fi() + ->beginIF($this->session->executionStoryBrowseType and strpos('changing|', $this->session->executionStoryBrowseType) !== false)->andWhere('t2.status')->in(array_keys($unclosedStatus))->fi() ->fi() - ->beginIF($this->session->storyBrowseType and strpos('changed|', $this->session->storyBrowseType) !== false)->andWhere('t2.status')->in(array_keys($unclosedStatus))->fi() + ->beginIF($this->session->storyBrowseType and strpos('changing|', $this->session->storyBrowseType) !== false)->andWhere('t2.status')->in(array_keys($unclosedStatus))->fi() ->beginIF($modules)->andWhere('t2.module')->in($modules)->fi() ->andWhere('t2.deleted')->eq(0) ->andWhere('t3.deleted')->eq(0) @@ -3249,7 +3350,7 @@ class storyModel extends model ->beginIF($branch !== 'all')->andWhere('t2.branch')->in("0,$branch")->fi() ->beginIF($moduleIdList)->andWhere('t2.module')->in($moduleIdList)->fi() ->beginIF($status == 'unclosed')->andWhere('t2.status')->ne('closed')->fi() - ->beginIF($status == 'review')->andWhere('t2.status')->in('draft,changed')->fi() + ->beginIF($status == 'review')->andWhere('t2.status')->in('draft,changing')->fi() ->beginIF($status == 'active')->andWhere('t2.status')->eq('active')->fi() ->orderBy('t1.`order` desc, t1.`story` desc') ->fetchAll('id'); @@ -3283,7 +3384,7 @@ class storyModel extends model } else { - $stories = $this->dao->select('distinct t1.story, t1.plan, t1.order, t2.*') + $stories = $this->dao->select("distinct t1.story, t1.plan, t1.order, t2.*, IF(t2.`pri` = 0, {$this->config->maxPriValue}, t2.`pri`) as priOrder") ->from(TABLE_PLANSTORY)->alias('t1') ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id') ->where('t1.plan')->eq($planID) @@ -3390,7 +3491,7 @@ class storyModel extends model */ public function getUserStories($account, $type = 'assignedTo', $orderBy = 'id_desc', $pager = null, $storyType = 'story', $includeLibStories = true) { - $sql = $this->dao->select('t1.*, t2.name as productTitle')->from(TABLE_STORY)->alias('t1') + $sql = $this->dao->select("t1.*, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder, t2.name as productTitle")->from(TABLE_STORY)->alias('t1') ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id'); if($type == 'reviewBy') $sql = $sql->leftJoin(TABLE_STORYREVIEW)->alias('t3')->on('t1.id = t3.story and t1.version = t3.version'); @@ -3401,7 +3502,7 @@ class storyModel extends model ->beginIF($type != 'closedBy' and $this->app->moduleName == 'block')->andWhere('t1.status')->ne('closed')->fi() ->beginIF($type != 'all') ->beginIF($type == 'assignedTo')->andWhere('t1.assignedTo')->eq($account)->fi() - ->beginIF($type == 'reviewBy')->andWhere('t3.reviewer')->eq($account)->andWhere('t3.result')->eq('')->andWhere('t1.status')->in('draft,changed')->fi() + ->beginIF($type == 'reviewBy')->andWhere('t3.reviewer')->eq($account)->andWhere('t3.result')->eq('')->andWhere('t1.status')->in('reviewing,changing')->fi() ->beginIF($type == 'openedBy')->andWhere('t1.openedBy')->eq($account)->fi() ->beginIF($type == 'reviewedBy')->andWhere("CONCAT(',', t1.reviewedBy, ',')")->like("%,$account,%")->fi() ->beginIF($type == 'closedBy')->andWhere('t1.closedBy')->eq($account)->fi() @@ -4073,15 +4174,15 @@ class storyModel extends model $isSuperReviewer = strpos(',' . trim(zget($config->story, 'superReviewers', ''), ',') . ',', ',' . $app->user->account . ','); - if($action == 'change') return ($isSuperReviewer !== false or count($story->reviewer) == 0 or count($story->notReview) == 0) and $story->status != 'closed'; - if($action == 'review') return (($isSuperReviewer !== false or in_array($app->user->account, $story->notReview)) and ($story->status == 'draft' or $story->status == 'changed')); - if($action == 'recall') return empty($story->reviewedBy) and strpos('draft,changed', $story->status) !== false and !empty($story->reviewer) and ($app->user->account == $story->openedBy); + if($action == 'change') return (($isSuperReviewer !== false or count($story->reviewer) == 0 or count($story->notReview) == 0) and $story->status == 'active'); + if($action == 'review') return (($isSuperReviewer !== false or in_array($app->user->account, $story->notReview)) and $story->status == 'reviewing'); + if($action == 'recall') return strpos('reviewing,changing', $story->status) !== false; if($action == 'close') return $story->status != 'closed'; if($action == 'activate') return $story->status == 'closed'; if($action == 'assignto') return $story->status != 'closed'; if($action == 'createcase') return $story->type != 'requirement'; if($action == 'batchcreate' and $story->parent > 0) return false; - if($action == 'batchcreate' and $story->type == 'requirement' and $story->status != 'closed') return $story->status != 'draft'; + if($action == 'batchcreate' and $story->type == 'requirement' and $story->status != 'closed') return strpos('draft,reviewing,changing', $story->status) === false; if($action == 'batchcreate' and $config->vision == 'lite' and ($story->status == 'active' and ($story->stage == 'wait' or $story->stage == 'projected'))) return true; if($action == 'batchcreate' and ($story->status != 'active' or $story->stage != 'wait' or !empty($story->plan))) return false; @@ -4109,44 +4210,54 @@ class storyModel extends model if($story->URChanged) return $this->buildMenu('story', 'processStoryChange', $params, $story, $type, 'ok', '', 'iframe', true, '', $this->lang->confirm); $isClick = $this->isClickable($story, 'change'); - $title = (!$isClick and $story->status != 'closed') ? $this->lang->story->changeTip : ''; + $title = (!$isClick and $story->status != 'closed' and $story->status != 'draft') ? $this->lang->story->changeTip : ''; $menu .= $this->buildMenu('story', 'change', $params . "&from=$story->from&storyType=$story->type", $story, $type, 'alter', '', 'showinonlybody', false, '', $title); - $isClick = $this->isClickable($story, 'review'); - $title = $this->lang->story->review; - if(!$isClick and $story->status != 'closed') + if(strpos('draft,changing', $story->status) !== false) { - if($story->status == 'active') - { - $title = $this->lang->story->reviewTip['active']; - } - elseif($storyReviewer and in_array($this->app->user->account, $storyReviewer)) - { - $title = $this->lang->story->reviewTip['reviewed']; - } - elseif($storyReviewer and !in_array($this->app->user->account, $storyReviewer)) - { - $title = $this->lang->story->reviewTip['notReviewer']; - } - elseif(empty($storyReviewer)) - { - $title = $this->lang->story->reviewTip['recalled']; - } + $menu .= $this->buildMenu('story', 'submitReview', "storyID=$story->id&storyType=$story->type", $story, $type, 'confirm', '', 'iframe', true, "data-width='50%'"); } - $menu .= $this->buildMenu('story', 'review', $params . "&from=$story->from&storyType=$story->type", $story, $type, 'search', '', 'showinonlybody', false, '', $title); - $title = $this->lang->story->recall; + else + { + $isClick = $this->isClickable($story, 'review'); + $title = $this->lang->story->review; + if(!$isClick and $story->status != 'closed') + { + if($story->status == 'active') + { + $title = $this->lang->story->reviewTip['active']; + } + elseif($storyReviewer and in_array($this->app->user->account, $storyReviewer)) + { + $title = $this->lang->story->reviewTip['reviewed']; + } + elseif($storyReviewer and !in_array($this->app->user->account, $storyReviewer)) + { + $title = $this->lang->story->reviewTip['notReviewer']; + } + elseif(empty($storyReviewer)) + { + $title = $this->lang->story->reviewTip['recalled']; + } + } + $menu .= $this->buildMenu('story', 'review', $params . "&from=$story->from&storyType=$story->type", $story, $type, 'search', '', 'showinonlybody', false, '', $title); + } + $isClick = $this->isClickable($story, 'recall'); + $title = $story->status == 'changing' ? $this->lang->story->recallChange : $this->lang->story->recall; if(!$isClick and $story->status != 'closed') { if($story->status == 'draft' and empty($storyReviewer)) $title = $this->lang->story->recallTip['recalled']; if($story->status == 'draft' and !empty($storyReviewer)) $title = $this->lang->story->recallTip['reviewed']; - if(empty($story->reviewedBy) and strpos('draft,changed', $story->status) !== false and !empty($story->reviewer) and $this->app->user->account != $story->openedBy) $title = $this->lang->story->recallTip['notOpenedBy']; + if(empty($story->reviewedBy) and strpos('draft,changing', $story->status) !== false and !empty($story->reviewer) and $this->app->user->account != $story->openedBy) $title = $this->lang->story->recallTip['notOpenedBy']; if($story->status == 'active' and empty($story->reviewer)) $title = $this->lang->story->recallTip['actived']; } - $menu .= $this->buildMenu('story', 'recall', $params . "&from=list&storyType=$story->type", $story, $type, 'undo', 'hiddenwin', 'showinonlybody', '', '', $title); + + $menu .= $this->buildMenu('story', 'recall', $params . "&from=list&confirm=no&storyType=$story->type", $story, $type, 'undo', 'hiddenwin', 'showinonlybody', false, '', $title); $menu .= $this->buildMenu('story', 'close', $params . "&from=&storyType=$story->type", $story, $type, '', '', 'iframe', true); - $menu .= $this->buildMenu('story', 'edit', $params . "&from=$story->from&storyType=$story->type", $story, $type, '', '', 'showinonlybody'); + $menu .= $this->buildMenu('story', 'edit', $params . "&kanbanGroup=default&storyType=$story->type", $story, $type, '', '', 'showinonlybody'); + $tab = $this->app->tab == 'project' ? 'project' : 'qa'; if($story->type != 'requirement' and $this->config->vision != 'lite') $menu .= $this->buildMenu('story', 'createCase', "productID=$story->product&branch=$story->branch&module=0&from=¶m=0&$params", $story, $type, 'sitemap', '', 'showinonlybody', false, "data-app='$tab'"); @@ -4181,7 +4292,11 @@ class storyModel extends model if($type == 'view') { $menu .= $this->buildMenu('story', 'change', $params . "&from=&storyType=$story->type", $story, $type, 'alter', '', 'showinonlybody'); - $menu .= $this->buildMenu('story', 'recall', $params . "&from=view&storyType=$story->type", $story, $type, 'undo', '', 'showinonlybody'); + if(strpos('draft,changing', $story->status) !== false) $menu .= $this->buildMenu('story', 'submitReview', $params . "&storyType=$story->type", $story, $type, 'confirm', '', 'showinonlybody iframe', true, "data-width='50%'"); + + $title = $story->status == 'changing' ? $this->lang->story->recallChange : $this->lang->story->recall; + $menu .= $this->buildMenu('story', 'recall', $params . "&from=view&confirm=no&storyType=$story->type", $story, $type, 'undo', 'hiddenwin', 'showinonlybody', false, '', $title); + $menu .= $this->buildMenu('story', 'review', $params . "&from=product&storyType=$story->type", $story, $type, 'search', '', 'showinonlybody'); if(!isonlybody()) $menu .= $this->buildMenu('story', 'batchCreate', "productID=$story->product&branch=$story->branch&moduleID=$story->module&$params&executionID=0&plan=0&storyType=story", $story, $type, 'split', '', 'divideStory', true, "data-toggle='modal' data-type='iframe' data-width='95%'", $this->lang->story->subdivide); @@ -4241,17 +4356,25 @@ class storyModel extends model $story->reviewer = isset($story->reviewer) ? $story->reviewer : array(); $story->notReview = isset($story->notReview) ? $story->notReview : array(); - if(common::hasPriv('story', 'review')) + if(strpos('draft,changing', $story->status) !== false) { - $reviewDisabled = in_array($this->app->user->account, $story->notReview) and ($story->status == 'draft' or $story->status == 'changed') ? '' : 'disabled'; - $story->from = 'execution'; - $menu .= common::printIcon('story', 'review', "story={$story->id}&from=story", $story, 'list', 'search', '', $reviewDisabled, false, "data-group=execution"); + if(common::hasPriv('story', 'submitReview')) $menu .= common::printIcon('story', 'submitReview', "storyID=$story->id&from=story", $story, 'list', 'confirm', '', 'iframe', true, "data-width='50%'"); + } + else + { + if(common::hasPriv('story', 'review')) + { + $reviewDisabled = in_array($this->app->user->account, $story->notReview) and ($story->status == 'draft' or $story->status == 'changing') ? '' : 'disabled'; + $story->from = 'execution'; + $menu .= common::printIcon('story', 'review', "story={$story->id}&from=story", $story, 'list', 'search', '', $reviewDisabled, false, "data-group=execution"); + } } if(common::hasPriv('story', 'recall')) { - $recallDisabled = empty($story->reviewedBy) and strpos('draft,changed', $story->status) !== false and !empty($story->reviewer) ? '' : 'disabled'; - $menu .= common::printIcon('story', 'recall', "story={$story->id}", $story, 'list', 'undo', 'hiddenwin', $recallDisabled, '', '', $this->lang->story->recall); + $recallDisabled = empty($story->reviewedBy) and strpos('draft,changing', $story->status) !== false and !empty($story->reviewer) ? '' : 'disabled'; + $title = $story->status == 'changing' ? $this->lang->story->recallChange : $this->lang->story->recall; + $menu .= common::printIcon('story', 'recall', "story={$story->id}", $story, 'list', 'undo', 'hiddenwin', $recallDisabled, '', '', $title); } $this->lang->task->create = $this->lang->execution->wbs; @@ -4455,7 +4578,7 @@ class storyModel extends model $executionID = empty($execution) ? $this->session->execution : $execution->id; $account = $this->app->user->account; $storyLink = helper::createLink('story', 'view', "storyID=$story->id&version=0¶m=0&storyType=$story->type"); - $canView = common::hasPriv('story', 'view'); + $canView = common::hasPriv($story->type, 'view', null, "storyType=$story->type"); if($tab == 'project') { @@ -4495,10 +4618,14 @@ class storyModel extends model { $canBatchAction = ($canBeChanged and ($canBatchEdit or $canBatchClose or $canBatchChangeStage or $canBatchUnlink or $canBatchToTask)); } - else + elseif($tab == 'project') { $canBatchAction = ($canBatchEdit or $canBatchClose or $canBatchReview or $canBatchChangeStage or $canBatchChangeBranch or $canBatchChangeModule or $canBatchChangePlan or $canBatchAssignTo or $canBatchUnlinkStory); } + else + { + $canBatchAction = ($canBatchEdit or $canBatchClose or $canBatchReview or $canBatchChangeStage or $canBatchChangeBranch or $canBatchChangeModule or $canBatchChangePlan or $canBatchAssignTo); + } $id = $col->id; if($col->show) @@ -4587,7 +4714,8 @@ class storyModel extends model switch($id) { case 'id': - if($canBatchAction) echo html::checkbox('storyIdList', array($story->id => '')); + if($canBatchAction and ($storyType == 'story' or ($storyType == 'requirement' and $story->type == 'requirement'))) echo html::checkbox('storyIdList', array($story->id => '')); + if($canBatchAction and $storyType == 'requirement' and $story->type == 'story') echo ""; echo $canView ? html::a($storyLink, sprintf('%03d', $story->id), '', "data-app='$tab'") : sprintf('%03d', $story->id); break; case 'order': @@ -4612,7 +4740,7 @@ class storyModel extends model { $showBranch = isset($this->config->product->browse->showBranch) ? $this->config->product->browse->showBranch : 1; } - if($storyType == 'requirement') echo 'SR '; + if($storyType == 'requirement' and $story->type == 'story') echo 'SR '; if($story->parent > 0 and isset($story->parentName)) $story->title = "{$story->parentName} / {$story->title}"; if(isset($branches[$story->branch]) and $showBranch and $this->config->vision == 'rnd') echo "branch]}>{$branches[$story->branch]} "; if($story->module and isset($modulePairs[$story->module])) echo "{$modulePairs[$story->module]} "; @@ -5425,23 +5553,33 @@ class storyModel extends model public function setStatusByReviewRules($reviewerList) { $status = ''; + $results = ''; $passCount = 0; $rejectCount = 0; $reviewRule = $this->config->story->reviewRules; foreach($reviewerList as $reviewer => $reviewResult) { + if($reviewResult == 'clarify') return 'draft'; + $passCount = $reviewResult == 'pass' ? $passCount + 1 : $passCount; $rejectCount = $reviewResult == 'reject' ? $rejectCount + 1 : $rejectCount; + + $results .= $reviewResult . ','; } if($reviewRule == 'allpass') { + if(strpos($results, 'reject') !== false) return 'closed'; + if($passCount == count($reviewerList)) $status = 'active'; if($rejectCount == count($reviewerList)) $status = 'closed'; } if($reviewRule == 'halfpass') { + /* When the number of reviewers is even, half of them reject to close. */ + if(count($reviewerList) > 1 and count($reviewerList) % 2 == 0 and $rejectCount == floor(count($reviewerList) / 2)) return 'closed'; + if($passCount >= floor(count($reviewerList) / 2) + 1) $status = 'active'; if($rejectCount >= floor(count($reviewerList) / 2) + 1) $status = 'closed'; } @@ -5478,9 +5616,10 @@ class storyModel extends model if($result != 'revert') { - if($story->status == 'closed') $this->action->create('story', $story->id, 'ReviewRejected'); + $isChanged = $story->changedBy ? true : false; + if($story->status == 'closed') $this->action->create('story', $story->id, 'ReviewRejected', '', $isChanged ? 'changing' : 'draft'); if($story->status == 'active') $this->action->create('story', $story->id, 'ReviewPassed'); - if(!array_diff(array_keys($reviewers), $reviewedBy) and ($story->status == 'draft' or $story->status == 'changed')) $this->action->create('story', $story->id, 'ReviewClarified'); + if(!array_diff(array_keys($reviewers), $reviewedBy) and ($story->status == 'draft' or $story->status == 'changing')) $this->action->create('story', $story->id, 'ReviewClarified'); } return $actionID; @@ -5505,7 +5644,12 @@ class storyModel extends model $reviewedBy = explode(',', trim($story->reviewedBy, ',')); if(!array_diff(array_keys($reviewerList), $reviewedBy)) { - $status = $this->post->result == 'revert' ? 'active' : $this->setStatusByReviewRules($reviewerList); + $status = $this->post->result == 'revert' ? 'active' : $this->setStatusByReviewRules($reviewerList); + + /* When the review result of the changed story is clarify, the status should be changing. */ + $isChanged = $oldStory->changedBy ? true : false; + $status = ($isChanged and $status == 'draft') ? 'changing' : $status; + $story->status = $status ? $status : $oldStory->status; if($story->status == 'closed') { @@ -5534,12 +5678,14 @@ class storyModel extends model */ public function superReview($storyID, $oldStory, $story, $result = '', $reason = '') { - $now = helper::now(); - $status = ''; $result = isset($_POST['result']) ? $this->post->result : $result; + if(empty($result)) return $story; + + $now = helper::now(); + $status = $oldStory->status; if(strpos('revert,pass', $result) !== false) $status = 'active'; if($result == 'reject') $status = 'closed'; - if($result == 'clarify' or empty($status)) $status = $oldStory->status; + if($result == 'clarify') $status = 'draft'; $story->status = $status; @@ -5779,6 +5925,30 @@ class storyModel extends model return $stories; } + /** + * Get the story status after activation. + * + * @param int $storyID + * @access public + * @return void + */ + public function getActivateStatus($storyID) + { + $status = 'active'; + $lastRecord = $this->dao->select('action,extra')->from(TABLE_ACTION) + ->where('objectType')->eq('story') + ->andWhere('objectID')->eq($storyID) + ->orderBy('id_desc') + ->fetch(); + + $lastAction = $lastRecord->action; + $preStatus = $lastRecord->extra; + if(strpos($preStatus, '|') !== false) $preStatus = substr($preStatus, strpos($preStatus, '|') + 1); + if(strpos('closed,reviewrejected', $lastAction) !== false) $status = $preStatus; + + return $status; + } + /** * Get reviewer pairs for story . * diff --git a/module/story/view/activate.html.php b/module/story/view/activate.html.php index 18c08dfe88..e1876c9dfa 100644 --- a/module/story/view/activate.html.php +++ b/module/story/view/activate.html.php @@ -28,16 +28,6 @@ - - - - printExtendFields($story, 'table');?> diff --git a/module/story/view/batchclose.html.php b/module/story/view/batchclose.html.php index 9ee2df95ef..15d999f9fb 100755 --- a/module/story/view/batchclose.html.php +++ b/module/story/view/batchclose.html.php @@ -15,7 +15,7 @@ tab);?>
    -

    story->common . $lang->colon . $lang->story->batchClose;?>

    +

    SRCommon : $lang->URCommon) . $lang->colon . $lang->story->batchClose;?>

    @@ -38,13 +38,13 @@
    product->bugs?> bugs?>
    story->statusList['changed'] . $space . $lang->story->common;?>stories['changed']?>product->releases?>releases?>product->cases?>cases?>
    story->statusList['draft'] . $space . $lang->story->common;?> stories['draft']?>docs?>
    story->statusList['closed'] . $space . $lang->story->common;?>stories['closed']?>story->statusList['changing'] . $space . $lang->story->common;?>stories['changing']?>product->releases?>releases?>product->cases?>cases?>
    story->statusList['reviewing'] . $space . $lang->story->common;?>stories['reviewing']?> product->projects?> projects?>

    " + beginGreateChild + childInfo.minChildBegin + "

    " + ignore + "

    " + endLetterChild + childInfo.maxChildEnd + "

    " + ignore + "

    " + beginLetterParent + data.selectedProgramBegin + "

    " + ignore + "

    " + endGreaterParent + data.selectedProgramEnd + "

    " + ignore + "

    " + budgetOverrun + currencySymbol[data.budgetUnit] + data.availableBudget + "

    " + ignore + "

    @@ -91,12 +91,12 @@ config->URAndSR):?> requirements['draft'];?> requirements['active'];?>requirements['changed'];?>requirements['changing'];?> requirements['closed'] / $totalRequirements, 3) * 100;?>% stories['draft'];?> stories['active'];?>stories['changed'];?>stories['changing'];?> stories['closed'] / $totalStories, 3) * 100;?>% unResolved;?> closedBugs;?>

    " + budgetOverrun + currencySymbol[data.budgetUnit] + data.availableBudget.toFixed(2) + "

    " + ignore + "

    " + ignore + "

    " + dateTip + "

    " + ignore + "

    - ' class='content-icon' style='width: 16px; height: 16px; vertical-align: middle;'/> + ' class='content-icon' style='width: 16px; height: 16px; vertical-align: middle;'/> lang->release->stories . '(' . count($stories) . ')';?>
    - ' class='content-icon' style='width: 16px; height: 16px; vertical-align: middle;'/> + ' class='content-icon' style='width: 16px; height: 16px; vertical-align: middle;'/> lang->release->bugs . '(' . count($bugs) . ')';?>
    - ' class='content-icon' style='width: 16px; height: 16px; vertical-align: middle;'/> + ' class='content-icon' style='width: 16px; height: 16px; vertical-align: middle;'/> lang->release->leftBugs . '(' . count($leftBugs) . ')';?>
    productplan->begin;?> productplan->end;?> story->statusList['draft'];?>story->statusList['reviewing'];?> story->statusList['active'];?>story->statusList['changed'];?>story->statusList['changing'];?> story->statusList['closed'];?> report->total;?>
    begin == '2030-01-01' ? $lang->productplan->future : $plan->begin;?> end == '2030-01-01' ? $lang->productplan->future : $plan->end;?> 0 0 00
    story->assignedTo;?> closedBy, 'class="form-control chosen"');?>
    story->status;?> - story->statusList['']); - unset($lang->story->statusList['closed']); - echo html::select('status', $lang->story->statusList, 'active', 'class="form-control chosen"'); - ?> -
    story->comment;?>processStatus('story', $story);?> status == 'draft') unset($reasonList['cancel']);?> - +
    - diff --git a/module/story/view/batchedit.html.php b/module/story/view/batchedit.html.php index b0050c2928..abca607988 100644 --- a/module/story/view/batchedit.html.php +++ b/module/story/view/batchedit.html.php @@ -123,13 +123,13 @@ foreach(explode(',', $showFields) as $field) status == 'closed'):?> - @@ -409,11 +420,11 @@ foreach($relation as $id => $title) { echo "
  • " . ($canViewLinkStory ? html::a($this->createLink('story', 'view', "id=$id&version=0¶m=0&storyType=$relationType", '', true), "#$id $title", '', "class='iframe' data-width='80%'") : "#$id $title"); - echo html::a($this->createLink('story', 'linkStory', "storyID=$story->id&type=remove&linkedID=$id"), '', 'hiddenwin', "class='deleter hide removeButton'"); + echo html::a($this->createLink('story', 'linkStory', "storyID=$story->id&type=remove&linkedID=$id&browseType=&queryID=0&storyType=$story->type"), '', 'hiddenwin', "class='deleter hide removeButton'"); } ?> type == 'story') ? $lang->story->requirement : $lang->story->story;?> -
  • createLink('story', 'linkStory', "storyID=$story->id", '', true), $lang->story->link . $linkLang, '', "class='btn btn-info iframe' data-width='95%' id='linkButton'");?> +
  • type, 'linkStory')) echo html::a($this->createLink('story', 'linkStory', "storyID=$story->id&type=linkStories&linkedID=0&browseType=&queryID=0&storyType=$story->type", '', true), $lang->story->link . $linkLang, '', "class='btn btn-info iframe' data-width='95%' id='linkButton'");?> story->unlink, '', "class='btn btn-info' id='unlinkStory'");?>
  • diff --git a/module/task/config.php b/module/task/config.php index b14fdcb456..96ca1d4d79 100644 --- a/module/task/config.php +++ b/module/task/config.php @@ -71,9 +71,6 @@ $config->task->datatable->fieldList['mode']['control'] = 'hidden'; $config->task->datatable->fieldList['desc']['title'] = 'idAB'; $config->task->datatable->fieldList['desc']['control'] = 'textarea'; -$config->task->datatable->fieldList['deadline']['title'] = 'idAB'; -$config->task->datatable->fieldList['deadline']['control'] = 'date'; - $config->task->datatable->fieldList['pri']['title'] = 'priAB'; $config->task->datatable->fieldList['pri']['fixed'] = 'left'; $config->task->datatable->fieldList['pri']['width'] = '50'; @@ -95,6 +92,18 @@ $config->task->datatable->fieldList['status']['fixed'] = 'no'; $config->task->datatable->fieldList['status']['width'] = '60'; $config->task->datatable->fieldList['status']['required'] = 'no'; +$config->task->datatable->fieldList['assignedTo']['title'] = 'assignedTo'; +$config->task->datatable->fieldList['assignedTo']['fixed'] = 'no'; +$config->task->datatable->fieldList['assignedTo']['width'] = '100'; +$config->task->datatable->fieldList['assignedTo']['required'] = 'no'; +$config->task->datatable->fieldList['assignedTo']['control'] = 'select'; +$config->task->datatable->fieldList['assignedTo']['dataSource'] = array('module' => 'user', 'method' => 'getTeamMemberPairs', 'params' => '$executionID&execution'); + +$config->task->datatable->fieldList['finishedBy']['title'] = 'finishedByAB'; +$config->task->datatable->fieldList['finishedBy']['fixed'] = 'no'; +$config->task->datatable->fieldList['finishedBy']['width'] = '80'; +$config->task->datatable->fieldList['finishedBy']['required'] = 'no'; + $config->task->datatable->fieldList['estimate']['title'] = 'estimateAB'; $config->task->datatable->fieldList['estimate']['fixed'] = 'no'; $config->task->datatable->fieldList['estimate']['width'] = '60'; @@ -121,6 +130,7 @@ $config->task->datatable->fieldList['deadline']['title'] = 'deadlineAB'; $config->task->datatable->fieldList['deadline']['fixed'] = 'no'; $config->task->datatable->fieldList['deadline']['width'] = '70'; $config->task->datatable->fieldList['deadline']['required'] = 'no'; +$config->task->datatable->fieldList['deadline']['control'] = 'date'; $config->task->datatable->fieldList['openedBy']['title'] = 'openedByAB'; $config->task->datatable->fieldList['openedBy']['fixed'] = 'no'; @@ -143,23 +153,11 @@ $config->task->datatable->fieldList['realStarted']['fixed'] = 'no'; $config->task->datatable->fieldList['realStarted']['width'] = '95'; $config->task->datatable->fieldList['realStarted']['required'] = 'no'; -$config->task->datatable->fieldList['assignedTo']['title'] = 'assignedTo'; -$config->task->datatable->fieldList['assignedTo']['fixed'] = 'no'; -$config->task->datatable->fieldList['assignedTo']['width'] = '100'; -$config->task->datatable->fieldList['assignedTo']['required'] = 'no'; -$config->task->datatable->fieldList['assignedTo']['control'] = 'select'; -$config->task->datatable->fieldList['assignedTo']['dataSource'] = array('module' => 'user', 'method' => 'getTeamMemberPairs', 'params' => '$executionID&execution'); - $config->task->datatable->fieldList['assignedDate']['title'] = 'assignedDate'; $config->task->datatable->fieldList['assignedDate']['fixed'] = 'no'; $config->task->datatable->fieldList['assignedDate']['width'] = '110'; $config->task->datatable->fieldList['assignedDate']['required'] = 'no'; -$config->task->datatable->fieldList['finishedBy']['title'] = 'finishedByAB'; -$config->task->datatable->fieldList['finishedBy']['fixed'] = 'no'; -$config->task->datatable->fieldList['finishedBy']['width'] = '80'; -$config->task->datatable->fieldList['finishedBy']['required'] = 'no'; - $config->task->datatable->fieldList['finishedDate']['title'] = 'finishedDateAB'; $config->task->datatable->fieldList['finishedDate']['fixed'] = 'no'; $config->task->datatable->fieldList['finishedDate']['width'] = '105'; diff --git a/module/task/control.php b/module/task/control.php index 4e013ae08a..0ece9f54c0 100755 --- a/module/task/control.php +++ b/module/task/control.php @@ -623,7 +623,7 @@ class task extends control $this->view->users = $this->loadModel('user')->getPairs('nodeleted|noclosed', "{$this->view->task->openedBy},{$this->view->task->canceledBy},{$this->view->task->closedBy}"); $this->view->showAllModule = isset($this->config->execution->task->allModule) ? $this->config->execution->task->allModule : ''; $this->view->modules = $this->tree->getTaskOptionMenu($this->view->task->execution, 0, 0, $this->view->showAllModule ? 'allModule' : ''); - $this->view->executions = $this->config->systemMode == 'classic' ? $this->execution->getPairs() : $this->execution->getByProject($task->project, 'all', 0, true); + $this->view->executions = $this->config->systemMode == 'classic' ? $this->execution->getPairs() : $this->execution->getByProject($task->project, 'noclosed', 0, true, false, $task->execution); $this->display(); } diff --git a/module/task/css/view.css b/module/task/css/view.css index 5bb814cad8..ff734be84e 100644 --- a/module/task/css/view.css +++ b/module/task/css/view.css @@ -1,8 +1,6 @@ .side-col .cell {padding: 0px;} .side-col #legendProjectAndTask .list-unstyled {padding: 10px; border: 1px solid #ddd; border-top: 0px; margin: 0px;} .tab-pane table {border: 1px solid #ddd; border-top: none;} -.page-title{max-width: 80%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;} -.pull-left{max-width: 80%;} .MRThWidth {width: 90px !important;} .btn-edit-comment {z-index: 100;} diff --git a/module/task/lang/de.php b/module/task/lang/de.php index 7f3109669d..bf5d6c16dc 100644 --- a/module/task/lang/de.php +++ b/module/task/lang/de.php @@ -261,7 +261,7 @@ $lang->task->error->realStartedEmpty = '"Real Started" should not be empty.'; $lang->task->error->finishedDateEmpty = '"Finished Date" should not be empty.'; $lang->task->error->finishedDateSmall = '"Finished Date" should be > "Real Started"'; $lang->task->error->alreadyConsumed = 'The currently selected parent task has been consumed.'; -$lang->task->error->date = 'The date should be >= today.'; +$lang->task->error->date = 'The date should be <= today.'; $lang->task->error->leftEmptyAB = 'When the task status is %s, "Hours Left" cannot be 0'; $lang->task->error->leftEmpty = 'Task#%sWhen the task status is %s, "Left" cannot be 0'; diff --git a/module/task/lang/en.php b/module/task/lang/en.php index 1e1b1e536b..2058e72cad 100755 --- a/module/task/lang/en.php +++ b/module/task/lang/en.php @@ -261,7 +261,7 @@ $lang->task->error->realStartedEmpty = '"Real Started" should not be empty.'; $lang->task->error->finishedDateEmpty = '"Finished Date" should not be empty.'; $lang->task->error->finishedDateSmall = '"Finished Date" should be > "Real Started"'; $lang->task->error->alreadyConsumed = 'The currently selected parent task has been consumed.'; -$lang->task->error->date = 'The date should be >= today.'; +$lang->task->error->date = 'The date should be <= today.'; $lang->task->error->leftEmptyAB = 'When the task status is %s, "Hours Left" cannot be 0'; $lang->task->error->leftEmpty = 'Task#%sWhen the task status is %s, "Left" cannot be 0'; diff --git a/module/task/lang/fr.php b/module/task/lang/fr.php index 4d668186e3..d676f327a7 100644 --- a/module/task/lang/fr.php +++ b/module/task/lang/fr.php @@ -261,7 +261,7 @@ $lang->task->error->realStartedEmpty = '"Real Started" should not be empty.'; $lang->task->error->finishedDateEmpty = '"Finished Date" should not be empty.'; $lang->task->error->finishedDateSmall = '"Finished Date" should be > "Real Started"'; $lang->task->error->alreadyConsumed = 'The currently selected parent task has been consumed.'; -$lang->task->error->date = 'The date should be >= today.'; +$lang->task->error->date = 'The date should be <= today.'; $lang->task->error->leftEmptyAB = 'When the task status is %s, "Hours Left" cannot be 0'; $lang->task->error->leftEmpty = 'Task#%sWhen the task status is %s, "Left" cannot be 0'; @@ -354,4 +354,4 @@ $lang->taskestimate = new stdclass(); $lang->taskestimate->consumed = 'Estimés'; $lang->task->overEsStartDate = 'The %s schedule start time has exceeded, please modify the %s schedule start time first'; -$lang->task->overEsEndDate = 'The %s schedule end time has exceeded, please modify the %s schedule end time first'; \ No newline at end of file +$lang->task->overEsEndDate = 'The %s schedule end time has exceeded, please modify the %s schedule end time first'; diff --git a/module/task/lang/vi.php b/module/task/lang/vi.php index 488a1fccea..42cccd53b3 100644 --- a/module/task/lang/vi.php +++ b/module/task/lang/vi.php @@ -223,7 +223,7 @@ $lang->task->error->realStartedEmpty = '"Real Started" should not be empty.'; $lang->task->error->finishedDateEmpty = '"Finished Date" should not be empty.'; $lang->task->error->finishedDateSmall = '"Finished Date" should be > "Real Started"'; $lang->task->error->alreadyConsumed = 'The currently selected parent task has been consumed.'; -$lang->task->error->date = 'The date should be >= today.'; +$lang->task->error->date = 'The date should be <= today.'; /* Report. */ $lang->task->report = new stdclass(); diff --git a/module/task/model.php b/module/task/model.php index 0201d70d01..e6e3499c11 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -1266,7 +1266,7 @@ class taskModel extends model $task->{$extendField->field} = htmlSpecialString($task->{$extendField->field}); } - if(isset($data->consumeds[$taskID])) + if(!empty($data->consumeds[$taskID])) { if($data->consumeds[$taskID] < 0) { @@ -2367,7 +2367,8 @@ class taskModel extends model public function getExecutionTasks($executionID, $productID = 0, $type = 'all', $modules = 0, $orderBy = 'status_asc, id_desc', $pager = null) { if(is_string($type)) $type = strtolower($type); - $fields = 'DISTINCT t1.*, t2.id AS storyID, t2.title AS storyTitle, t2.product, t2.branch, t2.version AS latestStoryVersion, t2.status AS storyStatus, t3.realname AS assignedToRealName'; + $orderBy = str_replace('pri_', 'priOrder_', $orderBy); + $fields = "DISTINCT t1.*, t2.id AS storyID, t2.title AS storyTitle, t2.product, t2.branch, t2.version AS latestStoryVersion, t2.status AS storyStatus, t3.realname AS assignedToRealName, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder"; $this->config->edition == 'max' && $fields .= ', t6.name as designName, t6.version as latestDesignVersion'; $actionIDList = array(); @@ -2510,7 +2511,8 @@ class taskModel extends model public function getUserTasks($account, $type = 'assignedTo', $limit = 0, $pager = null, $orderBy = "id_desc", $projectID = 0) { if(!$this->loadModel('common')->checkField(TABLE_TASK, $type)) return array(); - $tasks = $this->dao->select('t1.*, t2.id as executionID, t2.name as executionName, t2.type as executionType, t3.id as storyID, t3.title as storyTitle, t3.status AS storyStatus, t3.version AS latestStoryVersion') + $orderBy = str_replace('pri_', 'priOrder_', $orderBy); + $tasks = $this->dao->select("t1.*, t2.id as executionID, t2.name as executionName, t2.type as executionType, t3.id as storyID, t3.title as storyTitle, t3.status AS storyStatus, t3.version AS latestStoryVersion, IF(t1.`pri` = 0, {$this->config->maxPriValue}, t1.`pri`) as priOrder") ->from(TABLE_TASK)->alias('t1') ->leftJoin(TABLE_EXECUTION)->alias('t2')->on("t1.execution = t2.id") ->leftJoin(TABLE_STORY)->alias('t3')->on('t1.story = t3.id') @@ -3464,7 +3466,7 @@ class taskModel extends model $storyChanged = (!empty($task->storyStatus) and $task->storyStatus == 'active' and $task->latestStoryVersion > $task->storyVersion and !in_array($task->status, array('cancel', 'closed'))); $canView = common::hasPriv('task', 'view'); - $taskLink = helper::createLink('task', 'view', "taskID=$task->id", '', true); + $taskLink = helper::createLink('task', 'view', "taskID=$task->id"); $account = $this->app->user->account; $id = $col->id; if($col->show) @@ -3522,7 +3524,7 @@ class taskModel extends model if($task->module and isset($modulePairs[$task->module])) echo "" . $modulePairs[$task->module] . ' '; if($task->parent > 0) echo '' . $this->lang->task->childrenAB . ' '; if(!empty($task->team)) echo '' . $this->lang->task->multipleAB . ' '; - echo $canView ? html::a($taskLink, $task->name, null, "style='color: $task->color' title='$task->name' class='iframe'") : "$task->name"; + echo $canView ? html::a($taskLink, $task->name, null, "style='color: $task->color' title='$task->name'") : "$task->name"; if(!empty($task->children)) echo ''; if($task->fromBug) echo html::a(helper::createLink('bug', 'view', "id=$task->fromBug"), "[BUG#$task->fromBug]", '', "class='bug'"); break; diff --git a/module/task/view/create.html.php b/module/task/view/create.html.php index 720502042d..68d2055eeb 100644 --- a/module/task/view/create.html.php +++ b/module/task/view/create.html.php @@ -21,9 +21,6 @@ error->notempty, $lang->task->estimate))?> lifetime);?> - - -task->create->requiredFields) as $field) diff --git a/module/testcase/control.php b/module/testcase/control.php index 39a48f21b8..591f82c8cd 100644 --- a/module/testcase/control.php +++ b/module/testcase/control.php @@ -1370,10 +1370,13 @@ class testcase extends control * @param int $caseID * @param string $browseType * @param int $param + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID * @access public * @return void */ - public function linkCases($caseID, $browseType = '', $param = 0) + public function linkCases($caseID, $browseType = '', $param = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1) { /* Get case and queryID. */ $case = $this->testcase->getById($caseID); @@ -1392,14 +1395,21 @@ class testcase extends control /* Get cases to link. */ $cases2Link = $this->testcase->getCases2Link($caseID, $browseType, $queryID); + /* Pager. */ + $this->app->loadClass('pager', true); + $recTotal = count($cases2Link); + $pager = new pager($recTotal, $recPerPage, $pageID); + $cases2Link = array_chunk($cases2Link, $pager->recPerPage); + /* Assign. */ $this->view->title = $case->title . $this->lang->colon . $this->lang->testcase->linkCases; $this->view->position[] = html::a($this->createLink('product', 'view', "productID=$case->product"), $this->products[$case->product]); $this->view->position[] = html::a($this->createLink('testcase', 'view', "caseID=$caseID"), $case->title); $this->view->position[] = $this->lang->testcase->linkCases; $this->view->case = $case; - $this->view->cases2Link = $cases2Link; + $this->view->cases2Link = empty($cases2Link) ? $cases2Link : $cases2Link[$pageID - 1]; $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->view->pager = $pager; $this->display(); } @@ -1410,10 +1420,13 @@ class testcase extends control * @param int $caseID * @param string $browseType * @param int $param + * @param int $recTotal + * @param int $recPerPage + * @param int $pageID * @access public * @return void */ - public function linkBugs($caseID, $browseType = '', $param = 0) + public function linkBugs($caseID, $browseType = '', $param = 0, $recTotal = 0, $recPerPage = 20, $pageID = 1) { $this->loadModel('bug'); @@ -1431,11 +1444,18 @@ class testcase extends control /* Get cases to link. */ $bugs2Link = $this->testcase->getBugs2Link($caseID, $browseType, $queryID); + /* Pager. */ + $this->app->loadClass('pager', true); + $recTotal = count($bugs2Link); + $pager = new pager($recTotal, $recPerPage, $pageID); + $bugs2Link = array_chunk($bugs2Link, $pager->recPerPage); + /* Assign. */ $this->view->position[] = $this->lang->testcase->linkBugs; $this->view->case = $case; - $this->view->bugs2Link = $bugs2Link; + $this->view->bugs2Link = empty($bugs2Link) ? $bugs2Link : $bugs2Link[$pageID - 1]; $this->view->users = $this->loadModel('user')->getPairs('noletter'); + $this->view->pager = $pager; $this->display(); } diff --git a/module/testcase/css/edit.css b/module/testcase/css/edit.css index 1c5e8bcfc1..98116880d4 100644 --- a/module/testcase/css/edit.css +++ b/module/testcase/css/edit.css @@ -3,3 +3,7 @@ .table-form > tbody > tr > td .btn.addbutton {display: block; margin: 1px 0px; width: 40px; padding: 1px 6px;} .table-form > tbody > tr > td .btn.delbutton {display: block; margin: 1px 0px; width: 40px; padding: 1px 6px;} #branch {width: 95px!important;} + .detail > table > tbody th {width: 80px !important;} + [lang^=en] .detail > table > tbody th, [lang^=fr] .detail > table > tbody th {width: 100px !important;} + [lang^=de] .detail > table > tbody th {width: 125px !important;} + .linkCaseTitle, .linkBugTitle {white-space: nowrap;} diff --git a/module/testcase/css/linkbugs.css b/module/testcase/css/linkbugs.css new file mode 100644 index 0000000000..d0b4b319fe --- /dev/null +++ b/module/testcase/css/linkbugs.css @@ -0,0 +1 @@ +#mainContent {min-height: 400px;} diff --git a/module/testcase/css/linkcases.css b/module/testcase/css/linkcases.css index 906bda4878..b5a0ad4517 100644 --- a/module/testcase/css/linkcases.css +++ b/module/testcase/css/linkcases.css @@ -1,2 +1,2 @@ -#mainContent {min-height: 300px;} +#mainContent {min-height: 400px;} .table-actions {padding-left: 0;} diff --git a/module/testcase/css/view.css b/module/testcase/css/view.css index 8ca4dd7af3..99c8213415 100644 --- a/module/testcase/css/view.css +++ b/module/testcase/css/view.css @@ -3,3 +3,4 @@ .case-fullscreen .main-row > .side-col {width: 0; position: relative; overflow: hidden;} .case-fullscreen .fullscreen-btn > .icon-fullscreen:before {content: '\e972';} +.linkCaseTitles, .linkBugTitles {overflow: hidden; white-space: nowrap;} diff --git a/module/testcase/view/caseheader.html.php b/module/testcase/view/caseheader.html.php index bee9079524..f65de1485b 100644 --- a/module/testcase/view/caseheader.html.php +++ b/module/testcase/view/caseheader.html.php @@ -130,7 +130,7 @@ $class = common::hasPriv('testcase', 'exportTemplate') ? '' : "class=disabled"; $misc = common::hasPriv('testcase', 'exportTemplate') ? "class='export'" : "class=disabled"; $link = common::hasPriv('testcase', 'exportTemplate') ? $this->createLink('testcase', 'exportTemplate', "productID=$productID") : '#'; - echo "
  • " . html::a($link, $lang->testcase->exportTemplate, '', $misc . "data-app={$this->app->tab} data-width='50%'") . "
  • "; + echo "
  • " . html::a($link, $lang->testcase->exportTemplate, '', $misc . "data-app={$this->app->tab} data-width='65%'") . "
  • "; ?> diff --git a/module/testcase/view/edit.html.php b/module/testcase/view/edit.html.php index 07d9a0a0d6..bd0e86840a 100644 --- a/module/testcase/view/edit.html.php +++ b/module/testcase/view/edit.html.php @@ -173,7 +173,7 @@ - +
    ' closedReason != 'duplicate') echo "style='display:none'";?>> - idAB}'");?> + ' closedReason != 'duplicate') echo "style='display:none'";?>> + '') + $productStoryList[$story->product][$story->branch], $story->duplicateStory ? $story->duplicateStory : '', "class='form-control' placeholder='{$lang->bug->duplicateTip}'");?> ' closedReason != 'subdivided') echo "style='display:none'";?>> idAB}'");?> diff --git a/module/story/view/batchcreate.html.php b/module/story/view/batchcreate.html.php index 07f38f0967..652ccdcf6a 100755 --- a/module/story/view/batchcreate.html.php +++ b/module/story/view/batchcreate.html.php @@ -131,7 +131,8 @@
    - save);?> + save, "id='saveButton'", 'btn btn-primary btn-wide');?> + story->saveDraft, "id='saveDraftButton'", 'btn btn-secondary btn-wide');?>
    > - +
    - - +
    closedReason, "class=form-control onchange=setDuplicateAndChild(this.value,$storyID) style='min-width: 70px'");?> ' closedReason != 'duplicate') echo "style='display: none'";?>> - idAB}'");?> + ' closedReason != 'duplicate') echo "style='display: none'";?>> + product][$story->branch], $story->duplicateStory, "class='form-control' placeholder='{$lang->idAB}'");?> ' closedReason != 'subdivided') echo "style='display: none'";?>> idAB}'");?> diff --git a/module/story/view/change.html.php b/module/story/view/change.html.php index 7351297df3..a5b89ca66f 100644 --- a/module/story/view/change.html.php +++ b/module/story/view/change.html.php @@ -20,11 +20,11 @@ arrow . ' ' . $lang->story->change;?> - + - - @@ -48,7 +42,7 @@ printExtendFields($story, 'table');?> - - + - + - + - - + - @@ -107,4 +102,5 @@ type);?> app->rawModule);?> +app->rawMethod);?> diff --git a/module/story/view/close.html.php b/module/story/view/close.html.php index f27d1c9d12..8f09e2a651 100644 --- a/module/story/view/close.html.php +++ b/module/story/view/close.html.php @@ -30,7 +30,7 @@ - + diff --git a/module/story/view/create.html.php b/module/story/view/create.html.php index 9b485e3d92..b035884158 100644 --- a/module/story/view/create.html.php +++ b/module/story/view/create.html.php @@ -34,6 +34,14 @@ foreach(explode(',', $config->story->create->requiredFields) as $field)

    story->create;?>

    + story->checkForceReview()):?> +
    +
    + /> + +
    +
    +
    createLink('custom', 'ajaxSaveCustomFields', 'module=story§ion=custom&key=createFields')?> @@ -88,64 +96,24 @@ foreach(explode(',', $config->story->create->requiredFields) as $field) ?>
    -
    - - - - - - - - + + + + - - + + + + + + + + + + + config->URAndSR):?> @@ -270,10 +267,6 @@ foreach(explode(',', $config->story->create->requiredFields) as $field) - - - - printExtendFields('', 'table', 'columns=4');?> @@ -300,7 +293,9 @@ foreach(explode(',', $config->story->create->requiredFields) as $field) diff --git a/module/story/view/edit.html.php b/module/story/view/edit.html.php index 193efa168f..a06afb7524 100644 --- a/module/story/view/edit.html.php +++ b/module/story/view/edit.html.php @@ -19,9 +19,10 @@ app->rawModule);?> story->module);?> - +story->notice->reviewerNotEmpty);?> story->feedbackSource); ?> +status);?>
    @@ -34,7 +35,7 @@
    -
    +
    @@ -43,16 +44,46 @@
    - title, 'class="form-control disabled story-title" disabled="disabled"');?> + title, 'class="form-control disabled story-title"' . (strpos('draft,changing', $story->status) !== false ? '' : ' disabled="disabled"'));?> +
    +
    + status) !== false):?> +
    +
    story->reviewers;?>
    +
    +
    + story->checkForceReview()):?> +
    + +
    +
    + +
    + /> + +
    +
    +
    + +
    + +
    + +
    +
    +
    + +
    +
    story->legendSpec;?>
    +
    + status) !== false ? html::textarea('spec', htmlSpecialString($story->spec), "rows='5' class='form-control'") : $story->spec;?>
    -
    -
    story->legendSpec;?>
    -
    spec;?>
    -
    story->verify;?>
    -
    verify;?>
    +
    + status) !== false ? html::textarea('verify', htmlSpecialString($story->verify), "rows='5' class='form-control'") : $story->verify;?> +
    printExtendFields($story, 'div', 'position=left');?>
    @@ -64,7 +95,15 @@
    lastEditedDate); - echo html::submitButton($lang->save); + if(strpos('draft,changing', $story->status) !== false) + { + echo html::commonButton($lang->save, "id='saveButton'", 'btn btn-primary btn-wide'); + echo html::commonButton($story->status == 'changing' ? $lang->story->doNotSubmit : $lang->story->saveDraft, "id='saveDraftButton'", 'btn btn-secondary btn-wide'); + } + else + { + echo html::submitButton($lang->save); + } if(!isonlybody()) echo html::backButton(); ?>
    @@ -153,7 +192,7 @@ status);?> - status != 'draft' and $story->type == 'story'):?> + status) !== false and $story->type == 'story'):?>
    @@ -220,7 +259,7 @@ status == 'closed' ? $users + array('closed' => 'Closed') : $users;?> - + status == 'reviewing'):?> @@ -244,17 +283,15 @@
    story->legendMisc;?>
    story->reviewedBy;?> +
    story->checkForceReview() ? ' required' : ''));?> story->checkForceReview()):?> @@ -34,12 +34,6 @@
    story->status;?>
    story->title;?> +
    story->spec;?>spec), 'rows=8 class="form-control"');?>story->specTemplate;?>spec), 'rows=8 class="form-control"');?>story->specTemplate;?>
    story->verify;?>verify), 'rows=6 class="form-control"');?>verify), 'rows=6 class="form-control"');?>
    story->comment;?>
    attatch;?> - fetch('file', 'printFiles', array('files' => $files, 'fieldset' => 'true', 'object' => $story, 'method' => 'change'));?> + + fetch('file', 'printFiles', array('files' => $files, 'fieldset' => 'true', 'object' => $story, 'method' => 'storyChange'));?> fetch('file', 'buildform');?>
    story->checkAffection;?>
    + lastEditedDate); - echo html::submitButton(); + echo html::commonButton($lang->save, "id='saveButton'", 'btn btn-primary btn-wide'); + echo html::commonButton($lang->story->doNotSubmit, "id='saveDraftButton'", 'btn btn-secondary btn-wide'); if(!isonlybody()) echo html::backButton(); ?>
    story->reviewedBy;?>' id='reviewerBox'> -
    - story->checkForceReview()):?> -
    - PO : '', "class='form-control picker-select' multiple");?> -
    -
    - -
    - /> - -
    -
    -
    - -
    - PO : '', "class='form-control picker-select' multiple required");?> -
    - -
    -
    ' id='assignedToBox' class='hidden'> + ' id='assignedToBox'>
    story->assignedTo;?>
    +
    story->source;?> + story->sourceList, $source, "class='form-control chosen'");?> +
    -
    -
    story->source;?>
    - story->sourceList, $source, "class='form-control chosen'");?> - story->sourceNote;?> - -
    +
    story->sourceNote;?>
    +
    story->assignedTo;?> + + +
    +
    +
    story->source;?>
    + story->sourceList, $source, "class='form-control chosen'");?> + story->sourceNote;?> + +
    +
    +
    story->reviewedBy;?> +
    + story->checkForceReview() ? 'required' : '';?> + story->checkForceReview() ? '' : html::hidden('needNotReview', 1);?> +
    + PO : '', "class='form-control picker-select' multiple $required");?> +
    +
    +
    story->verify;?>
    story->status;?>
    story->legendAttatch;?>
    - + + save, "id='saveButton'", 'btn btn-primary btn-wide');?> + story->saveDraft, "id='saveDraftButton'", 'btn btn-secondary btn-wide');?> goback, '', 'class="btn btn-wide"') : html::backButton('', $source == 'bug' ? 'data-app=qa' : '');?>
    story->stage;?> @@ -201,7 +240,7 @@ story->mailto;?>
    - mailto), "class='form-control picker-select' multiple");?> + mailto, "class='form-control picker-select' multiple");?> fetch('my', 'buildContactLists');?>
    assignedTo, 'class="form-control chosen"');?>
    story->reviewers;?>
    - status == 'closed'):?> - + - - + diff --git a/module/story/view/linkstories.html.php b/module/story/view/linkstories.html.php index fbb8e1c1b2..ad604ab44f 100644 --- a/module/story/view/linkstories.html.php +++ b/module/story/view/linkstories.html.php @@ -18,7 +18,7 @@ id;?>createLink('story', 'view', "storyID=$story->id"), $story->title, '_blank', "title='$story->title'");?> type == 'story' ? $lang->story->linkStoriesAB : $lang->story->linkRequirementsAB?> - arrow . $lang->story->linkStoriesAB;?> + arrow . $title;?>
    diff --git a/module/story/view/review.html.php b/module/story/view/review.html.php index 73cfdc29d5..fba8b02852 100644 --- a/module/story/view/review.html.php +++ b/module/story/view/review.html.php @@ -31,9 +31,9 @@ - + > - + @@ -55,12 +55,6 @@ - status == 'changed' or ($story->status == 'draft' and $story->version > 1)):?> - - - - - @@ -90,4 +84,5 @@ type);?> app->rawModule);?> + diff --git a/module/story/view/submitreview.html.php b/module/story/view/submitreview.html.php new file mode 100644 index 0000000000..d8865c9955 --- /dev/null +++ b/module/story/view/submitreview.html.php @@ -0,0 +1,65 @@ + + * @package story + * @version $Id: submitreview.html.php 935 2022-07-20 09:49:24Z $ + * @link https://www.zentao.net + */ +?> + + +
    +
    +
    +

    + id;?> + title'>" . $story->title . '') : html::a($this->createLink('story', 'view', 'story=' . $story->id), $story->title);?> + + arrow . $lang->story->submitReview;?> + +

    +
    + +
    story->duplicateStory;?>duplicateStory == 0 ? '' : $story->duplicateStory, "class='form-control'");?> '') + $productStories, $story->duplicateStory ? $story->duplicateStory : '', "class='form-control' placeholder='{$lang->bug->duplicateTip}'"); ?>
    story->linkStory;?>type == 'story' ? $lang->requirement->linkStory : $lang->story->linkStory;?> type == 'story') echo html::a("#", $lang->story->linkStoriesAB, '', "class='btn btn-info' id='linkStoriesLink'");?> - type == 'requirement') echo html::a("#", $lang->story->linkRequirementsAB, '', "class='btn btn-info' id='linkStoriesLink'");?> + type == 'requirement') echo html::a("#", $lang->story->linkRequirementsAB, '', "class='btn btn-info' id='linkStoriesLink'");?>
    story->reviewResult;?> story->resultList, '', 'class="form-control chosen" onchange="switchShow(this.value)"');?>
    story->assignedTo;?>assignedTo, "class='form-control picker-select'");?>
    story->rejectedReason;?>story->childStories;?>
    story->preVersion;?>version - 1, 1), range($story->version - 1, 1)), $story->version - 1);?>
    story->status;?> status);?>
    + + + + + + + +
    story->reviewedBy;?>reviewer)) echo "class='required'";?>> +
    + story->checkForceReview()):?> +
    + reviewer, "class='form-control picker-select' multiple");?> +
    +
    + +
    + /> + +
    +
    +
    + +
    + reviewer, "class='form-control picker-select' multiple required");?> +
    + +
    +
    + id);?> + + goback, $this->session->storyList, '', '', 'btn btn-wide');?> +
    + +
    + + + + diff --git a/module/story/view/view.html.php b/module/story/view/view.html.php index 6bd3407f6c..5a1ccabe35 100644 --- a/module/story/view/view.html.php +++ b/module/story/view/view.html.php @@ -326,7 +326,18 @@
    story->legendMailto;?>mailto); foreach($mailto as $account) {if(empty($account)) continue; echo "" . zget($users, trim($account)) . '  '; }?> + mailto)) + { + foreach(explode(',', $story->mailto) as $account) + { + if(empty($account)) continue; + echo "" . zget($users, trim($account)) . '  '; + } + } + ?> +
    @@ -366,12 +377,12 @@
    story->closedReason;?> + closedReason) echo $lang->story->reasonList[$story->closedReason]; if(isset($story->extraStories[$story->duplicateStory])) { - echo html::a(inlink('view', "storyID=$story->duplicateStory"), '#' . $story->duplicateStory . ' ' . $story->extraStories[$story->duplicateStory]); + echo html::a(inlink('view', "storyID=$story->duplicateStory"), '#' . $story->duplicateStory . ' ' . $story->extraStories[$story->duplicateStory], '', "title='{$story->extraStories[$story->duplicateStory]}'"); } ?>
    testcase->product;?>testcase->product;?>
    @@ -248,9 +248,9 @@ { foreach($case->linkCaseTitles as $linkCaseID => $linkCaseTitle) { - echo "
  • "; + echo "
  • "; echo ""; - echo ""; + echo ""; echo '
  • '; } } @@ -275,9 +275,9 @@ { foreach($case->toBugs as $bugID => $bugTitle) { - echo "
  • "; + echo "
  • "; echo ""; - echo ""; + echo ""; echo '
  • '; } } @@ -294,7 +294,7 @@
    testcase->legendOpenAndEdit;?>
    - + diff --git a/module/testcase/view/linkbugs.html.php b/module/testcase/view/linkbugs.html.php index 3194623d1e..a5fc284ba5 100644 --- a/module/testcase/view/linkbugs.html.php +++ b/module/testcase/view/linkbugs.html.php @@ -52,8 +52,8 @@ id);?> - - + + @@ -66,6 +66,7 @@
    id);?> + show('right', 'pagerjs');?> @@ -83,7 +84,7 @@ $(function() $('#linkBugsForm').find('tr.checked').each(function(){ var bugID = $(this).find('td.c-id').find('div.checkbox-primary input').attr('value'); var bugTitle = "#" + bugID + ' ' + $(this).find('td').eq(3).attr('title'); - var checkbox = "
  • "; + var checkbox = "
  • "; output += checkbox; }); diff --git a/module/testcase/view/linkcases.html.php b/module/testcase/view/linkcases.html.php index e7ae9bd8ab..e97784fd3b 100644 --- a/module/testcase/view/linkcases.html.php +++ b/module/testcase/view/linkcases.html.php @@ -52,8 +52,8 @@ id);?> - - + + @@ -66,6 +66,7 @@
    id);?> + show('right', 'pagerjs');?> @@ -83,7 +84,7 @@ $(function() $('#linkCasesForm').find('tr.checked').each(function(){ var caseID = $(this).find('td.c-id').find('div.checkbox-primary input').attr('value'); var caseTitle = "#" + caseID + ' ' + $(this).find('td').eq(3).attr('title'); - var checkbox = "
  • "; + var checkbox = "
  • "; output += checkbox; }); diff --git a/module/testcase/view/view.html.php b/module/testcase/view/view.html.php index 0b45563774..7723517c9d 100644 --- a/module/testcase/view/view.html.php +++ b/module/testcase/view/view.html.php @@ -284,13 +284,13 @@ - - diff --git a/module/testtask/css/browse.css b/module/testtask/css/browse.css index c68ac80a50..a2a2c4134c 100644 --- a/module/testtask/css/browse.css +++ b/module/testtask/css/browse.css @@ -1,3 +1,5 @@ #taskList tbody>tr>td, #taskList thead>tr>th {white-space: nowrap;} -td {overflow: hidden; text-overflow: ellipsis; white-space: nowrap;} +#taskList td {overflow: hidden; text-overflow: unset;} .c-name {width: 200px;} +.c-id {width: 60px;} +.c-user, .c-status {width: 80px;} diff --git a/module/testtask/model.php b/module/testtask/model.php index f2aadcbb32..029545908c 100644 --- a/module/testtask/model.php +++ b/module/testtask/model.php @@ -76,11 +76,13 @@ class testtaskModel extends model $products = $scopeAndStatus[0] == 'all' ? $this->app->user->view->products : array(); $branch = $scopeAndStatus[0] == 'all' ? 'all' : $branch; - return $this->dao->select("t1.*, t2.name AS productName, t3.name AS executionName, t4.name AS buildName, t4.branch AS branch") + $executionNameField = $this->config->systemMode == 'new' ? "IF(t5.id IS NOT NULL, CONCAT(t5.name, ' / ', t3.name), t3.name)" : 't3.name'; + return $this->dao->select("t1.*, t2.name AS productName, $executionNameField AS executionName, t4.name AS buildName, t4.branch AS branch") ->from(TABLE_TESTTASK)->alias('t1') ->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id') ->leftJoin(TABLE_EXECUTION)->alias('t3')->on('t1.execution = t3.id') ->leftJoin(TABLE_BUILD)->alias('t4')->on('t1.build = t4.id') + ->leftJoin(TABLE_PROJECT)->alias('t5')->on('t3.project = t5.id') ->where('t1.deleted')->eq(0) ->andWhere('t1.auto')->ne('unit') @@ -294,11 +296,13 @@ class testtaskModel extends model */ public function getByUser($account, $pager = null, $orderBy = 'id_desc', $type = '') { - return $this->dao->select('t1.*, t2.name AS executionName, t3.name AS buildName') + $executionNameField = $this->config->systemMode == 'new' ? "IF(t5.id IS NOT NULL, CONCAT(t5.name, ' / ', t2.name), t2.name)" : 't2.name'; + return $this->dao->select("t1.*, $executionNameField AS executionName, t3.name AS buildName") ->from(TABLE_TESTTASK)->alias('t1') ->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.execution = t2.id') ->leftJoin(TABLE_BUILD)->alias('t3')->on('t1.build = t3.id') ->leftJoin(TABLE_PRODUCT)->alias('t4')->on('t1.product = t4.id') + ->leftJoin(TABLE_PROJECT)->alias('t5')->on('t2.project = t5.id') ->where('t1.deleted')->eq(0) ->andWhere('t4.deleted')->eq(0) ->andWhere('t1.auto')->ne('unit') diff --git a/module/tree/control.php b/module/tree/control.php index ddc0bf6b97..694fb98501 100644 --- a/module/tree/control.php +++ b/module/tree/control.php @@ -376,7 +376,8 @@ class tree extends control { $this->view->optionMenu = $this->tree->getOptionMenu($module->root, $module->type, 0, $module->branch); } - if($type == 'doc') $this->view->libs = $this->loadModel('doc')->getLibs('all', $extra = 'withObject'); + + if($type == 'doc') $this->view->libs = $this->loadModel('doc')->getLibs('all', $extra = 'withObject', '', 0, 'book'); $this->view->module = $module; $this->view->type = $type; diff --git a/module/tutorial/model.php b/module/tutorial/model.php index 604148087a..f549488e83 100644 --- a/module/tutorial/model.php +++ b/module/tutorial/model.php @@ -98,24 +98,26 @@ class tutorialModel extends model { $product = $this->getProduct(); $product->stories = array(); - $product->stories[0] = ''; - $product->stories[1] = 'draft'; - $product->stories[2] = 'active'; - $product->stories[3] = 'closed'; - $product->stories[4] = 'changed'; - $product->stories[''] = 0; - $product->stories['draft'] = 0; - $product->stories['active'] = 0; - $product->stories['closed'] = 0; - $product->stories['changed'] = 0; - $product->requirements = $product->stories; - $product->plans = 0; - $product->releases = 0; - $product->bugs = 0; - $product->unResolved = 0; - $product->closedBugs = 0; - $product->fixedBugs = 0; - $product->assignToNull = 0; + $product->stories[0] = ''; + $product->stories[1] = 'draft'; + $product->stories[2] = 'reviewing'; + $product->stories[3] = 'active'; + $product->stories[4] = 'closed'; + $product->stories[5] = 'changing'; + $product->stories[''] = 0; + $product->stories['draft'] = 0; + $product->stories['reviewing'] = 0; + $product->stories['active'] = 0; + $product->stories['closed'] = 0; + $product->stories['changing'] = 0; + $product->requirements = $product->stories; + $product->plans = 0; + $product->releases = 0; + $product->bugs = 0; + $product->unResolved = 0; + $product->closedBugs = 0; + $product->fixedBugs = 0; + $product->assignToNull = 0; $productStat[$product->program][$product->line]['products'][$product->id] = $product; return $productStat; diff --git a/module/upgrade/config.php b/module/upgrade/config.php index 4b605d8bba..c60d898753 100644 --- a/module/upgrade/config.php +++ b/module/upgrade/config.php @@ -23,6 +23,7 @@ $config->upgrade->maxVersion['max3_3'] = '17_2'; $config->upgrade->maxVersion['max3_4'] = '17_3'; $config->upgrade->maxVersion['max3_5'] = '17_4'; $config->upgrade->maxVersion['max3_6'] = '17_5'; +$config->upgrade->maxVersion['max3_6_1'] = '17_6'; $config->upgrade->bizVersion = array(); $config->upgrade->bizVersion['biz1_0'] = '9_5_1'; @@ -84,6 +85,7 @@ $config->upgrade->bizVersion['biz7_2'] = '17_2'; $config->upgrade->bizVersion['biz7_3'] = '17_3'; $config->upgrade->bizVersion['biz7_4'] = '17_4'; $config->upgrade->bizVersion['biz7_5'] = '17_5'; +$config->upgrade->bizVersion['biz7_6'] = '17_6'; $config->upgrade->proVersion = array(); $config->upgrade->proVersion['pro1_0'] = '3_1'; diff --git a/module/upgrade/lang/version.php b/module/upgrade/lang/version.php index f7855b207d..b48aec0eec 100644 --- a/module/upgrade/lang/version.php +++ b/module/upgrade/lang/version.php @@ -164,6 +164,7 @@ $lang->upgrade->fromVersions['17_2'] = '17.2'; $lang->upgrade->fromVersions['17_3'] = '17.3'; $lang->upgrade->fromVersions['17_4'] = '17.4'; $lang->upgrade->fromVersions['17_5'] = '17.5'; +$lang->upgrade->fromVersions['17_6'] = '17.6'; global $config; /* Lite. */ @@ -332,6 +333,7 @@ $lang->upgrade->fromVersions['biz7_2'] = 'Biz7.2'; $lang->upgrade->fromVersions['biz7_3'] = 'Biz7.3'; $lang->upgrade->fromVersions['biz7_4'] = 'Biz7.4'; $lang->upgrade->fromVersions['biz7_5'] = 'Biz7.5'; +$lang->upgrade->fromVersions['biz7_6'] = 'Biz7.6'; /* Max. */ $lang->upgrade->fromVersions['max2_0_beta4'] = 'Max2.0.beta4'; @@ -356,3 +358,4 @@ $lang->upgrade->fromVersions['max3_2'] = 'Max3.2'; $lang->upgrade->fromVersions['max3_3'] = 'Max3.3'; $lang->upgrade->fromVersions['max3_4'] = 'Max3.4'; $lang->upgrade->fromVersions['max3_5'] = 'Max3.5'; +$lang->upgrade->fromVersions['max3_6'] = 'Max3.6'; diff --git a/module/upgrade/model.php b/module/upgrade/model.php index 67e5a8d397..dd1e706ff2 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -546,6 +546,8 @@ class upgradeModel extends model case '17_5': $this->updateOSAndBrowserOfBug(); $this->addURPriv(); + $this->updateStoryStatus(); + if(strpos($fromVersion, 'max') !== false) $this->syncCase2Project(); break; } @@ -1008,6 +1010,8 @@ class upgradeModel extends model $confirmContent .= file_get_contents($xuanxuanSql); case '17_4': $confirmContent .= file_get_contents($this->getUpgradeFile('17.4')); + case '17_5': + $confirmContent .= file_get_contents($this->getUpgradeFile('17.5')); } return $confirmContent; @@ -3229,7 +3233,7 @@ class upgradeModel extends model } } - $openVersion = $this->getOpenVersion($fromVersion); + $openVersion = $this->getOpenVersion(str_replace('.', '_', $fromVersion)); if(version_compare($openVersion, '17_4', '<=')) $needProcess['changeEngine'] = 'notice'; return $needProcess; @@ -7051,6 +7055,28 @@ class upgradeModel extends model return !dao::isError(); } + /** + * Update story status. + * + * @access public + * @return void + */ + public function updateStoryStatus() + { + /* After cancel the review of changed story, the story status should be "changing". */ + $this->dao->update(TABLE_STORY)->set('status')->eq('changing')->where('status')->eq('draft')->andWhere('version')->gt(1)->exec(); + + /* The draft story with reviewers should be "reviewing". */ + $reviewingStories = $this->dao->select('story')->from(TABLE_STORYREVIEW)->alias('t1') + ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story = t2.id and t1.version = t2.version') + ->where('t2.status')->eq('draft') + ->andWhere('t2.version')->eq(1) + ->fetchPairs(); + $this->dao->update(TABLE_STORY)->set('status')->eq('reviewing')->where('id')->in($reviewingStories)->exec(); + + return !dao::isError(); + } + /** * Change FULLTEXT index for searchindex table. * @@ -7134,4 +7160,48 @@ class upgradeModel extends model $this->dbh->exec($sql); return true; } + + /** + * Sync case to project|execution if case create from import. + * + * @access public + * @return void + */ + public function syncCase2Project() + { + $linkStoryCases = $this->dao->select('id, story, version, product')->from(TABLE_CASE)->where('story')->ne('0')->fetchAll('id'); + $linkProjectCases = $this->dao->select('`case`, project')->from(TABLE_PROJECTCASE)->where('`case`')->ne('0')->andWhere('project')->ne('0')->fetchGroup('case', 'project'); + + if(empty($linkStoryCases)) return true; + + $projectList = $this->dao->select('t1.project, t1.story, t1.product')->from(TABLE_PROJECTSTORY)->alias('t1') + ->leftjoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id') + ->where('t2.status')->ne('closed') + ->fetchGroup('story', 'project'); + + if(empty($projectList)) return true; + + foreach($linkStoryCases as $caseID => $case) + { + /* If story unlink project continue. */ + if(!isset($projectList[$case->story])) continue; + + $storyProjects = $projectList[$case->story]; + + $lastOrder = 1; + foreach($storyProjects as $projectID => $value) + { + /* If case linked project continue.*/ + if(isset($linkProjectCases[$caseID][$projectID])) continue; + + $data = new stdclass(); + $data->project = $projectID; + $data->product = $case->product; + $data->case = $caseID; + $data->version = $case->version; + $data->order = $lastOrder ++; + $this->dao->insert(TABLE_PROJECTCASE)->data($data)->exec(); + } + } + } } diff --git a/module/user/model.php b/module/user/model.php index f0d90532c9..a2c0442d3f 100644 --- a/module/user/model.php +++ b/module/user/model.php @@ -1087,7 +1087,7 @@ class userModel extends model if(!$stmt) return array('rights' => $rights, 'acls' => $acls); while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { - $rights[strtolower($row['module'])][strtolower($row['method'])] = true; + if($row['module'] and $row['method']) $rights[strtolower($row['module'])][strtolower($row['method'])] = true; } /* Get can manage projects by user. */ diff --git a/module/user/view/task.html.php b/module/user/view/task.html.php index 8c9999fd4d..bae1a1e8f8 100644 --- a/module/user/view/task.html.php +++ b/module/user/view/task.html.php @@ -61,8 +61,11 @@ diff --git a/module/webhook/model.php b/module/webhook/model.php index 02428402bd..f34a4ca685 100644 --- a/module/webhook/model.php +++ b/module/webhook/model.php @@ -487,10 +487,11 @@ class webhookModel extends model $tab = $meeting->project ? '#app=project' : '#app=my'; } + $sysUrl = common::getSysURL(); $viewLink = helper::createLink($objectType, 'view', "id=$objectID", 'html') . $tab; if($oldOnlyBody) $_GET['onlybody'] = $oldOnlyBody; - return $viewLink; + return ltrim($viewLink, $sysUrl); } /** diff --git a/test/class/bug.class.php b/test/class/bug.class.php index 9ff50201bf..f9a54a65f9 100644 --- a/test/class/bug.class.php +++ b/test/class/bug.class.php @@ -2080,4 +2080,93 @@ class bugTest return $title; } } + + /** + * Test get statistic. + * + * @param int $productID + * @access public + * @return string + */ + public function getStatisticTest($productID = 0) + { + $dates = $this->objectModel->getStatistic($productID); + $returns = array(); + $today = date('m/d', time()); + foreach($dates as $dateType => $dateList) + { + $returns[$dateType] = $dateList[$today]; + } + + if(dao::isError()) + { + return dao::getError(); + } + else + { + return $returns; + } + } + + /** + * Test get bugs to review. + * + * @param array $productIDList + * @param int|string $branch + * @param array $modules + * @param array $executions + * @param string $orderBy + * @access public + * @return string + */ + public function getReviewBugsTest($productIDList, $branch, $modules, $executions, $orderBy) + { + $bugs = $this->objectModel->getReviewBugs($productIDList, $branch, $modules, $executions, $orderBy); + $ids = ''; + foreach($bugs as $bug) + { + $ids .= ",$bug->id"; + } + $ids = trim($ids, ','); + + if(dao::isError()) + { + return dao::getError(); + } + else + { + return $ids; + } + } + + /** + * Test get related objects id lists. + * + * @param array $productIDList + * @param int|string $branch + * @param array $modules + * @param array $executions + * @param string $orderBy + * @access public + * @return string + */ + public function getRelatedObjectsTest($object, $pairs) + { + $objects = $this->objectModel->getRelatedObjects($object, $pairs); + $ids = ''; + foreach($objects as $objectID => $object) + { + $ids .= ",$objectID:$object"; + } + $ids = trim($ids, ','); + + if(dao::isError()) + { + return dao::getError(); + } + else + { + return $ids; + } + } } diff --git a/test/class/execution.class.php b/test/class/execution.class.php index 9600ac750a..e958b9a486 100644 --- a/test/class/execution.class.php +++ b/test/class/execution.class.php @@ -1604,33 +1604,31 @@ class executionTest } /** - * function getBurnDataFlot test by execution + * Function getBurnDataFlot test by execution. * - * @param int $executionID - * @param string $count + * @param int $executionID * @access public - * @return array + * @return int */ - public function getBurnDataFlotTest($executionID = 0, $count) + public function getBurnDataFlotTest($executionID = 0) { $date = date("Y-m-d"); $object = $this->objectModel->getBurnDataFlot($executionID, $burnBy = 'left'); $todayData = array(); - foreach ($object[$date] as $key => $value) $todayData[$key] = $value; + if(isset($object[$date])) + { + foreach($object[$date] as $key => $value) $todayData[$key] = $value; + } if(dao::isError()) { $error = dao::getError(); return $error; } - elseif($count == "1") - { - return sizeof($todayData); - } else { - return $object; + return sizeof($todayData); } } diff --git a/test/class/todo.class.php b/test/class/todo.class.php index 0f5696d4ed..9ba0799c57 100755 --- a/test/class/todo.class.php +++ b/test/class/todo.class.php @@ -3,9 +3,10 @@ class todoTest { public function __construct() { - global $tester; - $this->objectModel = $tester->loadModel('todo'); - $tester->app->loadClass('dao'); + global $tester; + $this->objectModel = $tester->loadModel('todo'); + $tester->app->loadClass('dao'); + $_SERVER['HTTP_HOST'] = 'test.zentao.net'; } /** diff --git a/test/model/bug/assign.php b/test/model/bug/assign.php index 16806378cc..557caff822 100755 --- a/test/model/bug/assign.php +++ b/test/model/bug/assign.php @@ -16,7 +16,6 @@ pid=1 指派bugID为3的bug >> assignedTo,admin,user94 指派bugID为4的bug >> assignedTo,admin,user95 指派bugID为51的bug >> assignedTo,dev1,user96 -指派bugID为81的bug >> assignedTo,test1,user97 指派人不发生变化的bug >> 0 */ @@ -36,6 +35,5 @@ r($bug->assignTest($bugIDlist[1],$bug2)) && p('0:field,old,new') && e('assigned r($bug->assignTest($bugIDlist[2],$bug3)) && p('0:field,old,new') && e('assignedTo,admin,user94'); // 指派bugID为3的bug r($bug->assignTest($bugIDlist[3],$bug4)) && p('0:field,old,new') && e('assignedTo,admin,user95'); // 指派bugID为4的bug r($bug->assignTest($bugIDlist[4],$bug51)) && p('0:field,old,new') && e('assignedTo,dev1,user96'); // 指派bugID为51的bug -r($bug->assignTest($bugIDlist[5],$bug81)) && p('0:field,old,new') && e('assignedTo,test1,user97'); // 指派bugID为81的bug r($bug->assignTest($bugIDlist[5],$bug81)) && p() && e('0'); // 指派人不发生变化的bug -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/bug/getbugquery.php b/test/model/bug/getbugquery.php index 045f15f3df..1c0ee4c052 100755 --- a/test/model/bug/getbugquery.php +++ b/test/model/bug/getbugquery.php @@ -10,7 +10,7 @@ title=bugModel->getBugQuery(); cid=1 pid=1 -查询 `product` = 'all' 的bugQuery >> 1 AND `product` IN ('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59','60','61','62','63','64','65','66','67','68','69','70','71','72','73','74','75','76','77','78','79','80','81','82','83','84','85','86','87','88','89','90','91','92','93','94','95','96','97','98','99','100','101','102','103','104','105','106','107','108','109','110','111','112','113','114','115','116','117','118','119','120','1','2','3','4','5','6','7','8','9','10','21','22','23','24','25','26','27','28','29','30','41','42','43','44','45','46','47','48','49','50','61','62','63','64','65','66','67','68','69','70','81','82','83','84','85','86','87','88','89','90','101','102','103','104','105','106','107','108','109','110 +查询 `product` = 'all' 的bugQuery >> 1 AND `product` IN ('1','2','3','4','5','6','7','8','9','10','21','22','23','24','25','26','27','28','29','30','41','42','43','44','45','46','47','48','49','50','61','62','63','64','65','66','67','68','69','70','81','82','83','84','85','86','87','88','89','90','101','102','103','104','105','106','107','108','109','110','11','12','13','14','15','16','17','18','19','20','31','32','33','34','35','36','37','38','39','40','51','52','53','54','55','56','57','58','59','60','71','72','73','74','75','76','77','78','79','80','91','92','93','94','95','96','97','98','99','100','111','112','113','114','115','116','117','118','119','120','1','2','3','4','5','6','7','8','9','10','21','22','23','24','25','26','27','28','29','30','41','42','43','44','45','46','47','48','49','50','61','62','63','64','65','66','67','68','69','70','81','82','83','84','85','86','87','88','89','90','101','102','103','104','105','106','107','108','109','110') 查询 `project` = 'all' 的bugQuery >> 1 AND `project` in (11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750) 查询 `resolvedDate` = '2022-01-01' 的bugQuery >> `resolvedDate` != '0000-00-00 00:00:00' AND `resolvedDate` > '2022-01-01' 查询 `closedDate` = '2022-01-01' 的bugQuery >> `closedDate` != '0000-00-00 00:00:00' AND `closedDate` <= '2022-01-01' @@ -31,10 +31,10 @@ $bugQuery[] = " `product` = '1' and `project` = '1' and `story` > 'abc'"; $bug=new bugTest(); -r($bug->getBugQueryTest($bugQuery[0])) && p() && e("1 AND `product` IN ('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59','60','61','62','63','64','65','66','67','68','69','70','71','72','73','74','75','76','77','78','79','80','81','82','83','84','85','86','87','88','89','90','91','92','93','94','95','96','97','98','99','100','101','102','103','104','105','106','107','108','109','110','111','112','113','114','115','116','117','118','119','120','1','2','3','4','5','6','7','8','9','10','21','22','23','24','25','26','27','28','29','30','41','42','43','44','45','46','47','48','49','50','61','62','63','64','65','66','67','68','69','70','81','82','83','84','85','86','87','88','89','90','101','102','103','104','105','106','107','108','109','110')"); // 查询 `product` = 'all' 的bugQuery +r($bug->getBugQueryTest($bugQuery[0])) && p() && e("1 AND `product` IN ('1','2','3','4','5','6','7','8','9','10','21','22','23','24','25','26','27','28','29','30','41','42','43','44','45','46','47','48','49','50','61','62','63','64','65','66','67','68','69','70','81','82','83','84','85','86','87','88','89','90','101','102','103','104','105','106','107','108','109','110','11','12','13','14','15','16','17','18','19','20','31','32','33','34','35','36','37','38','39','40','51','52','53','54','55','56','57','58','59','60','71','72','73','74','75','76','77','78','79','80','91','92','93','94','95','96','97','98','99','100','111','112','113','114','115','116','117','118','119','120','1','2','3','4','5','6','7','8','9','10','21','22','23','24','25','26','27','28','29','30','41','42','43','44','45','46','47','48','49','50','61','62','63','64','65','66','67','68','69','70','81','82','83','84','85','86','87','88','89','90','101','102','103','104','105','106','107','108','109','110')"); // 查询 `product` = 'all' 的bugQuery r($bug->getBugQueryTest($bugQuery[1])) && p() && e("1 AND `project` in (11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750)"); // 查询 `project` = 'all' 的bugQuery r($bug->getBugQueryTest($bugQuery[2])) && p() && e(" `resolvedDate` != '0000-00-00 00:00:00' AND `resolvedDate` > '2022-01-01'"); // 查询 `resolvedDate` = '2022-01-01' 的bugQuery r($bug->getBugQueryTest($bugQuery[3])) && p() && e(" `closedDate` != '0000-00-00 00:00:00' AND `closedDate` <= '2022-01-01'"); // 查询 `closedDate` = '2022-01-01' 的bugQuery r($bug->getBugQueryTest($bugQuery[4])) && p() && e(" `story` IN (2,12,20,21,22,23,24,25,26,27,28,29,32,42,52,62,70,71,72,73,74,75,76,77,78,79,82,92,102,112,120,121,122,123,124,125,126,127,128,129,132,142,152,162,172,182,192,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,302,312,320,321,322,323,324,325,326,327,328,329,332,342,352,362,372,382,392,402,412,420,421,422,423,424,425,426,427,428,429,432,442) AND `story` != 0"); // 查询 `story` LIKE '%abc%' 的bugQuery r($bug->getBugQueryTest($bugQuery[5])) && p() && e(" `story` NOT IN (2,12,20,21,22,23,24,25,26,27,28,29,32,42,52,62,70,71,72,73,74,75,76,77,78,79,82,92,102,112,120,121,122,123,124,125,126,127,128,129,132,142,152,162,172,182,192,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,302,312,320,321,322,323,324,325,326,327,328,329,332,342,352,362,372,382,392,402,412,420,421,422,423,424,425,426,427,428,429,432,442) AND `story` != 0"); // 查询 `story` NOT LIKE '%abc%' 的bugQuery -r($bug->getBugQueryTest($bugQuery[6])) && p() && e("`product` = '1' and `project` = '1' and `story` > 'abc' AND `story` != 0"); // 查询 `product` = '1' and `project` = '1' and `story` > 'abc' 的bugQuery \ No newline at end of file +r($bug->getBugQueryTest($bugQuery[6])) && p() && e("`product` = '1' and `project` = '1' and `story` > 'abc' AND `story` != 0"); // 查询 `product` = '1' and `project` = '1' and `story` > 'abc' 的bugQuery diff --git a/test/model/bug/getrelatedobjects.php b/test/model/bug/getrelatedobjects.php new file mode 100755 index 0000000000..d2074cd36e --- /dev/null +++ b/test/model/bug/getrelatedobjects.php @@ -0,0 +1,33 @@ +#!/usr/bin/env php +getRelatedObjects(); +cid=1 +pid=1 + +获取bug关联的 branch 的 id,name >> :,0: +获取bug关联的 task 的 id,name >> :,0: +获取bug关联的 case 的 id,title >> :,0: +获取bug关联的 resolvedBuild 的 id,name >> :,0:,trunk:主干 +获取bug关联的 openedBuild 的 id,name >> :,0:,trunk:主干,1:项目版本版本1 +获取bug关联的 story 的 id,title >> :,0:,2:软件需求2,6:软件需求6,10:软件需求10,14:软件需求14,18:软件需求18,22:软件需求22,26:软件需求26,30:软件需求30,34:软件需求34 + +*/ + +$objects = array('branch', 'task', 'case', 'resolvedBuild', 'openedBuild', 'story'); +$pairs = array('id,name', 'id,title'); + +$bug=new bugTest(); +$_SESSION['bugQueryCondition'] = 'id < 10'; + +r($bug->getRelatedObjectsTest($objects[0], $pairs[0])) && p() && e(':,0:'); // 获取bug关联的 branch 的 id,name +r($bug->getRelatedObjectsTest($objects[1], $pairs[0])) && p() && e(':,0:'); // 获取bug关联的 task 的 id,name +r($bug->getRelatedObjectsTest($objects[2], $pairs[1])) && p() && e(':,0:'); // 获取bug关联的 case 的 id,title +r($bug->getRelatedObjectsTest($objects[3], $pairs[0])) && p() && e(':,0:,trunk:主干'); // 获取bug关联的 resolvedBuild 的 id,name +r($bug->getRelatedObjectsTest($objects[4], $pairs[0])) && p() && e(':,0:,trunk:主干,1:项目版本版本1'); // 获取bug关联的 openedBuild 的 id,name +r($bug->getRelatedObjectsTest($objects[5], $pairs[1])) && p() && e(':,0:,2:软件需求2,6:软件需求6,10:软件需求10,14:软件需求14,18:软件需求18,22:软件需求22,26:软件需求26,30:软件需求30,34:软件需求34'); // 获取bug关联的 story 的 id,title \ No newline at end of file diff --git a/test/model/bug/getreviewbugs.php b/test/model/bug/getreviewbugs.php new file mode 100755 index 0000000000..0bba515b5a --- /dev/null +++ b/test/model/bug/getreviewbugs.php @@ -0,0 +1,41 @@ +#!/usr/bin/env php +getReviewBugs(); +cid=1 +pid=1 + + + +*/ + +$productIDList = array('1,2,3,1000001', '1,3'); +$branch = array('all', '1'); +$moduleIDList = array('1821,1825,1832,1000001', '1821, 1825'); +$executions = array(array(101,102), array(101,111)); +$orderBy = 'id_asc'; + +$bug=new bugTest(); + +r($bug->getReviewBugsTest($productIDList[0], $branch[0], $moduleIDList[0], $executions[0], $orderBy)) && p('') && e(''); // 查询产品1 2 3 不存在的产品10001 与分支all 模块1821, 1825, 1832 不存在的模块1000001 执行101 102下审批人为当前用户的bug +r($bug->getReviewBugsTest($productIDList[0], $branch[1], $moduleIDList[0], $executions[0], $orderBy)) && p('') && e(''); // 查询产品1 2 3 不存在的产品10001 与分支1 模块1821, 1825, 1832 不存在的模块1000001 执行101 102下审批人为当前用户的bug +r($bug->getReviewBugsTest($productIDList[0], $branch[0], $moduleIDList[1], $executions[0], $orderBy)) && p('') && e(''); // 查询产品1 2 3 不存在的产品10001 与分支all 模块1821, 1825 执行101 102下审批人为当前用户的bug +r($bug->getReviewBugsTest($productIDList[0], $branch[1], $moduleIDList[1], $executions[0], $orderBy)) && p('') && e(''); // 查询产品1 2 3 不存在的产品10001 与分支1 模块1821, 1825 执行101 102下审批人为当前用户的bug +r($bug->getReviewBugsTest($productIDList[0], $branch[0], $moduleIDList[0], $executions[1], $orderBy)) && p('') && e(''); // 查询产品1 2 3 不存在的产品10001 与分支all 模块1821, 1825, 1832 不存在的模块1000001 执行101 111下审批人为当前用户的bug +r($bug->getReviewBugsTest($productIDList[0], $branch[1], $moduleIDList[0], $executions[1], $orderBy)) && p('') && e(''); // 查询产品1 2 3 不存在的产品10001 与分支1 模块1821, 1825, 1832 不存在的模块1000001 执行101 111下审批人为当前用户的bug +r($bug->getReviewBugsTest($productIDList[0], $branch[0], $moduleIDList[1], $executions[1], $orderBy)) && p('') && e(''); // 查询产品1 2 3 不存在的产品10001 与分支all 模块1821, 1825 执行101 111下审批人为当前用户的bug +r($bug->getReviewBugsTest($productIDList[0], $branch[1], $moduleIDList[1], $executions[1], $orderBy)) && p('') && e(''); // 查询产品1 2 3 不存在的产品10001 与分支1 模块1821, 1825 执行101 111下审批人为当前用户的bug +// +r($bug->getReviewBugsTest($productIDList[1], $branch[0], $moduleIDList[0], $executions[0], $orderBy)) && p('') && e(''); // 查询产品1 3 与分支all 模块1821, 1825, 1832 不存在的模块1000001 执行101 102下审批人为当前用户的bug +r($bug->getReviewBugsTest($productIDList[1], $branch[1], $moduleIDList[0], $executions[0], $orderBy)) && p('') && e(''); // 查询产品1 3 与分支1 模块1821, 1825, 1832 不存在的模块1000001 执行101 102下审批人为当前用户的bug +r($bug->getReviewBugsTest($productIDList[1], $branch[0], $moduleIDList[1], $executions[0], $orderBy)) && p('') && e(''); // 查询产品1 3 与分支all 模块1821, 1825 执行101 102下审批人为当前用户的bug +r($bug->getReviewBugsTest($productIDList[1], $branch[1], $moduleIDList[1], $executions[0], $orderBy)) && p('') && e(''); // 查询产品1 3 与分支1 模块1821, 1825 执行101 102下审批人为当前用户的bug +r($bug->getReviewBugsTest($productIDList[1], $branch[0], $moduleIDList[0], $executions[1], $orderBy)) && p('') && e(''); // 查询产品1 3 与分支all 模块1821, 1825, 1832 不存在的模块1000001 执行101 111下审批人为当前用户的bug +r($bug->getReviewBugsTest($productIDList[1], $branch[1], $moduleIDList[0], $executions[1], $orderBy)) && p('') && e(''); // 查询产品1 3 与分支1 模块1821, 1825, 1832 不存在的模块1000001 执行101 111下审批人为当前用户的bug +r($bug->getReviewBugsTest($productIDList[1], $branch[0], $moduleIDList[1], $executions[1], $orderBy)) && p('') && e(''); // 查询产品1 3 与分支all 模块1821, 1825 执行101 111下审批人为当前用户的bug +r($bug->getReviewBugsTest($productIDList[1], $branch[1], $moduleIDList[1], $executions[1], $orderBy)) && p('') && e(''); // 查询产品1 3 与分支1 模块1821, 1825 执行101 111下审批人为当前用户的bug \ No newline at end of file diff --git a/test/model/bug/getstatistic.php b/test/model/bug/getstatistic.php new file mode 100755 index 0000000000..58f5277a15 --- /dev/null +++ b/test/model/bug/getstatistic.php @@ -0,0 +1,37 @@ +#!/usr/bin/env php +getStatistic(); +cid=1 +pid=1 + +查询product id为0创建日期在今天的统计信息 >> 0 +查询product id为1创建日期在今天的统计信息 >> 0 +查询product id为1创建日期在今天的统计信息 >> 0 +查询product id为1创建日期在今天的统计信息 >> 0 +查询product id为11解决日期在今天的统计信息 >> 1 +查询product id为31解决日期在今天的统计信息 >> 0 +查询product id为61解决日期在今天的统计信息 >> 0 +查询product id为91关闭日期在今天的统计信息 >> 0 +查询product id为10001关闭日期在今天的统计信息 >> 0 + +*/ + +$productIDList = array('1', '11', '31', '61', '91', '10001'); + +$bug=new bugTest(); + +r($bug->getStatisticTest()) && p('openedDate:num') && e('0'); // 查询product id为0创建日期在今天的统计信息 +r($bug->getStatisticTest($productIDList[0])) && p('openedDate:num') && e('0'); // 查询product id为1创建日期在今天的统计信息 +r($bug->getStatisticTest($productIDList[0])) && p('resolvedDate:num') && e('0'); // 查询product id为1创建日期在今天的统计信息 +r($bug->getStatisticTest($productIDList[0])) && p('closedDate:num') && e('0'); // 查询product id为1创建日期在今天的统计信息 +r($bug->getStatisticTest($productIDList[1])) && p('openedDate:num') && e('1'); // 查询product id为11解决日期在今天的统计信息 +r($bug->getStatisticTest($productIDList[2])) && p('openedDate:num') && e('0'); // 查询product id为31解决日期在今天的统计信息 +r($bug->getStatisticTest($productIDList[3])) && p('openedDate:num') && e('0'); // 查询product id为61解决日期在今天的统计信息 +r($bug->getStatisticTest($productIDList[4])) && p('openedDate:num') && e('0'); // 查询product id为91关闭日期在今天的统计信息 +r($bug->getStatisticTest($productIDList[5])) && p('openedDate:num') && e('0'); // 查询product id为10001关闭日期在今天的统计信息 \ No newline at end of file diff --git a/test/model/execution/batchupdate.php b/test/model/execution/batchupdate.php index b0782fd400..1a95dd9003 100755 --- a/test/model/execution/batchupdate.php +++ b/test/model/execution/batchupdate.php @@ -12,7 +12,7 @@ cid=1 pid=1 测试批量修改任务 >> name,迭代1,批量修改执行一 -测试name为空 >> 『name』不能为空。 +测试name为空 >> 『执行名称』不能为空。 */ @@ -30,5 +30,5 @@ $noName = array('statuses'=> $statuses, 'codes' => $code, 'PMs' => $pms, 'lifet $execution = new executionTest(); r($execution->batchUpdateObject($normal, $executionID)) && p('0:field,old,new') && e('name,迭代1,批量修改执行一'); // 测试批量修改任务 -r($execution->batchUpdateObject($noName, $executionID)) && p() && e('『name』不能为空。'); // 测试name为空 -$db->restoreDB(); \ No newline at end of file +r($execution->batchUpdateObject($noName, $executionID)) && p('name:0') && e('『执行名称』不能为空。'); // 测试name为空 +$db->restoreDB(); diff --git a/test/model/execution/buildburndata.php b/test/model/execution/buildburndata.php index fcd757c70a..b5e94e8654 100755 --- a/test/model/execution/buildburndata.php +++ b/test/model/execution/buildburndata.php @@ -12,7 +12,7 @@ pid=1 敏捷执行燃尽图数据 >> 7/1 瀑布执行燃尽图数据 >> [0,0,0,0,0,0,0,0,0,0,0] -看板执行燃尽图数据 >> [20,18,16,14,12,10,8,6,4,2,0] +看板执行燃尽图数据 >> [0,0,0,0,0,0,0,0,0,0,0] 结果统计 >> 3 */ @@ -23,5 +23,5 @@ $count = array('0', '1'); $execution = new executionTest(); r($execution->buildBurnDataTest($executionIDList[0], $count[0])) && p('labels:0') && e('7/1'); // 敏捷执行燃尽图数据 r($execution->buildBurnDataTest($executionIDList[1], $count[0])) && p('burnLine') && e('[0,0,0,0,0,0,0,0,0,0,0]'); // 瀑布执行燃尽图数据 -r($execution->buildBurnDataTest($executionIDList[2], $count[0])) && p('baseLine') && e('[20,18,16,14,12,10,8,6,4,2,0]'); // 看板执行燃尽图数据 -r($execution->buildBurnDataTest($executionIDList[0], $count[1])) && p() && e('3'); // 结果统计 \ No newline at end of file +r($execution->buildBurnDataTest($executionIDList[2], $count[0])) && p('baseLine') && e('[0,0,0,0,0,0,0,0,0,0,0]'); // 看板执行燃尽图数据 +r($execution->buildBurnDataTest($executionIDList[0], $count[1])) && p() && e('3'); // 结果统计 diff --git a/test/model/execution/computeburn.php b/test/model/execution/computeburn.php index cf5ffb99f1..16681e385f 100755 --- a/test/model/execution/computeburn.php +++ b/test/model/execution/computeburn.php @@ -11,7 +11,7 @@ cid=1 pid=1 正常初始化 >> project600 -初始化后数据统计 >> 516 +初始化后数据统计 >> 361 */ @@ -19,4 +19,4 @@ $count = array('0','1'); $execution = new executionTest(); r($execution->computeBurnTest($count[0])) && p('700:executionName') && e('project600'); // 正常初始化 -r($execution->computeBurnTest($count[1])) && p() && e('516'); // 初始化后数据统计 \ No newline at end of file +r($execution->computeBurnTest($count[1])) && p() && e('361'); // 初始化后数据统计 diff --git a/test/model/execution/create.php b/test/model/execution/create.php index 12e44ada93..1a7f65c824 100755 --- a/test/model/execution/create.php +++ b/test/model/execution/create.php @@ -19,11 +19,10 @@ pid=1 测试创建看板公开执行 >> 新增公开看板执行code,kanban 测试创建迭代团队分配 >> pd58,pd72,dev10,dev10 测试不输入项目 >> 所属项目不能为空。 -测试不输入产品 >> 关联产品不能为空! 测试不输入执行名称 >> 『执行名称』不能为空。 测试不输入执行代号 >> 『执行代号』不能为空。 -测试一样的执行名称 >> 『执行名称』已经有『新增私有敏捷执行』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。 -测试一样的执行代号 >> 『执行代号』已经有『新增私有敏捷执行code』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。 +测试一样的执行名称 >> 『执行名称』已经有『新增私有敏捷执行』这条记录了。 +测试一样的执行代号 >> 『执行代号』已经有『新增私有敏捷执行code』这条记录了。 */ @@ -56,10 +55,9 @@ r($task->createObject($prvExecution_kanban, $projectIDList[3], $dayNum, $days)) r($task->createObject($openExecution_kanban, $projectIDList[3], $dayNum, $days)) && p('code,type') && e('新增公开看板执行code,kanban'); // 测试创建看板公开执行 r($task->createObject($teamExecution, $projectIDList[1], $dayNum, $days)) && p('PO,QD,PM,RD') && e('pd58,pd72,dev10,dev10'); // 测试创建迭代团队分配 r($task->createObject($prvExecution, '', $dayNum, $days)) && p('message:0') && e('所属项目不能为空。'); // 测试不输入项目 -r($task->createObject($noProductID, $projectIDList[1], $dayNum, $days)) && p('message:0') && e('关联产品不能为空!'); // 测试不输入产品 r($task->createObject($noName, $projectIDList[1], $dayNum, $days)) && p('name:0') && e('『执行名称』不能为空。'); // 测试不输入执行名称 r($task->createObject($noCode, $projectIDList[1], $dayNum, $days)) && p('code:0') && e('『执行代号』不能为空。'); // 测试不输入执行代号 -r($task->createObject($equallyName, $projectIDList[1], $dayNum, $days)) && p('name:0') && e('『执行名称』已经有『新增私有敏捷执行』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。'); // 测试一样的执行名称 -r($task->createObject($equallyCode, $projectIDList[1], $dayNum, $days)) && p('code:0') && e('『执行代号』已经有『新增私有敏捷执行code』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。'); // 测试一样的执行代号 +r($task->createObject($equallyName, $projectIDList[1], $dayNum, $days)) && p('name:0') && e('『执行名称』已经有『新增私有敏捷执行』这条记录了。'); // 测试一样的执行名称 +r($task->createObject($equallyCode, $projectIDList[1], $dayNum, $days)) && p('code:0') && e('『执行代号』已经有『新增私有敏捷执行code』这条记录了。'); // 测试一样的执行代号 -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/execution/getbranchbyproduct.php b/test/model/execution/getbranchbyproduct.php index d53992c944..7d9595117b 100755 --- a/test/model/execution/getbranchbyproduct.php +++ b/test/model/execution/getbranchbyproduct.php @@ -10,8 +10,8 @@ title=executionModel->getBranchByProduct(); cid=1 pid=1 -正常产品分支统计 >> 0 -分支产品分支查看 >> 分支2 +正常产品分支统计 >> 1 +分支产品分支查看 >> 分支1 分支产品分支统计 >> 1 */ @@ -20,6 +20,6 @@ $productIDList = array('1', '41'); $count = array('0', '1'); $execution = new executionTest(); -r($execution->getBranchByProductTest($productIDList[0],$count[1])) && p() && e('0'); //正常产品分支统计 -r($execution->getBranchByProductTest($productIDList[1],$count[0])) && p('41:2') && e('分支2'); //分支产品分支查看 -r($execution->getBranchByProductTest($productIDList[1],$count[1])) && p() && e('1'); //分支产品分支统计 \ No newline at end of file +r($execution->getBranchByProductTest($productIDList[0], $count[1])) && p() && e('1'); //正常产品分支统计 +r($execution->getBranchByProductTest($productIDList[1], $count[0])) && p('41:1') && e('分支1'); //分支产品分支查看 +r($execution->getBranchByProductTest($productIDList[1], $count[1])) && p() && e('1'); //分支产品分支统计 diff --git a/test/model/execution/getburndataflot.php b/test/model/execution/getburndataflot.php index 61b02ca1b6..efae0ee514 100755 --- a/test/model/execution/getburndataflot.php +++ b/test/model/execution/getburndataflot.php @@ -12,14 +12,13 @@ pid=1 敏捷执行查询统计 >> 3 瀑布执行查询统计 >> 3 -看板执行查询统计 >> 3 +看板执行查询统计 >> 0 */ $executionIDList = array('101', '131', '161'); -$count = array('0','1'); $execution = new executionTest(); -r($execution->getBurnDataFlotTest($executionIDList[0], $count[1])) && p() && e('3'); // 敏捷执行查询统计 -r($execution->getBurnDataFlotTest($executionIDList[1], $count[1])) && p() && e('3'); // 瀑布执行查询统计 -r($execution->getBurnDataFlotTest($executionIDList[2], $count[1])) && p() && e('3'); // 看板执行查询统计 \ No newline at end of file +r($execution->getBurnDataFlotTest($executionIDList[0])) && p() && e('3'); // 敏捷执行查询统计 +r($execution->getBurnDataFlotTest($executionIDList[1])) && p() && e('3'); // 瀑布执行查询统计 +r($execution->getBurnDataFlotTest($executionIDList[2])) && p() && e('0'); // 看板执行查询统计 diff --git a/test/model/execution/getchildexecutions.php b/test/model/execution/getchildexecutions.php index 2d12ee2382..8de2d620ef 100755 --- a/test/model/execution/getchildexecutions.php +++ b/test/model/execution/getchildexecutions.php @@ -19,5 +19,5 @@ $executionID = '131'; $count = array('0','1'); $execution = new executionTest(); -r($execution->getChildExecutionsTest($executionID,$count[0])) && p('701') && e('子阶段1'); // 查询子阶段 -r($execution->getChildExecutionsTest($executionID,$count[1])) && p() && e('1'); // 查询子阶段数量 \ No newline at end of file +r($execution->getChildExecutionsTest($executionID, $count[0])) && p('701:name') && e('子阶段1'); // 查询子阶段 +r($execution->getChildExecutionsTest($executionID, $count[1])) && p() && e('1'); // 查询子阶段数量 diff --git a/test/model/execution/getproductgrouplisttest.php b/test/model/execution/getproductgrouplisttest.php index 69c1d5d4f0..b7adc95881 100755 --- a/test/model/execution/getproductgrouplisttest.php +++ b/test/model/execution/getproductgrouplisttest.php @@ -11,12 +11,12 @@ cid=1 pid=1 查询当前用户访问的产品相关项目集 >> 项目集10 -查询当前用户访问的产品相关数量 >> 101 +查询当前用户访问的产品相关数量 >> 121 */ $count = array('0','1'); $execution = new executionTest(); -r($execution->getProductGroupListTest($count[0])) && p('9:name') && e('项目集10'); // 查询当前用户访问的产品相关项目集 -r($execution->getProductGroupListTest($count[1])) && p() && e('101'); // 查询当前用户访问的产品相关数量 \ No newline at end of file +r($execution->getProductGroupListTest($count[0])) && p('9:name') && e('项目集10'); // 查询当前用户访问的产品相关项目集 +r($execution->getProductGroupListTest($count[1])) && p() && e('121'); // 查询当前用户访问的产品相关数量 diff --git a/test/model/execution/isclickable.php b/test/model/execution/isclickable.php index e5362c804d..8003456c30 100755 --- a/test/model/execution/isclickable.php +++ b/test/model/execution/isclickable.php @@ -27,13 +27,13 @@ suspended状态执行close按钮检查 >> 检查通过 suspended状态执行suspend按钮检查 >> 检查不通过 suspended状态执行putoff按钮检查 >> 检查不通过 suspended状态执行activate按钮检查 >> 检查通过 -suspended状态执行delete按钮检查 >> 检查不通过 +suspended状态执行delete按钮检查 >> 检查通过 closed状态执行start按钮检查 >> 检查不通过 closed状态执行close按钮检查 >> 检查不通过 closed状态执行suspend按钮检查 >> 检查不通过 closed状态执行putoff按钮检查 >> 检查不通过 closed状态执行activate按钮检查 >> 检查通过 -closed状态执行delete按钮检查 >> 检查不通过 +closed状态执行delete按钮检查 >> 检查通过 */ @@ -67,10 +67,10 @@ r($execution->isClickableTest($suspendedExecution, $actionList[1])) && p() && e( r($execution->isClickableTest($suspendedExecution, $actionList[2])) && p() && e('检查不通过'); // suspended状态执行suspend按钮检查 r($execution->isClickableTest($suspendedExecution, $actionList[3])) && p() && e('检查不通过'); // suspended状态执行putoff按钮检查 r($execution->isClickableTest($suspendedExecution, $actionList[4])) && p() && e('检查通过'); // suspended状态执行activate按钮检查 -r($execution->isClickableTest($suspendedExecution, $actionList[5])) && p() && e('检查不通过'); // suspended状态执行delete按钮检查 +r($execution->isClickableTest($suspendedExecution, $actionList[5])) && p() && e('检查通过'); // suspended状态执行delete按钮检查 r($execution->isClickableTest($closedExecution, $actionList[0])) && p() && e('检查不通过'); // closed状态执行start按钮检查 r($execution->isClickableTest($closedExecution, $actionList[1])) && p() && e('检查不通过'); // closed状态执行close按钮检查 r($execution->isClickableTest($closedExecution, $actionList[2])) && p() && e('检查不通过'); // closed状态执行suspend按钮检查 -r($execution->isClickableTest($closedExecution, $actionList[3])) && p() && e('检查不通过'); // closed状态执行putoff按钮检查 +r($execution->isClickableTest($closedExecution, $actionList[3])) && p() && e('检查通过'); // closed状态执行putoff按钮检查 r($execution->isClickableTest($closedExecution, $actionList[4])) && p() && e('检查通过'); // closed状态执行activate按钮检查 -r($execution->isClickableTest($closedExecution, $actionList[5])) && p() && e('检查不通过'); // closed状态执行delete按钮检查 \ No newline at end of file +r($execution->isClickableTest($closedExecution, $actionList[5])) && p() && e('检查不通过'); // closed状态执行delete按钮检查 diff --git a/test/model/execution/linkcases.php b/test/model/execution/linkcases.php index a241abc112..740282cc36 100755 --- a/test/model/execution/linkcases.php +++ b/test/model/execution/linkcases.php @@ -14,7 +14,7 @@ pid=1 敏捷执行关联用例 >> 101,1,1 瀑布执行关联用例 >> 131,43,169 看板执行关联用例 >> 161,68,269 -敏捷执行关联用例统计 >> 4 +敏捷执行关联用例统计 >> 8 瀑布执行关联用例统计 >> 4 看板执行关联用例统计 >> 4 @@ -29,8 +29,8 @@ $execution = new executionTest(); r($execution->linkCasesTest($executionIDList[0], $count[0], $products[0], $stories[0])) && p('0:project,product,case') && e('101,1,1'); // 敏捷执行关联用例 r($execution->linkCasesTest($executionIDList[1], $count[0], $products[1], $stories[1])) && p('0:project,product,case') && e('131,43,169'); // 瀑布执行关联用例 r($execution->linkCasesTest($executionIDList[2], $count[0], $products[2], $stories[2])) && p('0:project,product,case') && e('161,68,269'); // 看板执行关联用例 -r($execution->linkCasesTest($executionIDList[0], $count[1], $products[0], $stories[0])) && p() && e('4'); // 敏捷执行关联用例统计 +r($execution->linkCasesTest($executionIDList[0], $count[1], $products[0], $stories[0])) && p() && e('8'); // 敏捷执行关联用例统计 r($execution->linkCasesTest($executionIDList[1], $count[1], $products[1], $stories[1])) && p() && e('4'); // 瀑布执行关联用例统计 r($execution->linkCasesTest($executionIDList[2], $count[1], $products[2], $stories[2])) && p() && e('4'); // 看板执行关联用例统计 -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/execution/linkstory.php b/test/model/execution/linkstory.php index c350b3abbd..e5dba1eb0e 100755 --- a/test/model/execution/linkstory.php +++ b/test/model/execution/linkstory.php @@ -14,9 +14,9 @@ pid=1 敏捷执行关联需求 >> 101,1,4 瀑布执行关联需求 >> 131,1,4 看板执行关联需求 >> 161,1,4 -敏捷执行关联需求统计 >> 3 -瀑布执行关联需求统计 >> 3 -看板执行关联需求统计 >> 3 +敏捷执行关联需求统计 >> 1 +瀑布执行关联需求统计 >> 1 +看板执行关联需求统计 >> 1 */ @@ -31,8 +31,8 @@ $execution = new executionTest(); r($execution->linkStoryTest($executionIDList[0], $count[0], $story)) && p('0:project,product,story') && e('101,1,4'); // 敏捷执行关联需求 r($execution->linkStoryTest($executionIDList[1], $count[0], $story)) && p('0:project,product,story') && e('131,1,4'); // 瀑布执行关联需求 r($execution->linkStoryTest($executionIDList[2], $count[0], $story)) && p('0:project,product,story') && e('161,1,4'); // 看板执行关联需求 -r($execution->linkStoryTest($executionIDList[0], $count[1], $story)) && p() && e('3'); // 敏捷执行关联需求统计 -r($execution->linkStoryTest($executionIDList[1], $count[1], $story)) && p() && e('3'); // 瀑布执行关联需求统计 -r($execution->linkStoryTest($executionIDList[2], $count[1], $story)) && p() && e('3'); // 看板执行关联需求统计 +r($execution->linkStoryTest($executionIDList[0], $count[1], $story)) && p() && e('1'); // 敏捷执行关联需求统计 +r($execution->linkStoryTest($executionIDList[1], $count[1], $story)) && p() && e('1'); // 瀑布执行关联需求统计 +r($execution->linkStoryTest($executionIDList[2], $count[1], $story)) && p() && e('1'); // 看板执行关联需求统计 -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/execution/processburndata.php b/test/model/execution/processburndata.php index 7d380b72c0..acc9c4eac0 100755 --- a/test/model/execution/processburndata.php +++ b/test/model/execution/processburndata.php @@ -10,9 +10,9 @@ title=测试executionModel->processBurnDataTest(); cid=1 pid=1 -敏捷执行查询统计 >> 29 -瀑布执行查询统计 >> 59 -看板执行查询统计 >> 62 +敏捷执行查询统计 >> 30 +瀑布执行查询统计 >> 60 +看板执行查询统计 >> 67 错误时间查询统计 >> 0 */ @@ -24,7 +24,7 @@ $end = array('2022-03-22','2022-01-15'); $count = array('0','1'); $execution = new executionTest(); -r($execution->processBurnDataTest($executionIDList[0], $itemCounts[0], $begin[0], $end[0], $count[1])) && p() && e('29'); // 敏捷执行查询统计 -r($execution->processBurnDataTest($executionIDList[1], $itemCounts[1], $begin[0], $end[0], $count[1])) && p() && e('59'); // 瀑布执行查询统计 -r($execution->processBurnDataTest($executionIDList[2], $itemCounts[2], $begin[0], $end[0], $count[1])) && p() && e('62'); // 看板执行查询统计 -r($execution->processBurnDataTest($executionIDList[2], $itemCounts[2], $begin[1], $end[1], $count[1])) && p() && e('0'); // 错误时间查询统计 \ No newline at end of file +r($execution->processBurnDataTest($executionIDList[0], $itemCounts[0], $begin[0], $end[0], $count[1])) && p() && e('30'); // 敏捷执行查询统计 +r($execution->processBurnDataTest($executionIDList[1], $itemCounts[1], $begin[0], $end[0], $count[1])) && p() && e('60'); // 瀑布执行查询统计 +r($execution->processBurnDataTest($executionIDList[2], $itemCounts[2], $begin[0], $end[0], $count[1])) && p() && e('67'); // 看板执行查询统计 +r($execution->processBurnDataTest($executionIDList[2], $itemCounts[2], $begin[1], $end[1], $count[1])) && p() && e('0'); // 错误时间查询统计 diff --git a/test/model/execution/unlinkmember.php b/test/model/execution/unlinkmember.php index 2964434b5e..b53603f8ba 100755 --- a/test/model/execution/unlinkmember.php +++ b/test/model/execution/unlinkmember.php @@ -14,8 +14,8 @@ pid=1 敏捷执行解除团队成员 >> po82,研发 敏捷执行解除团队成员后统计 >> 1 瀑布执行解除团队成员 >> 0 -看板执行解除团队成员 >> test52,测试 -看板执行解除团队成员后统计 >> 1 +看板执行解除团队成员 >> 0 +看板执行解除团队成员后统计 >> 0 */ @@ -27,6 +27,6 @@ $execution = new executionTest(); r($execution->unlinkMemberTest($executionIDList[0], $accountList[0], $count[0])) && p('0:account,role') && e('po82,研发'); // 敏捷执行解除团队成员 r($execution->unlinkMemberTest($executionIDList[0], $accountList[0], $count[1])) && p() && e('1'); // 敏捷执行解除团队成员后统计 r($execution->unlinkMemberTest($executionIDList[1], $accountList[1], $count[0])) && p() && e('0'); // 瀑布执行解除团队成员 -r($execution->unlinkMemberTest($executionIDList[2], $accountList[2], $count[0])) && p('0:account,role') && e('test52,测试'); // 看板执行解除团队成员 -r($execution->unlinkMemberTest($executionIDList[2], $accountList[2], $count[1])) && p() && e('1'); // 看板执行解除团队成员后统计 -$db->restoreDB(); \ No newline at end of file +r($execution->unlinkMemberTest($executionIDList[2], $accountList[2], $count[0])) && p('0:account,role') && e('0'); // 看板执行解除团队成员 +r($execution->unlinkMemberTest($executionIDList[2], $accountList[2], $count[1])) && p() && e('0'); // 看板执行解除团队成员后统计 +$db->restoreDB(); diff --git a/test/model/execution/unlinkstory.php b/test/model/execution/unlinkstory.php index 70de49b8ce..6daa4eec8f 100755 --- a/test/model/execution/unlinkstory.php +++ b/test/model/execution/unlinkstory.php @@ -11,12 +11,12 @@ title=测试executionModel->unlinkStoryTest(); cid=1 pid=1 -敏捷执行解除关联需求 >> 101,81,324 +敏捷执行解除关联需求 >> 0 瀑布执行解除关联需求 >> 131,1,4 看板执行解除关联需求 >> 161,1,4 -敏捷执行关联需求统计 >> 2 -瀑布执行关联需求统计 >> 2 -看板执行关联需求统计 >> 2 +敏捷执行关联需求统计 >> 0 +瀑布执行关联需求统计 >> 1 +看板执行关联需求统计 >> 1 */ @@ -28,11 +28,11 @@ $count = array('0', '1'); $story = array('stories' => $stories, 'products' => $products); $execution = new executionTest(); -r($execution->unlinkStoryTest($executionIDList[0], $count[0], $stories[0], $story)) && p('0:project,product,story') && e('101,81,324'); // 敏捷执行解除关联需求 -r($execution->unlinkStoryTest($executionIDList[1], $count[0], $stories[1], $story)) && p('0:project,product,story') && e('131,1,4'); // 瀑布执行解除关联需求 -r($execution->unlinkStoryTest($executionIDList[2], $count[0], $stories[2], $story)) && p('0:project,product,story') && e('161,1,4'); // 看板执行解除关联需求 -r($execution->unlinkStoryTest($executionIDList[0], $count[1], $stories[0], $story)) && p() && e('2'); // 敏捷执行关联需求统计 -r($execution->unlinkStoryTest($executionIDList[1], $count[1], $stories[1], $story)) && p() && e('2'); // 瀑布执行关联需求统计 -r($execution->unlinkStoryTest($executionIDList[2], $count[1], $stories[2], $story)) && p() && e('2'); // 看板执行关联需求统计 +r($execution->unlinkStoryTest($executionIDList[0], $count[0], $stories[0], $story)) && p('0:project,product,story') && e('0'); // 敏捷执行解除关联需求 +r($execution->unlinkStoryTest($executionIDList[1], $count[0], $stories[1], $story)) && p('0:project,product,story') && e('131,1,4'); // 瀑布执行解除关联需求 +r($execution->unlinkStoryTest($executionIDList[2], $count[0], $stories[2], $story)) && p('0:project,product,story') && e('161,1,4'); // 看板执行解除关联需求 +r($execution->unlinkStoryTest($executionIDList[0], $count[1], $stories[0], $story)) && p() && e('0'); // 敏捷执行关联需求统计 +r($execution->unlinkStoryTest($executionIDList[1], $count[1], $stories[1], $story)) && p() && e('1'); // 瀑布执行关联需求统计 +r($execution->unlinkStoryTest($executionIDList[2], $count[1], $stories[2], $story)) && p() && e('1'); // 看板执行关联需求统计 -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/execution/update.php b/test/model/execution/update.php index 352cb1123e..e329814c5d 100755 --- a/test/model/execution/update.php +++ b/test/model/execution/update.php @@ -11,7 +11,7 @@ title=测试executionModel->update(); cid=1 pid=1 -测试重复迭代code >> 『迭代代号』已经有『project1』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。 +测试重复迭代code >> 『迭代代号』已经有『project1』这条记录了。 测试修改迭代名称 >> name,迭代1,迭代名修改 测试修改迭代项目为瀑布项目 >> project,11,41 测试修改迭代项目为看板项目 >> project,41,71 @@ -44,7 +44,7 @@ $noCode = array('code' => ''); $repeatcode = array('name' => '迭代名修改1'); $execution = new executionTest(); -r($execution->updateObject($executionIDList[0], $repeatcode)) && p('code:0') && e('『迭代代号』已经有『project1』这条记录了。如果您确定该记录已删除,请到后台-系统-数据-回收站还原。'); // 测试重复迭代code +r($execution->updateObject($executionIDList[0], $repeatcode)) && p('code:0') && e('『迭代代号』已经有『project1』这条记录了。'); // 测试重复迭代code r($execution->updateObject($executionIDList[0], $changeName)) && p('0:field,old,new') && e('name,迭代1,迭代名修改'); // 测试修改迭代名称 r($execution->updateObject($executionIDList[0], $changeStage)) && p('0:field,old,new') && e('project,11,41'); // 测试修改迭代项目为瀑布项目 r($execution->updateObject($executionIDList[0], $changeKanban)) && p('0:field,old,new') && e('project,41,71'); // 测试修改迭代项目为看板项目 @@ -57,4 +57,4 @@ r($execution->updateObject($executionIDList[1], $noName)) && p('name:0') r($execution->updateObject($executionIDList[1], $noCode)) && p('code:0') && e('『迭代代号』不能为空。'); // 测试修改code为空 r($execution->updateObject($executionIDList[1], $noChange)) && p() && e('没有数据更新'); // 测试无修改 -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/todo/batchcreate.php b/test/model/todo/batchcreate.php index 06ffc578f9..f412b75a6a 100755 --- a/test/model/todo/batchcreate.php +++ b/test/model/todo/batchcreate.php @@ -23,8 +23,8 @@ $descs = array('desc1', 'desc2', 'desc3', 'desc4', '' , '', '', ''); $begins = array('0830', '0900', '0930', '1000', '1030', '1100', '1130', '1200'); $ends = array('0900', '0930', '1000','1030', '1100', '1130', '1200', '1230'); $bugs = array('2' => '313'); - -$noname_create = array('types' => $types, 'pris' => $pris, 'names' => $names, 'descs' => $descs, 'begins' => $begins, 'ends' => $ends); +$assignedTos = array('user1', 'ditto', 'ditto', 'ditto', 'ditto', 'ditto', 'ditto', 'ditto',); +$noname_create = array('types' => $types, 'pris' => $pris, 'names' => $names, 'descs' => $descs, 'begins' => $begins, 'ends' => $ends, 'assignedTos' => $assignedTos); $names = array('批量创建待办4','批量创建待办5','批量创建待办6', '批量创建待办7', '', '', '', ''); $types = array('bug', 'story', 'task', 'testtask', 'custom', 'custom', 'custom', 'custom'); @@ -33,10 +33,10 @@ $stories = array('2' => '1'); $tasks = array('3' => '1'); $testtasks = array('4' => '1'); -$except_create = array('types' => $types, 'pris' => $pris, 'names' => $names, 'descs' => $descs, 'begins' => $begins, 'ends' => $ends, 'bugs' => $bugs, 'stories' => $stories, 'tasks' => $tasks, 'testtasks' => $testtasks); +$except_create = array('types' => $types, 'pris' => $pris, 'names' => $names, 'descs' => $descs, 'begins' => $begins, 'ends' => $ends, 'bugs' => $bugs, 'stories' => $stories, 'tasks' => $tasks, 'testtasks' => $testtasks, 'assignedTos' => $assignedTos); $todo = new todoTest(); r($todo->batchCreateTest($noname_create)) && p('2006:name,desc,pri,type,idvalue;2007:name,desc,pri,type,idvalue;2008:name,desc,pri,type,idvalue') && e('批量创建待办1,desc1,1,custom,0;批量创建待办2,desc2,2,custom,0;批量创建待办3,desc4,4,custom,0'); // 批量创建有个没有名字的待办 -r($todo->batchCreateTest($except_create)) && p('2009:name,desc,pri,type,idvalue;2010:name,desc,pri,type,idvalue;2011:name,desc,pri,type,idvalue;2012:name,desc,pri,type,idvalue') && e('测试单转Bug13,desc1,1,bug,313;用户需求版本一61,desc2,2,story,1;开发任务11,desc3,3,task,1;测试单1,desc4,4,testtask,1'); // 批量创建的待办 -$db->restoreDB(); \ No newline at end of file +r($todo->batchCreateTest($except_create)) && p('2009:name,desc,pri,type,idvalue;2010:name,desc,pri,type,idvalue;2011:name,desc,pri,type,idvalue;2012:name,desc,pri,type,idvalue') && e('测试单转Bug13,desc1,1,bug,313;软件需求版本一551,desc2,2,story,1;开发任务11,desc3,3,task,1;测试单1,desc4,4,testtask,1'); // 批量创建的待办 +$db->restoreDB(); diff --git a/test/model/todo/batchupdate.php b/test/model/todo/batchupdate.php index 3c8c5434e4..791074b8e4 100755 --- a/test/model/todo/batchupdate.php +++ b/test/model/todo/batchupdate.php @@ -32,4 +32,4 @@ $todo = new todoTest(); r($todo->batchUpdateTest($changeType, '3')) && p('0:field,old,new') && e('type,task,custom'); // 批量修改todo类型 r($todo->batchUpdateTest($changePri, '2')) && p('0:field,old,new') && e('pri,2,1'); // 批量修改todo优先级 r($todo->batchUpdateTest($changeStatus, '1')) && p('0:field,old,new') && e('status,wait,doing'); // 批量修改todo状态 -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/tools/packDeb.php b/tools/packDeb.php index 25545d2555..8df6633a86 100644 --- a/tools/packDeb.php +++ b/tools/packDeb.php @@ -10,13 +10,13 @@ $fileList[] = "{$basePath}/ZenTaoPMS.$pmsVersion.php5.4_5.6.zip"; $fileList[] = "{$basePath}/ZenTaoPMS.$pmsVersion.php7.0.zip"; $fileList[] = "{$basePath}/ZenTaoPMS.$pmsVersion.php7.1.zip"; $fileList[] = "{$basePath}/ZenTaoPMS.$pmsVersion.php7.2_7.4.zip"; -$fileList[] = "{$basePath}/ZenTaoPMS.$pmsVersion.php8.0.zip"; +$fileList[] = "{$basePath}/ZenTaoPMS.$pmsVersion.php8.1.zip"; $fileList[] = "{$basePath}/ZenTaoALM.$pmsVersion.int.php5.4_5.6.zip"; $fileList[] = "{$basePath}/ZenTaoALM.$pmsVersion.int.php7.0.zip"; $fileList[] = "{$basePath}/ZenTaoALM.$pmsVersion.int.php7.1.zip"; $fileList[] = "{$basePath}/ZenTaoALM.$pmsVersion.int.php7.2_7.4.zip"; -$fileList[] = "{$basePath}/ZenTaoALM.$pmsVersion.int.php8.0.zip"; +$fileList[] = "{$basePath}/ZenTaoALM.$pmsVersion.int.php8.1.zip"; foreach($fileList as $file) if(!file_exists($file)) echo basename($file) . " is not exists\n"; @@ -30,7 +30,7 @@ foreach(array('zh-cn', 'en') as $langType) $dirName = $langType == 'zh-cn' ? 'zentaopms' : 'zentaoalm'; /* Cycle the php versions. */ - foreach(array('5.4_5.6', '7.0', '7.1', '7.2_7.4', '8.0') as $phpVersion) + foreach(array('5.4_5.6', '7.0', '7.1', '7.2_7.4', '8.1') as $phpVersion) { /* File name. */ $workDir = "tmp/$packPrefix.{$version}.{$phpVersion}/"; diff --git a/tools/packRpm.php b/tools/packRpm.php index 349b307df6..cb3e684f03 100644 --- a/tools/packRpm.php +++ b/tools/packRpm.php @@ -10,13 +10,13 @@ $fileList[] = "{$basePath}/ZenTaoPMS.$pmsVersion.php5.4_5.6.zip"; $fileList[] = "{$basePath}/ZenTaoPMS.$pmsVersion.php7.0.zip"; $fileList[] = "{$basePath}/ZenTaoPMS.$pmsVersion.php7.1.zip"; $fileList[] = "{$basePath}/ZenTaoPMS.$pmsVersion.php7.2_7.4.zip"; -$fileList[] = "{$basePath}/ZenTaoPMS.$pmsVersion.php8.0.zip"; +$fileList[] = "{$basePath}/ZenTaoPMS.$pmsVersion.php8.1.zip"; $fileList[] = "{$basePath}/ZenTaoALM.$pmsVersion.int.php5.4_5.6.zip"; $fileList[] = "{$basePath}/ZenTaoALM.$pmsVersion.int.php7.0.zip"; $fileList[] = "{$basePath}/ZenTaoALM.$pmsVersion.int.php7.1.zip"; $fileList[] = "{$basePath}/ZenTaoALM.$pmsVersion.int.php7.2_7.4.zip"; -$fileList[] = "{$basePath}/ZenTaoALM.$pmsVersion.int.php8.0.zip"; +$fileList[] = "{$basePath}/ZenTaoALM.$pmsVersion.int.php8.1.zip"; foreach($fileList as $file) if(!file_exists($file)) echo basename($file) . " is not exists\n"; @@ -30,7 +30,7 @@ foreach(array('zh-cn', 'en') as $langType) $dirName = $langType == 'zh-cn' ? 'zentaopms' : 'zentaoalm'; /* Cycle the php versions. */ - foreach(array('5.4_5.6', '7.0', '7.1', '7.2_7.4', '8.0') as $phpVersion) + foreach(array('5.4_5.6', '7.0', '7.1', '7.2_7.4', '8.1') as $phpVersion) { /* File name. */ $workDir = "tmp/$packPrefix.{$version}.{$phpVersion}/"; diff --git a/tools/packZip.php b/tools/packZip.php index ea7abd8064..6709315202 100644 --- a/tools/packZip.php +++ b/tools/packZip.php @@ -21,11 +21,13 @@ $fileList[] = "{$basePath}/zentaobiz.php5.4_5.6.zip"; $fileList[] = "{$basePath}/zentaobiz.php7.0.zip"; $fileList[] = "{$basePath}/zentaobiz.php7.1.zip"; $fileList[] = "{$basePath}/zentaobiz.php7.2_7.4.zip"; +$fileList[] = "{$basePath}/zentaobiz.php8.1.zip"; $fileList[] = "{$basePath}/zentaomax.php5.4_5.6.zip"; $fileList[] = "{$basePath}/zentaomax.php7.0.zip"; $fileList[] = "{$basePath}/zentaomax.php7.1.zip"; $fileList[] = "{$basePath}/zentaomax.php7.2_7.4.zip"; +$fileList[] = "{$basePath}/zentaomax.php8.1.zip"; foreach($fileList as $file) if(!file_exists($file)) echo basename($file) . " is not exists\n"; @@ -33,10 +35,12 @@ foreach($fileList as $file) if(!file_exists($file)) echo basename($file) . " is `unzip {$basePath}/zentaobiz.php7.0.zip; mv biz zentaobiz.php7.0`; `unzip {$basePath}/zentaobiz.php7.1.zip; mv biz zentaobiz.php7.1`; `unzip {$basePath}/zentaobiz.php7.2_7.4.zip; mv biz zentaobiz.php7.2_7.4`; +`unzip {$basePath}/zentaobiz.php8.1.zip; mv biz zentaobiz.php8.1`; `unzip {$basePath}/zentaomax.php5.4_5.6.zip; mv max zentaomax.php5.4_5.6`; `unzip {$basePath}/zentaomax.php7.0.zip; mv max zentaomax.php7.0`; `unzip {$basePath}/zentaomax.php7.1.zip; mv max zentaomax.php7.1`; `unzip {$basePath}/zentaomax.php7.2_7.4.zip; mv max zentaomax.php7.2_7.4`; +`unzip {$basePath}/zentaomax.php8.1.zip; mv max zentaomax.php8.1`; /* Create shells to make zip format packages. */ $shellList = array(); @@ -48,12 +52,11 @@ foreach(array('zh-cn', 'en') as $langType) $dirName = $langType == 'zh-cn' ? 'zentaopms' : 'zentaoalm'; /* Cycle the php versions. */ - foreach(array('5.4_5.6', '7.0', '7.1', '7.2_7.4', '8.0') as $phpVersion) + foreach(array('5.4_5.6', '7.0', '7.1', '7.2_7.4', '8.1') as $phpVersion) { /* File name. */ - $workDir = "tmp/$packPrefix.{$version}.{$phpVersion}/"; - $shellName = $workDir . "make.sh"; - $encryptedPhpVersion = $phpVersion == '8.0' ? '7.2_7.4' : $phpVersion; + $workDir = "tmp/$packPrefix.{$version}.{$phpVersion}/"; + $shellName = $workDir . "make.sh"; echo "Creating $shellName\n"; mkdir($workDir, 0777, true); @@ -63,8 +66,8 @@ foreach(array('zh-cn', 'en') as $langType) //$command .= "if [ ! -d ../$dirName ]; then unzip ../../$packPrefix.{$version}.zip -d ../ ; fi\n"; $command .= "unzip ../../$packPrefix.{$version}.zip\n"; //$command .= "cp -raf ../$dirName .\n"; - $command .= "cp -rf ../../zentaobiz.php$encryptedPhpVersion/* $dirName/\n"; - $command .= "cp -rf ../../zentaomax.php$encryptedPhpVersion/* $dirName/\n"; + $command .= "cp -rf ../../zentaobiz.php$phpVersion/* $dirName/\n"; + $command .= "cp -rf ../../zentaomax.php$phpVersion/* $dirName/\n"; $command .= "zip -r ../../$packPrefix.{$version}.php{$phpVersion}.zip $dirName\n"; $command .= "rm -rf $dirName/\n"; diff --git a/www/index.php b/www/index.php index fe323ffc08..663fcbf618 100644 --- a/www/index.php +++ b/www/index.php @@ -68,7 +68,7 @@ if($app->clientDevice == 'mobile' and (strpos($config->version, 'pro') === 0 or if(!empty($_GET['display']) && $_GET['display'] == 'card') $config->default->view = 'xhtml'; $app->parseRequest(); -$app->setParams(); +if(!$app->setParams()) return; $common->checkPriv(); $common->checkIframe(); $app->loadModule(); diff --git a/www/js/zui/min.js b/www/js/zui/min.js index 9d996d2b1d..127ff363b4 100644 --- a/www/js/zui/min.js +++ b/www/js/zui/min.js @@ -1,7 +1,7 @@ /*! - * ZUI: ZUI for Zentao - v1.10.0 - 2022-08-04 + * ZUI: ZUI for Zentao - v1.10.0 - 2022-08-24 * http://openzui.com - * GitHub: https://github.com/easysoft/zui.git + * GitHub: https://github.com/easysoft/zui.git * Copyright (c) 2022 cnezsoft.com; Licensed MIT */ !function(t,e,i){"use strict";if("undefined"==typeof t)throw new Error("ZUI requires jQuery");Number.isNaN||"function"!=typeof isNaN||(Number.isNaN=isNaN),Number.parseInt||"function"!=typeof parseInt||(Number.parseInt=parseInt),Number.parseFloat||"function"!=typeof parseFloat||(Number.parseFloat=parseFloat),t.zui||(t.zui=function(e){t.isPlainObject(e)&&t.extend(t.zui,e)});var n={all:-1,left:0,middle:1,right:2},o=0;t.zui({uuid:function(t){var e=1e5*(Date.now()-1580890015292)+10*Math.floor(1e4*Math.random())+o++%10;return t?e:e.toString(36)},callEvent:function(t,e,n){if("function"==typeof t){n!==i&&(t=t.bind(n));var o=t(e);return e&&(e.result=o),!(o!==i&&!o)}return 1},strCode:function(t){var e=0;if("string"!=typeof t&&(t=String(t)),t&&t.length)for(var i=0;i=e.innerWidth?0:t.zui.getScrollbarSize()},fixBodyScrollbar:function(){if(t.zui.checkBodyScrollbar()){var e=t("body"),i=parseInt(e.css("padding-right")||0,10);return t.zui._scrollbarWidth&&e.css({paddingRight:i+t.zui._scrollbarWidth,overflowY:"hidden"}),!0}},resetBodyScrollbar:function(){t("body").css({paddingRight:"",overflowY:""})}}),t.fn.callEvent=function(e,n,o){var a=t(this),s=e.indexOf(".zui."),r=s<0?e:e.substring(0,s),l=t.Event(r,n);if(o===i&&s>0&&(o=a.data(e.substring(s+1))),o&&o.options){var c=o.options[r];"function"==typeof c&&(l.result=t.zui.callEvent(c,l,o))}return a.trigger(l),l},t.fn.callComEvent=function(t,e,n){n===i||Array.isArray(n)||(n=[n]);var o,a=this;a.trigger(e,n);var s=t.options[e];return s&&(o=s.apply(t,n)),o}}(jQuery,window,void 0),function(){"use strict";function t(t,e){return i&&!e?requestAnimationFrame(t):setTimeout(t,e||0)}function e(t){return i?cancelAnimationFrame(t):void clearTimeout(t)}var i="function"==typeof window.requestAnimationFrame;$.zui({asap:t,clearAsap:e})}(),function(t){"use strict";t.fn.fixOlPd=function(e){return e=e||10,this.each(function(){var i=t(this);i.css("paddingLeft",Math.ceil(Math.log10(i.children().length))*e+10)})},t(function(){t(".ol-pd-fix,.article ol").fixOlPd()})}(jQuery),+function(t){"use strict";var e='[data-dismiss="alert"]',i="zui.alert",n=function(i){t(i).on("click",e,this.close)};n.prototype.close=function(e){function n(){s.trigger("closed."+i).remove()}var o=t(this),a=o.attr("data-target");a||(a=o.attr("href"),a=a&&a.replace(/.*(?=#[^\s]*$)/,""));var s=t(a);e&&e.preventDefault(),s.length||(s=o.hasClass("alert")?o:o.parent()),s.trigger(e=t.Event("close."+i)),e.isDefaultPrevented()||(s.removeClass("in"),t.support.transition&&s.hasClass("fade")?s.one(t.support.transition.end,n).emulateTransitionEnd(150):n())};var o=t.fn.alert;t.fn.alert=function(e){return this.each(function(){var o=t(this),a=o.data(i);a||o.data(i,a=new n(this)),"string"==typeof e&&a[e].call(o)})},t.fn.alert.Constructor=n,t.fn.alert.noConflict=function(){return t.fn.alert=o,this},t(document).on("click."+i+".data-api",e,n.prototype.close)}(window.jQuery),function(t,e){"use strict";var i="zui.pager",n={page:1,recTotal:0,recPerPage:10},o={zh_cn:{pageOfText:"第 {0} 页",prev:"上一页",next:"下一页",first:"第一页",last:"最后一页","goto":"跳转",pageOf:"第 {page} 页",totalPage:"共 {totalPage} 页",totalCount:"共 {recTotal} 项",pageSize:"每页 {recPerPage} 项",itemsRange:"第 {start} ~ {end} 项",pageOfTotal:"第 {page}/{totalPage} 页"},zh_tw:{pageOfText:"第 {0} 頁",prev:"上一頁",next:"下一頁",first:"第一頁",last:"最後一頁","goto":"跳轉",pageOf:"第 {page} 頁",totalPage:"共 {totalPage} 頁",totalCount:"共 {recTotal} 項",pageSize:"每頁 {recPerPage} 項",itemsRange:"第 {start} ~ {end} 項",pageOfTotal:"第 {page}/{totalPage} 頁"},en:{pageOfText:"Page {0}",prev:"Prev",next:"Next",first:"First",last:"Last","goto":"Goto",pageOf:"Page {page}",totalPage:"{totalPage} pages",totalCount:"Total: {recTotal} items",pageSize:"{recPerPage} per page",itemsRange:"From {start} to {end}",pageOfTotal:"Page {page} of {totalPage}"}},a=function(e,n){var s=this;s.name=i,s.$=t(e),n=s.options=t.extend({},a.DEFAULTS,this.$.data(),n),s.langName=n.lang||t.zui.clientLang(),s.lang=t.zui.getLangData(i,s.langName,o),s.state={},s.set(n.page,n.recTotal,n.recPerPage,!0),s.$.on("click",".pager-goto-btn",function(){var e=t(this).closest(".pager-goto"),i=parseInt(e.find(".pager-goto-input").val());NaN!==i&&s.set(i)}).on("click",".pager-item",function(){var e=t(this).data("page");"number"==typeof e&&e>0&&s.set(e)}).on("click",".pager-size-menu [data-size]",function(){var e=t(this).data("size");"number"==typeof e&&e>0&&s.set(-1,-1,e)})};a.prototype.set=function(e,i,o,a){var s=this;"object"==typeof e&&null!==e&&(o=e.recPerPage,i=e.recTotal,e=e.page);var r=s.state;r||(r=t.extend({},n));var l=t.extend({},r);return"number"==typeof o&&o>0&&(r.recPerPage=o),"number"==typeof i&&i>=0&&(r.recTotal=i),"number"==typeof e&&e>=0&&(r.page=e),r.totalPage=r.recTotal&&r.recPerPage?Math.ceil(r.recTotal/r.recPerPage):1,r.page=Math.max(0,Math.min(r.page,r.totalPage)),r.pageRecCount=r.recTotal,r.page&&r.recTotal&&(r.page1&&(r.pageRecCount=r.recTotal-r.recPerPage*(r.page-1))),r.skip=r.page>1?(r.page-1)*r.recPerPage:0,r.start=r.skip+1,r.end=r.skip+r.pageRecCount,r.prev=r.page>1?r.page-1:0,r.next=r.page').attr("href",i?a.createLink(i,a.state):"###").html(n);return o||(s=t("
  • ").append(s).toggleClass("active",i===a.state.page).toggleClass("disabled",!i||i===a.state.page)),s},a.prototype.createNavItems=function(t){var i=this,n=i.$,o=i.state,a=o.totalPage,s=o.page,r=function(t,o){if(t===!1)return void n.append(i.createLinkItem(0,o||i.options.navEllipsisItem));o===e&&(o=t);for(var a=t;a<=o;++a)n.append(i.createLinkItem(a))};t===e&&(t=i.options.maxNavCount||10),r(1),a>1&&(a<=t?r(2,a):sa-t+2?(r(!1),r(a-t+2,a)):(r(!1),r(s-Math.ceil((t-4)/2),s+Math.floor((t-4)/2)),r(!1),r(a)))},a.prototype.createGoto=function(){var e=this,i=this.state,n=t('
    ");return n},a.prototype.createSizeMenu=function(){var e=this,i=this.state,n=t(''),o=e.options.pageSizeOptions;"string"==typeof o&&(o=o.split(","));for(var a=0;a'+s+"
  • ").toggleClass("active",s===i.recPerPage);n.append(r)}return t('
    ').addClass(e.options.menuDirection).append(n)},a.prototype.createElement=function(e,i,n){var o=this,a=o.createLinkItem.bind(o),s=o.lang;switch(e){case"prev":return a(n.prev,s.prev);case"prev_icon":return a(n.prev,'');case"next":return a(n.next,s.next);case"next_icon":return a(n.next,'');case"first":return a(1,s.first);case"first_icon":return a(1,'');case"last":return a(n.totalPage,s.last);case"last_icon":return a(n.totalPage,'');case"space":case"|":return t('
  • ');case"nav":case"pages":return void o.createNavItems();case"total_text":return t(('
    '+s.totalCount+"
    ").format(n));case"page_text":return t(('
    '+s.pageOf+"
    ").format(n));case"total_page_text":return t(('
    '+s.totalPage+"
    ").format(n));case"page_of_total_text":return t(('
    '+s.pageOfTotal+"
    ").format(n));case"page_size_text":return t(('
    '+s.pageSize+"
    ").format(n));case"items_range_text":return t(('
    '+s.itemsRange+"
    ").format(n));case"goto":return o.createGoto();case"size_menu":return o.createSizeMenu();default:return t("
  • ").html(e.format(n))}},a.prototype.createLink=function(i,n){i===e&&(i=this.state.page),n===e&&(n=this.state);var o=this.options.linkCreator;return"string"==typeof o?o.format(t.extend({},n,{page:i})):"function"==typeof o?o(i,n):"#page="+i},a.prototype.render=function(e){var i=this,n=i.state,o=i.options.elementCreator||i.createElement,a=t.isPlainObject(o);e=e||i.elements||i.options.elements,"string"==typeof e&&(e=e.split(",")),i.elements=e,i.$.empty();for(var s=0;s").append(c)),i.$.append(c))}var h=null;return i.$.children("li").each(function(){var e=t(this),i=!!e.children(".pager-item").length;h?h.toggleClass("pager-item-right",!i):i&&e.addClass("pager-item-left"),h=i?e:null}),h&&h.addClass("pager-item-right"),i.$.callComEvent(i,"onRender",[n]),i},a.DEFAULTS=t.extend({elements:["first_icon","prev_icon","pages","next_icon","last_icon","page_of_total_text","items_range_text","total_text"],prevIcon:"icon-double-angle-left",nextIcon:"icon-double-angle-right",firstIcon:"icon-step-backward",lastIcon:"icon-step-forward",navEllipsisItem:'',maxNavCount:10,menuDirection:"dropdown",pageSizeOptions:[10,20,30,50,100]},n),t.fn.pager=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]()})},a.NAME=i,a.LANG=o,t.fn.pager.Constructor=a,t(function(){t('[data-ride="pager"]').pager()})}(jQuery,void 0),+function(t){"use strict";var e="zui.tab",i=function(e){this.element=t(e)};i.prototype.show=function(){var i=this.element,n=i.closest("ul:not(.dropdown-menu)"),o=i.attr("data-target")||i.attr("data-tab");if(o||(o=i.attr("href"),o=o&&o.replace(/.*(?=#[^\s]*$)/,"")),!i.parent("li").hasClass("active")){var a=n.find(".active:last a")[0],s=t.Event("show."+e,{relatedTarget:a});if(i.trigger(s),!s.isDefaultPrevented()){var r=t(o);this.activate(i.parent("li"),n),this.activate(r,r.parent(),function(){i.trigger({type:"shown."+e,relatedTarget:a})})}}},i.prototype.activate=function(e,i,n){function o(){a.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),e.addClass("active"),s?(e[0].offsetWidth,e.addClass("in")):e.removeClass("fade"),e.parent(".dropdown-menu")&&e.closest("li.dropdown").addClass("active"),n&&n()}var a=i.find("> .active"),s=n&&t.support.transition&&a.hasClass("fade");s?a.one(t.support.transition.end,o).emulateTransitionEnd(150):o(),a.removeClass("in")};var n=t.fn.tab;t.fn.tab=function(n){return this.each(function(){var o=t(this),a=o.data(e);a||o.data(e,a=new i(this)),"string"==typeof n&&a[n]()})},t.fn.tab.Constructor=i,t.fn.tab.noConflict=function(){return t.fn.tab=n,this},t(document).on("click.zui.tab.data-api",'[data-toggle="tab"], [data-tab]',function(e){e.preventDefault(),t(this).tab("show")})}(window.jQuery),+function(t){"use strict";function e(){var t=document.createElement("bootstrap"),e={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var i in e)if(void 0!==t.style[i])return{end:e[i]};return!1}t.fn.emulateTransitionEnd=function(e){var i=!1,n=this;t(this).one("bsTransitionEnd",function(){i=!0});var o=function(){i||t(n).trigger(t.support.transition.end)};return setTimeout(o,e),this},t(function(){t.support.transition=e(),t.support.transition&&(t.event.special.bsTransitionEnd={bindType:t.support.transition.end,delegateType:t.support.transition.end,handle:function(e){if(t(e.target).is(this))return e.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(t){"use strict";var e="zui.collapse",i=function(e,n){this.$element=t(e),this.options=t.extend({},i.DEFAULTS,n),this.transitioning=null,this.options.parent&&(this.$parent=t(this.options.parent)),this.options.toggle&&this.toggle()};i.DEFAULTS={toggle:!0},i.prototype.dimension=function(){var t=this.$element.hasClass("width");return t?"width":"height"},i.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var i=t.Event("show."+e);if(this.$element.trigger(i),!i.isDefaultPrevented()){var n=this.$parent&&this.$parent.find(".in");if(n&&n.length){var o=n.data(e);if(o&&o.transitioning)return;n.collapse("hide"),o||n.data(e,null)}var a=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[a](0),this.transitioning=1;var s=function(){this.$element.removeClass("collapsing").addClass("in")[a]("auto"),this.transitioning=0,this.$element.trigger("shown."+e)};if(!t.support.transition)return s.call(this);var r=t.camelCase(["scroll",a].join("-"));this.$element.one(t.support.transition.end,s.bind(this)).emulateTransitionEnd(350)[a](this.$element[0][r])}}},i.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var i=t.Event("hide."+e);if(this.$element.trigger(i),!i.isDefaultPrevented()){var n=this.dimension();this.$element[n](this.$element[n]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var o=function(){this.transitioning=0,this.$element.trigger("hidden."+e).removeClass("collapsing").addClass("collapse")};return t.support.transition?void this.$element[n](0).one(t.support.transition.end,o.bind(this)).emulateTransitionEnd(350):o.call(this)}}},i.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var n=t.fn.collapse;t.fn.collapse=function(n){return this.each(function(){var o=t(this),a=o.data(e),s=t.extend({},i.DEFAULTS,o.data(),"object"==typeof n&&n);a||o.data(e,a=new i(this,s)),"string"==typeof n&&a[n]()})},t.fn.collapse.Constructor=i,t.fn.collapse.noConflict=function(){return t.fn.collapse=n,this},t(document).on("click."+e+".data-api","[data-toggle=collapse]",function(i){var n,o=t(this),a=o.attr("data-target")||i.preventDefault()||(n=o.attr("href"))&&n.replace(/.*(?=#[^\s]+$)/,""),s=t(a),r=s.data(e),l=r?"toggle":o.data(),c=o.attr("data-parent"),h=c&&t(c);r&&r.transitioning||(h&&h.find('[data-toggle=collapse][data-parent="'+c+'"]').not(o).addClass("collapsed"),o[s.hasClass("in")?"addClass":"removeClass"]("collapsed")),s.collapse(l)})}(window.jQuery),function(t,e){"use strict";var i=1200,n=992,o=768,a=e(t),s=function(){var t=a.width();e("html").toggleClass("screen-desktop",t>=n&&t=i).toggleClass("screen-tablet",t>=o&&t=n)},r="",l=navigator.userAgent;l.match(/(iPad|iPhone|iPod)/i)?r+=" os-ios":l.match(/android/i)?r+=" os-android":l.match(/Win/i)?r+=" os-windows":l.match(/Mac/i)?r+=" os-mac":l.match(/Linux/i)?r+=" os-linux":l.match(/X11/i)&&(r+=" os-unix"),"ontouchstart"in document.documentElement&&(r+=" is-touchable"),e("html").addClass(r),a.resize(s),s()}(window,jQuery),function(t){"use strict";var e={zh_cn:'您的浏览器版本过低,无法体验所有功能,建议升级或者更换浏览器。 了解更多...',zh_tw:'您的瀏覽器版本過低,無法體驗所有功能,建議升級或者更换瀏覽器。了解更多...',en:'Your browser is too old, it has been unable to experience the colorful internet. We strongly recommend that you upgrade a better one. Learn more...'},i=function(){for(var t=!1,e=11;e>5;e--)if(this.isIE(e)){t=e;break}this.ie=t,this.cssHelper()};i.prototype.cssHelper=function(){var e=this.ie,i=t("html");i.toggleClass("ie",e).removeClass("ie-6 ie-7 ie-8 ie-9 ie-10"),e&&i.addClass("ie-"+e).toggleClass("gt-ie-7 gte-ie-8 support-ie",e>=8).toggleClass("lte-ie-7 lt-ie-8 outdated-ie",e<8).toggleClass("gt-ie-8 gte-ie-9",e>=9).toggleClass("lte-ie-8 lt-ie-9",e<9).toggleClass("gt-ie-9 gte-ie-10",e>=10).toggleClass("lte-ie-9 lt-ie-10",e<10).toggleClass("gt-ie-10 gte-ie-11",e>=11).toggleClass("lte-ie-10 lt-ie-11",e<11)},i.prototype.tip=function(i){var n=t("#browseHappyTip");n.length||(n=t('
    '),n.prependTo("body")),i||(i=t.zui.getLangData("zui.browser",t.zui.clientLang(),e),"object"==typeof i&&(i=i.tip)),n.find(".content").html(i)},i.prototype.isIE=function(t){if(11===t)return this.isIE11();if(10===t)return this.isIE10();if(!t&&(this.isIE11()||this.isIE10()))return!0;var e=document.createElement("b");return e.innerHTML="",1===e.getElementsByTagName("i").length},i.prototype.isIE10=function(){return navigator.appVersion.indexOf("MSIE 10")!==-1},i.prototype.isIE11=function(){var t=navigator.userAgent;return t.indexOf("Trident")!==-1&&t.indexOf("rv:11")!==-1},t.zui({browser:new i}),t(function(){t("body").hasClass("disabled-browser-tip")||t.zui.browser.ie&&t.zui.browser.ie<8&&t.zui.browser.tip()})}(jQuery),function(t){"use strict";var e=864e5,i=function(t){return t instanceof Date||("number"==typeof t&&t<1e10&&(t*=1e3),t=new Date(t)),t},n=function(t){return i(t).getTime()},o=function(t,e){t=i(t),void 0===e&&(e="yyyy-MM-dd hh:mm:ss");var n={"M+":t.getMonth()+1,"d+":t.getDate(),"h+":t.getHours(),"m+":t.getMinutes(),"s+":t.getSeconds(),"q+":Math.floor((t.getMonth()+3)/3),"S+":t.getMilliseconds()};/(y+)/i.test(e)&&(e=e.replace(RegExp.$1,(t.getFullYear()+"").substr(4-RegExp.$1.length)));for(var o in n)new RegExp("("+o+")").test(e)&&(e=e.replace(RegExp.$1,1==RegExp.$1.length?n[o]:("00"+n[o]).substr((""+n[o]).length)));return e},a=function(t,e){return t.setTime(t.getTime()+e),t},s=function(t,i){return a(t,i*e)},r=function(t){return new Date(i(t).getTime())},l=function(t){return t%4===0&&t%100!==0||t%400===0},c=function(t,e){return[31,l(t)?29:28,31,30,31,30,31,31,30,31,30,31][e]},h=function(t){return c(t.getFullYear(),t.getMonth())},d=function(t){return t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0),t},u=function(t,e){var i=t.getDate();return t.setDate(1),t.setMonth(t.getMonth()+e),t.setDate(Math.min(i,h(t))),t},p=function(t,e){e=e||1;for(var i=new Date(t.getTime());i.getDay()!=e;)i=s(i,-1);return d(i)},f=function(t,e){return t.toDateString()===e.toDateString()},g=function(t,e){var i=p(t),n=s(r(i),7);return e>=i&&e1){var i;if(2==arguments.length&&"object"==typeof e)for(var n in e)void 0!==e[n]&&(i=new RegExp("({"+n+"})","g"),t=t.replace(i,e[n]));else for(var o=1;othis.length)&&(e=this.length),this.substring(e-t.length,e)===t}),String.prototype.startsWith||Object.defineProperty(String.prototype,"startsWith",{value:function(t,e){return e=!e||e<0?0:+e,this.substring(e,e+t.length)===t}}),String.prototype.includes||(String.prototype.includes=function(){return String.prototype.indexOf.apply(this,arguments)!==-1}))}(),/*! @@ -74,7 +74,7 @@ function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"= * Original idea by: * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/ */ -function(t){function e(e){if("string"==typeof e.data){var i=e.handler,n=e.data.toLowerCase().split(" ");e.handler=function(e){if(this===e.target||!/textarea|select/i.test(e.target.nodeName)&&"text"!==e.target.type){var o="keypress"!==e.type&&t.hotkeys.specialKeys[e.which],a=String.fromCharCode(e.which).toLowerCase(),s="",r={};e.altKey&&"alt"!==o&&(s+="alt+"),e.ctrlKey&&"ctrl"!==o&&(s+="ctrl+"),e.metaKey&&!e.ctrlKey&&"meta"!==o&&(s+="meta+"),e.shiftKey&&"shift"!==o&&(s+="shift+"),o?r[s+o]=!0:(r[s+a]=!0,r[s+t.hotkeys.shiftNums[a]]=!0,"shift+"===s&&(r[t.hotkeys.shiftNums[a]]=!0));for(var l=0,c=n.length;l","/":"?","\\":"|"}},t.each(["keydown","keyup","keypress"],function(){t.event.special[this]={add:e}})}(jQuery),function(t,e,i){"use strict";var n="zui.picker",o={},a={lang:null,remote:null,remoteConverter:null,remoteOnly:!1,onRemoteError:null,disableEmptySearch:!1,textKey:"text",valueKey:"value",keysKey:"keys",multi:"auto",formItem:"auto",list:null,allowSingleDeselect:null,autoSelectFirst:!1,maxSelectedCount:0,maxListCount:100,hideEmptyTextOption:!0,searchValueKey:!0,emptyResultHint:null,hideOnScroll:!0,inheritFormItemClasses:!1,emptySearchResultHint:null,accurateSearchHint:null,remoteErrorHint:null,deleteByBackspace:!0,disableScrollOnShow:!0,maxDropHeight:250,dropDirection:"auto",dropWidth:"100%",maxAutoDropWidth:450,minAutoDropWidth:100,multiValueSplitter:",",multiSelectActions:5,searchDelay:200,autoClearDrop:6e4,fixLabelFor:!0,hotkey:!0,onSelect:null,onDeselect:null,onBeforeChange:null,onChange:null,onReady:null,onNoResults:null,onShowingDrop:null,onHidingDrop:null,onShowedDrop:null,onHiddenDrop:null,valueMustInList:!0},s={zh_cn:{emptyResultHint:"没有可选项",emptySearchResultHint:"没有找到 “{0}”",accurateSearchHint:"请提供更多关键词缩小匹配范围",remoteErrorHint:"无法从服务器获取结果 - {0}",selectAll:"全选",deselectAll:"取消选择"},zh_tw:{emptyResultHint:"沒有可選項",emptySearchResultHint:"沒有找到 “{0}”",accurateSearchHint:"請提供更多關鍵詞縮小匹配範圍",remoteErrorHint:"無法從服務器獲取結果 - {0}",selectAll:"全選",deselectAll:"取消選擇"},en:{emptyResultHint:"No options",emptySearchResultHint:'Cannot found "{0}"',accurateSearchHint:"Suggest to provide more keywords",remoteErrorHint:"Unable to get result from server: {0}",selectAll:"Select all",deselectAll:"Deselect all"}},r=function(o,a){var l=this;l.name=n,l.$=t(o),l.id="pk_"+(l.$.attr("id")||t.zui.uuid()),a=l.options=t.extend({},r.DEFAULTS,this.$.data(),a),void 0!==a.hideOnWindowScroll&&(a.hideOnScroll=a.hideOnWindowScroll);var c=t.zui.clientLang?t.zui.clientLang():"en",h=a.lang||c;l.lang=t.zui.getLangData?t.zui.getLangData(n,h,s):s[h]||s[c];var d,u,p=a.formItem,f='.form-item,input[type="hidden"],select,input[type="text"]';if(d="self"===p?l.$:"auto"!==p&&p?l.$.find(p):l.$.is(f)?l.$:l.$.find(f).first(),!d.length)return console.error&&console.error("Cannot found form item for picker.");if(d.is('input[type="hidden"]'))u="hidden";else if(d.is("select"))u="select";else{if(!d.is('input[type="text"]'))return console.error&&console.error("Unknown form type for picker.");u="text"}a.inheritFormItemClasses&&v.addClass(d.attr("class")),l.formType=u,l.$formItem=d.removeClass("picker").hide(),l.selfFormItem=d.is(l.$);var g=a.multi;g&&"auto"!==g||(g="select"===u&&"multiple"===d.attr("multiple")),g=!!g,l.multi=g,g||(l.options.checkable=!1);var m=a.list;m?l.setList("function"==typeof m?m({search:l.search,limit:a.maxListCount}):m,!0):"select"===u?l.updateFromSelect():l.setList([],!0);var v;v=!l.selfFormItem&&l.$.hasClass("picker")?l.$:t('
    ').insertAfter(l.$),v.addClass("picker").toggleClass("picker-multi",g).toggleClass("picker-single",!g);var y=v.children(".picker-selections");y.length?y.empty():y=t('
    ');var b=l.id+"-search",w=t('').appendTo(y);if(!g){var x=t('
    ');a.allowSingleDeselect&&x.append(''),x.appendTo(y),l.$singleSelection=x}v.toggleClass("picker-input-empty",!w.val().length).append(y),l.$container=v,l.$selections=y,l.$search=w,l.search="";var C=a.placeholder;if(void 0===C&&(C=d.attr("placeholder")),"string"==typeof C&&C.length&&y.append(t('
    ').text(C)),a.placeholder=C,a.fixLabelFor){var _=d.attr("id");_&&t('label[for="'+_+'"]').attr("for",b)}var k=void 0!==a.defaultValue?a.defaultValue:d.val();if(null===k&&(k=""),l.setValue(k,!0),l.setDisabled(),w.on("focus",function(){l.disabled||(l._blurTimer&&(clearTimeout(l._blurTimer),l._blurTimer=0),v.addClass("picker-focus"),l.showDropList())}).on("blur",function(){l.disabled||(l._blurTimer&&clearTimeout(l._blurTimer),l._blurTimer=setTimeout(function(){l._blurTimer=0,w.is(":focus")||v.removeClass("picker-focus")},100))}).on("input change",function(){if(!l.disabled){var t=w.val();g&&w.width(14*t.length),v.toggleClass("picker-input-empty",!t.length),l.tryUpdateList(t)}}),a.hotkey&&w.on("keydown",function(t){if(!l.disabled){var e=t.key||t.which;if(l.dropListShowed){var i=l.activeValue,n="string"==typeof i;if("Enter"===e||13===e)n&&(l.select(i,g),g?(l.$search.val(""),l.tryUpdateList("")):w.blur(),t.preventDefault(),t.stopPropagation());else if("ArrowDown"===e||40===e){var o,s=l.$activeOption;if(s&&(o=s.next(".picker-option"),g))for(;o.length&&o.hasClass("picker-option-selected");)o=o.next(".picker-option");o&&o.length||(o=l.$optionsList.children(g?".picker-option:not(.picker-option-selected)":".picker-option").first()),o.length&&l.activeOption(o),t.preventDefault(),t.stopPropagation()}else if("ArrowUp"===e||30===e){var r,s=l.$activeOption;if(s&&(r=s.prev(".picker-option"),g))for(;r.length&&r.hasClass("picker-option-selected");)r=r.prev(".picker-option");r&&r.length||(r=l.$optionsList.children(g?".picker-option:not(.picker-option-selected)":".picker-option").last()),r.length&&l.activeOption(r),t.preventDefault(),t.stopPropagation()}else"Escape"===e||27===e?l.hideDropList(!0):a.deleteByBackspace&&g&&("Backspace"===e||8===e)&&l.value&&l.value.length&&!w.val().length&&l.deselect(l.value[l.value.length-1])}}}),g){y.on("mousedown",function(t){if(!l.disabled)return l.dropListShowed&&!a.checkable?(t.preventDefault(),void t.stopPropagation()):void 0}).on("mouseup",function(e){l.disabled||y.hasClass("sortable-sorting")||t(e.target).closest(".picker-selection-remove").length||l.dropListShowed&&!a.checkable||l.focus()});var T=a.sortValuesByDnd;if(T&&t.fn.sortable){v.addClass("picker-sortable");var S={selector:".picker-selection",stopPropagation:!0,start:function(){l.hideDropList(!0)},finish:function(e){var i=[];t.each(e.list,function(t,e){i.push(e.item.data("value"))}),l.setValue(i.slice(),!1,!0)}};"object"==typeof T&&t.extend(S,T),y.sortable(S)}}if(y.on("click",".picker-selection-remove",function(e){if(!l.disabled){if(l.multi){var i=t(this).closest(".picker-selection");l.deselect(i.data("value"))}else l.deselect();e.stopPropagation()}}),d.on("chosen:updated",function(){l.updateFromSelect(!1),l.setValue(d.val(),!0),l.setDisabled(),l.updateList()}).on("chosen:activate",l.focus).on("chosen:open",l.showDropList).on("chosen:close",l.hideDropList),v.addClass("picker-ready"),t.zui.asap(function(){l.triggerEvent("ready",{picker:l},"","chosen:ready")}),!a.disableScrollOnShow){var D=a.hideOnScroll;D&&![e,i,!0].includes(D)&&t(D).on("scroll",this.handleParentScroll.bind(this))}};r.prototype.destroy=function(){var e=this,i=e.options;e.hideDropList(!0);var o=e.$search;o.off("focus blur input change"),i.hotkey&&o.off("keydown"),o.remove();var a=e.$selections;a.off("click"),e.multi&&a.off("mousedown mouseup"),a.remove();var s=e.$formItem;e.selectOptionsBackup&&(s.empty(),t.each(e.selectOptionsBackup,function(e,n){var o={value:n[i.valueKey]},a=n[i.keysKey];void 0!==a&&(o["data-"+i.keysKey]=a),s.append(t("
    ");i.$.addClass("load-indicator loading"),s.load(window.location.href+" #"+o,function(r){if(a===o)i.$.empty().html(s.children().html()),i.$.find('[data-ride="pager"]').pager();else{i.$.find("#"+o).empty().html(s.children().html());try{var l=t(r),c=l.find("#"+o).closest('[data-ride="table"],#'+a);if(c.length){var h=c.find(".table-statistic");h.length&&(i.defaultStatistic=h.html());var d=i.$.find('[data-ride="pager"]').data("zui.pager"),u=c.find('[data-ride="pager"]');d&&u.length&&d.set(u.data())}}catch(p){console.error(p)}}i.$.removeClass("load-indicator loading").trigger("beforeTableReload"),delete i.defaultStatistic,i.updateStatistic(),i.initModals(),i.$.datepickerAll();var f=i.$.find("tbody>tr"),g=!1;t.each(i.checkItems,function(t,e){e&&(i.checkRow(f.filter('[data-id="'+t+'"]'),!0,!0),g=!0)}),g&&i.updateCheckUI(),n.nested&&i.initNestedList(),i.$.trigger("tableReload");var m=t("#mainMenu>.btn-toolbar>.btn-active-text>.label");if(m.length){var u=i.$.find(".pager[data-rec-total]"),v=u.length?u.attr("data-rec-total"):i.getTable().find("tbody:first>tr:not(.table-children)").length;m.text(v)}e&&e(),n.afterReload&&n.afterReload()})},r.prototype.initModals=function(){var e=this,i=e.options,n=e.$.find(i.iframeModalTrigger);if(n.length){var o={type:"iframe",onHide:i.replaceId?function(){var n=t.cookie("selfClose");(1==n||i.hot)&&(t("#triggerModal").data("cancel-reload",1),e.reload(function(){t.cookie("selfClose",0)}))}:null};n.modalTrigger(o)}},r.prototype.getTable=function(){var t=this.$;if(this.isDataTable)return t.find("div.datatable");var e=t.is("table")?t:t.find("table:not(.fixed-header-copy)").first();return e.is(".datatable")&&(this.isDataTable=!0,e.data("zui.datatable")||window.initDatatable(e),e=t.find("div.datatable")),e},r.prototype.toggleGroups=function(e){var i=this,n={};i.$.find("tbody>tr").each(function(){var o=t(this).closest("tr").data("id");n[o]||i.toggleRowGroup(o,e)})},r.prototype.toggleRowGroup=function(i,n){var o=this.$.find('tbody>tr[data-id="'+i+'"]'),a=o.filter(".group-summary"),s=n===e?!a.hasClass("hidden"):!!n;o.not(".group-summary").toggleClass("hidden",!s),a.toggleClass("hidden",s),t("body").toggleClass("table-group-collapsed",!this.$.find("tbody>tr.group-summary.hidden").length)},r.prototype.updateStatistic=function(){var i=this,n=i.$.find(".table-statistic");if(n.length){if(i.defaultStatistic===e&&(i.defaultStatistic=n.html()),i.options.statisticCreator)return void n.html(i.options.statisticCreator(i)||i.defaultStatistic);var o=i.statisticCols;if(!o&&o!==!1){o={};var a=!1;i.getTable().find("thead th").each(function(e){var i=t(this),n=i.data("statistic");n&&(a=!0,o[e]={format:n,name:i.text()})}),i.statisticCols=!!a&&o}var s=0;o&&t.each(o,function(t){o[t].total=0,o[t].checkedTotal=0}),i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr").each(function(){var e=t(this),i=e.hasClass("checked"),n=e.children("td");i&&s++,o&&t.each(o,function(t){var e=parseFloat(n.eq(t).text());isNaN(e)&&(e=0),o[t].total+=e,i&&(o[t].checkedTotal+=e)})});var r=[];if(s)r.push(i.lang.selectedItems.format(s));else if(i.defaultStatistic)return void n.html(i.defaultStatistic);o&&t.each(o,function(t){var e=o[t],n=e[s?"checkedTotal":"total"];e.format&&(n=e.format.format(n)),r.push(i.lang.attrTotal.format(e.name,n))}),n.html(r.join(", "))}},r.prototype.updateFixUI=function(e){var i=this,n=(new Date).getTime();if(!e&&(i.lastUpdateCall&&clearTimeout(i.lastUpdateCall),!i.lastUpdateTime||n-i.lastUpdateTime
    ').append(t('
  • testcase->openedBy;?>testcase->openedBy;?> openedBy) . $lang->at . $case->openedDate;?>
    bug->priList, $bug2Link->pri, $bug2Link->pri)?>'>bug->priList, $bug2Link->pri, $bug2Link->pri)?>createLink('product', 'browse', "productID={$bug2Link->product}&branch={$bug2Link->branch}"), $products[$bug2Link->product], '_blank');?>createLink('bug', 'view', "bugID=$bug2Link->id"), $bug2Link->title, '_blank');?>createLink('product', 'browse', "productID={$bug2Link->product}&branch={$bug2Link->branch}"), $products[$bug2Link->product], '_blank');?>createLink('bug', 'view', "bugID=$bug2Link->id"), $bug2Link->title, '_blank');?> bug->typeList, $bug2Link->type);?> openedBy);?> testcase->priList, $case2Link->pri, $case2Link->pri)?>'>testcase->priList, $case2Link->pri, $case2Link->pri)?>createLink('product', 'browse', "productID={$case2Link->product}&branch={$case2Link->branch}"), $products[$case2Link->product], '_blank');?>createLink('testcase', 'view', "caseID=$case2Link->id"), $case2Link->title, '_blank');?>createLink('product', 'browse', "productID={$case2Link->product}&branch={$case2Link->branch}"), $products[$case2Link->product], '_blank');?>createLink('testcase', 'view', "caseID=$case2Link->id"), $case2Link->title, '_blank');?> testcase->typeList[$case2Link->type];?> openedBy);?>
    testcase->linkCase;?> + linkCaseTitles)) { foreach($case->linkCaseTitles as $linkCaseID => $linkCaseTitle) { - echo html::a($this->createLink('testcase', 'view', "caseID=$linkCaseID", '', true), "#$linkCaseID $linkCaseTitle", '', "class='iframe' data-width='80%'") . '
    '; + echo html::a($this->createLink('testcase', 'view', "caseID=$linkCaseID", '', true), "#$linkCaseID $linkCaseTitle", '', "class='iframe' data-width='80%' title='$linkCaseTitle'") . '
    '; } } ?> @@ -314,11 +314,11 @@ toBugs):?>
    + toBugs as $bugID => $bugTitle) { - echo '

    ' . html::a($this->createLink('bug', 'view', "bugID=$bugID", '', true), "#$bugID " . $bugTitle, '', "class='iframe' data-width='80%'") . '

    '; + echo html::a($this->createLink('bug', 'view', "bugID=$bugID", '', true), "#$bugID " . $bugTitle, '', "class='iframe' data-width='80%' title='$bugTitle'") . '
    '; } ?>
    team)) echo '' . $this->lang->task->multipleAB . ' ';?> parent > 0) echo '' . $this->lang->task->childrenAB . ' ';?> - executionType == 'kanban') ? 'iframe' : '';?> - createLink('task', 'view', "taskID=$task->id", '', true, $task->project), $task->name, null, "class='$class' data-width='80%' style='color: $task->color'");?> + executionType == 'kanban' ? true : ''; + $class = $task->executionType == 'kanban' ? 'iframe' : ''; + ?> + createLink('task', 'view', "taskID=$task->id", '', $onlybody, $task->project), $task->name, null, "class='$class' data-width='80%' style='color: $task->color'");?> estimate . $lang->execution->workHourUnit;?> consumed . $lang->execution->workHourUnit;?>
    ').addClass(i.attr("class")).append(n.clone())).insertAfter(i)),h){var d=c[0].getBoundingClientRect();l.css({left:d.left,width:c.width(),overflow:"hidden"}),l.find(".fixed-header-copy").css({left:o.left-d.left,position:"relative",minWidth:i.width()}),a||c.data("fixHeaderScroll")||(c.data("fixHeaderScroll",1),i.width()>c.width()&&c.on("scroll",function(){e.fixHeader()}))}else l.css({left:o.left,width:o.width});var u=l.find("th");n.find("th").each(function(e){u.eq(e).css("width",t(this).outerWidth())})}else l.remove()},r.prototype.fixFooter=function(){var e,i=this,n=i.getTable(),o=i.$.find(".table-footer");if(i.isDataTable)e=n[0].getBoundingClientRect();else{var a=n.find("tbody");if(!a.length)return;e=a[0].getBoundingClientRect()}var s=i.options.fixFooter;o.toggleClass("fixed-footer",!!r);var r="function"==typeof s?s(e,o):e.bottom>window.innerHeight-50-("number"==typeof s?s:i.pageFooterHeight||5);o.toggleClass("fixed-footer",!!r),n.toggleClass("with-footer-fixed",!!r),n.trigger("fixFooter",r);var l=t("body"),c=l.hasClass("body-modal");if(r){var h=n.parent(),d=h.is(".table-responsive");o.css({bottom:i.pageFooterHeight||0,left:d?h[0].getBoundingClientRect().left:e.left,width:d?h.width():e.width}),c&&l.css("padding-bottom",40)}else o.css({width:"",left:0,bottom:0}),c&&l.css("padding-bottom",0)},r.prototype.checkAll=function(e){var i=this,n=i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr");n.each(function(){i.checkRow(t(this),e,!0)}),i.updateCheckUI()},r.prototype.checkRow=function(i,n,o){var a=this,s=a.getTable();a.isDataTable&&!i.is(".datatable-row-left")&&(i=s.find('.datatable-row-left[data-index="'+i.data("index")+'"]'));var r=i.find('input[type="checkbox"]');if(r.length&&!r.is(":disabled")){n===e&&(n=!r.is(":checked")),a.isDataTable?s.find('.datatable-row[data-index="'+i.data("index")+'"]').toggleClass("checked",n):i.toggleClass("checked",n);var l=i.data("id");this.checkItems[l]=n,r.prop("checked",n).trigger("change"),o||(i.hasClass("table-parent")&&s.find((a.isDataTable?".fixed-left ":"")+"tbody>tr.parent-"+l).each(function(){a.checkRow(t(this),n,!0)}),a.updateCheckUI())}},r.prototype.updateCheckUI=function(){var e=this,i=e.getTable(),n=i.find(e.isDataTable?".fixed-left tbody>tr":"tbody>tr").not(".group-summary"),o=!1,a=null,s=0,r=!1,l=n.length;n.each(function(n){var c=t(this),h=c.find('input[type="checkbox"]');if(!h.length)return void l--;r=h.is(":checked");var d=e.isDataTable?i.find('.datatable-row[data-index="'+c.data("index")+'"]'):c;d.toggleClass("checked",r),d.toggleClass("row-check-begin",r&&!o),a&&a.toggleClass("row-check-end",!r&&o),r&&(s+=1),a=d,o=r,l===n+1&&d.toggleClass("row-check-end",r)}),e.$.toggleClass("has-row-checked",s>0).find(".check-all").toggleClass("checked",!(!l||s!==l)),e.updateStatistic(),e.options.onCheckChange&&e.options.onCheckChange(),i.trigger("checkChange")},r.DEFAULTS={checkable:!0,checkOnClickRow:!0,ajaxForm:!1,selectable:!0,fixHeader:!a,fixFooter:!a,iframeWidth:900,replaceId:"self",nestLevelIndent:18,nested:!1,preserveNested:!0,hot:!1,iframeModalTrigger:".iframe:not(.disabled,[disabled])"},t.fn.table=function(e){return this.each(function(){var n=t(this),o=n.data(i),a="object"==typeof e&&e;o||n.data(i,o=new r(this,a)), -"string"==typeof e&&o[e]()})},r.NAME=i,t.fn.table.Constructor=r,t(function(){t('[data-ride="table"]').table()})}(jQuery,void 0),function(t,e,i){t.fn._ajaxForm=t.fn.ajaxForm;var n={timeout:e.config?e.config.timeout:0,dataType:"json",method:"post"},o="";t.fn.enableForm=function(e,n,o){return e===i&&(e=!0),this.each(function(){var i=t(this);n||i.find('[type="submit"]').attr("disabled",e?null:"disabled"),!o&&i.hasClass("load-indicator")&&i.toggleClass("loading",!e),i.toggleClass("form-disabled",!e)})},t.enableForm=function(e,i,n,o){"string"==typeof e||e instanceof t?e=t(e):(o=n,n=i,i=e,e=t("form")),e.enableForm(i!==!1,n,o)},t.disableForm=function(e,i,n){t.enableForm(e,!1,i,n)};var a=function(e,i,n){i=i||"show",t.zui.messager?(n?n.html=!0:n={html:!0},e=e.toString().replace(/\n/g,"
    "),t.zui.messager[i](e,n)):alert(e)};t.ajaxForm=function(s,r){var l=t(s);if(l.length>1)return l.each(function(){t.ajaxForm(this,r)});"function"==typeof r&&(r={complete:r}),r=t.extend({},n,l.data(),r);var c=r.beforeSubmit,h=r.error,d=r.success,u=r.finish;delete r.finish,delete r.success,delete r.onError,delete r.beforeSubmit,r=t.extend({beforeSubmit:function(n,a,s){if((c&&c(n,a,s))===!1)return!1;l.removeClass("form-watched").enableForm(!1);var r={},h=a.find('[type="file"]');r.fileapi=h.length&&h[0].files!==i,r.formdata=e.FormData!==i;var d=r.fileapi&&a.find('input[type="file"]:enabled').filter(function(){return""!==t(this).val()}),u=d.length,p="multipart/form-data",f=a.attr("enctype")==p||a.attr("encoding")==p,g=r.fileapi&&r.formdata,m=u&&!g||f&&!r.formdata;m&&(""==o&&(o=s.url),s.url!=o&&(s.url=o),s.url=s.url.indexOf("&")>=0?s.url+"&HTTP_X_REQUESTED_WITH=XMLHttpRequest":s.url+"?HTTP_X_REQUESTED_WITH=XMLHttpRequest")},success:function(i,n,o){if((d&&d(i,n,o,l))!==!1){try{"string"==typeof i&&(i=JSON.parse(i))}catch(s){}if(null===i||"object"!=typeof i)return i?alert(i):a("No response.","danger");var c=r.responser?t(r.responser):l.find(".form-responser");c.length||(c=t("#responser"));var h=i.message,p=function(){var n=i.callback;if(n)if("object"==typeof n){var o=n.target?e[n.target]:e,a=o[n.name];a.apply(l,Array.isArray(n.params)?n.params:[n.params])}else{var s=n.indexOf("("),r=(s>0?n.substr(0,s):n).split("."),c=e,h=r[0];r.length>1&&(h=r[1],"top"===r[0]?c=e.top:"parent"===r[0]&&(c=e.parent));var a=c[h];if("function"==typeof a){var d=[];return s>0&&")"==n[n.length-1]&&(d=t.parseJSON("["+n.substring(s+1,n.length-1)+"]")),d.push(i),a.apply(l,d)}}};if("success"===i.result){var f=r.locate||i.locate,g=r.closeModal||i.closeModal,m=r.ajaxReload||i.ajaxReload;if(l.enableForm(!0,!!(f||g||m)),h){var v=l.find('[type="submit"]').first(),y=!1;v.length&&(v.popover({container:"body",trigger:"manual",content:h,tipClass:"popover-in-modal popover-success popover-form-result",placement:i.placement||v.data("placement")||r.popoverPlacement||"right"}).popover("show"),setTimeout(function(){v.popover("destroy")},r.popoverTime||2e3),y=!0),c.length&&(c.html(''+h+"").show().delay(3e3).fadeOut(100),y=!0),y||a(h,"success")}if(u)return u(i,!0,l);if(g&&setTimeout(t.zui.closeModal,"number"==typeof g?g:r.closeModalTime||2e3),p()===!1)return;if(f)if("loadInModal"==f){var b=t(".modal");setTimeout(function(){b.load(b.attr("ref"),function(){t(this).find(".modal-dialog").css("width",t(this).data("width")),t.zui.ajustModalPosition()})},1e3)}else"parent"===f||"top"===f?e[f]&&setTimeout(function(){e[f].location.reload()},1200):"reload"===f?setTimeout(function(){e.location.href=e.location.href},1200):setTimeout(function(){t.apps?t.apps.open(f):e.location.href=f},1200);if(m){var w=t(m);w.length&&w.load(e.location.href+" "+m,function(){w.find('[data-toggle="modal"]').modalTrigger()})}}else{if(l.enableForm(),"string"==typeof h)c.length?c.html(''+h+"").show().delay(3e3).fadeOut(100):a(h,"danger");else if("object"==typeof h){var x=!1,C=[];t.each(h,function(e,i){var n=t.isArray(i)?i.join(""):i,o=t("#"+e);if(!o.length)return void C.push(n);var a=e+"Label",s=t("#"+a);if(!s.length){var r=o.closest(".input-group").length,l=o.closest("td").length;s=t('
    ').appendTo(l?o.closest("td"):r?o.closest(".input-group").parent():o.parent())}s.empty().append(n),o.addClass("has-error");var c=function(){var e=t("#"+a);if(e.length)return e.remove(),o.removeClass("has-error"),!0};o.on("change input mousedown",c);var h=t("#"+e+"_chosen");if(h.length&&h.find(".chosen-single,.chosen-choices").addClass("has-error").on("mousedown",function(){c()===!0&&t(this).removeClass("has-error")}),!x&&!o.data("datetimepicker")){var d=o[0];if(o.hasClass("chosen"))o.trigger("chosen:activate").trigger("chosen:open"),d=o.parent().find(".chosen-container")[0];else if(o.is("textarea")&&o.data("keditor")){var u=o.data("keditor");u.focus(),u.edit.doc.body.focus(),d=o.parent().find(".ke-container")[0]}else o.focus();d.scrollIntoView&&d.scrollIntoView(),x=!0}}),C.length&&a(C.join(""),"danger")}if(u)return u(i,!1,l);if(p()===!1)return}}},error:function(t,i,n){if((h&&h(t,i,n,l))!==!1){l.enableForm();var o="timeout"==i||"error"==i?e.lang?e.lang.timeout:i:t.responseText+i+n;a(o,"danger")}}},r),l._ajaxForm(r).data("zui.ajaxform",!0),l.on("click","[data-form-action]",function(){l.attr("action",t(this).data("formAction")).submit()})},t.setAjaxForm=function(e,i,n){t.ajaxForm(e,t.isPlainObject(i)?i:{finish:i,beforeSubmit:n})},t.fn.ajaxForm=function(e){return this.each(function(){t.ajaxForm(this,e)})},t.fn.setInputRequired=function(){return this.each(function(){var e=t(this),i=e.parent();i.is(".input-control,td")?i.addClass("required"):e.is(".chosen")?e.attr("required",null).next(".chosen-container").addClass("required"):i.addClass("required"),e.attr("required",null);var n=i.closest(".input-group");n.length&&1===n.find(".required,input[required],select[required]").length&&n.addClass("required")})},t(function(){t('.form-ajax,form[data-type="ajax"]').ajaxForm(),setTimeout(function(){var i=e.config.requiredFields,n=t("form");i&&(i=i.split(",")),i&&i.length&&t.each(i,function(t,e){n.find("#"+e).attr("required","required")}),n.find("input[required],select[required],textarea[required]").setInputRequired()},400),t('form[target="hiddenwin"]').on("submit",function(){var e=t(this);e.data("zui.ajaxform")||e.enableForm(!1).data("disabledTime",(new Date).getTime())}).on("click",function(){var e=t(this),i=e.data("disabledTime");i&&(new Date).getTime()-i>1e4&&e.enableForm(!0).data("disabledTime",null)})})}(jQuery,window,void 0),function(t){"use strict";var e="zui.searchList",i=function(t,e){if(t&&t.length)for(var i=0;i
    ').append(s)),i.$menu.append(s),i.$menu.removeClass("loading"),i.isLoaded=!0,e&&e(!0)},error:function(){i.$menu.removeClass("loading").append('
    '+(n.errorText||window.lang&&window.lang.timeout)+"
    "),e&&e(!1)}},n.ajax))},n.prototype.scrollTo=function(t){t.length&&t[0].scrollIntoViewIfNeeded&&t[0].scrollIntoViewIfNeeded({behavior:"smooth"})},n.prototype.getItems=function(){return this.$.find(this.options.selector).addClass("search-list-item")},n.prototype.getActiveItem=function(){return this.getItems().filter(".active:first")},n.prototype.search=function(e){var n=this,o=void 0===e||null===e||""===e;n.$.toggleClass("has-search-text",!o);var a=n.getItems().removeClass("active");if(o)a.removeClass("hidden");else{var s=e.trim().split(" ");a.each(function(){var e=t(this),n=(e.text()+" "+(e.data("key")||e.data("filter")||"")).trim();e.toggleClass("hidden",!i(s,n))})}n.scrollTo(a.not(".hidden").first().addClass("active")),n.$.trigger("onSearchComplete",e)},n.DEFAULTS={selector:".list-group a:not(.not-list-item)",searchBox:".search-box",onSelectItem:null},t.fn.searchList=function(i){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof i&&i;a||o.data(e,a=new n(this,s)),"string"==typeof i&&a[i]()})},n.NAME=e,t.fn.searchList.Constructor=n,t(function(){t('[data-ride="searchList"]').searchList()})}(jQuery),function(t){"use strict";var e="zui.labelSelector",i=function(n,o){var a=this;a.name=e,a.$=t(n),o=a.options=t.extend({},i.DEFAULTS,this.$.data(),o),a.$.hide(),a.update()};i.prototype.select=function(t){t+="",this.$wrapper.find(".label.active").removeClass("active"),this.$wrapper.find('.label[data-value="'+t+'"]').addClass("active"),this.$.val(t).trigger("change")},i.prototype.update=function(){var e=this,i=e.options,n=e.$wrapper;if(!n){if(i.wrapper)n=t(i.wrapper);else{var o=e.$.next();n=o.hasClass(".label-selector")?o:t('
    ')}n.parent().length||e.$.after(n),e.$wrapper=n,n.on("click",".label",function(i){var n=e.$.val(),o=t(this).data("value");e.hasEmptyValue!==!1&&o==n&&(o=e.hasEmptyValue),e.select(o),i.preventDefault()})}n.empty();var a=e.$.val();e.hasEmptyValue=!1,e.$.children("option").each(function(){var e=t(this),o={label:e.text(),value:e.val()},s=(""===o.value||"0"===o.value)&&!o.label,r=t(i.labelTemplate||'');i.labelClass&&!s&&r.addClass(i.labelClass),i.labelCreator?r=i.labelCreator(r):(r.data("option",o).attr("data-value",o.value),s?r.addClass("empty").append(''):r.text(o.label).toggleClass("active",a===o.value)),n.append(r)})},i.DEFAULTS={},t.fn.labelSelector=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.labelSelector.Constructor=i,t(function(){t('[data-provide="labelSelector"]').labelSelector()})}(jQuery),function(t){"use strict";var e="zui.fileInput",i=t.BYTE_UNITS={B:1,KB:1024,MB:1048576,GB:1073741824,TB:1099511627776},n=t.formatBytes=function(t,e,n){return void 0===e&&(e=2),n||(n=ts.fileMaxSize&&(c.val(""),(window.bootbox||window).alert(s.fileSizeError.format(n(s.fileMaxSize)))),r.update()}),r.update()};a.prototype.getFile=function(){var t=this.$input.prop("files");return t&&t[0]},a.prototype.update=function(){var t=this,e=t.$,i=t.getFile(),o=!i;e.toggleClass("normal",!o).toggleClass("empty",o),i?(t.oldName=i.name,e.find(".file-title").text(i.name).attr("title",i.name),e.find(".file-size").text(n(i.size)),e.find(".file-editbox").val(i.name).attr("size",i.name.length),t.options.onSelect&&t.options.onSelect(i,t)):e.find(".file-editbox").val("")},a.DEFAULTS={fileMaxSize:0,fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInput=function(i){return this.each(function(){var n=t(this),o=n.data(e),s="object"==typeof i&&i;o||n.data(e,o=new a(this,s)),"string"==typeof i&&o[i]()})},a.NAME=e,t.fn.fileInput.Constructor=a,t(function(){t('[data-provide="fileInput"]').fileInput()});var s="zui.fileInputList",r=function(e,i){var n=this;n.name=s;var o=n.$=t(e);i=n.options=t.extend({},r.DEFAULTS,this.$.data(),i),n.$template=o.find(".file-input").detach(),n.add()};r.prototype.add=function(){var t=this,e=t.options,i=t.$template.clone();"before"===e.appendWay?t.$.prepend(i):t.$.append(i),i.fileInput({fileMaxSize:e.eachFileMaxSize,fileSizeError:e.fileSizeError,onDelete:function(e){e.$.remove(),t.options.onDelete&&t.options.onDelete(e,t)},onSelect:function(e,i){t.add(),t.options.onSelect&&t.options.onSelect(e,i,t)}})},r.DEFAULTS={fileMaxSize:0,eachFileMaxSize:0,appendWay:"after",fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInputList=function(e){return this.each(function(){var i=t(this),n=i.data(s),o="object"==typeof e&&e;n||i.data(s,n=new r(this,o)),"string"==typeof e&&n[e]()})},r.NAME=s,t.fn.fileInputList.Constructor=r,t(function(){t('[data-provide="fileInputList"]').fileInputList()})}(jQuery),function(t){window.config||(window.config={}),t.createLink=window.createLink=function(e,n,o,a,s,r,l){if("object"==typeof e)return t.createLink(e.moduleName,e.methodName,e.vars,e.viewType,e.isOnlyBody,e.hash,e.tid);if(t.tabSession&&!l&&(l=t.tabSession.getTid()),a||(a=config.defaultView),s||(s=!1),o)for("string"==typeof o&&(o=o.split("&")),i=0;i'+d+"")}}t.val()||(time=e(a.format("hh:mm")),time=time-time%10+10,t.val(n(time)))};t.fn.timeSpanControl=function(i){return this.each(function(){var s=t(this),r=t.extend({},i,s.data()),l=s.find('[name="begin"],.control-time-begin'),c=s.find('[name="end"],.control-time-end'),h=function(){var t=l.val();if(s.find(".hide-empty-begin").toggleClass("hide",!t),t){var i=n(e(t)+30);c.find('option[value="'+i+'"]').length&&c.val(i),r.onChange&&r.onChange(c,i)}};if(s.data("timeSpanControlInit")){if(r.begin){var d=o(r.begin).format("hh:mm");l.find('option[value="'+d+'"]').length&&l.val(d),r.onChange&&r.onChange(l,d)}if(r.end){var u=o(r.end).format("hh:mm");c.find('option[value="'+u+'"]').length&&c.val(u),r.onChange&&r.onChange(c,u)}}else l.on("change",h),a(l,r.begin),a(c,r.end),s.data("timeSpanControlInit",!0);r.end||h()})},t.timeSpanControl={convertTimeToNum:e,convertNumToTime:n,initTimeSelect:a,createTime:o};var s=t.setSearchType=function(e,i){var n=t("#searchType");e||(e=n.val()),e=e||"bug",n.val(e);var o=t("#searchTypeMenu");o.find("li.selected").removeClass("selected");var a=o.find('a[data-value="'+e+'"]'),s=a.text();a.parent().addClass("selected"),t("#searchTypeName").text(s),i||t("#searchInput").focus()};t.gotoObject=function(e,i){if(e||(e=t("#searchType").val()),i||(i=t("#searchInput").val()),i&&e)if(i=i.replace(/[^\d]/g,"")){var n=e.split("-");e=n[0];var o=n.length>1?n[1]:"testsuite"===e?"library":"view",a=t.createLink(e,o,"id="+i);t.apps?t.apps.open(a):window.location.href=a}else{var s={zh_cn:"请输入数字ID进行搜索",zh_tw:"請輸入數值ID行搜索"};alert(lang.searchTip||s[t.zui.clientLang()]||"Please enter a numberic id to search")}t("#searchInput").val(i).focus()},t(function(){s(null,!0),t(document).on("keydown",function(e){e.ctrlKey&&71===e.keyCode&&(t("#searchInput").val("").focus(),e.stopPropagation(),e.preventDefault())})}),t.removeAnchor=window.removeAnchor=function(t){var e=t.lastIndexOf("#");return e>-1?t.substr(0,e):t},t.refreshPage=function(t){t?window.top.location.reload():window.location.reload()},t.selectLang=window.selectLang=function(e){t.cookie("lang",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectLang"),t.refreshPage(1)},t.selectTheme=window.selectTheme=function(e){t.cookie("theme",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectTheme"),t.refreshPage(1)},t.zui.Picker&&(t.extend(t.zui.Picker.DEFAULTS,{optionRender:function(e,i,n){if("user"===n.options.type){var o=n.options.users;if(!o)return;var a=o[i.value];if(!a)return;if(e.find(".picker-option-text").text(a.realname||a.account),e.hasClass("picker-user-option"))return;return e.prepend(t('
    ').avatar({user:a})),a.deptName&&e.append(t('').text(a.deptName)),a.roleName&&e.append(t('').text(a.roleName)),e.addClass("picker-user-option")}},checkable:!0,maxListCount:500,disableScrollOnShow:!1}),t.zui.setUserPickerInfos=function(e){t.zui.Picker.DEFAULTS.users=t.extend({},t.zui.Picker.DEFAULTS.users,e)},t(function(){t(".picker-select[data-pickertype!='remote']").picker({chosenMode:!0}),t("[data-pickertype='remote']").each(function(){var e=t(this).attr("data-pickerremote");t(this).picker({chosenMode:!0,remote:e})}),window.pickerUsers&&t.zui.setUserPickerInfos(window.pickerUsers),t(".user-picker").picker({type:"user"})})),t.chosenDefaultOptions={middle_highlight:!0,disable_search_threshold:1,compact_search:!0,allow_single_deselect:!0,placeholder_text_single:" ",placeholder_text_multiple:" ",search_contains:!0,max_drop_width:500,max_drop_height:245,no_wrap:!0,drop_direction:function(){var e=t(this.container).closest(".table-responsive:not(.scroll-none)");if(e.length){if(this.drop_directionFixed)return this.drop_directionFixed;e.css("position","relative");var i="down",n=this.container.find(".chosen-drop"),o=this.container.position(),a=n.outerHeight();return o.top>=a&&o.top+31+a>e.outerHeight()&&(i="up"),this.drop_directionFixed=i,i}return"auto"}},t.chosenSimpleOptions=t.extend({},t.chosenDefaultOptions,{disable_search_threshold:6}),t.fn._chosen=t.fn.chosen,t.fn.chosen=function(e){return"string"==typeof e?this._chosen(e):this.each(function(){var i=t(this).addClass("chosen-controled");return i._chosen(t.extend({},i.hasClass("chosen-simple")?t.chosenSimpleOptions:t.chosenDefaultOptions,i.data(),e))})},t.fn.chosen.Constructor=t.fn._chosen.Constructor,t(function(){t(".chosen,.chosen-simple").each(function(){var e=t(this);e.closest(".template").length||e.chosen()})}),t.extend(t.fn.pager.Constructor.DEFAULTS,{maxNavCount:8,prevIcon:"icon-angle-left",nextIcon:"icon-angle-right",firstIcon:"icon-first-page",lastIcon:"icon-last-page",navEllipsisItem:"…",menuDirection:"dropup",pageSizeOptions:[5,10,15,20,25,30,35,40,45,50,100,200,500,1e3,2e3],elements:["total_text","size_menu","first_icon","prev_icon",'
    {page}/{totalPage}
    ',"next_icon","last_icon"],onPageChange:function(e,i){e.recPerPage!==i.recPerPage&&t.cookie(this.options.pageCookie,e.recPerPage,{expires:config.cookieLife,path:config.webRoot}),e.recPerPage!==i.recPerPage&&(window.location.href=this.createLink())}}),t.extend(!0,t.zui.Messager.DEFAULTS,{cssClass:"messagger-zt",icons:{success:"check-circle",info:"chat-line",warning:"exclamation-sign",danger:"exclamation-sign"}}),t.fn.reverseOrder=function(){return this.each(function(){var e=t(this);e.prependTo(e.parent())})};var r=function(e,i){var n=t(e);if(!n.data("historiesInited")){n.data("historiesInited",1),i=t.extend({},n.data(),i);var o=n.find(".histories-list"),a=!0,s=!1;n.on("click",".btn-reverse",function(){o.children("li").reverseOrder(),a=!a,t(this).find(".icon").toggleClass("icon-arrow-up",a).toggleClass("icon-arrow-down",!a);var e="#lastComment",i=t(e);i.length&&window.KindEditor&&(window.KindEditor.remove(e),i.kindeditor())}).on("click",".btn-expand-all",function(){var e=t(this).find(".icon");s=!s,e.toggleClass("icon-plus",!s).toggleClass("icon-minus",s),o.children("li").toggleClass("show-changes",s)}).on("click",".btn-expand",function(){t(this).closest("li").toggleClass("show-changes")}).on("click",".btn-strip",function(){var e=t(this),n=e.find(".icon"),o=n.hasClass("icon-code");n.toggleClass("icon-code",!o).toggleClass("icon-text",o),e.attr("title",o?i.original:i.textdiff),e.closest("li").toggleClass("show-original",o)}),o.find(".btn-strip").attr("title",i.original);var r=n.find(".modal-comment").modal({show:!1}).on("shown.zui.modal",function(){var t=r.find("#comment");t.length&&(t.focus(),window.editor&&window.editor.comment&&window.editor.comment.focus())}).on("show.zui.modal",function(){var e=r.find("#comment");e.length&&!e.data("keditor")&&t.fn.kindeditor&&e.kindeditor()});n.on("click",".btn-comment",function(t){r.modal("toggle"),t.preventDefault()}).on("click",".btn-edit-comment,.btn-hide-form",function(){t(this).closest("li").toggleClass("show-form")});var l=n.find(".comment-edit-form");l.ajaxForm({success:function(t,e,i,n){setTimeout(function(){l.closest("li").removeClass("show-form")},2e3)}})}};t.fn.histories=function(t){return this.each(function(){r(this,t)})},t(function(){t(".histories").histories()});var l=0,c=0;t.toggleSidebar=function(e){var i=t("#sidebar");if(i.length){var n=t("main");if(void 0===e)e=n.hasClass("hide-sidebar");else if(e&&!n.hasClass("hide-sidebar"))return;n.toggleClass("hide-sidebar",!e),clearTimeout(l),t.zui.store.set(c,e);var o=i.children(".cell"),a={overflow:"visible",maxHeight:"initial"};e?(i.addClass("showing"),l=setTimeout(function(){i.removeClass("showing"),i.trigger("sidebar.toggle",e)},210)):(i.trigger("sidebar.toggle",e),t(window).width()<1900&&(a={overflow:"hidden",maxHeight:t(window).height()-45})),o.css(a)}};var h=t.initSidebar=function(){var e=t("#sidebar");if(e.length){if(e.data("init"))return!0;c="sidebar:"+(e.data("id")||config.currentModule+"/"+config.currentMethod);var i=t("main");if(i.length){i.on("click",".sidebar-toggle",function(){t.toggleSidebar(i.hasClass("hide-sidebar"))});var n=t.zui.store.get(c,e.data("hide")!==!1);n===!1&&e.addClass("no-animate"),t.toggleSidebar(n),n===!1&&setTimeout(function(){e.removeClass("no-animate")},500);var o=e.find(".sidebar-toggle");if(o.length){var a=function(){var e=o[0].getBoundingClientRect(),i=t(window).height(),n=Math.max(0,Math.floor(Math.min(i-40,e.top+e.height)-Math.max(e.top,0))/2)+(e.top<0?0-e.top:0);o.removeClass("fade").find(".icon").css("top",n+(t.zui.browser.isIE()?(i-80)/2:0))};a(),e.data("init",1).on("sidebar.toggle",a);var s=t.zui.browser.isIE()?1500:0,r=0,l=null,h=function(){var t=Date.now();return l&&(clearTimeout(l),l=null),t-rtr input[type="checkbox"]:checked');i.each(function(){var i=parseInt(t(this).val(),10);NaN!==i&&e.push(i)}),t.cookie("checkedItem",e.join(","),{expires:config.cookieLife,path:config.webRoot})},t.extend(t.fn.modal.bs.Constructor.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:100}),t.extend(t.zui.ModalTrigger.DEFAULTS,{scrollInside:!0,backdrop:"static"}),t.fn.initIframeModal=function(){return this.each(function(){var e=t(this);if(!e.is("[disabled],.disabled")&&!e.parents('[data-ride="table"],.skip-iframe-modal').length){var i={type:"iframe"};e.hasClass("export")&&t.extend(i,{width:800,shown:setCheckedCookie},e.data()),e.modalTrigger(i)}})},t(function(){t("a.iframe,.export").initIframeModal()}),t.fixedTableHead=window.fixedTableHead=function(e,i){var n=t(e);if(n.is("table")||(n=n.find("table")),n.length){var o=t(i||window),a=null,s=function(){var e=n.children("thead"),i=e[0].getBoundingClientRect(),o=n.next(".fixed-head-table");if(i.top<0){var s=e.width();if(o.length){if(a!==s){a=s;var r=o.find("th");e.find("th").each(function(e){r.eq(e).width(t(this).width())})}}else{var o=t("
    ").addClass(n.attr("class")),l=e.clone(),r=l.find("th");e.find("th").each(function(e){r.eq(e).width(t(this).width())}),o.append(l).insertAfter(n)}o.css({left:i.left,width:i.width}).show()}else o.hide()};o.on("scroll",s).on("resize",s),s()}},t(document).on("click","tr[data-url]",function(){var e=t(this),i=e.data("href")||e.data("url");i&&(window.location.href=i)}),"yes"===config.onlybody&&self===parent&&(window.location.href=window.location.href.replace("?onlybody=yes","").replace("&onlybody=yes","")),t(function(){t("body").addClass("m-{currentModule}-{currentMethod}".format(config))});var d,u,p,f,g,m=function(){d||(d=t("#subNavbar"),u=t("#pageNav"),p=t("#pageActions"),f=d.children(".nav"),g=f.outerWidth());var e=d.outerWidth(),i=u.outerWidth()||0,n=p.outerWidth()||0;if(i=i?i+15:0,n=n?n+15:0,!i&&!n)return void f.css({maxWidth:null,left:null,position:"static"});var o=Math.max(300,e-i-n),a=Math.min(o,g),s=(e-a)/2,r=i&&s.btn-toolbar");if(e.length){var i,n,o=e.children(),a=o.length,s=!1,r=null;if(a)for(o.each(function(e){i=t(this),n=i.is(".divider"),n&&!r&&i.hide(),s||n||(s=!0),r=n?null:i,!n||e!==a-1&&0!==e||i.hide()});i.length&&i.is(".divider");)i=i.hide().prev();s||e.hide()}};t(function(){t(".input-group,.btn-group").fixInputGroup(),x()}),window.holders&&t.each(window.holders,function(e){var i=t("#"+e);i.length&&i.is("input")&&i.attr("placeholder",window.holders[e])}),t(function(){var e=t(".table-responsive"),i=t.fixTableResponsive=function(){e.each(function(){this.scrollHeight-3<=this.clientHeight&&this.scrollWidth-3<=this.clientWidth?t(this).addClass("scroll-none").css("overflow","visible"):t(this).removeClass("scroll-none").css("overflow","auto")})};e.length&&(t(window).on("resize",i),setTimeout(i,100))});var C=function(){ -var e=this,i=t(e),n=i.closest("tr").find("textarea");if(n.length){var o=32;n.each(function(){var e=t(this).closest("td"),i=e.css("height");e.css("height",this.style.height),this.style.height="auto";var n=this.value?this.scrollHeight+2:32;o=Math.max(o,n),e.css("height",i)}),n.css("height",o)}else{e.style.height="auto";var a=e.value?e.scrollHeight+2:32;e.style.height=a+"px"}};t.autoResizeTextarea=function(e){t(e).each(C)},t(function(){t("textarea.autosize").each(C),t(document).on("input paste change","textarea.autosize",C)}),t(function(){var e=t("#dropMenu,.drop-menu");e.length&&e.on("click",".toggle-right-col",function(e){t(this).closest("#dropMenu,.drop-menu").toggleClass("show-right-col"),e.stopPropagation(),e.preventDefault()})});var _="undefined"!=typeof InstallTrigger;t.zui.browser.firefox=_,t("html").toggleClass("is-firefox",_).toggleClass("not-firefox",!_),t(function(){var e=t("#mainContent>.main-col"),i=e.children(".main-actions");if(i.length){var n=i.prev();if(i.length&&n.length){t('
    ').css("height",i.outerHeight()).insertAfter(i);var o=0,a=function(){var e=n[0].getBoundingClientRect(),s=e.top+e.height+120>t(window).height();if(t("body").toggleClass("main-actions-fixed",s),s){var r=n.width();r?i.width(r):o<10&&setTimeout(a,1e3)}o++};t.resetToolbarPosition=a,a(),t(window).on("resize scroll",a)}}}),t(document).on("show.zui.modal",function(e){t("body.body-modal").length&&window.parent&&window.parent!==window&&t(e.target).is(".modal")&&window.parent.$("body").addClass("hide-modal-close")}).on("hidden.zui.modal",function(e){t("body.body-modal").length&&window.parent&&window.parent!==window&&window.parent.$("body").removeClass("hide-modal-close")}).on("loaded.zui.modal",function(e){t("body").removeClass("hide-modal-close")}),t(function(){var e=t(".dropdown-menu.with-search");e.length&&(e.find(".menu-search").on("click",function(t){return t.stopPropagation(),!1}),e.on("keyup change paste","input",function(){var e=t(this),i=e.closest(".dropdown-menu.with-search"),n=e.val().toLowerCase(),o=i.find(".option");""==n?o.removeClass("hide"):o.each(function(){var e=t(this);e.toggleClass("hide",e.text().toString().toLowerCase().indexOf(n)<0&&e.data("key").toString().toLowerCase().indexOf(n)<0)})}),e.parents(".dropdown-submenu").one("mouseenter",function(){var e=t(this).find(".dropdown-list")[0];e&&e.getBoundingClientRect&&setTimeout(function(){var i=270,n=e.getBoundingClientRect();n.top<0&&(i=Math.min(270,n.height)+n.top),e.style.maxHeight=Math.min(270,i,t(window).height()-28)+"px"},50)})),t(".dropdown-menu.with-search .menu-search").on("click",function(t){return t.stopPropagation(),!1})})}(jQuery),function(t){function e(){if(!config.skipRedirect&&!window.skipRedirect){var e=window.parent,i=config.currentModule,n=config.currentMethod;if("file"!==i||"download"!==n){var o="index"===i&&"index"===n,a="#_single"===location.hash||/(\?|\&)_single/.test(location.search)||o||!t("#mainHeader,#editorNav").length||"tutorial"===i||"install"===i||"upgrade"===i||"user"===i&&("login"===n||"deny"===n)||"my"===i&&"changepassword"===n||t("body").hasClass("allow-self-open"),s=location.href;if(e===window&&!a){var r=location.pathname+location.search+location.hash;return void(location.href=t.createLink("index","index","")+"#app="+encodeURIComponent(r))}if(e!==window&&e.$.apps){o&&e.location.reload();var l=window.name;if(0===l.indexOf("app-")){t.apps=window.apps=e.$.apps;var c=l.substring(4);t.appCode=c,t(document).on("click",function(t){var i=e.document.getElementById(window.name);if(i){var n=e.document.getElementById(i.name)||i;if(n){var o;"function"==typeof Event?o=new Event(t.type,{bubbles:!0}):(o=document.createEvent("Event"),o.initEvent(t.type,!0,!0)),n.dispatchEvent(o)}}}).on("click","a,.open-in-app,.show-in-app",function(e){var i=t(this);if(!i.is("[data-modal],[data-toggle],[data-ride],[data-tab],.iframe,.not-in-app,[target]")&&!i.data("zui.modaltrigger")){var n=i.hasClass("show-in-app")?"":i.attr("href")||(i.is("a")?"":i.data("url")),o=i.data("app")||i.data("group");if(n){if(0===n.indexOf("javascript:")||"#"===n[0])return;var a=t.parseLink(n);if(a.external||"file"===a.moduleName&&"download"===a.methodName)return;if("index"===a.moduleName&&"index"===a.methodName)return window.location.reload(),void e.preventDefault()}else if(!o)return;o||(o=t.apps.getAppCode(n)),o&&("help"===o&&(t.apps.appsMap.help.text=i.text(),t.apps.appsMap.help.url||(t.apps.appsMap.help.url=n)),t.apps.open(n,o)&&e.preventDefault())}}),t.apps.updateUrl(c,s,document.title)}}}}}function i(){var e=t("#navbar>.nav");if(e.length){var i=t("#heading"),n=+i.css("left").replace("px",""),o=i.outerWidth(),a=e.width(),s=t("#mainHeader>.container").width()-2*n,r=Math.floor((s-a)/2);e.css("marginLeft",r>>0;if(0===o)return!1;for(var a=0|e,s=Math.max(a>=0?a:o-Math.abs(a),0);s1&&("?"===e[0]&&(e=e.substr(1)),e.split("&").forEach(function(t){var e=t.split("=",2);if(e.length>1)try{i[e[0]]=decodeURIComponent(e[1])}catch(n){i[e[0]]=""}else i[e[0]]=""})),t?i[t]:i},t.parseLink=function(e){if(!e)return{};var i=0===e.indexOf("http:")||0===e.indexOf("https:");if(i){var n=window.location.origin;if(e.indexOf(n)<0)return{external:!0,url:e};e=e.substr((n+config.webRoot).length)}var o=e.split("#"),a=o[0].split("?"),s=a[1],r=s?t.getSearchParam("",s):{},l=a[0],c={url:e,isOnlyBody:"yes"===r.onlybody,vars:[],hash:o[1]||"",params:r,tid:r.tid||""};if("GET"===config.requestType){c.moduleName=r[config.moduleVar]||"index",c.methodName=r[config.methodVar]||"index",c.viewType=r[config.viewVar]||config.defaultView;for(var h in r)h!==config.moduleVar&&h!==config.methodVar&&h!==config.viewVar&&"onlybody"!==h&&"tid"!==h&&c.vars.push([h,r[h]])}else{var d=l.lastIndexOf("/");d===l.length-1&&(l=l.substr(0,d),d=l.lastIndexOf("/")),d>=0&&(l=l.substr(d+1));var u=l.lastIndexOf(".");u>=0?(c.viewType=l.substr(u+1),l=l.substr(0,u)):c.viewType=config.defaultView;var p=l.split(config.requestFix);if(c.moduleName=p[0]||"index",c.methodName=p[1]||"index",p.length>2)for(var f=2;f.nav>li").length>10&&(i(),t(window).on("resize",i)),setTimeout(n,1e3)})}(jQuery),function(t){"use strict";function e(e,i){"object"!=typeof i&&(i={user:i});var n=t(e);i=t.extend({},n.data(),i);var o=i.user;"string"==typeof o&&(o={account:o});var a={},s=i.size;s&&(a.width=s,a.height=s,a.lineHeight=s,Number.isNaN(+s)||n.addClass("size-"+s));var r=!!o.avatar;if(n.toggleClass("has-image",r).toggleClass("has-text",!r),n.empty(),r)n.append(t("").attr("src",o.avatar));else{var l=t.zui.strCode(o.account)*(i.hueDistance||43)%360;a.background="hsl("+l+","+(i.saturation||"40%")+","+(i.lightness||"60%")+")",Number.isNaN(+s)||(a.fontSize=Math.round(s/2)+"px");var c=o.name||o.realname||o.account;c=/^[\u4e00-\u9fa5\s]+$/.test(c)?c.length<=2?c:c.substring(c.length-2):/^[A-Za-z\d\s]+$/.test(c)?c[0].toUpperCase():c.length<=2?c:c.substring(0,2),n.append(t('').text(c))}return n.css(a)}t.fn.avatar=function(t){return this.each(function(){e(this,t)})}}(jQuery),$.zui.lang("de",{"zui.pager":{pageOfText:"Seite {0}",prev:"Zurück",next:"Nächste Seite",first:"Erste Seite",last:"Letzte Seite","goto":"Goto",pageOf:"Seite {page}",totalPage:"{totalPage} Seiten",totalCount:"Total: {recTotal} Artikel",pageSize:"{recPerPage} Artikel pro Seite",itemsRange:"Seiten {start} bis {end}",pageOfTotal:"Seite {page}/{totalPage}"},"zui.boards":{append2end:"Gehen Sie zum Ende"},"zui.browser":{tip:"Online. Sorgenfrei. Aktualisiere deinen Browser noch heute!"},"zui.calendar":{weekNames:["Son","Mon","Die","Mit","Don","Fri","Sam"],monthNames:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",year:"{0}Jahr",month:"{0}Monat",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Kein Icon]",commonIcons:"Gemeinsame Symbole",webIcons:"Web-Symbol",editorIcons:"Editor-Symbol",directionalIcons:"Pfeil Zusammenfluss",otherIcons:"Andere Symbole"},"zui.colorPicker":{errorTip:"Kein gültiger Farbwert"},"zui.datagrid":{errorCannotGetDataFromRemote:"Daten vom Remote-Server ({0}) können nicht abgerufen werden.",errorCannotHandleRemoteData:"Die vom Remote-Server zurückgegebenen Daten können nicht verarbeitet werden."},"zui.guideViewer":{prevStep:"Vorheriger Schritt",nextStep:"Nächster Schritt"},"zui.tabs":{reload:"Neu laden",close:"Schliessen",closeOthers:"Schließen Sie andere Registerkarten",closeRight:"Schließen Sie die rechte Registerkarte",reopenLast:"Letzten geschlossenen Tab wiederherstellen",errorCannotFetchFromRemote:"Inhalt kann nicht vom Remote-Server abgerufen werden ({0})."},"zui.uploader":{},datetimepicker:{days:["Sonntag","Montag","Diensteg","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["Son","Mon","Die","Mit","Don","Fri","Sam"],daysMin:["Son","Mon","Die","Mit","Don","Fri","Sam"],months:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",suffix:[],meridiem:[]},chosen:{no_results_text:"Nicht gefunden"},bootbox:{OK:"OK",CANCEL:"Stornieren",CONFIRM:"Bestätigen"}}),$.zui.lang("fr",{"zui.pager":{pageOfText:"Page {0}",prev:"Prev",next:"Suivant",first:"First",last:"Last","goto":"Goto",pageOf:"Page {page}",totalPage:"{totalPage} pages",totalCount:"Total: {recTotal} items",pageSize:"{recPerPage} per page",itemsRange:"De {start} à {end}",pageOfTotal:"Page {page} de {totalPage}"},"zui.boards":{append2end:"Aller jusqu'au bout"},"zui.browser":{tip:"Naviguez sans crainte sur Internet. Mettez votre navigateur à jour dès aujourd'hui!"},"zui.calendar":{weekNames:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],monthNames:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",year:"{0} Année",month:"{0} Mois",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Aucune icône]",commonIcons:"Icônes communes",webIcons:"Icône Web",editorIcons:"Icône de l'éditeur",directionalIcons:"Flèche confluence",otherIcons:"Autres icônes"},"zui.colorPicker":{errorTip:"Pas une valeur de couleur valide"},"zui.datagrid":{errorCannotGetDataFromRemote:"Impossible d'obtenir les données du serveur distant ({0}).",errorCannotHandleRemoteData:"Impossible de traiter les données renvoyées par le serveur distant."},"zui.guideViewer":{prevStep:"Étape précédente",nextStep:"Prochaine étape"},"zui.tabs":{reload:"Recharger",close:"Fermer",closeOthers:"Fermez les autres onglets",closeRight:"Fermer l'onglet de droite",reopenLast:"Restaurer le dernier onglet fermé",errorCannotFetchFromRemote:"Impossible d'obtenir le contenu du serveur distant ({0})."},"zui.uploader":{},datetimepicker:{days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],daysMin:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],months:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],monthsShort:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",suffix:[],meridiem:[]},chosen:{no_results_text:"Pas trouvé"},bootbox:{OK:"D'accord",CANCEL:"Annuler",CONFIRM:"Confirmer"}}); \ No newline at end of file +function(t){function e(e){if("string"==typeof e.data){var i=e.handler,n=e.data.toLowerCase().split(" ");e.handler=function(e){if(this===e.target||!/textarea|select/i.test(e.target.nodeName)&&"text"!==e.target.type){var o="keypress"!==e.type&&t.hotkeys.specialKeys[e.which],a=String.fromCharCode(e.which).toLowerCase(),s="",r={};e.altKey&&"alt"!==o&&(s+="alt+"),e.ctrlKey&&"ctrl"!==o&&(s+="ctrl+"),e.metaKey&&!e.ctrlKey&&"meta"!==o&&(s+="meta+"),e.shiftKey&&"shift"!==o&&(s+="shift+"),o?r[s+o]=!0:(r[s+a]=!0,r[s+t.hotkeys.shiftNums[a]]=!0,"shift+"===s&&(r[t.hotkeys.shiftNums[a]]=!0));for(var l=0,c=n.length;l","/":"?","\\":"|"}},t.each(["keydown","keyup","keypress"],function(){t.event.special[this]={add:e}})}(jQuery),function(t,e,i){"use strict";var n="zui.picker",o={},a={lang:null,remote:null,remoteConverter:null,remoteOnly:!1,onRemoteError:null,disableEmptySearch:!1,textKey:"text",valueKey:"value",keysKey:"keys",multi:"auto",formItem:"auto",list:null,allowSingleDeselect:null,autoSelectFirst:!1,maxSelectedCount:0,maxListCount:100,hideEmptyTextOption:!0,searchValueKey:!0,emptyResultHint:null,hideOnScroll:!0,inheritFormItemClasses:!1,emptySearchResultHint:null,accurateSearchHint:null,remoteErrorHint:null,deleteByBackspace:!0,disableScrollOnShow:!0,maxDropHeight:250,dropDirection:"auto",dropWidth:"100%",maxAutoDropWidth:450,minAutoDropWidth:100,multiValueSplitter:",",multiSelectActions:5,searchDelay:200,autoClearDrop:6e4,fixLabelFor:!0,hotkey:!0,onSelect:null,onDeselect:null,onBeforeChange:null,onChange:null,onReady:null,onNoResults:null,onShowingDrop:null,onHidingDrop:null,onShowedDrop:null,onHiddenDrop:null,valueMustInList:!0},s={zh_cn:{emptyResultHint:"没有可选项",emptySearchResultHint:"没有找到 “{0}”",accurateSearchHint:"请提供更多关键词缩小匹配范围",remoteErrorHint:"无法从服务器获取结果 - {0}",selectAll:"全选",deselectAll:"取消选择"},zh_tw:{emptyResultHint:"沒有可選項",emptySearchResultHint:"沒有找到 “{0}”",accurateSearchHint:"請提供更多關鍵詞縮小匹配範圍",remoteErrorHint:"無法從服務器獲取結果 - {0}",selectAll:"全選",deselectAll:"取消選擇"},en:{emptyResultHint:"No options",emptySearchResultHint:'Cannot found "{0}"',accurateSearchHint:"Suggest to provide more keywords",remoteErrorHint:"Unable to get result from server: {0}",selectAll:"Select all",deselectAll:"Deselect all"}},r=function(o,a){var l=this;l.name=n,l.$=t(o),l.id="pk_"+(l.$.attr("id")||t.zui.uuid()),a=l.options=t.extend({},r.DEFAULTS,this.$.data(),a),void 0!==a.hideOnWindowScroll&&(a.hideOnScroll=a.hideOnWindowScroll);var c=t.zui.clientLang?t.zui.clientLang():"en",h=a.lang||c;l.lang=t.zui.getLangData?t.zui.getLangData(n,h,s):s[h]||s[c];var d,u,p=a.formItem,f='.form-item,input[type="hidden"],select,input[type="text"]';if(d="self"===p?l.$:"auto"!==p&&p?l.$.find(p):l.$.is(f)?l.$:l.$.find(f).first(),!d.length)return console.error&&console.error("Cannot found form item for picker.");if(d.is('input[type="hidden"]'))u="hidden";else if(d.is("select"))u="select";else{if(!d.is('input[type="text"]'))return console.error&&console.error("Unknown form type for picker.");u="text"}a.inheritFormItemClasses&&v.addClass(d.attr("class")),l.formType=u,l.$formItem=d.removeClass("picker").hide(),l.selfFormItem=d.is(l.$);var g=a.multi;g&&"auto"!==g||(g="select"===u&&"multiple"===d.attr("multiple")),g=!!g,l.multi=g,g||(l.options.checkable=!1);var m=a.list;m?l.setList("function"==typeof m?m({search:l.search,limit:a.maxListCount}):m,!0):"select"===u?l.updateFromSelect():l.setList([],!0);var v;v=!l.selfFormItem&&l.$.hasClass("picker")?l.$:t('
    ').insertAfter(l.$),v.addClass("picker").toggleClass("picker-multi",g).toggleClass("picker-single",!g);var y=v.children(".picker-selections");y.length?y.empty():y=t('
    ');var b=l.id+"-search",w=t('').appendTo(y);if(!g){var x=t('
    ');a.allowSingleDeselect&&x.append(''),x.appendTo(y),l.$singleSelection=x}v.toggleClass("picker-input-empty",!w.val().length).append(y),l.$container=v,l.$selections=y,l.$search=w,l.search="";var C=a.placeholder;if(void 0===C&&(C=d.attr("placeholder")),"string"==typeof C&&C.length&&y.append(t('
    ').text(C)),a.placeholder=C,a.fixLabelFor){var _=d.attr("id");_&&t('label[for="'+_+'"]').attr("for",b)}var k=void 0!==a.defaultValue?a.defaultValue:d.val();if(null===k&&(k=""),l.setValue(k,!0),l.setDisabled(),w.on("focus",function(){l.disabled||(l._blurTimer&&(clearTimeout(l._blurTimer),l._blurTimer=0),v.addClass("picker-focus"),l.options.disableEmptySearch&&"string"==typeof l.search&&!l.search.length||l.showDropList())}).on("blur",function(){l.disabled||(l._blurTimer&&clearTimeout(l._blurTimer),l._blurTimer=setTimeout(function(){l._blurTimer=0,w.is(":focus")||v.removeClass("picker-focus")},100))}).on("input change",function(){if(!l.disabled){var t=w.val();if(g&&w.width(14*t.length),v.toggleClass("picker-input-empty",!t.length),l.tryUpdateList(t),a.disableEmptySearch){const e="string"!=typeof t||t.length;!l.dropListShowed&&e?l.showDropList():l.dropListShowed&&!e&&l.hideDropList()}}}),a.hotkey&&w.on("keydown",function(t){if(!l.disabled){var e=t.key||t.which;if(l.dropListShowed){var i=l.activeValue,n="string"==typeof i;if("Enter"===e||13===e)n&&(l.select(i,g),g?(l.$search.val(""),l.tryUpdateList("")):w.blur(),t.preventDefault(),t.stopPropagation());else if("ArrowDown"===e||40===e){var o,s=l.$activeOption;if(s&&(o=s.next(".picker-option"),g))for(;o.length&&o.hasClass("picker-option-selected");)o=o.next(".picker-option");o&&o.length||(o=l.$optionsList.children(g?".picker-option:not(.picker-option-selected)":".picker-option").first()),o.length&&l.activeOption(o),t.preventDefault(),t.stopPropagation()}else if("ArrowUp"===e||30===e){var r,s=l.$activeOption;if(s&&(r=s.prev(".picker-option"),g))for(;r.length&&r.hasClass("picker-option-selected");)r=r.prev(".picker-option");r&&r.length||(r=l.$optionsList.children(g?".picker-option:not(.picker-option-selected)":".picker-option").last()),r.length&&l.activeOption(r),t.preventDefault(),t.stopPropagation()}else"Escape"===e||27===e?l.hideDropList(!0):a.deleteByBackspace&&g&&("Backspace"===e||8===e)&&l.value&&l.value.length&&!w.val().length&&l.deselect(l.value[l.value.length-1])}}}),g){y.on("mousedown",function(t){if(!l.disabled)return l.dropListShowed&&!a.checkable?(t.preventDefault(),void t.stopPropagation()):void 0}).on("mouseup",function(e){l.disabled||y.hasClass("sortable-sorting")||t(e.target).closest(".picker-selection-remove").length||l.dropListShowed&&!a.checkable||l.focus()});var T=a.sortValuesByDnd;if(T&&t.fn.sortable){v.addClass("picker-sortable");var S={selector:".picker-selection",stopPropagation:!0,start:function(){l.hideDropList(!0)},finish:function(e){var i=[];t.each(e.list,function(t,e){i.push(e.item.data("value"))}),l.setValue(i.slice(),!1,!0)}};"object"==typeof T&&t.extend(S,T),y.sortable(S)}}if(y.on("click",".picker-selection-remove",function(e){if(!l.disabled){if(l.multi){var i=t(this).closest(".picker-selection");l.deselect(i.data("value"))}else l.deselect();e.stopPropagation()}}),d.on("chosen:updated",function(){l.updateFromSelect(!1),l.setValue(d.val(),!0),l.setDisabled(),l.updateList()}).on("chosen:activate",l.focus).on("chosen:open",l.showDropList).on("chosen:close",l.hideDropList),v.addClass("picker-ready"),t.zui.asap(function(){l.triggerEvent("ready",{picker:l},"","chosen:ready")}),!a.disableScrollOnShow){var D=a.hideOnScroll;D&&![e,i,!0].includes(D)&&t(D).on("scroll",this.handleParentScroll.bind(this))}};r.prototype.destroy=function(){var e=this,i=e.options;e.hideDropList(!0);var o=e.$search;o.off("focus blur input change"),i.hotkey&&o.off("keydown"),o.remove();var a=e.$selections;a.off("click"),e.multi&&a.off("mousedown mouseup"),a.remove();var s=e.$formItem;e.selectOptionsBackup&&(s.empty(),t.each(e.selectOptionsBackup,function(e,n){var o={value:n[i.valueKey]},a=n[i.keysKey];void 0!==a&&(o["data-"+i.keysKey]=a),s.append(t("
    ");i.$.addClass("load-indicator loading"),s.load(window.location.href+" #"+o,function(r){if(a===o)i.$.empty().html(s.children().html()),i.$.find('[data-ride="pager"]').pager();else{i.$.find("#"+o).empty().html(s.children().html());try{var l=t(r),c=l.find("#"+o).closest('[data-ride="table"],#'+a);if(c.length){var h=c.find(".table-statistic");h.length&&(i.defaultStatistic=h.html());var d=i.$.find('[data-ride="pager"]').data("zui.pager"),u=c.find('[data-ride="pager"]');d&&u.length&&d.set(u.data())}}catch(p){console.error(p)}}i.$.removeClass("load-indicator loading").trigger("beforeTableReload"),delete i.defaultStatistic,i.updateStatistic(),i.initModals(),i.$.datepickerAll();var f=i.$.find("tbody>tr"),g=!1;t.each(i.checkItems,function(t,e){e&&(i.checkRow(f.filter('[data-id="'+t+'"]'),!0,!0),g=!0)}),g&&i.updateCheckUI(),n.nested&&i.initNestedList(),i.$.trigger("tableReload");var m=t("#mainMenu>.btn-toolbar>.btn-active-text>.label");if(m.length){var u=i.$.find(".pager[data-rec-total]"),v=u.length?u.attr("data-rec-total"):i.getTable().find("tbody:first>tr:not(.table-children)").length;m.text(v)}e&&e(),n.afterReload&&n.afterReload()})},r.prototype.initModals=function(){var e=this,i=e.options,n=e.$.find(i.iframeModalTrigger);if(n.length){var o={type:"iframe",onHide:i.replaceId?function(){var n=t.cookie("selfClose");(1==n||i.hot)&&(t("#triggerModal").data("cancel-reload",1),e.reload(function(){t.cookie("selfClose",0)}))}:null};n.modalTrigger(o)}},r.prototype.getTable=function(){var t=this.$;if(this.isDataTable)return t.find("div.datatable");var e=t.is("table")?t:t.find("table:not(.fixed-header-copy)").first();return e.is(".datatable")&&(this.isDataTable=!0,e.data("zui.datatable")||window.initDatatable(e),e=t.find("div.datatable")),e},r.prototype.toggleGroups=function(e){var i=this,n={};i.$.find("tbody>tr").each(function(){var o=t(this).closest("tr").data("id");n[o]||i.toggleRowGroup(o,e)})},r.prototype.toggleRowGroup=function(i,n){var o=this.$.find('tbody>tr[data-id="'+i+'"]'),a=o.filter(".group-summary"),s=n===e?!a.hasClass("hidden"):!!n;o.not(".group-summary").toggleClass("hidden",!s),a.toggleClass("hidden",s),t("body").toggleClass("table-group-collapsed",!this.$.find("tbody>tr.group-summary.hidden").length)},r.prototype.updateStatistic=function(){var i=this,n=i.$.find(".table-statistic");if(n.length){if(i.defaultStatistic===e&&(i.defaultStatistic=n.html()),i.options.statisticCreator)return void n.html(i.options.statisticCreator(i)||i.defaultStatistic);var o=i.statisticCols;if(!o&&o!==!1){o={};var a=!1;i.getTable().find("thead th").each(function(e){var i=t(this),n=i.data("statistic");n&&(a=!0,o[e]={format:n,name:i.text()})}),i.statisticCols=!!a&&o}var s=0;o&&t.each(o,function(t){o[t].total=0,o[t].checkedTotal=0}),i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr").each(function(){var e=t(this),i=e.hasClass("checked"),n=e.children("td");i&&s++,o&&t.each(o,function(t){var e=parseFloat(n.eq(t).text());isNaN(e)&&(e=0),o[t].total+=e,i&&(o[t].checkedTotal+=e)})});var r=[];if(s)r.push(i.lang.selectedItems.format(s));else if(i.defaultStatistic)return void n.html(i.defaultStatistic);o&&t.each(o,function(t){var e=o[t],n=e[s?"checkedTotal":"total"];e.format&&(n=e.format.format(n)),r.push(i.lang.attrTotal.format(e.name,n))}),n.html(r.join(", "))}},r.prototype.updateFixUI=function(e){var i=this,n=(new Date).getTime();if(!e&&(i.lastUpdateCall&&clearTimeout(i.lastUpdateCall),!i.lastUpdateTime||n-i.lastUpdateTime
    ').append(t('
    ').addClass(i.attr("class")).append(n.clone())).insertAfter(i)),h){var d=c[0].getBoundingClientRect();l.css({left:d.left,width:c.width(),overflow:"hidden"}),l.find(".fixed-header-copy").css({left:o.left-d.left,position:"relative",minWidth:i.width()}),a||c.data("fixHeaderScroll")||(c.data("fixHeaderScroll",1),i.width()>c.width()&&c.on("scroll",function(){e.fixHeader()}))}else l.css({left:o.left,width:o.width});var u=l.find("th");n.find("th").each(function(e){u.eq(e).css("width",t(this).outerWidth())})}else l.remove()},r.prototype.fixFooter=function(){var e,i=this,n=i.getTable(),o=i.$.find(".table-footer");if(i.isDataTable)e=n[0].getBoundingClientRect();else{var a=n.find("tbody");if(!a.length)return;e=a[0].getBoundingClientRect()}var s=i.options.fixFooter;o.toggleClass("fixed-footer",!!r);var r="function"==typeof s?s(e,o):e.bottom>window.innerHeight-50-("number"==typeof s?s:i.pageFooterHeight||5);o.toggleClass("fixed-footer",!!r),n.toggleClass("with-footer-fixed",!!r),n.trigger("fixFooter",r);var l=t("body"),c=l.hasClass("body-modal");if(r){var h=n.parent(),d=h.is(".table-responsive");o.css({bottom:i.pageFooterHeight||0,left:d?h[0].getBoundingClientRect().left:e.left,width:d?h.width():e.width}),c&&l.css("padding-bottom",40)}else o.css({width:"",left:0,bottom:0}),c&&l.css("padding-bottom",0)},r.prototype.checkAll=function(e){var i=this,n=i.$.find(i.isDataTable?".fixed-left tbody>tr":"tbody>tr");n.each(function(){i.checkRow(t(this),e,!0)}),i.updateCheckUI()},r.prototype.checkRow=function(i,n,o){var a=this,s=a.getTable();a.isDataTable&&!i.is(".datatable-row-left")&&(i=s.find('.datatable-row-left[data-index="'+i.data("index")+'"]'));var r=i.find('input[type="checkbox"]');if(r.length&&!r.is(":disabled")){n===e&&(n=!r.is(":checked")),a.isDataTable?s.find('.datatable-row[data-index="'+i.data("index")+'"]').toggleClass("checked",n):i.toggleClass("checked",n);var l=i.data("id");this.checkItems[l]=n,r.prop("checked",n).trigger("change"),o||(i.hasClass("table-parent")&&s.find((a.isDataTable?".fixed-left ":"")+"tbody>tr.parent-"+l).each(function(){a.checkRow(t(this),n,!0)}),a.updateCheckUI())}},r.prototype.updateCheckUI=function(){var e=this,i=e.getTable(),n=i.find(e.isDataTable?".fixed-left tbody>tr":"tbody>tr").not(".group-summary"),o=!1,a=null,s=0,r=!1,l=n.length;n.each(function(n){var c=t(this),h=c.find('input[type="checkbox"]');if(!h.length)return void l--;r=h.is(":checked");var d=e.isDataTable?i.find('.datatable-row[data-index="'+c.data("index")+'"]'):c;d.toggleClass("checked",r),d.toggleClass("row-check-begin",r&&!o),a&&a.toggleClass("row-check-end",!r&&o),r&&(s+=1),a=d,o=r,l===n+1&&d.toggleClass("row-check-end",r)}),e.$.toggleClass("has-row-checked",s>0).find(".check-all").toggleClass("checked",!(!l||s!==l)),e.updateStatistic(),e.options.onCheckChange&&e.options.onCheckChange(),i.trigger("checkChange")},r.DEFAULTS={checkable:!0,checkOnClickRow:!0,ajaxForm:!1,selectable:!0,fixHeader:!a,fixFooter:!a,iframeWidth:900,replaceId:"self", +nestLevelIndent:18,nested:!1,preserveNested:!0,hot:!1,iframeModalTrigger:".iframe:not(.disabled,[disabled])"},t.fn.table=function(e){return this.each(function(){var n=t(this),o=n.data(i),a="object"==typeof e&&e;o||n.data(i,o=new r(this,a)),"string"==typeof e&&o[e]()})},r.NAME=i,t.fn.table.Constructor=r,t(function(){t('[data-ride="table"]').table()})}(jQuery,void 0),function(t,e,i){t.fn._ajaxForm=t.fn.ajaxForm;var n={timeout:e.config?e.config.timeout:0,dataType:"json",method:"post"},o="";t.fn.enableForm=function(e,n,o){return e===i&&(e=!0),this.each(function(){var i=t(this);n||i.find('[type="submit"]').attr("disabled",e?null:"disabled"),!o&&i.hasClass("load-indicator")&&i.toggleClass("loading",!e),i.toggleClass("form-disabled",!e)})},t.enableForm=function(e,i,n,o){"string"==typeof e||e instanceof t?e=t(e):(o=n,n=i,i=e,e=t("form")),e.enableForm(i!==!1,n,o)},t.disableForm=function(e,i,n){t.enableForm(e,!1,i,n)};var a=function(e,i,n){i=i||"show",t.zui.messager?(n?n.html=!0:n={html:!0},e=e.toString().replace(/\n/g,"
    "),t.zui.messager[i](e,n)):alert(e)};t.ajaxForm=function(s,r){var l=t(s);if(l.length>1)return l.each(function(){t.ajaxForm(this,r)});"function"==typeof r&&(r={complete:r}),r=t.extend({},n,l.data(),r);var c=r.beforeSubmit,h=r.error,d=r.success,u=r.finish;delete r.finish,delete r.success,delete r.onError,delete r.beforeSubmit,r=t.extend({beforeSubmit:function(n,a,s){if((c&&c(n,a,s))===!1)return!1;l.removeClass("form-watched").enableForm(!1);var r={},h=a.find('[type="file"]');r.fileapi=h.length&&h[0].files!==i,r.formdata=e.FormData!==i;var d=r.fileapi&&a.find('input[type="file"]:enabled').filter(function(){return""!==t(this).val()}),u=d.length,p="multipart/form-data",f=a.attr("enctype")==p||a.attr("encoding")==p,g=r.fileapi&&r.formdata,m=u&&!g||f&&!r.formdata;m&&(""==o&&(o=s.url),s.url!=o&&(s.url=o),s.url=s.url.indexOf("&")>=0?s.url+"&HTTP_X_REQUESTED_WITH=XMLHttpRequest":s.url+"?HTTP_X_REQUESTED_WITH=XMLHttpRequest")},success:function(i,n,o){if((d&&d(i,n,o,l))!==!1){try{"string"==typeof i&&(i=JSON.parse(i))}catch(s){}if(null===i||"object"!=typeof i)return i?alert(i):a("No response.","danger");var c=r.responser?t(r.responser):l.find(".form-responser");c.length||(c=t("#responser"));var h=i.message,p=function(){var n=i.callback;if(n)if("object"==typeof n){var o=n.target?e[n.target]:e,a=o[n.name];a.apply(l,Array.isArray(n.params)?n.params:[n.params])}else{var s=n.indexOf("("),r=(s>0?n.substr(0,s):n).split("."),c=e,h=r[0];r.length>1&&(h=r[1],"top"===r[0]?c=e.top:"parent"===r[0]&&(c=e.parent));var a=c[h];if("function"==typeof a){var d=[];return s>0&&")"==n[n.length-1]&&(d=t.parseJSON("["+n.substring(s+1,n.length-1)+"]")),d.push(i),a.apply(l,d)}}};if("success"===i.result){var f=r.locate||i.locate,g=r.closeModal||i.closeModal,m=r.ajaxReload||i.ajaxReload;if(l.enableForm(!0,!!(f||g||m)),h){var v=l.find('[type="submit"]').first(),y=!1;v.length&&(v.popover({container:"body",trigger:"manual",content:h,tipClass:"popover-in-modal popover-success popover-form-result",placement:i.placement||v.data("placement")||r.popoverPlacement||"right"}).popover("show"),setTimeout(function(){v.popover("destroy")},r.popoverTime||2e3),y=!0),c.length&&(c.html(''+h+"").show().delay(3e3).fadeOut(100),y=!0),y||a(h,"success")}if(u)return u(i,!0,l);if(g&&setTimeout(t.zui.closeModal,"number"==typeof g?g:r.closeModalTime||2e3),p()===!1)return;if(f)if("loadInModal"==f){var b=t(".modal");setTimeout(function(){b.load(b.attr("ref"),function(){t(this).find(".modal-dialog").css("width",t(this).data("width")),t.zui.ajustModalPosition()})},1e3)}else"parent"===f||"top"===f?e[f]&&setTimeout(function(){e[f].location.reload()},1200):"reload"===f?setTimeout(function(){e.location.href=e.location.href},1200):setTimeout(function(){t.apps?t.apps.open(f):e.location.href=f},1200);if(m){var w=t(m);w.length&&w.load(e.location.href+" "+m,function(){w.find('[data-toggle="modal"]').modalTrigger()})}}else{if(l.enableForm(),"string"==typeof h)c.length?c.html(''+h+"").show().delay(3e3).fadeOut(100):a(h,"danger");else if("object"==typeof h){var x=!1,C=[];t.each(h,function(e,i){var n=t.isArray(i)?i.join(""):i,o=t("#"+e);if(!o.length)return void C.push(n);var a=e+"Label",s=t("#"+a);if(!s.length){var r=o.closest(".input-group").length,l=o.closest("td").length;s=t('
    ').appendTo(l?o.closest("td"):r?o.closest(".input-group").parent():o.parent())}s.empty().append(n),o.addClass("has-error");var c=function(){var e=t("#"+a);if(e.length)return e.remove(),o.removeClass("has-error"),!0};o.on("change input mousedown",c);var h=t("#"+e+"_chosen");if(h.length&&h.find(".chosen-single,.chosen-choices").addClass("has-error").on("mousedown",function(){c()===!0&&t(this).removeClass("has-error")}),!x&&!o.data("datetimepicker")){var d=o[0];if(o.hasClass("chosen"))o.trigger("chosen:activate").trigger("chosen:open"),d=o.parent().find(".chosen-container")[0];else if(o.is("textarea")&&o.data("keditor")){var u=o.data("keditor");u.focus(),u.edit.doc.body.focus(),d=o.parent().find(".ke-container")[0]}else o.focus();d.scrollIntoView&&d.scrollIntoView(),x=!0}}),C.length&&a(C.join(""),"danger")}if(u)return u(i,!1,l);if(p()===!1)return}}},error:function(t,i,n){if((h&&h(t,i,n,l))!==!1){l.enableForm();var o="timeout"==i||"error"==i?e.lang?e.lang.timeout:i:t.responseText+i+n;a(o,"danger")}}},r),l._ajaxForm(r).data("zui.ajaxform",!0),l.on("click","[data-form-action]",function(){l.attr("action",t(this).data("formAction")).submit()})},t.setAjaxForm=function(e,i,n){t.ajaxForm(e,t.isPlainObject(i)?i:{finish:i,beforeSubmit:n})},t.fn.ajaxForm=function(e){return this.each(function(){t.ajaxForm(this,e)})},t.fn.setInputRequired=function(){return this.each(function(){var e=t(this),i=e.parent();i.is(".input-control,td")?i.addClass("required"):e.is(".chosen")?e.attr("required",null).next(".chosen-container").addClass("required"):i.addClass("required"),e.attr("required",null);var n=i.closest(".input-group");n.length&&1===n.find(".required,input[required],select[required]").length&&n.addClass("required")})},t(function(){t('.form-ajax,form[data-type="ajax"]').ajaxForm(),setTimeout(function(){var i=e.config.requiredFields,n=t("form");i&&(i=i.split(",")),i&&i.length&&t.each(i,function(t,e){n.find("#"+e).attr("required","required")}),n.find("input[required],select[required],textarea[required]").setInputRequired()},400),t('form[target="hiddenwin"]').on("submit",function(){var e=t(this);e.data("zui.ajaxform")||e.enableForm(!1).data("disabledTime",(new Date).getTime())}).on("click",function(){var e=t(this),i=e.data("disabledTime");i&&(new Date).getTime()-i>1e4&&e.enableForm(!0).data("disabledTime",null)})})}(jQuery,window,void 0),function(t){"use strict";var e="zui.searchList",i=function(t,e){if(t&&t.length)for(var i=0;i
    ').append(s)),i.$menu.append(s),i.$menu.removeClass("loading"),i.isLoaded=!0,e&&e(!0)},error:function(){i.$menu.removeClass("loading").append('
    '+(n.errorText||window.lang&&window.lang.timeout)+"
    "),e&&e(!1)}},n.ajax))},n.prototype.scrollTo=function(t){t.length&&t[0].scrollIntoViewIfNeeded&&t[0].scrollIntoViewIfNeeded({behavior:"smooth"})},n.prototype.getItems=function(){return this.$.find(this.options.selector).addClass("search-list-item")},n.prototype.getActiveItem=function(){return this.getItems().filter(".active:first")},n.prototype.search=function(e){var n=this,o=void 0===e||null===e||""===e;n.$.toggleClass("has-search-text",!o);var a=n.getItems().removeClass("active");if(o)a.removeClass("hidden");else{var s=e.trim().split(" ");a.each(function(){var e=t(this),n=(e.text()+" "+(e.data("key")||e.data("filter")||"")).trim();e.toggleClass("hidden",!i(s,n))})}n.scrollTo(a.not(".hidden").first().addClass("active")),n.$.trigger("onSearchComplete",e)},n.DEFAULTS={selector:".list-group a:not(.not-list-item)",searchBox:".search-box",onSelectItem:null},t.fn.searchList=function(i){return this.each(function(){var o=t(this),a=o.data(e),s="object"==typeof i&&i;a||o.data(e,a=new n(this,s)),"string"==typeof i&&a[i]()})},n.NAME=e,t.fn.searchList.Constructor=n,t(function(){t('[data-ride="searchList"]').searchList()})}(jQuery),function(t){"use strict";var e="zui.labelSelector",i=function(n,o){var a=this;a.name=e,a.$=t(n),o=a.options=t.extend({},i.DEFAULTS,this.$.data(),o),a.$.hide(),a.update()};i.prototype.select=function(t){t+="",this.$wrapper.find(".label.active").removeClass("active"),this.$wrapper.find('.label[data-value="'+t+'"]').addClass("active"),this.$.val(t).trigger("change")},i.prototype.update=function(){var e=this,i=e.options,n=e.$wrapper;if(!n){if(i.wrapper)n=t(i.wrapper);else{var o=e.$.next();n=o.hasClass(".label-selector")?o:t('
    ')}n.parent().length||e.$.after(n),e.$wrapper=n,n.on("click",".label",function(i){var n=e.$.val(),o=t(this).data("value");e.hasEmptyValue!==!1&&o==n&&(o=e.hasEmptyValue),e.select(o),i.preventDefault()})}n.empty();var a=e.$.val();e.hasEmptyValue=!1,e.$.children("option").each(function(){var e=t(this),o={label:e.text(),value:e.val()},s=(""===o.value||"0"===o.value)&&!o.label,r=t(i.labelTemplate||'');i.labelClass&&!s&&r.addClass(i.labelClass),i.labelCreator?r=i.labelCreator(r):(r.data("option",o).attr("data-value",o.value),s?r.addClass("empty").append(''):r.text(o.label).toggleClass("active",a===o.value)),n.append(r)})},i.DEFAULTS={},t.fn.labelSelector=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.labelSelector.Constructor=i,t(function(){t('[data-provide="labelSelector"]').labelSelector()})}(jQuery),function(t){"use strict";var e="zui.fileInput",i=t.BYTE_UNITS={B:1,KB:1024,MB:1048576,GB:1073741824,TB:1099511627776},n=t.formatBytes=function(t,e,n){return void 0===e&&(e=2),n||(n=ts.fileMaxSize&&(c.val(""),(window.bootbox||window).alert(s.fileSizeError.format(n(s.fileMaxSize)))),r.update()}),r.update()};a.prototype.getFile=function(){var t=this.$input.prop("files");return t&&t[0]},a.prototype.update=function(){var t=this,e=t.$,i=t.getFile(),o=!i;e.toggleClass("normal",!o).toggleClass("empty",o),i?(t.oldName=i.name,e.find(".file-title").text(i.name).attr("title",i.name),e.find(".file-size").text(n(i.size)),e.find(".file-editbox").val(i.name).attr("size",i.name.length),t.options.onSelect&&t.options.onSelect(i,t)):e.find(".file-editbox").val("")},a.DEFAULTS={fileMaxSize:0,fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInput=function(i){return this.each(function(){var n=t(this),o=n.data(e),s="object"==typeof i&&i;o||n.data(e,o=new a(this,s)),"string"==typeof i&&o[i]()})},a.NAME=e,t.fn.fileInput.Constructor=a,t(function(){t('[data-provide="fileInput"]').fileInput()});var s="zui.fileInputList",r=function(e,i){var n=this;n.name=s;var o=n.$=t(e);i=n.options=t.extend({},r.DEFAULTS,this.$.data(),i),n.$template=o.find(".file-input").detach(),n.add()};r.prototype.add=function(){var t=this,e=t.options,i=t.$template.clone();"before"===e.appendWay?t.$.prepend(i):t.$.append(i),i.fileInput({fileMaxSize:e.eachFileMaxSize,fileSizeError:e.fileSizeError,onDelete:function(e){e.$.remove(),t.options.onDelete&&t.options.onDelete(e,t)},onSelect:function(e,i){t.add(),t.options.onSelect&&t.options.onSelect(e,i,t)}})},r.DEFAULTS={fileMaxSize:0,eachFileMaxSize:0,appendWay:"after",fileSizeError:"无法上传大于 {0} 的文件。"},t.fn.fileInputList=function(e){return this.each(function(){var i=t(this),n=i.data(s),o="object"==typeof e&&e;n||i.data(s,n=new r(this,o)),"string"==typeof e&&n[e]()})},r.NAME=s,t.fn.fileInputList.Constructor=r,t(function(){t('[data-provide="fileInputList"]').fileInputList()})}(jQuery),function(t){window.config||(window.config={}),t.createLink=window.createLink=function(e,n,o,a,s,r,l){if("object"==typeof e)return t.createLink(e.moduleName,e.methodName,e.vars,e.viewType,e.isOnlyBody,e.hash,e.tid);if(t.tabSession&&!l&&(l=t.tabSession.getTid()),a||(a=config.defaultView),s||(s=!1),o)for("string"==typeof o&&(o=o.split("&")),i=0;i'+d+"")}}t.val()||(time=e(a.format("hh:mm")),time=time-time%10+10,t.val(n(time)))};t.fn.timeSpanControl=function(i){return this.each(function(){var s=t(this),r=t.extend({},i,s.data()),l=s.find('[name="begin"],.control-time-begin'),c=s.find('[name="end"],.control-time-end'),h=function(){var t=l.val();if(s.find(".hide-empty-begin").toggleClass("hide",!t),t){var i=n(e(t)+30);c.find('option[value="'+i+'"]').length&&c.val(i),r.onChange&&r.onChange(c,i)}};if(s.data("timeSpanControlInit")){if(r.begin){var d=o(r.begin).format("hh:mm");l.find('option[value="'+d+'"]').length&&l.val(d),r.onChange&&r.onChange(l,d)}if(r.end){var u=o(r.end).format("hh:mm");c.find('option[value="'+u+'"]').length&&c.val(u),r.onChange&&r.onChange(c,u)}}else l.on("change",h),a(l,r.begin),a(c,r.end),s.data("timeSpanControlInit",!0);r.end||h()})},t.timeSpanControl={convertTimeToNum:e,convertNumToTime:n,initTimeSelect:a,createTime:o};var s=t.setSearchType=function(e,i){var n=t("#searchType");e||(e=n.val()),e=e||"bug",n.val(e);var o=t("#searchTypeMenu");o.find("li.selected").removeClass("selected");var a=o.find('a[data-value="'+e+'"]'),s=a.text();a.parent().addClass("selected"),t("#searchTypeName").text(s),i||t("#searchInput").focus()};t.gotoObject=function(e,i){if(e||(e=t("#searchType").val()),i||(i=t("#searchInput").val()),i&&e)if(i=i.replace(/[^\d]/g,"")){var n=e.split("-");e=n[0];var o=n.length>1?n[1]:"testsuite"===e?"library":"view",a=t.createLink(e,o,"id="+i);t.apps?t.apps.open(a):window.location.href=a}else{var s={zh_cn:"请输入数字ID进行搜索",zh_tw:"請輸入數值ID行搜索"};alert(lang.searchTip||s[t.zui.clientLang()]||"Please enter a numberic id to search")}t("#searchInput").val(i).focus()},t(function(){s(null,!0),t(document).on("keydown",function(e){e.ctrlKey&&71===e.keyCode&&(t("#searchInput").val("").focus(),e.stopPropagation(),e.preventDefault())})}),t.removeAnchor=window.removeAnchor=function(t){var e=t.lastIndexOf("#");return e>-1?t.substr(0,e):t},t.refreshPage=function(t){t?window.top.location.reload():window.location.reload()},t.selectLang=window.selectLang=function(e){t.cookie("lang",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectLang"),t.refreshPage(1)},t.selectTheme=window.selectTheme=function(e){t.cookie("theme",e,{expires:config.cookieLife,path:config.webRoot}),t.ajaxSendScore("selectTheme"),t.refreshPage(1)},t.zui.Picker&&(t.extend(t.zui.Picker.DEFAULTS,{optionRender:function(e,i,n){if("user"===n.options.type){var o=n.options.users;if(!o)return;var a=o[i.value];if(!a)return;if(e.find(".picker-option-text").text(a.realname||a.account),e.hasClass("picker-user-option"))return;return e.prepend(t('
    ').avatar({user:a})),a.deptName&&e.append(t('').text(a.deptName)),a.roleName&&e.append(t('').text(a.roleName)),e.addClass("picker-user-option")}},checkable:!0,maxListCount:500,disableScrollOnShow:!1}),t.zui.setUserPickerInfos=function(e){t.zui.Picker.DEFAULTS.users=t.extend({},t.zui.Picker.DEFAULTS.users,e)},t(function(){t(".picker-select[data-pickertype!='remote']").picker({chosenMode:!0}),t("[data-pickertype='remote']").each(function(){var e=t(this).attr("data-pickerremote");t(this).picker({chosenMode:!0,remote:e})}),window.pickerUsers&&t.zui.setUserPickerInfos(window.pickerUsers),t(".user-picker").picker({type:"user"})})),t.chosenDefaultOptions={middle_highlight:!0,disable_search_threshold:1,compact_search:!0,allow_single_deselect:!0,placeholder_text_single:" ",placeholder_text_multiple:" ",search_contains:!0,max_drop_width:500,max_drop_height:245,no_wrap:!0,drop_direction:function(){var e=t(this.container).closest(".table-responsive:not(.scroll-none)");if(e.length){if(this.drop_directionFixed)return this.drop_directionFixed;e.css("position","relative");var i="down",n=this.container.find(".chosen-drop"),o=this.container.position(),a=n.outerHeight();return o.top>=a&&o.top+31+a>e.outerHeight()&&(i="up"),this.drop_directionFixed=i,i}return"auto"}},t.chosenSimpleOptions=t.extend({},t.chosenDefaultOptions,{disable_search_threshold:6}),t.fn._chosen=t.fn.chosen,t.fn.chosen=function(e){return"string"==typeof e?this._chosen(e):this.each(function(){var i=t(this).addClass("chosen-controled");return i._chosen(t.extend({},i.hasClass("chosen-simple")?t.chosenSimpleOptions:t.chosenDefaultOptions,i.data(),e))})},t.fn.chosen.Constructor=t.fn._chosen.Constructor,t(function(){t(".chosen,.chosen-simple").each(function(){var e=t(this);e.closest(".template").length||e.chosen()})}),t.extend(t.fn.pager.Constructor.DEFAULTS,{maxNavCount:8,prevIcon:"icon-angle-left",nextIcon:"icon-angle-right",firstIcon:"icon-first-page",lastIcon:"icon-last-page",navEllipsisItem:"…",menuDirection:"dropup",pageSizeOptions:[5,10,15,20,25,30,35,40,45,50,100,200,500,1e3,2e3],elements:["total_text","size_menu","first_icon","prev_icon",'
    {page}/{totalPage}
    ',"next_icon","last_icon"],onPageChange:function(e,i){e.recPerPage!==i.recPerPage&&t.cookie(this.options.pageCookie,e.recPerPage,{expires:config.cookieLife,path:config.webRoot}),e.recPerPage!==i.recPerPage&&(window.location.href=this.createLink())}}),t.extend(!0,t.zui.Messager.DEFAULTS,{cssClass:"messagger-zt",icons:{success:"check-circle",info:"chat-line",warning:"exclamation-sign",danger:"exclamation-sign"}}),t.fn.reverseOrder=function(){return this.each(function(){var e=t(this);e.prependTo(e.parent())})};var r=function(e,i){var n=t(e);if(!n.data("historiesInited")){n.data("historiesInited",1),i=t.extend({},n.data(),i);var o=n.find(".histories-list"),a=!0,s=!1;n.on("click",".btn-reverse",function(){o.children("li").reverseOrder(),a=!a,t(this).find(".icon").toggleClass("icon-arrow-up",a).toggleClass("icon-arrow-down",!a);var e="#lastComment",i=t(e);i.length&&window.KindEditor&&(window.KindEditor.remove(e),i.kindeditor())}).on("click",".btn-expand-all",function(){var e=t(this).find(".icon");s=!s,e.toggleClass("icon-plus",!s).toggleClass("icon-minus",s),o.children("li").toggleClass("show-changes",s)}).on("click",".btn-expand",function(){t(this).closest("li").toggleClass("show-changes")}).on("click",".btn-strip",function(){var e=t(this),n=e.find(".icon"),o=n.hasClass("icon-code");n.toggleClass("icon-code",!o).toggleClass("icon-text",o),e.attr("title",o?i.original:i.textdiff),e.closest("li").toggleClass("show-original",o)}),o.find(".btn-strip").attr("title",i.original);var r=n.find(".modal-comment").modal({show:!1}).on("shown.zui.modal",function(){var t=r.find("#comment");t.length&&(t.focus(),window.editor&&window.editor.comment&&window.editor.comment.focus())}).on("show.zui.modal",function(){var e=r.find("#comment");e.length&&!e.data("keditor")&&t.fn.kindeditor&&e.kindeditor()});n.on("click",".btn-comment",function(t){r.modal("toggle"),t.preventDefault()}).on("click",".btn-edit-comment,.btn-hide-form",function(){t(this).closest("li").toggleClass("show-form")});var l=n.find(".comment-edit-form");l.ajaxForm({success:function(t,e,i,n){setTimeout(function(){l.closest("li").removeClass("show-form")},2e3)}})}};t.fn.histories=function(t){return this.each(function(){r(this,t)})},t(function(){t(".histories").histories()});var l=0,c=0;t.toggleSidebar=function(e){var i=t("#sidebar");if(i.length){var n=t("main");if(void 0===e)e=n.hasClass("hide-sidebar");else if(e&&!n.hasClass("hide-sidebar"))return;n.toggleClass("hide-sidebar",!e),clearTimeout(l),t.zui.store.set(c,e);var o=i.children(".cell"),a={overflow:"visible",maxHeight:"initial"};e?(i.addClass("showing"),l=setTimeout(function(){i.removeClass("showing"),i.trigger("sidebar.toggle",e)},210)):(i.trigger("sidebar.toggle",e),t(window).width()<1900&&(a={overflow:"hidden",maxHeight:t(window).height()-45})),o.css(a)}};var h=t.initSidebar=function(){var e=t("#sidebar");if(e.length){if(e.data("init"))return!0;c="sidebar:"+(e.data("id")||config.currentModule+"/"+config.currentMethod);var i=t("main");if(i.length){i.on("click",".sidebar-toggle",function(){t.toggleSidebar(i.hasClass("hide-sidebar"))});var n=t.zui.store.get(c,e.data("hide")!==!1);n===!1&&e.addClass("no-animate"),t.toggleSidebar(n),n===!1&&setTimeout(function(){e.removeClass("no-animate")},500);var o=e.find(".sidebar-toggle");if(o.length){var a=function(){var e=o[0].getBoundingClientRect(),i=t(window).height(),n=Math.max(0,Math.floor(Math.min(i-40,e.top+e.height)-Math.max(e.top,0))/2)+(e.top<0?0-e.top:0);o.removeClass("fade").find(".icon").css("top",n+(t.zui.browser.isIE()?(i-80)/2:0))};a(),e.data("init",1).on("sidebar.toggle",a);var s=t.zui.browser.isIE()?1500:0,r=0,l=null,h=function(){var t=Date.now();return l&&(clearTimeout(l),l=null),t-rtr input[type="checkbox"]:checked');i.each(function(){var i=parseInt(t(this).val(),10);NaN!==i&&e.push(i)}),t.cookie("checkedItem",e.join(","),{expires:config.cookieLife,path:config.webRoot})},t.extend(t.fn.modal.bs.Constructor.DEFAULTS,{scrollInside:!0,backdrop:"static",headerHeight:100}),t.extend(t.zui.ModalTrigger.DEFAULTS,{scrollInside:!0,backdrop:"static"}),t.fn.initIframeModal=function(){return this.each(function(){var e=t(this);if(!e.is("[disabled],.disabled")&&!e.parents('[data-ride="table"],.skip-iframe-modal').length){var i={type:"iframe"};e.hasClass("export")&&t.extend(i,{width:800,shown:setCheckedCookie},e.data()),e.modalTrigger(i)}})},t(function(){t("a.iframe,.export").initIframeModal()}),t.fixedTableHead=window.fixedTableHead=function(e,i){var n=t(e);if(n.is("table")||(n=n.find("table")),n.length){var o=t(i||window),a=null,s=function(){var e=n.children("thead"),i=e[0].getBoundingClientRect(),o=n.next(".fixed-head-table");if(i.top<0){var s=e.width();if(o.length){if(a!==s){a=s;var r=o.find("th");e.find("th").each(function(e){r.eq(e).width(t(this).width())})}}else{var o=t("
    ").addClass(n.attr("class")),l=e.clone(),r=l.find("th");e.find("th").each(function(e){r.eq(e).width(t(this).width())}),o.append(l).insertAfter(n)}o.css({left:i.left,width:i.width}).show()}else o.hide()};o.on("scroll",s).on("resize",s),s()}},t(document).on("click","tr[data-url]",function(){var e=t(this),i=e.data("href")||e.data("url");i&&(window.location.href=i)}),"yes"===config.onlybody&&self===parent&&(window.location.href=window.location.href.replace("?onlybody=yes","").replace("&onlybody=yes","")),t(function(){t("body").addClass("m-{currentModule}-{currentMethod}".format(config))});var d,u,p,f,g,m=function(){d||(d=t("#subNavbar"),u=t("#pageNav"),p=t("#pageActions"),f=d.children(".nav"),g=f.outerWidth());var e=d.outerWidth(),i=u.outerWidth()||0,n=p.outerWidth()||0;if(i=i?i+15:0,n=n?n+15:0,!i&&!n)return void f.css({maxWidth:null,left:null,position:"static"});var o=Math.max(300,e-i-n),a=Math.min(o,g),s=(e-a)/2,r=i&&s.btn-toolbar");if(e.length){var i,n,o=e.children(),a=o.length,s=!1,r=null;if(a)for(o.each(function(e){i=t(this),n=i.is(".divider"),n&&!r&&i.hide(),s||n||(s=!0),r=n?null:i,!n||e!==a-1&&0!==e||i.hide()});i.length&&i.is(".divider");)i=i.hide().prev();s||e.hide()}};t(function(){t(".input-group,.btn-group").fixInputGroup(),x()}),window.holders&&t.each(window.holders,function(e){var i=t("#"+e);i.length&&i.is("input")&&i.attr("placeholder",window.holders[e])}),t(function(){var e=t(".table-responsive"),i=t.fixTableResponsive=function(){e.each(function(){this.scrollHeight-3<=this.clientHeight&&this.scrollWidth-3<=this.clientWidth?t(this).addClass("scroll-none").css("overflow","visible"):t(this).removeClass("scroll-none").css("overflow","auto"); +})};e.length&&(t(window).on("resize",i),setTimeout(i,100))});var C=function(){var e=this,i=t(e),n=i.closest("tr").find("textarea");if(n.length){var o=32;n.each(function(){var e=t(this).closest("td"),i=e.css("height");e.css("height",this.style.height),this.style.height="auto";var n=this.value?this.scrollHeight+2:32;o=Math.max(o,n),e.css("height",i)}),n.css("height",o)}else{e.style.height="auto";var a=e.value?e.scrollHeight+2:32;e.style.height=a+"px"}};t.autoResizeTextarea=function(e){t(e).each(C)},t(function(){t("textarea.autosize").each(C),t(document).on("input paste change","textarea.autosize",C)}),t(function(){var e=t("#dropMenu,.drop-menu");e.length&&e.on("click",".toggle-right-col",function(e){t(this).closest("#dropMenu,.drop-menu").toggleClass("show-right-col"),e.stopPropagation(),e.preventDefault()})});var _="undefined"!=typeof InstallTrigger;t.zui.browser.firefox=_,t("html").toggleClass("is-firefox",_).toggleClass("not-firefox",!_),t(function(){var e=t("#mainContent>.main-col"),i=e.children(".main-actions");if(i.length){var n=i.prev();if(i.length&&n.length){t('
    ').css("height",i.outerHeight()).insertAfter(i);var o=0,a=function(){var e=n[0].getBoundingClientRect(),s=e.top+e.height+120>t(window).height();if(t("body").toggleClass("main-actions-fixed",s),s){var r=n.width();r?i.width(r):o<10&&setTimeout(a,1e3)}o++};t.resetToolbarPosition=a,a(),t(window).on("resize scroll",a)}}}),t(document).on("show.zui.modal",function(e){t("body.body-modal").length&&window.parent&&window.parent!==window&&t(e.target).is(".modal")&&window.parent.$("body").addClass("hide-modal-close")}).on("hidden.zui.modal",function(e){t("body.body-modal").length&&window.parent&&window.parent!==window&&window.parent.$("body").removeClass("hide-modal-close")}).on("loaded.zui.modal",function(e){t("body").removeClass("hide-modal-close")}),t(function(){var e=t(".dropdown-menu.with-search");e.length&&(e.find(".menu-search").on("click",function(t){return t.stopPropagation(),!1}),e.on("keyup change paste","input",function(){var e=t(this),i=e.closest(".dropdown-menu.with-search"),n=e.val().toLowerCase(),o=i.find(".option");""==n?o.removeClass("hide"):o.each(function(){var e=t(this);e.toggleClass("hide",e.text().toString().toLowerCase().indexOf(n)<0&&e.data("key").toString().toLowerCase().indexOf(n)<0)})}),e.parents(".dropdown-submenu").one("mouseenter",function(){var e=t(this).find(".dropdown-list")[0];e&&e.getBoundingClientRect&&setTimeout(function(){var i=270,n=e.getBoundingClientRect();n.top<0&&(i=Math.min(270,n.height)+n.top),e.style.maxHeight=Math.min(270,i,t(window).height()-28)+"px"},50)})),t(".dropdown-menu.with-search .menu-search").on("click",function(t){return t.stopPropagation(),!1})})}(jQuery),function(t){function e(){if(!config.skipRedirect&&!window.skipRedirect){var e=window.parent,i=config.currentModule,n=config.currentMethod;if("file"!==i||"download"!==n){var o="index"===i&&"index"===n,a="#_single"===location.hash||/(\?|\&)_single/.test(location.search)||o||!t("#mainHeader,#editorNav").length||"tutorial"===i||"install"===i||"upgrade"===i||"user"===i&&("login"===n||"deny"===n)||"my"===i&&"changepassword"===n||t("body").hasClass("allow-self-open"),s=location.href;if(e===window&&!a){var r=location.pathname+location.search+location.hash;return void(location.href=t.createLink("index","index","")+"#app="+encodeURIComponent(r))}if(e!==window&&e.$.apps){o&&e.location.reload();var l=window.name;if(0===l.indexOf("app-")){t.apps=window.apps=e.$.apps;var c=l.substring(4);t.appCode=c,t(document).on("click",function(t){var i=e.document.getElementById(window.name);if(i){var n=e.document.getElementById(i.name)||i;if(n){var o;"function"==typeof Event?o=new Event(t.type,{bubbles:!0}):(o=document.createEvent("Event"),o.initEvent(t.type,!0,!0)),n.dispatchEvent(o)}}}).on("click","a,.open-in-app,.show-in-app",function(e){var i=t(this);if(!i.is("[data-modal],[data-toggle],[data-ride],[data-tab],.iframe,.not-in-app,[target]")&&!i.data("zui.modaltrigger")){var n=i.hasClass("show-in-app")?"":i.attr("href")||(i.is("a")?"":i.data("url")),o=i.data("app")||i.data("group");if(n){if(0===n.indexOf("javascript:")||"#"===n[0])return;var a=t.parseLink(n);if(a.external||"file"===a.moduleName&&"download"===a.methodName)return;if("index"===a.moduleName&&"index"===a.methodName)return window.location.reload(),void e.preventDefault()}else if(!o)return;o||(o=t.apps.getAppCode(n)),o&&("help"===o&&(t.apps.appsMap.help.text=i.text(),t.apps.appsMap.help.url||(t.apps.appsMap.help.url=n)),t.apps.open(n,o)&&e.preventDefault())}}),t.apps.updateUrl(c,s,document.title)}}}}}function i(){var e=t("#navbar>.nav");if(e.length){var i=t("#heading"),n=+i.css("left").replace("px",""),o=i.outerWidth(),a=e.width(),s=t("#mainHeader>.container").width()-2*n,r=Math.floor((s-a)/2);e.css("marginLeft",r>>0;if(0===o)return!1;for(var a=0|e,s=Math.max(a>=0?a:o-Math.abs(a),0);s1&&("?"===e[0]&&(e=e.substr(1)),e.split("&").forEach(function(t){var e=t.split("=",2);if(e.length>1)try{i[e[0]]=decodeURIComponent(e[1])}catch(n){i[e[0]]=""}else i[e[0]]=""})),t?i[t]:i},t.parseLink=function(e){if(!e)return{};var i=0===e.indexOf("http:")||0===e.indexOf("https:");if(i){var n=window.location.origin;if(e.indexOf(n)<0)return{external:!0,url:e};e=e.substr((n+config.webRoot).length)}var o=e.split("#"),a=o[0].split("?"),s=a[1],r=s?t.getSearchParam("",s):{},l=a[0],c={url:e,isOnlyBody:"yes"===r.onlybody,vars:[],hash:o[1]||"",params:r,tid:r.tid||""};if("GET"===config.requestType){c.moduleName=r[config.moduleVar]||"index",c.methodName=r[config.methodVar]||"index",c.viewType=r[config.viewVar]||config.defaultView;for(var h in r)h!==config.moduleVar&&h!==config.methodVar&&h!==config.viewVar&&"onlybody"!==h&&"tid"!==h&&c.vars.push([h,r[h]])}else{var d=l.lastIndexOf("/");d===l.length-1&&(l=l.substr(0,d),d=l.lastIndexOf("/")),d>=0&&(l=l.substr(d+1));var u=l.lastIndexOf(".");u>=0?(c.viewType=l.substr(u+1),l=l.substr(0,u)):c.viewType=config.defaultView;var p=l.split(config.requestFix);if(c.moduleName=p[0]||"index",c.methodName=p[1]||"index",p.length>2)for(var f=2;f.nav>li").length>10&&(i(),t(window).on("resize",i)),setTimeout(n,1e3)})}(jQuery),function(t){"use strict";function e(e,i){"object"!=typeof i&&(i={user:i});var n=t(e);i=t.extend({},n.data(),i);var o=i.user;"string"==typeof o&&(o={account:o});var a={},s=i.size;s&&(a.width=s,a.height=s,a.lineHeight=s,Number.isNaN(+s)||n.addClass("size-"+s));var r=!!o.avatar;if(n.toggleClass("has-image",r).toggleClass("has-text",!r),n.empty(),r)n.append(t("").attr("src",o.avatar));else{var l=t.zui.strCode(o.account)*(i.hueDistance||43)%360;a.background="hsl("+l+","+(i.saturation||"40%")+","+(i.lightness||"60%")+")",Number.isNaN(+s)||(a.fontSize=Math.round(s/2)+"px");var c=o.name||o.realname||o.account;c=/^[\u4e00-\u9fa5\s]+$/.test(c)?c.length<=2?c:c.substring(c.length-2):/^[A-Za-z\d\s]+$/.test(c)?c[0].toUpperCase():c.length<=2?c:c.substring(0,2),n.append(t('').text(c))}return n.css(a)}t.fn.avatar=function(t){return this.each(function(){e(this,t)})}}(jQuery),$.zui.lang("de",{"zui.pager":{pageOfText:"Seite {0}",prev:"Zurück",next:"Nächste Seite",first:"Erste Seite",last:"Letzte Seite","goto":"Goto",pageOf:"Seite {page}",totalPage:"{totalPage} Seiten",totalCount:"Total: {recTotal} Artikel",pageSize:"{recPerPage} Artikel pro Seite",itemsRange:"Seiten {start} bis {end}",pageOfTotal:"Seite {page}/{totalPage}"},"zui.boards":{append2end:"Gehen Sie zum Ende"},"zui.browser":{tip:"Online. Sorgenfrei. Aktualisiere deinen Browser noch heute!"},"zui.calendar":{weekNames:["Son","Mon","Die","Mit","Don","Fri","Sam"],monthNames:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",year:"{0}Jahr",month:"{0}Monat",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Kein Icon]",commonIcons:"Gemeinsame Symbole",webIcons:"Web-Symbol",editorIcons:"Editor-Symbol",directionalIcons:"Pfeil Zusammenfluss",otherIcons:"Andere Symbole"},"zui.colorPicker":{errorTip:"Kein gültiger Farbwert"},"zui.datagrid":{errorCannotGetDataFromRemote:"Daten vom Remote-Server ({0}) können nicht abgerufen werden.",errorCannotHandleRemoteData:"Die vom Remote-Server zurückgegebenen Daten können nicht verarbeitet werden."},"zui.guideViewer":{prevStep:"Vorheriger Schritt",nextStep:"Nächster Schritt"},"zui.tabs":{reload:"Neu laden",close:"Schliessen",closeOthers:"Schließen Sie andere Registerkarten",closeRight:"Schließen Sie die rechte Registerkarte",reopenLast:"Letzten geschlossenen Tab wiederherstellen",errorCannotFetchFromRemote:"Inhalt kann nicht vom Remote-Server abgerufen werden ({0})."},"zui.uploader":{},datetimepicker:{days:["Sonntag","Montag","Diensteg","Mittwoch","Donnerstag","Freitag","Samstag"],daysShort:["Son","Mon","Die","Mit","Don","Fri","Sam"],daysMin:["Son","Mon","Die","Mit","Don","Fri","Sam"],months:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],monthsShort:["Jan","Feb","Mär","Apr","Mai","Jun","Jul","Aug","Sep","Okt","Nov","Dez"],today:"Heute",suffix:[],meridiem:[]},chosen:{no_results_text:"Nicht gefunden"},bootbox:{OK:"OK",CANCEL:"Stornieren",CONFIRM:"Bestätigen"}}),$.zui.lang("fr",{"zui.pager":{pageOfText:"Page {0}",prev:"Prev",next:"Suivant",first:"First",last:"Last","goto":"Goto",pageOf:"Page {page}",totalPage:"{totalPage} pages",totalCount:"Total: {recTotal} items",pageSize:"{recPerPage} per page",itemsRange:"De {start} à {end}",pageOfTotal:"Page {page} de {totalPage}"},"zui.boards":{append2end:"Aller jusqu'au bout"},"zui.browser":{tip:"Naviguez sans crainte sur Internet. Mettez votre navigateur à jour dès aujourd'hui!"},"zui.calendar":{weekNames:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],monthNames:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",year:"{0} Année",month:"{0} Mois",yearMonth:"{0}-{1}"},"zui.chosenIcons":{emptyIcon:"[Aucune icône]",commonIcons:"Icônes communes",webIcons:"Icône Web",editorIcons:"Icône de l'éditeur",directionalIcons:"Flèche confluence",otherIcons:"Autres icônes"},"zui.colorPicker":{errorTip:"Pas une valeur de couleur valide"},"zui.datagrid":{errorCannotGetDataFromRemote:"Impossible d'obtenir les données du serveur distant ({0}).",errorCannotHandleRemoteData:"Impossible de traiter les données renvoyées par le serveur distant."},"zui.guideViewer":{prevStep:"Étape précédente",nextStep:"Prochaine étape"},"zui.tabs":{reload:"Recharger",close:"Fermer",closeOthers:"Fermez les autres onglets",closeRight:"Fermer l'onglet de droite",reopenLast:"Restaurer le dernier onglet fermé",errorCannotFetchFromRemote:"Impossible d'obtenir le contenu du serveur distant ({0})."},"zui.uploader":{},datetimepicker:{days:["Dimanche","Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi"],daysShort:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],daysMin:["Dim","Lun","Mar","Mer","Jeu","Ven","Sam"],months:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],monthsShort:["Jan","Fév","Mar","Avr","Mai","Juin","Juil","Août","Sep","Oct","Nov","Déc"],today:"Aujourd'hui",suffix:[],meridiem:[]},chosen:{no_results_text:"Pas trouvé"},bootbox:{OK:"D'accord",CANCEL:"Annuler",CONFIRM:"Confirmer"}}); diff --git a/www/theme/default/images/project/active-line.png b/www/theme/default/images/project/active-line.png index fff6283c73..1f1f287daf 100644 Binary files a/www/theme/default/images/project/active-line.png and b/www/theme/default/images/project/active-line.png differ diff --git a/www/theme/default/images/project/default-line.png b/www/theme/default/images/project/default-line.png index 8b57e83b14..bf40185d0a 100644 Binary files a/www/theme/default/images/project/default-line.png and b/www/theme/default/images/project/default-line.png differ diff --git a/www/theme/zui/css/min.css b/www/theme/zui/css/min.css index 2846fd52e2..e668a0fe49 100644 --- a/www/theme/zui/css/min.css +++ b/www/theme/zui/css/min.css @@ -1,5 +1,5 @@ /*! - * ZUI: ZUI for Zentao - v1.10.0 - 2022-08-18 + * ZUI: ZUI for Zentao - v1.10.0 - 2022-08-26 * http://openzui.com * GitHub: https://github.com/easysoft/zui.git * Copyright (c) 2022 cnezsoft.com; Licensed MIT @@ -13,4 +13,4 @@ * * Copyright (c) 2011-2016 Harvest http://getharvest.com * MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md -*/.chosen-container{position:relative;display:block;font-size:13px;vertical-align:middle;zoom:1;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.chosen-container .chosen-drop{position:absolute;top:100%;z-index:1010;display:none;width:100%;background:#fff;border:1px solid #b6bdcc;border:1px solid rgba(0,0,0,.15);border-top:0;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.chosen-container .chosen-drop.chosen-drop-size-limited{border-top:1px solid rgba(0,0,0,.15)}.chosen-container .chosen-drop.chosen-auto-max-width{min-width:100%;border-top:1px solid rgba(0,0,0,.15);opacity:0}.chosen-container .chosen-drop.chosen-auto-max-width>.chosen-results>li{display:inline-block;white-space:nowrap}.chosen-container .chosen-drop.chosen-auto-max-width.in{opacity:1}.chosen-container .chosen-drop.chosen-auto-max-width.in>.chosen-results>li{display:block;white-space:normal}.chosen-container .chosen-drop.chosen-no-wrap>.chosen-results>li{overflow:hidden;text-overflow:ellipsis;white-space:nowrap!important}.chosen-container.chosen-with-drop .chosen-drop{display:block}.chosen-container a{cursor:pointer}.chosen-container.chosen-up .chosen-drop{top:inherit;bottom:100%;margin-top:auto;margin-bottom:-1px;border-radius:2px 2px 0 0;-webkit-box-shadow:0 -3px 5px rgba(0,0,0,.175);box-shadow:0 -3px 5px rgba(0,0,0,.175)}.chosen-container.chosen-highlight-selected .result-selected{color:#0c64eb;background:#e9f2fb}.chosen-container-single .chosen-single{display:block;width:100%;height:32px;padding:5px 8px;overflow:hidden;line-height:1.42857143;color:#222;text-decoration:none;white-space:nowrap;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #dcdcdc;border-radius:2px;-webkit-box-shadow:none;box-shadow:none;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s,-webkit-box-shadow ease-in-out .15s}.chosen-container-single .chosen-default{color:#838a9d}.chosen-container-single .chosen-single>span{display:block;margin-right:26px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.chosen-container-single .chosen-single-with-deselect span{margin-right:38px}.chosen-container-single .chosen-single abbr{position:absolute;top:5px;right:24px;display:block;width:20px;height:20px;font-family:sans-serif;font-size:18px;font-weight:700;line-height:18px;color:#000;text-align:center;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.chosen-container-single .chosen-single abbr:before{display:block;content:'×'}.chosen-container-single .chosen-single abbr:focus,.chosen-container-single .chosen-single abbr:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}.chosen-container-single .chosen-single div{position:absolute;top:0;right:0;display:block;height:100%;padding:5px 8px}.chosen-container-single .chosen-single div b{display:inline-block;width:0;height:0;margin-bottom:2px;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent;opacity:.5}.chosen-container-single .chosen-search{position:relative;z-index:1010;padding:3px 4px;margin:0;white-space:nowrap}.chosen-container-single .chosen-search input[type=text]{width:100%;height:27px;padding:2px 26px 2px 8px;margin:1px 0;font-size:12px;line-height:1.5;background-color:#fff;border:1px solid #dcdcdc;border-radius:2px;outline:0}.chosen-container-single .chosen-search input[type=text]:focus{border-color:#0c64eb}.chosen-container-single .chosen-search:before{position:absolute;top:10px;right:10px;display:block;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;color:#838a9d;text-transform:none;content:"\e928";speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.chosen-container-single .chosen-drop{margin-top:-1px;-webkit-background-clip:padding-box;background-clip:padding-box;border-radius:0 0 4px 4px}.chosen-container-single.chosen-container-single-nosearch .chosen-search{position:absolute;left:-9999px}.chosen-container .chosen-results{position:relative;max-height:240px;padding:0;margin:0;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch}.chosen-container .chosen-results li{display:none;padding:5px 10px;margin:0;line-height:15px;list-style:none;-webkit-transition:background-color .2s cubic-bezier(.175,.885,.32,1);-o-transition:background-color .2s cubic-bezier(.175,.885,.32,1);transition:background-color .2s cubic-bezier(.175,.885,.32,1);-webkit-touch-callout:none}.chosen-container .chosen-results li.active-result{display:list-item;cursor:pointer}.chosen-container .chosen-results li.disabled-result{display:list-item;color:#ccc;cursor:default}.chosen-container .chosen-results li.highlighted{color:#fff;background-color:#0c64eb}.chosen-container .chosen-results li.no-results{display:list-item;background:#f4f4f4}.chosen-container .chosen-results li.group-result{display:list-item;font-weight:700;cursor:default}.chosen-container .chosen-results li.group-option{padding-left:15px}.chosen-container .chosen-results li em{font-style:normal;text-decoration:underline}.chosen-container-multi .chosen-choices{position:relative;width:100%;min-height:32px;min-height:30px\9;padding:0;margin:0;overflow:hidden;cursor:text;background-color:#fff;border:1px solid #dcdcdc;border-radius:2px;-webkit-box-shadow:none;box-shadow:none;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s,-webkit-box-shadow ease-in-out .15s}.chosen-container-multi .chosen-choices:after,.chosen-container-multi .chosen-choices:before{display:table;content:" "}.chosen-container-multi .chosen-choices:after{clear:both}.chosen-container-multi .chosen-choices li{display:block;float:left;padding:0 6px;margin:5px 4px;list-style:none}.chosen-container-multi .chosen-choices li.search-field{padding:0;line-height:12px;white-space:nowrap}.chosen-container-multi .chosen-choices li.search-field input[type=text]{height:20px;font-size:100%;color:#838a9d;background:0 0!important;border:0!important;border-radius:0;outline:0;-webkit-box-shadow:none;box-shadow:none}.chosen-container-multi .chosen-choices li.search-field .default{color:#999}.chosen-container-multi .chosen-choices li.search-field:before{position:absolute;right:8px;bottom:8px;display:block;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;color:#838a9d;text-transform:none;content:"\e928";opacity:0;-webkit-transition:opacity .2s cubic-bezier(.175,.885,.32,1);-o-transition:opacity .2s cubic-bezier(.175,.885,.32,1);transition:opacity .2s cubic-bezier(.175,.885,.32,1);speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.chosen-container-multi .chosen-choices li.search-choice{position:relative;padding:3px 20px 3px 5px;line-height:12px;cursor:default;background-color:#f1f1f1;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #cbd0db;border-radius:3px;-webkit-box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);-webkit-transition:all .4s cubic-bezier(.175,.885,.32,1);-o-transition:all .4s cubic-bezier(.175,.885,.32,1);transition:all .4s cubic-bezier(.175,.885,.32,1)}.chosen-container-multi .chosen-choices li.search-choice:hover{background-color:#fff;border-color:#adb5c6;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.1);box-shadow:0 1px 0 rgba(0,0,0,.1)}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close{position:absolute;top:1px;right:0;display:block;width:20px;height:18px;line-height:18px;color:#000;text-align:center;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:before{font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;text-shadow:0 1px 0 #fff;text-transform:none;content:'\d7';speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:focus,.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}.chosen-container-multi .chosen-choices li.search-choice-disabled{padding-right:5px;color:#666;background-color:#e4e4e4;border:1px solid #ccc}.chosen-container-multi .chosen-choices li.search-choice-focus{background:#d4d4d4}.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close{background-position:-42px -10px}.chosen-container-multi .chosen-results{padding:5px 0;margin:0}.chosen-container-multi .chosen-drop .result-selected{display:list-item;color:#ccc;cursor:default}.chosen-container-active .chosen-single{border-color:#0c64eb;-webkit-box-shadow:none,0 0 8px rgba(12,100,235,.6);box-shadow:none,0 0 8px rgba(12,100,235,.6)}.chosen-container-active.chosen-with-drop .chosen-single{border:1px solid #b6bdcc;border:1px solid rgba(0,0,0,.15);border-bottom-right-radius:0!important;border-bottom-left-radius:0!important;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.chosen-container-active.chosen-with-drop .chosen-single div{background:0 0;border-left:none}.chosen-container-active.chosen-with-drop .chosen-single div b{content:"";border-top:0 dotted;border-bottom:4px solid}.chosen-container-active.chosen-with-drop.chosen-up .chosen-single{border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:2px;border-bottom-left-radius:2px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.chosen-container-active .chosen-choices{border-color:#0c64eb;-webkit-box-shadow:none,0 0 8px rgba(12,100,235,.6);box-shadow:none,0 0 8px rgba(12,100,235,.6)}.chosen-container-active .chosen-choices li.search-field input[type=text]{color:#111!important}.chosen-container-active .chosen-choices li.search-field:before{opacity:1}.chosen-disabled{cursor:default;opacity:.5!important}.chosen-disabled .chosen-single{cursor:default}.chosen-disabled .chosen-choices .search-choice .search-choice-close{cursor:default}.chosen-compact.chosen-container-single .chosen-single>.chosen-search{left:0;display:none;padding:3px 4px;opacity:0}.chosen-compact.chosen-container-single .chosen-single>.chosen-search>input{height:25px;padding:2px 26px 2px 4px;font-size:inherit}.chosen-compact.chosen-container-single .chosen-single>.chosen-search:before{top:9px}.chosen-compact.chosen-with-search.chosen-with-drop .chosen-single>.chosen-search{display:block;opacity:1}select.chosen[multiple]{height:32px;overflow:hidden}select.chosen[multiple] option{visibility:hidden}.picker{min-height:32px;background-color:#eee}.picker:not(.picker-ready)>*{display:none}.picker-selections{position:relative;min-height:32px;color:#222;background-color:#fff;border:1px solid #dcdcdc;border-radius:2px;-webkit-box-shadow:none;box-shadow:none}.picker-focus .picker-selections{border-color:#0c64eb;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(12,100,235,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(12,100,235,.6)}.disabled .picker-selections{cursor:not-allowed;background-color:#f5f5f5}.picker-multi .picker-selections{padding:3px}.picker-multi.picker-focus .picker-selections:before{position:absolute;right:0;bottom:8px;display:block;width:24px;height:14px;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;text-align:center;text-transform:none;content:"\e928";opacity:.4;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.picker-multi.picker-focus.picker-loading .picker-selections::before{display:inline-block;content:"\e982";-webkit-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}.picker-multi .picker-selection{position:relative;display:inline-block;padding:0 20px 0 5px;margin:2px;line-height:18px;background-color:#f1f1f1;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #cbd0db;border-radius:3px;-webkit-box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05)}.picker-selection-single{max-width:100%;padding:5px 20px 5px 8px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.picker-focus .picker-selection-single .picker-selection-text{display:none}.picker-selection-single:after{position:absolute;top:7px;right:0;display:block;width:24px;height:14px;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;text-align:center;text-transform:none;content:"\f0d7";opacity:.4;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.picker-focus .picker-selection-single::after{content:"\e928"}.picker-focus.picker-loading .picker-selection-single::after{display:inline-block;content:"\e982";-webkit-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}.picker-selection-remove{position:absolute;top:0;right:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:18px;height:18px;text-align:center;cursor:pointer;opacity:.2;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.picker-selection-remove:before{font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;text-shadow:0 1px 0 #fff;text-transform:none;content:'\d7';speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.picker-selection-remove:hover{opacity:.5}.picker-single .picker-selection-remove{top:5px;right:20px;z-index:1}.picker-no-value .picker-selection-remove,.picker-single.picker-focus .picker-selection-remove{display:none}.picker-multi.picker-sortable .picker-selection-text{cursor:move}.picker-search{color:transparent;background:0 0;border:none}.picker-search:focus{color:inherit;outline:0}.disabled .picker-search{cursor:not-allowed}.picker-single .picker-search{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;width:100%;padding:5px 8px}.picker-multi .picker-search{display:inline-block;width:10px;min-width:10px;max-width:100%;padding:0 2px;margin:2px 0}.picker-placeholder{position:absolute;top:5px;right:20px;left:8px;z-index:0;display:none;overflow:hidden;color:#838a9d;text-overflow:ellipsis;white-space:nowrap}.picker-no-value.picker-focus .picker-placeholder{display:none}.picker-input-empty.picker-focus.picker-no-value .picker-placeholder,.picker-no-value .picker-placeholder{display:block}.picker-drop-menu{position:fixed;z-index:1200;display:none;min-width:100px;background-color:#fff;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.12),0 1px 3px rgba(0,0,0,.1);box-shadow:0 6px 12px rgba(0,0,0,.12),0 1px 3px rgba(0,0,0,.1);opacity:0}.picker-drop-menu.picker-drop-show{display:block}.picker-option-list{padding:5px 0;margin:0;overflow-y:auto}.picker-no-options .picker-option-list{display:none}.picker-option{display:block;min-height:30px;padding:5px 10px;overflow:hidden;clear:both;font-weight:400;line-height:1.42857143;color:#3c4353;text-overflow:ellipsis;white-space:nowrap;-webkit-transition:none;-o-transition:none;transition:none}.picker-single .picker-option.picker-option-selected{color:#0c64eb;background:#e9f2fb}.picker-option:focus,.picker-option:hover{text-decoration:none}.picker-option.picker-option-active,.picker-single .picker-option.picker-option-selected.picker-option-active{color:#fff;background-color:#0c64eb}.picker-multi .picker-option.picker-option-selected,.picker-multi .picker-option.picker-option-selected.picker-option-active{color:#ccc;cursor:not-allowed;background-color:#fff}.picker-option.disabled{cursor:not-allowed!important}.picker-option-text-matched{position:relative;color:#0c64eb}.picker-option-text-matched:before{position:absolute;right:0;bottom:-4px;left:0;display:block;height:2px;content:' ';background-color:#0c64eb;border-radius:2px;opacity:.5}.picker-option-active .picker-option-text-matched,.picker-option:hover .picker-option-text-matched{color:#fff}.picker-option-active .picker-option-text-matched:before,.picker-option:hover .picker-option-text-matched:before{background-color:#fff}.picker-message{display:none;height:22px;padding:2px 5px;overflow:hidden;font-size:12px;color:#838a9d;text-overflow:ellipsis;white-space:nowrap;background-color:#f1f1f1}.picker-has-message .picker-message{display:block}.picker-message[data-type=danger]{color:#ff5d5d}.picker-actions{padding:5px;border-top:1px solid #eee}.picker-no-actions .picker-actions{display:none}.picker-actions .btn{padding:2px 4px}.picker-actions .btn[disabled]{background-color:transparent;filter:grayscale(1);-webkit-filter:grayscale(1)}.picker-actions .btn+.btn{margin-left:4px}.picker-checkable .picker-option{position:relative;padding-left:32px;color:inherit!important;cursor:pointer!important}.picker-checkable .picker-option>.checkbox-primary{position:absolute;top:4px;left:10px}.picker-checkable .picker-option.picker-option-active{background-color:rgba(0,0,0,.05)!important}.picker-checkable .picker-option:hover{background-color:rgba(0,0,0,.075)!important}.picker-checkable .picker-option.picker-option-selected{background-color:#e9f2fb!important}.picker-checkable .picker-option-active .picker-option-text-matched,.picker-checkable .picker-option:hover .picker-option-text-matched{color:#0c64eb!important}.picker-checkable .picker-option-active .picker-option-text-matched:before,.picker-checkable .picker-option:hover .picker-option-text-matched:before{background:#0c64eb!important}:root{--color-primary:#0c64eb;--color-secondary:#16a8f8;--color-pale:#e9f2fb;--color-fore:#3c4353;--color-back:#fff;--color-red:#ff5d5d;--color-yellow:#ff9800;--color-green:#00da88;--color-blue:#2196f3;--color-purple:#8666b8;--color-brown:#bd7b46;--color-danger:#ff5d5d;--color-warning:#ff9800;--color-success:#00da88;--color-info:#2196f3;--color-special:#8666b8;--color-important:#bd7b46;--color-green-pale:#e8f5e9;--color-yellow-pale:#fff3e0;--color-red-pale:#ffebee;--color-blue-pale:#e3f2fd;--color-brown-pale:#efebe9;--color-purple-pale:#f3e5f5;--link-color:#3c4353;--link-hover-color:#0c64eb;--color-gray-darker:#222;--color-gray-dark:#3c495c;--color-gray:#838a9d;--color-gray-light:#cbd0db;--color-gray-lighter:#eee;--color-gray-pale:#f1f1f1;--border-radius:4px;--border-radius-lg:6px;--border-radius-sm:3px;--bg-gradient:linear-gradient(-90deg, #0a48d1 0%, #1183fb 100%)}.container,.container-fixed,.container-fluid{position:relative}.container{max-width:1800px!important}body{background-color:#efefef}body.article-content,body.body-modal{background:0 0}body.body-modal{padding:0}@media screen and (min-width:1920px){body{font-size:14px}}a:active,a:focus,button:active,button:focus{outline:0!important}.strong{font-weight:700}.font-normal{font-weight:400!important}.text-middle{vertical-align:middle!important}.text-bottom{vertical-align:bottom!important}.text-top{vertical-align:top!important}.inline-block{display:inline-block!important}.layer{border-radius:4px;-webkit-box-shadow:0 0 20px 0 #bdc9d8;box-shadow:0 0 20px 0 #bdc9d8}.space{margin-bottom:20px}.space-lg{margin-bottom:30px}.space-sm{margin-bottom:10px}.muted{opacity:.5}.text-muted em{color:#3c4353}.no-animate{-webkit-transition:none!important;-o-transition:none!important;transition:none!important}.template{display:none!important}.text-left{text-align:left!important}.text-yellow.icon-folder{color:#ffe066}.table-row{display:table;width:100%;table-layout:fixed}.table-col,.table-row>.col,.table-row>[class*=col-],.table-row>[class*="-col"]{display:table-cell;float:none;vertical-align:top}.side-col{width:200px;padding-right:20px}.side-col.col-4{width:33.3333333%}.col-lg{width:260px}.col-xl{width:320px}.col-sm{width:150px}.col-xs{width:100px}.main-col+.side-col{padding-right:0;padding-left:20px}.row-grid>[class*=col-],.row-grid>[class*="-col"]{padding-top:6px;padding-bottom:6px}hr.space{margin:10px 0;border:none}hr.space-sm{margin:5px 0;border:none}.text-secondary{color:#16a8f8}a.text-primary{color:#0c64eb}.nav-primary>li>a{min-width:100px;padding:5px 8px;color:#838a9d;border-color:#e7f1fc}.nav-primary>li.active>a{color:#0c64eb;background-color:#e7f1fc;border-color:#e7f1fc}.nav-primary>li.active>a:hover{color:#0c64eb;background-color:#c3dcf7;border-color:#c3dcf7}.end-marker{margin-bottom:20px;color:#cbd0db;text-align:center}@-webkit-keyframes highlight{0%{background:#fff;outline:1px solid transparent}100%{background:#fff0d5;outline:2px solid #ffdcbc}}@-o-keyframes highlight{0%{background:#fff;outline:1px solid transparent}100%{background:#fff0d5;outline:2px solid #ffdcbc}}@keyframes highlight{0%{background:#fff;outline:1px solid transparent}100%{background:#fff0d5;outline:2px solid #ffdcbc}}.highlight{-webkit-animation:highlight .5s linear 0s 2 alternate;-o-animation:highlight .5s linear 0s 2 alternate;animation:highlight .5s linear 0s 2 alternate}.progress.inline-block{width:100px;margin:0}.w-p5{width:5%!important}.w-p10{width:10%!important}.w-p15{width:15%!important}.w-p20{width:20%!important}.w-p25{width:25%!important}.w-p30{width:30%!important}.w-p35{width:35%!important}.w-p40{width:40%!important}.w-p45{width:45%!important}.w-p50{width:50%!important}.w-p55{width:55%!important}.w-p60{width:60%!important}.w-p65{width:65%!important}.w-p70{width:70%!important}.w-p75{width:75%!important}.w-p80{width:80%!important}.w-p85{width:85%!important}.w-p90{width:90%!important}.w-p94{width:94%!important}.w-p95{width:95%!important}.w-p98{width:98%!important}.w-p99{width:99%!important}.w-p100{width:100%!important}.w-auto{width:auto!important}.w-10px{width:10px!important}.w-20px{width:20px!important}.w-30px{width:30px!important}.w-35px{width:35px!important}.w-40px{width:40px!important}.w-45px{width:45px!important}.w-50px{width:50px!important}.w-60px{width:60px!important}.w-70px{width:70px!important}.w-80px{width:80px!important}.w-90px{width:90px!important}.w-100px{width:100px!important}.w-110px{width:110px!important}.w-120px{width:120px!important}.w-130px{width:130px!important}.w-140px{width:140px!important}.w-150px{width:150px!important}.w-160px{width:160px!important}.w-180px{width:180px!important}.w-200px{width:200px!important}.w-230px{width:230px!important}.w-250px{width:250px!important}.w-300px{width:300px!important}.w-400px{width:400px!important}.w-500px{width:500px!important}.w-600px{width:600px!important}.w-700px{width:700px!important}.w-800px{width:800px!important}.w-900px{width:900px!important}.mw-200px{max-width:200px!important}.mw-300px{max-width:300px!important}.mw-400px{max-width:400px!important}.mw-500px{max-width:500px!important}.mw-600px{max-width:600px!important}.mw-700px{max-width:700px!important}.mw-800px{max-width:800px!important}.mw-900px{max-width:900px!important}.mw-1400px{max-width:1400px!important}.w-id{width:70px!important}.w-pri{width:40px!important}.w-severity{width:50px!important}.w-hour{width:57px!important}.w-date{width:90px!important}.w-status{width:60px!important}.w-resolution,.w-type,.w-user{width:80px!important}.w-p15-f{width:15%!important;min-width:120px!important}.w-p25-f{width:25%!important;min-width:200px!important}.w-p35-f{width:35%!important;min-width:300px!important}.w-p45-f{width:45%!important;min-width:400px!important}.h-5px{height:5px!important}.h-10px{height:10px!important}.h-20px{height:20px!important}.h-30px{height:30px!important}.h-35px{height:35px!important}.h-40px{height:40px!important}.h-45px{height:45px!important}.h-50px{height:50px!important}.h-60px{height:60px!important}.h-70px{height:70px!important}.h-80px{height:80px!important}.h-100px{height:100px!important}.h-120px{height:120px!important}.h-130px{height:130px!important}.h-140px{height:140px!important}.h-150px{height:150px!important}.h-200px{height:200px!important}.pd-0{padding:0!important}.mg-0{margin:0!important}.mgb-20{margin-bottom:20px!important}.mgb-10{margin-bottom:10px!important}.pdb-20{padding-bottom:20px!important}.pdt-20{padding-top:20px!important}.br-0{border-radius:0!important}.bd-0,.bd-none,.borderless{border:none!important}.bg-none{background:0 0!important}.red{color:#ff5d5d!important}.icon-pro-version{font-size:14px!important}.icon-pro-version:before{position:relative;top:-1px;font-size:14px;color:#ff5d5d;content:"\e92b"}.bg-primary{color:#fff;background:-webkit-gradient(linear,right top,left top,from(#0a48d1),to(#1183fb));background:-webkit-linear-gradient(right,#0a48d1 0,#1183fb 100%);background:-o-linear-gradient(right,#0a48d1 0,#1183fb 100%);background:linear-gradient(-90deg,#0a48d1 0,#1183fb 100%);border-top-color:#0c64eb}.bg-primary-pure{color:#fff;background-color:#0c64eb}.bg-primary-pale{color:#0c64eb;background-color:#e9f2fb}.bg-secondary{color:#fff;background:#16a8f8}.hl-tutorial{position:relative!important;z-index:1010!important;-webkit-box-shadow:0 0 0 0 #000!important;box-shadow:0 0 0 0 #000!important;-webkit-transition:-webkit-box-shadow 1s!important;-o-transition:box-shadow 1s!important;transition:-webkit-box-shadow 1s!important;transition:box-shadow 1s!important;transition:box-shadow 1s,-webkit-box-shadow 1s!important}.hl-tutorial.hl-in{-webkit-box-shadow:0 0 20px 0 #ffff8d,0 0 0 2px #ffd180,0 0 0 3000px rgba(0,0,0,.2)!important;box-shadow:0 0 20px 0 #ffff8d,0 0 0 2px #ffd180,0 0 0 3000px rgba(0,0,0,.2)!important}.btn.tooltip-tutorial,.hl-tutorial.hl-in:hover{position:relative!important;z-index:1010!important;-webkit-box-shadow:0 0 30px 0 #ffff8d,0 0 0 5px #ffd180,0 0 0 3000px rgba(0,0,0,.3)!important;box-shadow:0 0 30px 0 #ffff8d,0 0 0 5px #ffd180,0 0 0 3000px rgba(0,0,0,.3)!important}.tooltip-max .tooltip-inner{max-width:1000px;padding:8px 10px}.transition-all *{-webkit-transition:all .2s!important;-o-transition:all .2s!important;transition:all .2s!important}.scroll-x{overflow-x:auto!important}.scroll-y{overflow-y:auto!important}.divider+.divider{display:none}.ie *{-webkit-transition:none!important;-o-transition:none!important;transition:none!important}@font-face{font-family:Oswald;font-weight:400;src:url(../fonts/Oswald-Regular.ttf)}@font-face{font-family:Oswald;font-weight:500;src:url(../fonts/Oswald-Medium.ttf)}@font-face{font-family:Oswald;font-weight:300;src:url(../fonts/Oswald-Light.ttf)}.num{font-family:Oswald;font-weight:400}@font-face{font-family:ZentaoIcon;font-style:normal;font-weight:400;src:url(../fonts/ZentaoIcon.eot?v=1.34);src:url(../fonts/ZentaoIcon.eot?#iefix&v=1.34) format('embedded-opentype'),url(../fonts/ZentaoIcon.woff?v=1.34) format('woff'),url(../fonts/ZentaoIcon.ttf?v=1.34) format('truetype'),url(../fonts/ZentaoIcon.svg#regular?v=1.34) format('svg')}.icon,[class*=" icon-"],[class^=icon-]{font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;text-transform:none;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon:before{display:inline-block;min-width:14px;text-align:center}a .icon,a [class*=" icon-"],a [class^=icon-]{display:inline}.icon-lg:before{font-size:1.33333333em;vertical-align:-10%}.icon-2x{font-size:28px}.icon-3x{font-size:42px}.icon-4x{font-size:56px}.icon-5x{font-size:70px}.icon-spin{display:inline-block;-webkit-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}a .icon-spin{display:inline-block;text-decoration:none}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0);transform:rotate(0)}100%{-o-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}.icon-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.icon-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.icon-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.icon-flip-horizontal{-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);-o-transform:scale(-1,1);transform:scale(-1,1)}.icon-flip-vertical{-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)}.icon.icon-flip-horizontal,.icon.icon-flip-vertical,.icon.icon-rotate-180,.icon.icon-rotate-270,.icon.icon-rotate-90{display:inline-block}.icon-zentao:before{content:"\e901"}.icon-zentao-alt:before{content:"\e900"}.icon-help:before{content:"\e968"}.icon-import:before{content:"\e904"}.icon-download:before{content:"\e904"}.icon-export:before{content:"\e905"}.icon-lightbulb:before{content:"\e91c"}.icon-close:before{content:"\e936"}.icon-check:before{content:"\e5ca"}.icon-plus:before{content:"\e925"}.icon-minus:before{content:"\e926"}.icon-expand-alt:before{content:"\e6f1"}.icon-collapse-alt:before{content:"\e6f2"}.icon-fullscreen:before{content:"\e96b"}.icon-star-empty:before{content:"\e94a"}.icon-star:before{content:"\e94b"}.icon-exclamation-sign:before{content:"\e930"}.icon-info-sign:before{content:"\e9d5"}.icon-flag:before{content:"\e937"}.icon-check-circle:before{content:"\e92f"}.icon-check-sign:before{content:"\e938"}.icon-chart-pie:before{content:"\e95b"}.icon-history:before{content:"\e95f"}.icon-pencil:before{content:"\e254"}.icon-search:before{content:"\e928"}.icon-restart:before{content:"\e95e"}.icon-cog:before{content:"\e93b"}.icon-chart-line:before{content:"\e95c"}.icon-chart-bar:before{content:"\e95d"}.icon-bar-chart:before{content:"\e95d"}.icon-exchange:before{content:"\e927"}.icon-severity:before{content:"\e973"}.icon-book:before{content:"\f02d"}.icon-treemap-alt:before{content:"\e971"}.icon-severity-solid:before{content:"\e902"}.icon-chat-line:before{content:"\e998"}.icon-stack:before{content:"\e943"}.icon-cube:before{content:"\e967"}.icon-minus-sign:before{content:"\e939"}.icon-bars-sign:before{content:"\e93a"}.icon-chat:before{content:"\e940"}.icon-message:before{content:"\e940"}.icon-more:before{content:"\e744"}.icon-certificate:before{content:"\f0a3"}.icon-bell:before{content:"\e7f5"}.icon-columns:before{content:"\f0db"}.icon-envelope-o:before{content:"\e92a"}.icon-unfold-all:before{content:"\e931"}.icon-fold-all:before{content:"\e932"}.icon-bars:before{content:"\e948"}.icon-cards-view:before{content:"\e949"}.icon-ellipsis-v:before{content:"\e5d4"}.icon-spinner-indicator:before{content:"\e982"}.icon-up-circle:before{content:"\e92b"}.icon-right-circle:before{content:"\e92c"}.icon-down-circle:before{content:"\e92d"}.icon-left-circle:before{content:"\e92e"}.icon-angle-double-right:before{content:"\f101"}.icon-angle-down:before{content:"\e313"}.icon-angle-left:before{content:"\e314"}.icon-angle-right:before{content:"\e315"}.icon-angle-top:before{content:"\e316"}.icon-first-page:before{content:"\e5dc"}.icon-last-page:before{content:"\e5dd"}.icon-caret-down:before{content:"\f0d7"}.icon-caret-up:before{content:"\f0d8"}.icon-caret-left:before{content:"\f0d9"}.icon-caret-right:before{content:"\f0da"}.icon-sort:before{content:"\f0dc"}.icon-sort-down:before{content:"\f0dd"}.icon-sort-up:before{content:"\f0de"}.icon-arrow-up:before{content:"\e923"}.icon-arrow-down:before{content:"\e924"}.icon-arrow-left:before{content:"\e952"}.icon-arrow-right:before{content:"\e93e"}.icon-chevron-left:before{content:"\e934"}.icon-chevron-right:before{content:"\e935"}.icon-chevron-double-up:before{content:"\e959"}.icon-chevron-double-down:before{content:"\e95a"}.icon-folder-account:before{content:"\e942"}.icon-folder-move:before{content:"\e960"}.icon-folder-plus:before{content:"\e961"}.icon-folder-upload:before{content:"\e962"}.icon-folder-star:before{content:"\e963"}.icon-folder-edit:before{content:"\e964"}.icon-folder-download:before{content:"\e965"}.icon-folder-outline:before{content:"\e966"}.icon-folder:before{content:"\e944"}.icon-folder-o:before{content:"\e945"}.icon-folder-open-o:before{content:"\e946"}.icon-folder-open:before{content:"\e947"}.icon-color:before{content:"\e93c"}.icon-paper-clip:before{content:"\e93d"}.icon-text:before{content:"\e929"}.icon-share:before{content:"\f064"}.icon-format-list-bulleted:before{content:"\e9a8"}.icon-format-bold:before{content:"\e953"}.icon-format-header-pound:before{content:"\e954"}.icon-format-italic:before{content:"\e955"}.icon-format-list-numbers:before{content:"\e969"}.icon-format-quote-close:before{content:"\e96a"}.icon-image:before{content:"\e96c"}.icon-table-large:before{content:"\e96d"}.icon-aiux:before{content:"\e99e"}.icon-qc:before{content:"\e986"}.icon-qc-q:before{content:"\e985"}.icon-qc-c:before{content:"\e987"}.icon-sonarqube:before{content:"\e9ba"}.icon-college:before{content:"\e9c8"}.icon-ztool:before{content:"\e9c1"}.icon-contacts:before{content:"\e9c3"}.icon-chats:before{content:"\e9c4"}.icon-menu-my:before{content:"\e97a"}.icon-home:before{content:"\e97a"}.icon-program:before{content:"\e9aa"}.icon-lightbulb-alt:before{content:"\e98f"}.icon-product:before{content:"\e98f"}.icon-rocket:before{content:"\e99c"}.icon-project:before{content:"\e99c"}.icon-run:before{content:"\e9a9"}.icon-test:before{content:"\e956"}.icon-infinite:before{content:"\e9a3"}.icon-devops:before{content:"\e9a3"}.icon-ops:before{content:"\e903"}.icon-doc:before{content:"\e99b"}.icon-menu-doc:before{content:"\e99b"}.icon-statistic:before{content:"\e999"}.icon-menu-backend:before{content:"\e993"}.icon-assets:before{content:"\e9ae"}.icon-diamond:before{content:"\e9ae"}.icon-feedback:before{content:"\e991"}.icon-flow:before{content:"\e994"}.icon-oa:before{content:"\e9a1"}.icon-more-circle:before{content:"\e988"}.icon-controls:before{content:"\e995"}.icon-account:before{content:"\e992"}.icon-about:before{content:"\e996"}.icon-info:before{content:"\e996"}.icon-cog-outline:before{content:"\e997"}.icon-backend:before{content:"\e997"}.icon-exit:before{content:"\e99a"}.icon-theme:before{content:"\e9a0"}.icon-globe:before{content:"\f0ac"}.icon-lang:before{content:"\f0ac"}.icon-draft-edit:before{content:"\e9dd"}.icon-sub-review:before{content:"\e9df"}.icon-sub-review-user:before{content:"\e9db"}.icon-ztf:before{content:"\e9dc"}.icon-save:before{content:"\e9d8"}.icon-list-box:before{content:"\e9b4"}.icon-usecase:before{content:"\e99d"}.icon-code:before{content:"\e990"}.icon-summary:before{content:"\e9ad"}.icon-more-alt:before{content:"\e9a7"}.icon-customer:before{content:"\e9d9"}.icon-tree:before{content:"\e9c9"}.icon-list:before{content:"\e9cb"}.icon-gantt:before{content:"\e9cc"}.icon-group-view:before{content:"\e9cd"}.icon-inherit-space:before{content:"\e9c2"}.icon-card-archive:before{content:"\e9b8"}.icon-col-archive:before{content:"\e9b9"}.icon-col-add-right:before{content:"\e9bb"}.icon-col-add-left:before{content:"\e9bc"}.icon-col-split:before{content:"\e9bd"}.icon-waterfall:before{content:"\e9a4"}.icon-manual:before{content:"\e98d"}.icon-kanban:before{content:"\e983"}.icon-lane:before{content:"\e9b1"}.icon-back:before{content:"\e9d3"}.icon-back-circle:before{content:"\e9da"}.icon-shield:before{content:"\e9ca"}.icon-meh:before{content:"\e9ce"}.icon-frown:before{content:"\e9cf"}.icon-smile:before{content:"\e9d0"}.icon-unlock-solid:before{content:"\e9d1"}.icon-lock-solid:before{content:"\e9d2"}.icon-ver:before{content:"\e9c6"}.icon-publish:before{content:"\e9c7"}.icon-send:before{content:"\e9c7"}.icon-tag:before{content:"\e9be"}.icon-tag-lock:before{content:"\e9bf"}.icon-code-fork:before{content:"\f126"}.icon-branch-lock:before{content:"\e9c0"}.icon-groups:before{content:"\e9af"}.icon-thumbs-up:before{content:"\f087"}.icon-thumbs-down:before{content:"\f088"}.icon-thumbs-up-solid:before{content:"\e9d6"}.icon-thumbs-down-solid:before{content:"\e9d7"}.icon-hash:before{content:"\e9ab"}.icon-version:before{content:"\e9ab"}.icon-p-square:before{content:"\e97b"}.icon-video-play:before{content:"\e97f"}.icon-plus-solid-circle:before{content:"\e974"}.icon-minuse-solid-circle:before{content:"\e9b6"}.icon-s:before{content:"\e975"}.icon-c:before{content:"\e976"}.icon-t:before{content:"\e977"}.icon-guide:before{content:"\e978"}.icon-todo:before{content:"\e979"}.icon-side-left:before{content:"\e9b3"}.icon-side-right:before{content:"\e9b2"}.icon-fullscreen-exit:before{content:"\e972"}.icon-alert:before{content:"\e99f"}.icon-undo:before{content:"\e93f"}.icon-redo:before{content:"\e9d4"}.icon-swap:before{content:"\e9b0"}.icon-chat-solid:before{content:"\e9b5"}.icon-clock:before{content:"\e97c"}.icon-cost:before{content:"\e97d"}.icon-pencil-alt:before{content:"\e984"}.icon-size-height:before{content:"\e9c5"}.icon-file-log:before{content:"\e9de"}.icon-rich-text:before{content:"\e913"}.icon-markdown:before{content:"\e916"}.icon-excel:before{content:"\e933"}.icon-text-link:before{content:"\e94d"}.icon-ppt:before{content:"\e957"}.icon-word:before{content:"\e958"}.icon-doc-lib:before{content:"\e96f"}.icon-file:before{content:"\f016"}.icon-file-empty:before{content:"\f016"}.icon-file-text:before{content:"\f0f6"}.icon-file-alt:before{content:"\f15b"}.icon-file-text-alt:before{content:"\f15c"}.icon-file-pdf:before{content:"\f1c1"}.icon-file-word:before{content:"\f1c2"}.icon-file-excel:before{content:"\f1c3"}.icon-file-powerpoint:before{content:"\f1c4"}.icon-file-image:before{content:"\f1c5"}.icon-file-archive:before{content:"\f1c6"}.icon-file-audio:before{content:"\f1c7"}.icon-file-video:before{content:"\f1c8"}.icon-file-code:before{content:"\f1c9"}.icon-menu-collapse:before{content:"\e980"}.icon-menu-expand:before{content:"\e981"}.icon-group:before{content:"\e97e"}.icon-menu-users:before{content:"\e97e"}.icon-persons:before{content:"\e97e"}.icon-team:before{content:"\e97e"}.icon-estimate:before{content:"\e9ac"}.icon-sprint:before{content:"\e9a2"}.icon-shield-check:before{content:"\e9a5"}.icon-ok:before{content:"\e9a6"}.icon-printer:before{content:"\e906"}.icon-bullhorn:before{content:"\e910"}.icon-person:before{content:"\e941"}.icon-fields:before{content:"\e989"}.icon-trigger:before{content:"\e98a"}.icon-layout:before{content:"\e98b"}.icon-audit:before{content:"\e98c"}.icon-cancel:before{content:"\e951"}.icon-ban-circle:before{content:"\e951"}.icon-eye:before{content:"\e94e"}.icon-eye-off:before{content:"\e96e"}.icon-unlock:before{content:"\e94f"}.icon-lock:before{content:"\e950"}.icon-private:before{content:"\e950"}.icon-move:before{content:"\e94c"}.icon-hand-right:before{content:"\e907"}.icon-checked:before{content:"\e908"}.icon-off:before{content:"\e909"}.icon-start:before{content:"\e90a"}.icon-play:before{content:"\e90a"}.icon-time:before{content:"\e90b"}.icon-edit:before{content:"\e90c"}.icon-trash:before{content:"\e90d"}.icon-link:before{content:"\e90e"}.icon-unlink:before{content:"\e90f"}.icon-bug:before{content:"\e911"}.icon-list-alt:before{content:"\e912"}.icon-change:before{content:"\e970"}.icon-alter:before{content:"\e970"}.icon-glasses:before{content:"\e914"}.icon-review:before{content:"\e914"}.icon-sitemap:before{content:"\e915"}.icon-testcase:before{content:"\e915"}.icon-pluses:before{content:"\e917"}.icon-report-list:before{content:"\e918"}.icon-magic:before{content:"\e919"}.icon-active:before{content:"\e919"}.icon-treemap:before{content:"\e91a"}.icon-confirm:before{content:"\e91b"}.icon-split:before{content:"\e98e"}.icon-delay:before{content:"\e91d"}.icon-calendar:before{content:"\e91d"}.icon-pause:before{content:"\e91e"}.icon-ban:before{content:"\e91f"}.icon-plus-bold:before{content:"\e920"}.icon-copy:before{content:"\e921"}.icon-refresh:before{content:"\e922"}.icon-diff:before{content:"\e9b7"}.icon-sm:before{font-size:14px;vertical-align:10%}.icon-qc{position:relative}.icon-qc:before{width:1em;color:#7cb938;content:"\e985"}.icon-qc:after{position:absolute;top:0;left:0;width:1em;height:1em;font-family:ZentaoIcon;font-size:14px;font-size:inherit;font-style:normal;font-weight:400;font-variant:normal;line-height:1;color:#36a742;text-transform:none;content:"\e987";speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-message.has-dot{position:relative}.icon-message.has-dot::after{position:absolute;top:-3px;right:-5px;display:block;width:6px;height:6px;content:' ';background-color:#ff5d5d;border-radius:50%}.icon-project{-webkit-transform:scale(1.2);-ms-transform:scale(1.2);-o-transform:scale(1.2);transform:scale(1.2)}.icon-product{-webkit-transform:scale(1.15);-ms-transform:scale(1.15);-o-transform:scale(1.15);transform:scale(1.15)}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:13px;font-weight:400;line-height:18px;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;border-radius:4px;-webkit-transition:.4s cubic-bezier(.175,.885,.32,1);-o-transition:.4s cubic-bezier(.175,.885,.32,1);transition:.4s cubic-bezier(.175,.885,.32,1);-webkit-transition-property:background,border,outline,opacity,-webkit-box-shadow;-o-transition-property:background,border,box-shadow,outline,opacity;transition-property:background,border,outline,opacity,-webkit-box-shadow;transition-property:background,border,box-shadow,outline,opacity;transition-property:background,border,box-shadow,outline,opacity,-webkit-box-shadow}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:focus,.btn:hover{color:#3c4353;text-decoration:none}.btn:active{text-decoration:none;background-image:none;outline:0;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.1)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;filter:grayscale(1);-webkit-box-shadow:none;box-shadow:none;opacity:.5;-webkit-filter:grayscale(1)}.btn{color:#3c4353;background-color:#fff;border-color:#d6dae3}.btn.active,.btn.hover,.btn:active,.btn:focus,.btn:hover,.open .dropdown-toggle.btn{color:#3c4353;background-color:rgba(255,255,255,.8);border-color:#b8bfce}.btn.active,.btn:active,.open .dropdown-toggle.btn{background-color:#f2f2f2;background-image:none;border-color:#b8bfce}.btn.disabled,.btn.disabled.active,.btn.disabled:active,.btn.disabled:focus,.btn.disabled:hover,.btn[disabled],.btn[disabled].active,.btn[disabled]:active,.btn[disabled]:focus,.btn[disabled]:hover,fieldset[disabled] .btn,fieldset[disabled] .btn.active,fieldset[disabled] .btn:active,fieldset[disabled] .btn:focus,fieldset[disabled] .btn:hover{color:rgba(60,67,83,.3);background-color:#fff;border-color:#d6dae3}.btn-gray{color:#82899f;background-color:#f1f1f1;border-color:#f1f1f1}.btn-gray.active,.btn-gray.hover,.btn-gray:active,.btn-gray:focus,.btn-gray:hover,.open .dropdown-toggle.btn-gray{color:#82899f;background-color:rgba(241,241,241,.8);border-color:#d8d8d8}.btn-gray.active,.btn-gray:active,.open .dropdown-toggle.btn-gray{background-color:#e4e4e4;background-image:none;border-color:#d8d8d8}.btn-gray.disabled,.btn-gray.disabled.active,.btn-gray.disabled:active,.btn-gray.disabled:focus,.btn-gray.disabled:hover,.btn-gray[disabled],.btn-gray[disabled].active,.btn-gray[disabled]:active,.btn-gray[disabled]:focus,.btn-gray[disabled]:hover,fieldset[disabled] .btn-gray,fieldset[disabled] .btn-gray.active,fieldset[disabled] .btn-gray:active,fieldset[disabled] .btn-gray:focus,fieldset[disabled] .btn-gray:hover{color:rgba(130,137,159,.3);background-color:#f1f1f1;border-color:#f1f1f1}.btn-primary{color:#fff;background-color:#0c64eb;border-color:transparent}.btn-primary.active,.btn-primary.hover,.btn-primary:active,.btn-primary:focus,.btn-primary:hover,.open .dropdown-toggle.btn-primary{color:#fff;background-color:rgba(12,100,235,.8);border-color:rgba(0,0,0,0)}.btn-primary.active,.btn-primary:active,.open .dropdown-toggle.btn-primary{background-color:#0b5ad3;background-image:none;border-color:rgba(0,0,0,0)}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{color:rgba(255,255,255,.3);background-color:#0c64eb;border-color:transparent}.btn-secondary{color:#fff;background-color:#16a8f8;border-color:transparent}.btn-secondary.active,.btn-secondary.hover,.btn-secondary:active,.btn-secondary:focus,.btn-secondary:hover,.open .dropdown-toggle.btn-secondary{color:#fff;background-color:rgba(22,168,248,.8);border-color:rgba(0,0,0,0)}.btn-secondary.active,.btn-secondary:active,.open .dropdown-toggle.btn-secondary{background-color:#079ced;background-image:none;border-color:rgba(0,0,0,0)}.btn-secondary.disabled,.btn-secondary.disabled.active,.btn-secondary.disabled:active,.btn-secondary.disabled:focus,.btn-secondary.disabled:hover,.btn-secondary[disabled],.btn-secondary[disabled].active,.btn-secondary[disabled]:active,.btn-secondary[disabled]:focus,.btn-secondary[disabled]:hover,fieldset[disabled] .btn-secondary,fieldset[disabled] .btn-secondary.active,fieldset[disabled] .btn-secondary:active,fieldset[disabled] .btn-secondary:focus,fieldset[disabled] .btn-secondary:hover{color:rgba(255,255,255,.3);background-color:#16a8f8;border-color:transparent}.btn-warning{color:#fff;background-color:#ff9800;border-color:transparent}.btn-warning.active,.btn-warning.hover,.btn-warning:active,.btn-warning:focus,.btn-warning:hover,.open .dropdown-toggle.btn-warning{color:#fff;background-color:rgba(255,152,0,.8);border-color:rgba(0,0,0,0)}.btn-warning.active,.btn-warning:active,.open .dropdown-toggle.btn-warning{background-color:#e68900;background-image:none;border-color:rgba(0,0,0,0)}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{color:rgba(255,255,255,.3);background-color:#ff9800;border-color:transparent}.btn-danger{color:#fff;background-color:#ff5d5d;border-color:transparent}.btn-danger.active,.btn-danger.hover,.btn-danger:active,.btn-danger:focus,.btn-danger:hover,.open .dropdown-toggle.btn-danger{color:#fff;background-color:rgba(255,93,93,.8);border-color:rgba(0,0,0,0)}.btn-danger.active,.btn-danger:active,.open .dropdown-toggle.btn-danger{background-color:#ff4343;background-image:none;border-color:rgba(0,0,0,0)}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{color:rgba(255,255,255,.3);background-color:#ff5d5d;border-color:transparent}.btn-success{color:#fff;background-color:#00da88;border-color:transparent}.btn-success.active,.btn-success.hover,.btn-success:active,.btn-success:focus,.btn-success:hover,.open .dropdown-toggle.btn-success{color:#fff;background-color:rgba(0,218,136,.8);border-color:rgba(0,0,0,0)}.btn-success.active,.btn-success:active,.open .dropdown-toggle.btn-success{background-color:#00c178;background-image:none;border-color:rgba(0,0,0,0)}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{color:rgba(255,255,255,.3);background-color:#00da88;border-color:transparent}.btn-info{color:#0c64eb;background-color:#e9f2fb;border-color:transparent}.btn-info.active,.btn-info.hover,.btn-info:active,.btn-info:focus,.btn-info:hover,.open .dropdown-toggle.btn-info{color:#0c64eb;background-color:rgba(233,242,251,.8);border-color:rgba(0,0,0,0)}.btn-info.active,.btn-info:active,.open .dropdown-toggle.btn-info{background-color:#d3e5f7;background-image:none;border-color:rgba(0,0,0,0)}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{color:rgba(12,100,235,.3);background-color:#e9f2fb;border-color:transparent}.btn-link{padding-right:6px;padding-left:6px;font-weight:400;color:#3c495c;text-shadow:none;cursor:pointer;background:0 0;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover,.btn-link[disabled],fieldset[disabled] .btn-link{border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link:focus,.btn-link:hover{color:#222;background:#f1f1f1;background:rgba(0,0,0,.075)}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#cbd0db;text-decoration:none}.btn-lg{padding:11px 16px;font-size:14px;line-height:18px;border-radius:4px}.btn-mini,.btn-sm{padding:3px 8px;font-size:12px;line-height:18px;border-radius:4px}.btn-mini,.btn-xs{padding:0 5px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.btn-wide{min-width:120px}.btn-limit{max-width:180px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.btn-limit>.caret{position:absolute;top:14px;right:8px}.btn-circle{border-radius:17px}.btn>.label-icon{top:3px;padding:3px;margin:-2px;background-color:rgba(0,0,0,.2);border-radius:12px}.btn>.label-icon>.icon{font-size:16px;line-height:18px}.btn>.icon+.text{margin-left:5px}.btn.btn-sm.btn-circle{border-radius:12px}.btn.btn-sm>.label-icon{top:2px;width:20px;height:20px;padding:1px;line-height:20px}.btn.btn-sm>.label-icon>.icon{position:relative;top:-1px;display:inline-block;font-size:14px;line-height:18px}.btn-icon-left{position:relative;padding-left:35px;overflow:hidden;text-align:right}.btn-icon-left>.label-icon{position:absolute;left:5px;margin:0}.btn-icon-left>.icon{position:absolute;top:0;bottom:0;left:0;display:block;width:30px;line-height:30px;color:#16a8f8;text-align:center;background:#e9f2fb}.btn-icon-left.btn-sm{padding-left:28px}.btn-icon-left.btn-sm>.label-icon{left:2px}.btn-icon-left.btn-sm>.icon{width:24px;line-height:24px}.btn-icon-right{position:relative;padding-right:35px;text-align:left}.btn-icon-right>.label-icon{position:absolute;right:5px;margin:0}.btn-icon-right.btn-sm{padding-right:28px}.btn-icon-right.btn-sm>.label-icon{right:2px}.btn-icon{min-width:32px;padding-right:0;padding-left:0}.btn-icon.btn-sm{width:24px;min-width:24px;height:24px}.btn-group{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group>.btn-group{float:left}.btn-group>.btn{border-radius:0}.btn-group>.btn:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}.btn-group>.btn:last-child{border-top-right-radius:2px;border-bottom-right-radius:2px}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.dropdown{float:left;margin-right:10px}.btn-toolbar>.btn-group:last-child,.btn-toolbar>.btn:last-child,.btn-toolbar>.dropdown:last-child{margin-right:0}.btn-toolbar>.divider{float:left;height:20px;margin:7px 5px 4px 10px;border-left:1px solid rgba(0,0,0,.1)}.btn-toolbar .space{float:left;min-height:1px;margin:0 10px 0 10px}.btn-toolbar .input-control{float:left;width:120px}.btn-toolbar .page-title{float:left;line-height:34px}.btn-toolbar .page-title .text{font-size:14px;font-weight:700}.btn-toolbar .page-title .label{top:-2px;margin-right:10px}.btn-toolbar .divider+.page-title{margin-left:15px}.btn-active-line{position:relative;font-weight:700;color:#0c64eb}.btn-active-line:after{position:absolute;right:5px;bottom:1px;left:5px;display:block;content:' ';border-bottom:2px solid #0c64eb}.btn-active-line:hover{color:#0c64eb}.btn-active-text .text{position:relative;top:-1px;display:inline-block;font-weight:700;color:#0c64eb}.btn-active-text .text:after{position:absolute;bottom:-5px;display:block;width:100%;content:' ';border-bottom:2px solid #0c64eb}.angle-btn{position:relative;padding:1px;background:#fff;border:1px solid #cbd0db;border-right:none}.angle-btn:first-child{border-radius:2px 0 0 2px}.btn-toolbar>.angle-btn{margin-right:8px}.angle-btn:after,.angle-btn:before{position:absolute;top:-1px;right:-8px;display:block;width:0;height:0;content:' ';border-color:transparent transparent transparent #cbd0db;border-style:solid;border-width:17px 0 17px 8px}.angle-btn:after{right:-7px;border-color:transparent transparent transparent #fff;border-radius:2px}.angle-btn .btn{padding:6px;font-weight:700;background:#fff;border:none;border-radius:4px!important}.angle-btn .btn.btn-limit{padding-right:16px}.angle-btn .btn.btn-limit>.caret{right:4px}.angle-btn+.angle-btn{border-left:none}.angle-btn+.angle-btn>.btn-group:first-child{padding-left:8px}.angle-btn+.angle-btn>.btn-group:first-child:after,.angle-btn+.angle-btn>.btn-group:first-child:before{position:absolute;top:-2px;left:0;display:block;width:0;height:0;content:' ';border-color:transparent transparent transparent #cbd0db;border-style:solid;border-width:17px 0 17px 8px}.angle-btn+.angle-btn>.btn-group:first-child:after{left:-1px;border-color:transparent transparent transparent #fff;border-width:17px 0 17px 8px}.btn-toolbar>.angle-btn.active,.btn-toolbar>.angle-btn:last-child{border-color:#0c64eb}.btn-toolbar>.angle-btn.active .btn,.btn-toolbar>.angle-btn:last-child .btn{color:#0c64eb}.btn-toolbar>.angle-btn.active:after,.btn-toolbar>.angle-btn.active:before,.btn-toolbar>.angle-btn:last-child:after,.btn-toolbar>.angle-btn:last-child:before{border-color:transparent transparent transparent #0c64eb}.btn-toolbar>.angle-btn.active:after,.btn-toolbar>.angle-btn:last-child:after{border-color:transparent transparent transparent #fff}.btn-toolbar>.angle-btn+.angle-btn:last-child>.btn-group:first-child:after,.btn-toolbar>.angle-btn+.angle-btn:last-child>.btn-group:first-child:before,.btn-toolbar>.angle-btn.active+.angle-btn>.btn-group:first-child:after,.btn-toolbar>.angle-btn.active+.angle-btn>.btn-group:first-child:before{border-color:transparent transparent transparent #0c64eb}.btn-toolbar>.angle-btn+.angle-btn:last-child>.btn-group:first-child:after,.btn-toolbar>.angle-btn.active+.angle-btn>.btn-group:first-child:after{border-color:transparent transparent transparent #fff}.btn-toolbar>.angle-btn.active+.angle-btn,.btn-toolbar>.angle-btn.normal{border-color:#cbd0db}.btn-toolbar>.angle-btn.active+.angle-btn .btn,.btn-toolbar>.angle-btn.normal .btn{color:#3c4353}.btn-toolbar>.angle-btn.active+.angle-btn:after,.btn-toolbar>.angle-btn.active+.angle-btn:before,.btn-toolbar>.angle-btn.normal:after,.btn-toolbar>.angle-btn.normal:before{border-color:transparent transparent transparent #cbd0db}.btn-toolbar>.angle-btn.active+.angle-btn:after,.btn-toolbar>.angle-btn.normal:after{border-color:transparent transparent transparent #fff}.btn-toolbar>.angle-btn.active+.angle-btn>.btn-group:first-child:before,.btn-toolbar>.angle-btn.normal>.btn-group:first-child:before{border-color:transparent transparent transparent #cbd0db!important}.nav>li>.btn.btn-primary{color:#fff}.nav>li>.btn.btn-primary:focus,.nav>li>.btn.btn-primary:hover{background:rgba(12,100,235,.8)}.btn.btn-action,.c-actions .btn{display:inline-block;width:26px;padding:2px;overflow:hidden;line-height:20px;color:#16a8f8;background:0 0;border-color:transparent}.btn.btn-action>i,.c-actions .btn>i{position:relative;top:1px;font-size:18px}.btn.btn-action:hover,.c-actions .btn:hover{color:#0c64eb;background-color:#d3e5f7}.c-actions .btn+.btn{margin-left:-4px}.label{position:relative;display:inline-block;padding:3px 5px;font-size:12px;font-weight:400;vertical-align:middle;border-radius:2px}.label+.label{margin-left:4px}.label-pale{background:#bed8f3!important}.label-badge{border-radius:9px}.label-light{color:#3c4353;background-color:#ddd}.label-primary{background:#0c64eb!important}.label-gray{color:#878da0;background:#e8ebef}.label-outline.label-danger{color:#ff5d5d;background:#ffebee;border-color:rgba(255,93,93,.25)}.label-outline.label-light{color:#838a9d;background:#f2f5fb;border-color:#e1e5ee}.label-primary.label-outline{background:#e9f2fb!important;border-color:rgba(12,100,235,.25)}.label-outline.label-success{background:#e8f5e9;border-color:rgba(0,218,136,.25)}.label-outline.label-info{background:#e3f2fd;border-color:rgba(33,150,243,.25)}.label-outline.label-warning{background:#fff3e0;border-color:rgba(255,152,0,.25)}.label-dot{position:relative;top:-1px;padding:0;border-radius:50%}.label-dot+.status-text{display:inline-block;margin-left:5px}.label-icon{min-width:18px;padding:0;line-height:18px;border-radius:10px}.label-id{display:inline-block;min-width:30px;padding:0 5px;font-size:12px;line-height:16px;color:#838a9d;text-align:center;vertical-align:middle;background-color:transparent;border:1px solid #838a9d;border-radius:2px}.pri-1,.todo-pri-1{color:#ff5d5d}[class*=" status-"],[class^=status-]{color:#3c4353}.status-changed,.status-changing,.status-delayed,.status-doing,.status-fail,.status-investigate{color:#ff5d5d}.status-changed>.label-dot,.status-changing>.label-dot,.status-delayed>.label-dot,.status-doing>.label-dot,.status-fail>.label-dot,.status-investigate>.label-dot{background-color:#ff5d5d}.status-wait{color:#838a9d}.status-wait>.label-dot{background-color:#7ec5ff}.status-unclosed{color:#838a9d}.status-unclosed>.label-dot{background-color:#0c64eb}.status-done,.status-normal,.status-pass,.status-resolved{color:#43a047}.status-done>.label-dot,.status-normal>.label-dot,.status-pass>.label-dot,.status-resolved>.label-dot{background-color:#00da88}.status-postpone{color:#838a9d}.status-postpone>.label-dot{background-color:#ff5d5d}.status-blocked{position:relative;left:-5px;display:inline-block;padding:0 5px;line-height:20px;color:#3c4353;background:0 0;border-radius:10px}.status-blocked>.label-dot{background-color:#ff9800}.status-pause,.status-suspended{color:#ff9800}.status-pause>.label-dot,.status-suspended>.label-dot{background-color:#ff9800}.status-active.status-bug,.status-draft{color:#8666b8}.status-active.status-bug>.label-dot,.status-draft>.label-dot{background-color:#8666b8}.status-closed,.status-terminate{color:#838a9d}.status-closed>.label-dot,.status-terminate>.label-dot{background-color:#838a9d}.status-cancel{color:#838a9d}.status-cancel>.label-dot{background-color:#cbd0db}.label-pri{display:inline-block;min-width:18px;max-width:100%;height:18px;padding:0 4px;overflow:hidden;font-size:12px;line-height:16px;color:#838a9d;text-align:center;text-overflow:clip;white-space:normal;vertical-align:middle;border:1px solid #838a9d;border-radius:10px}.label-pri-1,.label-selector>.label-pri[data-value="1"]{color:#d50000;border-color:#d50000}.label-pri-2,.label-selector>.label-pri[data-value="2"]{color:#ff9800;border-color:#ff9800}.label-pri-3,.label-selector>.label-pri[data-value="3"]{color:#2098ee;border-color:#2098ee}.label-pri-4,.label-selector>.label-pri[data-value="4"]{color:#009688;border-color:#009688}.label-pri-5,.label-selector>.label-pri[data-value="5"]{color:#838a9d;border-color:#838a9d}.label-pri-0,.label-selector>.label-pri.active[data-value="0"]{color:#d5d9df;border-color:#d5d9df}.label-severity{position:relative;display:inline-block;width:24px;height:20px;font-weight:bolder;text-align:center;vertical-align:middle}.label-severity:before{position:absolute;top:-3px;left:0;z-index:0;display:block;font-family:ZentaoIcon;font-size:14px;font-size:24px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;color:inherit;text-transform:none;content:"\e973";speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.label-severity:after{position:absolute;top:7px;left:0;z-index:1;display:block;width:24px;font-size:12px;line-height:12px;text-align:center;content:attr(data-severity)}.label-severity[data-severity],.label-severity[data-value]{color:#ccc}.label-severity[data-severity="0"],.label-severity[data-value="0"]{color:#ccc}.label-severity[data-severity="1"],.label-severity[data-value="1"]{color:#c62828}.label-severity[data-severity="2"],.label-severity[data-value="2"]{color:#ff8f00}.label-severity[data-severity="3"],.label-severity[data-value="3"]{color:#fdd835}.label-severity[data-severity="4"],.label-severity[data-value="4"]{color:#cddc39}.label-severity[data-severity="5"],.label-severity[data-value="5"]{color:#8bc34a}.label-severity-custom[data-severity]{color:#d5d9df}.label-severity-custom[data-severity="1"]{color:#c62828}.label-severity-custom[data-severity="2"]{color:#ff8f00}.label-severity-custom[data-severity="3"]{color:#fdd835}.label-severity-custom[data-severity="4"]{color:#cddc39}.label-severity-custom[data-severity="5"]{color:#8bc34a}.label-selector{padding:0 10px}.label-selector>.label{display:inline-block;min-width:24px;height:24px;padding:0 5px;font-size:14px;line-height:20px;text-align:center;cursor:pointer;background:0 0;border:2px solid #d5d9df;border-radius:15px}.label-selector>.label+.label{margin-left:10px}.label-selector>.label.empty{border-color:transparent}.label-selector>.label.label-severity{font-size:12px;line-height:28px;border-color:transparent}.label-selector>.label.label-severity:before{top:-2px;left:-2px}.label-selector>.label.label-severity:after{display:none}.label-selector>.label.label-severity.active{background:0 0;filter:none;-webkit-filter:none}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{margin-top:2px}.ie .checkbox input[type=checkbox],.ie .checkbox-inline input[type=checkbox],.ie .radio input[type=radio],.ie .radio-inline input[type=radio]{margin-top:4px}.is-firefox .checkbox input[type=checkbox],.is-firefox .checkbox-inline input[type=checkbox],.is-firefox .radio input[type=radio],.is-firefox .radio-inline input[type=radio]{margin-top:3px}.checkbox-primary,.radio-primary{position:relative;display:block;vertical-align:middle}.checkbox-primary.inline-block,.radio-primary.inline-block{display:inline-block}.checkbox-primary.inline-block+.inline-block,.radio-primary.inline-block+.inline-block{margin-left:15px}.checkbox-primary>input,.radio-primary>input{position:absolute;top:0;left:0;z-index:3;width:100%;height:100%;margin:0;opacity:0}.checkbox-primary>label,.radio-primary>label{display:block;height:20px;padding-left:20px;margin:0;font-weight:400;line-height:20px;cursor:pointer}.checkbox-primary>label:after,.checkbox-primary>label:before,.radio-primary>label:after,.radio-primary>label:before{position:absolute;top:3px;right:0;left:0;display:block;width:14px;height:14px;line-height:14px;text-align:center;content:' ';border-radius:3px}.checkbox-primary>label:after,.radio-primary>label:after{z-index:1;border:1px solid #d9dbe1;border-color:rgba(0,0,0,.15);-webkit-transition:.4s cubic-bezier(.175,.885,.32,1);-o-transition:.4s cubic-bezier(.175,.885,.32,1);transition:.4s cubic-bezier(.175,.885,.32,1);-webkit-transition-property:border,background-color;-o-transition-property:border,background-color;transition-property:border,background-color}.checkbox-primary>label:before,.radio-primary>label:before{top:3px;z-index:2;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-weight:900;font-variant:normal;line-height:1;text-transform:none;content:"\e5ca";opacity:0;-webkit-transition:.2s cubic-bezier(.175,.885,.32,1);-o-transition:.2s cubic-bezier(.175,.885,.32,1);transition:.2s cubic-bezier(.175,.885,.32,1);-webkit-transition-property:opacity,-webkit-transform;-o-transition-property:opacity,-o-transform;transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform,-o-transform;-webkit-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0);speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.checkbox-primary.checked>label:after,.checkbox-primary>input:checked+label:after,.radio-primary.checked>label:after,.radio-primary>input:checked+label:after{background-color:#00da88;border-color:#00da88;border-width:4px}.checkbox-primary.checked>label:before,.checkbox-primary>input:checked+label:before,.radio-primary.checked>label:before,.radio-primary>input:checked+label:before{color:#fff;opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}.checkbox-primary input:indeterminate+label:before,.checkbox-primary.indeterminate>label:before,.radio-primary input:indeterminate+label:before,.radio-primary.indeterminate>label:before{top:9px;left:3px;width:8px;height:2px;content:' ';background-color:#a3a2bc;opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}.checkbox-primary.focus>label:after,.checkbox-primary>input:focus+label:after,.radio-primary.focus>label:after,.radio-primary>input:focus+label:after{border-color:#00da88;-webkit-box-shadow:0 0 0 3px rgba(0,218,136,.2);box-shadow:0 0 0 3px rgba(0,218,136,.2)}.checkbox-primary:hover>label:after,.radio-primary:hover>label:after{border-color:#00da88}.checkbox-primary.checkbox-right>label,.radio-primary.checkbox-right>label{padding:0 30px 0 0}.checkbox-primary.checkbox-right>label:after,.checkbox-primary.checkbox-right>label:before,.radio-primary.checkbox-right>label:after,.radio-primary.checkbox-right>label:before{right:0;left:auto}.checkbox-primary input:disabled+label:after,.checkbox-primary.disabled>label:after,.radio-primary input:disabled+label:after,.radio-primary.disabled>label:after{background-color:#e5e5e5!important;border-color:#bbb!important}.checkbox-primary input:disabled:checked+label:after,.checkbox-primary.checked.disabled>label:after,.radio-primary input:disabled:checked+label:after,.radio-primary.checked.disabled>label:after{background-color:#bbb!important}.radio-primary>label:after{border-radius:50%}.radio-primary>label:before{top:7px;left:6px;width:6px;height:6px;content:' ';border:none;border-radius:50%}.radio-primary.checked>label:after,.radio-primary>input:checked+label:after{background-color:transparent;border-color:#00da88;border-width:2px}.radio-primary.checked>label:before,.radio-primary>input:checked+label:before{background-color:#00da88}.radio-primary input:disabled:checked+label:after,.radio-primary.checked.disabled>label:after{background-color:transparent;border-color:#bbb}.radio-primary input:disabled:checked+label:before,.radio-primary.checked.disabled>label:before{background-color:#bbb}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li>a{position:relative;border:none!important;border-radius:2px!important}.nav-tabs>li.active>a{font-weight:700;color:#3c4353!important}.nav-tabs>li.active>a:before{position:absolute;right:0;bottom:-1px;left:0;display:block;height:2px;content:' ';background:#0c64eb}.nav-tabs-primary>li.active>a{color:#0c64eb!important}.panel{position:relative;margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045);box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045)}.panel-body{padding:20px}.panel-body.has-table{padding:10px}.panel-body.has-table .table{margin-bottom:0;table-layout:fixed}.panel-heading{padding:12px 48px 12px 20px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading+.panel-body{padding-top:0}.panel-title{font-size:14px;font-weight:700;line-height:20px}.panel-title .label{top:-1px}.panel-actions{position:absolute;top:0;right:0;padding:7px 8px}.panel:hover .panel-actions{z-index:10}.panel-actions>li>a{display:inline-block;min-width:30px;padding:0 5px;line-height:30px;color:#a6aab8;text-align:center;border-radius:4px}.panel-actions>li>a:hover{color:#3c495c;text-decoration:initial;background-color:#f1f1f1}.panel-actions .btn-icon{color:#a6aab8}.panel-actions .btn.text-primary{color:#0c64eb}.panel .empty-tip{padding:30px 10px 50px;font-size:14px;color:#838a9d;text-align:center}.progress-text-left{position:relative;margin:7px 0;margin-left:35px;overflow:visible}.progress-text-left .progress-text{position:absolute;top:-7px;left:-35px;display:block;width:35px;height:20px;padding-right:5px;line-height:20px;color:#838a9d;text-align:right}.chart-color{width:20px}.chart-color-dot{display:inline-block;width:10px;height:10px;border-radius:50%}.chart-row{margin-top:10px}.chart-row+.chart-row{padding-top:10px;border-top:1px solid #eee}.chart-wrapper{padding:10px 5px;background:#eee}.chart-wrapper>h4{margin:5px 0 10px}.table-wrapper{max-height:250px;overflow:auto}.table-wrapper .table{margin:0}.progress-pie{position:relative}.progress-pie canvas{display:block}.progress-pie .progress-info{position:absolute;top:0;left:0;width:100%;height:100%;padding-top:25px;text-align:center}.progress-pie .progress-info>small{display:block;line-height:14px;color:#a6aab8}.progress-pie .progress-info>strong{display:block;font-size:36px;line-height:40px}.progress-pie .progress-info>strong>small{font-size:20px}.progress-pie-120 .progress-info{padding-top:30px}.progress-pie-120 .progress-info>small{line-height:18px}.progress-pie-50 .progress-info{padding-top:4px}.progress-pie-50 .progress-info>strong{font-size:20px;font-weight:400}.progress-pie-50 .progress-info>strong>small{font-size:14px}.progress-pie[data-value="100"] .progress-info>strong{-webkit-transform:scale(.7);-ms-transform:scale(.7);-o-transform:scale(.7);transform:scale(.7)}.progress-pie-24 .progress-info{right:-10px;left:-10px;width:auto;padding-top:0;font-size:12px;line-height:24px;-webkit-transform:scale(.9,1);-ms-transform:scale(.9,1);-o-transform:scale(.9,1);transform:scale(.9,1)}.progress-pie-24[data-value="100"] .progress-info{-webkit-transform:scale(.8,1);-ms-transform:scale(.8,1);-o-transform:scale(.8,1);transform:scale(.8,1)}.progress-pie-26 .progress-info{right:-10px;left:-10px;width:auto;padding-top:0;font-size:12px;line-height:26px;-webkit-transform:scale(.9,1);-ms-transform:scale(.9,1);-o-transform:scale(.9,1);transform:scale(.9,1)}.progress-pie-26[data-value="100"] .progress-info{-webkit-transform:scale(.8,1);-ms-transform:scale(.8,1);-o-transform:scale(.8,1);transform:scale(.8,1)}.status-bars{display:table;width:100%;height:140px;padding:5px;padding-top:50px;margin:0;overflow:hidden}.status-bars>li{position:relative;display:table-cell;text-align:center;vertical-align:bottom}.status-bars .bar{position:absolute;bottom:20px;left:50%;display:block;width:10px;margin-left:-5px;background:#0c64eb;border-radius:5px 5px 0 0}.status-bars .bar:after{position:absolute;right:-50px;bottom:0;left:-50px;display:block;height:1px;content:' ';background:#eee}.status-bars .title{font-size:12px;font-weight:400;color:#a6a8b6}.status-bars .value{position:relative;top:-20px;left:-20px;display:inline-block;width:50px;font-size:16px;font-weight:700;text-align:center}.status-bars-h{display:block;padding-right:50px;padding-left:60px;list-style:none}.status-bars-h>li{position:relative;height:40px;border-left:1px solid #eee}.status-bars-h .bar{position:relative;top:15px;display:block;height:10px;line-height:20px;background:#0c64eb;border-radius:0 5px 5px 0}.status-bars-h .title{position:absolute;top:-5px;left:-60px;width:60px;padding-right:10px;font-size:12px;color:#a6a8b6;text-align:right}.status-bars-h .value{position:absolute;top:-5px;right:-50px;display:block;width:40px;font-size:14px;font-weight:700;text-align:left;white-space:nowrap}.ring,[class*=" ring-"],[class^=ring-]{width:24px;height:24px;font-size:12px;line-height:24px;text-align:center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAACZAAAAAwCAMAAACyyT3hAAAAP1BMVEUAAAAAAAA5rm06sG87snE4q200o2o7sG86r244q2w6r244rWw7snA7sG86rG05rm07snA5qWw7sW86sG48s3ECZypFAAAAFHRSTlMACl2b8TkPtnsqj0fVv4Zt4RrIqxUkbyYAAA1gSURBVHja7NrbbtswEIRhmyJ1IiVS0v/+z9rCbeGkdZodNEnVdHmTxP4wmF1exLB9eXCu12tqLX39cTGcm78use2z5Msx19wLfunGpOZvSv4xh/798tt+dKPSZ+jGMNn9/pWnXp1X7f9e+ynf53Xv3r37j/bLyfq4/1u+n8T8VI8jLWY/hbEbSjT76+2ssH77zeyBJHooom9dkHzssuQ5wvau+YuWz141/87zMoTewP9kP+7d2/31ZPln82e7L/fuP9LnJPk+DDDb/TQvEaDc/1//vk9Yvrl7vmHa+ztk347BXwcA1UMRPXCIfq+b5Jm3d82PneY5guSHG1fmVfu/837m5N69e/fu3T89fRZ9bRTBpyMCLFa/zfG7CU98l1/M/+EBS/59PT//bfD9lCS/pbAeR7bnb1OqC7AI+QWAkiz5Kdd1B6BVLb8Fk891Poox/7bPUNcIwGHrM3YDAHu1zyv0yWHcjfNen++nWvsvANC5d6/468nyz+bPdl/u3es+NFbFjw1A8BGAPUv5xGFMz/382HcAsNy+W9Sb9/PwwbP4ra5J8WluQDb7qQ4Ayybl05nnrQVgSFafB4AyWfvPEaBT57X2Seu3ecX9HBfN75t79+7du/+sPnVBy++A1e6nHaAEsz9ufk7W/gUgrvmBP/pf/bYDtDlp+/x8j4du1XwBFsHvQMlW348NIJjz0yH5bbz1n7R5m71/bUAL2n5iMueHAYjZvXv37t1/Tp8bJMFPDYhCfgTa2Ft9aEDJ5vzUbvnbC3562GcI5j6vf3T43/h+hlnJnwFGs99WgGDPv/lq9yPQsjCv1mcT/aUDGEVf3bt37979v+DH1kk+RIiCrwCz0AeI82bvc8vvzT5HYP1NfnjQv3uL/d+f/X/8ljUfGiD4ChDsPkcgCX0iUMX8UfDDw/6Xl+fV+q8Awb373/rLyfLP5s92X+4/rQ8QFV+BmO0+AyTND0nqT1H6xFf715/zWe35l5fXf3/e/YtnGugUnxsQhD47sNl9Klp+ipq/DmL/ovXPAJN79+7du/9on5dV80An+BEoye4nYLhofu/tPgAtafO26RWfn/chv9F93YX7N/PTDoOSHzW/LVA2Ib9Am+y+34Es5DdYlHmB2Lt37969+4/1fYQs+KlB6e0+Acsm9CnQXTQfJ61PTMI+dyiv99me7pO3u6+7cf9mvj/Ikgc6xRfNXyIcgt8KLIoX+0/A4d69e/fu/8znoPkOBsH3O8Qk5C8wiH12xR9AFvwAUfEzREOf/Wmf6Q3v967cv52fNJ+BIPgg+gmogk/xmb9a+lex/+ze/WN/PVn+2fzZ7sv93/MVVsUHIAn+AKrgV4hK/gxsYv+q7Ycg+AxMFt/d+9vy/QXZP+RHCIrvoGyCr9B6wa/QNq3/ftHyye7df2HP3pbQBKIgihqGmzKA4P7/b02lTOX2EncSEky1z8uungPosYyPj/8Nv8Mk/HaHm/Adzk/AIvy1hUb4vkKR5y0yf33Nd+K89vo+Xfy/81Oj/FahmPwBRuH7CjeTX6GRfUp8fHx8/Fc/UpRvoBpf4L4ZL/MfsLvzUoxfgM6e1/V5vNjn9jl/eLV/FrL/2DcwS1+lZxN+9X3a+Pj4+Pgvvm9B5Q8wyvxV+K11+VdgMv2r810LRZ63MX1m6IwX+ep+eMr49/HL3ChfoTF+eD65r/q+wiTy+zus8fHf+8vJ8s/mz3a94n/im075FarxE7Sby2975+8mf5T9G9gvLp/O9Jf5nfHNcz6vzzMLWfyX1wiz8Ss8ZP5g/A32+Pj4+P/XP0D5GRbjC9xkfjF+l/lV9h9gtP2PnOfN9JntfMQPsCeN/3/9dmc2/gqtym+d74BrfHx8/P/q+xaM34CryZf+CnTCT9Ca/A7YnG+N71V/P89La/r7eZ5pIYj/x35aNuUH6IzfpZ+hiY+Pj38X35dF+Ql241eoxncwGD/K/EbmL8r7/En2X+X8J99/dveb+4L/EB//zX+Wo/EFVunH+Pj4+HfxI0zG3+BmfIHF+AaKzB/VeU+Wv8BwZJ/14P56IbvEx39+bdDIBa4YP8bHx8e/kS/QGb/DZPwDVuMXGGV+Y3yR+QM+X/py5HlvB/e3C1l8/Fe/TYZfJtjNGxoY4uN/8JeT5Z/Nn+16vbVf7kX5Ga7GV+iM32Ey/gHNkfnDyfJnWA+d58H9L+aB/4Tj43/Vb4DxHdT4+Pj4f+WhVb7CZnwrfYWr8Tt0xt9lfj1ZfoVJedvn4P5ZyOL/nn+wGN9DGx8fH/+vPKB8630f/0f9drI+ymchiz+vB5Q/4Qd6fHz8efxCycIU/5G9e9lRHAaAKEr7kZi8nIT7/986UlatWaWGCbjpYn1UKizAQU7sZr0vyOzb9QkUv8Ek+qT4u77ksYv5q5g/tZQv91F9g0ta9j/Loy8RZnv7795LlvYf4b/U/JgWccLur/xBH2EXfbw4v28pP8B8cZ9HgzfR27/Tj9utpZvK7e2f8W09tWdv/8S+aBmi4OWnPis8FF+gKD7o+VHM78X8QfGD3uch+qG1bQ7s3+sDbIqPUEVf7O2/+5a2vWhqHyx7+++vUbwAGsQJfhEnjAhB8UXPLy3l97BcOgF7Y2H7v3yBeuVGqcXe/oW+qaN77O2f8jF2it9hVPwE9eKjpYqYH0S/XJk/ieM5i+P5gLG1o3Ls/7PfllE9Gkj0u3r0jb39q3xbE6q9/Qs9pE7wd+BKn4FNyU8wCn4DsuKT5vPF49Phw+k/389Mm+IT3DWf5MOh7e1f5G/n1ywPaW//MR4eil9EP0AU83sxf1d8Ub3YJ4q+iONZYRDHZ7b/aX6GovgIVfG9kr8ffYbz+fb2z/nbTZnw7O2f8V9N9clV8hMEwW8JRsF3q5i/QlX676rX+mSgqPmKnyGr42n/dh/mRfEjTIoP0Kv53Vlfj/z1tA/29s/5039hDmdv/2s9pE7wBXolv+r5aRP8CIh+UvpHSFnwQXy/GeabmG//fj9DUPyk+Q0IYp+q+ATB3v4lvqkJz96+ZR+pip8gCH5bIUr5ot/hofgIRfAZWK58vzMUxfcw2F/hQ1D8ANMm+Aq9mt8JPsB0Mj8e+UIfe/vn/Olv5KHs7e3P+QC74gdY75onC34BRsFXSEqfCFOn+XUT/KDnk+0v8AGK4LcJouC7FQYlf4VF6b9DEb4vmfP97X+HX859fvT843Vq880D2dv/o7811udyv0AV/IjmK/AQfE6wKB4YxD5B8AGoYp9R8AsQ7f+0a287bsJQFIapTxxssA3/+z9rJVS1VVOmezeDOp1s7mI+LS1bxJZChH7WeAdkpXcKX4Gs8yHqPFXyfC4/jspNlG/+VbyTPD/6/G+X9EAyb9681Dun8SMcCh8D7Enu0wirpk/T+QyMGh90fgiwKPvs5oU+45PCH4DGeyjK/KDpv0Lpyv7z237mp+/jDmRBvvnX8YLn5y/yxd/gU5g3b/4enyF0uU8FWpT7vgIKf56JSe5jgNY1XtlnV+5XQOjmhf6AfVb4AkGR3wuMXe7nBrsiPwN7evf+3xN7AAR9zJt/yst3uPO+efPmb/LbmhXeAwofCzAp8kcgyn0qyj4NcHLflfkzr+494yz3DmhZ7mdgH3T5JSp91/lxeL/+GWC++HyZb/6lfL72+Yl80d8OztvmzYv8I/9gff5/H6DKfQ6ofARwCj+i61MAp+sfstw7gPrZfO4KDzQn9w5A4TMQZrmvQFDkT0DIuv5j1Hku87eH1aiC9TH/Yn678tsT+Vdn5uM98+bNfxDvwyT3KUBwcr/o9oe+BJVPZ76T529AyBf+8jz9bH6BJYn9BLDI8x3A1nX5VZ6fGzAp+yxJ6ZX9t+ufn6m/W5+3+pt/Oe+vnx99/tWxYOM2buOfanyGluU+AHuX+jQ1IERxfi5Ac1Lfz/wmzk9uBML8P/jNO7lfgSL3sQC73DuANiWpzwA+i/Pns//UxflNN1/XgFaTuE8D1sv8/OADMLrLfPPmn/JXO/qX3w+aN2/+P/X1iHK/AZM43xWAsQt9XE5/zEKftwBQoji/nfnpH/m41S72GQg+Cn1aAcZpluYvqPLjCFCqdL59B1jFfvAAYZH2j8r5dq+b77Bd+70/8nQAtOX3+ebNP+Wvd9zz+vWjefNaP3ywPuZFfqNluQcIm9DnndNPIh+nMQDQJL5HN/kVAJY/+TinJPX5OCYXhX4F1hrnPgh8LAAUaX5tnH6rWdTfNXX+yZeaRd4DELaaZetZdwBGf/N8Jyfz+Wp9/Buv8mF97G/e/JP+egt6vAbz5s2/is9J4QthEvsVIBxR5F2A0y9d4Avwzfv8Jw8g9gXk/gDkvtdd5xfuzfdB5d2Iyg9uvHe+PrzD+izxyueLfPPmn/OaLXoYzJv/az98sD7m39XHrPAe1pqEfgUI6zJL/AYAsNc/94mA3O+g8M43lc8+aPxcR+7M73VH5aei7cOd8011fW59Vve2f1wf8+bv84+vmsybN2/+Xfzc5b4fR43i/DWU0U9uFvlpb0HsU578WOR+iJNfFb4r85Nbjjvz58kfe1N4p+wf3Xbsyvmq+9+4Ps68+dv8V5yOdlOUBd3vAAAAAElFTkSuQmCC);background-position:0 0;-webkit-background-size:1224px 24px;background-size:1224px 24px}.ring>span,[class*=" ring-"]>span,[class^=ring-]>span{display:inline-block;-webkit-transform:scale(.9,1);-ms-transform:scale(.9,1);-o-transform:scale(.9,1);transform:scale(.9,1)}.messager{border-radius:4px;-webkit-box-shadow:0 4px 16px rgba(0,0,0,.2),0 2px 8px rgba(0,0,0,.1);box-shadow:0 4px 16px rgba(0,0,0,.2),0 2px 8px rgba(0,0,0,.1)}.messager-icon{vertical-align:middle}.messager-icon>.icon{font-size:24px}.messager-content{padding:18px 20px;font-size:18px;line-height:30px}.messager-content>.icon{font-size:28px;line-height:30px}.messager-actions{vertical-align:middle}.messagger-zt{color:#3c4353;background-color:#fff!important}.messagger-zt .messager-icon>.icon{color:#0c64eb}.messagger-zt .messager-actions>.action{color:#838a9d}.messagger-zt.messager-success .messager-icon>.icon{color:#00da88}.messagger-zt.messager-danger .messager-icon>.icon{color:#ff5d5d}.messagger-zt.messager-warning .messager-icon>.icon{color:#ff9800}.messagger-zt.messager-info .messager-icon>.icon{color:#2196f3}.tree{padding-left:0;overflow:hidden}.tree ul{position:relative;display:none;padding-left:0}.tree li{position:relative;padding:2px 0 2px 15px;list-style:none}.tree li.heading{padding-left:5px;color:#3c495c}.tree li>a{display:block;max-width:90%;padding:2px 6px;color:#3c495c;word-break:break-all}.tree li>a:hover{color:#3c4353}.tree li>a.tree-toggle:hover{background:0 0}.tree li.active>a{position:relative;font-weight:700;color:#0c64eb}.tree li>.list-toggle{position:absolute;top:1px;left:1px;z-index:10;width:20px;font-size:14px;line-height:22px;color:#cbd0db;text-align:center;cursor:pointer;-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s}.tree li>.list-toggle:before{content:"\f0da"}.tree li>.list-toggle:active,.tree li>.list-toggle:hover{color:#0c64eb}.tree li.has-active-item>.list-toggle{color:#3c4353}.tree li.has-list.open>ul{display:block}.tree li.has-list.open>.list-toggle{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.tree li.has-list.open:before{position:absolute;top:16px;bottom:-5px;left:10px;display:block;content:' ';border-left:1px solid #d8d8d8}.tree-actions{display:inline-block;margin-left:5px;vertical-align:middle}.tree-actions a{display:inline-block;margin-left:5px;font-size:13px;opacity:.6}.tree-actions a:hover{opacity:1}.tree li>.module-name{color:#3c495c;vertical-align:middle}.tree li>.module-name:hover{background-color:#f0f2f5}.tree li>.module-name:hover>a{color:#3c4353}.treemap-node-fold-icon:before{position:relative;left:-4px;min-width:18px}.dropdown-menu{padding:5px 0;border-color:rgba(0,0,0,.1)}.dropdown-menu>li{padding:0 10px}.dropdown-menu>li>a{padding:2px 10px;margin:5px 0;border-radius:3px}.dropdown-menu>li>a>.icon{position:relative;left:-5px;opacity:.5}.dropdown-menu>li>a:hover>.icon{opacity:.8}.dropdown-menu>li.active>a,.dropdown-menu>li.selected>a{position:relative;color:#fff;background-color:#16a8f8}.dropdown-menu>li.selected>a:after{position:absolute;top:2px;right:4px;display:block;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;line-height:20px;text-transform:none;content:"\e5ca";speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.dropdown-menu>li.divider{margin:10px}.dropdown-submenu>a:after{margin-right:-5px}.dropdown-submenu>.dropdown-menu.pull-left{margin-left:-1px}.dropdown-submenu:focus>a,.dropdown-submenu:hover>a{color:#3c4353;background-color:#e9f2fb}.dropdown-submenu:hover>a:after{border-left-color:#0c64eb}.dropdown-submenu>a:hover:after{border-left-color:#fff}.pager .btn{padding:3px 10px}.pager .btn .caret{opacity:.7}.pager>li>.pager-label{padding:2px;line-height:20px}.pager>li>.pager-item{min-width:20px;padding:1px;margin:2px 0;font-size:16px;line-height:20px;text-align:center;background:0 0;border-color:transparent}.pager>li>.pager-item:hover{background-color:rgba(0,0,0,.1)}.pager>li>.pager-item>.icon{position:relative;top:-1px}.pager>li>.btn:hover,.pager>li>a:hover{background:rgba(0,0,0,.1)}.pager>li.disabled>a.pager-item{background:0 0;border-color:transparent;opacity:.5}.pager>li.active>a{background-color:#16a8f8}.pager>li .btn-group .btn{padding:1px;margin:1px 0;border-radius:4px}.pager .dropdown-menu{width:200px}.pager .dropdown-menu>li{float:left;width:33.333333%}.modal-dialog{width:900px;max-width:1360px;border:none;border-radius:0;-webkit-box-shadow:0 0 20px 0 rgba(0,0,0,.25);box-shadow:0 0 20px 0 rgba(0,0,0,.25)}.modal-dialog.modal-md{width:700px}.modal-dialog.modal-xs{width:400px}.modal-dialog.modal-sm{width:500px}.modal-dialog.modal-lg{width:1200px}.modal-dialog.modal-fullscreen{position:fixed;max-width:initial}.modal-header{padding:20px 0;margin:0 20px}.modal-header>.close{color:#838a9d;text-shadow:0 1px 0 rgba(255,255,255,.85);opacity:1}.modal-header>.close:hover{color:#222}.modal-footer{padding:20px 0;margin:0 20px}.modal-title{font-size:14px;font-weight:400;line-height:20px}.modal-actions{position:absolute;top:16px;right:16px}.modal-actions .divider{position:relative;top:5px;display:inline-block;width:0;height:20px;margin:0 10px;border-left:#eee 1px solid}.modal-actions>.dropdown{display:inline-block}.modal-body{padding:20px}.modal-iframe .modal-body>iframe{border-radius:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-3%);-ms-transform:translate(0,-3%);-o-transform:translate(0,-3%);transform:translate(0,-3%)}.modal.fade.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-simple .modal-footer{padding-top:0;border-top:none}.modal-iframe .modal-header{position:relative;z-index:10;min-height:0;padding:0;border:none}.modal-iframe .modal-title{display:none}.modal-iframe .modal-header .close{position:absolute;top:12px;right:10px;font-size:32px;font-weight:200}.modal-iframe .modal-dialog{overflow:hidden}.modal-inverse .modal-header>.close{color:rgba(255,255,255,.7);text-shadow:none}.modal-inverse .modal-header>.close:hover{color:#fff}.modal-scroll-inside>.modal-dialog{max-height:100%}.hide-modal-close .modal-iframe .modal-header .close{display:none}.tile{text-align:center}.tile-title{line-height:20px;color:#3c495c}.tile-amount{font-size:32px;font-weight:700;line-height:56px}.timeline>li{position:relative;list-style:none}.timeline>li:before,.timeline>li>a:after,.timeline>li>div:after{position:absolute;left:-20px;display:block;width:15px;height:15px;content:' ';border-radius:50%}.timeline>li:before{top:12px;left:-16px;z-index:3;width:7px;height:7px;background-color:#cbd0db;border:none;border:1px solid #cbd0db}.timeline>li>a:after,.timeline>li>div:after{top:11px;left:-17px;z-index:3;width:9px;height:9px;background-color:#0c64eb;border-radius:50%;opacity:0}.timeline>li+li:after{position:absolute;top:-12px;bottom:20px;left:-13px;z-index:1;display:block;content:' ';border-left:1px solid #eee}.timeline>li.active>a:after,.timeline>li.active>div:after{opacity:1}.timeline>li.active:before{top:8px;left:-20px;width:15px;height:15px;background-color:rgba(12,100,235,.2);border:none}.timeline>li>a,.timeline>li>div{display:block;padding:5px;line-height:20px}.timeline>li.active>a{color:#3c4353}.timeline-tag{position:absolute;top:5px;left:-115px;font-size:12px}.timeline-tag-left{padding-left:115px}.timeline-sm{font-size:12px}.timeline-sm>li:before,.timeline-sm>li>a:after,.timeline-sm>li>div:after{top:10px;left:-20px;width:11px;height:11px}.timeline-sm>li.active:before,.timeline-sm>li:before{top:10px;left:-18px;width:11px;height:11px;background:0 0;border:1px solid #eee}.timeline-sm>li>a,.timeline-sm>li>div{line-height:20px}.timeline-sm>li>a:after,.timeline-sm>li>div:after{top:13px;left:-15px;width:5px;height:5px}.form-control{-webkit-box-shadow:none;box-shadow:none}.form-horizontal .form-group>label{padding-right:0}.form-actions{margin-top:20px;margin-bottom:0}.form-actions .btn{margin-right:10px}form label{font-weight:400;color:#3c495c}.form-group .btn+.btn{margin-left:5px}.table-form{margin-bottom:0;table-layout:fixed}.table-form>thead>tr>th.required:after{position:relative;top:3px;right:auto;left:4px;display:inline-block;vertical-align:middle}.table-form>tbody>tr>td,.table-form>tbody>tr>th,.table-form>tfoot>tr>td,.table-form>thead>tr>th{padding:7px;vertical-align:middle;border-bottom:none}.table-form>tfoot>tr>td{padding:20px 7px 10px}.table-form>tbody>tr>th{width:100px;font-weight:700;text-align:right}.table-form .input-group{width:100%}.chosen-container-single .chosen-single{position:relative}.chosen-container-single .chosen-single>span{height:20px;line-height:20px;word-break:break-all;white-space:normal}.chosen-container-single .chosen-single div b{position:relative;top:1px;color:#cbd0db;opacity:1}.chosen-container-single .chosen-search:before{top:8px;right:15px}.chosen-container-multi .chosen-choices li.search-choice{font-size:13px;background:#eee;border-color:#cbd0db;-webkit-box-shadow:none;box-shadow:none}.chosen-container-single .chosen-search input[type=text]{height:30px;padding:3px 25px 3px 5px}.chosen-container-single .chosen-search{padding:3px 10px 0}.chosen-container-single .chosen-single{overflow:visible}.chosen-container .chosen-results{max-height:245px;padding:10px}.chosen-container .chosen-results>li{border-radius:4px}.chosen-container .chosen-results li.highlighted em{color:#fff}.table-responsive .chosen-container .chosen-results{max-height:200px}.chosen-compact.chosen-container-single .chosen-single>.chosen-search{top:-2px;right:-1px;bottom:-1px;left:-1px;display:none;height:auto;padding:0;opacity:0}.chosen-compact.chosen-container-single .chosen-single>.chosen-search>input{height:31px;padding:5px 26px 5px 8px;font-size:inherit;line-height:20px}.chosen-compact.chosen-container-single .chosen-single>.chosen-search:before{right:8px}.datetimepicker{padding:10px}.datetimepicker td.day.today{background-color:#f77}.datetimepicker td.day.active{background-color:#16a8f8}.datetimepicker tfoot th,.datetimepicker thead th{color:#838a9d}.input-control .colorpicker{top:0;z-index:auto;opacity:1}.input-control .colorpicker .btn{padding:5px}.input-control .input-control-icon-right.btn{top:0}.colorpicker .dropdown-menu{min-width:232px;padding:5px 10px 10px 10px}.colorpicker .dropdown-menu>li{display:block;float:left;padding:5px}.colorpicker .dropdown-menu>li.heading{width:100%;margin-bottom:5px;font-size:16px;font-weight:700;text-align:left}.colorpicker .dropdown-menu>li.heading>.icon-close{position:relative;top:4px;float:right;cursor:pointer;opacity:.6}.colorpicker .dropdown-menu>li>a{position:relative;display:block;width:100%;height:100%;padding:0;margin:0;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;text-align:center;text-transform:none;border:1px solid transparent;border-radius:50%;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.colorpicker .dropdown-menu>li>a:before{position:absolute;top:0;display:block;width:100%;height:20px;line-height:18px}.colorpicker .dropdown-menu>li>a:hover{-webkit-box-shadow:0 1px 4px rgba(0,0,0,.25);box-shadow:0 1px 4px rgba(0,0,0,.25)}.colorpicker .dropdown-menu>li>a.active:before{font-size:14px;content:"\e5ca"}.colorpicker .dropdown-menu>li>a.empty{color:#666;background:#fff}.colorpicker .dropdown-menu>li>a.empty:before{content:"\e90d"}.colorpicker .btn{position:relative}.colorpicker .btn .color-bar{position:absolute;right:5px;bottom:3px;left:5px;height:3px}.colorpicker .btn .color-bar[style*='background: ']+.ic{position:relative;top:-2px}.colorpicker .btn .ic{color:#cbd0db}.colorpicker .btn:hover .ic{color:#838a9d}.input-group .colorpicker{z-index:3}.input-group .chosen-container{display:table-cell}.input-group-addon{border-right-width:0;border-left-width:0}.input-group-addon:first-child{border-left-width:1px}.input-group-addon:last-child{border-right-width:1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin:0}.input-group-cell{display:table-cell;width:1%;padding:0 12px;white-space:nowrap;vertical-align:middle}.ke-container{border-color:#dcdcdc!important;border-radius:2px!important}.ke-container.focus{border-color:#0c64eb!important}.ke-toolbar{border-color:#dcdcdc!important}.required:after{top:6px;right:-10px;font-size:20px}td.required:after{top:12px;right:-5px}.input-group>.chosen-container.required:after,.input-group>.input-control.required:after{top:1px;right:1px;z-index:2}.input-group.required .required:after{display:none}.file-input{position:relative;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.file-input .input-group{width:auto}.file-input .input-group>.input-group-cell:first-child{padding-right:0;padding-left:7px}.file-input input[type=file]{position:absolute;width:0;height:0;opacity:0}.file-input .file-title{display:inline-block;max-width:400px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.file-input .file-editbox{min-width:200px;max-width:100%}.file-input .file-size{display:inline-block;vertical-align:middle}.edit .file-input-empty,.file-input-edit,.file-input-normal,.normal .file-input-empty{display:none}.edit .file-input-edit,.normal .file-input-normal{display:block}.edit .file-input-edit.input-group,.normal .file-input-normal.input-group{display:table}.edit .file-input-normal{display:none!important}.file-input-normal>.input-group-btn{width:auto}.input-group .chosen-container-active .chosen-choices{border-color:#0c64eb!important}.input-group .chosen-container{min-width:100px}.input-group .input-group-btn .btn>.icon{line-height:17px}.os-mac select.form-control{-webkit-appearance:none;background-image:url(data:image/gif;base64,R0lGODlhCQAFAIAAAMvQ2////yH5BAEAAAEALAAAAAAJAAUAAAIKhH+BGYoNGWxgFgA7);background-image:url(data:image/gif;base64,R0lGODlhBwAEAIAAAMvQ2////yH5BAEAAAEALAAAAAAHAAQAAAIIhA+BGWoNWSgAOw==);background-repeat:no-repeat;background-position:right 5px top 12px;-moz-appearance:none}input::-webkit-contacts-auto-fill-button{position:absolute;right:0;display:none!important;pointer-events:none;visibility:hidden}.chosen-choices.has-error,.chosen-single.has-error,.form-control.has-error{border-color:#ff5d5d!important;-webkit-box-shadow:0 0 6px #ffc3c3!important;box-shadow:0 0 6px #ffc3c3!important}.popover-success.popover-form-result{font-weight:700;color:#fff;background:#00da88}.popover-success.popover-form-result.popover.right .arrow:after{border-right-color:#00da88}textarea.kindeditor{padding:0!important}.form-unsaved{outline:2px solid #ff9800;-webkit-box-shadow:0 1px 12px #ff9800;box-shadow:0 1px 12px #ff9800;-webkit-transition:all .5s;-o-transition:all .5s;transition:all .5s}select[multiple].picker-select,select[multiple][data-toggle=picker]{max-height:32px;visibility:hidden}.picker-selection-remove:before{font-size:18px}.picker-user-option{position:relative;padding-left:40px}.picker-user-option>.avatar{position:absolute;top:5px;left:10px}.picker-user-option>.picker-option-text{display:inline-block;min-width:40px;font-weight:700}.picker-user-option>.dept-name,.picker-user-option>.role-name{display:inline-block;margin-left:10px;font-size:12px;opacity:.6}.picker-user-option>.dept-name{min-width:50px}#mainHeader{height:50px;color:#fff;background:-webkit-gradient(linear,right top,left top,from(#0a48d1),to(#1183fb));background:-webkit-linear-gradient(right,#0a48d1 0,#1183fb 100%);background:-o-linear-gradient(right,#0a48d1 0,#1183fb 100%);background:linear-gradient(-90deg,#0a48d1 0,#1183fb 100%);border-top-color:#0c64eb;border-bottom-color:#e9f2fb}#mainHeader>.container{min-width:1200px;padding:0}#heading{position:absolute;top:10px;left:20px}@media (min-width:1400px){#heading{left:40px}}#heading h1{float:left;max-width:250px;margin:0;overflow:hidden;font-size:20px;font-weight:400;line-height:30px;text-overflow:ellipsis;white-space:nowrap}#heading h1 a{color:inherit;text-decoration:inherit}#heading h1.long-name{position:relative;top:-5px;display:table-cell;font-size:16px;line-height:20px;word-break:break-all;white-space:normal}#heading>.btn{display:block;float:left;height:20px;padding:1px 5px;margin:0;margin:5px 0 0 10px;font-size:12px;font-weight:lighter;line-height:18px;background-color:rgba(255,255,255,.2);border:none}#heading>.btn:hover{background-color:rgba(0,0,0,.1)}#navbar{margin:0 auto;text-align:center}#navbar .nav{display:inline-block}#navbar .nav>li>a{padding:10px;line-height:30px;color:#fff;border-radius:0;opacity:.9}@media (max-width:1400px){#navbar .nav>li>a{padding:10px 8px}}#navbar .nav>li>a:focus,#navbar .nav>li>a:hover{background:rgba(0,0,0,.15);opacity:1}#navbar .nav>li.active>a{font-weight:700;background:rgba(0,0,0,.1);opacity:1}#navbar .nav>li.divider{display:block;width:2px;height:20px;margin:15px 8px;background:rgba(255,255,255,.4)}@media (max-width:1400px){#navbar .nav>li.divider{margin:15px 5px}}@media (max-width:1300px){#navbar .nav>li.divider{margin:15px 3px}}#navbar .nav>li.divider:last-child{display:none}#navbar .nav .dropdown-menu li>a{text-align:left}#toolbar{position:absolute;top:12px;right:20px;font-size:12px;color:#fff}@media (min-width:1400px){#toolbar{right:40px}}#extraNav{text-align:right}#extraNav>li{display:inline-block;float:none;text-align:left}#extraNav>li>a{display:block;padding:0;color:#fff;opacity:.75}#extraNav>li>a:hover{text-decoration:unset;background-color:rgba(0,0,0,.1);opacity:1}#extraNav>li.open>a{background-color:rgba(0,0,0,.1)}#extraNav>li+li{margin-left:10px}#showSearchGo{color:#fff;background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.5)}#searchbox{position:relative;float:left;width:150px}#searchbox .input-group-btn .btn{position:relative;padding:1px 4px;font-size:12px;line-height:20px;color:#fff;background-color:rgba(255,255,255,.15);border-right:none;border-radius:2px}#searchbox .input-group-btn .btn:after{position:absolute;top:3px;right:0;bottom:3px;display:block;width:1px;content:' ';background-color:rgba(255,255,255,.15)}#searchbox .input-group-btn .btn:hover{background-color:rgba(255,255,255,.25)}#searchGo{position:absolute;top:0;right:-1px;z-index:9;min-width:24px;height:24px;padding:2px 3px;font-size:12px;line-height:20px;color:#fff;background-color:#16a8f8;border-radius:2px}#searchGo:hover{color:#fff!important;background-color:#0c64eb}#searchInput{height:24px;padding:2px 30px 2px 5px;color:#fff;text-align:left;background:rgba(255,255,255,.15);border-color:transparent;border-radius:0 12px 12px 0;-webkit-transition:background .2s,border .2s;-o-transition:background .2s,border .2s;transition:background .2s,border .2s}#searchInput:hover{background:rgba(255,255,255,.25)}#searchInput:focus{color:#333;background:#fff}#searchInput::-webkit-input-placeholder{font-size:12px;color:#fff;color:rgba(255,255,255,.5)}#searchInput::-moz-placeholder{font-size:12px;color:#fff;color:rgba(255,255,255,.5)}#searchInput:-ms-input-placeholder{font-size:12px;color:#fff;color:rgba(255,255,255,.5)}#searchInput::placeholder{font-size:12px;color:#fff;color:rgba(255,255,255,.5)}#searchInput:focus::-webkit-input-placeholder{color:#838a9d}#searchInput:focus::-moz-placeholder{color:#838a9d}#searchInput:focus:-ms-input-placeholder{color:#838a9d}#searchInput:focus::placeholder{color:#838a9d}#searchTypeMenu{min-width:220px}#searchTypeMenu>li{float:left;width:50%}#searchTypeMenu>li>a{margin:4px 0}#userNav .avatar{display:inline-block;vertical-align:middle}#userNav>li>a{padding:2px 6px;line-height:20px;color:#fff;opacity:.9}#userNav>li>a .user-name{max-width:100px;overflow:hidden;font-size:15px;text-overflow:ellipsis;white-space:nowrap}#userNav>li>a:hover{background-color:rgba(0,0,0,.1);opacity:1}#userNav>li>a:hover>i{opacity:1}#userNav>li>a span{vertical-align:middle}#userNav>li.open>a{background-color:rgba(0,0,0,.1)}#userNav>li.has-new-items>a{position:relative}#userNav>li.has-new-items>a:before{position:absolute;top:3px;right:-1px;display:block;width:4px;height:4px;content:' ';background-color:#ff5d5d;border-radius:50%}#userNav .dropdown-menu{min-width:150px}#userNav .dropdown-menu>li>a>.icon{position:absolute;top:10px;right:5px;display:block;width:20px;height:20px;line-height:20px;text-align:center}#userNav .user-profile-item>a{position:relative;padding-left:45px}#userNav .user-profile-item .avatar{position:absolute;top:6px;left:5px}#userNav .user-profile-name{font-size:16px}#userNav .user-profile-role{font-size:12px;color:#a9abb8}#userNav .no-role .user-profile-role{display:none}#userNav .no-role .user-profile-name{line-height:40px}#subHeader{min-height:50px;background:#fff}#subHeader>.container{padding:0 20px}@media (min-width:1400px){#subHeader>.container{padding:0 40px}}#pageNav{position:absolute;top:8px;left:0;left:20px}@media (min-width:1400px){#pageNav{left:40px}}#subNavbar{margin-top:5px;font-size:14px;text-align:center}#subNavbar .nav{display:inline-block}#subNavbar .nav>li>a{padding:8px 12px;line-height:24px;color:#3c495c}#subNavbar .nav>li>a:hover{color:#3c495c;background-color:rgba(0,0,0,.075)}#subNavbar .nav>li.active>a{font-weight:700;color:#0c64eb}#subNavbar .nav>li.divider{display:block;width:2px;height:20px;margin:9px 5px;background-color:rgba(0,0,0,.05)}#subNavbar .dropdown-menu{text-align:left}[lang=en] #subNavbar>.nav>li>a{padding-right:8px;padding-left:8px}#pageActions{position:absolute;top:9px;right:20px}@media (min-width:1400px){#pageActions{right:40px}}.cell{padding:10px;background-color:#fff;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045);box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045)}.cell+.cell{margin-top:10px}.cell>.panel{margin:0;-webkit-box-shadow:none;box-shadow:none}.cell>.panel>.panel-heading{padding:5px 5px 10px}.cell>.panel>.panel-heading .panel-actions{padding:0}.cell>.panel>.panel-body{padding:5px}.cell>.table{margin:0}#main{min-width:1200px;padding:20px 0}#main>.container{padding:0 20px}@media (min-width:1400px){#main>.container{padding:0 40px}}#header,#header+#main{min-width:1200px}#mainMenu{margin:-10px 0 8px}.main-content{padding:20px;background-color:#fff;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045);box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045)}@media (min-width:1400px){.main-content>.center-block{max-width:1350px;padding:20px;border:1px solid #eee}.main-content>.center-block .main-header{background-color:#f1f1f1}}.main-content>h2{margin:0 0 20px}.main-content .cell{-webkit-box-shadow:none;box-shadow:none}.main-header{padding:5px 20px;border-bottom:1px solid #eee}.main-header:after,.main-header:before{display:table;content:" "}.main-header:after{clear:both}.main-header>h2{display:block;float:left;margin:0 10px 0 0;font-size:14px;line-height:34px}.main-header>h2 .label-id{margin-right:5px}.main-header>h2 small{font-size:14px;font-weight:400}.main-content .main-header{margin:-20px -20px 10px}.main-header .label{top:-1px}.main-row{display:table;width:100%;table-layout:fixed}.main-row>[class*=" col-"],.main-row>[class*="-col"],.main-row>[class^=col-]{display:table-cell;vertical-align:top}@media (max-width:720px){.main-row{display:block}.main-row>*{display:block;width:100%}.main-row .side-col{width:100%;padding:0}.main-row .main-col+.side-col,.main-row .side-col+.main-col{margin-top:10px}}.main-row.hide-side .side-col{display:none}.main-form{margin:0}@media (min-width:720px){.main-content>.center-block .main-form{padding-right:20px}}#main .side-col .tabs{padding:5px}#main .side-col .nav-tabs{margin:0 5px 5px 5px}#main .side-col .nav-tabs>li{margin:0}#main .side-col .nav-tabs>li+li{margin-left:10px}#main .side-col .nav-tabs>li>a{padding:8px 5px}#main .side-col .tab-content .tab-pane table{border:none}.main-actions .btn-toolbar{display:inline-block;padding:4px 15px;color:#fff;pointer-events:auto;background:#717171;background-color:rgba(90,90,90,.85);border-radius:4px}.main-actions .btn-toolbar .divider{margin-right:15px;margin-left:15px;border-color:rgba(255,255,255,.1)}.main-actions .btn-toolbar .btn{height:30px;padding-right:10px;padding-left:10px;margin-right:0;color:#fff;background-color:transparent;border:none}.main-actions .btn-toolbar .btn+.btn{margin-left:10px}.main-actions .btn-toolbar .btn:focus,.main-actions .btn-toolbar .btn:hover{background-color:rgba(255,255,255,.2)}.main-actions .btn-toolbar .btn.btn-icon{min-width:32px;padding-right:0;padding-left:0}.main-actions .btn-toolbar .btn+.btn-group{margin-right:0;margin-left:10px}#mainContent .main-col>.main-actions{padding:30px 0 0 0;text-align:center}#mainContent .main-col>.main-actions>.btn-toolbar{visibility:visible;opacity:1;-webkit-transition:opacity .2s;-o-transition:opacity .2s;transition:opacity .2s}#mainActions{position:fixed;top:0;right:0;bottom:0;left:0;text-align:center;pointer-events:none}#mainActions .btn-toolbar{position:relative;top:-90px}#mainActions .dropdown-menu{text-align:left}#mainActions>.container{height:100%}.main-actions-holder{display:none}.main-actions-fixed .main-actions-holder{display:block}.main-actions-fixed #mainContent .main-col>.main-actions{position:fixed;bottom:10px}.main-actions-fixed.body-modal #mainContent .main-col>.main-actions{bottom:20px}#nextPage,#prevPage{position:absolute;top:50%;left:-10px;width:40px;height:60px;padding:10px 0;margin-top:-30px;line-height:40px;color:#fff;text-align:center;pointer-events:auto;background:#717171;background-color:rgba(90,90,90,.85);-webkit-box-shadow:0 2px 15px 2px rgba(0,0,0,.05);box-shadow:0 2px 15px 2px rgba(0,0,0,.05)}#nextPage:hover,#prevPage:hover{-webkit-box-shadow:0 2px 15px 2px rgba(0,0,0,.15);box-shadow:0 2px 15px 2px rgba(0,0,0,.15)}#nextPage>i,#prevPage>i{display:block;font-size:18px;line-height:36px}#nextPage{right:-10px;left:auto}@media (max-width:1800px){#prevPage{left:-3px}#nextPage{right:-3px}}#sidebarHeader{position:relative;float:left;width:180px;height:34px;padding-right:20px;margin-right:20px;background:#fff;border-left:4px solid #0c64eb;border-radius:4px 2px 2px 4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045);box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045)}#sidebarHeader:after{position:absolute;top:-1px;right:-8px;display:block;width:0;height:0;content:' ';border-color:transparent transparent transparent #fff;border-style:solid;border-width:18px 0 18px 8px}#sidebarHeader .title{padding:0 5px;overflow:hidden;font-size:14px;font-weight:700;line-height:32px;color:#0c64eb;text-align:center;text-overflow:ellipsis;white-space:nowrap}#sidebarHeader .title>a{position:absolute;top:0;right:0;width:20px;opacity:.5}#sidebarHeader .title>a:hover{opacity:1}#sidebar{position:relative;-webkit-transition:width .2s,padding .2s;-o-transition:width .2s,padding .2s;transition:width .2s,padding .2s}#sidebar>.sidebar-toggle{position:absolute;top:0;right:5px;bottom:0;width:10px;cursor:pointer;background:0 0;border-radius:5px;-webkit-transition:background-color .2s,opacity .5s;-o-transition:background-color .2s,opacity .5s;transition:background-color .2s,opacity .5s}#sidebar>.sidebar-toggle>.icon{position:absolute;top:50%;left:-1px;width:12px;height:30px;margin-top:-10px;line-height:30px;color:#fff;text-align:center;background:#79cdfb;border-radius:6px}#sidebar>.sidebar-toggle>.icon:before{position:relative;left:-1px}#sidebar>.sidebar-toggle:before{position:absolute;top:0;right:-5px;bottom:0;left:-5px;display:block;content:' '}#sidebar>.sidebar-toggle:hover{background:rgba(0,0,0,.075)}#sidebar>.cell{position:relative;left:0;width:180px;-webkit-transition:left .2s,opacity .2s;-o-transition:left .2s,opacity .2s;transition:left .2s,opacity .2s}#sidebar.no-animate>.cell{display:none;-webkit-transition:none;-o-transition:none;transition:none}.hide-sidebar #sidebar>.cell{position:absolute;left:-200px;visibility:hidden;opacity:0}.hide-sidebar #sidebar{position:relative;width:0;padding:0}.hide-sidebar #sidebar>.sidebar-toggle>.icon:before{content:"\e315"}@media (max-width:720px){#sidebar>.cell{width:100%}}#queryBox{max-height:0;padding:0;overflow:hidden;-webkit-transition:cubic-bezier(.175,.885,.32,1) .2s;-o-transition:cubic-bezier(.175,.885,.32,1) .2s;transition:cubic-bezier(.175,.885,.32,1) .2s;-webkit-transition-property:padding,max-height,margin;-o-transition-property:padding,max-height,margin;transition-property:padding,max-height,margin}#queryBox>form{visibility:hidden;-webkit-transition:visibility .2s .2s;-o-transition:visibility .2s .2s;transition:visibility .2s .2s}#queryBox.loading{height:50px}#queryBox.show{min-height:110px;max-height:300px;margin-bottom:10px;overflow:visible}#queryBox.show>form{visibility:visible}#queryBox.divider{border-bottom:1px solid #eee}#main .querybox-toggle.querybox-opened{position:relative;color:#0c64eb;background:0 0;border:none}#main .querybox-toggle.querybox-opened:before{position:absolute;bottom:-14px;left:50%;width:0;height:0;content:' ';border-color:transparent transparent #fff transparent;border-style:solid;border-width:0 10px 10px 10px}#contentNav{padding:5px;background:#fff;border-bottom:1px solid #eee}#contentNav .nav>li>a{position:relative;padding:6px 10px;color:#838a9d}#contentNav .nav>li.active>a{font-weight:700;color:#0c64eb}#contentNav .nav>li.active>a:before{position:absolute;right:10px;bottom:3px;left:10px;display:block;height:2px;content:' ';background:#0c64eb}.body-modal{padding-bottom:0}.body-modal #main,.body-modal .container{min-width:0!important}.body-modal #main{padding:0}.body-modal .main-header{position:fixed;top:0;right:20px;left:20px;z-index:100;padding:13px 48px 13px 0;margin:0;background:#fff}.body-modal #mainContent{padding-top:70px}.body-modal .main-header>h2{max-width:100%;overflow:hidden;font-size:14px;text-overflow:ellipsis;white-space:nowrap}.body-modal .cell,.body-modal .main-content{-webkit-box-shadow:none;box-shadow:none}.body-modal #mainMenu{position:fixed;top:0;right:0;left:0;z-index:100;padding:12px 60px 12px 10px;margin:0;background:#fff}.body-modal #mainMenu>.btn-toolbar.pull-left.divider{display:none}.body-modal #mainMenu>.btn-toolbar{width:100%;margin-left:20px}.body-modal #mainMenu>.btn-toolbar>.divider:first-child{display:none}.body-modal #mainMenu>.btn-toolbar .page-title{width:100%;margin-left:0}.body-modal #mainMenu>.btn-toolbar .page-title>.text{position:relative;top:-2px;display:inline-block;max-width:85%;max-width:-webkit-calc(100% - 100px);max-width:calc(100% - 100px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.body-modal #mainMenu+#mainContent.main-row{padding:60px 10px 0}.body-modal #mainMenu+#mainContent.main-row .cell{border:1px solid #efefef;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045);box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045)}.body-modal #mainActions{top:auto}.body-modal #mainActions .btn-toolbar{top:auto;bottom:10px}.body-modal.m-bug-view,.body-modal.m-story-view,.body-modal.m-task-view,.body-modal.m-testcase-view,.body-modal.m-testtask-view,.body-modal.m-todo-view{padding-bottom:20px;border-radius:3px}#tabsNav{position:relative}#tabsNav .tab-pane>.actions{position:absolute;top:-8px;right:0}#tabsNav .tab-pane>.cell,#tabsNav .tab-pane>.main-table{padding:0;border:1px solid #cbd0db;border-top:none;border-radius:0 0 4px 4px}#tabsNav .tab-pane>.cell .detail-title{padding-left:5px}#helpContent{position:fixed;top:50px;right:0;bottom:40px;left:0;display:none;background-color:#fff}#helpContent .load-error{display:none;padding:20px}#helpContent .show-error .load-error{display:block}.text-middle td,.text-middle th{vertical-align:middle}.text-center td,.text-center th{text-align:center}.c-sm{width:40px}.c-id{width:90px}.c-id-sm{width:70px}.c-id-xs{width:55px}.c-date{width:100px}.c-num,.c-pri,.c-type{width:80px;overflow:hidden}.c-begin,.c-end,.c-time{width:65px}.c-hours{width:60px}.c-actions-1{width:50px}.c-actions-2{width:75px}.c-actions-3{width:102px}.c-actions,.c-actions-4{width:128px}.c-actions-5{width:155px}.c-actions-6{width:180px}.c-product,.c-project{width:180px}.c-plan{width:130px}.c-datetime{width:120px}.c-stage,.c-status,.c-user{width:80px}.c-side{width:200px;border-right:10px solid #efefef}.c-assign,.c-assignedTo,.c-openedBy{width:130px}.c-progress{width:155px}.c-assign,.c-assignedTo,.c-openedBy,.c-product,.c-project,.c-status,.c-url,.c-user{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}td.c-name,td.c-title{overflow:hidden;text-align:left!important;text-overflow:ellipsis;white-space:nowrap}td.c-actions{position:relative;padding-top:0;padding-bottom:0;overflow:hidden;white-space:nowrap;vertical-align:middle}td.c-actions .btn-link{color:#3c495c;background:0 0}td.c-actions .btn-link:hover{color:#0c64eb;background:#e9f2fb}td.c-actions .btn.disabled,td.c-actions .btn[disabled]{pointer-events:auto}td.c-actions .more{position:absolute;top:50%;right:100%;display:none;padding-right:4px;padding-left:20px;margin-top:-15px;margin-right:-6px;white-space:nowrap;background-color:#fafafa;-webkit-transition:opacity .3s,margin .3s;-o-transition:opacity .3s,margin .3s;transition:opacity .3s,margin .3s}tr:hover td.c-actions .more{display:block}td:hover+td.c-actions>.more{margin-right:-15px;pointer-events:none;opacity:.15}tr[data-url]{cursor:pointer}.table tbody>tr>td,.table thead>tr>th{vertical-align:middle}.table tbody>tr>td.has-btn,.table thead>tr>th.has-btn{padding-top:1px;padding-bottom:1px;overflow:visible}.table tbody>tr>td .progress,.table thead>tr>th .progress{height:6px}.table .em,.table em{color:#3c4353}.table .divider{border-bottom:10px solid #efefef}.table .divider-top{border-top:10px solid #efefef}.table .btn-icon-left{max-width:100%;padding-left:20px;overflow:hidden;line-height:18px;text-align:left;text-overflow:ellipsis;background:0 0;border-color:#eaf3fc}.table .btn-icon-left>.icon{width:20px;font-size:14px;background:0 0!important;opacity:0}.table .btn-icon-left.btn-sm{height:26px;font-size:13px}.table .btn-icon-left:active,.table .btn-icon-left:focus,.table .btn-icon-left:hover{border-color:rgba(0,0,0,.2)}.table .btn-icon-left:active>.icon,.table .btn-icon-left:focus>.icon,.table .btn-icon-left:hover>.icon{opacity:1}.table .btn-icon-left>.text{padding-left:25px}.table thead>tr>th.c-assign,.table thead>tr>th.c-assignedTo{padding-left:29px}.table a{vertical-align:middle}.table tbody>tr:last-child{border-bottom:none}.table caption{margin-bottom:5px;background:#f1f1f1;border:none}.is-firefox .table .btn-icon-left>.icon{line-height:22px}.main-table{border-radius:4px}.main-table>.table,.main-table>.table-footer,.main-table>.table-header,.main-table>.table-responsive{-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045);box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045)}.main-table .table{font-size:13px;table-layout:fixed;background-color:#fff;border-radius:4px 4px 0 0}.main-table .table.table-lg{font-size:14px}.main-table .table .btn-icon-left{border-color:transparent}.main-table .table .btn-icon-left>.icon{background:0 0;border-radius:4px}.main-table .table .btn-icon-left.btn-sm{height:26px}.main-table .table .btn-icon-left:hover{border-color:rgba(0,0,0,.2)}.main-table .table .btn-icon-left:hover>.icon{background:#e9f2fb;border-radius:4px 0 0 4px}.main-table tbody>tr>td,.main-table thead>tr>th{min-height:36px;padding:2px 8px;line-height:30px}.main-table tbody>tr>td:first-child,.main-table thead>tr>th:first-child{padding-right:4px;padding-left:15px}.main-table thead>tr>th{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-bottom:1px solid #ddd}.main-table tbody>tr:nth-child(odd){background-color:#f5f5f5}.main-table tbody>tr:last-child>td{border-bottom:1px solid #ddd}.main-table tbody>tr>td{position:relative;border-bottom:none;border-bottom:1px solid #eee}.main-table tbody>tr>td .label{max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.main-table tbody>tr>td>a{line-height:28px;color:#0c60e1}.main-table tbody>tr>td>a:not(.btn):visited{color:#082999;opacity:.9}.main-table tbody>tr>td>a:hover,.main-table tbody>tr>td>a:visited:hover{color:#0c64eb}.main-table tbody>tr>td.c-actions{padding-right:10px}.main-table tbody>tr>td.c-side+td:before,.main-table tbody>tr>td:first-child:before{position:absolute;top:0;bottom:0;left:0;display:block;width:0;content:'';background:#0c64eb;opacity:0;-webkit-transition:.2s linear;-o-transition:.2s linear;transition:.2s linear;-webkit-transition-property:width,opacity,border-radius;-o-transition-property:width,opacity,border-radius;transition-property:width,opacity,border-radius}@-moz-document url-prefix(){.main-table tbody>tr>td.c-side+td:before,.main-table tbody>tr>td:first-child:before{bottom:-1px}}.main-table tbody>tr>td.c-side:before{display:none}.main-table tbody>tr{-webkit-transition:.2s cubic-bezier(.175,.885,.32,1);-o-transition:.2s cubic-bezier(.175,.885,.32,1);transition:.2s cubic-bezier(.175,.885,.32,1);-webkit-transition-property:background-color,-webkit-box-shadow;-o-transition-property:box-shadow,background-color;transition-property:background-color,-webkit-box-shadow;transition-property:box-shadow,background-color;transition-property:box-shadow,background-color,-webkit-box-shadow}.main-table tbody>tr:hover{background:#e9f2fb}.main-table .table-grouped tbody>tr:hover{background:#f2f7fd;-webkit-box-shadow:none;box-shadow:none}.main-table .table-grouped tbody>tr:hover td.c-actions .more{background:#f2f7fd}.main-table tbody>tr.checked{background:#fff3e0}.main-table tbody>tr.checked:hover{background:#ffebbc}.main-table tbody>tr.checked>td.c-side+td:before,.main-table tbody>tr.checked>td:first-child:before{width:4px;opacity:1}.main-table tbody>tr.checked.row-check-begin{border-top-left-radius:4px;border-top-right-radius:2px}.main-table tbody>tr.checked.row-check-begin>td:first-child:before{border-top-left-radius:4px}.main-table tbody>tr.checked.row-check-end{border-bottom-right-radius:2px;border-bottom-left-radius:4px}.main-table tbody>tr.checked.row-check-end>td:first-child:before{border-bottom-left-radius:4px}.main-table .checkbox-primary{display:inline-block;line-height:20px}.main-table .checkbox-primary label{margin:0}.main-table .table{margin:0}.table-header{padding:4px 0 12px}.table-header .table-statistic{color:#838a9d}.table-header .table-statistic strong{font-size:15px;color:#3c4353}.table-header .btn-toolbar{margin-top:-28px}.table-header.fixed-right{position:relative;z-index:5;padding:0}.table-header.fixed-right>.btn-toolbar{position:absolute;top:0;right:1px;z-index:1;padding:1px;margin:0;background:#fff;border-radius:4px}.table-header.fixed-right>.btn-toolbar .btn{opacity:.65}.table-header.fixed-right>.btn-toolbar .btn:hover{opacity:1}.table-header-fixed .table-header{position:fixed;top:0}.table-header-fixed .table-header>.btn-toolbar{background-color:transparent}.table-header-fixed .table-header>.btn-toolbar .btn{color:#fff}.table-footer{position:relative;min-height:40px;padding:6px 15px;background:#fff;border-radius:0 0 4px 4px}.body-modal .table-footer{margin-bottom:20px}.talbe-lg+.table-footer{padding:11px 15px}.table-footer .btn-toolbar,.table-footer .checkbox-primary{float:left}.table-footer .btn-toolbar+.btn-toolbar{margin-left:8px}.table-footer .checkbox-primary{margin:5px 20px 0 0}.table-footer .checkbox-primary.checked label:after{border-color:#00da88!important}.table-footer .btn{padding:3px 10px;line-height:20px}.table-footer .pager{position:absolute;top:0;right:0;z-index:5;height:40px;padding:6px 5px 6px 10px;margin:0;background:#fff;opacity:1;-webkit-transition:opacity .4s;-o-transition:opacity .4s;transition:opacity .4s}.table-footer .pager:before{position:absolute;top:0;bottom:0;left:-50px;display:block;width:50px;content:' ';background:-webkit-gradient(linear,left top,right top,from(rgba(255,255,255,0)),to(#fff));background:-webkit-linear-gradient(left,rgba(255,255,255,0) 0,#fff 100%);background:-o-linear-gradient(left,rgba(255,255,255,0) 0,#fff 100%);background:linear-gradient(to right,rgba(255,255,255,0) 0,#fff 100%)}.table-footer .pager .btn,.table-footer .pager>li>.pager-item,.table-footer .pager>li>.pager-label{color:#838a9d;background:0 0;border-color:transparent}.table-footer .pager .btn,.table-footer .pager>li>a{border-radius:3px}.table-footer .pager .btn:hover,.table-footer .pager>li>a:hover{background:rgba(0,0,0,.1)}.table-footer .pager>li.disabled>a.pager-item{opacity:1}.table-footer .form-control{height:28px;padding:3px 8px}.table-footer .table-statistic{position:relative;z-index:2;float:left;padding-right:30px;line-height:28px;color:#838a9d;background:#fff}.table-footer .table-statistic:hover{z-index:4}.table-footer .table-statistic:hover+.pager{z-index:2;opacity:.3}.table-footer .btn-toolbar+.table-statistic,.table-footer .btn-toolbar+.text{margin-left:10px}.table-footer .text{float:left;line-height:28px}.table-footer.fixed-footer{position:fixed;z-index:10;margin:0;background:rgba(75,75,75,.85);border-top-color:transparent}.table-footer.fixed-footer .checkbox-primary label{color:#fff}.table-footer.fixed-footer .checkbox-primary label:after{border-color:rgba(255,255,255,.8)}.table-footer.fixed-footer .table-statistic{color:#fff;background:0 0}.table-footer.fixed-footer .pager{background:#666}.table-footer.fixed-footer .pager:before{background:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,0)),to(#666));background:-webkit-linear-gradient(left,rgba(0,0,0,0) 0,#666 100%);background:-o-linear-gradient(left,rgba(0,0,0,0) 0,#666 100%);background:linear-gradient(to right,rgba(0,0,0,0) 0,#666 100%)}.table-footer.fixed-footer .pager .btn,.table-footer.fixed-footer .pager>li>.pager-item,.table-footer.fixed-footer .pager>li>.pager-label{color:#fff}.table-footer.fixed-footer .pager .btn:hover,.table-footer.fixed-footer .pager>li>a:hover{background:rgba(255,255,255,.3)}.table-footer.fixed-footer .pager>li.disabled>a.pager-item{opacity:.5}.table-actions{display:none;height:28px}.table-actions.show-always{display:block;pointer-events:none;cursor:not-allowed}.has-row-checked .table-actions{display:block;pointer-events:auto!important;cursor:default}.table-lg tbody>tr>td{padding:9px 10px}.table-lg tbody>tr>td .btn+.btn{margin-left:5px}.table.has-sort-head thead>tr>th{padding-right:0}.table.has-sort-head thead>tr>th>a{position:relative;display:inline-block;padding-right:16px;color:#3c4353}.table.has-sort-head thead>tr>th>a:after,.table.has-sort-head thead>tr>th>a:before{position:absolute;top:0;right:0;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;line-height:30px;color:#3c495c;text-transform:none;content:"\f0de";opacity:.5;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.table.has-sort-head thead>tr>th>a:after{content:"\f0dd"}.table.has-sort-head thead>tr>th>a.sort-down,.table.has-sort-head thead>tr>th>a.sort-up{color:#000;text-decoration:none}.table.has-sort-head thead>tr>th>a:hover,.table.has-sort-head thead>tr>th>a:hover:after,.table.has-sort-head thead>tr>th>a:hover:before{color:#0c64eb;opacity:1}.table.has-sort-head thead>tr>th>a.sort-down:after,.table.has-sort-head thead>tr>th>a.sort-up:before{color:#000;opacity:1}.head-fixed .datatable-head-span .table,.table.fixed-header-copy{z-index:10;color:#fff;background:rgba(75,75,75,.85)}.head-fixed .datatable-head-span .table thead>tr>th,.table.fixed-header-copy thead>tr>th{color:#eee}.head-fixed .datatable-head-span .table thead>tr>th>a,.table.fixed-header-copy thead>tr>th>a{color:#eee}.head-fixed .datatable-head-span .table thead>tr>th>a:hover,.table.fixed-header-copy thead>tr>th>a:hover{color:#fff}.head-fixed .datatable-head-span .table thead>tr>th>a:after,.head-fixed .datatable-head-span .table thead>tr>th>a:before,.table.fixed-header-copy thead>tr>th>a:after,.table.fixed-header-copy thead>tr>th>a:before{color:#eee}.head-fixed .datatable-head-span .table thead>tr>th>a.sort-down,.head-fixed .datatable-head-span .table thead>tr>th>a.sort-down:after,.head-fixed .datatable-head-span .table thead>tr>th>a.sort-up,.head-fixed .datatable-head-span .table thead>tr>th>a.sort-up:before,.head-fixed .datatable-head-span .table thead>tr>th>a:hover,.head-fixed .datatable-head-span .table thead>tr>th>a:hover:after,.head-fixed .datatable-head-span .table thead>tr>th>a:hover:before,.table.fixed-header-copy thead>tr>th>a.sort-down,.table.fixed-header-copy thead>tr>th>a.sort-down:after,.table.fixed-header-copy thead>tr>th>a.sort-up,.table.fixed-header-copy thead>tr>th>a.sort-up:before,.table.fixed-header-copy thead>tr>th>a:hover,.table.fixed-header-copy thead>tr>th>a:hover:after,.table.fixed-header-copy thead>tr>th>a:hover:before{color:#fff}.head-fixed .datatable-head-span .table thead>tr>th>.dropdown>a,.table.fixed-header-copy thead>tr>th>.dropdown>a{color:#eee}.head-fixed .datatable-head-span .table thead>tr>th>.dropdown>a:hover,.table.fixed-header-copy thead>tr>th>.dropdown>a:hover{color:#fff}.head-fixed .datatable-head-span .table .checkbox-primary,.table.fixed-header-copy .checkbox-primary{z-index:1}.head-fixed .datatable-head-span .table .checkbox-primary label,.table.fixed-header-copy .checkbox-primary label{color:#fff}.head-fixed .datatable-head-span .table .checkbox-primary label:after,.table.fixed-header-copy .checkbox-primary label:after{border-color:rgba(255,255,255,.8)}.head-fixed .datatable-head-span .table .checkbox-primary.checked label:after,.table.fixed-header-copy .checkbox-primary.checked label:after{border-color:#00da88!important}.table-data{margin:0;table-layout:fixed}.table-data tbody>tr>td,.table-data tbody>tr>th{padding:6px 8px;word-break:break-all;border:none}.table-data tbody>tr>th{width:70px;padding-left:0;font-weight:400;color:#838a9d;text-align:right;vertical-align:middle}.table-data tbody>tr>td{padding-right:0}.table-data tbody>tr>td>a{color:#0c60e1}.table-data tbody>tr>td>a:not(.btn):visited{color:#082999}.table-data tbody>tr>td>a:hover,.table-data tbody>tr>td>a:visited:hover{color:#0c64eb}.table-data ol,.table-data ul{margin:0}.fixed-head-table{background:rgba(0,0,0,.7);border-bottom:1px solid #ddd}.fixed-head-table thead>tr>th{color:#fff}.table-empty-tip{padding:80px 10px;text-align:center;background:#fff}.not-firefox .table-grouped>tbody>tr>td.c-side{background:#fff!important}.table-grouped .group-toggle{cursor:pointer}.table-grouped .group-toggle.group-summary{border-top:10px solid #efefef}.table-grouped tbody>tr>td:first-child,.table-grouped thead>tr>th:first-child{padding-left:8px}.group-expand-all,.table-group-collapsed .group-collapse-all{display:none}.table-group-collapsed .group-expand-all{display:inline-block}.table-auto{table-layout:auto}.datatable .table>tbody>tr.checked.hover>td,.datatable .table>tbody>tr.checked>td.col-hover{background:#ffebbc}body.has-fixed-footer{padding-bottom:60px}.table.with-footer-fixed{margin-bottom:20px}.table-nest-hide{display:none!important}th.table-nest-title{position:relative;padding-left:30px!important}.table-nest-icon{position:relative;display:inline-block;width:22px;height:22px;font-size:16px;color:#a6aab8;text-align:center;border-radius:4px}.table-nest-toggle:before{line-height:22px;content:"\e6f2"}.table-nest-toggle:hover{color:#0c64eb;background-color:rgba(0,0,0,.1)}.table-nest-child-hide .table-nest-toggle:before{font-size:16px;content:"\e6f1"}th.table-nest-title .table-nest-toggle{position:absolute!important;top:7px;left:8px}.table-nest-toggle.table-nest-toggle-global{width:22px;height:22px;padding:0!important;line-height:22px;text-align:center;border-radius:4px}.table-nest-toggle.table-nest-toggle-global:before{position:static!important;font-size:16px!important;line-height:22px!important;content:"\e6f2"!important;opacity:1!important}.table-nest-toggle.table-nest-toggle-global:after{display:none!important}.table-nest-collapsed .table-nest-toggle.table-nest-toggle-global:before{font-size:16px!important;content:"\e6f1"!important}.disable-empty-nest-row .is-nest-child .table-nest-icon:before,.disable-empty-nest-row .no-nest .table-nest-icon:before{position:relative;top:-1px;width:6px;min-width:6px;height:6px;content:' ';background-color:#cbd0db;border-radius:1px}.table-nest-child-hover>td:first-child,.table-nest-hover>td:first-child{-webkit-box-shadow:inset 3px 0 0 #cbd0db;box-shadow:inset 3px 0 0 #cbd0db}.article-content{overflow:auto}.article-content img{margin-top:0}.article-content table{margin:10px 0}.article-content table td,.article-content table th{border:1px solid #cbd0db}.article-content table th{background:#eee}.article-content a{color:#0c64eb}.article-content a:focus,.article-content a:hover{color:#16a8f8}.article-content,.article>.content{word-wrap:break-word}.detail{padding:10px 0;margin:0 10px}.detail+.detail{padding-top:25px;border-top:1px solid #eee}.detail-title{font-size:14px;font-weight:700;line-height:20px}.detail-title>.pull-right{position:relative;top:-8px}h2.detail-title{margin:0;font-size:15px;font-weight:700}h2.detail-title .label,h2.detail-title .label-id{position:relative;top:-1px}.detail-content{padding:0;margin-top:10px}.detail-content em{color:#3c4353}.detail-content .list-unstyled>li+li{margin-top:5px}.side-col .detail-content{padding-left:0}details.detail{padding:10px 0}details.detail summary{position:relative;cursor:pointer;outline:0}details.detail summary::-webkit-details-marker{display:none}details.detail summary:after{position:absolute;top:0;right:0;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;text-transform:none;content:"\e316";opacity:.4;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}details.detail[open] summary:after{content:"\e313"}.files-list{padding-left:0;list-style:none}.files-list>li>a{display:block;line-height:24px}.files-list>li>a>.icon{display:inline-block;margin-right:5px;opacity:.7}.files-list>li>a:hover{color:#0c64eb}.files-list>li>.right-icon{opacity:0;-webkit-transition:opacity .2s;-o-transition:opacity .2s;transition:opacity .2s}.files-list>li:hover>.right-icon{opacity:1}.histories-list{padding-left:15px;margin-bottom:0}.histories-list>li{position:relative}.histories-list>li+li{margin-top:5px}.histories-list>li strong{color:#3c4353}.histories-list .comment,.histories-list .show-form .comment-edit-form{padding:5px 5px 5px 10px;margin:5px 0 0;background-color:rgba(0,0,0,.025);border:1px solid #eee}.histories-list .btn-edit-comment{position:absolute;top:28px;right:2px}.histories-list .comment-edit-form,.histories-list .show-form .btn-edit-comment,.histories-list .show-form .comment{display:none}.histories-list .show-form .comment-edit-form{display:block;padding:10px;border:1px solid #eee}.histories .btn-mini{width:16px;min-width:16px;height:16px;overflow:hidden;line-height:16px;color:#cbd0db;vertical-align:-8%;border-radius:1px}.histories .btn-mini:focus,.histories .btn-mini:hover{color:#0c64eb;border-color:#0c64eb}.histories .show-changes .btn-expand>.icon:before{content:"\e926"}.histories .btn-strip{display:none}.histories .show-changes .btn-strip{display:inline-block}.history-changes{display:none;padding:5px;margin-bottom:-5px;margin-left:5px;font-size:12px;line-height:20px}.history-changes blockquote{padding:5px 5px 5px 10px;margin:5px 0 0;font-size:12px;background-color:rgba(0,0,0,.05);border-left:3px solid #eee}.history-changes blockquote.original{display:none}.show-changes .history-changes,.show-original .history-changes blockquote.original{display:block}.show-original .history-changes blockquote.textdiff{display:none}.syntaxhighlighter{overflow:auto}.list-group{overflow-y:auto}.list-group>a{display:block;padding:2px 10px 2px 5px;overflow:hidden;line-height:20px;text-overflow:ellipsis;white-space:nowrap;border-radius:4px}.list-group>a+a{margin-top:5px}.list-group>a>.icon{display:inline-block;margin-right:3px;opacity:.5}.list-group>a.selected{color:#e9f2fb;background-color:#0c64eb}.list-group>a.active{color:#0c64eb;background-color:#e9f2fb}.list-group>a.active:hover,.list-group>a:hover{color:#fff;background-color:#0c64eb}.list-group>.heading{padding:2px 5px;line-height:20px;color:#838a9d}.list-group>a+.heading{margin-top:4px}.dropup .search-box-sink{padding-top:5px;padding-bottom:45px}.dropup .search-box-sink .search-box{position:absolute;right:10px;bottom:10px;left:10px;margin:0}.dropup .search-box-sink .search-box+.list-group{height:auto;max-height:171px}.search-list{min-width:200px;max-width:300px;padding:0}.search-list .search-box{float:none;width:auto;margin:10px}.search-list .search-box .icon-search{opacity:.5}.search-list .list-group{max-height:248px;padding:5px 10px;margin:5px 0}.dropup .search-list .search-box+.list-group{height:171px;padding-top:0}.search-list .search-input{height:30px}.search-list .input-control-icon-right{height:28px;line-height:28px}.search-list .list-group>a.active{color:inherit;background-color:inherit}.search-list.searchbox-focus .list-group>a.active{color:#0c64eb;background-color:#e9f2fb}.search-list .list-group>a.active:hover,.search-list.searchbox-focus .list-group>a.active:hover{color:#fff;background-color:#0c64eb}#dropMenu{width:initial;max-width:initial}#dropMenu>.search-box{width:100%;padding:10px 10px 0;margin:0}#dropMenu>.search-box .icon-search{color:#333}#dropMenu>.search-box.has-icon-right>.form-control{padding-left:26px}#dropMenu .input-control-icon-left{top:10px;left:10px}#dropMenu .input-control-icon-right{top:11px;right:11px}#dropMenu .input-control-icon-right .icon{position:relative;top:2px}#dropMenu .list-group{max-height:initial;margin:0}#dropMenu .table-row{margin:0 -10px;table-layout:auto}#dropMenu .table-col{position:relative;width:100%;min-width:250px;max-width:450px}#dropMenu .table-col .list-group{max-height:300px;padding:0 10px 5px}#dropMenu .col-left{padding-bottom:30px}#dropMenu .col-right{display:none}#dropMenu .col-footer{position:absolute;right:0;bottom:-5px;left:0;padding:8px 10px;border-top:1px solid #eee}#dropMenu .col-footer>a{opacity:.8}#dropMenu .col-footer>a:hover{opacity:1}#dropMenu.show-right-col .table-col{width:50%}#dropMenu.show-right-col .col-right{display:table-cell;border-left:1px solid #eee}#dropMenu.show-right-col .col-right>.list-group{max-height:335px;margin:0}#dropMenu.show-right-col .col-right>.list-group>a{opacity:.7}#dropMenu.show-right-col .col-right>.list-group>a:hover{opacity:1}#dropMenu.show-right-col .toggle-right-col>.icon-angle-right:before{content:"\e314"}#dropMenu.has-search-text .list-group{overflow-x:hidden}#dropMenu.has-search-text>.search-box{width:100%!important}#dropMenu.has-search-text>.list-group>.table-row{display:block}#dropMenu.has-search-text>.list-group>.table-row>.table-col{display:block;width:100%}#dropMenu.has-search-text .col-left{padding-bottom:0}#dropMenu.has-search-text .pull-right.toggle-right-col{display:none}#dropMenu.has-search-text .col-left .list-group{margin-bottom:0}#dropMenu.has-search-text .col-right .list-group{margin-bottom:0}#dropMenu.has-search-text .col-right .list-group>a{opacity:.7}#dropMenu.has-search-text .col-footer,#dropMenu.has-search-text .hide-in-search{display:none}#swapper{position:relative}#swapper #dropMenu .tree li>.selected{color:#0c64eb!important;background:#e9f2fb!important}#swapper #dropMenu .list-group>a.active:hover,#swapper #dropMenu .search-box .list-group>a.active,#swapper #dropMenu .tree li>.clickable:hover,#swapper #dropMenu.searchbox-focus .list-group>a.active:hover{color:#fff!important;background:#0c64eb!important}#swapper #dropMenu .tree{margin:0}.release-path{overflow:hidden}.release-line{display:table;width:100%;padding:0;table-layout:fixed}.release-line>li{display:table-cell;list-style:none}.release-line>li>a{position:relative;display:block}.release-line>li>a:before{position:absolute;left:0;display:block;width:13px;height:13px;content:' ';background:#fff;border:2px solid #838a9d;border-radius:50%}.release-line>li>a:after{position:absolute;left:5px;display:block;width:2px;height:30px;content:' ';background:#cbe0f6}.release-line>li>a>.icon{position:absolute;left:4px;font-size:24px}.release-line>li>a .title{display:block;font-size:14px;white-space:nowrap}.release-line>li>a .date,.release-line>li>a .info{display:block;max-height:18px;overflow:hidden;font-size:12px;color:#838a9d;text-overflow:ellipsis;white-space:nowrap}.release-line>li>a:hover:before{background-color:#e9f2fb}.release-line>li>a:hover:after{background-color:#838a9d}.release-line>li>a:hover .title{color:#0c64eb}.release-line>li>a:hover .date,.release-line>li>a:hover .info{color:#838a9d}.release-line>li:nth-child(odd){padding-top:80px;vertical-align:top}.release-line>li:nth-child(odd)>a{height:85px;padding-top:36px;border-top:5px solid #cbe0f6}.release-line>li:nth-child(odd)>a:before{top:-9px}.release-line>li:nth-child(odd)>a:after{top:6px}.release-line>li:nth-child(odd)>a>.icon{top:-26px}.release-line>li:nth-child(even){padding-bottom:80px;vertical-align:bottom}.release-line>li:nth-child(even)>a{height:85px;padding-bottom:36px;border-bottom:5px solid #cbe0f6}.release-line>li:nth-child(even)>a:before{bottom:-9px}.release-line>li:nth-child(even)>a:after{bottom:6px}.release-line>li:nth-child(even)>a>.icon{bottom:-2px}.release-line>li:last-child>a{border-color:transparent}.release-line>li.active>a:before{border-color:#0c64eb}.release-line>li+li>a>.date,.release-line>li+li>a>.info,.release-line>li+li>a>.title{position:relative;left:-36%}#footer{position:fixed;right:0;bottom:0;left:0;z-index:1010;height:40px;background:#fff;border-top:1px solid #eff1f7}#footer .breadcrumb{padding:10px 0;margin:0}#footer .breadcrumb>li{max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#footer .breadcrumb>.active,#footer .breadcrumb>li>a{color:#838a9e}#footer .breadcrumb>.active>.icon,#footer .breadcrumb>li>a>.icon{display:none}#footer .breadcrumb>.active:hover,#footer .breadcrumb>li>a:hover{color:#16a8f8}#footer .breadcrumb>li+li:before{content:'>'}#footer>.container{padding:0 20px}@media (min-width:1400px){#footer>.container{padding:0 40px}}#poweredBy{position:absolute;top:4px;right:0;padding:5px 10px}#poweredBy .icon-zentao{color:#0097fd}#poweredBy a{color:#3c4353}#poweredBy a:hover{color:#0c64eb}#poweredBy a:hover .icon-zentao{color:#0c64eb}#poweredBy a.text-important{color:#bd7b46}#poweredBy a.text-important:hover{color:#ff5d5d}#poweredBy a.text-primary{color:#0c64eb}#poweredBy a.text-primary:hover{color:#16a8f8}#poweredBy #aiux{color:#cbd0dc}#noticeBox .alert{-webkit-box-shadow:rgba(0,0,0,.15) 0 3px 10px,rgba(0,0,0,.25) 0 3px 10px;box-shadow:rgba(0,0,0,.15) 0 3px 10px,rgba(0,0,0,.25) 0 3px 10px}#heading{top:0}.header-btn{position:relative;padding:8px 0}.header-btn .btn{position:relative;height:34px;padding:1px 6px;margin:0;overflow:visible;font-size:13px;font-weight:400;line-height:28px;color:#fff;background-color:transparent;border-color:transparent!important;border-right:none;-webkit-transition:none;-o-transition:none;transition:none}.header-btn .btn>.caret{margin-left:0;border-width:4px}.header-btn .btn>.text{display:inline-block;max-width:150px;overflow:hidden;text-overflow:ellipsis;vertical-align:middle}.header-btn .btn:hover{-webkit-box-shadow:none;box-shadow:none}.header-btn .btn:hover,.header-btn.active .btn{color:#fff;background:rgba(0,0,0,.15)}.header-btn .btn:hover>.caret,.header-btn.active .btn>.caret{opacity:1}.header-btn+.header-btn{margin-left:10px}.header-btn+.header-btn:before{position:absolute;top:16px;left:-13px;display:block;font-family:ZentaoIcon;font-size:14px;font-size:16px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;text-transform:none;content:"\e315";opacity:.6;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.header-btn .dropdown-menu{margin-top:-10px}#toolbar{top:0;height:50px}#userNav>li{margin-right:0}#userNav>li>a{padding:10px 5px}#userNav>li>a>.icon{font-size:30px;filter:brightness(1.2) hue-rotate(30deg);opacity:.9;-webkit-filter:brightness(1.2) hue-rotate(30deg)}#userNav>li:hover>a{background-color:rgba(0,0,0,.1)}#userNav .dropdown-menu>li>a{position:relative;padding-left:24px}#userNav .dropdown-menu>li>a>.icon{top:1px;left:0}#userNav .dropdown-menu>li.user-profile-item>a{padding-left:45px} \ No newline at end of file +*/.chosen-container{position:relative;display:block;font-size:13px;vertical-align:middle;zoom:1;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.chosen-container .chosen-drop{position:absolute;top:100%;z-index:1010;display:none;width:100%;background:#fff;border:1px solid #b6bdcc;border:1px solid rgba(0,0,0,.15);border-top:0;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.chosen-container .chosen-drop.chosen-drop-size-limited{border-top:1px solid rgba(0,0,0,.15)}.chosen-container .chosen-drop.chosen-auto-max-width{min-width:100%;border-top:1px solid rgba(0,0,0,.15);opacity:0}.chosen-container .chosen-drop.chosen-auto-max-width>.chosen-results>li{display:inline-block;white-space:nowrap}.chosen-container .chosen-drop.chosen-auto-max-width.in{opacity:1}.chosen-container .chosen-drop.chosen-auto-max-width.in>.chosen-results>li{display:block;white-space:normal}.chosen-container .chosen-drop.chosen-no-wrap>.chosen-results>li{overflow:hidden;text-overflow:ellipsis;white-space:nowrap!important}.chosen-container.chosen-with-drop .chosen-drop{display:block}.chosen-container a{cursor:pointer}.chosen-container.chosen-up .chosen-drop{top:inherit;bottom:100%;margin-top:auto;margin-bottom:-1px;border-radius:2px 2px 0 0;-webkit-box-shadow:0 -3px 5px rgba(0,0,0,.175);box-shadow:0 -3px 5px rgba(0,0,0,.175)}.chosen-container.chosen-highlight-selected .result-selected{color:#0c64eb;background:#e9f2fb}.chosen-container-single .chosen-single{display:block;width:100%;height:32px;padding:5px 8px;overflow:hidden;line-height:1.42857143;color:#222;text-decoration:none;white-space:nowrap;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #dcdcdc;border-radius:2px;-webkit-box-shadow:none;box-shadow:none;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s,-webkit-box-shadow ease-in-out .15s}.chosen-container-single .chosen-default{color:#838a9d}.chosen-container-single .chosen-single>span{display:block;margin-right:26px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.chosen-container-single .chosen-single-with-deselect span{margin-right:38px}.chosen-container-single .chosen-single abbr{position:absolute;top:5px;right:24px;display:block;width:20px;height:20px;font-family:sans-serif;font-size:18px;font-weight:700;line-height:18px;color:#000;text-align:center;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.chosen-container-single .chosen-single abbr:before{display:block;content:'×'}.chosen-container-single .chosen-single abbr:focus,.chosen-container-single .chosen-single abbr:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}.chosen-container-single .chosen-single div{position:absolute;top:0;right:0;display:block;height:100%;padding:5px 8px}.chosen-container-single .chosen-single div b{display:inline-block;width:0;height:0;margin-bottom:2px;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent;opacity:.5}.chosen-container-single .chosen-search{position:relative;z-index:1010;padding:3px 4px;margin:0;white-space:nowrap}.chosen-container-single .chosen-search input[type=text]{width:100%;height:27px;padding:2px 26px 2px 8px;margin:1px 0;font-size:12px;line-height:1.5;background-color:#fff;border:1px solid #dcdcdc;border-radius:2px;outline:0}.chosen-container-single .chosen-search input[type=text]:focus{border-color:#0c64eb}.chosen-container-single .chosen-search:before{position:absolute;top:10px;right:10px;display:block;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;color:#838a9d;text-transform:none;content:"\e928";speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.chosen-container-single .chosen-drop{margin-top:-1px;-webkit-background-clip:padding-box;background-clip:padding-box;border-radius:0 0 4px 4px}.chosen-container-single.chosen-container-single-nosearch .chosen-search{position:absolute;left:-9999px}.chosen-container .chosen-results{position:relative;max-height:240px;padding:0;margin:0;overflow-x:hidden;overflow-y:auto;-webkit-overflow-scrolling:touch}.chosen-container .chosen-results li{display:none;padding:5px 10px;margin:0;line-height:15px;list-style:none;-webkit-transition:background-color .2s cubic-bezier(.175,.885,.32,1);-o-transition:background-color .2s cubic-bezier(.175,.885,.32,1);transition:background-color .2s cubic-bezier(.175,.885,.32,1);-webkit-touch-callout:none}.chosen-container .chosen-results li.active-result{display:list-item;cursor:pointer}.chosen-container .chosen-results li.disabled-result{display:list-item;color:#ccc;cursor:default}.chosen-container .chosen-results li.highlighted{color:#fff;background-color:#0c64eb}.chosen-container .chosen-results li.no-results{display:list-item;background:#f4f4f4}.chosen-container .chosen-results li.group-result{display:list-item;font-weight:700;cursor:default}.chosen-container .chosen-results li.group-option{padding-left:15px}.chosen-container .chosen-results li em{font-style:normal;text-decoration:underline}.chosen-container-multi .chosen-choices{position:relative;width:100%;min-height:32px;min-height:30px\9;padding:0;margin:0;overflow:hidden;cursor:text;background-color:#fff;border:1px solid #dcdcdc;border-radius:2px;-webkit-box-shadow:none;box-shadow:none;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s,-webkit-box-shadow ease-in-out .15s}.chosen-container-multi .chosen-choices:after,.chosen-container-multi .chosen-choices:before{display:table;content:" "}.chosen-container-multi .chosen-choices:after{clear:both}.chosen-container-multi .chosen-choices li{display:block;float:left;padding:0 6px;margin:5px 4px;list-style:none}.chosen-container-multi .chosen-choices li.search-field{padding:0;line-height:12px;white-space:nowrap}.chosen-container-multi .chosen-choices li.search-field input[type=text]{height:20px;font-size:100%;color:#838a9d;background:0 0!important;border:0!important;border-radius:0;outline:0;-webkit-box-shadow:none;box-shadow:none}.chosen-container-multi .chosen-choices li.search-field .default{color:#999}.chosen-container-multi .chosen-choices li.search-field:before{position:absolute;right:8px;bottom:8px;display:block;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;color:#838a9d;text-transform:none;content:"\e928";opacity:0;-webkit-transition:opacity .2s cubic-bezier(.175,.885,.32,1);-o-transition:opacity .2s cubic-bezier(.175,.885,.32,1);transition:opacity .2s cubic-bezier(.175,.885,.32,1);speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.chosen-container-multi .chosen-choices li.search-choice{position:relative;padding:3px 20px 3px 5px;line-height:12px;cursor:default;background-color:#f1f1f1;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #cbd0db;border-radius:3px;-webkit-box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);-webkit-transition:all .4s cubic-bezier(.175,.885,.32,1);-o-transition:all .4s cubic-bezier(.175,.885,.32,1);transition:all .4s cubic-bezier(.175,.885,.32,1)}.chosen-container-multi .chosen-choices li.search-choice:hover{background-color:#fff;border-color:#adb5c6;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.1);box-shadow:0 1px 0 rgba(0,0,0,.1)}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close{position:absolute;top:1px;right:0;display:block;width:20px;height:18px;line-height:18px;color:#000;text-align:center;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:before{font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;text-shadow:0 1px 0 #fff;text-transform:none;content:'\d7';speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:focus,.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}.chosen-container-multi .chosen-choices li.search-choice-disabled{padding-right:5px;color:#666;background-color:#e4e4e4;border:1px solid #ccc}.chosen-container-multi .chosen-choices li.search-choice-focus{background:#d4d4d4}.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close{background-position:-42px -10px}.chosen-container-multi .chosen-results{padding:5px 0;margin:0}.chosen-container-multi .chosen-drop .result-selected{display:list-item;color:#ccc;cursor:default}.chosen-container-active .chosen-single{border-color:#0c64eb;-webkit-box-shadow:none,0 0 8px rgba(12,100,235,.6);box-shadow:none,0 0 8px rgba(12,100,235,.6)}.chosen-container-active.chosen-with-drop .chosen-single{border:1px solid #b6bdcc;border:1px solid rgba(0,0,0,.15);border-bottom-right-radius:0!important;border-bottom-left-radius:0!important;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.chosen-container-active.chosen-with-drop .chosen-single div{background:0 0;border-left:none}.chosen-container-active.chosen-with-drop .chosen-single div b{content:"";border-top:0 dotted;border-bottom:4px solid}.chosen-container-active.chosen-with-drop.chosen-up .chosen-single{border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:2px;border-bottom-left-radius:2px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.chosen-container-active .chosen-choices{border-color:#0c64eb;-webkit-box-shadow:none,0 0 8px rgba(12,100,235,.6);box-shadow:none,0 0 8px rgba(12,100,235,.6)}.chosen-container-active .chosen-choices li.search-field input[type=text]{color:#111!important}.chosen-container-active .chosen-choices li.search-field:before{opacity:1}.chosen-disabled{cursor:default;opacity:.5!important}.chosen-disabled .chosen-single{cursor:default}.chosen-disabled .chosen-choices .search-choice .search-choice-close{cursor:default}.chosen-compact.chosen-container-single .chosen-single>.chosen-search{left:0;display:none;padding:3px 4px;opacity:0}.chosen-compact.chosen-container-single .chosen-single>.chosen-search>input{height:25px;padding:2px 26px 2px 4px;font-size:inherit}.chosen-compact.chosen-container-single .chosen-single>.chosen-search:before{top:9px}.chosen-compact.chosen-with-search.chosen-with-drop .chosen-single>.chosen-search{display:block;opacity:1}select.chosen[multiple]{height:32px;overflow:hidden}select.chosen[multiple] option{visibility:hidden}.picker{min-height:32px;background-color:#eee}.picker:not(.picker-ready)>*{display:none}.picker-selections{position:relative;min-height:32px;color:#222;background-color:#fff;border:1px solid #dcdcdc;border-radius:2px;-webkit-box-shadow:none;box-shadow:none}.picker-focus .picker-selections{border-color:#0c64eb;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(12,100,235,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(12,100,235,.6)}.disabled .picker-selections{cursor:not-allowed;background-color:#f5f5f5}.picker-multi .picker-selections{padding:3px}.picker-multi.picker-focus .picker-selections:before{position:absolute;right:0;bottom:8px;display:block;width:24px;height:14px;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;text-align:center;text-transform:none;content:"\e928";opacity:.4;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.picker-multi.picker-focus.picker-loading .picker-selections::before{display:inline-block;content:"\e982";-webkit-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}.picker-multi .picker-selection{position:relative;display:inline-block;padding:0 20px 0 5px;margin:2px;line-height:18px;background-color:#f1f1f1;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #cbd0db;border-radius:3px;-webkit-box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05);box-shadow:0 0 2px #fff inset,0 1px 0 rgba(0,0,0,.05)}.picker-selection-single{max-width:100%;padding:5px 20px 5px 8px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.picker-focus .picker-selection-single .picker-selection-text{display:none}.picker-selection-single:after{position:absolute;top:7px;right:0;display:block;width:24px;height:14px;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;text-align:center;text-transform:none;content:"\f0d7";opacity:.4;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.picker-focus .picker-selection-single::after{content:"\e928"}.picker-focus.picker-loading .picker-selection-single::after{display:inline-block;content:"\e982";-webkit-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}.picker-selection-remove{position:absolute;top:0;right:0;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:18px;height:18px;text-align:center;cursor:pointer;opacity:.2;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center}.picker-selection-remove:before{font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;text-shadow:0 1px 0 #fff;text-transform:none;content:'\d7';speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.picker-selection-remove:hover{opacity:.5}.picker-single .picker-selection-remove{top:5px;right:20px;z-index:1}.picker-no-value .picker-selection-remove,.picker-single.picker-focus .picker-selection-remove{display:none}.picker-multi.picker-sortable .picker-selection-text{cursor:move}.picker-search{color:transparent;background:0 0;border:none}.picker-search:focus{color:inherit;outline:0}.disabled .picker-search{cursor:not-allowed}.picker-single .picker-search{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;width:100%;padding:5px 8px}.picker-multi .picker-search{display:inline-block;width:10px;min-width:10px;max-width:100%;padding:0 2px;margin:2px 0}.picker-placeholder{position:absolute;top:5px;right:20px;left:8px;z-index:0;display:none;overflow:hidden;color:#838a9d;text-overflow:ellipsis;white-space:nowrap}.picker-no-value.picker-focus .picker-placeholder{display:none}.picker-input-empty.picker-focus.picker-no-value .picker-placeholder,.picker-no-value .picker-placeholder{display:block}.picker-drop-menu{position:fixed;z-index:1200;display:none;min-width:100px;background-color:#fff;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.12),0 1px 3px rgba(0,0,0,.1);box-shadow:0 6px 12px rgba(0,0,0,.12),0 1px 3px rgba(0,0,0,.1);opacity:0}.picker-drop-menu.picker-drop-show{display:block}.picker-option-list{padding:5px 0;margin:0;overflow-y:auto}.picker-no-options .picker-option-list{display:none}.picker-option{display:block;min-height:30px;padding:5px 10px;overflow:hidden;clear:both;font-weight:400;line-height:1.42857143;color:#3c4353;text-overflow:ellipsis;white-space:nowrap;-webkit-transition:none;-o-transition:none;transition:none}.picker-single .picker-option.picker-option-selected{color:#0c64eb;background:#e9f2fb}.picker-option:focus,.picker-option:hover{text-decoration:none}.picker-option.picker-option-active,.picker-single .picker-option.picker-option-selected.picker-option-active{color:#fff;background-color:#0c64eb}.picker-multi .picker-option.picker-option-selected,.picker-multi .picker-option.picker-option-selected.picker-option-active{color:#ccc;cursor:not-allowed;background-color:#fff}.picker-option.disabled{cursor:not-allowed!important}.picker-option-text-matched{position:relative;color:#0c64eb}.picker-option-text-matched:before{position:absolute;right:0;bottom:-4px;left:0;display:block;height:2px;content:' ';background-color:#0c64eb;border-radius:2px;opacity:.5}.picker-option-active .picker-option-text-matched,.picker-option:hover .picker-option-text-matched{color:#fff}.picker-option-active .picker-option-text-matched:before,.picker-option:hover .picker-option-text-matched:before{background-color:#fff}.picker-message{display:none;height:22px;padding:2px 5px;overflow:hidden;font-size:12px;color:#838a9d;text-overflow:ellipsis;white-space:nowrap;background-color:#f1f1f1}.picker-has-message .picker-message{display:block}.picker-message[data-type=danger]{color:#ff5d5d}.picker-actions{padding:5px;border-top:1px solid #eee}.picker-no-actions .picker-actions{display:none}.picker-actions .btn{padding:2px 4px}.picker-actions .btn[disabled]{background-color:transparent;filter:grayscale(1);-webkit-filter:grayscale(1)}.picker-actions .btn+.btn{margin-left:4px}.picker-checkable .picker-option{position:relative;padding-left:32px;color:inherit!important;cursor:pointer!important}.picker-checkable .picker-option>.checkbox-primary{position:absolute;top:4px;left:10px}.picker-checkable .picker-option.picker-option-active{background-color:rgba(0,0,0,.05)!important}.picker-checkable .picker-option:hover{background-color:rgba(0,0,0,.075)!important}.picker-checkable .picker-option.picker-option-selected{background-color:#e9f2fb!important}.picker-checkable .picker-option-active .picker-option-text-matched,.picker-checkable .picker-option:hover .picker-option-text-matched{color:#0c64eb!important}.picker-checkable .picker-option-active .picker-option-text-matched:before,.picker-checkable .picker-option:hover .picker-option-text-matched:before{background:#0c64eb!important}:root{--color-primary:#0c64eb;--color-secondary:#16a8f8;--color-pale:#e9f2fb;--color-fore:#3c4353;--color-back:#fff;--color-red:#ff5d5d;--color-yellow:#ff9800;--color-green:#00da88;--color-blue:#2196f3;--color-purple:#8666b8;--color-brown:#bd7b46;--color-danger:#ff5d5d;--color-warning:#ff9800;--color-success:#00da88;--color-info:#2196f3;--color-special:#8666b8;--color-important:#bd7b46;--color-green-pale:#e8f5e9;--color-yellow-pale:#fff3e0;--color-red-pale:#ffebee;--color-blue-pale:#e3f2fd;--color-brown-pale:#efebe9;--color-purple-pale:#f3e5f5;--link-color:#3c4353;--link-hover-color:#0c64eb;--color-gray-darker:#222;--color-gray-dark:#3c495c;--color-gray:#838a9d;--color-gray-light:#cbd0db;--color-gray-lighter:#eee;--color-gray-pale:#f1f1f1;--border-radius:4px;--border-radius-lg:6px;--border-radius-sm:3px;--bg-gradient:linear-gradient(-90deg, #0a48d1 0%, #1183fb 100%)}.container,.container-fixed,.container-fluid{position:relative}.container{max-width:1800px!important}body{background-color:#efefef}body.article-content,body.body-modal{background:0 0}body.body-modal{padding:0}@media screen and (min-width:1920px){body{font-size:14px}}a:active,a:focus,button:active,button:focus{outline:0!important}.strong{font-weight:700}.font-normal{font-weight:400!important}.text-middle{vertical-align:middle!important}.text-bottom{vertical-align:bottom!important}.text-top{vertical-align:top!important}.inline-block{display:inline-block!important}.layer{border-radius:4px;-webkit-box-shadow:0 0 20px 0 #bdc9d8;box-shadow:0 0 20px 0 #bdc9d8}.space{margin-bottom:20px}.space-lg{margin-bottom:30px}.space-sm{margin-bottom:10px}.muted{opacity:.5}.text-muted em{color:#3c4353}.no-animate{-webkit-transition:none!important;-o-transition:none!important;transition:none!important}.template{display:none!important}.text-left{text-align:left!important}.text-yellow.icon-folder{color:#ffe066}.table-row{display:table;width:100%;table-layout:fixed}.table-col,.table-row>.col,.table-row>[class*=col-],.table-row>[class*="-col"]{display:table-cell;float:none;vertical-align:top}.side-col{width:200px;padding-right:20px}.side-col.col-4{width:33.3333333%}.col-lg{width:260px}.col-xl{width:320px}.col-sm{width:150px}.col-xs{width:100px}.main-col+.side-col{padding-right:0;padding-left:20px}.row-grid>[class*=col-],.row-grid>[class*="-col"]{padding-top:6px;padding-bottom:6px}hr.space{margin:10px 0;border:none}hr.space-sm{margin:5px 0;border:none}.text-secondary{color:#16a8f8}a.text-primary{color:#0c64eb}.nav-primary>li>a{min-width:100px;padding:5px 8px;color:#838a9d;border-color:#e7f1fc}.nav-primary>li.active>a{color:#0c64eb;background-color:#e7f1fc;border-color:#e7f1fc}.nav-primary>li.active>a:hover{color:#0c64eb;background-color:#c3dcf7;border-color:#c3dcf7}.end-marker{margin-bottom:20px;color:#cbd0db;text-align:center}@-webkit-keyframes highlight{0%{background:#fff;outline:1px solid transparent}100%{background:#fff0d5;outline:2px solid #ffdcbc}}@-o-keyframes highlight{0%{background:#fff;outline:1px solid transparent}100%{background:#fff0d5;outline:2px solid #ffdcbc}}@keyframes highlight{0%{background:#fff;outline:1px solid transparent}100%{background:#fff0d5;outline:2px solid #ffdcbc}}.highlight{-webkit-animation:highlight .5s linear 0s 2 alternate;-o-animation:highlight .5s linear 0s 2 alternate;animation:highlight .5s linear 0s 2 alternate}.progress.inline-block{width:100px;margin:0}.w-p5{width:5%!important}.w-p10{width:10%!important}.w-p15{width:15%!important}.w-p20{width:20%!important}.w-p25{width:25%!important}.w-p30{width:30%!important}.w-p35{width:35%!important}.w-p40{width:40%!important}.w-p45{width:45%!important}.w-p50{width:50%!important}.w-p55{width:55%!important}.w-p60{width:60%!important}.w-p65{width:65%!important}.w-p70{width:70%!important}.w-p75{width:75%!important}.w-p80{width:80%!important}.w-p85{width:85%!important}.w-p90{width:90%!important}.w-p94{width:94%!important}.w-p95{width:95%!important}.w-p98{width:98%!important}.w-p99{width:99%!important}.w-p100{width:100%!important}.w-auto{width:auto!important}.w-10px{width:10px!important}.w-20px{width:20px!important}.w-30px{width:30px!important}.w-35px{width:35px!important}.w-40px{width:40px!important}.w-45px{width:45px!important}.w-50px{width:50px!important}.w-60px{width:60px!important}.w-70px{width:70px!important}.w-80px{width:80px!important}.w-90px{width:90px!important}.w-100px{width:100px!important}.w-110px{width:110px!important}.w-120px{width:120px!important}.w-130px{width:130px!important}.w-140px{width:140px!important}.w-150px{width:150px!important}.w-160px{width:160px!important}.w-180px{width:180px!important}.w-200px{width:200px!important}.w-230px{width:230px!important}.w-250px{width:250px!important}.w-300px{width:300px!important}.w-400px{width:400px!important}.w-500px{width:500px!important}.w-600px{width:600px!important}.w-700px{width:700px!important}.w-800px{width:800px!important}.w-900px{width:900px!important}.mw-200px{max-width:200px!important}.mw-300px{max-width:300px!important}.mw-400px{max-width:400px!important}.mw-500px{max-width:500px!important}.mw-600px{max-width:600px!important}.mw-700px{max-width:700px!important}.mw-800px{max-width:800px!important}.mw-900px{max-width:900px!important}.mw-1400px{max-width:1400px!important}.w-id{width:70px!important}.w-pri{width:40px!important}.w-severity{width:50px!important}.w-hour{width:57px!important}.w-date{width:90px!important}.w-status{width:60px!important}.w-resolution,.w-type,.w-user{width:80px!important}.w-p15-f{width:15%!important;min-width:120px!important}.w-p25-f{width:25%!important;min-width:200px!important}.w-p35-f{width:35%!important;min-width:300px!important}.w-p45-f{width:45%!important;min-width:400px!important}.h-5px{height:5px!important}.h-10px{height:10px!important}.h-20px{height:20px!important}.h-30px{height:30px!important}.h-35px{height:35px!important}.h-40px{height:40px!important}.h-45px{height:45px!important}.h-50px{height:50px!important}.h-60px{height:60px!important}.h-70px{height:70px!important}.h-80px{height:80px!important}.h-100px{height:100px!important}.h-120px{height:120px!important}.h-130px{height:130px!important}.h-140px{height:140px!important}.h-150px{height:150px!important}.h-200px{height:200px!important}.pd-0{padding:0!important}.mg-0{margin:0!important}.mgb-20{margin-bottom:20px!important}.mgb-10{margin-bottom:10px!important}.pdb-20{padding-bottom:20px!important}.pdt-20{padding-top:20px!important}.br-0{border-radius:0!important}.bd-0,.bd-none,.borderless{border:none!important}.bg-none{background:0 0!important}.red{color:#ff5d5d!important}.icon-pro-version{font-size:14px!important}.icon-pro-version:before{position:relative;top:-1px;font-size:14px;color:#ff5d5d;content:"\e92b"}.bg-primary{color:#fff;background:-webkit-gradient(linear,right top,left top,from(#0a48d1),to(#1183fb));background:-webkit-linear-gradient(right,#0a48d1 0,#1183fb 100%);background:-o-linear-gradient(right,#0a48d1 0,#1183fb 100%);background:linear-gradient(-90deg,#0a48d1 0,#1183fb 100%);border-top-color:#0c64eb}.bg-primary-pure{color:#fff;background-color:#0c64eb}.bg-primary-pale{color:#0c64eb;background-color:#e9f2fb}.bg-secondary{color:#fff;background:#16a8f8}.hl-tutorial{position:relative!important;z-index:1010!important;-webkit-box-shadow:0 0 0 0 #000!important;box-shadow:0 0 0 0 #000!important;-webkit-transition:-webkit-box-shadow 1s!important;-o-transition:box-shadow 1s!important;transition:-webkit-box-shadow 1s!important;transition:box-shadow 1s!important;transition:box-shadow 1s,-webkit-box-shadow 1s!important}.hl-tutorial.hl-in{-webkit-box-shadow:0 0 20px 0 #ffff8d,0 0 0 2px #ffd180,0 0 0 3000px rgba(0,0,0,.2)!important;box-shadow:0 0 20px 0 #ffff8d,0 0 0 2px #ffd180,0 0 0 3000px rgba(0,0,0,.2)!important}.btn.tooltip-tutorial,.hl-tutorial.hl-in:hover{position:relative!important;z-index:1010!important;-webkit-box-shadow:0 0 30px 0 #ffff8d,0 0 0 5px #ffd180,0 0 0 3000px rgba(0,0,0,.3)!important;box-shadow:0 0 30px 0 #ffff8d,0 0 0 5px #ffd180,0 0 0 3000px rgba(0,0,0,.3)!important}.tooltip-max .tooltip-inner{max-width:1000px;padding:8px 10px}.transition-all *{-webkit-transition:all .2s!important;-o-transition:all .2s!important;transition:all .2s!important}.scroll-x{overflow-x:auto!important}.scroll-y{overflow-y:auto!important}.divider+.divider{display:none}.ie *{-webkit-transition:none!important;-o-transition:none!important;transition:none!important}@font-face{font-family:Oswald;font-weight:400;src:url(../fonts/Oswald-Regular.ttf)}@font-face{font-family:Oswald;font-weight:500;src:url(../fonts/Oswald-Medium.ttf)}@font-face{font-family:Oswald;font-weight:300;src:url(../fonts/Oswald-Light.ttf)}.num{font-family:Oswald;font-weight:400}@font-face{font-family:ZentaoIcon;font-style:normal;font-weight:400;src:url(../fonts/ZentaoIcon.eot?v=1.35);src:url(../fonts/ZentaoIcon.eot?#iefix&v=1.35) format('embedded-opentype'),url(../fonts/ZentaoIcon.woff?v=1.35) format('woff'),url(../fonts/ZentaoIcon.ttf?v=1.35) format('truetype'),url(../fonts/ZentaoIcon.svg#regular?v=1.35) format('svg')}.icon,[class*=" icon-"],[class^=icon-]{font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;text-transform:none;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon:before{display:inline-block;min-width:14px;text-align:center}a .icon,a [class*=" icon-"],a [class^=icon-]{display:inline}.icon-lg:before{font-size:1.33333333em;vertical-align:-10%}.icon-2x{font-size:28px}.icon-3x{font-size:42px}.icon-4x{font-size:56px}.icon-5x{font-size:70px}.icon-spin{display:inline-block;-webkit-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}a .icon-spin{display:inline-block;text-decoration:none}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0);transform:rotate(0)}100%{-o-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spin{0%{-webkit-transform:rotate(0);-o-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(359deg);-o-transform:rotate(359deg);transform:rotate(359deg)}}.icon-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.icon-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.icon-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.icon-flip-horizontal{-webkit-transform:scale(-1,1);-ms-transform:scale(-1,1);-o-transform:scale(-1,1);transform:scale(-1,1)}.icon-flip-vertical{-webkit-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)}.icon.icon-flip-horizontal,.icon.icon-flip-vertical,.icon.icon-rotate-180,.icon.icon-rotate-270,.icon.icon-rotate-90{display:inline-block}.icon-zentao:before{content:"\e901"}.icon-zentao-alt:before{content:"\e900"}.icon-help:before{content:"\e968"}.icon-import:before{content:"\e904"}.icon-download:before{content:"\e904"}.icon-export:before{content:"\e905"}.icon-lightbulb:before{content:"\e91c"}.icon-close:before{content:"\e936"}.icon-check:before{content:"\e5ca"}.icon-plus:before{content:"\e925"}.icon-minus:before{content:"\e926"}.icon-expand-alt:before{content:"\e6f1"}.icon-collapse-alt:before{content:"\e6f2"}.icon-fullscreen:before{content:"\e96b"}.icon-star-empty:before{content:"\e94a"}.icon-star:before{content:"\e94b"}.icon-exclamation-sign:before{content:"\e930"}.icon-info-sign:before{content:"\e9d5"}.icon-flag:before{content:"\e937"}.icon-check-circle:before{content:"\e92f"}.icon-check-sign:before{content:"\e938"}.icon-chart-pie:before{content:"\e95b"}.icon-history:before{content:"\e95f"}.icon-pencil:before{content:"\e254"}.icon-search:before{content:"\e928"}.icon-restart:before{content:"\e95e"}.icon-cog:before{content:"\e93b"}.icon-chart-line:before{content:"\e95c"}.icon-chart-bar:before{content:"\e95d"}.icon-bar-chart:before{content:"\e95d"}.icon-exchange:before{content:"\e927"}.icon-severity:before{content:"\e973"}.icon-book:before{content:"\f02d"}.icon-treemap-alt:before{content:"\e971"}.icon-severity-solid:before{content:"\e902"}.icon-chat-line:before{content:"\e998"}.icon-stack:before{content:"\e943"}.icon-cube:before{content:"\e967"}.icon-minus-sign:before{content:"\e939"}.icon-bars-sign:before{content:"\e93a"}.icon-chat:before{content:"\e940"}.icon-message:before{content:"\e940"}.icon-more:before{content:"\e744"}.icon-certificate:before{content:"\f0a3"}.icon-bell:before{content:"\e7f5"}.icon-columns:before{content:"\f0db"}.icon-envelope-o:before{content:"\e92a"}.icon-unfold-all:before{content:"\e931"}.icon-fold-all:before{content:"\e932"}.icon-bars:before{content:"\e948"}.icon-cards-view:before{content:"\e949"}.icon-ellipsis-v:before{content:"\e5d4"}.icon-spinner-indicator:before{content:"\e982"}.icon-up-circle:before{content:"\e92b"}.icon-right-circle:before{content:"\e92c"}.icon-down-circle:before{content:"\e92d"}.icon-left-circle:before{content:"\e92e"}.icon-angle-double-right:before{content:"\f101"}.icon-angle-down:before{content:"\e313"}.icon-angle-left:before{content:"\e314"}.icon-angle-right:before{content:"\e315"}.icon-angle-top:before{content:"\e316"}.icon-first-page:before{content:"\e5dc"}.icon-last-page:before{content:"\e5dd"}.icon-caret-down:before{content:"\f0d7"}.icon-caret-up:before{content:"\f0d8"}.icon-caret-left:before{content:"\f0d9"}.icon-caret-right:before{content:"\f0da"}.icon-sort:before{content:"\f0dc"}.icon-sort-down:before{content:"\f0dd"}.icon-sort-up:before{content:"\f0de"}.icon-arrow-up:before{content:"\e923"}.icon-arrow-down:before{content:"\e924"}.icon-arrow-left:before{content:"\e952"}.icon-arrow-right:before{content:"\e93e"}.icon-chevron-left:before{content:"\e934"}.icon-chevron-right:before{content:"\e935"}.icon-chevron-double-up:before{content:"\e959"}.icon-chevron-double-down:before{content:"\e95a"}.icon-folder-account:before{content:"\e942"}.icon-folder-move:before{content:"\e960"}.icon-folder-plus:before{content:"\e961"}.icon-folder-upload:before{content:"\e962"}.icon-folder-star:before{content:"\e963"}.icon-folder-edit:before{content:"\e964"}.icon-folder-download:before{content:"\e965"}.icon-folder-outline:before{content:"\e966"}.icon-folder:before{content:"\e944"}.icon-folder-o:before{content:"\e945"}.icon-folder-open-o:before{content:"\e946"}.icon-folder-open:before{content:"\e947"}.icon-color:before{content:"\e93c"}.icon-paper-clip:before{content:"\e93d"}.icon-text:before{content:"\e929"}.icon-share:before{content:"\f064"}.icon-format-list-bulleted:before{content:"\e9a8"}.icon-format-bold:before{content:"\e953"}.icon-format-header-pound:before{content:"\e954"}.icon-format-italic:before{content:"\e955"}.icon-format-list-numbers:before{content:"\e969"}.icon-format-quote-close:before{content:"\e96a"}.icon-image:before{content:"\e96c"}.icon-table-large:before{content:"\e96d"}.icon-aiux:before{content:"\e99e"}.icon-qc:before{content:"\e986"}.icon-qc-q:before{content:"\e985"}.icon-qc-c:before{content:"\e987"}.icon-sonarqube:before{content:"\e9ba"}.icon-college:before{content:"\e9c8"}.icon-ztool:before{content:"\e9c1"}.icon-contacts:before{content:"\e9c3"}.icon-chats:before{content:"\e9c4"}.icon-menu-my:before{content:"\e97a"}.icon-home:before{content:"\e97a"}.icon-program:before{content:"\e9aa"}.icon-lightbulb-alt:before{content:"\e98f"}.icon-product:before{content:"\e98f"}.icon-rocket:before{content:"\e99c"}.icon-project:before{content:"\e99c"}.icon-run:before{content:"\e9a9"}.icon-test:before{content:"\e956"}.icon-infinite:before{content:"\e9a3"}.icon-devops:before{content:"\e9a3"}.icon-ops:before{content:"\e903"}.icon-doc:before{content:"\e99b"}.icon-menu-doc:before{content:"\e99b"}.icon-statistic:before{content:"\e999"}.icon-menu-backend:before{content:"\e993"}.icon-assets:before{content:"\e9ae"}.icon-diamond:before{content:"\e9ae"}.icon-feedback:before{content:"\e991"}.icon-flow:before{content:"\e994"}.icon-oa:before{content:"\e9a1"}.icon-more-circle:before{content:"\e988"}.icon-controls:before{content:"\e995"}.icon-account:before{content:"\e992"}.icon-about:before{content:"\e996"}.icon-info:before{content:"\e996"}.icon-cog-outline:before{content:"\e997"}.icon-backend:before{content:"\e997"}.icon-exit:before{content:"\e99a"}.icon-theme:before{content:"\e9a0"}.icon-globe:before{content:"\f0ac"}.icon-lang:before{content:"\f0ac"}.icon-blame:before{content:"\e9e0"}.icon-draft-edit:before{content:"\e9dd"}.icon-sub-review:before{content:"\e9df"}.icon-sub-review-user:before{content:"\e9db"}.icon-ztf:before{content:"\e9dc"}.icon-save:before{content:"\e9d8"}.icon-list-box:before{content:"\e9b4"}.icon-usecase:before{content:"\e99d"}.icon-code:before{content:"\e990"}.icon-summary:before{content:"\e9ad"}.icon-more-alt:before{content:"\e9a7"}.icon-customer:before{content:"\e9d9"}.icon-tree:before{content:"\e9c9"}.icon-list:before{content:"\e9cb"}.icon-gantt:before{content:"\e9cc"}.icon-group-view:before{content:"\e9cd"}.icon-inherit-space:before{content:"\e9c2"}.icon-card-archive:before{content:"\e9b8"}.icon-col-archive:before{content:"\e9b9"}.icon-col-add-right:before{content:"\e9bb"}.icon-col-add-left:before{content:"\e9bc"}.icon-col-split:before{content:"\e9bd"}.icon-waterfall:before{content:"\e9a4"}.icon-manual:before{content:"\e98d"}.icon-kanban:before{content:"\e983"}.icon-lane:before{content:"\e9b1"}.icon-back:before{content:"\e9d3"}.icon-back-circle:before{content:"\e9da"}.icon-shield:before{content:"\e9ca"}.icon-meh:before{content:"\e9ce"}.icon-frown:before{content:"\e9cf"}.icon-smile:before{content:"\e9d0"}.icon-unlock-solid:before{content:"\e9d1"}.icon-lock-solid:before{content:"\e9d2"}.icon-ver:before{content:"\e9c6"}.icon-publish:before{content:"\e9c7"}.icon-send:before{content:"\e9c7"}.icon-tag:before{content:"\e9be"}.icon-tag-lock:before{content:"\e9bf"}.icon-code-fork:before{content:"\f126"}.icon-branch-lock:before{content:"\e9c0"}.icon-groups:before{content:"\e9af"}.icon-thumbs-up:before{content:"\f087"}.icon-thumbs-down:before{content:"\f088"}.icon-thumbs-up-solid:before{content:"\e9d6"}.icon-thumbs-down-solid:before{content:"\e9d7"}.icon-hash:before{content:"\e9ab"}.icon-version:before{content:"\e9ab"}.icon-p-square:before{content:"\e97b"}.icon-video-play:before{content:"\e97f"}.icon-plus-solid-circle:before{content:"\e974"}.icon-minuse-solid-circle:before{content:"\e9b6"}.icon-s:before{content:"\e975"}.icon-c:before{content:"\e976"}.icon-t:before{content:"\e977"}.icon-guide:before{content:"\e978"}.icon-todo:before{content:"\e979"}.icon-side-left:before{content:"\e9b3"}.icon-side-right:before{content:"\e9b2"}.icon-fullscreen-exit:before{content:"\e972"}.icon-alert:before{content:"\e99f"}.icon-undo:before{content:"\e93f"}.icon-redo:before{content:"\e9d4"}.icon-swap:before{content:"\e9b0"}.icon-chat-solid:before{content:"\e9b5"}.icon-clock:before{content:"\e97c"}.icon-cost:before{content:"\e97d"}.icon-pencil-alt:before{content:"\e984"}.icon-size-height:before{content:"\e9c5"}.icon-file-log:before{content:"\e9de"}.icon-rich-text:before{content:"\e913"}.icon-markdown:before{content:"\e916"}.icon-excel:before{content:"\e933"}.icon-text-link:before{content:"\e94d"}.icon-ppt:before{content:"\e957"}.icon-word:before{content:"\e958"}.icon-doc-lib:before{content:"\e96f"}.icon-file:before{content:"\f016"}.icon-file-empty:before{content:"\f016"}.icon-file-text:before{content:"\f0f6"}.icon-file-alt:before{content:"\f15b"}.icon-file-text-alt:before{content:"\f15c"}.icon-file-pdf:before{content:"\f1c1"}.icon-file-word:before{content:"\f1c2"}.icon-file-excel:before{content:"\f1c3"}.icon-file-powerpoint:before{content:"\f1c4"}.icon-file-image:before{content:"\f1c5"}.icon-file-archive:before{content:"\f1c6"}.icon-file-audio:before{content:"\f1c7"}.icon-file-video:before{content:"\f1c8"}.icon-file-code:before{content:"\f1c9"}.icon-menu-collapse:before{content:"\e980"}.icon-menu-expand:before{content:"\e981"}.icon-group:before{content:"\e97e"}.icon-menu-users:before{content:"\e97e"}.icon-persons:before{content:"\e97e"}.icon-team:before{content:"\e97e"}.icon-estimate:before{content:"\e9ac"}.icon-sprint:before{content:"\e9a2"}.icon-shield-check:before{content:"\e9a5"}.icon-ok:before{content:"\e9a6"}.icon-printer:before{content:"\e906"}.icon-bullhorn:before{content:"\e910"}.icon-person:before{content:"\e941"}.icon-fields:before{content:"\e989"}.icon-trigger:before{content:"\e98a"}.icon-layout:before{content:"\e98b"}.icon-audit:before{content:"\e98c"}.icon-cancel:before{content:"\e951"}.icon-ban-circle:before{content:"\e951"}.icon-eye:before{content:"\e94e"}.icon-eye-off:before{content:"\e96e"}.icon-unlock:before{content:"\e94f"}.icon-lock:before{content:"\e950"}.icon-private:before{content:"\e950"}.icon-move:before{content:"\e94c"}.icon-hand-right:before{content:"\e907"}.icon-checked:before{content:"\e908"}.icon-off:before{content:"\e909"}.icon-start:before{content:"\e90a"}.icon-play:before{content:"\e90a"}.icon-time:before{content:"\e90b"}.icon-edit:before{content:"\e90c"}.icon-trash:before{content:"\e90d"}.icon-link:before{content:"\e90e"}.icon-unlink:before{content:"\e90f"}.icon-bug:before{content:"\e911"}.icon-list-alt:before{content:"\e912"}.icon-change:before{content:"\e970"}.icon-alter:before{content:"\e970"}.icon-glasses:before{content:"\e914"}.icon-review:before{content:"\e914"}.icon-sitemap:before{content:"\e915"}.icon-testcase:before{content:"\e915"}.icon-pluses:before{content:"\e917"}.icon-report-list:before{content:"\e918"}.icon-magic:before{content:"\e919"}.icon-active:before{content:"\e919"}.icon-treemap:before{content:"\e91a"}.icon-confirm:before{content:"\e91b"}.icon-split:before{content:"\e98e"}.icon-delay:before{content:"\e91d"}.icon-calendar:before{content:"\e91d"}.icon-pause:before{content:"\e91e"}.icon-ban:before{content:"\e91f"}.icon-plus-bold:before{content:"\e920"}.icon-copy:before{content:"\e921"}.icon-refresh:before{content:"\e922"}.icon-diff:before{content:"\e9b7"}.icon-sm:before{font-size:14px;vertical-align:10%}.icon-qc{position:relative}.icon-qc:before{width:1em;color:#7cb938;content:"\e985"}.icon-qc:after{position:absolute;top:0;left:0;width:1em;height:1em;font-family:ZentaoIcon;font-size:14px;font-size:inherit;font-style:normal;font-weight:400;font-variant:normal;line-height:1;color:#36a742;text-transform:none;content:"\e987";speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-message.has-dot{position:relative}.icon-message.has-dot::after{position:absolute;top:-3px;right:-5px;display:block;width:6px;height:6px;content:' ';background-color:#ff5d5d;border-radius:50%}.icon-project{-webkit-transform:scale(1.2);-ms-transform:scale(1.2);-o-transform:scale(1.2);transform:scale(1.2)}.icon-product{-webkit-transform:scale(1.15);-ms-transform:scale(1.15);-o-transform:scale(1.15);transform:scale(1.15)}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:13px;font-weight:400;line-height:18px;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid transparent;border-radius:4px;-webkit-transition:.4s cubic-bezier(.175,.885,.32,1);-o-transition:.4s cubic-bezier(.175,.885,.32,1);transition:.4s cubic-bezier(.175,.885,.32,1);-webkit-transition-property:background,border,outline,opacity,-webkit-box-shadow;-o-transition-property:background,border,box-shadow,outline,opacity;transition-property:background,border,outline,opacity,-webkit-box-shadow;transition-property:background,border,box-shadow,outline,opacity;transition-property:background,border,box-shadow,outline,opacity,-webkit-box-shadow}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:focus,.btn:hover{color:#3c4353;text-decoration:none}.btn:active{text-decoration:none;background-image:none;outline:0;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.1)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;filter:grayscale(1);-webkit-box-shadow:none;box-shadow:none;opacity:.5;-webkit-filter:grayscale(1)}.btn{color:#3c4353;background-color:#fff;border-color:#d6dae3}.btn.active,.btn.hover,.btn:active,.btn:focus,.btn:hover,.open .dropdown-toggle.btn{color:#3c4353;background-color:rgba(255,255,255,.8);border-color:#b8bfce}.btn.active,.btn:active,.open .dropdown-toggle.btn{background-color:#f2f2f2;background-image:none;border-color:#b8bfce}.btn.disabled,.btn.disabled.active,.btn.disabled:active,.btn.disabled:focus,.btn.disabled:hover,.btn[disabled],.btn[disabled].active,.btn[disabled]:active,.btn[disabled]:focus,.btn[disabled]:hover,fieldset[disabled] .btn,fieldset[disabled] .btn.active,fieldset[disabled] .btn:active,fieldset[disabled] .btn:focus,fieldset[disabled] .btn:hover{color:rgba(60,67,83,.3);background-color:#fff;border-color:#d6dae3}.btn-gray{color:#82899f;background-color:#f1f1f1;border-color:#f1f1f1}.btn-gray.active,.btn-gray.hover,.btn-gray:active,.btn-gray:focus,.btn-gray:hover,.open .dropdown-toggle.btn-gray{color:#82899f;background-color:rgba(241,241,241,.8);border-color:#d8d8d8}.btn-gray.active,.btn-gray:active,.open .dropdown-toggle.btn-gray{background-color:#e4e4e4;background-image:none;border-color:#d8d8d8}.btn-gray.disabled,.btn-gray.disabled.active,.btn-gray.disabled:active,.btn-gray.disabled:focus,.btn-gray.disabled:hover,.btn-gray[disabled],.btn-gray[disabled].active,.btn-gray[disabled]:active,.btn-gray[disabled]:focus,.btn-gray[disabled]:hover,fieldset[disabled] .btn-gray,fieldset[disabled] .btn-gray.active,fieldset[disabled] .btn-gray:active,fieldset[disabled] .btn-gray:focus,fieldset[disabled] .btn-gray:hover{color:rgba(130,137,159,.3);background-color:#f1f1f1;border-color:#f1f1f1}.btn-primary{color:#fff;background-color:#0c64eb;border-color:transparent}.btn-primary.active,.btn-primary.hover,.btn-primary:active,.btn-primary:focus,.btn-primary:hover,.open .dropdown-toggle.btn-primary{color:#fff;background-color:rgba(12,100,235,.8);border-color:rgba(0,0,0,0)}.btn-primary.active,.btn-primary:active,.open .dropdown-toggle.btn-primary{background-color:#0b5ad3;background-image:none;border-color:rgba(0,0,0,0)}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{color:rgba(255,255,255,.3);background-color:#0c64eb;border-color:transparent}.btn-secondary{color:#fff;background-color:#16a8f8;border-color:transparent}.btn-secondary.active,.btn-secondary.hover,.btn-secondary:active,.btn-secondary:focus,.btn-secondary:hover,.open .dropdown-toggle.btn-secondary{color:#fff;background-color:rgba(22,168,248,.8);border-color:rgba(0,0,0,0)}.btn-secondary.active,.btn-secondary:active,.open .dropdown-toggle.btn-secondary{background-color:#079ced;background-image:none;border-color:rgba(0,0,0,0)}.btn-secondary.disabled,.btn-secondary.disabled.active,.btn-secondary.disabled:active,.btn-secondary.disabled:focus,.btn-secondary.disabled:hover,.btn-secondary[disabled],.btn-secondary[disabled].active,.btn-secondary[disabled]:active,.btn-secondary[disabled]:focus,.btn-secondary[disabled]:hover,fieldset[disabled] .btn-secondary,fieldset[disabled] .btn-secondary.active,fieldset[disabled] .btn-secondary:active,fieldset[disabled] .btn-secondary:focus,fieldset[disabled] .btn-secondary:hover{color:rgba(255,255,255,.3);background-color:#16a8f8;border-color:transparent}.btn-warning{color:#fff;background-color:#ff9800;border-color:transparent}.btn-warning.active,.btn-warning.hover,.btn-warning:active,.btn-warning:focus,.btn-warning:hover,.open .dropdown-toggle.btn-warning{color:#fff;background-color:rgba(255,152,0,.8);border-color:rgba(0,0,0,0)}.btn-warning.active,.btn-warning:active,.open .dropdown-toggle.btn-warning{background-color:#e68900;background-image:none;border-color:rgba(0,0,0,0)}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{color:rgba(255,255,255,.3);background-color:#ff9800;border-color:transparent}.btn-danger{color:#fff;background-color:#ff5d5d;border-color:transparent}.btn-danger.active,.btn-danger.hover,.btn-danger:active,.btn-danger:focus,.btn-danger:hover,.open .dropdown-toggle.btn-danger{color:#fff;background-color:rgba(255,93,93,.8);border-color:rgba(0,0,0,0)}.btn-danger.active,.btn-danger:active,.open .dropdown-toggle.btn-danger{background-color:#ff4343;background-image:none;border-color:rgba(0,0,0,0)}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{color:rgba(255,255,255,.3);background-color:#ff5d5d;border-color:transparent}.btn-success{color:#fff;background-color:#00da88;border-color:transparent}.btn-success.active,.btn-success.hover,.btn-success:active,.btn-success:focus,.btn-success:hover,.open .dropdown-toggle.btn-success{color:#fff;background-color:rgba(0,218,136,.8);border-color:rgba(0,0,0,0)}.btn-success.active,.btn-success:active,.open .dropdown-toggle.btn-success{background-color:#00c178;background-image:none;border-color:rgba(0,0,0,0)}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{color:rgba(255,255,255,.3);background-color:#00da88;border-color:transparent}.btn-info{color:#0c64eb;background-color:#e9f2fb;border-color:transparent}.btn-info.active,.btn-info.hover,.btn-info:active,.btn-info:focus,.btn-info:hover,.open .dropdown-toggle.btn-info{color:#0c64eb;background-color:rgba(233,242,251,.8);border-color:rgba(0,0,0,0)}.btn-info.active,.btn-info:active,.open .dropdown-toggle.btn-info{background-color:#d3e5f7;background-image:none;border-color:rgba(0,0,0,0)}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{color:rgba(12,100,235,.3);background-color:#e9f2fb;border-color:transparent}.btn-link{padding-right:6px;padding-left:6px;font-weight:400;color:#3c495c;text-shadow:none;cursor:pointer;background:0 0;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover,.btn-link[disabled],fieldset[disabled] .btn-link{border-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link:focus,.btn-link:hover{color:#222;background:#f1f1f1;background:rgba(0,0,0,.075)}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#cbd0db;text-decoration:none}.btn-lg{padding:11px 16px;font-size:14px;line-height:18px;border-radius:4px}.btn-mini,.btn-sm{padding:3px 8px;font-size:12px;line-height:18px;border-radius:4px}.btn-mini,.btn-xs{padding:0 5px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.btn-wide{min-width:120px}.btn-limit{max-width:180px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.btn-limit>.caret{position:absolute;top:14px;right:8px}.btn-circle{border-radius:17px}.btn>.label-icon{top:3px;padding:3px;margin:-2px;background-color:rgba(0,0,0,.2);border-radius:12px}.btn>.label-icon>.icon{font-size:16px;line-height:18px}.btn>.icon+.text{margin-left:5px}.btn.btn-sm.btn-circle{border-radius:12px}.btn.btn-sm>.label-icon{top:2px;width:20px;height:20px;padding:1px;line-height:20px}.btn.btn-sm>.label-icon>.icon{position:relative;top:-1px;display:inline-block;font-size:14px;line-height:18px}.btn-icon-left{position:relative;padding-left:35px;overflow:hidden;text-align:right}.btn-icon-left>.label-icon{position:absolute;left:5px;margin:0}.btn-icon-left>.icon{position:absolute;top:0;bottom:0;left:0;display:block;width:30px;line-height:30px;color:#16a8f8;text-align:center;background:#e9f2fb}.btn-icon-left.btn-sm{padding-left:28px}.btn-icon-left.btn-sm>.label-icon{left:2px}.btn-icon-left.btn-sm>.icon{width:24px;line-height:24px}.btn-icon-right{position:relative;padding-right:35px;text-align:left}.btn-icon-right>.label-icon{position:absolute;right:5px;margin:0}.btn-icon-right.btn-sm{padding-right:28px}.btn-icon-right.btn-sm>.label-icon{right:2px}.btn-icon{min-width:32px;padding-right:0;padding-left:0}.btn-icon.btn-sm{width:24px;min-width:24px;height:24px}.btn-group{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group>.btn-group{float:left}.btn-group>.btn{border-radius:0}.btn-group>.btn:first-child{border-top-left-radius:2px;border-bottom-left-radius:2px}.btn-group>.btn:last-child{border-top-right-radius:2px;border-bottom-right-radius:2px}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.dropdown{float:left;margin-right:10px}.btn-toolbar>.btn-group:last-child,.btn-toolbar>.btn:last-child,.btn-toolbar>.dropdown:last-child{margin-right:0}.btn-toolbar>.divider{float:left;height:20px;margin:7px 5px 4px 10px;border-left:1px solid rgba(0,0,0,.1)}.btn-toolbar .space{float:left;min-height:1px;margin:0 10px 0 10px}.btn-toolbar .input-control{float:left;width:120px}.btn-toolbar .page-title{float:left;line-height:34px}.btn-toolbar .page-title .text{font-size:14px;font-weight:700}.btn-toolbar .page-title .label{top:-2px;margin-right:10px}.btn-toolbar .divider+.page-title{margin-left:15px}.btn-active-line{position:relative;font-weight:700;color:#0c64eb}.btn-active-line:after{position:absolute;right:5px;bottom:1px;left:5px;display:block;content:' ';border-bottom:2px solid #0c64eb}.btn-active-line:hover{color:#0c64eb}.btn-active-text .text{position:relative;top:-1px;display:inline-block;font-weight:700;color:#0c64eb}.btn-active-text .text:after{position:absolute;bottom:-5px;display:block;width:100%;content:' ';border-bottom:2px solid #0c64eb}.angle-btn{position:relative;padding:1px;background:#fff;border:1px solid #cbd0db;border-right:none}.angle-btn:first-child{border-radius:2px 0 0 2px}.btn-toolbar>.angle-btn{margin-right:8px}.angle-btn:after,.angle-btn:before{position:absolute;top:-1px;right:-8px;display:block;width:0;height:0;content:' ';border-color:transparent transparent transparent #cbd0db;border-style:solid;border-width:17px 0 17px 8px}.angle-btn:after{right:-7px;border-color:transparent transparent transparent #fff;border-radius:2px}.angle-btn .btn{padding:6px;font-weight:700;background:#fff;border:none;border-radius:4px!important}.angle-btn .btn.btn-limit{padding-right:16px}.angle-btn .btn.btn-limit>.caret{right:4px}.angle-btn+.angle-btn{border-left:none}.angle-btn+.angle-btn>.btn-group:first-child{padding-left:8px}.angle-btn+.angle-btn>.btn-group:first-child:after,.angle-btn+.angle-btn>.btn-group:first-child:before{position:absolute;top:-2px;left:0;display:block;width:0;height:0;content:' ';border-color:transparent transparent transparent #cbd0db;border-style:solid;border-width:17px 0 17px 8px}.angle-btn+.angle-btn>.btn-group:first-child:after{left:-1px;border-color:transparent transparent transparent #fff;border-width:17px 0 17px 8px}.btn-toolbar>.angle-btn.active,.btn-toolbar>.angle-btn:last-child{border-color:#0c64eb}.btn-toolbar>.angle-btn.active .btn,.btn-toolbar>.angle-btn:last-child .btn{color:#0c64eb}.btn-toolbar>.angle-btn.active:after,.btn-toolbar>.angle-btn.active:before,.btn-toolbar>.angle-btn:last-child:after,.btn-toolbar>.angle-btn:last-child:before{border-color:transparent transparent transparent #0c64eb}.btn-toolbar>.angle-btn.active:after,.btn-toolbar>.angle-btn:last-child:after{border-color:transparent transparent transparent #fff}.btn-toolbar>.angle-btn+.angle-btn:last-child>.btn-group:first-child:after,.btn-toolbar>.angle-btn+.angle-btn:last-child>.btn-group:first-child:before,.btn-toolbar>.angle-btn.active+.angle-btn>.btn-group:first-child:after,.btn-toolbar>.angle-btn.active+.angle-btn>.btn-group:first-child:before{border-color:transparent transparent transparent #0c64eb}.btn-toolbar>.angle-btn+.angle-btn:last-child>.btn-group:first-child:after,.btn-toolbar>.angle-btn.active+.angle-btn>.btn-group:first-child:after{border-color:transparent transparent transparent #fff}.btn-toolbar>.angle-btn.active+.angle-btn,.btn-toolbar>.angle-btn.normal{border-color:#cbd0db}.btn-toolbar>.angle-btn.active+.angle-btn .btn,.btn-toolbar>.angle-btn.normal .btn{color:#3c4353}.btn-toolbar>.angle-btn.active+.angle-btn:after,.btn-toolbar>.angle-btn.active+.angle-btn:before,.btn-toolbar>.angle-btn.normal:after,.btn-toolbar>.angle-btn.normal:before{border-color:transparent transparent transparent #cbd0db}.btn-toolbar>.angle-btn.active+.angle-btn:after,.btn-toolbar>.angle-btn.normal:after{border-color:transparent transparent transparent #fff}.btn-toolbar>.angle-btn.active+.angle-btn>.btn-group:first-child:before,.btn-toolbar>.angle-btn.normal>.btn-group:first-child:before{border-color:transparent transparent transparent #cbd0db!important}.nav>li>.btn.btn-primary{color:#fff}.nav>li>.btn.btn-primary:focus,.nav>li>.btn.btn-primary:hover{background:rgba(12,100,235,.8)}.btn.btn-action,.c-actions .btn{display:inline-block;width:26px;padding:2px;overflow:hidden;line-height:20px;color:#16a8f8;background:0 0;border-color:transparent}.btn.btn-action>i,.c-actions .btn>i{position:relative;top:1px;font-size:18px}.btn.btn-action:hover,.c-actions .btn:hover{color:#0c64eb;background-color:#d3e5f7}.c-actions .btn+.btn{margin-left:-4px}.label{position:relative;display:inline-block;padding:3px 5px;font-size:12px;font-weight:400;vertical-align:middle;border-radius:2px}.label+.label{margin-left:4px}.label-pale{background:#bed8f3!important}.label-badge{border-radius:9px}.label-light{color:#3c4353;background-color:#ddd}.label-primary{background:#0c64eb!important}.label-gray{color:#878da0;background:#e8ebef}.label-outline.label-danger{color:#ff5d5d;background:#ffebee;border-color:rgba(255,93,93,.25)}.label-outline.label-light{color:#838a9d;background:#f2f5fb;border-color:#e1e5ee}.label-primary.label-outline{background:#e9f2fb!important;border-color:rgba(12,100,235,.25)}.label-outline.label-success{background:#e8f5e9;border-color:rgba(0,218,136,.25)}.label-outline.label-info{background:#e3f2fd;border-color:rgba(33,150,243,.25)}.label-outline.label-warning{background:#fff3e0;border-color:rgba(255,152,0,.25)}.label-dot{position:relative;top:-1px;padding:0;border-radius:50%}.label-dot+.status-text{display:inline-block;margin-left:5px}.label-icon{min-width:18px;padding:0;line-height:18px;border-radius:10px}.label-id{display:inline-block;min-width:30px;padding:0 5px;font-size:12px;line-height:16px;color:#838a9d;text-align:center;vertical-align:middle;background-color:transparent;border:1px solid #838a9d;border-radius:2px}.pri-1,.todo-pri-1{color:#ff5d5d}[class*=" status-"],[class^=status-]{color:#3c4353}.status-changed,.status-delayed,.status-doing,.status-fail,.status-investigate{color:#ff5d5d}.status-changed>.label-dot,.status-delayed>.label-dot,.status-doing>.label-dot,.status-fail>.label-dot,.status-investigate>.label-dot{background-color:#ff5d5d}.status-wait{color:#838a9d}.status-wait>.label-dot{background-color:#7ec5ff}.status-unclosed{color:#838a9d}.status-unclosed>.label-dot{background-color:#0c64eb}.status-done,.status-normal,.status-pass,.status-resolved{color:#43a047}.status-done>.label-dot,.status-normal>.label-dot,.status-pass>.label-dot,.status-resolved>.label-dot{background-color:#00da88}.status-postpone{color:#838a9d}.status-postpone>.label-dot{background-color:#ff5d5d}.status-blocked{position:relative;left:-5px;display:inline-block;padding:0 5px;line-height:20px;color:#3c4353;background:0 0;border-radius:10px}.status-blocked>.label-dot{background-color:#ff9800}.status-pause,.status-suspended{color:#ff9800}.status-pause>.label-dot,.status-suspended>.label-dot{background-color:#ff9800}.status-active.status-bug,.status-draft{color:#8666b8}.status-active.status-bug>.label-dot,.status-draft>.label-dot{background-color:#8666b8}.status-closed,.status-terminate{color:#838a9d}.status-closed>.label-dot,.status-terminate>.label-dot{background-color:#838a9d}.status-cancel{color:#838a9d}.status-cancel>.label-dot{background-color:#cbd0db}.label-pri{display:inline-block;min-width:18px;max-width:100%;height:18px;padding:0 4px;overflow:hidden;font-size:12px;line-height:16px;color:#838a9d;text-align:center;text-overflow:clip;white-space:normal;vertical-align:middle;border:1px solid #838a9d;border-radius:10px}.label-pri-1,.label-selector>.label-pri[data-value="1"]{color:#d50000;border-color:#d50000}.label-pri-2,.label-selector>.label-pri[data-value="2"]{color:#ff9800;border-color:#ff9800}.label-pri-3,.label-selector>.label-pri[data-value="3"]{color:#2098ee;border-color:#2098ee}.label-pri-4,.label-selector>.label-pri[data-value="4"]{color:#009688;border-color:#009688}.label-pri-5,.label-selector>.label-pri[data-value="5"]{color:#838a9d;border-color:#838a9d}.label-pri-0,.label-selector>.label-pri.active[data-value="0"]{color:#d5d9df;border-color:#d5d9df}.label-severity{position:relative;display:inline-block;width:24px;height:20px;font-weight:bolder;text-align:center;vertical-align:middle}.label-severity:before{position:absolute;top:-3px;left:0;z-index:0;display:block;font-family:ZentaoIcon;font-size:14px;font-size:24px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;color:inherit;text-transform:none;content:"\e973";speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.label-severity:after{position:absolute;top:7px;left:0;z-index:1;display:block;width:24px;font-size:12px;line-height:12px;text-align:center;content:attr(data-severity)}.label-severity[data-severity],.label-severity[data-value]{color:#ccc}.label-severity[data-severity="0"],.label-severity[data-value="0"]{color:#ccc}.label-severity[data-severity="1"],.label-severity[data-value="1"]{color:#c62828}.label-severity[data-severity="2"],.label-severity[data-value="2"]{color:#ff8f00}.label-severity[data-severity="3"],.label-severity[data-value="3"]{color:#fdd835}.label-severity[data-severity="4"],.label-severity[data-value="4"]{color:#cddc39}.label-severity[data-severity="5"],.label-severity[data-value="5"]{color:#8bc34a}.label-severity-custom[data-severity]{color:#d5d9df}.label-severity-custom[data-severity="1"]{color:#c62828}.label-severity-custom[data-severity="2"]{color:#ff8f00}.label-severity-custom[data-severity="3"]{color:#fdd835}.label-severity-custom[data-severity="4"]{color:#cddc39}.label-severity-custom[data-severity="5"]{color:#8bc34a}.label-selector{padding:0 10px}.label-selector>.label{display:inline-block;min-width:24px;height:24px;padding:0 5px;font-size:14px;line-height:20px;text-align:center;cursor:pointer;background:0 0;border:2px solid #d5d9df;border-radius:15px}.label-selector>.label+.label{margin-left:10px}.label-selector>.label.empty{border-color:transparent}.label-selector>.label.label-severity{font-size:12px;line-height:28px;border-color:transparent}.label-selector>.label.label-severity:before{top:-2px;left:-2px}.label-selector>.label.label-severity:after{display:none}.label-selector>.label.label-severity.active{background:0 0;filter:none;-webkit-filter:none}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{margin-top:2px}.ie .checkbox input[type=checkbox],.ie .checkbox-inline input[type=checkbox],.ie .radio input[type=radio],.ie .radio-inline input[type=radio]{margin-top:4px}.is-firefox .checkbox input[type=checkbox],.is-firefox .checkbox-inline input[type=checkbox],.is-firefox .radio input[type=radio],.is-firefox .radio-inline input[type=radio]{margin-top:3px}.checkbox-primary,.radio-primary{position:relative;display:block;vertical-align:middle}.checkbox-primary.inline-block,.radio-primary.inline-block{display:inline-block}.checkbox-primary.inline-block+.inline-block,.radio-primary.inline-block+.inline-block{margin-left:15px}.checkbox-primary>input,.radio-primary>input{position:absolute;top:0;left:0;z-index:3;width:100%;height:100%;margin:0;opacity:0}.checkbox-primary>label,.radio-primary>label{display:block;height:20px;padding-left:20px;margin:0;font-weight:400;line-height:20px;cursor:pointer}.checkbox-primary>label:after,.checkbox-primary>label:before,.radio-primary>label:after,.radio-primary>label:before{position:absolute;top:3px;right:0;left:0;display:block;width:14px;height:14px;line-height:14px;text-align:center;content:' ';border-radius:3px}.checkbox-primary>label:after,.radio-primary>label:after{z-index:1;border:1px solid #d9dbe1;border-color:rgba(0,0,0,.15);-webkit-transition:.4s cubic-bezier(.175,.885,.32,1);-o-transition:.4s cubic-bezier(.175,.885,.32,1);transition:.4s cubic-bezier(.175,.885,.32,1);-webkit-transition-property:border,background-color;-o-transition-property:border,background-color;transition-property:border,background-color}.checkbox-primary>label:before,.radio-primary>label:before{top:3px;z-index:2;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-weight:900;font-variant:normal;line-height:1;text-transform:none;content:"\e5ca";opacity:0;-webkit-transition:.2s cubic-bezier(.175,.885,.32,1);-o-transition:.2s cubic-bezier(.175,.885,.32,1);transition:.2s cubic-bezier(.175,.885,.32,1);-webkit-transition-property:opacity,-webkit-transform;-o-transition-property:opacity,-o-transform;transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform,-o-transform;-webkit-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0);speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.checkbox-primary.checked>label:after,.checkbox-primary>input:checked+label:after,.radio-primary.checked>label:after,.radio-primary>input:checked+label:after{background-color:#00da88;border-color:#00da88;border-width:4px}.checkbox-primary.checked>label:before,.checkbox-primary>input:checked+label:before,.radio-primary.checked>label:before,.radio-primary>input:checked+label:before{color:#fff;opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}.checkbox-primary input:indeterminate+label:before,.checkbox-primary.indeterminate>label:before,.radio-primary input:indeterminate+label:before,.radio-primary.indeterminate>label:before{top:9px;left:3px;width:8px;height:2px;content:' ';background-color:#a3a2bc;opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}.checkbox-primary.focus>label:after,.checkbox-primary>input:focus+label:after,.radio-primary.focus>label:after,.radio-primary>input:focus+label:after{border-color:#00da88;-webkit-box-shadow:0 0 0 3px rgba(0,218,136,.2);box-shadow:0 0 0 3px rgba(0,218,136,.2)}.checkbox-primary:hover>label:after,.radio-primary:hover>label:after{border-color:#00da88}.checkbox-primary.checkbox-right>label,.radio-primary.checkbox-right>label{padding:0 30px 0 0}.checkbox-primary.checkbox-right>label:after,.checkbox-primary.checkbox-right>label:before,.radio-primary.checkbox-right>label:after,.radio-primary.checkbox-right>label:before{right:0;left:auto}.checkbox-primary input:disabled+label:after,.checkbox-primary.disabled>label:after,.radio-primary input:disabled+label:after,.radio-primary.disabled>label:after{background-color:#e5e5e5!important;border-color:#bbb!important}.checkbox-primary input:disabled:checked+label:after,.checkbox-primary.checked.disabled>label:after,.radio-primary input:disabled:checked+label:after,.radio-primary.checked.disabled>label:after{background-color:#bbb!important}.radio-primary>label:after{border-radius:50%}.radio-primary>label:before{top:7px;left:6px;width:6px;height:6px;content:' ';border:none;border-radius:50%}.radio-primary.checked>label:after,.radio-primary>input:checked+label:after{background-color:transparent;border-color:#00da88;border-width:2px}.radio-primary.checked>label:before,.radio-primary>input:checked+label:before{background-color:#00da88}.radio-primary input:disabled:checked+label:after,.radio-primary.checked.disabled>label:after{background-color:transparent;border-color:#bbb}.radio-primary input:disabled:checked+label:before,.radio-primary.checked.disabled>label:before{background-color:#bbb}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li>a{position:relative;border:none!important;border-radius:2px!important}.nav-tabs>li.active>a{font-weight:700;color:#3c4353!important}.nav-tabs>li.active>a:before{position:absolute;right:0;bottom:-1px;left:0;display:block;height:2px;content:' ';background:#0c64eb}.nav-tabs-primary>li.active>a{color:#0c64eb!important}.panel{position:relative;margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045);box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045)}.panel-body{padding:20px}.panel-body.has-table{padding:10px}.panel-body.has-table .table{margin-bottom:0;table-layout:fixed}.panel-heading{padding:12px 48px 12px 20px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading+.panel-body{padding-top:0}.panel-title{font-size:14px;font-weight:700;line-height:20px}.panel-title .label{top:-1px}.panel-actions{position:absolute;top:0;right:0;padding:7px 8px}.panel:hover .panel-actions{z-index:10}.panel-actions>li>a{display:inline-block;min-width:30px;padding:0 5px;line-height:30px;color:#a6aab8;text-align:center;border-radius:4px}.panel-actions>li>a:hover{color:#3c495c;text-decoration:initial;background-color:#f1f1f1}.panel-actions .btn-icon{color:#a6aab8}.panel-actions .btn.text-primary{color:#0c64eb}.panel .empty-tip{padding:30px 10px 50px;font-size:14px;color:#838a9d;text-align:center}.progress-text-left{position:relative;margin:7px 0;margin-left:35px;overflow:visible}.progress-text-left .progress-text{position:absolute;top:-7px;left:-35px;display:block;width:35px;height:20px;padding-right:5px;line-height:20px;color:#838a9d;text-align:right}.chart-color{width:20px}.chart-color-dot{display:inline-block;width:10px;height:10px;border-radius:50%}.chart-row{margin-top:10px}.chart-row+.chart-row{padding-top:10px;border-top:1px solid #eee}.chart-wrapper{padding:10px 5px;background:#eee}.chart-wrapper>h4{margin:5px 0 10px}.table-wrapper{max-height:250px;overflow:auto}.table-wrapper .table{margin:0}.progress-pie{position:relative}.progress-pie canvas{display:block}.progress-pie .progress-info{position:absolute;top:0;left:0;width:100%;height:100%;padding-top:25px;text-align:center}.progress-pie .progress-info>small{display:block;line-height:14px;color:#a6aab8}.progress-pie .progress-info>strong{display:block;font-size:36px;line-height:40px}.progress-pie .progress-info>strong>small{font-size:20px}.progress-pie-120 .progress-info{padding-top:30px}.progress-pie-120 .progress-info>small{line-height:18px}.progress-pie-50 .progress-info{padding-top:4px}.progress-pie-50 .progress-info>strong{font-size:20px;font-weight:400}.progress-pie-50 .progress-info>strong>small{font-size:14px}.progress-pie[data-value="100"] .progress-info>strong{-webkit-transform:scale(.7);-ms-transform:scale(.7);-o-transform:scale(.7);transform:scale(.7)}.progress-pie-24 .progress-info{right:-10px;left:-10px;width:auto;padding-top:0;font-size:12px;line-height:24px;-webkit-transform:scale(.9,1);-ms-transform:scale(.9,1);-o-transform:scale(.9,1);transform:scale(.9,1)}.progress-pie-24[data-value="100"] .progress-info{-webkit-transform:scale(.8,1);-ms-transform:scale(.8,1);-o-transform:scale(.8,1);transform:scale(.8,1)}.progress-pie-26 .progress-info{right:-10px;left:-10px;width:auto;padding-top:0;font-size:12px;line-height:26px;-webkit-transform:scale(.9,1);-ms-transform:scale(.9,1);-o-transform:scale(.9,1);transform:scale(.9,1)}.progress-pie-26[data-value="100"] .progress-info{-webkit-transform:scale(.8,1);-ms-transform:scale(.8,1);-o-transform:scale(.8,1);transform:scale(.8,1)}.status-bars{display:table;width:100%;height:140px;padding:5px;padding-top:50px;margin:0;overflow:hidden}.status-bars>li{position:relative;display:table-cell;text-align:center;vertical-align:bottom}.status-bars .bar{position:absolute;bottom:20px;left:50%;display:block;width:10px;margin-left:-5px;background:#0c64eb;border-radius:5px 5px 0 0}.status-bars .bar:after{position:absolute;right:-50px;bottom:0;left:-50px;display:block;height:1px;content:' ';background:#eee}.status-bars .title{font-size:12px;font-weight:400;color:#a6a8b6}.status-bars .value{position:relative;top:-20px;left:-20px;display:inline-block;width:50px;font-size:16px;font-weight:700;text-align:center}.status-bars-h{display:block;padding-right:50px;padding-left:60px;list-style:none}.status-bars-h>li{position:relative;height:40px;border-left:1px solid #eee}.status-bars-h .bar{position:relative;top:15px;display:block;height:10px;line-height:20px;background:#0c64eb;border-radius:0 5px 5px 0}.status-bars-h .title{position:absolute;top:-5px;left:-60px;width:60px;padding-right:10px;font-size:12px;color:#a6a8b6;text-align:right}.status-bars-h .value{position:absolute;top:-5px;right:-50px;display:block;width:40px;font-size:14px;font-weight:700;text-align:left;white-space:nowrap}.ring,[class*=" ring-"],[class^=ring-]{width:24px;height:24px;font-size:12px;line-height:24px;text-align:center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAACZAAAAAwCAMAAACyyT3hAAAAP1BMVEUAAAAAAAA5rm06sG87snE4q200o2o7sG86r244q2w6r244rWw7snA7sG86rG05rm07snA5qWw7sW86sG48s3ECZypFAAAAFHRSTlMACl2b8TkPtnsqj0fVv4Zt4RrIqxUkbyYAAA1gSURBVHja7NrbbtswEIRhmyJ1IiVS0v/+z9rCbeGkdZodNEnVdHmTxP4wmF1exLB9eXCu12tqLX39cTGcm78use2z5Msx19wLfunGpOZvSv4xh/798tt+dKPSZ+jGMNn9/pWnXp1X7f9e+ynf53Xv3r37j/bLyfq4/1u+n8T8VI8jLWY/hbEbSjT76+2ssH77zeyBJHooom9dkHzssuQ5wvau+YuWz141/87zMoTewP9kP+7d2/31ZPln82e7L/fuP9LnJPk+DDDb/TQvEaDc/1//vk9Yvrl7vmHa+ztk347BXwcA1UMRPXCIfq+b5Jm3d82PneY5guSHG1fmVfu/837m5N69e/fu3T89fRZ9bRTBpyMCLFa/zfG7CU98l1/M/+EBS/59PT//bfD9lCS/pbAeR7bnb1OqC7AI+QWAkiz5Kdd1B6BVLb8Fk891Poox/7bPUNcIwGHrM3YDAHu1zyv0yWHcjfNen++nWvsvANC5d6/468nyz+bPdl/u3es+NFbFjw1A8BGAPUv5xGFMz/382HcAsNy+W9Sb9/PwwbP4ra5J8WluQDb7qQ4Ayybl05nnrQVgSFafB4AyWfvPEaBT57X2Seu3ecX9HBfN75t79+7du/+sPnVBy++A1e6nHaAEsz9ufk7W/gUgrvmBP/pf/bYDtDlp+/x8j4du1XwBFsHvQMlW348NIJjz0yH5bbz1n7R5m71/bUAL2n5iMueHAYjZvXv37t1/Tp8bJMFPDYhCfgTa2Ft9aEDJ5vzUbvnbC3562GcI5j6vf3T43/h+hlnJnwFGs99WgGDPv/lq9yPQsjCv1mcT/aUDGEVf3bt37979v+DH1kk+RIiCrwCz0AeI82bvc8vvzT5HYP1NfnjQv3uL/d+f/X/8ljUfGiD4ChDsPkcgCX0iUMX8UfDDw/6Xl+fV+q8Awb373/rLyfLP5s92X+4/rQ8QFV+BmO0+AyTND0nqT1H6xFf715/zWe35l5fXf3/e/YtnGugUnxsQhD47sNl9Klp+ipq/DmL/ovXPAJN79+7du/9on5dV80An+BEoye4nYLhofu/tPgAtafO26RWfn/chv9F93YX7N/PTDoOSHzW/LVA2Ib9Am+y+34Es5DdYlHmB2Lt37969+4/1fYQs+KlB6e0+Acsm9CnQXTQfJ61PTMI+dyiv99me7pO3u6+7cf9mvj/Ikgc6xRfNXyIcgt8KLIoX+0/A4d69e/fu/8znoPkOBsH3O8Qk5C8wiH12xR9AFvwAUfEzREOf/Wmf6Q3v967cv52fNJ+BIPgg+gmogk/xmb9a+lex/+ze/WN/PVn+2fzZ7sv93/MVVsUHIAn+AKrgV4hK/gxsYv+q7Ycg+AxMFt/d+9vy/QXZP+RHCIrvoGyCr9B6wa/QNq3/ftHyye7df2HP3pbQBKIgihqGmzKA4P7/b02lTOX2EncSEky1z8uungPosYyPj/8Nv8Mk/HaHm/Adzk/AIvy1hUb4vkKR5y0yf33Nd+K89vo+Xfy/81Oj/FahmPwBRuH7CjeTX6GRfUp8fHx8/Fc/UpRvoBpf4L4ZL/MfsLvzUoxfgM6e1/V5vNjn9jl/eLV/FrL/2DcwS1+lZxN+9X3a+Pj4+Pgvvm9B5Q8wyvxV+K11+VdgMv2r810LRZ63MX1m6IwX+ep+eMr49/HL3ChfoTF+eD65r/q+wiTy+zus8fHf+8vJ8s/mz3a94n/im075FarxE7Sby2975+8mf5T9G9gvLp/O9Jf5nfHNcz6vzzMLWfyX1wiz8Ss8ZP5g/A32+Pj4+P/XP0D5GRbjC9xkfjF+l/lV9h9gtP2PnOfN9JntfMQPsCeN/3/9dmc2/gqtym+d74BrfHx8/P/q+xaM34CryZf+CnTCT9Ca/A7YnG+N71V/P89La/r7eZ5pIYj/x35aNuUH6IzfpZ+hiY+Pj38X35dF+Ql241eoxncwGD/K/EbmL8r7/En2X+X8J99/dveb+4L/EB//zX+Wo/EFVunH+Pj4+HfxI0zG3+BmfIHF+AaKzB/VeU+Wv8BwZJ/14P56IbvEx39+bdDIBa4YP8bHx8e/kS/QGb/DZPwDVuMXGGV+Y3yR+QM+X/py5HlvB/e3C1l8/Fe/TYZfJtjNGxoY4uN/8JeT5Z/Nn+16vbVf7kX5Ga7GV+iM32Ey/gHNkfnDyfJnWA+d58H9L+aB/4Tj43/Vb4DxHdT4+Pj4f+WhVb7CZnwrfYWr8Tt0xt9lfj1ZfoVJedvn4P5ZyOL/nn+wGN9DGx8fH/+vPKB8630f/0f9drI+ymchiz+vB5Q/4Qd6fHz8efxCycIU/5G9e9lRHAaAKEr7kZi8nIT7/986UlatWaWGCbjpYn1UKizAQU7sZr0vyOzb9QkUv8Ek+qT4u77ksYv5q5g/tZQv91F9g0ta9j/Loy8RZnv7795LlvYf4b/U/JgWccLur/xBH2EXfbw4v28pP8B8cZ9HgzfR27/Tj9utpZvK7e2f8W09tWdv/8S+aBmi4OWnPis8FF+gKD7o+VHM78X8QfGD3uch+qG1bQ7s3+sDbIqPUEVf7O2/+5a2vWhqHyx7+++vUbwAGsQJfhEnjAhB8UXPLy3l97BcOgF7Y2H7v3yBeuVGqcXe/oW+qaN77O2f8jF2it9hVPwE9eKjpYqYH0S/XJk/ieM5i+P5gLG1o3Ls/7PfllE9Gkj0u3r0jb39q3xbE6q9/Qs9pE7wd+BKn4FNyU8wCn4DsuKT5vPF49Phw+k/389Mm+IT3DWf5MOh7e1f5G/n1ywPaW//MR4eil9EP0AU83sxf1d8Ub3YJ4q+iONZYRDHZ7b/aX6GovgIVfG9kr8ffYbz+fb2z/nbTZnw7O2f8V9N9clV8hMEwW8JRsF3q5i/QlX676rX+mSgqPmKnyGr42n/dh/mRfEjTIoP0Kv53Vlfj/z1tA/29s/5039hDmdv/2s9pE7wBXolv+r5aRP8CIh+UvpHSFnwQXy/GeabmG//fj9DUPyk+Q0IYp+q+ATB3v4lvqkJz96+ZR+pip8gCH5bIUr5ot/hofgIRfAZWK58vzMUxfcw2F/hQ1D8ANMm+Aq9mt8JPsB0Mj8e+UIfe/vn/Olv5KHs7e3P+QC74gdY75onC34BRsFXSEqfCFOn+XUT/KDnk+0v8AGK4LcJouC7FQYlf4VF6b9DEb4vmfP97X+HX859fvT843Vq880D2dv/o7811udyv0AV/IjmK/AQfE6wKB4YxD5B8AGoYp9R8AsQ7f+0a287bsJQFIapTxxssA3/+z9rJVS1VVOmezeDOp1s7mI+LS1bxJZChH7WeAdkpXcKX4Gs8yHqPFXyfC4/jspNlG/+VbyTPD/6/G+X9EAyb9681Dun8SMcCh8D7Enu0wirpk/T+QyMGh90fgiwKPvs5oU+45PCH4DGeyjK/KDpv0Lpyv7z237mp+/jDmRBvvnX8YLn5y/yxd/gU5g3b/4enyF0uU8FWpT7vgIKf56JSe5jgNY1XtlnV+5XQOjmhf6AfVb4AkGR3wuMXe7nBrsiPwN7evf+3xN7AAR9zJt/yst3uPO+efPmb/LbmhXeAwofCzAp8kcgyn0qyj4NcHLflfkzr+494yz3DmhZ7mdgH3T5JSp91/lxeL/+GWC++HyZb/6lfL72+Yl80d8OztvmzYv8I/9gff5/H6DKfQ6ofARwCj+i61MAp+sfstw7gPrZfO4KDzQn9w5A4TMQZrmvQFDkT0DIuv5j1Hku87eH1aiC9TH/Yn678tsT+Vdn5uM98+bNfxDvwyT3KUBwcr/o9oe+BJVPZ76T529AyBf+8jz9bH6BJYn9BLDI8x3A1nX5VZ6fGzAp+yxJ6ZX9t+ufn6m/W5+3+pt/Oe+vnx99/tWxYOM2buOfanyGluU+AHuX+jQ1IERxfi5Ac1Lfz/wmzk9uBML8P/jNO7lfgSL3sQC73DuANiWpzwA+i/Pns//UxflNN1/XgFaTuE8D1sv8/OADMLrLfPPmn/JXO/qX3w+aN2/+P/X1iHK/AZM43xWAsQt9XE5/zEKftwBQoji/nfnpH/m41S72GQg+Cn1aAcZpluYvqPLjCFCqdL59B1jFfvAAYZH2j8r5dq+b77Bd+70/8nQAtOX3+ebNP+Wvd9zz+vWjefNaP3ywPuZFfqNluQcIm9DnndNPIh+nMQDQJL5HN/kVAJY/+TinJPX5OCYXhX4F1hrnPgh8LAAUaX5tnH6rWdTfNXX+yZeaRd4DELaaZetZdwBGf/N8Jyfz+Wp9/Buv8mF97G/e/JP+egt6vAbz5s2/is9J4QthEvsVIBxR5F2A0y9d4Avwzfv8Jw8g9gXk/gDkvtdd5xfuzfdB5d2Iyg9uvHe+PrzD+izxyueLfPPmn/OaLXoYzJv/az98sD7m39XHrPAe1pqEfgUI6zJL/AYAsNc/94mA3O+g8M43lc8+aPxcR+7M73VH5aei7cOd8011fW59Vve2f1wf8+bv84+vmsybN2/+Xfzc5b4fR43i/DWU0U9uFvlpb0HsU578WOR+iJNfFb4r85Nbjjvz58kfe1N4p+wf3Xbsyvmq+9+4Ps68+dv8V5yOdlOUBd3vAAAAAElFTkSuQmCC);background-position:0 0;-webkit-background-size:1224px 24px;background-size:1224px 24px}.ring>span,[class*=" ring-"]>span,[class^=ring-]>span{display:inline-block;-webkit-transform:scale(.9,1);-ms-transform:scale(.9,1);-o-transform:scale(.9,1);transform:scale(.9,1)}.messager{border-radius:4px;-webkit-box-shadow:0 4px 16px rgba(0,0,0,.2),0 2px 8px rgba(0,0,0,.1);box-shadow:0 4px 16px rgba(0,0,0,.2),0 2px 8px rgba(0,0,0,.1)}.messager-icon{vertical-align:middle}.messager-icon>.icon{font-size:24px}.messager-content{padding:18px 20px;font-size:18px;line-height:30px}.messager-content>.icon{font-size:28px;line-height:30px}.messager-actions{vertical-align:middle}.messagger-zt{color:#3c4353;background-color:#fff!important}.messagger-zt .messager-icon>.icon{color:#0c64eb}.messagger-zt .messager-actions>.action{color:#838a9d}.messagger-zt.messager-success .messager-icon>.icon{color:#00da88}.messagger-zt.messager-danger .messager-icon>.icon{color:#ff5d5d}.messagger-zt.messager-warning .messager-icon>.icon{color:#ff9800}.messagger-zt.messager-info .messager-icon>.icon{color:#2196f3}.tree{padding-left:0;overflow:hidden}.tree ul{position:relative;display:none;padding-left:0}.tree li{position:relative;padding:2px 0 2px 15px;list-style:none}.tree li.heading{padding-left:5px;color:#3c495c}.tree li>a{display:block;max-width:90%;padding:2px 6px;color:#3c495c;word-break:break-all}.tree li>a:hover{color:#3c4353}.tree li>a.tree-toggle:hover{background:0 0}.tree li.active>a{position:relative;font-weight:700;color:#0c64eb}.tree li>.list-toggle{position:absolute;top:1px;left:1px;z-index:10;width:20px;font-size:14px;line-height:22px;color:#cbd0db;text-align:center;cursor:pointer;-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s}.tree li>.list-toggle:before{content:"\f0da"}.tree li>.list-toggle:active,.tree li>.list-toggle:hover{color:#0c64eb}.tree li.has-active-item>.list-toggle{color:#3c4353}.tree li.has-list.open>ul{display:block}.tree li.has-list.open>.list-toggle{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.tree li.has-list.open:before{position:absolute;top:16px;bottom:-5px;left:10px;display:block;content:' ';border-left:1px solid #d8d8d8}.tree-actions{display:inline-block;margin-left:5px;vertical-align:middle}.tree-actions a{display:inline-block;margin-left:5px;font-size:13px;opacity:.6}.tree-actions a:hover{opacity:1}.tree li>.module-name{color:#3c495c;vertical-align:middle}.tree li>.module-name:hover{background-color:#f0f2f5}.tree li>.module-name:hover>a{color:#3c4353}.treemap-node-fold-icon:before{position:relative;left:-4px;min-width:18px}.dropdown-menu{padding:5px 0;border-color:rgba(0,0,0,.1)}.dropdown-menu>li{padding:0 10px}.dropdown-menu>li>a{padding:2px 10px;margin:5px 0;border-radius:3px}.dropdown-menu>li>a>.icon{position:relative;left:-5px;opacity:.5}.dropdown-menu>li>a:hover>.icon{opacity:.8}.dropdown-menu>li.active>a,.dropdown-menu>li.selected>a{position:relative;color:#fff;background-color:#16a8f8}.dropdown-menu>li.selected>a:after{position:absolute;top:2px;right:4px;display:block;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;line-height:20px;text-transform:none;content:"\e5ca";speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.dropdown-menu>li.divider{margin:10px}.dropdown-submenu>a:after{margin-right:-5px}.dropdown-submenu>.dropdown-menu.pull-left{margin-left:-1px}.dropdown-submenu:focus>a,.dropdown-submenu:hover>a{color:#3c4353;background-color:#e9f2fb}.dropdown-submenu:hover>a:after{border-left-color:#0c64eb}.dropdown-submenu>a:hover:after{border-left-color:#fff}.pager .btn{padding:3px 10px}.pager .btn .caret{opacity:.7}.pager>li>.pager-label{padding:2px;line-height:20px}.pager>li>.pager-item{min-width:20px;padding:1px;margin:2px 0;font-size:16px;line-height:20px;text-align:center;background:0 0;border-color:transparent}.pager>li>.pager-item:hover{background-color:rgba(0,0,0,.1)}.pager>li>.pager-item>.icon{position:relative;top:-1px}.pager>li>.btn:hover,.pager>li>a:hover{background:rgba(0,0,0,.1)}.pager>li.disabled>a.pager-item{background:0 0;border-color:transparent;opacity:.5}.pager>li.active>a{background-color:#16a8f8}.pager>li .btn-group .btn{padding:1px;margin:1px 0;border-radius:4px}.pager .dropdown-menu{width:200px}.pager .dropdown-menu>li{float:left;width:33.333333%}.modal-dialog{width:900px;max-width:1360px;border:none;border-radius:0;-webkit-box-shadow:0 0 20px 0 rgba(0,0,0,.25);box-shadow:0 0 20px 0 rgba(0,0,0,.25)}.modal-dialog.modal-md{width:700px}.modal-dialog.modal-xs{width:400px}.modal-dialog.modal-sm{width:500px}.modal-dialog.modal-lg{width:1200px}.modal-dialog.modal-fullscreen{position:fixed;max-width:initial}.modal-header{padding:20px 0;margin:0 20px}.modal-header>.close{color:#838a9d;text-shadow:0 1px 0 rgba(255,255,255,.85);opacity:1}.modal-header>.close:hover{color:#222}.modal-footer{padding:20px 0;margin:0 20px}.modal-title{font-size:14px;font-weight:400;line-height:20px}.modal-actions{position:absolute;top:16px;right:16px}.modal-actions .divider{position:relative;top:5px;display:inline-block;width:0;height:20px;margin:0 10px;border-left:#eee 1px solid}.modal-actions>.dropdown{display:inline-block}.modal-body{padding:20px}.modal-iframe .modal-body>iframe{border-radius:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-3%);-ms-transform:translate(0,-3%);-o-transform:translate(0,-3%);transform:translate(0,-3%)}.modal.fade.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-simple .modal-footer{padding-top:0;border-top:none}.modal-iframe .modal-header{position:relative;z-index:10;min-height:0;padding:0;border:none}.modal-iframe .modal-title{display:none}.modal-iframe .modal-header .close{position:absolute;top:12px;right:10px;font-size:32px;font-weight:200}.modal-iframe .modal-dialog{overflow:hidden}.modal-inverse .modal-header>.close{color:rgba(255,255,255,.7);text-shadow:none}.modal-inverse .modal-header>.close:hover{color:#fff}.modal-scroll-inside>.modal-dialog{max-height:100%}.hide-modal-close .modal-iframe .modal-header .close{display:none}.tile{text-align:center}.tile-title{line-height:20px;color:#3c495c}.tile-amount{font-size:32px;font-weight:700;line-height:56px}.timeline>li{position:relative;list-style:none}.timeline>li:before,.timeline>li>a:after,.timeline>li>div:after{position:absolute;left:-20px;display:block;width:15px;height:15px;content:' ';border-radius:50%}.timeline>li:before{top:12px;left:-16px;z-index:3;width:7px;height:7px;background-color:#cbd0db;border:none;border:1px solid #cbd0db}.timeline>li>a:after,.timeline>li>div:after{top:11px;left:-17px;z-index:3;width:9px;height:9px;background-color:#0c64eb;border-radius:50%;opacity:0}.timeline>li+li:after{position:absolute;top:-12px;bottom:20px;left:-13px;z-index:1;display:block;content:' ';border-left:1px solid #eee}.timeline>li.active>a:after,.timeline>li.active>div:after{opacity:1}.timeline>li.active:before{top:8px;left:-20px;width:15px;height:15px;background-color:rgba(12,100,235,.2);border:none}.timeline>li>a,.timeline>li>div{display:block;padding:5px;line-height:20px}.timeline>li.active>a{color:#3c4353}.timeline-tag{position:absolute;top:5px;left:-115px;font-size:12px}.timeline-tag-left{padding-left:115px}.timeline-sm{font-size:12px}.timeline-sm>li:before,.timeline-sm>li>a:after,.timeline-sm>li>div:after{top:10px;left:-20px;width:11px;height:11px}.timeline-sm>li.active:before,.timeline-sm>li:before{top:10px;left:-18px;width:11px;height:11px;background:0 0;border:1px solid #eee}.timeline-sm>li>a,.timeline-sm>li>div{line-height:20px}.timeline-sm>li>a:after,.timeline-sm>li>div:after{top:13px;left:-15px;width:5px;height:5px}.form-control{-webkit-box-shadow:none;box-shadow:none}.form-horizontal .form-group>label{padding-right:0}.form-actions{margin-top:20px;margin-bottom:0}.form-actions .btn{margin-right:10px}form label{font-weight:400;color:#3c495c}.form-group .btn+.btn{margin-left:5px}.table-form{margin-bottom:0;table-layout:fixed}.table-form>thead>tr>th.required:after{position:relative;top:3px;right:auto;left:4px;display:inline-block;vertical-align:middle}.table-form>tbody>tr>td,.table-form>tbody>tr>th,.table-form>tfoot>tr>td,.table-form>thead>tr>th{padding:7px;vertical-align:middle;border-bottom:none}.table-form>tfoot>tr>td{padding:20px 7px 10px}.table-form>tbody>tr>th{width:100px;font-weight:700;text-align:right}.table-form .input-group{width:100%}.chosen-container-single .chosen-single{position:relative}.chosen-container-single .chosen-single>span{height:20px;line-height:20px;word-break:break-all;white-space:normal}.chosen-container-single .chosen-single div b{position:relative;top:1px;color:#cbd0db;opacity:1}.chosen-container-single .chosen-search:before{top:8px;right:15px}.chosen-container-multi .chosen-choices li.search-choice{font-size:13px;background:#eee;border-color:#cbd0db;-webkit-box-shadow:none;box-shadow:none}.chosen-container-single .chosen-search input[type=text]{height:30px;padding:3px 25px 3px 5px}.chosen-container-single .chosen-search{padding:3px 10px 0}.chosen-container-single .chosen-single{overflow:visible}.chosen-container .chosen-results{max-height:245px;padding:10px}.chosen-container .chosen-results>li{border-radius:4px}.chosen-container .chosen-results li.highlighted em{color:#fff}.table-responsive .chosen-container .chosen-results{max-height:200px}.chosen-compact.chosen-container-single .chosen-single>.chosen-search{top:-2px;right:-1px;bottom:-1px;left:-1px;display:none;height:auto;padding:0;opacity:0}.chosen-compact.chosen-container-single .chosen-single>.chosen-search>input{height:31px;padding:5px 26px 5px 8px;font-size:inherit;line-height:20px}.chosen-compact.chosen-container-single .chosen-single>.chosen-search:before{right:8px}.datetimepicker{padding:10px}.datetimepicker td.day.today{background-color:#f77}.datetimepicker td.day.active{background-color:#16a8f8}.datetimepicker tfoot th,.datetimepicker thead th{color:#838a9d}.input-control .colorpicker{top:0;z-index:auto;opacity:1}.input-control .colorpicker .btn{padding:5px}.input-control .input-control-icon-right.btn{top:0}.colorpicker .dropdown-menu{min-width:232px;padding:5px 10px 10px 10px}.colorpicker .dropdown-menu>li{display:block;float:left;padding:5px}.colorpicker .dropdown-menu>li.heading{width:100%;margin-bottom:5px;font-size:16px;font-weight:700;text-align:left}.colorpicker .dropdown-menu>li.heading>.icon-close{position:relative;top:4px;float:right;cursor:pointer;opacity:.6}.colorpicker .dropdown-menu>li>a{position:relative;display:block;width:100%;height:100%;padding:0;margin:0;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;text-align:center;text-transform:none;border:1px solid transparent;border-radius:50%;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.colorpicker .dropdown-menu>li>a:before{position:absolute;top:0;display:block;width:100%;height:20px;line-height:18px}.colorpicker .dropdown-menu>li>a:hover{-webkit-box-shadow:0 1px 4px rgba(0,0,0,.25);box-shadow:0 1px 4px rgba(0,0,0,.25)}.colorpicker .dropdown-menu>li>a.active:before{font-size:14px;content:"\e5ca"}.colorpicker .dropdown-menu>li>a.empty{color:#666;background:#fff}.colorpicker .dropdown-menu>li>a.empty:before{content:"\e90d"}.colorpicker .btn{position:relative}.colorpicker .btn .color-bar{position:absolute;right:5px;bottom:3px;left:5px;height:3px}.colorpicker .btn .color-bar[style*='background: ']+.ic{position:relative;top:-2px}.colorpicker .btn .ic{color:#cbd0db}.colorpicker .btn:hover .ic{color:#838a9d}.input-group .colorpicker{z-index:3}.input-group .chosen-container{display:table-cell}.input-group-addon{border-right-width:0;border-left-width:0}.input-group-addon:first-child{border-left-width:1px}.input-group-addon:last-child{border-right-width:1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin:0}.input-group-cell{display:table-cell;width:1%;padding:0 12px;white-space:nowrap;vertical-align:middle}.ke-container{border-color:#dcdcdc!important;border-radius:2px!important}.ke-container.focus{border-color:#0c64eb!important}.ke-toolbar{border-color:#dcdcdc!important}.required:after{top:6px;right:-10px;font-size:20px}td.required:after{top:12px;right:-5px}.input-group>.chosen-container.required:after,.input-group>.input-control.required:after{top:1px;right:1px;z-index:2}.input-group.required .required:after{display:none}.file-input{position:relative;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.file-input .input-group{width:auto}.file-input .input-group>.input-group-cell:first-child{padding-right:0;padding-left:7px}.file-input input[type=file]{position:absolute;width:0;height:0;opacity:0}.file-input .file-title{display:inline-block;max-width:400px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.file-input .file-editbox{min-width:200px;max-width:100%}.file-input .file-size{display:inline-block;vertical-align:middle}.edit .file-input-empty,.file-input-edit,.file-input-normal,.normal .file-input-empty{display:none}.edit .file-input-edit,.normal .file-input-normal{display:block}.edit .file-input-edit.input-group,.normal .file-input-normal.input-group{display:table}.edit .file-input-normal{display:none!important}.file-input-normal>.input-group-btn{width:auto}.input-group .chosen-container-active .chosen-choices{border-color:#0c64eb!important}.input-group .chosen-container{min-width:100px}.input-group .input-group-btn .btn>.icon{line-height:17px}.os-mac select.form-control{-webkit-appearance:none;background-image:url(data:image/gif;base64,R0lGODlhCQAFAIAAAMvQ2////yH5BAEAAAEALAAAAAAJAAUAAAIKhH+BGYoNGWxgFgA7);background-image:url(data:image/gif;base64,R0lGODlhBwAEAIAAAMvQ2////yH5BAEAAAEALAAAAAAHAAQAAAIIhA+BGWoNWSgAOw==);background-repeat:no-repeat;background-position:right 5px top 12px;-moz-appearance:none}input::-webkit-contacts-auto-fill-button{position:absolute;right:0;display:none!important;pointer-events:none;visibility:hidden}.chosen-choices.has-error,.chosen-single.has-error,.form-control.has-error{border-color:#ff5d5d!important;-webkit-box-shadow:0 0 6px #ffc3c3!important;box-shadow:0 0 6px #ffc3c3!important}.popover-success.popover-form-result{font-weight:700;color:#fff;background:#00da88}.popover-success.popover-form-result.popover.right .arrow:after{border-right-color:#00da88}textarea.kindeditor{padding:0!important}.form-unsaved{outline:2px solid #ff9800;-webkit-box-shadow:0 1px 12px #ff9800;box-shadow:0 1px 12px #ff9800;-webkit-transition:all .5s;-o-transition:all .5s;transition:all .5s}select[multiple].picker-select,select[multiple][data-toggle=picker]{max-height:32px;visibility:hidden}.picker-selection-remove:before{font-size:18px}.picker-user-option{position:relative;padding-left:40px}.picker-user-option>.avatar{position:absolute;top:5px;left:10px}.picker-user-option>.picker-option-text{display:inline-block;min-width:40px;font-weight:700}.picker-user-option>.dept-name,.picker-user-option>.role-name{display:inline-block;margin-left:10px;font-size:12px;opacity:.6}.picker-user-option>.dept-name{min-width:50px}#mainHeader{height:50px;color:#fff;background:-webkit-gradient(linear,right top,left top,from(#0a48d1),to(#1183fb));background:-webkit-linear-gradient(right,#0a48d1 0,#1183fb 100%);background:-o-linear-gradient(right,#0a48d1 0,#1183fb 100%);background:linear-gradient(-90deg,#0a48d1 0,#1183fb 100%);border-top-color:#0c64eb;border-bottom-color:#e9f2fb}#mainHeader>.container{min-width:1200px;padding:0}#heading{position:absolute;top:10px;left:20px}@media (min-width:1400px){#heading{left:40px}}#heading h1{float:left;max-width:250px;margin:0;overflow:hidden;font-size:20px;font-weight:400;line-height:30px;text-overflow:ellipsis;white-space:nowrap}#heading h1 a{color:inherit;text-decoration:inherit}#heading h1.long-name{position:relative;top:-5px;display:table-cell;font-size:16px;line-height:20px;word-break:break-all;white-space:normal}#heading>.btn{display:block;float:left;height:20px;padding:1px 5px;margin:0;margin:5px 0 0 10px;font-size:12px;font-weight:lighter;line-height:18px;background-color:rgba(255,255,255,.2);border:none}#heading>.btn:hover{background-color:rgba(0,0,0,.1)}#navbar{margin:0 auto;text-align:center}#navbar .nav{display:inline-block}#navbar .nav>li>a{padding:10px;line-height:30px;color:#fff;border-radius:0;opacity:.9}@media (max-width:1400px){#navbar .nav>li>a{padding:10px 8px}}#navbar .nav>li>a:focus,#navbar .nav>li>a:hover{background:rgba(0,0,0,.15);opacity:1}#navbar .nav>li.active>a{font-weight:700;background:rgba(0,0,0,.1);opacity:1}#navbar .nav>li.divider{display:block;width:2px;height:20px;margin:15px 8px;background:rgba(255,255,255,.4)}@media (max-width:1400px){#navbar .nav>li.divider{margin:15px 5px}}@media (max-width:1300px){#navbar .nav>li.divider{margin:15px 3px}}#navbar .nav>li.divider:last-child{display:none}#navbar .nav .dropdown-menu li>a{text-align:left}#toolbar{position:absolute;top:12px;right:20px;font-size:12px;color:#fff}@media (min-width:1400px){#toolbar{right:40px}}#extraNav{text-align:right}#extraNav>li{display:inline-block;float:none;text-align:left}#extraNav>li>a{display:block;padding:0;color:#fff;opacity:.75}#extraNav>li>a:hover{text-decoration:unset;background-color:rgba(0,0,0,.1);opacity:1}#extraNav>li.open>a{background-color:rgba(0,0,0,.1)}#extraNav>li+li{margin-left:10px}#showSearchGo{color:#fff;background:rgba(255,255,255,.1);border:1px solid rgba(255,255,255,.5)}#searchbox{position:relative;float:left;width:150px}#searchbox .input-group-btn .btn{position:relative;padding:1px 4px;font-size:12px;line-height:20px;color:#fff;background-color:rgba(255,255,255,.15);border-right:none;border-radius:2px}#searchbox .input-group-btn .btn:after{position:absolute;top:3px;right:0;bottom:3px;display:block;width:1px;content:' ';background-color:rgba(255,255,255,.15)}#searchbox .input-group-btn .btn:hover{background-color:rgba(255,255,255,.25)}#searchGo{position:absolute;top:0;right:-1px;z-index:9;min-width:24px;height:24px;padding:2px 3px;font-size:12px;line-height:20px;color:#fff;background-color:#16a8f8;border-radius:2px}#searchGo:hover{color:#fff!important;background-color:#0c64eb}#searchInput{height:24px;padding:2px 30px 2px 5px;color:#fff;text-align:left;background:rgba(255,255,255,.15);border-color:transparent;border-radius:0 12px 12px 0;-webkit-transition:background .2s,border .2s;-o-transition:background .2s,border .2s;transition:background .2s,border .2s}#searchInput:hover{background:rgba(255,255,255,.25)}#searchInput:focus{color:#333;background:#fff}#searchInput::-webkit-input-placeholder{font-size:12px;color:#fff;color:rgba(255,255,255,.5)}#searchInput::-moz-placeholder{font-size:12px;color:#fff;color:rgba(255,255,255,.5)}#searchInput:-ms-input-placeholder{font-size:12px;color:#fff;color:rgba(255,255,255,.5)}#searchInput::placeholder{font-size:12px;color:#fff;color:rgba(255,255,255,.5)}#searchInput:focus::-webkit-input-placeholder{color:#838a9d}#searchInput:focus::-moz-placeholder{color:#838a9d}#searchInput:focus:-ms-input-placeholder{color:#838a9d}#searchInput:focus::placeholder{color:#838a9d}#searchTypeMenu{min-width:220px}#searchTypeMenu>li{float:left;width:50%}#searchTypeMenu>li>a{margin:4px 0}#userNav .avatar{display:inline-block;vertical-align:middle}#userNav>li>a{padding:2px 6px;line-height:20px;color:#fff;opacity:.9}#userNav>li>a .user-name{max-width:100px;overflow:hidden;font-size:15px;text-overflow:ellipsis;white-space:nowrap}#userNav>li>a:hover{background-color:rgba(0,0,0,.1);opacity:1}#userNav>li>a:hover>i{opacity:1}#userNav>li>a span{vertical-align:middle}#userNav>li.open>a{background-color:rgba(0,0,0,.1)}#userNav>li.has-new-items>a{position:relative}#userNav>li.has-new-items>a:before{position:absolute;top:3px;right:-1px;display:block;width:4px;height:4px;content:' ';background-color:#ff5d5d;border-radius:50%}#userNav .dropdown-menu{min-width:150px}#userNav .dropdown-menu>li>a>.icon{position:absolute;top:10px;right:5px;display:block;width:20px;height:20px;line-height:20px;text-align:center}#userNav .user-profile-item>a{position:relative;padding-left:45px}#userNav .user-profile-item .avatar{position:absolute;top:6px;left:5px}#userNav .user-profile-name{font-size:16px}#userNav .user-profile-role{font-size:12px;color:#a9abb8}#userNav .no-role .user-profile-role{display:none}#userNav .no-role .user-profile-name{line-height:40px}#subHeader{min-height:50px;background:#fff}#subHeader>.container{padding:0 20px}@media (min-width:1400px){#subHeader>.container{padding:0 40px}}#pageNav{position:absolute;top:8px;left:0;left:20px}@media (min-width:1400px){#pageNav{left:40px}}#subNavbar{margin-top:5px;font-size:14px;text-align:center}#subNavbar .nav{display:inline-block}#subNavbar .nav>li>a{padding:8px 12px;line-height:24px;color:#3c495c}#subNavbar .nav>li>a:hover{color:#3c495c;background-color:rgba(0,0,0,.075)}#subNavbar .nav>li.active>a{font-weight:700;color:#0c64eb}#subNavbar .nav>li.divider{display:block;width:2px;height:20px;margin:9px 5px;background-color:rgba(0,0,0,.05)}#subNavbar .dropdown-menu{text-align:left}[lang=en] #subNavbar>.nav>li>a{padding-right:8px;padding-left:8px}#pageActions{position:absolute;top:9px;right:20px}@media (min-width:1400px){#pageActions{right:40px}}.cell{padding:10px;background-color:#fff;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045);box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045)}.cell+.cell{margin-top:10px}.cell>.panel{margin:0;-webkit-box-shadow:none;box-shadow:none}.cell>.panel>.panel-heading{padding:5px 5px 10px}.cell>.panel>.panel-heading .panel-actions{padding:0}.cell>.panel>.panel-body{padding:5px}.cell>.table{margin:0}#main{min-width:1200px;padding:20px 0}#main>.container{padding:0 20px}@media (min-width:1400px){#main>.container{padding:0 40px}}#header,#header+#main{min-width:1200px}#mainMenu{margin:-10px 0 8px}.main-content{padding:20px;background-color:#fff;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045);box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045)}@media (min-width:1400px){.main-content>.center-block{max-width:1350px;padding:20px;border:1px solid #eee}.main-content>.center-block .main-header{background-color:#f1f1f1}}.main-content>h2{margin:0 0 20px}.main-content .cell{-webkit-box-shadow:none;box-shadow:none}.main-header{padding:5px 20px;border-bottom:1px solid #eee}.main-header:after,.main-header:before{display:table;content:" "}.main-header:after{clear:both}.main-header>h2{display:block;float:left;margin:0 10px 0 0;font-size:14px;line-height:34px}.main-header>h2 .label-id{margin-right:5px}.main-header>h2 small{font-size:14px;font-weight:400}.main-content .main-header{margin:-20px -20px 10px}.main-header .label{top:-1px}.main-row{display:table;width:100%;table-layout:fixed}.main-row>[class*=" col-"],.main-row>[class*="-col"],.main-row>[class^=col-]{display:table-cell;vertical-align:top}@media (max-width:720px){.main-row{display:block}.main-row>*{display:block;width:100%}.main-row .side-col{width:100%;padding:0}.main-row .main-col+.side-col,.main-row .side-col+.main-col{margin-top:10px}}.main-row.hide-side .side-col{display:none}.main-form{margin:0}@media (min-width:720px){.main-content>.center-block .main-form{padding-right:20px}}#main .side-col .tabs{padding:5px}#main .side-col .nav-tabs{margin:0 5px 5px 5px}#main .side-col .nav-tabs>li{margin:0}#main .side-col .nav-tabs>li+li{margin-left:10px}#main .side-col .nav-tabs>li>a{padding:8px 5px}#main .side-col .tab-content .tab-pane table{border:none}.main-actions .btn-toolbar{display:inline-block;padding:4px 15px;color:#fff;pointer-events:auto;background:#717171;background-color:rgba(90,90,90,.85);border-radius:4px}.main-actions .btn-toolbar .divider{margin-right:15px;margin-left:15px;border-color:rgba(255,255,255,.1)}.main-actions .btn-toolbar .btn{height:30px;padding-right:10px;padding-left:10px;margin-right:0;color:#fff;background-color:transparent;border:none}.main-actions .btn-toolbar .btn+.btn{margin-left:10px}.main-actions .btn-toolbar .btn:focus,.main-actions .btn-toolbar .btn:hover{background-color:rgba(255,255,255,.2)}.main-actions .btn-toolbar .btn.btn-icon{min-width:32px;padding-right:0;padding-left:0}.main-actions .btn-toolbar .btn+.btn-group{margin-right:0;margin-left:10px}#mainContent .main-col>.main-actions{padding:30px 0 0 0;text-align:center}#mainContent .main-col>.main-actions>.btn-toolbar{visibility:visible;opacity:1;-webkit-transition:opacity .2s;-o-transition:opacity .2s;transition:opacity .2s}#mainActions{position:fixed;top:0;right:0;bottom:0;left:0;text-align:center;pointer-events:none}#mainActions .btn-toolbar{position:relative;top:-90px}#mainActions .dropdown-menu{text-align:left}#mainActions>.container{height:100%}.main-actions-holder{display:none}.main-actions-fixed .main-actions-holder{display:block}.main-actions-fixed #mainContent .main-col>.main-actions{position:fixed;bottom:10px}.main-actions-fixed.body-modal #mainContent .main-col>.main-actions{bottom:20px}#nextPage,#prevPage{position:absolute;top:50%;left:-10px;width:40px;height:60px;padding:10px 0;margin-top:-30px;line-height:40px;color:#fff;text-align:center;pointer-events:auto;background:#717171;background-color:rgba(90,90,90,.85);-webkit-box-shadow:0 2px 15px 2px rgba(0,0,0,.05);box-shadow:0 2px 15px 2px rgba(0,0,0,.05)}#nextPage:hover,#prevPage:hover{-webkit-box-shadow:0 2px 15px 2px rgba(0,0,0,.15);box-shadow:0 2px 15px 2px rgba(0,0,0,.15)}#nextPage>i,#prevPage>i{display:block;font-size:18px;line-height:36px}#nextPage{right:-10px;left:auto}@media (max-width:1800px){#prevPage{left:-3px}#nextPage{right:-3px}}#sidebarHeader{position:relative;float:left;width:180px;height:34px;padding-right:20px;margin-right:20px;background:#fff;border-left:4px solid #0c64eb;border-radius:4px 2px 2px 4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045);box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045)}#sidebarHeader:after{position:absolute;top:-1px;right:-8px;display:block;width:0;height:0;content:' ';border-color:transparent transparent transparent #fff;border-style:solid;border-width:18px 0 18px 8px}#sidebarHeader .title{padding:0 5px;overflow:hidden;font-size:14px;font-weight:700;line-height:32px;color:#0c64eb;text-align:center;text-overflow:ellipsis;white-space:nowrap}#sidebarHeader .title>a{position:absolute;top:0;right:0;width:20px;opacity:.5}#sidebarHeader .title>a:hover{opacity:1}#sidebar{position:relative;-webkit-transition:width .2s,padding .2s;-o-transition:width .2s,padding .2s;transition:width .2s,padding .2s}#sidebar>.sidebar-toggle{position:absolute;top:0;right:5px;bottom:0;width:10px;cursor:pointer;background:0 0;border-radius:5px;-webkit-transition:background-color .2s,opacity .5s;-o-transition:background-color .2s,opacity .5s;transition:background-color .2s,opacity .5s}#sidebar>.sidebar-toggle>.icon{position:absolute;top:50%;left:-1px;width:12px;height:30px;margin-top:-10px;line-height:30px;color:#fff;text-align:center;background:#79cdfb;border-radius:6px}#sidebar>.sidebar-toggle>.icon:before{position:relative;left:-1px}#sidebar>.sidebar-toggle:before{position:absolute;top:0;right:-5px;bottom:0;left:-5px;display:block;content:' '}#sidebar>.sidebar-toggle:hover{background:rgba(0,0,0,.075)}#sidebar>.cell{position:relative;left:0;width:180px;-webkit-transition:left .2s,opacity .2s;-o-transition:left .2s,opacity .2s;transition:left .2s,opacity .2s}#sidebar.no-animate>.cell{display:none;-webkit-transition:none;-o-transition:none;transition:none}.hide-sidebar #sidebar>.cell{position:absolute;left:-200px;visibility:hidden;opacity:0}.hide-sidebar #sidebar{position:relative;width:0;padding:0}.hide-sidebar #sidebar>.sidebar-toggle>.icon:before{content:"\e315"}@media (max-width:720px){#sidebar>.cell{width:100%}}#queryBox{max-height:0;padding:0;overflow:hidden;-webkit-transition:cubic-bezier(.175,.885,.32,1) .2s;-o-transition:cubic-bezier(.175,.885,.32,1) .2s;transition:cubic-bezier(.175,.885,.32,1) .2s;-webkit-transition-property:padding,max-height,margin;-o-transition-property:padding,max-height,margin;transition-property:padding,max-height,margin}#queryBox>form{visibility:hidden;-webkit-transition:visibility .2s .2s;-o-transition:visibility .2s .2s;transition:visibility .2s .2s}#queryBox.loading{height:50px}#queryBox.show{min-height:110px;max-height:300px;margin-bottom:10px;overflow:visible}#queryBox.show>form{visibility:visible}#queryBox.divider{border-bottom:1px solid #eee}#main .querybox-toggle.querybox-opened{position:relative;color:#0c64eb;background:0 0;border:none}#main .querybox-toggle.querybox-opened:before{position:absolute;bottom:-14px;left:50%;width:0;height:0;content:' ';border-color:transparent transparent #fff transparent;border-style:solid;border-width:0 10px 10px 10px}#contentNav{padding:5px;background:#fff;border-bottom:1px solid #eee}#contentNav .nav>li>a{position:relative;padding:6px 10px;color:#838a9d}#contentNav .nav>li.active>a{font-weight:700;color:#0c64eb}#contentNav .nav>li.active>a:before{position:absolute;right:10px;bottom:3px;left:10px;display:block;height:2px;content:' ';background:#0c64eb}.body-modal{padding-bottom:0}.body-modal #main,.body-modal .container{min-width:0!important}.body-modal #main{padding:0}.body-modal .main-header{position:fixed;top:0;right:20px;left:20px;z-index:100;padding:13px 48px 13px 0;margin:0;background:#fff}.body-modal #mainContent{padding-top:70px}.body-modal .main-header>h2{max-width:100%;overflow:hidden;font-size:14px;text-overflow:ellipsis;white-space:nowrap}.body-modal .cell,.body-modal .main-content{-webkit-box-shadow:none;box-shadow:none}.body-modal #mainMenu{position:fixed;top:0;right:0;left:0;z-index:100;padding:12px 60px 12px 10px;margin:0;background:#fff}.body-modal #mainMenu>.btn-toolbar.pull-left.divider{display:none}.body-modal #mainMenu>.btn-toolbar{width:100%;margin-left:20px}.body-modal #mainMenu>.btn-toolbar>.divider:first-child{display:none}.body-modal #mainMenu>.btn-toolbar .page-title{width:100%;margin-left:0}.body-modal #mainMenu>.btn-toolbar .page-title>.text{position:relative;top:-2px;display:inline-block;max-width:85%;max-width:-webkit-calc(100% - 100px);max-width:calc(100% - 100px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.body-modal #mainMenu+#mainContent.main-row{padding:60px 10px 0}.body-modal #mainMenu+#mainContent.main-row .cell{border:1px solid #efefef;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045);box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045)}.body-modal #mainActions{top:auto}.body-modal #mainActions .btn-toolbar{top:auto;bottom:10px}.body-modal.m-bug-view,.body-modal.m-story-view,.body-modal.m-task-view,.body-modal.m-testcase-view,.body-modal.m-testtask-view,.body-modal.m-todo-view{padding-bottom:20px;border-radius:3px}#tabsNav{position:relative}#tabsNav .tab-pane>.actions{position:absolute;top:-8px;right:0}#tabsNav .tab-pane>.cell,#tabsNav .tab-pane>.main-table{padding:0;border:1px solid #cbd0db;border-top:none;border-radius:0 0 4px 4px}#tabsNav .tab-pane>.cell .detail-title{padding-left:5px}#helpContent{position:fixed;top:50px;right:0;bottom:40px;left:0;display:none;background-color:#fff}#helpContent .load-error{display:none;padding:20px}#helpContent .show-error .load-error{display:block}.text-middle td,.text-middle th{vertical-align:middle}.text-center td,.text-center th{text-align:center}.c-sm{width:40px}.c-id{width:90px}.c-id-sm{width:70px}.c-id-xs{width:55px}.c-date{width:100px}.c-num,.c-pri,.c-type{width:80px;overflow:hidden}.c-begin,.c-end,.c-time{width:65px}.c-hours{width:60px}.c-actions-1{width:50px}.c-actions-2{width:75px}.c-actions-3{width:102px}.c-actions,.c-actions-4{width:128px}.c-actions-5{width:155px}.c-actions-6{width:180px}.c-product,.c-project{width:180px}.c-plan{width:130px}.c-datetime{width:120px}.c-stage,.c-status,.c-user{width:80px}.c-side{width:200px;border-right:10px solid #efefef}.c-assign,.c-assignedTo,.c-openedBy{width:130px}.c-progress{width:155px}.c-assign,.c-assignedTo,.c-openedBy,.c-product,.c-project,.c-status,.c-url,.c-user{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}td.c-name,td.c-title{overflow:hidden;text-align:left!important;text-overflow:ellipsis;white-space:nowrap}td.c-actions{position:relative;padding-top:0;padding-bottom:0;overflow:hidden;white-space:nowrap;vertical-align:middle}td.c-actions .btn-link{color:#3c495c;background:0 0}td.c-actions .btn-link:hover{color:#0c64eb;background:#e9f2fb}td.c-actions .btn.disabled,td.c-actions .btn[disabled]{pointer-events:auto}td.c-actions .more{position:absolute;top:50%;right:100%;display:none;padding-right:4px;padding-left:20px;margin-top:-15px;margin-right:-6px;white-space:nowrap;background-color:#fafafa;-webkit-transition:opacity .3s,margin .3s;-o-transition:opacity .3s,margin .3s;transition:opacity .3s,margin .3s}tr:hover td.c-actions .more{display:block}td:hover+td.c-actions>.more{margin-right:-15px;pointer-events:none;opacity:.15}tr[data-url]{cursor:pointer}.table tbody>tr>td,.table thead>tr>th{vertical-align:middle}.table tbody>tr>td.has-btn,.table thead>tr>th.has-btn{padding-top:1px;padding-bottom:1px;overflow:visible}.table tbody>tr>td .progress,.table thead>tr>th .progress{height:6px}.table .em,.table em{color:#3c4353}.table .divider{border-bottom:10px solid #efefef}.table .divider-top{border-top:10px solid #efefef}.table .btn-icon-left{max-width:100%;padding-left:20px;overflow:hidden;line-height:18px;text-align:left;text-overflow:ellipsis;background:0 0;border-color:#eaf3fc}.table .btn-icon-left>.icon{width:20px;font-size:14px;background:0 0!important;opacity:0}.table .btn-icon-left.btn-sm{height:26px;font-size:13px}.table .btn-icon-left:active,.table .btn-icon-left:focus,.table .btn-icon-left:hover{border-color:rgba(0,0,0,.2)}.table .btn-icon-left:active>.icon,.table .btn-icon-left:focus>.icon,.table .btn-icon-left:hover>.icon{opacity:1}.table .btn-icon-left>.text{padding-left:25px}.table thead>tr>th.c-assign,.table thead>tr>th.c-assignedTo{padding-left:29px}.table a{vertical-align:middle}.table tbody>tr:last-child{border-bottom:none}.table caption{margin-bottom:5px;background:#f1f1f1;border:none}.is-firefox .table .btn-icon-left>.icon{line-height:22px}.main-table{border-radius:4px}.main-table>.table,.main-table>.table-footer,.main-table>.table-header,.main-table>.table-responsive{-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045);box-shadow:0 1px 1px rgba(0,0,0,.05),0 2px 6px 0 rgba(0,0,0,.045)}.main-table .table{font-size:13px;table-layout:fixed;background-color:#fff;border-radius:4px 4px 0 0}.main-table .table.table-lg{font-size:14px}.main-table .table .btn-icon-left{border-color:transparent}.main-table .table .btn-icon-left>.icon{background:0 0;border-radius:4px}.main-table .table .btn-icon-left.btn-sm{height:26px}.main-table .table .btn-icon-left:hover{border-color:rgba(0,0,0,.2)}.main-table .table .btn-icon-left:hover>.icon{background:#e9f2fb;border-radius:4px 0 0 4px}.main-table tbody>tr>td,.main-table thead>tr>th{min-height:36px;padding:2px 8px;line-height:30px}.main-table tbody>tr>td:first-child,.main-table thead>tr>th:first-child{padding-right:4px;padding-left:15px}.main-table thead>tr>th{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;border-bottom:1px solid #ddd}.main-table tbody>tr:nth-child(odd){background-color:#f5f5f5}.main-table tbody>tr:last-child>td{border-bottom:1px solid #ddd}.main-table tbody>tr>td{position:relative;border-bottom:none;border-bottom:1px solid #eee}.main-table tbody>tr>td .label{max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.main-table tbody>tr>td>a{line-height:28px;color:#0c60e1}.main-table tbody>tr>td>a:not(.btn):visited{color:#082999;opacity:.9}.main-table tbody>tr>td>a:hover,.main-table tbody>tr>td>a:visited:hover{color:#0c64eb}.main-table tbody>tr>td.c-actions{padding-right:10px}.main-table tbody>tr>td.c-side+td:before,.main-table tbody>tr>td:first-child:before{position:absolute;top:0;bottom:0;left:0;display:block;width:0;content:'';background:#0c64eb;opacity:0;-webkit-transition:.2s linear;-o-transition:.2s linear;transition:.2s linear;-webkit-transition-property:width,opacity,border-radius;-o-transition-property:width,opacity,border-radius;transition-property:width,opacity,border-radius}@-moz-document url-prefix(){.main-table tbody>tr>td.c-side+td:before,.main-table tbody>tr>td:first-child:before{bottom:-1px}}.main-table tbody>tr>td.c-side:before{display:none}.main-table tbody>tr{-webkit-transition:.2s cubic-bezier(.175,.885,.32,1);-o-transition:.2s cubic-bezier(.175,.885,.32,1);transition:.2s cubic-bezier(.175,.885,.32,1);-webkit-transition-property:background-color,-webkit-box-shadow;-o-transition-property:box-shadow,background-color;transition-property:background-color,-webkit-box-shadow;transition-property:box-shadow,background-color;transition-property:box-shadow,background-color,-webkit-box-shadow}.main-table tbody>tr:hover{background:#e9f2fb}.main-table .table-grouped tbody>tr:hover{background:#f2f7fd;-webkit-box-shadow:none;box-shadow:none}.main-table .table-grouped tbody>tr:hover td.c-actions .more{background:#f2f7fd}.main-table tbody>tr.checked{background:#fff3e0}.main-table tbody>tr.checked:hover{background:#ffebbc}.main-table tbody>tr.checked>td.c-side+td:before,.main-table tbody>tr.checked>td:first-child:before{width:4px;opacity:1}.main-table tbody>tr.checked.row-check-begin{border-top-left-radius:4px;border-top-right-radius:2px}.main-table tbody>tr.checked.row-check-begin>td:first-child:before{border-top-left-radius:4px}.main-table tbody>tr.checked.row-check-end{border-bottom-right-radius:2px;border-bottom-left-radius:4px}.main-table tbody>tr.checked.row-check-end>td:first-child:before{border-bottom-left-radius:4px}.main-table .checkbox-primary{display:inline-block;line-height:20px}.main-table .checkbox-primary label{margin:0}.main-table .table{margin:0}.table-header{padding:4px 0 12px}.table-header .table-statistic{color:#838a9d}.table-header .table-statistic strong{font-size:15px;color:#3c4353}.table-header .btn-toolbar{margin-top:-28px}.table-header.fixed-right{position:relative;z-index:5;padding:0}.table-header.fixed-right>.btn-toolbar{position:absolute;top:0;right:1px;z-index:1;padding:1px;margin:0;background:#fff;border-radius:4px}.table-header.fixed-right>.btn-toolbar .btn{opacity:.65}.table-header.fixed-right>.btn-toolbar .btn:hover{opacity:1}.table-header-fixed .table-header{position:fixed;top:0}.table-header-fixed .table-header>.btn-toolbar{background-color:transparent}.table-header-fixed .table-header>.btn-toolbar .btn{color:#fff}.table-footer{position:relative;min-height:40px;padding:6px 15px;background:#fff;border-radius:0 0 4px 4px}.body-modal .table-footer{margin-bottom:20px}.talbe-lg+.table-footer{padding:11px 15px}.table-footer .btn-toolbar,.table-footer .checkbox-primary{float:left}.table-footer .btn-toolbar+.btn-toolbar{margin-left:8px}.table-footer .checkbox-primary{margin:5px 20px 0 0}.table-footer .checkbox-primary.checked label:after{border-color:#00da88!important}.table-footer .btn{padding:3px 10px;line-height:20px}.table-footer .pager{position:absolute;top:0;right:0;z-index:5;height:40px;padding:6px 5px 6px 10px;margin:0;background:#fff;opacity:1;-webkit-transition:opacity .4s;-o-transition:opacity .4s;transition:opacity .4s}.table-footer .pager:before{position:absolute;top:0;bottom:0;left:-50px;display:block;width:50px;content:' ';background:-webkit-gradient(linear,left top,right top,from(rgba(255,255,255,0)),to(#fff));background:-webkit-linear-gradient(left,rgba(255,255,255,0) 0,#fff 100%);background:-o-linear-gradient(left,rgba(255,255,255,0) 0,#fff 100%);background:linear-gradient(to right,rgba(255,255,255,0) 0,#fff 100%)}.table-footer .pager .btn,.table-footer .pager>li>.pager-item,.table-footer .pager>li>.pager-label{color:#838a9d;background:0 0;border-color:transparent}.table-footer .pager .btn,.table-footer .pager>li>a{border-radius:3px}.table-footer .pager .btn:hover,.table-footer .pager>li>a:hover{background:rgba(0,0,0,.1)}.table-footer .pager>li.disabled>a.pager-item{opacity:1}.table-footer .form-control{height:28px;padding:3px 8px}.table-footer .table-statistic{position:relative;z-index:2;float:left;padding-right:30px;line-height:28px;color:#838a9d;background:#fff}.table-footer .table-statistic:hover{z-index:4}.table-footer .table-statistic:hover+.pager{z-index:2;opacity:.3}.table-footer .btn-toolbar+.table-statistic,.table-footer .btn-toolbar+.text{margin-left:10px}.table-footer .text{float:left;line-height:28px}.table-footer.fixed-footer{position:fixed;z-index:10;margin:0;background:rgba(75,75,75,.85);border-top-color:transparent}.table-footer.fixed-footer .checkbox-primary label{color:#fff}.table-footer.fixed-footer .checkbox-primary label:after{border-color:rgba(255,255,255,.8)}.table-footer.fixed-footer .table-statistic{color:#fff;background:0 0}.table-footer.fixed-footer .pager{background:#666}.table-footer.fixed-footer .pager:before{background:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,0)),to(#666));background:-webkit-linear-gradient(left,rgba(0,0,0,0) 0,#666 100%);background:-o-linear-gradient(left,rgba(0,0,0,0) 0,#666 100%);background:linear-gradient(to right,rgba(0,0,0,0) 0,#666 100%)}.table-footer.fixed-footer .pager .btn,.table-footer.fixed-footer .pager>li>.pager-item,.table-footer.fixed-footer .pager>li>.pager-label{color:#fff}.table-footer.fixed-footer .pager .btn:hover,.table-footer.fixed-footer .pager>li>a:hover{background:rgba(255,255,255,.3)}.table-footer.fixed-footer .pager>li.disabled>a.pager-item{opacity:.5}.table-actions{display:none;height:28px}.table-actions.show-always{display:block;pointer-events:none;cursor:not-allowed}.has-row-checked .table-actions{display:block;pointer-events:auto!important;cursor:default}.table-lg tbody>tr>td{padding:9px 10px}.table-lg tbody>tr>td .btn+.btn{margin-left:5px}.table.has-sort-head thead>tr>th{padding-right:0}.table.has-sort-head thead>tr>th>a{position:relative;display:inline-block;padding-right:16px;color:#3c4353}.table.has-sort-head thead>tr>th>a:after,.table.has-sort-head thead>tr>th>a:before{position:absolute;top:0;right:0;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;line-height:30px;color:#3c495c;text-transform:none;content:"\f0de";opacity:.5;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.table.has-sort-head thead>tr>th>a:after{content:"\f0dd"}.table.has-sort-head thead>tr>th>a.sort-down,.table.has-sort-head thead>tr>th>a.sort-up{color:#000;text-decoration:none}.table.has-sort-head thead>tr>th>a:hover,.table.has-sort-head thead>tr>th>a:hover:after,.table.has-sort-head thead>tr>th>a:hover:before{color:#0c64eb;opacity:1}.table.has-sort-head thead>tr>th>a.sort-down:after,.table.has-sort-head thead>tr>th>a.sort-up:before{color:#000;opacity:1}.head-fixed .datatable-head-span .table,.table.fixed-header-copy{z-index:10;color:#fff;background:rgba(75,75,75,.85)}.head-fixed .datatable-head-span .table thead>tr>th,.table.fixed-header-copy thead>tr>th{color:#eee}.head-fixed .datatable-head-span .table thead>tr>th>a,.table.fixed-header-copy thead>tr>th>a{color:#eee}.head-fixed .datatable-head-span .table thead>tr>th>a:hover,.table.fixed-header-copy thead>tr>th>a:hover{color:#fff}.head-fixed .datatable-head-span .table thead>tr>th>a:after,.head-fixed .datatable-head-span .table thead>tr>th>a:before,.table.fixed-header-copy thead>tr>th>a:after,.table.fixed-header-copy thead>tr>th>a:before{color:#eee}.head-fixed .datatable-head-span .table thead>tr>th>a.sort-down,.head-fixed .datatable-head-span .table thead>tr>th>a.sort-down:after,.head-fixed .datatable-head-span .table thead>tr>th>a.sort-up,.head-fixed .datatable-head-span .table thead>tr>th>a.sort-up:before,.head-fixed .datatable-head-span .table thead>tr>th>a:hover,.head-fixed .datatable-head-span .table thead>tr>th>a:hover:after,.head-fixed .datatable-head-span .table thead>tr>th>a:hover:before,.table.fixed-header-copy thead>tr>th>a.sort-down,.table.fixed-header-copy thead>tr>th>a.sort-down:after,.table.fixed-header-copy thead>tr>th>a.sort-up,.table.fixed-header-copy thead>tr>th>a.sort-up:before,.table.fixed-header-copy thead>tr>th>a:hover,.table.fixed-header-copy thead>tr>th>a:hover:after,.table.fixed-header-copy thead>tr>th>a:hover:before{color:#fff}.head-fixed .datatable-head-span .table thead>tr>th>.dropdown>a,.table.fixed-header-copy thead>tr>th>.dropdown>a{color:#eee}.head-fixed .datatable-head-span .table thead>tr>th>.dropdown>a:hover,.table.fixed-header-copy thead>tr>th>.dropdown>a:hover{color:#fff}.head-fixed .datatable-head-span .table .checkbox-primary,.table.fixed-header-copy .checkbox-primary{z-index:1}.head-fixed .datatable-head-span .table .checkbox-primary label,.table.fixed-header-copy .checkbox-primary label{color:#fff}.head-fixed .datatable-head-span .table .checkbox-primary label:after,.table.fixed-header-copy .checkbox-primary label:after{border-color:rgba(255,255,255,.8)}.head-fixed .datatable-head-span .table .checkbox-primary.checked label:after,.table.fixed-header-copy .checkbox-primary.checked label:after{border-color:#00da88!important}.table-data{margin:0;table-layout:fixed}.table-data tbody>tr>td,.table-data tbody>tr>th{padding:6px 8px;word-break:break-all;border:none}.table-data tbody>tr>th{width:70px;padding-left:0;font-weight:400;color:#838a9d;text-align:right;vertical-align:middle}.table-data tbody>tr>td{padding-right:0}.table-data tbody>tr>td>a{color:#0c60e1}.table-data tbody>tr>td>a:not(.btn):visited{color:#082999}.table-data tbody>tr>td>a:hover,.table-data tbody>tr>td>a:visited:hover{color:#0c64eb}.table-data ol,.table-data ul{margin:0}.fixed-head-table{background:rgba(0,0,0,.7);border-bottom:1px solid #ddd}.fixed-head-table thead>tr>th{color:#fff}.table-empty-tip{padding:80px 10px;text-align:center;background:#fff}.not-firefox .table-grouped>tbody>tr>td.c-side{background:#fff!important}.table-grouped .group-toggle{cursor:pointer}.table-grouped .group-toggle.group-summary{border-top:10px solid #efefef}.table-grouped tbody>tr>td:first-child,.table-grouped thead>tr>th:first-child{padding-left:8px}.group-expand-all,.table-group-collapsed .group-collapse-all{display:none}.table-group-collapsed .group-expand-all{display:inline-block}.table-auto{table-layout:auto}.datatable .table>tbody>tr.checked.hover>td,.datatable .table>tbody>tr.checked>td.col-hover{background:#ffebbc}body.has-fixed-footer{padding-bottom:60px}.table.with-footer-fixed{margin-bottom:20px}.table-nest-hide{display:none!important}th.table-nest-title{position:relative;padding-left:30px!important}.table-nest-icon{position:relative;display:inline-block;width:22px;height:22px;font-size:16px;color:#a6aab8;text-align:center;border-radius:4px}.table-nest-toggle:before{line-height:22px;content:"\e6f2"}.table-nest-toggle:hover{color:#0c64eb;background-color:rgba(0,0,0,.1)}.table-nest-child-hide .table-nest-toggle:before{font-size:16px;content:"\e6f1"}th.table-nest-title .table-nest-toggle{position:absolute!important;top:7px;left:8px}.table-nest-toggle.table-nest-toggle-global{width:22px;height:22px;padding:0!important;line-height:22px;text-align:center;border-radius:4px}.table-nest-toggle.table-nest-toggle-global:before{position:static!important;font-size:16px!important;line-height:22px!important;content:"\e6f2"!important;opacity:1!important}.table-nest-toggle.table-nest-toggle-global:after{display:none!important}.table-nest-collapsed .table-nest-toggle.table-nest-toggle-global:before{font-size:16px!important;content:"\e6f1"!important}.disable-empty-nest-row .is-nest-child .table-nest-icon:before,.disable-empty-nest-row .no-nest .table-nest-icon:before{position:relative;top:-1px;width:6px;min-width:6px;height:6px;content:' ';background-color:#cbd0db;border-radius:1px}.table-nest-child-hover>td:first-child,.table-nest-hover>td:first-child{-webkit-box-shadow:inset 3px 0 0 #cbd0db;box-shadow:inset 3px 0 0 #cbd0db}.article-content{overflow:auto}.article-content img{margin-top:0}.article-content table{margin:10px 0}.article-content table td,.article-content table th{border:1px solid #cbd0db}.article-content table th{background:#eee}.article-content a{color:#0c64eb}.article-content a:focus,.article-content a:hover{color:#16a8f8}.article-content,.article>.content{word-wrap:break-word}.detail{padding:10px 0;margin:0 10px}.detail+.detail{padding-top:25px;border-top:1px solid #eee}.detail-title{font-size:14px;font-weight:700;line-height:20px}.detail-title>.pull-right{position:relative;top:-8px}h2.detail-title{margin:0;font-size:15px;font-weight:700}h2.detail-title .label,h2.detail-title .label-id{position:relative;top:-1px}.detail-content{padding:0;margin-top:10px}.detail-content em{color:#3c4353}.detail-content .list-unstyled>li+li{margin-top:5px}.side-col .detail-content{padding-left:0}details.detail{padding:10px 0}details.detail summary{position:relative;cursor:pointer;outline:0}details.detail summary::-webkit-details-marker{display:none}details.detail summary:after{position:absolute;top:0;right:0;font-family:ZentaoIcon;font-size:14px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;text-transform:none;content:"\e316";opacity:.4;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}details.detail[open] summary:after{content:"\e313"}.files-list{padding-left:0;list-style:none}.files-list>li>a{display:block;line-height:24px}.files-list>li>a>.icon{display:inline-block;margin-right:5px;opacity:.7}.files-list>li>a:hover{color:#0c64eb}.files-list>li>.right-icon{opacity:0;-webkit-transition:opacity .2s;-o-transition:opacity .2s;transition:opacity .2s}.files-list>li:hover>.right-icon{opacity:1}.histories-list{padding-left:15px;margin-bottom:0}.histories-list>li{position:relative}.histories-list>li+li{margin-top:5px}.histories-list>li strong{color:#3c4353}.histories-list .comment,.histories-list .show-form .comment-edit-form{padding:5px 5px 5px 10px;margin:5px 0 0;background-color:rgba(0,0,0,.025);border:1px solid #eee}.histories-list .btn-edit-comment{position:absolute;top:28px;right:2px}.histories-list .comment-edit-form,.histories-list .show-form .btn-edit-comment,.histories-list .show-form .comment{display:none}.histories-list .show-form .comment-edit-form{display:block;padding:10px;border:1px solid #eee}.histories .btn-mini{width:16px;min-width:16px;height:16px;overflow:hidden;line-height:16px;color:#cbd0db;vertical-align:-8%;border-radius:1px}.histories .btn-mini:focus,.histories .btn-mini:hover{color:#0c64eb;border-color:#0c64eb}.histories .show-changes .btn-expand>.icon:before{content:"\e926"}.histories .btn-strip{display:none}.histories .show-changes .btn-strip{display:inline-block}.history-changes{display:none;padding:5px;margin-bottom:-5px;margin-left:5px;font-size:12px;line-height:20px}.history-changes blockquote{padding:5px 5px 5px 10px;margin:5px 0 0;font-size:12px;background-color:rgba(0,0,0,.05);border-left:3px solid #eee}.history-changes blockquote.original{display:none}.show-changes .history-changes,.show-original .history-changes blockquote.original{display:block}.show-original .history-changes blockquote.textdiff{display:none}.syntaxhighlighter{overflow:auto}.list-group{overflow-y:auto}.list-group>a{display:block;padding:2px 10px 2px 5px;overflow:hidden;line-height:20px;text-overflow:ellipsis;white-space:nowrap;border-radius:4px}.list-group>a+a{margin-top:5px}.list-group>a>.icon{display:inline-block;margin-right:3px;opacity:.5}.list-group>a.selected{color:#e9f2fb;background-color:#0c64eb}.list-group>a.active{color:#0c64eb;background-color:#e9f2fb}.list-group>a.active:hover,.list-group>a:hover{color:#fff;background-color:#0c64eb}.list-group>.heading{padding:2px 5px;line-height:20px;color:#838a9d}.list-group>a+.heading{margin-top:4px}.dropup .search-box-sink{padding-top:5px;padding-bottom:45px}.dropup .search-box-sink .search-box{position:absolute;right:10px;bottom:10px;left:10px;margin:0}.dropup .search-box-sink .search-box+.list-group{height:auto;max-height:171px}.search-list{min-width:200px;max-width:300px;padding:0}.search-list .search-box{float:none;width:auto;margin:10px}.search-list .search-box .icon-search{opacity:.5}.search-list .list-group{max-height:248px;padding:5px 10px;margin:5px 0}.dropup .search-list .search-box+.list-group{height:171px;padding-top:0}.search-list .search-input{height:30px}.search-list .input-control-icon-right{height:28px;line-height:28px}.search-list .list-group>a.active{color:inherit;background-color:inherit}.search-list.searchbox-focus .list-group>a.active{color:#0c64eb;background-color:#e9f2fb}.search-list .list-group>a.active:hover,.search-list.searchbox-focus .list-group>a.active:hover{color:#fff;background-color:#0c64eb}#dropMenu{width:initial;max-width:initial}#dropMenu>.search-box{width:100%;padding:10px 10px 0;margin:0}#dropMenu>.search-box .icon-search{color:#333}#dropMenu>.search-box.has-icon-right>.form-control{padding-left:26px}#dropMenu .input-control-icon-left{top:10px;left:10px}#dropMenu .input-control-icon-right{top:11px;right:11px}#dropMenu .input-control-icon-right .icon{position:relative;top:2px}#dropMenu .list-group{max-height:initial;margin:0}#dropMenu .table-row{margin:0 -10px;table-layout:auto}#dropMenu .table-col{position:relative;width:100%;min-width:250px;max-width:450px}#dropMenu .table-col .list-group{max-height:300px;padding:0 10px 5px}#dropMenu .col-left{padding-bottom:30px}#dropMenu .col-right{display:none}#dropMenu .col-footer{position:absolute;right:0;bottom:-5px;left:0;padding:8px 10px;border-top:1px solid #eee}#dropMenu .col-footer>a{opacity:.8}#dropMenu .col-footer>a:hover{opacity:1}#dropMenu.show-right-col .table-col{width:50%}#dropMenu.show-right-col .col-right{display:table-cell;border-left:1px solid #eee}#dropMenu.show-right-col .col-right>.list-group{max-height:335px;margin:0}#dropMenu.show-right-col .col-right>.list-group>a{opacity:.7}#dropMenu.show-right-col .col-right>.list-group>a:hover{opacity:1}#dropMenu.show-right-col .toggle-right-col>.icon-angle-right:before{content:"\e314"}#dropMenu.has-search-text .list-group{overflow-x:hidden}#dropMenu.has-search-text>.search-box{width:100%!important}#dropMenu.has-search-text>.list-group>.table-row{display:block}#dropMenu.has-search-text>.list-group>.table-row>.table-col{display:block;width:100%}#dropMenu.has-search-text .col-left{padding-bottom:0}#dropMenu.has-search-text .pull-right.toggle-right-col{display:none}#dropMenu.has-search-text .col-left .list-group{margin-bottom:0}#dropMenu.has-search-text .col-right .list-group{margin-bottom:0}#dropMenu.has-search-text .col-right .list-group>a{opacity:.7}#dropMenu.has-search-text .col-footer,#dropMenu.has-search-text .hide-in-search{display:none}#swapper{position:relative}#swapper #dropMenu .tree li>.selected{color:#0c64eb!important;background:#e9f2fb!important}#swapper #dropMenu .list-group>a.active:hover,#swapper #dropMenu .search-box .list-group>a.active,#swapper #dropMenu .tree li>.clickable:hover,#swapper #dropMenu.searchbox-focus .list-group>a.active:hover{color:#fff!important;background:#0c64eb!important}#swapper #dropMenu .tree{margin:0}.release-path{overflow:hidden}.release-line{display:table;width:100%;padding:0;table-layout:fixed}.release-line>li{display:table-cell;list-style:none}.release-line>li>a{position:relative;display:block}.release-line>li>a:before{position:absolute;left:0;display:block;width:13px;height:13px;content:' ';background:#fff;border:2px solid #838a9d;border-radius:50%}.release-line>li>a:after{position:absolute;left:5px;display:block;width:2px;height:30px;content:' ';background:#cbe0f6}.release-line>li>a>.icon{position:absolute;left:4px;font-size:24px}.release-line>li>a .title{display:block;font-size:14px;white-space:nowrap}.release-line>li>a .date,.release-line>li>a .info{display:block;max-height:18px;overflow:hidden;font-size:12px;color:#838a9d;text-overflow:ellipsis;white-space:nowrap}.release-line>li>a:hover:before{background-color:#e9f2fb}.release-line>li>a:hover:after{background-color:#838a9d}.release-line>li>a:hover .title{color:#0c64eb}.release-line>li>a:hover .date,.release-line>li>a:hover .info{color:#838a9d}.release-line>li:nth-child(odd){padding-top:80px;vertical-align:top}.release-line>li:nth-child(odd)>a{height:85px;padding-top:36px;border-top:5px solid #cbe0f6}.release-line>li:nth-child(odd)>a:before{top:-9px}.release-line>li:nth-child(odd)>a:after{top:6px}.release-line>li:nth-child(odd)>a>.icon{top:-26px}.release-line>li:nth-child(even){padding-bottom:80px;vertical-align:bottom}.release-line>li:nth-child(even)>a{height:85px;padding-bottom:36px;border-bottom:5px solid #cbe0f6}.release-line>li:nth-child(even)>a:before{bottom:-9px}.release-line>li:nth-child(even)>a:after{bottom:6px}.release-line>li:nth-child(even)>a>.icon{bottom:-2px}.release-line>li:last-child>a{border-color:transparent}.release-line>li.active>a:before{border-color:#0c64eb}.release-line>li+li>a>.date,.release-line>li+li>a>.info,.release-line>li+li>a>.title{position:relative;left:-36%}#footer{position:fixed;right:0;bottom:0;left:0;z-index:1010;height:40px;background:#fff;border-top:1px solid #eff1f7}#footer .breadcrumb{padding:10px 0;margin:0}#footer .breadcrumb>li{max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#footer .breadcrumb>.active,#footer .breadcrumb>li>a{color:#838a9e}#footer .breadcrumb>.active>.icon,#footer .breadcrumb>li>a>.icon{display:none}#footer .breadcrumb>.active:hover,#footer .breadcrumb>li>a:hover{color:#16a8f8}#footer .breadcrumb>li+li:before{content:'>'}#footer>.container{padding:0 20px}@media (min-width:1400px){#footer>.container{padding:0 40px}}#poweredBy{position:absolute;top:4px;right:0;padding:5px 10px}#poweredBy .icon-zentao{color:#0097fd}#poweredBy a{color:#3c4353}#poweredBy a:hover{color:#0c64eb}#poweredBy a:hover .icon-zentao{color:#0c64eb}#poweredBy a.text-important{color:#bd7b46}#poweredBy a.text-important:hover{color:#ff5d5d}#poweredBy a.text-primary{color:#0c64eb}#poweredBy a.text-primary:hover{color:#16a8f8}#poweredBy #aiux{color:#cbd0dc}#noticeBox .alert{-webkit-box-shadow:rgba(0,0,0,.15) 0 3px 10px,rgba(0,0,0,.25) 0 3px 10px;box-shadow:rgba(0,0,0,.15) 0 3px 10px,rgba(0,0,0,.25) 0 3px 10px}#heading{top:0}.header-btn{position:relative;padding:8px 0}.header-btn .btn{position:relative;height:34px;padding:1px 6px;margin:0;overflow:visible;font-size:13px;font-weight:400;line-height:28px;color:#fff;background-color:transparent;border-color:transparent!important;border-right:none;-webkit-transition:none;-o-transition:none;transition:none}.header-btn .btn>.caret{margin-left:0;border-width:4px}.header-btn .btn>.text{display:inline-block;max-width:150px;overflow:hidden;text-overflow:ellipsis;vertical-align:middle}.header-btn .btn:hover{-webkit-box-shadow:none;box-shadow:none}.header-btn .btn:hover,.header-btn.active .btn{color:#fff;background:rgba(0,0,0,.15)}.header-btn .btn:hover>.caret,.header-btn.active .btn>.caret{opacity:1}.header-btn+.header-btn{margin-left:10px}.header-btn+.header-btn:before{position:absolute;top:16px;left:-13px;display:block;font-family:ZentaoIcon;font-size:14px;font-size:16px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;text-transform:none;content:"\e315";opacity:.6;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.header-btn .dropdown-menu{margin-top:-10px}#toolbar{top:0;height:50px}#userNav>li{margin-right:0}#userNav>li>a{padding:10px 5px}#userNav>li>a>.icon{font-size:30px;filter:brightness(1.2) hue-rotate(30deg);opacity:.9;-webkit-filter:brightness(1.2) hue-rotate(30deg)}#userNav>li:hover>a{background-color:rgba(0,0,0,.1)}#userNav .dropdown-menu>li>a{position:relative;padding-left:24px}#userNav .dropdown-menu>li>a>.icon{top:1px;left:0}#userNav .dropdown-menu>li.user-profile-item>a{padding-left:45px} \ No newline at end of file diff --git a/www/theme/zui/fonts/ZentaoIcon.eot b/www/theme/zui/fonts/ZentaoIcon.eot index a218205266..ca3c22f3f3 100644 Binary files a/www/theme/zui/fonts/ZentaoIcon.eot and b/www/theme/zui/fonts/ZentaoIcon.eot differ diff --git a/www/theme/zui/fonts/ZentaoIcon.svg b/www/theme/zui/fonts/ZentaoIcon.svg index 330852886d..9d60e3a7ef 100644 --- a/www/theme/zui/fonts/ZentaoIcon.svg +++ b/www/theme/zui/fonts/ZentaoIcon.svg @@ -1,276 +1,277 @@ - - - -Generated by IcoMoon - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + +Generated by IcoMoon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/www/theme/zui/fonts/ZentaoIcon.ttf b/www/theme/zui/fonts/ZentaoIcon.ttf index 563822fd63..041009540e 100644 Binary files a/www/theme/zui/fonts/ZentaoIcon.ttf and b/www/theme/zui/fonts/ZentaoIcon.ttf differ diff --git a/www/theme/zui/fonts/ZentaoIcon.woff b/www/theme/zui/fonts/ZentaoIcon.woff index 92b2904fc7..8fb9c224ad 100644 Binary files a/www/theme/zui/fonts/ZentaoIcon.woff and b/www/theme/zui/fonts/ZentaoIcon.woff differ diff --git a/xuanxuan/XUANVERSION b/xuanxuan/XUANVERSION index 3f8e85a56d..dffc266d6a 100644 --- a/xuanxuan/XUANVERSION +++ b/xuanxuan/XUANVERSION @@ -1 +1 @@ -v6.2.0-rc.3 +v6.3.0 diff --git a/xuanxuan/XVERSION b/xuanxuan/XVERSION index 0cda48ac61..0faee7d968 100644 --- a/xuanxuan/XVERSION +++ b/xuanxuan/XVERSION @@ -1 +1 @@ -6.2 +6.3