From ddb8a4037dff81bb1d7e2ec8b27fb6ccd377341b Mon Sep 17 00:00:00 2001 From: liumengyi Date: Tue, 11 Jan 2022 10:11:59 +0800 Subject: [PATCH 01/85] * Finish task #47340, #47341. --- module/execution/control.php | 30 ++++++++++++++++++++++++++- module/execution/view/create.html.php | 2 ++ module/execution/view/edit.html.php | 2 ++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/module/execution/control.php b/module/execution/control.php index a4f703d5b6..f7d23dd56e 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1264,10 +1264,25 @@ class execution extends control $project = $this->project->getByID($projectID); + if(!empty($projectID) and $project->model == 'kanban') + { + $this->lang->execution->createExec = str_replace($this->lang->execution->common, $this->lang->execution->kanban, $this->lang->execution->createExec); + $this->lang->execution->execName = str_replace($this->lang->execution->common, $this->lang->execution->kanban, $this->lang->execution->execName); + $this->lang->execution->execCode = str_replace($this->lang->execution->common, $this->lang->execution->kanban, $this->lang->execution->execCode); + $this->lang->execution->execDesc = str_replace($this->lang->execution->common, $this->lang->execution->kanban, $this->lang->execution->execDesc); + $this->lang->execution->copyExec = str_replace($this->lang->execution->common, $this->lang->execution->kanban, $this->lang->execution->copyExec); + $this->lang->execution->copy = str_replace($this->lang->executionCommon, $this->lang->execution->kanban, $this->lang->execution->copy); + $this->lang->execution->PM = str_replace($this->lang->executionCommon, $this->lang->execution->kanban, $this->lang->execution->PM); + $this->lang->execution->name = str_replace($this->lang->executionCommon, $this->lang->execution->kanban, $this->lang->execution->name); + $this->lang->execution->code = str_replace($this->lang->executionCommon, $this->lang->execution->kanban, $this->lang->execution->code); + $this->lang->execution->desc = str_replace($this->lang->executionCommon, $this->lang->execution->kanban, $this->lang->execution->desc); + $this->lang->execution->copyTeamTip = str_replace(array($this->lang->execution->common, $this->lang->executionCommon), $this->lang->execution->kanban, $this->lang->execution->copyTeamTip); + } + $extra = str_replace(array(',', ' '), array('&', ''), $extra); parse_str($extra, $output); - $this->app->loadLang('program'); + $this->app->loadlang('program'); $this->app->loadLang('stage'); $this->app->loadLang('programplan'); if($executionID) @@ -1289,6 +1304,7 @@ class execution extends control $this->view->tips = $this->fetch('execution', 'tips', "executionID=$executionID"); $this->view->executionID = $executionID; $this->view->projectID = $projectID; + $this->view->project = $project; $this->display(); exit; } @@ -1430,6 +1446,7 @@ class execution extends control $this->view->copyExecution = isset($copyExecution) ? $copyExecution : ''; $this->view->from = $this->app->tab; $this->view->isStage = (isset($project->model) and $project->model == 'waterfall') ? true : false; + $this->view->project = $project; $this->display(); } @@ -1512,6 +1529,16 @@ class execution extends control $execution = $this->execution->getById($executionID); $managers = $this->execution->getDefaultManagers($executionID); + $project = $this->project->getByID($execution->project); + if($project->model == 'kanban') + { + $this->lang->execution->edit = str_replace($this->lang->executionCommon, $this->lang->execution->kanban, $this->lang->execution->edit); + $this->lang->execution->name = str_replace($this->lang->executionCommon, $this->lang->execution->kanban, $this->lang->execution->name); + $this->lang->execution->code = str_replace($this->lang->executionCommon, $this->lang->execution->kanban, $this->lang->execution->code); + $this->lang->execution->desc = str_replace($this->lang->executionCommon, $this->lang->execution->kanban, $this->lang->execution->desc); + $this->lang->execution->status = str_replace($this->lang->executionCommon, $this->lang->execution->kanban, $this->lang->execution->status); + $this->lang->execution->PM = str_replace($this->lang->executionCommon, $this->lang->execution->kanban, $this->lang->execution->PM); + } /* Remove current execution from the executions. */ unset($executions[$executionID]); @@ -1584,6 +1611,7 @@ class execution extends control $this->view->multiBranchProducts = $this->product->getMultiBranchPairs(); $this->view->productPlans = $productPlans; $this->view->branchGroups = $this->execution->getBranchByProduct(array_keys($linkedProducts), $this->config->systemMode == 'new' ? $execution->project : 0, 'noclosed', $linkedBranchList); + $this->view->project = $project; $this->display(); } diff --git a/module/execution/view/create.html.php b/module/execution/view/create.html.php index 2fb95dbfc9..7cb8450541 100644 --- a/module/execution/view/create.html.php +++ b/module/execution/view/create.html.php @@ -88,6 +88,7 @@ + model != 'kanban'):?> systemMode == 'new')) ? $lang->execution->execType : $lang->execution->type;?> @@ -104,6 +105,7 @@
execution->typeDesc;?>
+ stage->percent;?> diff --git a/module/execution/view/edit.html.php b/module/execution/view/edit.html.php index dfd74c8305..68f911e281 100644 --- a/module/execution/view/edit.html.php +++ b/module/execution/view/edit.html.php @@ -66,6 +66,7 @@ + model != 'kanban'):?> execution->type;?> @@ -81,6 +82,7 @@ ?> + execution->teamname;?> team, "class='form-control'");?> From 203b97de5f32e7a6b976375dc285635084c7d11e Mon Sep 17 00:00:00 2001 From: liumengyi Date: Tue, 11 Jan 2022 10:14:49 +0800 Subject: [PATCH 02/85] * Finish task #47340. --- module/execution/view/create.html.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/execution/view/create.html.php b/module/execution/view/create.html.php index 7cb8450541..96203eba46 100644 --- a/module/execution/view/create.html.php +++ b/module/execution/view/create.html.php @@ -88,7 +88,7 @@ - model != 'kanban'):?> + model != 'kanban'):?> systemMode == 'new')) ? $lang->execution->execType : $lang->execution->type;?> From 759841b3a50767e908febc741075dbcb1b8e874b Mon Sep 17 00:00:00 2001 From: liumengyi Date: Tue, 11 Jan 2022 10:16:13 +0800 Subject: [PATCH 03/85] * Fix bug for create execution. --- module/execution/control.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/execution/control.php b/module/execution/control.php index f7d23dd56e..3d18fcf079 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1282,7 +1282,7 @@ class execution extends control $extra = str_replace(array(',', ' '), array('&', ''), $extra); parse_str($extra, $output); - $this->app->loadlang('program'); + $this->app->loadLang('program'); $this->app->loadLang('stage'); $this->app->loadLang('programplan'); if($executionID) From 54fc83b0fcebadb2265cea97c3ed8d099e17ac6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B9=BF=E6=98=8E?= Date: Tue, 11 Jan 2022 11:17:41 +0800 Subject: [PATCH 04/85] * Add execution kanban list. --- db/update16.1.sql | 15 +++++ db/zentao.sql | 13 ++++ module/common/lang/menu.php | 5 ++ module/common/model.php | 2 +- module/execution/model.php | 17 +++++ module/project/control.php | 12 +++- module/project/css/index.css | 24 +++++++ module/project/lang/en.php | 9 ++- module/project/lang/zh-cn.php | 9 ++- module/project/model.php | 4 +- module/project/view/ajaxgetdropmenu.html.php | 9 ++- module/project/view/createguide.html.php | 11 +++- module/project/view/index.html.php | 69 ++++++++++++++++++++ 13 files changed, 186 insertions(+), 13 deletions(-) create mode 100644 db/update16.1.sql create mode 100644 module/project/css/index.css diff --git a/db/update16.1.sql b/db/update16.1.sql new file mode 100644 index 0000000000..f759fffb73 --- /dev/null +++ b/db/update16.1.sql @@ -0,0 +1,15 @@ +CREATE TABLE `zt_kanbancardgroup` ( + `id` int(8) NOT NULL AUTO_INCREMENT, + `kanban` mediumint(8) NOT NULL, + `objectType` char(30) NOT NULL, + `objectID` mediumint(8) NOT NULL, + `lane` mediumint(8) NOT NULL, + `column` mediumint(8) NOT NULL, + `order` mediumint(8) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `card_group` (`kanban`,`objectType`,`objectID`,`lane`,`column`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +ALTER TABLE `zt_kanban` ADD `displayCards` smallint(6) NOT NULL AFTER `order`; +ALTER TABLE `zt_kanbancard` DROP COLUMN `lane`; +ALTER TABLE `zt_kanbancard` DROP COLUMN `column`; diff --git a/db/zentao.sql b/db/zentao.sql index c733278613..f687d2b7be 100644 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -677,6 +677,7 @@ CREATE TABLE `zt_kanban` ( `archived` enum('0', '1') NOT NULL DEFAULT '0', `status` enum('active','closed') NOT NULL default 'active', `order` mediumint(8) NOT NULL DEFAULT '0', + `displayCards` smallint(6) NOT NULL, `createdBy` char(30) NOT NULL, `createdDate` datetime NOT NULL, `lastEditedBy` char(30) NOT NULL, @@ -731,6 +732,18 @@ CREATE TABLE `zt_kanbancard` ( `deleted` enum('0', '1') NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; +-- DROP TABLE IF EXISTS `zt_kanbancardgroup`; +CREATE TABLE `zt_kanbancardgroup` ( + `id` int(8) NOT NULL AUTO_INCREMENT, + `kanban` mediumint(8) NOT NULL, + `objectType` char(30) NOT NULL, + `objectID` mediumint(8) NOT NULL, + `lane` mediumint(8) NOT NULL, + `column` mediumint(8) NOT NULL, + `order` mediumint(8) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `card_group` (`kanban`,`objectType`,`objectID`,`lane`,`column`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_kanbangroup`; CREATE TABLE `zt_kanbangroup` ( `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php index 3bf77d2863..95959733ca 100644 --- a/module/common/lang/menu.php +++ b/module/common/lang/menu.php @@ -289,6 +289,11 @@ $lang->waterfall->menu->design['subMenu']->dbds = array('link' => "{$lang->d $lang->waterfall->menu->design['subMenu']->ads = array('link' => "{$lang->design->ADS}|design|browse|projectID=%s&productID=0&browseType=ADS"); $lang->waterfall->menu->design['subMenu']->bysearch = array('link' => ' ' . $lang->searchAB . ''); +/* Kanban project menu. */ +$lang->kanban->menu = new stdclass(); +$lang->kanban->menuOrder = array(); +$lang->kanban->dividerMenu = ''; + /* Execution menu. */ $lang->execution->homeMenu = new stdclass(); $lang->execution->homeMenu->all = array('link' => "{$lang->execution->all}|execution|all|", 'alias' => 'batchedit'); diff --git a/module/common/model.php b/module/common/model.php index fe1993ad7a..814602a66d 100644 --- a/module/common/model.php +++ b/module/common/model.php @@ -528,7 +528,7 @@ class commonModel extends model $attr = "class='iframe' data-width='650px'"; break; case 'project': - if(isset($config->maxVersion) and!defined('TUTORIAL')) + if(!defined('TUTORIAL')) { $params = "programID=0©ProjectID=0&extra=from=global"; $createMethod = 'createGuide'; diff --git a/module/execution/model.php b/module/execution/model.php index 549b58d0d2..e6663c158b 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -2478,6 +2478,23 @@ class executionModel extends model ->fetchAll('account'); } + /** + * Get members by execution id list. + * + * @param array $executionIdList + * @access public + * @return void + */ + public function getMembersByIdList($executionIdList) + { + return $this->dao->select("t1.root, t1.account, t2.realname")->from(TABLE_TEAM)->alias('t1') + ->leftJoin(TABLE_USER)->alias('t2')->on('t1.account = t2.account') + ->where('t1.root')->in($executionIdList) + ->andWhere('t1.type')->eq('execution') + ->andWhere('t2.deleted')->eq('0') + ->fetchGroup('root'); + } + /** * Get the skip members of the team. * diff --git a/module/project/control.php b/module/project/control.php index fb5a0cfbce..2851aa5228 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -222,10 +222,11 @@ class project extends control * Project index view. * * @param int $projectID + * @param string $browseType * @access public * @return void */ - public function index($projectID = 0) + public function index($projectID = 0, $browseType = 'all') { $projectID = $this->project->saveState($projectID, $this->project->getPairsByProgram()); @@ -240,6 +241,15 @@ class project extends control if(!$projectID) $this->locate($this->createLink('project', 'browse')); setCookie("lastProject", $projectID, $this->config->cookieLife, $this->config->webRoot, '', false, true); + if($project->model == 'kanban') + { + $kanbanList = $this->loadModel('execution')->getList($projectID, 'all', $browseType); + $this->view->kanbanList = $kanbanList; + $this->view->browseType = $browseType; + $this->view->memberGroup = $this->execution->getMembersByIdList(array_keys($kanbanList)); + $this->view->usersAvatar = $this->loadModel('user')->getAvatarPairs(); + } + $this->view->title = $this->lang->project->common . $this->lang->colon . $this->lang->project->index; $this->view->position[] = $this->lang->project->index; $this->view->project = $project; diff --git a/module/project/css/index.css b/module/project/css/index.css new file mode 100644 index 0000000000..c32fcc5b4f --- /dev/null +++ b/module/project/css/index.css @@ -0,0 +1,24 @@ +#cards > .col {width: 25% !important;} +#cards .panel {margin: 0 0; border: 1px solid #DCDCDC; border-radius: 4px; box-shadow: none; cursor: pointer; height: 160px; margin-bottom: 5px;} +#cards .panel:hover {border-color: #006AF1; box-shadow: 0 0 10px 0 rgba(0,0,100,.25);} +#cards .panel-heading {padding: 4px 2px 10px 16px;} +#cards .kanban-name {overflow: hidden; white-space:nowrap; width: 88%; float: left; padding-top: 8px;} +#cards .panel .label-closed {background: #AAA !important; color: #FFF; margin-top:-1px !important;} +#cards .kanban-actions {float: right; visibility: hidden;} +#cards .kanban-actions .dropdown-menu.pull-right {top:31px; right: -84px; left: auto;} +#cards .kanban-actions .dropdown-menu.pull-left {top:31px; right:-1px; left: auto;} +#cards .panel .label-closed {background: #AAA !important; color: #FFF; margin-top:-6px;} +#cards .panel-body {padding: 0 16px 16px;} +#cards .kanban-desc {color: #838a9d; word-break:break-all; height: 70px; overflow: hidden; display: -webkit-box; float:left;} +#cards .kanban-footer {position: absolute; bottom: 10px; right: 10px; left: 15px;} +#cards .kanban-members {float: left; height: 24px; line-height: 24px;} +#cards .kanban-members > div {display: inline-block; height: 24px;} +#cards .kanban-members > div + div {margin-left: -5px;} +#cards .kanban-members > div > .avatar {display: inline-block; width: 24px; height: 24px; line-height: 24px; margin-right: 1px;} +#cards .kanban-members > span {display: inline-block; color: transparent; width: 2px; height: 2px; background-color: #8990a2; position: relative; border-radius: 50%; top: 3px; margin: 0 3px;} +#cards .kanban-members > span:before, +#cards .kanban-members > span:after {content: ''; display: block; position: absolute; width: 2px; height: 2px; background-color: #8990a2; top: 0; border-radius: 50%} +#cards .kanban-members > span:before {left: -4px;} +#cards .kanban-members > span:after {right: -4px;} +#cards .kanban-members-total {display: inline-block; margin-left: 6px; position: relative; top: 3px} +#cards .kanbanAcl {position: absolute; right: 0px; bottom: 2px; color: #838a9d;} diff --git a/module/project/lang/en.php b/module/project/lang/en.php index 2df5ddb34c..bcc353b63e 100644 --- a/module/project/lang/en.php +++ b/module/project/lang/en.php @@ -155,6 +155,8 @@ $lang->project->etc = " , etc"; $lang->project->product = 'Product'; $lang->project->branch = 'Branch'; $lang->project->plan = 'Plan'; +$lang->project->kanban = 'Kanban'; +$lang->project->createKanban = 'Create Kanban'; /* Project Kanban. */ $lang->project->typeList = array(); @@ -220,6 +222,7 @@ $lang->project->currencySymbol['SGD'] = 'S$'; $lang->project->modelList['scrum'] = "Scrum"; $lang->project->modelList['waterfall'] = "CMMI"; +$lang->project->modelList['kanban'] = "Kanban"; $lang->project->featureBar['all'] = 'All'; $lang->project->featureBar['doing'] = 'Going'; @@ -252,6 +255,10 @@ $lang->project->endList[186] = 'Half yearly'; $lang->project->endList[365] = 'One year'; $lang->project->endList[999] = 'Longtime'; +$lang->project->scrumTitle = 'Agile Development Management'; +$lang->project->waterfallTitle = 'Waterfall Project Management'; +$lang->project->kanbanTitle = 'Kanban Project Management'; + $lang->project->empty = 'No project.'; $lang->project->nextStep = 'Next step'; $lang->project->hoursUnit = '%s hours'; @@ -260,7 +267,6 @@ $lang->project->lastIteration = "Recent {$lang->executionCommon}"; $lang->project->ongoingStage = 'Ongoing stage'; $lang->project->scrum = 'Scrum'; $lang->project->waterfall = 'Waterfall'; -$lang->project->waterfallTitle = 'Waterfall Project Management'; $lang->project->cannotCreateChild = 'It is not empty, so you cannot add a child. You can add a parent for it, and then create a child.'; $lang->project->confirmDelete = "Do you want to delete [%s]?"; $lang->project->emptyPM = 'No manager'; @@ -278,7 +284,6 @@ $lang->project->programTitle['end'] = 'End-level project only'; $lang->project->accessDenied = 'Access denied to this project'; $lang->project->chooseProgramType = 'Select management type'; -$lang->project->scrumTitle = 'Agile Development Management'; $lang->project->cannotCreateChild = 'The project has contents, so you cannot add a child project. You can create a parent project for this one and then add a child project for the parent project.'; $lang->project->hasChildren = 'This project has a child project, so it cannot be deleted.'; $lang->project->confirmDelete = 'Do you want to delete this project?'; diff --git a/module/project/lang/zh-cn.php b/module/project/lang/zh-cn.php index 643d7f02d8..c0e8a48e9b 100644 --- a/module/project/lang/zh-cn.php +++ b/module/project/lang/zh-cn.php @@ -155,6 +155,8 @@ $lang->project->etc = "等"; $lang->project->product = '所属产品'; $lang->project->branch = '所属分支'; $lang->project->plan = '所属计划'; +$lang->project->createKanban = '创建看板'; +$lang->project->kanban = '看板'; /* Project Kanban. */ $lang->project->typeList = array(); @@ -220,6 +222,7 @@ $lang->project->currencySymbol['SGD'] = 'S$'; $lang->project->modelList['scrum'] = "Scrum"; $lang->project->modelList['waterfall'] = "瀑布"; +$lang->project->modelList['kanban'] = "看板"; $lang->project->featureBar['all'] = '所有'; $lang->project->featureBar['doing'] = '进行中'; @@ -252,6 +255,10 @@ $lang->project->endList[186] = '半年'; $lang->project->endList[365] = '一年'; $lang->project->endList[999] = '长期'; +$lang->project->scrumTitle = '敏捷开发全流程项目管理'; +$lang->project->waterfallTitle = '瀑布式项目管理'; +$lang->project->kanbanTitle = '专业研发看板项目管理'; + $lang->project->empty = '暂时没有项目'; $lang->project->nextStep = '下一步'; $lang->project->hoursUnit = '%s 工时'; @@ -260,7 +267,6 @@ $lang->project->lastIteration = "近期{$lang->executionCommon}"; $lang->project->ongoingStage = '进行中的阶段'; $lang->project->scrum = 'Scrum'; $lang->project->waterfall = '瀑布'; -$lang->project->waterfallTitle = '瀑布式项目管理'; $lang->project->cannotCreateChild = '该项目已经有实际的内容,无法直接添加子项目。您可以为当前项目创建一个父项目,然后在新的父项目下面添加子项目。'; $lang->project->confirmDelete = "您确定要删除吗?"; $lang->project->emptyPM = '暂无'; @@ -278,7 +284,6 @@ $lang->project->programTitle['end'] = '只显示最后一级项目集'; $lang->project->accessDenied = '您无权访问该项目!'; $lang->project->chooseProgramType = '选择项目管理方式'; -$lang->project->scrumTitle = '敏捷开发全流程项目管理'; $lang->project->cannotCreateChild = '该项目已经有实际的内容,无法直接添加子项目。您可以为当前项目创建一个父项目,然后在新的父项目下面添加子项目。'; $lang->project->hasChildren = '该项目有子项目存在,不能删除。'; $lang->project->confirmDelete = "您确定删除项目[%s]吗?"; diff --git a/module/project/model.php b/module/project/model.php index c01a4e8c2c..d47fb02ab0 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -632,7 +632,7 @@ class projectModel extends model /** * Get project pairs by model and project. * - * @param string $model all|scrum|waterfall + * @param string $model all|scrum|waterfall|kanban * @param int $programID * @access public * @return array @@ -1776,7 +1776,7 @@ class projectModel extends model $type = 'project'; if($this->config->systemMode == 'new') { - if($project->type == 'sprint' or $project->type == 'stage') $type = 'execution'; + if($project->type == 'sprint' or $project->type == 'stage' or $project->type == 'kanban') $type = 'execution'; } $members = $this->dao->select("t1.account, if(t2.deleted='0', t2.realname, t1.account) as realname")->from(TABLE_TEAM)->alias('t1') diff --git a/module/project/view/ajaxgetdropmenu.html.php b/module/project/view/ajaxgetdropmenu.html.php index 4aa753f687..648ed20b7f 100644 --- a/module/project/view/ajaxgetdropmenu.html.php +++ b/module/project/view/ajaxgetdropmenu.html.php @@ -72,9 +72,12 @@ foreach($projects as $programID => $programProjects) foreach($programProjects as $index => $project) { - $selected = $project->id == $projectID ? 'selected' : ''; - $link = helper::createLink('project', 'index', "projectID=%s", '', '', $project->id); - $projectName = $project->model == 'scrum' ? ' ' . $project->name : ' ' . $project->name; + $selected = $project->id == $projectID ? 'selected' : ''; + $link = helper::createLink('project', 'index', "projectID=%s", '', '', $project->id); + $icon = ' '; + + if($project->model != 'scrum') $icon = " "; + $projectName = $icon . $project->name; if($project->status != 'done' and $project->status != 'closed' and $project->PM == $this->app->user->account) { diff --git a/module/project/view/createguide.html.php b/module/project/view/createguide.html.php index 42f5a457b9..ee90dc000c 100644 --- a/module/project/view/createguide.html.php +++ b/module/project/view/createguide.html.php @@ -15,20 +15,27 @@

project->chooseProgramType; ?>

-
+
createLink("project", "create", "model=scrum&programID=$programID©ProjectID=0&extra=productID=$productID,branchID=$branchID"), "", '', "data-app='project' class='createButton'")?>

project->scrum; ?>

project->scrumTitle; ?>

-
+
createLink("project", "create", "model=waterfall&programID=$programID©ProjectID=0&extra=productID=$productID,branchID=$branchID"), "", '', "data-app='project' class='createButton'")?>

project->waterfall; ?>

project->waterfallTitle; ?>

+
+
+ createLink("project", "create", "model=kanban&programID=$programID©ProjectID=0&extra=productID=$productID,branchID=$branchID"), "", '', "data-app='project' class='createButton'")?> +

project->kanban;?>

+

project->kanbanTitle;?>

+
+
diff --git a/module/project/view/index.html.php b/module/project/view/index.html.php index a21c11d5f4..83900d0e7e 100644 --- a/module/project/view/index.html.php +++ b/module/project/view/index.html.php @@ -10,5 +10,74 @@ */ ?> +model != 'kanban'):?> fetch('block', 'dashboard', "module=project&type={$project->model}&projectID={$project->id}");?> + + +
+
+ +
+

+ noData;?> + id", ' ' . $lang->project->createKanban, '', 'class="btn btn-info"');?> +

+
+ + $kanban):?> +
+
+
+
+ execution->statusList, $kanban->status);?> + name;?> +
+
+
+
desc));?>
+ +
+
+
+ + +
+
+ From ec74445096500e8036849fbfb1f38847541386f1 Mon Sep 17 00:00:00 2001 From: liumengyi Date: Tue, 11 Jan 2022 15:38:50 +0800 Subject: [PATCH 05/85] * Finish task #47340.When adding kanban execution, create region, group, lanes and columns. --- db/update16.1.sql | 2 + module/common/lang/menu.php | 2 +- module/execution/control.php | 26 +- module/execution/css/taskkanban.css | 58 ++ module/execution/js/taskkanban.js | 1070 +++++++++++++++++++++ module/execution/lang/en.php | 2 + module/execution/lang/zh-cn.php | 2 + module/execution/model.php | 2 +- module/execution/view/all.html.php | 3 +- module/execution/view/taskkanban.html.php | 175 ++++ module/group/lang/resource.php | 6 +- module/kanban/model.php | 118 +++ module/project/model.php | 4 +- 13 files changed, 1462 insertions(+), 8 deletions(-) create mode 100644 module/execution/css/taskkanban.css create mode 100644 module/execution/js/taskkanban.js create mode 100644 module/execution/view/taskkanban.html.php diff --git a/db/update16.1.sql b/db/update16.1.sql index a517a5fed2..67fc99a135 100644 --- a/db/update16.1.sql +++ b/db/update16.1.sql @@ -13,3 +13,5 @@ CREATE TABLE `zt_cardgroup` ( ALTER TABLE `zt_kanban` ADD `displayCards` smallint(6) NOT NULL AFTER `order`; ALTER TABLE `zt_kanbancard` DROP COLUMN `lane`; ALTER TABLE `zt_kanbancard` DROP COLUMN `column`; + +UPDATE `zt_grouppriv` SET `method` = 'taskKanban' WHERE `module` = 'execution' AND `method` = 'kanban'; diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php index 3bf77d2863..8763ae6fcc 100644 --- a/module/common/lang/menu.php +++ b/module/common/lang/menu.php @@ -296,7 +296,7 @@ if($config->systemMode == 'new') $lang->execution->homeMenu->executionkanban = a $lang->execution->menu = new stdclass(); $lang->execution->menu->task = array('link' => "{$lang->task->common}|execution|task|executionID=%s", 'subModule' => 'task,tree', 'alias' => 'importtask,importbug'); -$lang->execution->menu->kanban = array('link' => "$lang->executionKanban|execution|kanban|executionID=%s"); +$lang->execution->menu->kanban = array('link' => "$lang->executionKanban|execution|taskkanban|executionID=%s"); $lang->execution->menu->burn = array('link' => "$lang->burn|execution|burn|executionID=%s"); $lang->execution->menu->view = array('link' => "$lang->view|execution|grouptask|executionID=%s", 'alias' => 'grouptask,tree,taskeffort,gantt,calendar,relation,maintainrelation'); $lang->execution->menu->story = array('link' => "$lang->SRCommon|execution|story|executionID=%s", 'subModule' => 'story', 'alias' => 'batchcreate,linkstory,storykanban'); diff --git a/module/execution/control.php b/module/execution/control.php index 3d18fcf079..407ab663c3 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1392,6 +1392,15 @@ class execution extends control } } + if(!empty($projectID) and $project->model == 'kanban') + { + $execution = $this->execution->getById($executionID); + $this->loadModel('kanban')->createRDKanban($execution); + + if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('kanban', "executionID=$executionID"))); + } + if(!empty($planID)) { return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('create', "projectID=$projectID&executionID=$executionID©ExecutionID=&planID=$planID&confirm=no"))); @@ -1950,6 +1959,21 @@ class execution extends control /** * Kanban. * + * @param int $executionID + * @param string $browseType + * @param string $orderBy + * @param string $group + * @access public + * @return void + */ + public function kanban($executionID, $browseType = 'all', $orderBy = 'id_asc', $group = 'all') + { + $this->display(); + } + + /** + * Task kanban. + * * @param int $executionID * @param string $browseType story|bug|task|all * @param string $orderBy @@ -1957,7 +1981,7 @@ class execution extends control * @access public * @return void */ - public function kanban($executionID, $browseType = '', $orderBy = 'order_asc', $groupBy = '') + public function taskKanban($executionID, $browseType = '', $orderBy = 'order_asc', $groupBy = '') { if(empty($browseType)) $browseType = $this->session->kanbanType ? $this->session->kanbanType : 'all'; if(empty($groupBy) and $browseType != 'all') $groupBy = $this->session->{'kanbanGroupBy' . $browseType} ? $this->session->{'kanbanGroupBy' . $browseType} : 'default'; diff --git a/module/execution/css/taskkanban.css b/module/execution/css/taskkanban.css new file mode 100644 index 0000000000..372183c4b4 --- /dev/null +++ b/module/execution/css/taskkanban.css @@ -0,0 +1,58 @@ +#main {padding-bottom: 10px;} +#main > .container {max-width: 1960px!important; padding: 0 10px} + +.kanban + .kanban {margin-top: 15px} +.kanban-card > .title {display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis} +.kanban-card > .infos {position: relative; margin-top: 5px} +.kanban-card > .infos > .info + .info {margin-left: 8px} +.kanban-card > .infos > .info-id, +.kanban-card > .infos > .info-deadline, +.kanban-card > .infos > .info-estimate {font-size: 12px; position: relative; top: 2px} +.kanban-card > .infos > .label-pri {min-width: 16px; line-height: 14px; height: 16px; padding: 0} +.kanban-card > .infos > .label-severity {transform: scale(.75)} +.kanban-card > .infos > .avatar {position: absolute; right: 0; top: 0} +.kanban-card > .actions {position: absolute; top: 4px; right: 4px; opacity: 0;} +.kanban-card:hover > .actions {opacity: 1;} +.kanban-card > .actions > a {display: block; float: left; width: 20px; height: 20px; line-height: 20px; text-align: center; border-radius: 4px; opacity: .7;} +.kanban-card > .actions > a:hover {background-color: rgba(0,0,0,.075); opacity: 1;} + +.kanban-header-col > .actions {padding-top: 22px} +.kanban-header-parent-col .kanban-header-col > .actions {padding-top: 6px; padding-right: 2px;} +.kanban-header-col > .actions > a {display: block; float: left; width: 20px; height: 20px; line-height: 20px; text-align: center; border-radius: 4px; opacity: .7;} +.kanban-header-col > .actions > a:hover {background-color: rgba(0,0,0,.075); opacity: 1;} + +.kanban-lane-name > .actions {position: absolute; top: 0; left: 0; right: 0; opacity: 0;} +.kanban-lane-name:hover > .actions {opacity: 1;} +.kanban-lane-name > .actions > a {display: block; width: 20px; height: 20px; line-height: 20px; text-align: center; opacity: .7; color: #fff;} +.kanban-lane-name > .actions > a:hover {background-color: rgba(0,0,0,.2); opacity: 1;} + +.kanban-affixed .kanban-header-col > .title > .text, +.kanban-affixed .kanban-header-col > .title > .count {color: #fff!important;} + +#kanbanContainer {margin: 0;} +#kanbanContainer > .panel-body {overflow: auto;} +#kanbans .kanban {min-height: initial;} +#kanbans .kanban-lane {min-height: 150px; margin-top: 2px;} +#kanbans .kanban-affixed > .kanban-header {top: 100px;} +#kanbans .kanban-card[data-scale-size="4"] {padding: 8px;} +#kanbans .kanban-card[data-scale-size="3"] {padding: 3px 4px;} +#kanbans .kanban-card[data-scale-size="3"] > .title {white-space: normal; max-height: 100%;} +#kanbans .kanban-card[data-scale-size="2"] {padding: 3px 4px; overflow: hidden;} +#kanbans .kanban-card[data-scale-size="2"] > .title {display: inline; line-height: 18px; white-space: normal; max-height: 100%; word-break: break-all;} +#kanbans .kanban-card[data-scale-size="2"] > .infos {display: inline-block; height: 18px; vertical-align: top; margin: 0;} +#kanbans .kanban-card[data-scale-size="2"] > .infos > .info-pri {transform: scale(.8); vertical-align: top;} +#kanbans .kanban-card[data-scale-size="2"] > .infos > .avatar {display: inline-block; transform: scale(.8); position: relative; top: -2px; vertical-align: top; margin-right: -1px;} + +#kanbanScaleControl {width: 100px;} +#kanbanScaleControl .input-group-addon {background: #fff; padding: 5px;} +#kanbanScaleControl > .input-group-btn:first-child > .btn {border-radius: 16px 0 0 16px; border-right-color: transparent;} +#kanbanScaleControl > .input-group-btn:last-child > .btn {border-radius: 0 16px 16px 0; border-left-color: transparent;} +#kanbanScaleControl > .input-group-btn > .btn:hover {border-color: #b8bfce;} + +#type_chosen .icon-kanban {padding-right: 10px; font-size: 15px;} + +.dropdown-menu a {text-align: left;} +.scrollbar-hover {max-height: 2000px; overflow: scroll !important;} +.c-type {width: 150px !important; overflow: unset;} +.c-group {width: 190px !important; overflow: unset;} +.c-type {margin-left: 0px !important;} diff --git a/module/execution/js/taskkanban.js b/module/execution/js/taskkanban.js new file mode 100644 index 0000000000..daf1724e18 --- /dev/null +++ b/module/execution/js/taskkanban.js @@ -0,0 +1,1070 @@ +function changeView(view) +{ + var link = createLink('execution', 'kanban', "executionID=" + executionID + '&type=' + view); + location.href = link; +} + +/** + * Render user avatar + * @param {String|{account: string, avatar: string}} user User account or user object + * @returns {string} + */ +function renderUserAvatar(user, objectType, objectID, size) +{ + var avatarSizeClass = 'avatar-' + (size || 'sm'); + var $noPrivAndNoAssigned = $('
'); + if(objectType == 'task') + { + if(!priv.canAssignTask && !user) return $noPrivAndNoAssigned; + var link = createLink('task', 'assignto', 'executionID=' + executionID + '&id=' + objectID, '', true); + } + if(objectType == 'story') + { + if(!priv.canAssignStory && !user) return $noPrivAndNoAssigned; + var link = createLink('story', 'assignto', 'id=' + objectID, '', true); + } + if(objectType == 'bug') + { + if(!priv.canAssignBug && !user) return $noPrivAndNoAssigned; + var link = createLink('bug', 'assignto', 'id=' + objectID, '', true); + } + + if(!user) return $(''); + + if(typeof user === 'string') user = {account: user}; + if(!user.avatar && window.userList && window.userList[user.account]) user = window.userList[user.account]; + + var $noPrivAvatar = $('
').avatar({user: user}); + if(objectType == 'task' && !priv.canAssignTask) return $noPrivAvatar; + if(objectType == 'story' && !priv.canAssignStory) return $noPrivAvatar; + if(objectType == 'bug' && !priv.canAssignBug) return $noPrivAvatar; + + return $('').avatar({user: user}); +} + +/** + * Render deadline + * @param {String|Date} deadline Deadline + * @returns {JQuery} + */ +function renderDeadline(deadline) +{ + if(deadline == '0000-00-00') return; + + var date = $.zui.createDate(deadline); + var now = new Date(); + now.setHours(0); + now.setMinutes(0); + now.setSeconds(0); + now.setMilliseconds(0); + var isEarlyThanToday = date.getTime() < now.getTime(); + var deadlineDate = $.zui.formatDate(date, 'MM-dd'); + + return $('').text(deadlineLang + ' ' + deadlineDate).addClass(isEarlyThanToday ? 'text-red' : 'text-muted'); +} + +/** + * Render story item + * @param {Object} item Story item object + * @param {JQuery} $item Kanban item element + * @param {Object} col Column object + * @returns {JQuery} $item Kanban item element + */ +function renderStoryItem(item, $item, col) +{ + var scaleSize = window.kanbanScaleSize; + if(+$item.attr('data-scale-size') !== scaleSize) $item.empty().attr('data-scale-size', scaleSize); + + if(scaleSize <= 3) + { + var $title = $item.find('.title'); + if(!$title.length) + { + $title = $('' + (scaleSize <= 1 ? ' ' : '') + '') + .attr('href', $.createLink('story', 'view', 'storyID=' + item.id, '', true)); + $title.appendTo($item); + } + $title.attr('title', item.title).find('.text').text(item.title); + } + + if(scaleSize <= 2) + { + var idHtml = scaleSize <= 1 ? ('#' + item.id + '') : ''; + var priHtml = '' + item.pri + ''; + var hoursHtml = (item.estimate && scaleSize <= 1) ? ('' + item.estimate + 'h') : ''; + var avatarHtml = renderUserAvatar(item.assignedTo, 'story', item.id); + var $infos = $item.find('.infos'); + if(!$infos.length) $infos = $('
'); + $infos.html([idHtml, priHtml, hoursHtml].join('')); + + $infos[scaleSize <= 1 ? 'append' : 'prepend'](avatarHtml); + if(scaleSize <= 1) $infos.appendTo($item); + else if(scaleSize === 2) $infos.prependTo($item); + else $infos.prependTo($item.find('.title')); + } + else if(scaleSize === 4) + { + $item.html(renderUserAvatar(item.assignedTo, 'story', item.id, 'md')); + } + + if(scaleSize <= 1) + { + var $actions = $item.find('.actions'); + if(!$actions.length && item.menus.length) + { + $actions = $([ + '
', + '', + '', + '', + '
' + ].join('')).appendTo($item); + } + } + + return $item.attr('data-type', 'story').addClass('kanban-item-story'); +} + +/** + * Render bug item + * @param {Object} item Bug item object + * @param {JQuery} $item Kanban item element + * @param {Object} col Column object + * @returns {JQuery} $item Kanban item element + */ +function renderBugItem(item, $item, col) +{ + var scaleSize = window.kanbanScaleSize; + if(+$item.attr('data-scale-size') !== scaleSize) $item.empty().attr('data-scale-size', scaleSize); + + if(scaleSize <= 3) + { + var $title = $item.find('.title'); + if(!$title.length) + { + $title = $('' + (scaleSize <= 1 ? ' ' : '') + '') + .attr('href', $.createLink('bug', 'view', 'bugID=' + item.id, '', true)); + $title.appendTo($item); + } + $title.attr('title', item.title).find('.text').text(item.title); + } + + if(scaleSize <= 2) + { + var idHtml = scaleSize <= 1 ? ('#' + item.id + '') : ''; + var severityHtml = scaleSize <= 1 ? ('') : ''; + var priHtml = '' + item.pri + ''; + var avatarHtml = renderUserAvatar(item.assignedTo, 'bug', item.id); + + var $infos = $item.find('.infos'); + if(!$infos.length) $infos = $('
'); + $infos.html([idHtml, severityHtml, priHtml].join('')); + if(item.deadline && scaleSize <= 1) $infos.append(renderDeadline(item.deadline)); + $infos[scaleSize <= 1 ? 'append' : 'prepend'](avatarHtml); + + if(scaleSize <= 1) $infos.appendTo($item); + else if(scaleSize === 2) $infos.prependTo($item); + else $infos.prependTo($item.find('.title')); + } + else if(scaleSize === 4) + { + $item.html(renderUserAvatar(item.assignedTo, 'bug', item.id, 'md')); + } + + if(scaleSize <= 1) + { + var $actions = $item.find('.actions'); + if(!$actions.length && item.menus.length) + { + $actions = $([ + '
', + '', + '', + '', + '
' + ].join('')).appendTo($item); + } + } + + return $item.attr('data-type', 'bug').addClass('kanban-item-bug'); +} + +/** + * Render task item + * @param {Object} item Task item object + * @param {JQuery} $item Kanban item element + * @param {Object} col Column object + * @returns {JQuery} $item Kanban item element + */ +function renderTaskItem(item, $item, col) +{ + var scaleSize = window.kanbanScaleSize; + if(+$item.attr('data-scale-size') !== scaleSize) $item.empty().attr('data-scale-size', scaleSize); + + if(scaleSize <= 3) + { + var $title = $item.find('.title'); + if(!$title.length) + { + $title = $('' + (scaleSize <= 1 ? ' ' : '') + '') + .attr('href', $.createLink('task', 'view', 'taskID=' + item.id, '', true)); + $title.appendTo($item); + } + $title.attr('title', item.name).find('.text').text(item.name); + } + + if(scaleSize <= 2) + { + var idHtml = scaleSize <= 1 ? ('#' + item.id + '') : ''; + var priHtml = '' + item.pri + ''; + var hoursHtml = (item.estimate && scaleSize <= 1) ? ('' + item.estimate + 'h') : ''; + var avatarHtml = renderUserAvatar(item.assignedTo, 'task', item.id); + + var $infos = $item.find('.infos'); + if(!$infos.length) $infos = $('
'); + $infos.html([idHtml, priHtml, hoursHtml].join('')); + if(item.deadline && scaleSize <= 1) $infos.append(renderDeadline(item.deadline)); + $infos[scaleSize <= 1 ? 'append' : 'prepend'](avatarHtml); + + if(scaleSize <= 1) $infos.appendTo($item); + else if(scaleSize === 2) $infos.prependTo($item); + else $infos.prependTo($item.find('.title')); + } + else if(scaleSize === 4) + { + $item.html(renderUserAvatar(item.assignedTo, 'task', item.id, 'md')); + } + + if(scaleSize <= 1) + { + var $actions = $item.find('.actions'); + if(!$actions.length && item.menus.length) + { + $actions = $([ + '
', + '', + '', + '', + '
' + ].join('')).appendTo($item); + } + } + + $item.attr('data-type', 'task').addClass('kanban-item-task'); + + return $item; +} + +/* Add column renderer */ +addColumnRenderer('story', renderStoryItem); +addColumnRenderer('bug', renderBugItem); +addColumnRenderer('task', renderTaskItem); + +/** + * Render column count + * @param {JQuery} $count Kanban count element + * @param {number} count Column cards count + * @param {number} col Column object + * @param {Object} kanban Kanban intance + */ +function renderColumnCount($count, count, col) +{ + var text = count + '/' + (col.limit < 0 ? '' : col.limit); + $count.html(text + ''); +} + +/** + * Render header column + * @param {JQuery} $col Header column element + * @param {Object} col Header column object + * @param {JQuery} $header Header element + * @param {Object} kanban Kanban object + */ +function renderHeaderCol($col, col, $header, kanban) +{ + if(col.asParent) $col = $col.children('.kanban-header-col'); + var $actions = $('
'); + var printStoryButton = printTaskButton = printBugButton = false; + if(priv.canCreateStory || priv.canBatchCreateStory || priv.canLinkStory || priv.canLinkStoryByPlane) printStoryButton = true; + if(priv.canCreateTask || priv.canBatchCreateTask) printTaskButton = true; + if(priv.canCreateBug || priv.canBatchCreateBug) printBugButton = true; + + if((col.type === 'backlog' && printStoryButton) || (col.type === 'wait' && printTaskButton) || (col.type == 'unconfirmed' && printBugButton)) + { + $actions.append([ + '', + '', + '' + ].join('')); + } + + $actions.append([ + '', + '', + '' + ].join('')); + $actions.appendTo($col); +} + +/** + * Render lane name + * @param {JQuery} $name Name element + * @param {Object} lane Lane object + * @param {JQuery} $kanban $kanban element + * @param {Object} columns Kanban columns + * @param {Object} kanban Kanban object + */ +function renderLaneName($name, lane, $kanban, columns, kanban) +{ + if(lane.id != 'story' && lane.id != 'task' && lane.id != 'bug') return false; + if(!$name.children('.actions').length && (priv.canSetLane || priv.canMoveLane)) + { + $([ + '
', + '', + '', + '', + '
' + ].join('')).appendTo($name); + } +} + +/** + * Updata kanban data + * @param {string} kanbanID Kanban id + * @param {Object} data Kanban data + */ +function updateKanban(kanbanID, data) +{ + var $kanban = $('#kanban-' + kanbanID); + if(!$kanban.length) return; + + $kanban.data('zui.kanban').render(data); +} + +/** + * Create kanban in page + * @param {string} kanbanID Kanban id + * @param {Object} data Kanban data + * @param {Object} options Kanban options + */ +function createKanban(kanbanID, data, options) +{ + var $kanban = $('#kanban-' + kanbanID); + if($kanban.length) return updateKanban(kanbanID, data); + + $kanban = $('
').appendTo('#kanbans'); + $kanban.kanban($.extend({data: data}, options)); +} + +function fullScreen() +{ + var element = document.getElementById('kanbanContainer'); + var requestMethod = element.requestFullScreen || element.webkitRequestFullScreen || element.mozRequestFullScreen || element.msRequestFullScreen; + if(requestMethod) + { + var afterEnterFullscreen = function() + { + $('#kanbanContainer').addClass('scrollbar-hover'); + $('.actions').hide(); + $('#kanbanContainer a.iframe').each(function() + { + if($(this).hasClass('iframe')) + { + var href = $(this).attr('href'); + $(this).removeClass('iframe'); + $(this).attr('href', 'javascript:void(0)'); + $(this).attr('href-bak', href); + } + }) + $.cookie('isFullScreen', 1); + } + + var whenFailEnterFullscreen = function() + { + exitFullScreen(); + } + + try + { + var result = requestMethod.call(element); + if(result && (typeof result.then === 'function' || result instanceof window.Promise)) + { + result.then(afterEnterFullscreen).catch(whenFailEnterFullscreen); + } + else + { + afterEnterFullscreen(); + } + } + catch (error) + { + whenFailEnterFullscreen(error); + } + } +} + +/** + * Exit full screen. + * + * @access public + * @return void + */ +function exitFullScreen() +{ + $('#kanbanContainer').removeClass('scrollbar-hover'); + $('.actions').show(); + $('#kanbanContainer a').each(function() + { + var hrefBak = $(this).attr('href-bak'); + if(hrefBak) + { + $(this).addClass('iframe'); + $(this).attr('href', hrefBak); + } + }) + $.cookie('isFullScreen', 0); +} + +document.addEventListener('fullscreenchange', function (e) +{ + if(!document.fullscreenElement) exitFullScreen(); +}); + +document.addEventListener('webkitfullscreenchange', function (e) +{ + if(!document.webkitFullscreenElement) exitFullScreen(); +}); + +document.addEventListener('mozfullscreenchange', function (e) +{ + if(!document.mozFullScreenElement) exitFullScreen(); +}); + +document.addEventListener('msfullscreenChange', function (e) +{ + if(!document.msfullscreenElement) exitFullScreen(); +}); + +/* Define drag and drop rules */ +if(!window.kanbanDropRules) +{ + window.kanbanDropRules = + { + story: + { + backlog: ['ready'], + ready: ['backlog'], + }, + bug: + { + 'unconfirmed': ['confirmed', 'fixing', 'fixed'], + 'confirmed': ['fixing', 'fixed'], + 'fixing': ['fixed'], + 'fixed': ['testing', 'tested', 'fixing'], + 'testing': ['tested', 'closed', 'fixing'], + 'tested': ['closed', 'fixing'], + 'closed': ['fixing'], + }, + task: + { + 'wait': ['developing', 'developed', 'canceled', 'closed'], + 'developing': ['developed', 'pause'], + 'developed': ['canceled', 'closed'], + 'pause': ['developing'], + 'canceled': ['developing'], + 'closed': ['developing'], + } + } +} + +/* + * Find drop columns + * @param {JQuery} $element Drag element + * @param {JQuery} $root Dnd root element + */ +function findDropColumns($element, $root) +{ + var $col = $element.closest('.kanban-col'); + var col = $col.data(); + var kanbanID = $root.data('id'); + var kanbanRules = window.kanbanDropRules ? window.kanbanDropRules[kanbanID] : null; + + if(!kanbanRules) return $root.find('.kanban-lane-col:not([data-type="' + col.type + '"])'); + + var colRules = kanbanRules[col.type]; + var lane = $col.closest('.kanban-lane').data('lane'); + return $root.find('.kanban-lane-col').filter(function() + { + if(!colRules) return false; + if(colRules === true) return true; + + var $newCol = $(this); + var newCol = $newCol.data(); + if(newCol.id === col.id) return false; + + var $newLane = $newCol.closest('.kanban-lane'); + var newLane = $newLane.data('lane'); + var canDropHere = colRules.indexOf(newCol.type) > -1 && newLane.id === lane.id; + if(canDropHere) $newCol.addClass('can-drop-here'); + return canDropHere; + }); +} + +/** + * Change column type for a card + * @param {Object} card Card object + * @param {String} fromColType The column type before change + * @param {String} toColType The column type after change + * @param {String} kanbanID Kanban ID + */ +function changeCardColType(card, fromColType, toColType, kanbanID) +{ + if(typeof card == 'undefined') return false; + var objectID = card.id; + var showIframe = false; + var moveCard = false; + + /* Task lane. */ + if(kanbanID == 'task') + { + if(toColType == 'developed') + { + if((fromColType == 'developing' || fromColType == 'wait') && priv.canFinishTask) + { + var link = createLink('task', 'finish', 'taskID=' + objectID, '', true); + showIframe = true; + } + } + else if(toColType == 'pause') + { + if(fromColType == 'developing' && priv.canPauseTask) + { + var link = createLink('task', 'pause', 'taskID=' + objectID, '', true); + showIframe = true; + } + } + else if(toColType == 'developing') + { + if((fromColType == 'pause' || fromColType == 'cancel' || fromColType == 'closed' || fromColType == 'developed') && priv.canActivateTask) + { + var link = createLink('task', 'activate', 'taskID=' + objectID, '', true); + showIframe = true; + } + if(fromColType == 'wait' && priv.canStartTask) + { + var link = createLink('task', 'start', 'taskID=' + objectID, '', true); + showIframe = true; + } + } + else if(toColType == 'canceled') + { + if((fromColType == 'developing' || fromColType == 'wait' || fromColType == 'pause') && priv.canCancelTask) + { + var link = createLink('task', 'cancel', 'taskID=' + objectID, '', true); + showIframe = true; + } + } + else if(toColType == 'closed') + { + if((fromColType == 'developed' || fromColType == 'canceled') && priv.canCloseTask) + { + var link = createLink('task', 'close', 'taskID=' + objectID, '', true); + showIframe = true; + } + } + } + + /* Bug lane. */ + if(kanbanID == 'bug') + { + if(toColType == 'confirmed') + { + if(fromColType == 'unconfirmed' && priv.canConfirmBug) + { + var link = createLink('bug', 'confirmBug', 'bugID=' + objectID, '', true); + showIframe = true; + } + } + else if(toColType == 'fixing') + { + if(fromColType == 'confirmed' || fromColType == 'unconfirmed') moveCard = true; + if((fromColType == 'closed' || fromColType == 'fixed' || fromColType == 'testing' || fromColType == 'tested') && priv.canActivateBug) + { + var link = createLink('bug', 'activate', 'bugID=' + objectID, '', true); + showIframe = true; + } + } + else if(toColType == 'fixed') + { + if(fromColType == 'fixing' || fromColType == 'confirmed' || fromColType == 'unconfirmed') + { + var link = createLink('bug', 'resolve', 'bugID=' + objectID, '', true); + showIframe = true; + } + } + else if(toColType == 'testing') + { + if(fromColType == 'fixed') moveCard = true; + } + else if(toColType == 'tested') + { + if(fromColType == 'fixed' || fromColType == 'testing') moveCard = true; + } + else if(toColType == 'closed') + { + if(fromColType == 'testing' || fromColType == 'tested') + { + var link = createLink('bug', 'close', 'bugID=' + objectID, '', true); + showIframe = true; + } + } + + if(moveCard) + { + var colID = card.$col.columnID; + var link = createLink('kanban', 'ajaxMoveCard', 'cardID=' + objectID + '&colID=' + colID + '&toColType=' + toColType + '&execitionID=' + executionID + '&browseType=' + browseType + '&groupBy=' + groupBy); + $.get(link, function(data) + { + if(data) + { + kanbanGroup = $.parseJSON(data); + if(groupBy == 'default') + { + updateKanban('bug', kanbanGroup.bug); + } + else + { + updateKanban(browseType, kanbanGroup[groupBy]); + } + } + }) + } + } + + /* Story lane. */ + if(kanbanID == 'story') + { + if(toColType == 'ready' || toColType == 'backlog') + { + var colID = card.$col.columnID; + var link = createLink('kanban', 'ajaxMoveCard', 'cardID=' + objectID + '&colID=' + colID + '&toColType=' + toColType + '&execitionID=' + executionID + '&browseType=' + browseType + '&groupBy=' + groupBy); + $.get(link, function(data) + { + if(data) + { + kanbanGroup = $.parseJSON(data); + if(groupBy == 'default') + { + updateKanban('story', kanbanGroup.story); + } + else + { + updateKanban(browseType, kanbanGroup[groupBy]); + } + } + }) + } + } + + if(showIframe) + { + var modalTrigger = new $.zui.ModalTrigger({type: 'iframe', width: '80%', url: link}); + modalTrigger.show(); + } +} + +/** + * Handle finish drop task + * @param {Object} event Event object + * @returns {void} + */ +function handleFinishDrop(event) +{ + var $card = $(event.element); // The drag card + var $dragCol = $card.closest('.kanban-lane-col'); + var $dropCol = $(event.target); + + /* Get d-n-d(drag and drop) infos */ + var card = $card.data('item'); + var fromColType = $dragCol.data('type'); + var toColType = $dropCol.data('type'); + var kanbanID = $card.closest('.kanban').data('id'); + + changeCardColType(card, fromColType, toColType, kanbanID); + + $('#kanbans').find('.can-drop-here').removeClass('can-drop-here'); +} + +/** Handle sort cards in column */ +function handleSortColCards() +{ + /* TODO: handle sort cards from column contextmenu */ + return false; +} + +/** + * Create column menu + * @returns {Object[]} + */ +function createColumnMenu(options) +{ + var $col = options.$trigger.closest('.kanban-col'); + var col = $col.data('col'); + var kanbanID = options.kanban; + + var items = []; + if(priv.canEditName) items.push({label: executionLang.editName, url: $.createLink('kanban', 'setColumn', 'col=' + col.columnID + '&executionID=' + executionID + '&from=execution'), className: 'iframe', attrs: {'data-width': '500px'}}) + if(priv.canSetWIP) items.push({label: executionLang.setWIP, url: $.createLink('kanban', 'setWIP', 'col=' + col.columnID + '&executionID=' + executionID + '&from=execution'), className: 'iframe', attrs: {'data-width': '500px'}}) + //if(priv.canSortCards) items.push({label: executionLang.sortColumn, items: ['按ID倒序', '按ID顺序'], className: 'iframe', onClick: handleSortColCards}) + return items; +} + +/** + * Create column create button menu + * @returns {Object[]} + */ +function createColumnCreateMenu(options) +{ + var $col = options.$trigger.closest('.kanban-col'); + var col = $col.data('col'); + var items = []; + + if(col.laneType == 'story') + { + if(priv.canCreateStory) items.push({label: storyLang.create, url: $.createLink('story', 'create', 'productID=' + productID, '', true), className: 'iframe'}); + if(priv.canBatchCreateStory) items.push({label: executionLang.batchCreateStroy, url: $.createLink('story', 'batchcreate', 'productID=' + productID + '&branch=0&moduleID=0&storyID=0&executionID=' + executionID, '', true), className: 'iframe', attrs: {'data-width': '90%'}}); + if(priv.canLinkStory) items.push({label: executionLang.linkStory, url: $.createLink('execution', 'linkStory', 'executionID=' + executionID, '', true), className: 'iframe', attrs: {'data-width': '90%'}}); + if(priv.canLinkStoryByPlane) items.push({label: executionLang.linkStoryByPlan, url: '#linkStoryByPlan', 'attrs' : {'data-toggle': 'modal'}}); + } + else if(col.laneType == 'bug') + { + if(priv.canCreateBug) items.push({label: bugLang.create, url: $.createLink('bug', 'create', 'productID=0&moduleID=0&extra=executionID=' + executionID, '', true), className: 'iframe'}); + if(priv.canBatchCreateBug) items.push({label: bugLang.batchCreate, url: $.createLink('bug', 'batchcreate', 'productID=' + productID + '&moduleID=0&executionID=' + executionID, '', true), className: 'iframe'}); + } + else + { + if(priv.canCreateTask) items.push({label: taskLang.create, url: $.createLink('task', 'create', 'executionID=' + executionID, '', true), className: 'iframe'}); + if(priv.canBatchCreateTask) items.push({label: taskLang.batchCreate, url: $.createLink('task', 'batchcreate', 'executionID=' + executionID, '', true), className: 'iframe'}); + } + return items; +} + +/** + * Create lane menu + * @returns {Object[]} + */ +function createLaneMenu(options) +{ + var $lane = options.$trigger.closest('.kanban-lane'); + var $kanban = $lane.closest('.kanban'); + var lane = $lane.data('lane'); + var kanbanID = options.kanban; + var upTargetKanban = $kanban.prev('.kanban').length ? $kanban.prev('.kanban').data('id') : ''; + var downTargetKanban = $kanban.next('.kanban').length ? $kanban.next('.kanban').data('id') : ''; + + var items = []; + if(priv.canSetLane) items.push({label: kanbanLang.setLane, icon: 'edit', url: $.createLink('kanban', 'setLane', 'lane=' + lane.laneID + '&executionID=' + executionID + '&from=execution'), className: 'iframe'}); + if(priv.canMoveLane) items.push( + {label: kanbanLang.moveUp, icon: 'arrow-up', url: $.createLink('kanban', 'laneMove', 'executionID=' + executionID + '¤tLane=' + lane.id + '&targetLane=' + upTargetKanban), className: 'iframe', disabled: !$kanban.prev('.kanban').length}, + {label: kanbanLang.moveDown, icon: 'arrow-down', url: $.createLink('kanban', 'laneMove', 'executionID=' + executionID + '¤tLane=' + lane.id + '&targetLane=' + downTargetKanban), className: 'iframe', disabled: !$kanban.next('.kanban').length} + ); + + var bounds = options.$trigger[0].getBoundingClientRect(); + items.$options = {x: bounds.right, y: bounds.top}; + return items; +} + +/** + * Create story menu + * @returns {Object[]} + */ +function createStoryMenu(options) +{ + var $card = options.$trigger.closest('.kanban-item'); + var story = $card.data('item'); + + var items = []; + $.each(story.menus, function() + { + var item = {label: this.label, icon: this.icon, url: this.url, attrs: {'data-toggle': 'modal', 'data-type': 'iframe'}}; + if(this.size) item.attrs['data-width'] = this.size; + + if(this.icon == 'unlink') item = {label: this.label, icon: this.icon, url: this.url, attrs: {'target': 'hiddenwin'}}; + items.push(item); + }); + + return items; +} + +/** + * Create bug menu + * @returns {Object[]} + */ +function createBugMenu(options) +{ + var $card = options.$trigger.closest('.kanban-item'); + var bug = $card.data('item'); + + var items = []; + $.each(bug.menus, function() + { + var item = {label: this.label, icon: this.icon, url: this.url, attrs: {'data-toggle': 'modal', 'data-type': 'iframe'}}; + if(this.size) item.attrs['data-width'] = this.size; + + items.push(item); + }); + + return items; +} + + /** + * Create task menu + * @returns {Object[]} + */ +function createTaskMenu(options) +{ + var $card = options.$trigger.closest('.kanban-item'); + var task = $card.data('item'); + + var items = []; + $.each(task.menus, function() + { + var item = {label: this.label, icon: this.icon, url: this.url, attrs: {'data-toggle': 'modal', 'data-type': 'iframe'}}; + if(this.size) item.attrs['data-width'] = this.size; + + items.push(item); + }); + + return items; +} + +/** Resize kanban container size */ +function resizeKanbanContainer() +{ + var $container = $('#kanbanContainer'); + var maxHeight = window.innerHeight - 98 - 15; + if($.cookie('isFullScreen') == 1) maxHeight = window.innerHeight - 15; + $container.children('.panel-body').css('max-height', maxHeight); +} + +/* Define menu creators */ +window.menuCreators = +{ + column: createColumnMenu, + columnCreate: createColumnCreateMenu, + lane: createLaneMenu, + story: createStoryMenu, + bug: createBugMenu, + task: createTaskMenu, +}; + +/* Set kanban affix container */ +window.kanbanAffixContainer = '#kanbanContainer>.panel-body'; + +/* Overload kanban default options */ +$.extend($.fn.kanban.Constructor.DEFAULTS, +{ + onRender: function() + { + var maxWidth = 0; + $('#kanbans .kanban-board').each(function() + { + maxWidth = Math.max(maxWidth, $(this).outerWidth()); + }); + $('#kanbans').css('min-width', maxWidth); + } +}); + +/** Get card height */ +function getCardHeight() +{ + return [59, 59, 62, 62, 47][window.kanbanScaleSize]; +} + +/** Change kanban scale size */ +function changeKanbanScaleSize(newScaleSize) +{ + var newScaleSize = Math.max(1, Math.min(4, newScaleSize)); + if(newScaleSize === window.kanbanScaleSize) return; + + window.kanbanScaleSize = newScaleSize; + $.zui.store.set('executionKanbanScaleSize', newScaleSize); + $('#kanbanScaleSize').text(newScaleSize); + $('#kanbanScaleControl .btn[data-type="+"]').attr('disabled', newScaleSize >= 4 ? 'disabled' : null); + $('#kanbanScaleControl .btn[data-type="-"]').attr('disabled', newScaleSize <= 1 ? 'disabled' : null); + + $('#kanbans').children('.kanban').each(function() + { + var kanban = $(this).data('zui.kanban'); + if(!kanban) return; + kanban.setOptions({cardsPerRow: newScaleSize, cardHeight: getCardHeight()}); + }); + + return newScaleSize; +} + +/* Example code: */ +$(function() +{ + $.cookie('isFullScreen', 0); + + window.kanbanScaleSize = +$.zui.store.get('executionKanbanScaleSize', 1); + $('#kanbanScaleSize').text(window.kanbanScaleSize); + $('#kanbanScaleControl .btn[data-type="+"]').attr('disabled', window.kanbanScaleSize >= 4 ? 'disabled' : null); + $('#kanbanScaleControl .btn[data-type="-"]').attr('disabled', window.kanbanScaleSize <= 1 ? 'disabled' : null); + + /* Common options */  + var commonOptions = + { + maxColHeight: 'auto', + minColWidth: 240, + maxColWidth: 240, + cardHeight: getCardHeight(), + showCount: true, + showZeroCount: true, + fluidBoardWidth: false, + cardsPerRow: window.kanbanScaleSize, + virtualize: true, + virtualRenderOptions: {container: '#kanbanContainer>.panel-body'}, + droppable: + { + target: findDropColumns, + finish: handleFinishDrop, + mouseButton: 'left' + }, + onRenderHeaderCol: renderHeaderCol, + onRenderLaneName: renderLaneName, + onRenderCount: renderColumnCount + }; + + /* Create kanban */ + if(groupBy == 'default') + { + var kanbanLane = ''; + for(var i in kanbanList) + { + if(kanbanList[i] == 'story') kanbanLane = kanbanGroup.story; + if(kanbanList[i] == 'bug') kanbanLane = kanbanGroup.bug; + if(kanbanList[i] == 'task') kanbanLane = kanbanGroup.task; + + if(browseType == kanbanList[i] || browseType == 'all') createKanban(kanbanList[i], kanbanLane, commonOptions); + } + } + else + { + /* Create kanban by group. */ + createKanban(browseType, kanbanGroup[groupBy], commonOptions); + } + + /* Init iframe modals */ + $(document).on('click', '#kanbans .iframe,.contextmenu-menu .iframe', function(event) + { + var $link = $(this); + if($link.data('zui.modaltrigger')) return; + $link.modalTrigger({show: true}); + event.preventDefault(); + }); + + /* Init contextmenu */ + $('#kanbans').on('click', '[data-contextmenu]', function(event) + { + var $trigger = $(this); + var menuType = $trigger.data('contextmenu'); + + var menuCreator = window.menuCreators[menuType]; + if(!menuCreator) return; + + var options = $.extend({event: event, $trigger: $trigger}, $trigger.data()); + var items = menuCreator(options); + if(!items || !items.length) return; + + $.zui.ContextMenu.show(items, items.$options || {event: event}); + }); + + /* Make kanbanScaleControl works */ + $('#kanbanScaleControl').on('click', '.btn', function() + { + changeKanbanScaleSize(window.kanbanScaleSize + ($(this).data('type') === '+' ? 1 : -1)); + }); + + /* Resize kanban container on window resize */ + resizeKanbanContainer(); + $(window).on('resize', resizeKanbanContainer); + + /* Hide contextmenu when page scroll */ + $(window).on('scroll', function() + { + $.zui.ContextMenu.hide(); + }); + + $('#toStoryButton').on('click', function() + { + var planID = $('#plan').val(); + if(planID) + { + location.href = createLink('execution', 'importPlanStories', 'executionID=' + executionID + '&planID=' + planID + '&productID=0&fromMethod=kanban'); + } + }); + + $('#type_chosen .chosen-single span').prepend(''); + $('#group_chosen .chosen-single span').prepend(kanbanLang.laneGroup + ': '); + + /* Ajax update kanban. */ + var lastUpdateData; + setInterval(function() + { + $.get(createLink('execution', 'ajaxUpdateKanban', "executionID=" + executionID + "&entertime=" + entertime + "&browseType=" + browseType + "&groupBy=" + groupBy), function(data) + { + if(data && lastUpdateData !== data) + { + lastUpdateData = data; + kanbanGroup = $.parseJSON(data); + if(groupBy == 'default') + { + var kanbanLane = ''; + for(var i in kanbanList) + { + if(kanbanList[i] == 'story') kanbanLane = kanbanGroup.story; + if(kanbanList[i] == 'bug') kanbanLane = kanbanGroup.bug; + if(kanbanList[i] == 'task') kanbanLane = kanbanGroup.task; + + if(browseType == kanbanList[i] || browseType == 'all') updateKanban(kanbanList[i], kanbanLane); + } + } + else + { + updateKanban(browseType, kanbanGroup[groupBy]); + } + } + }); + }, 10000); +}); + +$('#type').change(function() +{ + var type = $('#type').val(); + if(type != 'all') + { + $('.c-group').show(); + $.get(createLink('execution', 'ajaxGetGroup', 'type=' + type), function(data) + { + $('#group_chosen').remove(); + $('#group').replaceWith(data); + $('#group').chosen(); + }) + } + + var link = createLink('execution', 'kanban', "executionID=" + executionID + '&type=' + type); + location.href = link; +}); + +$('.c-group').change(function() +{ + $('.c-group').show(); + + var type = $('#type').val(); + var group = $('#group').val(); + var link = createLink('execution', 'kanban', 'executionID=' + executionID + '&type=' + type + '&orderBy=order_asc' + '&groupBy=' + group); + location.href = link; +}); diff --git a/module/execution/lang/en.php b/module/execution/lang/en.php index 6006065bfc..40578c1152 100644 --- a/module/execution/lang/en.php +++ b/module/execution/lang/en.php @@ -247,6 +247,8 @@ $lang->execution->iteration = 'Iterations'; $lang->execution->iterationInfo = '%s Iterations'; $lang->execution->viewAll = 'View All'; $lang->execution->testreport = 'Test Report'; +$lang->execution->taskKanban = 'Task Kanban'; +$lang->execution->RDKanban = 'Research & Development Kanban'; /* Group browsing. */ $lang->execution->allTasks = 'All'; diff --git a/module/execution/lang/zh-cn.php b/module/execution/lang/zh-cn.php index eed1188d4c..f33c35aeac 100644 --- a/module/execution/lang/zh-cn.php +++ b/module/execution/lang/zh-cn.php @@ -247,6 +247,8 @@ $lang->execution->iteration = '版本迭代'; $lang->execution->iterationInfo = '迭代%s次'; $lang->execution->viewAll = '查看所有'; $lang->execution->testreport = '测试报告'; +$lang->execution->taskKanban = '任务看板'; +$lang->execution->RDKanban = '研发看板'; /* 分组浏览。*/ $lang->execution->allTasks = '所有'; diff --git a/module/execution/model.php b/module/execution/model.php index 549b58d0d2..840285edd6 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -381,7 +381,7 @@ class executionModel extends model $creatorExists = false; $teamMembers = array(); - $this->loadModel('kanban')->createExecutionLane($executionID); + if(isset($project) and $project->model != 'kanban') $this->loadModel('kanban')->createExecutionLane($executionID); /* Save order. */ $this->dao->update(TABLE_EXECUTION)->set('`order`')->eq($executionID * 5)->where('id')->eq($executionID)->exec(); diff --git a/module/execution/view/all.html.php b/module/execution/view/all.html.php index 4c46d38b2f..3652b0b19f 100644 --- a/module/execution/view/all.html.php +++ b/module/execution/view/all.html.php @@ -122,7 +122,8 @@ '>execution->typeList[$execution->type]?> children) ? $execution->name : html::a($this->createLink('execution', 'task', 'execution=' . $execution->id), $execution->name, '', "class='text-ellipsis'"); + $executionLink = $execution->projectModel == 'kanban' ? html::a($this->createLink('execution', 'kanban', 'executionID=' . $execution->id), $execution->name, '', "class='text-ellipsis'") : html::a($this->createLink('execution', 'task', 'execution=' . $execution->id), $execution->name, '', "class='text-ellipsis'"); + echo !empty($execution->children) ? $execution->name : $executionLink; if(isset($execution->delay)) echo "{$lang->execution->delayed} "; ?> children)):?> diff --git a/module/execution/view/taskkanban.html.php b/module/execution/view/taskkanban.html.php new file mode 100644 index 0000000000..28fb732228 --- /dev/null +++ b/module/execution/view/taskkanban.html.php @@ -0,0 +1,175 @@ + + + + +
+ +
+
+
+
+
+ + + + + + + + + common::hasPriv('kanban', 'setColumn'), + 'canSetWIP' => common::hasPriv('kanban', 'setWIP'), + 'canSetLane' => common::hasPriv('kanban', 'setLane'), + 'canMoveLane' => common::hasPriv('kanban', 'laneMove'), + 'canSortCards' => common::hasPriv('kanban', 'cardsSort'), + 'canCreateTask' => $canCreateTask, + 'canBatchCreateTask' => $canBatchCreateTask, + 'canCreateBug' => $canCreateBug, + 'canBatchCreateBug' => $canBatchCreateBug, + 'canCreateStory' => $canCreateStory, + 'canBatchCreateStory' => $canBatchCreateStory, + 'canLinkStory' => $canLinkStory, + 'canLinkStoryByPlane' => $canLinkStoryByPlane, + 'canAssignTask' => common::hasPriv('task', 'assignto'), + 'canAssignStory' => common::hasPriv('story', 'assignto'), + 'canFinishTask' => common::hasPriv('task', 'finish'), + 'canPauseTask' => common::hasPriv('task', 'pause'), + 'canCancelTask' => common::hasPriv('task', 'cancel'), + 'canCloseTask' => common::hasPriv('task', 'close'), + 'canActivateTask' => common::hasPriv('task', 'activate'), + 'canStartTask' => common::hasPriv('task', 'start'), + 'canAssignBug' => common::hasPriv('bug', 'assignto'), + 'canConfirmBug' => common::hasPriv('bug', 'confirmBug'), + 'canActivateBug' => common::hasPriv('bug', 'activate') + ) +); +?> +execution);?> +story);?> +task);?> +bug);?> +execution->editName);?> +execution->setWIP);?> +execution->sortColumn);?> +kanban);?> +task->deadlineAB);?> +task->noAssigned);?> + + + diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index bd9da48739..9a66f4c96d 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -759,7 +759,7 @@ $lang->resource->execution->linkStory = 'linkStory'; $lang->resource->execution->unlinkStory = 'unlinkStory'; $lang->resource->execution->batchUnlinkStory = 'batchUnlinkStory'; $lang->resource->execution->updateOrder = 'updateOrder'; -$lang->resource->execution->kanban = 'kanban'; +$lang->resource->execution->taskKanban = 'taskKanban'; $lang->resource->execution->printKanban = 'printKanbanAction'; $lang->resource->execution->tree = 'treeAction'; $lang->resource->execution->treeTask = 'treeOnlyTask'; @@ -775,6 +775,7 @@ $lang->resource->execution->addWhitelist = 'addWhitelist'; $lang->resource->execution->unbindWhitelist = 'unbindWhitelist'; $lang->resource->execution->storyEstimate = 'storyEstimate'; $lang->resource->execution->executionkanban = 'kanbanAction'; +$lang->resource->execution->kanban = 'RDKanban'; //if($config->systemMode == 'classic') $lang->resource->project->list = 'list'; //$lang->execution->methodOrder[0] = 'index'; @@ -816,7 +817,7 @@ $lang->execution->methodOrder[170] = 'linkStory'; $lang->execution->methodOrder[175] = 'unlinkStory'; $lang->execution->methodOrder[180] = 'batchUnlinkStory'; $lang->execution->methodOrder[185] = 'updateOrder'; -$lang->execution->methodOrder[190] = 'kanban'; +$lang->execution->methodOrder[190] = 'taskKanban'; $lang->execution->methodOrder[195] = 'printKanban'; $lang->execution->methodOrder[200] = 'kanbanHideCols'; $lang->execution->methodOrder[205] = 'kanbanColsColor'; @@ -832,6 +833,7 @@ $lang->execution->methodOrder[250] = 'addWhitelist'; $lang->execution->methodOrder[255] = 'unbindWhitelist'; $lang->execution->methodOrder[260] = 'storyEstimate'; $lang->execution->methodOrder[265] = 'executionkanban'; +$lang->execution->methodOrder[270] = 'kanban'; /* Task. */ $lang->resource->task = new stdclass(); diff --git a/module/kanban/model.php b/module/kanban/model.php index e3edc42ed7..3e0c29fa7b 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -1503,6 +1503,124 @@ class kanbanModel extends model } } + /** + * Create a default RD kanban. + * + * @param object $execution + * @access public + * @return void + */ + public function createRDKanban($execution) + { + $regionID = $this->createRDRegion($execution); + if(dao::isError()) return false; + + $groupID = $this->createGroup($execution->id, $regionID); + if(dao::isError()) return false; + + $this->createRDLane($execution->id, $regionID); + if(dao::isError()) return false; + } + + /** + * Create a default RD region. + * + * @param object $execution + * + * @access public + * @return int|bool + */ + public function createRDRegion($execution) + { + $region = new stdclass(); + $region->name = $this->lang->kanbanregion->default; + $region->kanban = $execution->id; + $region->createdBy = $this->app->user->account; + $region->createdDate = helper::today(); + $region->order = 1; + + $this->dao->insert(TABLE_KANBANREGION)->data($region) + ->check('name', 'unique', "kanban={$execution->id} AND deleted='0'") + ->autoCheck() + ->exec(); + + if(dao::isError()) return false; + return $this->dao->lastInsertId(); + } + + /** + * Create default RD lanes. + * + * @param int $executionID + * @param int $regionID + * + * @access public + * @return bool + */ + public function createRDLane($executionID, $regionID) + { + $laneIndex = 0; + foreach($this->lang->kanban->laneTypeList as $type => $name) + { + $groupID = $this->createGroup($executionID, $regionID); + if(dao::isError()) return false; + + $lane = new stdclass(); + $lane->execution = $executionID; + $lane->type = $type; + $lane->region = $regionID; + $lane->group = $groupID; + $lane->name = $name; + $lane->color = $this->config->kanban->laneColorList[$laneIndex]; + $lane->order = ++ $laneIndex * 5; + + $this->dao->insert(TABLE_KANBANLANE)->data($lane)->autoCheck()->exec(); + if(dao::isError()) return false; + + $this->createRDColumn($regionID, $groupID, $this->dao->lastInsertId(), $type); + } + } + + /** + * Create default RD columns. + * + * @param int $regionID + * @param int $groupID + * @param int $laneID + * @param string $laneType + * + * @access public + * @return bool + */ + public function createRDColumn($regionID, $groupID, $laneID, $laneType) + { + $devColumnID = $testColumnID = $resolvingColumnID = 0; + if($laneType == 'story') $columnList = $this->lang->kanban->storyColumn; + if($laneType == 'bug') $columnList = $this->lang->kanban->bugColumn; + if($laneType == 'task') $columnList = $this->lang->kanban->taskColumn; + + foreach($columnList as $type => $name) + { + $data = new stdClass(); + $data->lane = $laneID; + $data->name = $name; + $data->color = '#333'; + $data->type = $type; + + if(strpos(',developing,developed,', $type) !== false) $data->parent = $devColumnID; + if(strpos(',testing,tested,', $type) !== false) $data->parent = $testColumnID; + if(strpos(',fixing,fixed,', $type) !== false) $data->parent = $resolvingColumnID; + if(strpos(',develop,test,resolving,', $type) !== false) $data->parent = -1; + + $this->dao->insert(TABLE_KANBANCOLUMN)->data($data)->exec(); + if(dao::isError()) return false; + + if($type == 'develop') $devColumnID = $this->dao->lastInsertId(); + if($type == 'test') $testColumnID = $this->dao->lastInsertId(); + if($type == 'resolving') $resolvingColumnID = $this->dao->lastInsertId(); + } + } + /** * Update a region. * diff --git a/module/project/model.php b/module/project/model.php index 1633a24e75..015b91979e 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -1834,7 +1834,7 @@ class projectModel extends model ->fetchPairs(); } - $executions = $this->dao->select('t1.*,t2.name projectName')->from(TABLE_EXECUTION)->alias('t1') + $executions = $this->dao->select('t1.*,t2.name projectName, t2.model as projectModel')->from(TABLE_EXECUTION)->alias('t1') ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') ->where('t1.type')->in('sprint,stage') ->beginIF($projectID != 0)->andWhere('t1.project')->eq($projectID)->fi() @@ -1849,7 +1849,7 @@ class projectModel extends model } else { - $executions = $this->dao->select('t2.*,t3.name projectName')->from(TABLE_PROJECTPRODUCT)->alias('t1') + $executions = $this->dao->select('t2.*,t3.name projectName, t3.model as projectModel')->from(TABLE_PROJECTPRODUCT)->alias('t1') ->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.project=t2.id') ->leftJoin(TABLE_PROJECT)->alias('t3')->on('t2.project=t3.id') ->where('t1.product')->eq($productID) From b3681c395a7d557ea09e651013c8027971abbdd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B9=BF=E6=98=8E?= Date: Tue, 11 Jan 2022 16:18:07 +0800 Subject: [PATCH 06/85] * Refactor kanban. --- db/update16.1.sql | 9 ++--- db/zentao.sql | 13 +++---- module/kanban/model.php | 84 ++++++++++++++++++++++++++++------------- 3 files changed, 67 insertions(+), 39 deletions(-) diff --git a/db/update16.1.sql b/db/update16.1.sql index 30870b5441..1f7e3173b3 100644 --- a/db/update16.1.sql +++ b/db/update16.1.sql @@ -1,13 +1,12 @@ -CREATE TABLE `zt_kanbancardgroup` ( +CREATE TABLE `zt_kanbancell` ( `id` int(8) NOT NULL AUTO_INCREMENT, `kanban` mediumint(8) NOT NULL, - `objectType` char(30) NOT NULL, - `objectID` mediumint(8) NOT NULL, `lane` mediumint(8) NOT NULL, `column` mediumint(8) NOT NULL, - `order` mediumint(8) NOT NULL, + `type` char(30) NOT NULL, + `cards` text NOT NULL, PRIMARY KEY (`id`), - UNIQUE KEY `card_group` (`kanban`,`objectType`,`objectID`,`lane`,`column`) + UNIQUE KEY `card_group` (`kanban`,`type`,`lane`,`column`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; ALTER TABLE `zt_kanban` ADD `displayCards` smallint(6) NOT NULL AFTER `order`; diff --git a/db/zentao.sql b/db/zentao.sql index f687d2b7be..7638b9a2d0 100644 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -707,8 +707,6 @@ CREATE TABLE `zt_kanbancard` ( `kanban` mediumint(8) unsigned NOT NULL, `region` mediumint(8) unsigned NOT NULL, `group` mediumint(8) unsigned NOT NULL, - `lane` mediumint(8) unsigned NOT NULL, - `column` mediumint(8) unsigned NOT NULL, `name` varchar(255) NOT NULL, `pri` mediumint(8) unsigned NOT NULL, `assignedTo` text NOT NULL, @@ -732,17 +730,16 @@ CREATE TABLE `zt_kanbancard` ( `deleted` enum('0', '1') NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; --- DROP TABLE IF EXISTS `zt_kanbancardgroup`; -CREATE TABLE `zt_kanbancardgroup` ( +-- DROP TABLE IF EXISTS `zt_kanbancell`; +CREATE TABLE `zt_kanbancell` ( `id` int(8) NOT NULL AUTO_INCREMENT, `kanban` mediumint(8) NOT NULL, - `objectType` char(30) NOT NULL, - `objectID` mediumint(8) NOT NULL, `lane` mediumint(8) NOT NULL, `column` mediumint(8) NOT NULL, - `order` mediumint(8) NOT NULL, + `type` char(30) NOT NULL, + `cards` text NOT NULL, PRIMARY KEY (`id`), - UNIQUE KEY `card_group` (`kanban`,`objectType`,`objectID`,`lane`,`column`) + UNIQUE KEY `card_group` (`kanban`,`type`,`lane`,`column`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_kanbangroup`; CREATE TABLE `zt_kanbangroup` ( diff --git a/module/kanban/model.php b/module/kanban/model.php index 3e0c29fa7b..1303fba193 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -1406,6 +1406,7 @@ class kanbanModel extends model } } + $cards = ''; $devColumnID = $testColumnID = $resolvingColumnID = 0; if($type == 'story') { @@ -1416,25 +1417,26 @@ class kanbanModel extends model $data->name = $name; $data->color = '#333'; $data->type = $colType; - $data->cards = ''; if(strpos(',developing,developed,', $colType) !== false) $data->parent = $devColumnID; if(strpos(',testing,tested,', $colType) !== false) $data->parent = $testColumnID; if(strpos(',develop,test,', $colType) !== false) $data->parent = -1; + + $this->dao->insert(TABLE_KANBANCOLUMN)->data($data)->exec(); + + $colID = $this->dao->lastInsertId(); + if($colType == 'develop') $devColumnID = $colID; + if($colType == 'test') $testColumnID = $colID; + if(strpos(',ready,develop,test,', $colType) === false) { $storyStatus = $this->config->kanban->storyColumnStatusList[$colType]; $storyStage = $this->config->kanban->storyColumnStageList[$colType]; foreach($objects as $storyID => $story) { - if($story->status == $storyStatus and $story->stage == $storyStage) $data->cards .= $storyID . ','; + if($story->status == $storyStatus and $story->stage == $storyStage) $cards .= $storyID . ','; } - if(!empty($data->cards)) $data->cards = ',' . $data->cards; } - - $this->dao->insert(TABLE_KANBANCOLUMN)->data($data)->exec(); - if($colType == 'develop') $devColumnID = $this->dao->lastInsertId(); - if($colType == 'test') $testColumnID = $this->dao->lastInsertId(); } } elseif($type == 'bug') @@ -1446,10 +1448,16 @@ class kanbanModel extends model $data->name = $name; $data->color = '#333'; $data->type = $colType; - $data->cards = ''; if(strpos(',fixing,fixed,', $colType) !== false) $data->parent = $resolvingColumnID; if(strpos(',testing,tested,', $colType) !== false) $data->parent = $testColumnID; if(strpos(',resolving,test,', $colType) !== false) $data->parent = -1; + + $this->dao->insert(TABLE_KANBANCOLUMN)->data($data)->exec(); + + $colID = $this->dao->lastInsertId(); + if($colType == 'resolving') $resolvingColumnID = $colID; + if($colType == 'test') $testColumnID = $colID; + if(strpos(',resolving,fixing,test,testing,tested,', $colType) === false) { $bugStatus = $this->config->kanban->bugColumnStatusList[$colType]; @@ -1457,22 +1465,18 @@ class kanbanModel extends model { if($colType == 'unconfirmed' and $bug->status == $bugStatus and $bug->confirmed == 0) { - $data->cards .= $bugID . ','; + $cards .= $bugID . ','; } elseif($colType == 'confirmed' and $bug->status == $bugStatus and $bug->confirmed == 1) { - $data->cards .= $bugID . ','; + $cards .= $bugID . ','; } elseif(strpos(',unconfirmed,confirmed,', $colType) === false and $bug->status == $bugStatus) { - $data->cards .= $bugID . ','; + $cards .= $bugID . ','; } } - if(!empty($data->cards)) $data->cards = ',' . $data->cards; } - $this->dao->insert(TABLE_KANBANCOLUMN)->data($data)->exec(); - if($colType == 'resolving') $resolvingColumnID = $this->dao->lastInsertId(); - if($colType == 'test') $testColumnID = $this->dao->lastInsertId(); } } elseif($type == 'task') @@ -1484,23 +1488,51 @@ class kanbanModel extends model $data->name = $name; $data->color = '#333'; $data->type = $colType; - $data->cards = ''; if(strpos(',developing,developed,', $colType) !== false) $data->parent = $devColumnID; if($colType == 'develop') $data->parent = -1; - if(strpos(',develop,', $colType) === false) - { - $taskStatus = $this->config->kanban->taskColumnStatusList[$colType]; - foreach($objects as $taskID => $task) - { - if($task->status == $taskStatus) $data->cards .= $taskID . ','; - } - if(!empty($data->cards)) $data->cards = ',' . $data->cards; - } $this->dao->insert(TABLE_KANBANCOLUMN)->data($data)->exec(); - if($colType == 'develop') $devColumnID = $this->dao->lastInsertId(); + + $colID = $this->dao->lastInsertId(); + if($colType == 'develop') $devColumnID = $colID; + } + + if(strpos(',develop,', $colType) === false) + { + $taskStatus = $this->config->kanban->taskColumnStatusList[$colType]; + foreach($objects as $taskID => $task) + { + if($task->status == $taskStatus) $cards .= $taskID . ','; + } } } + + if(!empty($cards)) $this->parkCards($executionID, $laneID, $colID, $cards, $type); + } + + /** + * Park cards into kanban cell. + * + * @param int $kanbanID + * @param int $laneID + * @param int $colID + * @param string $cards + * @param string $type + * @access public + * @return void + */ + public function parkCards($kanbanID, $laneID, $colID, $cards, $type) + { + $cards = ',' . $cards; + + $cardGroup = new stdclass(); + $cardGroup->kanban = $executionID; + $cardGroup->lane = $laneID; + $cardGroup->column = $colID; + $cardGroup->type = $type; + $cardGroup->cards = $cards; + + $this->dao->insert(TABLE_KANBANCELL)->data($cardGroup)->exec(); } /** From aca23db3461549a12f47bfa3fd3fc0762a362a16 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Tue, 11 Jan 2022 17:02:17 +0800 Subject: [PATCH 07/85] * Finish task #47358. --- module/group/lang/resource.php | 2 + module/kanban/control.php | 27 ++++++++++ module/kanban/js/setlaneheight.js | 17 ++++++ module/kanban/js/view.js | 16 ++++++ module/kanban/lang/en.php | 11 ++++ module/kanban/lang/zh-cn.php | 10 ++++ module/kanban/model.php | 64 ++++++++++++++++++++--- module/kanban/view/setlaneheight.html.php | 38 ++++++++++++++ 8 files changed, 178 insertions(+), 7 deletions(-) create mode 100644 module/kanban/js/setlaneheight.js create mode 100644 module/kanban/view/setlaneheight.html.php diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index 9a66f4c96d..e72e4e7126 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -674,6 +674,7 @@ $lang->resource->kanban->cardsSort = 'cardsSort'; $lang->resource->kanban->viewArchivedColumn = 'viewArchivedColumn'; $lang->resource->kanban->viewArchivedCard = 'viewArchivedCard'; $lang->resource->kanban->restoreCard = 'restoreCard'; +$lang->resource->kanban->setLaneHeight = 'setLaneHeight'; $lang->kanban->methodOrder[5] = 'space'; $lang->kanban->methodOrder[10] = 'createSpace'; @@ -718,6 +719,7 @@ $lang->kanban->methodOrder[195] = 'viewArchivedColumn'; $lang->kanban->methodorder[200] = 'viewArchivedCard'; $lang->kanban->methodorder[205] = 'archiveColumn'; $lang->kanban->methodorder[210] = 'restoreCard'; +$lang->kanban->methodorder[215] = 'setLaneHeight'; /* Execution. */ $lang->resource->execution = new stdclass(); diff --git a/module/kanban/control.php b/module/kanban/control.php index daaa210ea3..1730ffa893 100644 --- a/module/kanban/control.php +++ b/module/kanban/control.php @@ -457,6 +457,33 @@ class kanban extends control return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess)); } + /** + * Set lane height. + * + * @param int $kanbanID + * @param string $from kanban|execution + * @access public + * @return void + */ + public function setLaneHeight($kanbanID, $from = 'kanban') + { + if(!empty($_POST)) + { + $this->kanban->setLaneHeight($kanbanID, $from); + + if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); + + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent')); + + } + + if($from == 'execution') $this->loadModel('execution'); + + $this->view->kanban = $this->$from->getByID($kanbanID); + + $this->display(); + } + /** * Delete a lane. * diff --git a/module/kanban/js/setlaneheight.js b/module/kanban/js/setlaneheight.js new file mode 100644 index 0000000000..4f37eb4763 --- /dev/null +++ b/module/kanban/js/setlaneheight.js @@ -0,0 +1,17 @@ +/** + * Set card count. + * + * @param string $heightType + * @access public + * @return void + */ +function setCardCount(heightType) +{ + heightType != 'custom' ? $('#cardBox').addClass('hidden') : $('#cardBox').removeClass('hidden'); +} + +$(function() +{ + var heightType = $("[name='heightType']:checked").val(); + setCardCount(heightType); +}) diff --git a/module/kanban/js/view.js b/module/kanban/js/view.js index 49ec25d957..c69c6516fc 100644 --- a/module/kanban/js/view.js +++ b/module/kanban/js/view.js @@ -1012,4 +1012,20 @@ $(function() if(sortType == 'lane') $cards.show(); } }); + + if(Object.keys(regions).length == 1) + { + var regionID = Object.keys(regions)[0]; + var region = regions[regionID].groups; + if(Object.keys(region).length == 1) + { + var group = region[0]; + if(Object.keys(group.lanes).length == 1) + { + var windowHeight = $(window).height(); + $('.region').css('height', windowHeight -132); + $('.kanban-lane').css('height', windowHeight - 222); + } + } + } }); diff --git a/module/kanban/lang/en.php b/module/kanban/lang/en.php index 7ba2b2d2c4..9075c9e2b8 100644 --- a/module/kanban/lang/en.php +++ b/module/kanban/lang/en.php @@ -18,6 +18,8 @@ $lang->kanban->deleteRegion = 'Delete Region'; $lang->kanban->createLane = 'Create Lane'; $lang->kanban->editLane = 'Edit Lane'; $lang->kanban->sortLane = 'Sort Lane'; +$lang->kanban->laneHeight = 'Lane Height'; +$lang->kanban->setLaneHeight = 'Set Lane Height'; $lang->kanban->deleteLane = 'Delete Lane'; $lang->kanban->createColumn = 'Create Column'; $lang->kanban->editColumn = 'Edit Column'; @@ -73,12 +75,14 @@ $lang->kanban->closedBy = 'Closed By'; $lang->kanban->closedDate = 'Closed Date'; $lang->kanban->empty = 'No Kanban'; $lang->kanban->teamSumCount = '%s people in total'; +$lang->kanban->cardCount = 'Card Count'; $lang->kanban->createColumnOnLeft = 'Create Column On Left'; $lang->kanban->createColumnOnRight = 'Create Column On Right'; $lang->kanban->accessDenied = "You have no access to the kanban."; $lang->kanban->confirmDelete = 'Do you want to delete this?'; +$lang->kanban->cardCountTip = 'Please enter the number of cards'; $lang->kanban->aclGroup['open'] = 'Open'; $lang->kanban->aclGroup['private'] = 'Private'; @@ -250,6 +254,13 @@ $lang->kanbanlane->confirmDelete = 'Are you sure to delete this lane? After dele $lang->kanbanlane->modeList['sameAsOther'] = 'Use the same Kanban column as other lanes'; $lang->kanbanlane->modeList['independent'] = 'Independent Kanban column is adopted'; +$lang->kanbanlane->heightTypeList['auto'] = 'Adaptive (Adaptive according to the card height)'; +$lang->kanbanlane->heightTypeList['custom'] = 'Custom (Customize lane height based on number of cards)'; + +$lang->kanbanlane->error = new stdclass(); +$lang->kanbanlane->error->mustBeInt = 'The number of cards must be a positive integer greater than 2.'; + + $lang->kanbanregion = new stdclass(); $lang->kanbanregion->name = 'Region Name'; $lang->kanbanregion->default = 'Default Region'; diff --git a/module/kanban/lang/zh-cn.php b/module/kanban/lang/zh-cn.php index 62a58dec97..46e3890c0c 100644 --- a/module/kanban/lang/zh-cn.php +++ b/module/kanban/lang/zh-cn.php @@ -18,6 +18,8 @@ $lang->kanban->deleteRegion = '删除区域'; $lang->kanban->createLane = '创建泳道'; $lang->kanban->editLane = '泳道设置'; $lang->kanban->sortLane = '泳道排序'; +$lang->kanban->laneHeight = '泳道高度'; +$lang->kanban->setLaneHeight = '设置泳道高度'; $lang->kanban->deleteLane = '删除泳道'; $lang->kanban->createColumn = '创建看板列'; $lang->kanban->editColumn = '编辑看板列'; @@ -73,12 +75,14 @@ $lang->kanban->closedBy = '由谁关闭'; $lang->kanban->closedDate = '关闭日期'; $lang->kanban->empty = '暂时没有看板'; $lang->kanban->teamSumCount = '共%s人'; +$lang->kanban->cardCount = '卡片数量'; $lang->kanban->createColumnOnLeft = '在左侧添加看板列'; $lang->kanban->createColumnOnRight = '在右侧添加看板列'; $lang->kanban->accessDenied = '您无权访问该看板'; $lang->kanban->confirmDelete = '您确认删除吗?'; +$lang->kanban->cardCountTip = '请输入卡片数量'; $lang->kanban->aclGroup['open'] = '公开'; $lang->kanban->aclGroup['private'] = '私有'; @@ -250,6 +254,12 @@ $lang->kanbanlane->confirmDelete = '您确认删除该泳道吗?删除泳道 $lang->kanbanlane->modeList['sameAsOther'] = '与其他泳道使用相同看板列'; $lang->kanbanlane->modeList['independent'] = '采用独立的看板列'; +$lang->kanbanlane->heightTypeList['auto'] = '自适应(根据卡片高度自适应)'; +$lang->kanbanlane->heightTypeList['custom'] = '自定义(根据卡片数量自定义泳道高度)'; + +$lang->kanbanlane->error = new stdclass(); +$lang->kanbanlane->error->mustBeInt = '卡片数量必须是大于2的正整数。'; + $lang->kanbanregion = new stdclass(); $lang->kanbanregion->name = '区域名称'; $lang->kanbanregion->default = '默认区域'; diff --git a/module/kanban/model.php b/module/kanban/model.php index 1303fba193..3ffe4c260d 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -2117,6 +2117,36 @@ class kanbanModel extends model return dao::isError(); } + /** + * Set lane height. + * + * @param int $kanbanID + * @param string $from kanban|execution + * @access public + * @return bool + */ + public function setLaneHeight($kanbanID, $from = 'kanban') + { + $kanbanID = (int)$kanbanID; + $kanban = fixer::input('post') + ->setIF($this->post->heightType == 'auto', 'displayCards', 0) + ->get(); + + if($kanban->heightType == 'custom') + { + if(!preg_match("/^-?\d+$/", $kanban->displayCards) or $kanban->displayCards < 3) + { + dao::$errors['displayCards'] = $this->lang->kanbanlane->error->mustBeInt; + return false; + } + } + + $table = $this->config->objectTables[$from]; + $this->dao->update($table)->set('displayCards')->eq((int)$kanban->displayCards)->where('id')->eq($kanbanID)->exec(); + + if(dao::isError()) return false; + } + /** * Set kanban headerActions. * @@ -2126,24 +2156,44 @@ class kanbanModel extends model */ public function setHeaderActions($kanban) { - $actions = ''; - $actions .= "
"; - $actions .= " {$this->lang->kanban->fullScreen}"; - $printSettingBtn = (common::hasPriv('kanban', 'createRegion') or common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'delete')); + $actions = ''; + $actions .= "
"; + $actions .= " {$this->lang->kanban->fullScreen}"; + $printSetHeight = false; + if(common::hasPriv('kanban', 'setLaneHeight')) + { + $lanes = $this->dao->select('t2.id')->from(TABLE_KANBANREGION)->alias('t1') + ->leftJoin(TABLE_KANBANLANE)->alias('t2')->on('t1.id=t2.region') + ->where('t1.kanban')->eq($kanban->id) + ->andWhere('t1.deleted')->eq(0) + ->andWhere('t2.deleted')->eq(0) + ->fetchPairs(); + + if(count($lanes) > 1) $printSetHeight = true; + } + + $printSettingBtn = (common::hasPriv('kanban', 'createRegion') or $printSetHeight or common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'delete')); + if($printSettingBtn) { $actions .= "" . ' ' . $this->lang->kanban->setting . ''; $actions .= ""; } diff --git a/module/kanban/view/setlaneheight.html.php b/module/kanban/view/setlaneheight.html.php new file mode 100644 index 0000000000..8409fc9ad8 --- /dev/null +++ b/module/kanban/view/setlaneheight.html.php @@ -0,0 +1,38 @@ + + * @package kanban + * @version $Id: setlaneheight.html.php 935 2022-01-11 10:49:24Z $ + * @link https://www.zentao.net + */ +?> + +
+
+
+

kanban->setLaneHeight;?>

+
+
+ + + + + + + + + + + + +
kanban->laneHeight;?>kanbanlane->heightTypeList, 'custom', "onclick='setCardCount(this.value);'"));?>
+ +
+
+
+
+ From 9faee43d47f4e2789bf79b335cd2be77cc02dd54 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Tue, 11 Jan 2022 17:07:40 +0800 Subject: [PATCH 08/85] * Modify default value. --- module/kanban/control.php | 4 +++- module/kanban/view/setlaneheight.html.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/module/kanban/control.php b/module/kanban/control.php index 1730ffa893..640e004377 100644 --- a/module/kanban/control.php +++ b/module/kanban/control.php @@ -479,7 +479,9 @@ class kanban extends control if($from == 'execution') $this->loadModel('execution'); - $this->view->kanban = $this->$from->getByID($kanbanID); + $kanban = $this->$from->getByID($kanbanID); + + $this->view->heightType = $kanban->displayCards > 2 ? 'custom' : 'auto'; $this->display(); } diff --git a/module/kanban/view/setlaneheight.html.php b/module/kanban/view/setlaneheight.html.php index 8409fc9ad8..d41e84b686 100644 --- a/module/kanban/view/setlaneheight.html.php +++ b/module/kanban/view/setlaneheight.html.php @@ -20,7 +20,7 @@ - + From cf829b4731e8b234d1834039ebcb9ede603a3c26 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Tue, 11 Jan 2022 17:14:27 +0800 Subject: [PATCH 09/85] * Add new icons: "size-height" and "inherit-space". --- www/theme/zui/css/min.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/www/theme/zui/css/min.css b/www/theme/zui/css/min.css index cba0ca7062..ead471140a 100644 --- a/www/theme/zui/css/min.css +++ b/www/theme/zui/css/min.css @@ -1,8 +1,8 @@ /*! - * ZUI: ZUI for Zentao - v1.10.0 - 2021-12-31 + * ZUI: ZUI for Zentao - v1.10.0 - 2022-01-11 * http://openzui.com * GitHub: https://github.com/easysoft/zui.git - * Copyright (c) 2021 cnezsoft.com; Licensed MIT + * Copyright (c) 2022 cnezsoft.com; Licensed MIT *//*! normalize.css v2.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}a{background:0 0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{margin:.67em 0;font-size:2em}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}mark{color:#000;background:#ff0}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}button,input,select,textarea{margin:0;font-family:inherit;font-size:100%}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}textarea{overflow:auto;vertical-align:top}table{border-spacing:0;border-collapse:collapse}#userMenu:after,#userMenu:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fixed-md:after,.container-fixed-md:before,.container-fixed-sm:after,.container-fixed-sm:before,.container-fixed-xs:after,.container-fixed-xs:before,.container-fixed:after,.container-fixed:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.dl-inline:after,.dl-inline:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.modal-header:after,.modal-header:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager-justify:after,.pager-justify:before,.pager-loose:after,.pager-loose:before,.row:after,.row:before,.table-footer:after,.table-footer:before{display:table;content:" "}#userMenu:after,.btn-toolbar:after,.clearfix:after,.container-fixed-md:after,.container-fixed-sm:after,.container-fixed-xs:after,.container-fixed:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.dl-inline:after,.form-horizontal .form-group:after,.modal-footer:after,.modal-header:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager-justify:after,.pager-loose:after,.row:after,.table-footer:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none}.showing{display:block}.hidden{display:none!important;visibility:hidden!important}.show{display:block!important;visibility:visible!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.affix{position:fixed}.with-padding{padding:5px 12px}.no-padding{padding:0!important}.no-margin{margin:0!important}.inline-block.visible-xs,.inline.visible-xs,.visible-xs,td.visible-xs,th.visible-xs,tr.visible-xs{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}.inline.visible-xs{display:inline!important}.inline-block.visible-xs{display:inline-block!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block!important}.inline.visible-xs.visible-sm{display:inline!important}.inline-block.visible-xs.visible-sm{display:inline-block!important}tr.visible-xs.visible-sm{display:table-row!important}td.visible-xs.visible-sm,th.visible-xs.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1799px){.visible-xs.visible-md{display:block!important}.inline.visible-xs.visible-md{display:inline!important}.inline-block.visible-xs.visible-md{display:inline-block!important}tr.visible-xs.visible-md{display:table-row!important}td.visible-xs.visible-md,th.visible-xs.visible-md{display:table-cell!important}}@media (min-width:1800px){.visible-xs.visible-lg{display:block!important}.inline.visible-xs.visible-lg{display:inline!important}.inline-block.visible-xs.visible-lg{display:inline-block!important}tr.visible-xs.visible-lg{display:table-row!important}td.visible-xs.visible-lg,th.visible-xs.visible-lg{display:table-cell!important}}.inline-block.visible-sm,.inline.visible-sm,.visible-sm,td.visible-sm,th.visible-sm,tr.visible-sm{display:none!important}@media (max-width:767px){.visible-sm.visible-xs{display:block!important}.inline.visible-sm.visible-xs{display:inline!important}.inline-block.visible-sm.visible-xs{display:inline-block!important}tr.visible-sm.visible-xs{display:table-row!important}td.visible-sm.visible-xs,th.visible-sm.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}.inline.visible-sm{display:inline!important}.inline-block.visible-sm{display:inline-block!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1799px){.visible-sm.visible-md{display:block!important}.inline.visible-sm.visible-md{display:inline!important}.inline-block.visible-sm.visible-md{display:inline-block!important}tr.visible-sm.visible-md{display:table-row!important}td.visible-sm.visible-md,th.visible-sm.visible-md{display:table-cell!important}}@media (min-width:1800px){.visible-sm.visible-lg{display:block!important}.inline.visible-sm.visible-lg{display:inline!important}.inline-block.visible-sm.visible-lg{display:inline-block!important}tr.visible-sm.visible-lg{display:table-row!important}td.visible-sm.visible-lg,th.visible-sm.visible-lg{display:table-cell!important}}.inline-block.visible-md,.inline.visible-md,.visible-md,td.visible-md,th.visible-md,tr.visible-md{display:none!important}@media (max-width:767px){.visible-md.visible-xs{display:block!important}.inline.visible-md.visible-xs{display:inline!important}.inline-block.visible-md.visible-xs{display:inline-block!important}tr.visible-md.visible-xs{display:table-row!important}td.visible-md.visible-xs,th.visible-md.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block!important}.inline.visible-md.visible-sm{display:inline!important}.inline-block.visible-md.visible-sm{display:inline-block!important}tr.visible-md.visible-sm{display:table-row!important}td.visible-md.visible-sm,th.visible-md.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1799px){.visible-md{display:block!important}.inline.visible-md{display:inline!important}.inline-block.visible-md{display:inline-block!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:1800px){.visible-md.visible-lg{display:block!important}.inline.visible-md.visible-lg{display:inline!important}.inline-block.visible-md.visible-lg{display:inline-block!important}tr.visible-md.visible-lg{display:table-row!important}td.visible-md.visible-lg,th.visible-md.visible-lg{display:table-cell!important}}.inline-block.visible-lg,.inline.visible-lg,.visible-lg,td.visible-lg,th.visible-lg,tr.visible-lg{display:none!important}@media (max-width:767px){.visible-lg.visible-xs{display:block!important}.inline.visible-lg.visible-xs{display:inline!important}.inline-block.visible-lg.visible-xs{display:inline-block!important}tr.visible-lg.visible-xs{display:table-row!important}td.visible-lg.visible-xs,th.visible-lg.visible-xs{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block!important}.inline.visible-lg.visible-sm{display:inline!important}.inline-block.visible-lg.visible-sm{display:inline-block!important}tr.visible-lg.visible-sm{display:table-row!important}td.visible-lg.visible-sm,th.visible-lg.visible-sm{display:table-cell!important}}@media (min-width:992px) and (max-width:1799px){.visible-lg.visible-md{display:block!important}.inline.visible-lg.visible-md{display:inline!important}.inline-block.visible-lg.visible-md{display:inline-block!important}tr.visible-lg.visible-md{display:table-row!important}td.visible-lg.visible-md,th.visible-lg.visible-md{display:table-cell!important}}@media (min-width:1800px){.visible-lg{display:block!important}.inline.visible-lg{display:inline!important}.inline-block.visible-lg{display:inline-block!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}.hidden-xs{display:block!important}.inline.hidden-xs{display:inline!important}.inline-block.hidden-xs{display:inline-block!important}tr.hidden-xs{display:table-row!important}td.hidden-xs,th.hidden-xs{display:table-cell!important}@media (max-width:767px){.hidden-xs,.inline-block.hidden-xs,.inline.hidden-xs,td.hidden-xs,th.hidden-xs,tr.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm,.inline-block.hidden-xs.hidden-sm,.inline.hidden-xs.hidden-sm,td.hidden-xs.hidden-sm,th.hidden-xs.hidden-sm,tr.hidden-xs.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1799px){.hidden-xs.hidden-md,.inline-block.hidden-xs.hidden-md,.inline.hidden-xs.hidden-md,td.hidden-xs.hidden-md,th.hidden-xs.hidden-md,tr.hidden-xs.hidden-md{display:none!important}}@media (min-width:1800px){.hidden-xs.hidden-lg,.inline-block.hidden-xs.hidden-lg,.inline.hidden-xs.hidden-lg,td.hidden-xs.hidden-lg,th.hidden-xs.hidden-lg,tr.hidden-xs.hidden-lg{display:none!important}}.hidden-sm{display:block!important}.inline.hidden-sm{display:inline!important}.inline-block.hidden-sm{display:inline-block!important}tr.hidden-sm{display:table-row!important}td.hidden-sm,th.hidden-sm{display:table-cell!important}@media (max-width:767px){.hidden-sm.hidden-xs,.inline-block.hidden-sm.hidden-xs,.inline.hidden-sm.hidden-xs,td.hidden-sm.hidden-xs,th.hidden-sm.hidden-xs,tr.hidden-sm.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm,.inline-block.hidden-sm,.inline.hidden-sm,td.hidden-sm,th.hidden-sm,tr.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1799px){.hidden-sm.hidden-md,.inline-block.hidden-sm.hidden-md,.inline.hidden-sm.hidden-md,td.hidden-sm.hidden-md,th.hidden-sm.hidden-md,tr.hidden-sm.hidden-md{display:none!important}}@media (min-width:1800px){.hidden-sm.hidden-lg,.inline-block.hidden-sm.hidden-lg,.inline.hidden-sm.hidden-lg,td.hidden-sm.hidden-lg,th.hidden-sm.hidden-lg,tr.hidden-sm.hidden-lg{display:none!important}}.hidden-md{display:block!important}.inline.hidden-md{display:inline!important}.inline-block.hidden-md{display:inline-block!important}tr.hidden-md{display:table-row!important}td.hidden-md,th.hidden-md{display:table-cell!important}@media (max-width:767px){.hidden-md.hidden-xs,.inline-block.hidden-md.hidden-xs,.inline.hidden-md.hidden-xs,td.hidden-md.hidden-xs,th.hidden-md.hidden-xs,tr.hidden-md.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-md.hidden-sm,.inline-block.hidden-md.hidden-sm,.inline.hidden-md.hidden-sm,td.hidden-md.hidden-sm,th.hidden-md.hidden-sm,tr.hidden-md.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1799px){.hidden-md,.inline-block.hidden-md,.inline.hidden-md,td.hidden-md,th.hidden-md,tr.hidden-md{display:none!important}}@media (min-width:1800px){.hidden-md.hidden-lg,.inline-block.hidden-md.hidden-lg,.inline.hidden-md.hidden-lg,td.hidden-md.hidden-lg,th.hidden-md.hidden-lg,tr.hidden-md.hidden-lg{display:none!important}}.hidden-lg{display:block!important}.inline.hidden-lg{display:inline!important}.inline-block.hidden-lg{display:inline-block!important}tr.hidden-lg{display:table-row!important}td.hidden-lg,th.hidden-lg{display:table-cell!important}@media (max-width:767px){.hidden-lg.hidden-xs,.inline-block.hidden-lg.hidden-xs,.inline.hidden-lg.hidden-xs,td.hidden-lg.hidden-xs,th.hidden-lg.hidden-xs,tr.hidden-lg.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-lg.hidden-sm,.inline-block.hidden-lg.hidden-sm,.inline.hidden-lg.hidden-sm,td.hidden-lg.hidden-sm,th.hidden-lg.hidden-sm,tr.hidden-lg.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1799px){.hidden-lg.hidden-md,.inline-block.hidden-lg.hidden-md,.inline.hidden-lg.hidden-md,td.hidden-lg.hidden-md,th.hidden-lg.hidden-md,tr.hidden-lg.hidden-md{display:none!important}}@media (min-width:1800px){.hidden-lg,.inline-block.hidden-lg,.inline.hidden-lg,td.hidden-lg,th.hidden-lg,tr.hidden-lg{display:none!important}}.inline-block.visible-print,.inline.visible-print,.visible-print,td.visible-print,th.visible-print,tr.visible-print{display:none!important}@media print{.visible-print{display:block!important}.inline.visible-print{display:inline!important}.inline-block.visible-print{display:inline-block!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}.hidden-print,.inline-block.hidden-print,.inline.hidden-print,td.hidden-print,th.hidden-print,tr.hidden-print{display:none!important}}*,:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Tahoma,Arial,'PingFang SC','Source Han Sans CN','Source Han Sans','Source Han Serif','Hiragino Sans GB','WenQuanYi Micro Hei','Microsoft YaHei',sans-serif;font-size:13px;line-height:1.42857143;color:#3c4353;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#3c4353;text-decoration:none;cursor:pointer;-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:color,background,opacity,-webkit-transform;-o-transition-property:color,background,opacity,-o-transform;transition-property:color,background,opacity,-webkit-transform;transition-property:color,background,transform,opacity;transition-property:color,background,transform,opacity,-webkit-transform,-o-transform}a:focus,a:hover{color:#0c64eb;text-decoration:none}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a.disabled,a.disabled:focus,a.disabled:hover,a[disabled],a[disabled]:focus,a[disabled]:hover{color:#aaa;text-decoration:none;cursor:default}audio,canvas,img,video{max-width:100%;vertical-align:middle}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);border:0}::-moz-selection{text-shadow:none;background:#b3d4fc}::selection{text-shadow:none;background:#b3d4fc}fieldset{padding:0;margin:0;border:0}textarea{resize:vertical}ol,ul{padding-left:20px}.scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}.container,.container-fixed,.container-fixed-md,.container-fixed-sm,.container-fixed-xs,.container-fluid{padding-right:10px;padding-left:10px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{max-width:972px}}@media (min-width:992px){.container{max-width:1760px}}@media (min-width:1800px){.container{max-width:1760px}}.container-fixed{width:1760px}.container-fixed-md{width:1760px}.container-fixed-sm{width:972px}.container-fixed-xs{width:748px}.row{margin-right:-10px;margin-left:-10px}.col,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:10px;padding-left:10px}.col,.col-xs,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-1,.col-xs-1{width:8.33333333%}.col-2,.col-xs-2{width:16.66666667%}.col-3,.col-xs-3{width:25%}.col-4,.col-xs-4{width:33.33333333%}.col-5,.col-xs-5{width:41.66666667%}.col-6,.col-xs-6{width:50%}.col-7,.col-xs-7{width:58.33333333%}.col-8,.col-xs-8{width:66.66666667%}.col-9,.col-xs-9{width:75%}.col-10,.col-xs-10{width:83.33333333%}.col-11,.col-xs-11{width:91.66666667%}.col-12,.col-xs-12{width:100%}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-1{width:8.33333333%}.col-sm-2{width:16.66666667%}.col-sm-3{width:25%}.col-sm-4{width:33.33333333%}.col-sm-5{width:41.66666667%}.col-sm-6{width:50%}.col-sm-7{width:58.33333333%}.col-sm-8{width:66.66666667%}.col-sm-9{width:75%}.col-sm-10{width:83.33333333%}.col-sm-11{width:91.66666667%}.col-sm-12{width:100%}.col-sm-push-1{left:8.33333333%}.col-sm-push-2{left:16.66666667%}.col-sm-push-3{left:25%}.col-sm-push-4{left:33.33333333%}.col-sm-push-5{left:41.66666667%}.col-sm-push-6{left:50%}.col-sm-push-7{left:58.33333333%}.col-sm-push-8{left:66.66666667%}.col-sm-push-9{left:75%}.col-sm-push-10{left:83.33333333%}.col-sm-push-11{left:91.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-3{right:25%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-6{right:50%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-9{right:75%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-11{right:91.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-11{margin-left:91.66666667%}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-1{width:8.33333333%}.col-md-2{width:16.66666667%}.col-md-3{width:25%}.col-md-4{width:33.33333333%}.col-md-5{width:41.66666667%}.col-md-6{width:50%}.col-md-7{width:58.33333333%}.col-md-8{width:66.66666667%}.col-md-9{width:75%}.col-md-10{width:83.33333333%}.col-md-11{width:91.66666667%}.col-md-12{width:100%}.col-md-push-0{left:auto}.col-md-push-1{left:8.33333333%}.col-md-push-2{left:16.66666667%}.col-md-push-3{left:25%}.col-md-push-4{left:33.33333333%}.col-md-push-5{left:41.66666667%}.col-md-push-6{left:50%}.col-md-push-7{left:58.33333333%}.col-md-push-8{left:66.66666667%}.col-md-push-9{left:75%}.col-md-push-10{left:83.33333333%}.col-md-push-11{left:91.66666667%}.col-md-pull-0{right:auto}.col-md-pull-1{right:8.33333333%}.col-md-pull-2{right:16.66666667%}.col-md-pull-3{right:25%}.col-md-pull-4{right:33.33333333%}.col-md-pull-5{right:41.66666667%}.col-md-pull-6{right:50%}.col-md-pull-7{right:58.33333333%}.col-md-pull-8{right:66.66666667%}.col-md-pull-9{right:75%}.col-md-pull-10{right:83.33333333%}.col-md-pull-11{right:91.66666667%}.col-md-offset-0{margin-left:0}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-3{margin-left:25%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-6{margin-left:50%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-9{margin-left:75%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-11{margin-left:91.66666667%}}@media (min-width:1800px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-1{width:8.33333333%}.col-lg-2{width:16.66666667%}.col-lg-3{width:25%}.col-lg-4{width:33.33333333%}.col-lg-5{width:41.66666667%}.col-lg-6{width:50%}.col-lg-7{width:58.33333333%}.col-lg-8{width:66.66666667%}.col-lg-9{width:75%}.col-lg-10{width:83.33333333%}.col-lg-11{width:91.66666667%}.col-lg-12{width:100%}.col-lg-push-0{left:auto}.col-lg-push-1{left:8.33333333%}.col-lg-push-2{left:16.66666667%}.col-lg-push-3{left:25%}.col-lg-push-4{left:33.33333333%}.col-lg-push-5{left:41.66666667%}.col-lg-push-6{left:50%}.col-lg-push-7{left:58.33333333%}.col-lg-push-8{left:66.66666667%}.col-lg-push-9{left:75%}.col-lg-push-10{left:83.33333333%}.col-lg-push-11{left:91.66666667%}.col-lg-pull-0{right:auto}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-3{right:25%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-6{right:50%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-9{right:75%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-11{right:91.66666667%}.col-lg-offset-0{margin-left:0}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-11{margin-left:91.66666667%}}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:14px;line-height:1.4}@media (min-width:768px){.lead{font-size:19.5px}}.small,small{font-size:85%}cite{font-style:normal}.text-gray,.text-muted{color:#838a9d}.text-gray a,.text-muted a{color:#757d92}.text-gray a:active,.text-gray a:hover,.text-muted a:active,.text-muted a:hover{color:#3c4353}.text-primary{color:#0c64eb}.text-warning,.text-yellow{color:#ff9800}.text-danger,.text-red{color:#ff5d5d}.text-green,.text-success{color:#00da88}.text-blue,.text-info{color:#2196f3}.text-brown,.text-important{color:#bd7b46}.text-purple,.text-special{color:#8666b8}.text-link{color:#3c4353}.text-link:active,.text-link:hover{color:#3c4353}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.nobr,.text-nowrap{overflow:hidden;white-space:nowrap}.text-wrap{overflow:visible;white-space:normal}.text-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}dl{margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}.dl-inline dt{display:inline-block}.dl-inline dd{display:inline-block;padding-right:1em}.dl-inline dd:last-child{padding-right:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}blockquote{padding:10px 20px;margin:0 0 20px;font-size:16.25px;border-left:5px solid #eee}blockquote ol,blockquote p,blockquote ul{font-weight:300}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote small{display:block;line-height:1.42857143;color:#838a9d}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}.ol-pd-2{padding-left:40px}.ol-pd-3{padding-left:60px}.ol-pd-4{padding-left:80px}.bg-black,.bg-default{color:#fff;background-color:#3c4353}.bg-primary{color:#fff;background-color:#0c64eb}.bg-green,.bg-success{color:#fff;background-color:#00da88}.bg-blue,.bg-info{color:#fff;background-color:#2196f3}.bg-warning,.bg-yellow{color:#fff;background-color:#ff9800}.bg-danger,.bg-red{color:#fff;background-color:#ff5d5d}.bg-brown,.bg-important{color:#fff;background-color:#bd7b46}.bg-purple,.bg-special{color:#fff;background-color:#8666b8}.hl-default,.hl-gray{background-color:#f1f1f1}.hl-primary{background-color:#e9f2fb}.hl-green,.hl-success{background-color:#e8f5e9}.hl-blue,.hl-info{background-color:#e3f2fd}.hl-warning,.hl-yellow{background-color:#fff3e0}.hl-danger,.hl-red{background-color:#ffebee}.hl-brown,.hl-important{background-color:#efebe9}.hl-purple,.hl-special{background-color:#f3e5f5}.header-dividing,.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}h1,h2,h3,h4,h5,h6{font-family:"Helvetica Neue",Helvetica,Tahoma,Arial,'PingFang SC','Source Han Sans CN','Source Han Sans','Source Han Serif','Hiragino Sans GB','WenQuanYi Micro Hei','Microsoft YaHei',sans-serif;font-weight:700;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:400;line-height:1;color:#838a9d}h1,h2,h3{margin-top:20px;margin-bottom:10px}h1 small,h2 small,h3 small{font-size:65%}h4,h5,h6{margin-top:10px;margin-bottom:10px}h4 small,h5 small,h6 small{font-size:75%}h1{font-size:24px}h2{font-size:20px}h3{font-size:18px}h4{font-size:14px}h5{font-size:13px}h6{font-size:12px}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}hr.divider-sm{margin-top:10px;margin-bottom:10px}hr.divider{margin:0}.label{display:inline;padding:.2em .6em .2em;font-size:85.71428571%;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#838a9d;border-radius:.25em}.label[href]:focus,.label[href]:hover{color:#fff;background-color:#697084}.label.label-outline{color:#838a9d;background:0 0;border:1px solid #838a9d}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.label-badge{display:inline-block;min-width:18px;padding:3px 7px;font-size:12px;line-height:1;border-radius:9px}.label-dot{display:inline-block;width:8px;height:8px;padding:0;line-height:20px;text-indent:-9999em;border-radius:50%}.label-dot:empty{display:inline-block}.label-primary{background-color:#0c64eb}.label-primary[href]:focus,.label-primary[href]:hover{color:#fff;background-color:#0a4fba}.label-primary.label-outline{color:#0c64eb;background:0 0;border:1px solid #0c64eb}.label-success{background-color:#00da88}.label-success[href]:focus,.label-success[href]:hover{color:#fff;background-color:#00a768}.label-success.label-outline{color:#00da88;background:0 0;border:1px solid #00da88}.label-info{background-color:#2196f3}.label-info[href]:focus,.label-info[href]:hover{color:#fff;background-color:#0c7cd5}.label-info.label-outline{color:#2196f3;background:0 0;border:1px solid #2196f3}.label-warning{background-color:#ff9800}.label-warning[href]:focus,.label-warning[href]:hover{color:#fff;background-color:#cc7a00}.label-warning.label-outline{color:#ff9800;background:0 0;border:1px solid #ff9800}.label-danger{background-color:#ff5d5d}.label-danger[href]:focus,.label-danger[href]:hover{color:#fff;background-color:#ff2a2a}.label-danger.label-outline{color:#ff5d5d;background:0 0;border:1px solid #ff5d5d}.btn .label,.nav-primary>li>a>.label{position:relative;top:-1px}.btn-danger .label,.btn-info .label,.btn-primary .label,.btn-success .label,.btn-warning .label{background-color:rgba(0,0,0,.2)}.list-group-item.active>.label,.nav-pills>.active>a>.label,.nav-primary>.active>a>.label{color:#3c4353;background-color:#fff}.nav>li>a>.label{margin-left:3px}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#838a9d}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:8px;margin-bottom:20px;overflow:hidden;background-color:#e9f2fb;border-radius:3px}.progress-bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;background-color:#0c64eb;-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress>.progress-bar:first-child{border-top-left-radius:3px;border-bottom-left-radius:3px}.progress>.progress-bar:last-child{border-top-right-radius:3px;border-bottom-right-radius:3px}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#00da88}.progress-bar-info{background-color:#2196f3}.progress-bar-warning{background-color:#ff9800}.progress-bar-danger{background-color:#ff5d5d}.avatar{position:relative;display:block;width:30px;height:30px;overflow:hidden;line-height:30px;text-align:center;background-position:center;-webkit-background-size:cover;background-size:cover;border-radius:4px}.avatar img{display:block;width:100%;height:100%;margin:0}.avatar.has-text{color:#fff;background-color:#16a8f8}.avatar-sm{width:20px;height:20px;font-size:12px;line-height:20px}.avatar-lg{width:40px;height:40px;font-size:20px;line-height:40px}.avatar-lg>.icon{font-size:20px}.avatar-xl{width:70px;height:70px;font-size:35px;line-height:70px}.avatar-xl>.icon{font-size:35px}.avatar-circle{border-radius:50%}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:19.5px;line-height:inherit;color:#3c495c;border:0;border-bottom:1px solid #eee}label{display:inline-block;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:5px 0 0;margin-top:0\9;line-height:normal}input[type=file]{display:block}select[multiple],select[size]{height:auto}select:-moz-focusring{color:transparent;text-shadow:0 0 0 #000}select optgroup{font-family:inherit;font-size:inherit;font-style:inherit}.os-mac select.form-control{-webkit-appearance:none;padding-right:18px;background-image:url(data:image/gif;base64,R0lGODlhBwAEAIAAAMvQ2////yH5BAEAAAEALAAAAAAHAAQAAAIIhA+BGWoNWSgAOw==);background-repeat:no-repeat;background-position:right 5px top 14px;-moz-appearance:none}.input-sm .os-mac select.form-control{background-position:right 5px top 9px}.input-lg .os-mac select.form-control{background-position:right 5px top 19px}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}@-moz-document url-prefix(){input[type=radio]:focus{outline:2px solid #0c64eb;-moz-outline-radius:100%}}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}.form-control::-webkit-input-placeholder{color:#838a9d}.form-control::-moz-placeholder{color:#838a9d}.form-control:-ms-input-placeholder{color:#838a9d}.form-control::placeholder{color:#838a9d}.form-control{display:block;width:100%;height:32px;padding:5px 8px;font-size:13px;line-height:1.42857143;color:#222;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}.form-control.focus,.form-control:focus{border-color:#0c64eb;outline:0;-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)}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#f5f5f5}.form-control[readonly]{cursor:default}textarea.form-control{height:auto;min-height:32px}.form-group{margin-bottom:10px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:3px;margin-top:4px\9;margin-left:-20px}.os-android .checkbox input[type=checkbox],.os-android .checkbox-inline input[type=checkbox],.os-android .radio input[type=radio],.os-android .radio-inline input[type=radio]{margin-top:0}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.input-sm{height:24px;padding:2px 8px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:24px;line-height:24px}textarea.input-sm{height:auto}.input-lg{height:39px;padding:10px 16px;font-size:14px;line-height:1.25;border-radius:6px}select.input-lg{height:39px;line-height:39px}textarea.input-lg{height:auto}.has-warning .help-block,.has-warning>label{color:#ff9800}.has-warning .form-control{border-color:#ff9800;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#cc7a00;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ffc166;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ffc166}.has-warning .input-group-addon{color:#ff9800;background-color:#fff3e0;border-color:#ff9800}.has-error .help-block,.has-error>label{color:#ff5d5d}.has-error .form-control{border-color:#ff5d5d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#ff2a2a;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ffc3c3;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ffc3c3}.has-error .input-group-addon{color:#ff5d5d;background-color:#ffebee;border-color:#ff5d5d}.has-success .help-block,.has-success>label{color:#00da88}.has-success .form-control{border-color:#00da88;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#00a768;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #41ffb8;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #41ffb8}.has-success .input-group-addon{color:#00da88;background-color:#e8f5e9;border-color:#00da88}.form-control-static{min-height:33px;padding-top:6px;padding-bottom:6px;margin-bottom:0}.help-block{display:block;margin:5px 0;color:#74809b}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{float:none;margin-left:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .form-group>label,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:6px;margin-top:0;margin-bottom:0}.form-horizontal .form-group{margin-right:-10px;margin-left:-10px}@media (min-width:768px){.form-horizontal .form-group>label{text-align:right}}.required{position:relative}.required:after{position:absolute;top:0;right:-10px;display:inline-block;font-size:14px;color:#ff5d5d;content:'*'}.form-horizontal .required:after{top:5px;right:-1px}.form-condensed .form-group{margin-bottom:10px}.form-condensed .form-control{height:24px;padding:2px 8px;font-size:12px;line-height:1.5;border-radius:3px}select.form-condensed .form-control{height:24px;line-height:24px}textarea.form-condensed .form-control{height:auto}.form-condensed textarea.form-control{height:auto}.form-condensed .btn{padding:3px 8px;font-size:12px;line-height:18px;border-radius:4px}.form-condensed .input-group>.form-control,.form-condensed .input-group>.input-group-addon,.form-condensed .input-group>.input-group-btn>.btn{padding:2px 8px;font-size:12px;border-radius:3px}.form-condensed .input-group .form-control:first-child,.form-condensed .input-group-addon:first-child,.form-condensed .input-group-btn:first-child>.btn,.form-condensed .input-group-btn:first-child>.btn-group>.btn,.form-condensed .input-group-btn:first-child>.dropdown-toggle,.form-condensed .input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.form-condensed .input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.form-condensed .input-group .form-control:last-child,.form-condensed .input-group-addon:last-child,.form-condensed .input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.form-condensed .input-group-btn:first-child>.btn:not(:first-child),.form-condensed .input-group-btn:last-child>.btn,.form-condensed .input-group-btn:last-child>.btn-group>.btn,.form-condensed .input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.form-condensed .input-group-addon:first-child{border-right:0}.form-condensed .input-group-addon:last-child{border-left:0}.form-condensed .input-group-addon.fix-border,.form-condensed .input-group-btn.fix-border>.btn{border-right:0;border-left:0;border-radius:0}.form-condensed.form-horizontal .checkbox,.form-condensed.form-horizontal .checkbox-inline,.form-condensed.form-horizontal .form-group>label,.form-condensed.form-horizontal .radio,.form-condensed.form-horizontal .radio-inline{padding-top:1px}.close{float:right;font-size:19.5px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.load-indicator{position:relative}.load-indicator:after,.load-indicator:before{position:absolute;color:#838a9d;text-align:center;visibility:hidden;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:visibility,opacity;-o-transition-property:visibility,opacity;transition-property:visibility,opacity}.load-indicator:before{top:0;right:0;bottom:0;left:0;z-index:10;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;font-size:12px;content:attr(data-loading);background-color:rgba(255,255,255,.8);-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}.load-indicator[data-loading]:before{padding-top:50px}.load-indicator:after{top:50%;left:50%;z-index:11;display:block;width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-family:ZentaoIcon;font-size:14px;font-size:24px;font-style:normal;font-weight:400;font-variant:normal;line-height:1;line-height:30px;text-transform:none;content:"\e982";-webkit-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.load-indicator.loading:after,.load-indicator.loading:before{visibility:visible;opacity:1}table{max-width:100%;font-size:inherit;background-color:transparent}caption{padding:8px 10px;color:#838a9d;text-align:left}th{text-align:left}.table{width:100%;margin-bottom:20px}.table td,.table th{padding:8px 10px;line-height:1.42857143;vertical-align:top;border-bottom:1px solid #cbd0db;-webkit-transition:background .2s cubic-bezier(.175,.885,.32,1);-o-transition:background .2s cubic-bezier(.175,.885,.32,1);transition:background .2s cubic-bezier(.175,.885,.32,1)}.table>thead>tr>th{font-weight:700;color:#3c4353;vertical-align:bottom;background-color:transparent;border-bottom:1px solid #cbd0db}.table>tbody+tbody{border-top:2px solid #cbd0db}.table-fixed{table-layout:fixed}.table-fixed td,.table-fixed th{overflow:hidden;white-space:nowrap}.table-fixed .nofixed,.table-fixed tfoot>tr>td,.table-fixed tfoot>tr>th{overflow:visible}.table-borderless td,.table-borderless th,.table-borderless thead>tr>th{border:none}.table-auto{width:auto;max-width:100%}.table-condensed td,.table-condensed th{padding:5px}.table-bordered{border:1px solid #cbd0db}.table-bordered td,.table-bordered th{border:1px solid #cbd0db}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#e9f2fb}table col[class*=col-]{display:table-column;float:none}table td[class*=col-],table th[class*=col-]{display:table-cell;float:none}.table tr.active>td,.table tr.active>th,.table tr>td.active,.table tr>th.active{background-color:#ffe9c6}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#e8f5e9;border-color:#c7e6c4}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d6edd8;border-color:#b7deb3}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#ffebee;border-color:#ffd1e0}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ffd1d8;border-color:#ffb8ce}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fff3e0;border-color:#ffe0c6}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#ffe9c6;border-color:#ffd2ad}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #cbd0db}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered th{border-top:none}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}.alert{padding:15px;margin-bottom:20px;color:#313744;background-color:#f1f1f1;border-radius:3px;-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)}.alert hr{border-top-color:#e4e4e4}.alert .alert-link{color:#22262f}.alert h4{margin-top:0;color:inherit}.alert hr{margin:10px 0}.alert p,.alert ul{margin-bottom:0}.alert p+p{margin-top:5px}.alert-link{font-weight:700}.alert>[class*=icon-]{float:left;margin-top:-5px;font-size:42px;opacity:.6;-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)}.alert>[class*=icon-]+.content{min-height:30px;margin-left:64px}.alert.with-icon{display:table;width:100%}.alert.with-icon>[class*=icon-],.alert.with-icon>[class*=icon-]+.content{display:table-cell;float:none;min-height:0;margin:0;vertical-align:middle}.alert.with-icon>[class*=icon-]{width:48px;text-align:center}.alert.with-icon>[class*=icon-]+.content{padding-left:1em}.alert-block{margin:0;border-radius:0}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-6px;right:-21px;color:inherit}.alert-primary{color:#313744;background-color:#e9f2fb}.alert-primary hr{border-top-color:#cbe0f6}.alert-primary .alert-link{color:#22262f}.alert-success{color:#00c178;background-color:#e8f5e9}.alert-success hr{border-top-color:#c7e6c4}.alert-success .alert-link{color:#009d62}.alert-info{color:#0d8aee;background-color:#e3f2fd}.alert-info hr{border-top-color:#9ce0f8}.alert-info .alert-link{color:#0b76cc}.alert-warning{color:#e68900;background-color:#fff3e0}.alert-warning hr{border-top-color:#ffe0c6}.alert-warning .alert-link{color:#c27400}.alert-danger{color:#ff4343;background-color:#ffebee}.alert-danger hr{border-top-color:#ffd1e0}.alert-danger .alert-link{color:#ff2020}.alert-inverse{color:#fff;background-color:#3c4353;border-color:#3c4353}.alert-inverse hr{border-top-color:#cbd0db;border-top-color:rgba(203,208,219,.25)}.alert-inverse .alert-link{color:rgba(255,255,255,.8)}.alert-primary-inverse{color:#fff;background-color:#0c64eb;border-color:#0c64eb}.alert-primary-inverse hr{border-top-color:#cbd0db;border-top-color:rgba(203,208,219,.25)}.alert-primary-inverse .alert-link{color:rgba(255,255,255,.8)}.alert-success-inverse{color:#fff;background-color:#00da88;border-color:#00da88}.alert-success-inverse hr{border-top-color:#cbd0db;border-top-color:rgba(203,208,219,.25)}.alert-success-inverse .alert-link{color:rgba(255,255,255,.8)}.alert-info-inverse{color:#fff;background-color:#2196f3;border-color:#2196f3}.alert-info-inverse hr{border-top-color:#cbd0db;border-top-color:rgba(203,208,219,.25)}.alert-info-inverse .alert-link{color:rgba(255,255,255,.8)}.alert-warning-inverse{color:#fff;background-color:#ff9800;border-color:#ff9800}.alert-warning-inverse hr{border-top-color:#cbd0db;border-top-color:rgba(203,208,219,.25)}.alert-warning-inverse .alert-link{color:rgba(255,255,255,.8)}.alert-danger-inverse{color:#fff;background-color:#ff5d5d;border-color:#ff5d5d}.alert-danger-inverse hr{border-top-color:#cbd0db;border-top-color:rgba(203,208,219,.25)}.alert-danger-inverse .alert-link{color:rgba(255,255,255,.8)}.input-control-icon-left,.input-control-icon-right,.input-control-label-left,.input-control-label-right{position:absolute;top:1px;z-index:5;height:30px;line-height:30px;opacity:.5}.input-control-icon-left,.input-control-icon-right{width:30px;text-align:center}.input-control-icon-left,.input-control-label-left{left:1px}.input-control-icon-right,.input-control-label-right{right:1px}.input-control-label-left,.input-control-label-right{width:70px;padding:0 8px;overflow:hidden;text-overflow:ellipsis}.has-label-left-sm>.input-control-label-left,.has-label-left-sm>.input-control-label-right{width:55px}.has-label-left-lg>.input-control-label-left,.has-label-left-lg>.input-control-label-right{width:95px}.input-control{position:relative}.input-control.has-icon-left>.form-control{padding-left:30px}.input-control.has-icon-right>.form-control{padding-right:30px}.input-control.has-label-left>.form-control{padding-left:70px}.input-control.has-label-right>.form-control{padding-right:70px}.input-control.has-label-left-sm>.form-control{padding-left:55px}.input-control.has-label-right-sm>.form-control{padding-right:55px}.input-control.has-label-left-lg>.form-control{padding-left:95px}.input-control.has-label-right-lg>.form-control{padding-right:95px}.input-control>a:hover{background-color:#f1f1f1;opacity:1}.form-control:focus+[class^=input-control-],.form-control:focus+[class^=input-control-]+[class^=input-control-]{opacity:1}.form-control:focus+.input-control-label-left{color:#16a8f8}.empty+.search-clear-btn,.empty+.search-icon+.search-clear-btn{opacity:0!important}input:placeholder-shown+.search-clear-btn,input:placeholder-shown+.search-icon+.search-clear-btn{opacity:0!important}.search-box-circle .input-control-icon-left,.search-box-circle .input-control-icon-right,.search-box-circle>.form-control{border-radius:16px}.search-box-circle+.input-group-btn>.btn{border-radius:0 16px 16px 0}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:5px 12px;font-size:13px;font-weight:400;line-height:1;color:#3c495c;text-align:center;background-color:#eee;border:1px solid #dcdcdc;border-radius:2px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group-addon.fix-border{border-right:0;border-left:0}.input-group-addon:empty{width:1px;padding:0}.input-group-addon.fix-padding{width:1px;padding:0}.input-group-btn.fix-border>.btn{border-right:0;border-left:0;border-radius:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:first-child{border-right:0}.input-group-addon:last-child{border-left:0}.input-group-addon+.input-group-addon{border-left:1px solid #dcdcdc}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:39px;padding:10px 16px;font-size:14px;line-height:1.25;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:39px;line-height:39px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:24px;padding:2px 8px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:24px;line-height:24px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon.input-sm{padding:2px 8px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:14px;border-radius:6px}.code,code,kbd,pre,samp{font-family:Monaco,Menlo,Consolas,"Courier New",monospace}code,kbd{padding:2px 4px;font-size:90%;color:#37474f;background-color:#f3f5f7;border-radius:4px}kbd{padding:1px 4px;font-weight:700;color:#666;background-color:#f1f1f1;border:1px solid #d8d8d8;border-bottom-width:2px}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:12px;line-height:1.38461538;color:#3c495c;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;margin:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.com{color:#93a1a1}.lit{color:#195f91}.clo,.opn,.pun{color:#93a1a1}.fun{color:#dc322f}.atv,.str{color:#d14}.kwd,.prettyprint .tag{color:#1e347b}.atn,.dec,.typ,.var{color:teal}.pln{color:#48484c}.prettyprint.linenums{-webkit-box-shadow:inset 40px 0 0 #fbfbfc,inset 41px 0 0 #ececf0;box-shadow:inset 40px 0 0 #fbfbfc,inset 41px 0 0 #ececf0}.prettyprint ol.linenums{padding-left:35px;margin-bottom:0;line-height:20px;color:#bebec5;text-shadow:0 1px 0 #fff}.pager{display:inline-block;padding-left:0;margin:20px 0;list-style:none}.pager>li{display:inline}.pager>li>a,.pager>li>span{position:relative;float:left;padding:5px 12px;margin-left:-1px;line-height:1.42857143;text-decoration:none;background-color:#fff;border:1px solid #cbd0db}.pager>li:first-child>a,.pager>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pager>li:last-child>a,.pager>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pager>li>a:focus,.pager>li>a:hover,.pager>li>span:focus,.pager>li>span:hover{z-index:2;background-color:#eee}.pager>li.active>a,.pager>li.active>a:hover,.pager>li.active>span,.pager>li.active>span:hover{z-index:3;color:#fff;cursor:default;background-color:#0c64eb;border-color:#0c64eb}.pager>li.disabled>a,.pager>li.disabled>a:focus,.pager>li.disabled>a:hover,.pager>li.disabled>span,.pager>li.disabled>span:focus,.pager>li.disabled>span:hover{color:#cbd0db;pointer-events:none;cursor:not-allowed;background-color:#fff;border-color:#cbd0db}.pager-justify{display:block}.pager-justify .next>a,.pager-justify .next>span{float:right;border-radius:4px}.pager-justify .previous>a,.pager-justify .previous>span{float:left;border-radius:4px}.pager-goto{width:100px;text-align:center}.pager>li>div{float:left}.pager>li .pager-goto,.pager>li .pager-size-menu,.pager>li.space{margin:0 5px}.pager-label{position:relative;float:left;padding:5px 4px;margin-left:-1px;line-height:1.42857143;text-decoration:none;border:1px solid transparent}.pager-item-left>a{border-top-left-radius:4px;border-bottom-left-radius:4px}.pager-item-right>a{border-top-right-radius:4px;border-bottom-right-radius:4px}.pager-lg>li>a,.pager-lg>li>span{padding:10px 16px;font-size:14px}.pager-lg>li:first-child>a,.pager-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pager-lg>li:last-child>a,.pager-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pager-sm>li>a,.pager-sm>li>span{padding:2px 8px;font-size:12px}.pager-sm>li:first-child>a,.pager-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pager-sm>li:last-child>a,.pager-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager-pills>li:first-child>a,.pager-pills>li:first-child>span{border-radius:16px 0 0 16px}.pager-pills>li:last-child>a,.pager-pills>li:last-child>span{border-radius:0 16px 16px 0}.pager-pills.pager-justify>li>a,.pager-pills.pager-justify>li>span{border-radius:16px}.pager-loose{display:block;margin:20px 0}.pager-loose.pager-pills>li>a,.pager-loose.pager-pills>li>span{border-radius:16px}.pager-loose>li>a,.pager-loose>li>span{margin-left:5px;border-radius:4px}.pager-loose>li:first-child>a,.pager-loose>li:first-child>span{margin-left:0}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>.nav-heading{padding:8px 15px;font-weight:700;color:#838a9d}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:8px 15px;color:#3c4353}.nav>li>a:focus,.nav>li>a:hover{color:#0c64eb;text-decoration:none;background-color:#f1f1f1}.nav>li.disabled>a{color:#cbd0db}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#cbd0db;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#f1f1f1;border-color:#3c4353}.nav>li>a>img{max-width:none}.nav-default>li{float:left}.nav-simple>li{float:left}.nav-simple>li>a{border-radius:4px}.nav-simple>li.active>a,.nav-simple>li.active>a:focus,.nav-simple>li.active>a:hover{color:#0c64eb;background-color:#e9f2fb}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:20px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#0c64eb}.nav-primary>li{float:left;margin-left:-1px}.nav-primary>li:first-child>a{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.nav-primary>li:last-child>a{border-top-right-radius:4px;border-bottom-right-radius:4px}.nav-primary>li>a{border:1px solid #cbd0db}.nav-primary>li.active>a,.nav-primary>li.active>a:focus,.nav-primary>li.active>a:hover{color:#fff;background-color:#0c64eb;border-color:#0c64eb}.nav-secondary>li{float:left}.nav-secondary>li>a{border-bottom:2px solid #eee}.nav-secondary>li.active>a,.nav-secondary>li.active>a:focus,.nav-secondary>li.active>a:hover{color:#0c64eb;border-bottom-color:#0c64eb}.nav-secondary>li.nav-heading{border-bottom:2px solid #eee}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-stacked.nav-primary>li,.nav-stacked.nav-primary>li>a{margin-left:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.nav-stacked.nav-primary>li+li{margin-top:-1px}.nav-stacked.nav-primary>li:first-child{margin-top:0}.nav-stacked.nav-primary>li:first-child.nav-heading,.nav-stacked.nav-primary>li:first-child>a{margin-left:0;border-top-left-radius:4px;border-top-right-radius:4px}.nav-stacked.nav-primary>li:last-child>a{border-top-left-radius:0;border-top-right-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.nav-stacked.nav-primary>li.nav-heading{background-color:#f1f1f1;border:1px solid #cbd0db}.nav-stacked.nav-secondary>li>a{border:none;border-top-right-radius:4px;border-bottom-right-radius:4px;-webkit-box-shadow:inset 2px 0 0 #f5f5f5;box-shadow:inset 2px 0 0 #f5f5f5}.nav-stacked.nav-secondary>li>a:hover{-webkit-box-shadow:inset 2px 0 0 #eee;box-shadow:inset 2px 0 0 #eee}.nav-stacked.nav-secondary>li+li{margin-top:-1px}.nav-stacked.nav-secondary>li:first-child{margin-top:0}.nav-stacked.nav-secondary>li.active>a,.nav-stacked.nav-secondary>li.active>a:focus,.nav-stacked.nav-secondary>li.active>a:hover{background-color:#f5f5f5;-webkit-box-shadow:inset 2px 0 0 #0c64eb;box-shadow:inset 2px 0 0 #0c64eb}.nav-stacked.nav-secondary>li.nav-heading{border-bottom:1px solid #cbd0db}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{padding-right:0;padding-left:0;margin-bottom:5px;text-align:center}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}.nav-justified.nav-primary>li+li>a{border-left:0}}.nav-tabs{border-bottom:1px solid #cbd0db}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #cbd0db}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#838a9d;cursor:default;background-color:#fff;border:1px solid #cbd0db;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{padding-right:0;padding-left:0;margin-bottom:5px;text-align:center}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}.nav-tabs.nav-justified.nav-primary>li+li>a{border-left:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #cbd0db}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #cbd0db;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}@-moz-document url-prefix(){.nav-tabs>li.active>a:focus .nav-tabs>li>a:focus{outline:0}}.nav-tabs.nav-stacked{border-right:1px solid #cbd0db;border-bottom:none}.nav-tabs.nav-stacked>li{float:none;margin-right:-1px;margin-bottom:0}.nav-tabs.nav-stacked>li>a{margin-right:0;border-radius:4px 0 0 4px}.nav-tabs.nav-stacked>li.active>a,.nav-tabs.nav-stacked>li.active>a:focus,.nav-tabs.nav-stacked>li.active>a:hover{border:1px solid #cbd0db;border-right-color:transparent}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #cbd0db}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #cbd0db;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:40px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:10px;padding-left:10px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-10px;margin-left:-10px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:40px;padding:10px 15px;font-size:14px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-10px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:3px;margin-right:3px;margin-bottom:3px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:5px -10px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px}.navbar-nav.nav-justified>li{float:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-nav.pull-right>li>.dropdown-menu,.navbar-nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar-btn{margin-top:4px;margin-bottom:4px}.navbar-text{float:left;margin-top:10px;margin-bottom:10px}@media (min-width:768px){.navbar-text{margin-right:10px;margin-left:10px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-10px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f7f7f7;border-color:#dedede}.navbar-default .navbar-brand{color:#3c495c}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#28313d;background-color:transparent}.navbar-default .navbar-text{color:#3c495c}.navbar-default .navbar-nav>li>a{color:#3c495c}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#222;background-color:#eee}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#cbd0db}.navbar-default .navbar-toggle .icon-bar{background-color:#838a9d}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#dedede}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#3c495c}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#222;background-color:#eee}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#3c495c}.navbar-default .navbar-link:hover{color:#222}.navbar-default .btn-link{color:#3c495c}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#222}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#16a8f8;border-color:#068cd5}.navbar-inverse .navbar-brand{color:#cbd0db}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#cbd0db}.navbar-inverse .navbar-nav>li>a{color:#cbd0db}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:#34b3f9}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#48baf9}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#079ced}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#0795e3}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#48baf9}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#068cd5}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#068cd5}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#cbd0db}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:#34b3f9}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#48baf9}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#cbd0db}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-form{padding:10px 10px;margin-top:4px;margin-right:-10px;margin-bottom:4px;margin-left:-10px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{float:none;margin-left:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.no-animation,.no-animation *,.no-animation :after,.no-animation :before,.no-animation:after,.no-animation:before{-webkit-transition:none!important;-o-transition:none!important;transition:none!important}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.scale{-webkit-transition:all .15s ease;-o-transition:all .15s ease;transition:all .15s ease;-webkit-transform:scale(.8);-ms-transform:scale(.8);-o-transform:scale(.8);transform:scale(.8)}.scale.in{-webkit-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.scrollbar-hover::-webkit-scrollbar,.scrollbar-hover::-webkit-scrollbar-button,.scrollbar-hover::-webkit-scrollbar-thumb,.scrollbar-hover::-webkit-scrollbar-track{visibility:hidden}.scrollbar-hover:hover::-webkit-scrollbar,.scrollbar-hover:hover::-webkit-scrollbar-button,.scrollbar-hover:hover::-webkit-scrollbar-thumb,.scrollbar-hover:hover::-webkit-scrollbar-track{visibility:visible}@media (min-width:768px){::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-button{width:0;height:0}::-webkit-scrollbar-button:end:increment,::-webkit-scrollbar-button:start:decrement{display:block}::-webkit-scrollbar-button:vertical:end:decrement,::-webkit-scrollbar-button:vertical:start:increment{display:none}::-webkit-scrollbar-thumb:horizontal,::-webkit-scrollbar-thumb:vertical,::-webkit-scrollbar-track:horizontal,::-webkit-scrollbar-track:vertical{border-color:transparent;border-style:solid}::-webkit-scrollbar-track:vertical::-webkit-scrollbar-track:horizontal{background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box}::-webkit-scrollbar-thumb{min-height:28px;background-color:rgba(0,0,0,.2);-webkit-background-clip:padding-box;background-clip:padding-box;border-radius:2px;-webkit-box-shadow:inset 1px 1px 0 rgba(0,0,0,.1),inset 0 -1px 0 rgba(0,0,0,.07)}::-webkit-scrollbar-thumb:hover{background-color:rgba(0,0,0,.4);-webkit-box-shadow:inset 1px 1px 1px rgba(0,0,0,.25)}::-webkit-scrollbar-thumb:active{background-color:rgba(0,0,0,.5);-webkit-box-shadow:inset 1px 1px 3px rgba(0,0,0,.35)}::-webkit-scrollbar-thumb:horizontal,::-webkit-scrollbar-thumb:vertical,::-webkit-scrollbar-track:horizontal,::-webkit-scrollbar-track:vertical{border-width:0}::-webkit-scrollbar-track:hover{background-color:rgba(0,0,0,.05);-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,.1)}::-webkit-scrollbar-track:active{background-color:rgba(0,0,0,.05);-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,.14),inset -1px -1px 0 rgba(0,0,0,.07)}}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out,-o-transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal>.loader{display:none}.modal.modal-loading .loader,.modal.modal-updating .loader{position:absolute;top:35%;left:50%;display:block;width:80px;margin-left:-40px;font-size:56px;color:#fff;text-align:center}.modal.modal-loading .modal-dialog{opacity:0}.modal.modal-updating .modal-dialog{opacity:1}.modal.modal-updating .modal-body{opacity:0}.modal.modal-updating .loader{z-index:1;color:#eee}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-iframe .modal-body{overflow:hidden!important}.modal-iframe .modal-body>iframe{border-radius:0 0 6px 6px}.modal-dialog{position:relative;width:auto;margin:0 auto;pointer-events:initial;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-dialog.modal-moveable{position:absolute;margin:0}.modal-dialog.modal-moveable .modal-header{cursor:move}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media (min-width:768px){.modal-dialog{width:600px;-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.modal-fullscreen{position:relative;width:100%!important;height:100%!important;margin:0;border-radius:0}.modal-fullscreen .modal-body{position:absolute;top:52px;right:0;bottom:0;left:0;overflow-y:auto}.modal-scroll-inside{overflow:hidden!important}.body-modal-scroll-inside{overflow:auto}.tooltip{position:absolute;z-index:1030;display:block;font-size:12px;line-height:1.4;visibility:visible;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=100);opacity:1}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#3c4353;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#3c4353}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#3c4353}.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-width:5px 5px 0;border-top-color:#3c4353}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#3c4353}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#3c4353}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#3c4353}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#3c4353}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#3c4353}.tooltip-primary .tooltip-inner{background-color:#0c64eb}.tooltip-primary.tooltip.top .tooltip-arrow{border-top-color:#0c64eb}.tooltip-primary.tooltip.top-left .tooltip-arrow{border-top-color:#0c64eb}.tooltip-primary.tooltip.top-right .tooltip-arrow{border-top-color:#0c64eb}.tooltip-primary.tooltip.right .tooltip-arrow{border-right-color:#0c64eb}.tooltip-primary.tooltip.left .tooltip-arrow{border-left-color:#0c64eb}.tooltip-primary.tooltip.bottom .tooltip-arrow{border-bottom-color:#0c64eb}.tooltip-primary.tooltip.bottom-left .tooltip-arrow{border-bottom-color:#0c64eb}.tooltip-primary.tooltip.bottom-right .tooltip-arrow{border-bottom-color:#0c64eb}.tooltip-success .tooltip-inner{background-color:#00da88}.tooltip-success.tooltip.top .tooltip-arrow{border-top-color:#00da88}.tooltip-success.tooltip.top-left .tooltip-arrow{border-top-color:#00da88}.tooltip-success.tooltip.top-right .tooltip-arrow{border-top-color:#00da88}.tooltip-success.tooltip.right .tooltip-arrow{border-right-color:#00da88}.tooltip-success.tooltip.left .tooltip-arrow{border-left-color:#00da88}.tooltip-success.tooltip.bottom .tooltip-arrow{border-bottom-color:#00da88}.tooltip-success.tooltip.bottom-left .tooltip-arrow{border-bottom-color:#00da88}.tooltip-success.tooltip.bottom-right .tooltip-arrow{border-bottom-color:#00da88}.tooltip-info .tooltip-inner{background-color:#2196f3}.tooltip-info.tooltip.top .tooltip-arrow{border-top-color:#2196f3}.tooltip-info.tooltip.top-left .tooltip-arrow{border-top-color:#2196f3}.tooltip-info.tooltip.top-right .tooltip-arrow{border-top-color:#2196f3}.tooltip-info.tooltip.right .tooltip-arrow{border-right-color:#2196f3}.tooltip-info.tooltip.left .tooltip-arrow{border-left-color:#2196f3}.tooltip-info.tooltip.bottom .tooltip-arrow{border-bottom-color:#2196f3}.tooltip-info.tooltip.bottom-left .tooltip-arrow{border-bottom-color:#2196f3}.tooltip-info.tooltip.bottom-right .tooltip-arrow{border-bottom-color:#2196f3}.tooltip-warning .tooltip-inner{background-color:#ff9800}.tooltip-warning.tooltip.top .tooltip-arrow{border-top-color:#ff9800}.tooltip-warning.tooltip.top-left .tooltip-arrow{border-top-color:#ff9800}.tooltip-warning.tooltip.top-right .tooltip-arrow{border-top-color:#ff9800}.tooltip-warning.tooltip.right .tooltip-arrow{border-right-color:#ff9800}.tooltip-warning.tooltip.left .tooltip-arrow{border-left-color:#ff9800}.tooltip-warning.tooltip.bottom .tooltip-arrow{border-bottom-color:#ff9800}.tooltip-warning.tooltip.bottom-left .tooltip-arrow{border-bottom-color:#ff9800}.tooltip-warning.tooltip.bottom-right .tooltip-arrow{border-bottom-color:#ff9800}.tooltip-danger .tooltip-inner{background-color:#ff5d5d}.tooltip-danger.tooltip.top .tooltip-arrow{border-top-color:#ff5d5d}.tooltip-danger.tooltip.top-left .tooltip-arrow{border-top-color:#ff5d5d}.tooltip-danger.tooltip.top-right .tooltip-arrow{border-top-color:#ff5d5d}.tooltip-danger.tooltip.right .tooltip-arrow{border-right-color:#ff5d5d}.tooltip-danger.tooltip.left .tooltip-arrow{border-left-color:#ff5d5d}.tooltip-danger.tooltip.bottom .tooltip-arrow{border-bottom-color:#ff5d5d}.tooltip-danger.tooltip.bottom-left .tooltip-arrow{border-bottom-color:#ff5d5d}.tooltip-danger.tooltip.bottom-right .tooltip-arrow{border-bottom-color:#ff5d5d}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:300px;text-align:left;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:4px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover.no-arrow.top{margin-top:0}.popover.no-arrow.right{margin-left:0}.popover.no-arrow.bottom{margin-top:0}.popover.no-arrow.left{margin-left:0}.modal .popover,.popover-in-modal{z-index:1050}.popover-title{padding:8px 14px;margin:0;font-size:13px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:4px 4px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{content:"";border-width:10px}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom .arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left .arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.popover-primary{border-color:#0c64eb}.popover-primary .popover-title{color:#fff;background-color:#0c64eb}.popover-primary.popover.top .arrow{border-top-color:#0c64eb}.popover-primary.popover.right .arrow{border-right-color:#0c64eb}.popover-primary.popover.left .arrow{border-left-color:#0c64eb}.popover-primary.popover.bottom .arrow,.popover-primary.popover.bottom .arrow:after{border-bottom-color:#0c64eb}.popover-success{border-color:#00da88}.popover-success .popover-title{color:#fff;background-color:#00da88}.popover-success.popover.top .arrow{border-top-color:#00da88}.popover-success.popover.right .arrow{border-right-color:#00da88}.popover-success.popover.left .arrow{border-left-color:#00da88}.popover-success.popover.bottom .arrow,.popover-success.popover.bottom .arrow:after{border-bottom-color:#00da88}.popover-info{border-color:#2196f3}.popover-info .popover-title{color:#fff;background-color:#2196f3}.popover-info.popover.top .arrow{border-top-color:#2196f3}.popover-info.popover.right .arrow{border-right-color:#2196f3}.popover-info.popover.left .arrow{border-left-color:#2196f3}.popover-info.popover.bottom .arrow,.popover-info.popover.bottom .arrow:after{border-bottom-color:#2196f3}.popover-warning{border-color:#ff9800}.popover-warning .popover-title{color:#fff;background-color:#ff9800}.popover-warning.popover.top .arrow{border-top-color:#ff9800}.popover-warning.popover.right .arrow{border-right-color:#ff9800}.popover-warning.popover.left .arrow{border-left-color:#ff9800}.popover-warning.popover.bottom .arrow,.popover-warning.popover.bottom .arrow:after{border-bottom-color:#ff9800}.popover-danger{border-color:#ff5d5d}.popover-danger .popover-title{color:#fff;background-color:#ff5d5d}.popover-danger.popover.top .arrow{border-top-color:#ff5d5d}.popover-danger.popover.right .arrow{border-right-color:#ff5d5d}.popover-danger.popover.left .arrow{border-left-color:#ff5d5d}.popover-danger.popover.bottom .arrow,.popover-danger.popover.bottom .arrow:after{border-bottom-color:#ff5d5d}.caret{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}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:100px;padding:5px 0;margin:2px 0 0;font-size:13px;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #b6bdcc;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)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#eee}.dropdown-menu>li>a{display:block;padding:5px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#3c4353;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#fff;text-decoration:none;background-color:#0c64eb}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#0c64eb;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#cbd0db}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.dropdown-hover .dropdown-menu{margin:-1px 0}.dropdown-hover:hover>.dropdown-menu,.open>.dropdown-menu{display:block;opacity:1}.dropdown-hover:hover>a,.open>a{outline:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;font-weight:700;line-height:1.42857143;color:#838a9d}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0 dotted;border-bottom:4px solid}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;border-radius:4px}.dropdown-submenu.open>.dropdown-menu,.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;border-radius:4px}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;content:" ";border-color:transparent;border-style:solid;border-width:5px 0 5px 5px;border-left-color:#ccc}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu>a{min-width:100px}.dropdown-submenu>.dropdown-menu.pull-left{right:100%;left:auto}.dropdown-submenu:focus>a,.dropdown-submenu:hover>a{color:#fff;text-decoration:none;background-color:#0c64eb}.messager{display:table;margin:10px;overflow:hidden;color:#fff;pointer-events:auto;background-color:#3c4353;background-color:rgba(0,0,0,.8);border-radius:20px;-webkit-transition-property:opacity,-webkit-transform!important;-o-transition-property:opacity,-o-transform!important;transition-property:opacity,-webkit-transform!important;transition-property:opacity,transform!important;transition-property:opacity,transform,-webkit-transform,-o-transform!important}.messager-icon{display:table-cell;padding:10px 0 10px 15px;line-height:20px;text-align:center;vertical-align:top}.messager-content{display:table-cell;padding:10px 15px;vertical-align:top}.messager-content a{font-weight:700;color:inherit}.messager-title{font-size:14px;font-weight:700}.messager-title+.messager-text{margin-top:10px}.messager-actions{display:table-cell;vertical-align:top}.messager-actions>.action{min-width:40px;height:40px;padding:0 12px;color:#fafafa;color:rgba(255,255,255,.6);text-align:center;text-shadow:none;background:0 0;border:none}.messager-actions>.action.close{padding-bottom:5px;font-size:20px;font-weight:400;opacity:1}.messager-actions>.action:hover{color:#fff;background:rgba(0,0,0,.1)}.messager-actions .action-icon+.action-text{margin-left:8px}.messagers-holder{position:fixed;z-index:99999;padding:10px;pointer-events:none}.messagers-holder.top{top:0}.messagers-holder.top-left{top:0;left:0}.messagers-holder.top-right{top:0;right:0}.messagers-holder.bottom{bottom:0}.messagers-holder.bottom-left{bottom:0;left:0}.messagers-holder.bottom-right{right:0;bottom:0}.messagers-holder.bottom-right .messager,.messagers-holder.top-right .messager{margin-left:auto}.messagers-holder.center{top:0}.messagers-holder.bottom,.messagers-holder.center,.messagers-holder.top{right:0;left:0}.messagers-holder.bottom .messager,.messagers-holder.center .messager,.messagers-holder.top .messager{margin:10px auto}.messager-notification{min-width:250px;max-width:400px;border-radius:4px}.messager-notification .messager-icon{width:42px;vertical-align:middle}.messager-notification .messager-content{vertical-align:middle}.messager-text>p:last-child{margin:0}.messager-primary{background-color:#0c64eb}.messager-success{background-color:#00da88}.messager-info{background-color:#2196f3}.messager-warning{background-color:#ff9800}.messager-danger{background-color:#ff5d5d}.messager-important{background-color:#bd7b46}.messager-special{background-color:#8666b8}.article{padding:20px}.article>header h1,.article>header h2,.article>header h3{margin-bottom:20px;line-height:1.5}.article>header>.abstract,.article>header>dl{padding:10px 15px;font-size:12px;color:#67738e;background-color:#f1f1f1}.article>header>.abstract>p:last-child,.article>header>dl>p:last-child{margin-bottom:0}.article>header>dl{margin:0;border-bottom:1px solid #e9e9e9}.article>header>dl.pull-right{background-color:transparent;border:none}.article>footer{border-top:1px dashed #d8d8d8}.article>footer>p{padding:10px 15px}.article-content,.article>.content{padding:20px 0;font-size:14px;line-height:1.57142857}.article-content h1,.article>.content h1{font-size:20px}.article-content h2,.article>.content h2{font-size:18px}.article-content h3,.article>.content h3{font-size:16px}.article-content h4,.article>.content h4{margin-top:15px;font-size:14px}.article-content h5,.article>.content h5{margin-top:15px;font-size:13px}.article-content h6,.article>.content h6{margin-top:15px;font-size:11px}.article-content img,.article>.content img{margin:10px 0}.article-content p>img+img,.article>.content p>img+img{margin-left:10px}.article-content p>img[align=right],.article>.content p>img[align=right]{margin-left:10px}.article-content dl,.article>.content dl{padding-right:2em;padding-left:2em}.article-content table,.article>.content table{margin-bottom:20px}.article-content table td,.article-content table th,.article>.content table td,.article>.content table th{padding:8px 10px;line-height:1.42857143;vertical-align:top;border-bottom:1px solid #cbd0db}.article-content table>thead>tr>th,.article>.content table>thead>tr>th{vertical-align:bottom;background-color:transparent}.article-content p{margin-bottom:0}.article>.content table td,.article>.content table th,.article>.content table>thead>tr>th{border:1px solid #cbd0db}body.article-content{padding:8px}.article-condensed{padding:20px 0}.article-condensed>header{padding:0 20px}.article-condensed>header>.abstract,.article-condensed>header>dl{padding:10px 15px;margin:0 -20px}.article-condensed>.article-content,.article-condensed>.content{padding:20px}.article-condensed>.article-content>img,.article-condensed>.article-content>pre,.article-condensed>.content>img,.article-condensed>.content>pre{margin-right:-20px;margin-left:-20px;border-radius:0}.article-condensed>.article-content>pre,.article-condensed>.content>pre{border-right:none;border-left:none}.article-condensed>footer{border-top:1px dashed #d8d8d8}.article-condensed>footer>p{padding:10px 15px}.article-condensed>footer>.pager-justify>.previous>a{border-left:none;border-radius:0}.article-condensed>footer>.pager-justify>.next>a{border-right:none;border-radius:0}/*! * Datetimepicker for Bootstrap * Copyright 2012 Stefan Petre @@ -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)}.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}.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-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}.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:#1183fb -webkit-gradient(linear,right top,left top,from(#0a48d1),to(#1183fb));background:#1183fb -webkit-linear-gradient(right,#0a48d1 0,#1183fb 100%);background:#1183fb -o-linear-gradient(right,#0a48d1 0,#1183fb 100%);background:#1183fb linear-gradient(-90deg,#0a48d1 0,#1183fb 100%);background-color:#00b1fd}.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.22);src:url(../fonts/ZentaoIcon.eot?#iefix&v=1.22) format('embedded-opentype'),url(../fonts/ZentaoIcon.woff?v=1.22) format('woff'),url(../fonts/ZentaoIcon.ttf?v=1.22) format('truetype'),url(../fonts/ZentaoIcon.svg#regular?v=1.22) 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-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-list:before{content:"\e9a8"}.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-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-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-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-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-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-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-back:before{content:"\e93f"}.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-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{border-color:rgba(33,150,243,.25)}.label-outline.label-warning{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:#fff3e0;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:67px;height:18px;padding:0 4px;overflow:hidden;font-size:12px;line-height:16px;color:#838a9d;text-align:center;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;border:1px solid #838a9d;border-radius:10px}.label-selector>.label-pri,[class*=label-pri-]{color:#158af1;border-color:#2098ee}.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="0"]:after,.label-severity[data-value="0"]:after{display:none}.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:30px;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:1px;right:0;left:0;display:block;width:18px;height:18px;line-height:18px;text-align:center;content:' ';border-radius:3px}.checkbox-primary>label:after,.radio-primary>label:after{z-index:1;border:2px solid #eee;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:5px;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}.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;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}.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}.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:#1183fb -webkit-gradient(linear,right top,left top,from(#0a48d1),to(#1183fb));background:#1183fb -webkit-linear-gradient(right,#0a48d1 0,#1183fb 100%);background:#1183fb -o-linear-gradient(right,#0a48d1 0,#1183fb 100%);background:#1183fb linear-gradient(-90deg,#0a48d1 0,#1183fb 100%);background-color:#1183fb;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{display:inline-block;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>*{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;border-bottom:1px solid #ddd}#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{position:relative;padding:8px 5px;border:none;border-radius:2px!important}#main .side-col .nav-tabs>li.active>a{font-weight:700;color:#3c4353}#main .side-col .nav-tabs>li.active>a:before{position:absolute;right:0;bottom:-1px;left:0;display:block;height:2px;content:' ';background:#0c64eb}#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 .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:1px;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:4;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{width:0;height:28px;visibility:hidden;opacity:0;-webkit-transition:opacity cubic-bezier(.175,.885,.32,1) .8s;-o-transition:opacity cubic-bezier(.175,.885,.32,1) .8s;transition:opacity cubic-bezier(.175,.885,.32,1) .8s}.table-actions.show-always{width:auto;pointer-events:none;cursor:not-allowed;visibility:visible;opacity:.75}.has-row-checked .table-actions{width:auto;pointer-events:auto!important;cursor:default;visibility:visible;opacity:1}.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:0;left:0;padding:5px 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 .list-group>a.active:hover,#swapper #dropMenu .search-box .list-group>a.active,#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)}.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}.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-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}.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:#1183fb -webkit-gradient(linear,right top,left top,from(#0a48d1),to(#1183fb));background:#1183fb -webkit-linear-gradient(right,#0a48d1 0,#1183fb 100%);background:#1183fb -o-linear-gradient(right,#0a48d1 0,#1183fb 100%);background:#1183fb linear-gradient(-90deg,#0a48d1 0,#1183fb 100%);background-color:#00b1fd}.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.24);src:url(../fonts/ZentaoIcon.eot?#iefix&v=1.24) format('embedded-opentype'),url(../fonts/ZentaoIcon.woff?v=1.24) format('woff'),url(../fonts/ZentaoIcon.ttf?v=1.24) format('truetype'),url(../fonts/ZentaoIcon.svg#regular?v=1.24) 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-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-list:before{content:"\e9a8"}.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-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-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-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-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-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-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-back:before{content:"\e93f"}.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-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{border-color:rgba(33,150,243,.25)}.label-outline.label-warning{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:#fff3e0;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:67px;height:18px;padding:0 4px;overflow:hidden;font-size:12px;line-height:16px;color:#838a9d;text-align:center;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;border:1px solid #838a9d;border-radius:10px}.label-selector>.label-pri,[class*=label-pri-]{color:#158af1;border-color:#2098ee}.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="0"]:after,.label-severity[data-value="0"]:after{display:none}.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:30px;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:1px;right:0;left:0;display:block;width:18px;height:18px;line-height:18px;text-align:center;content:' ';border-radius:3px}.checkbox-primary>label:after,.radio-primary>label:after{z-index:1;border:2px solid #eee;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:5px;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}.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;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}.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}.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:#1183fb -webkit-gradient(linear,right top,left top,from(#0a48d1),to(#1183fb));background:#1183fb -webkit-linear-gradient(right,#0a48d1 0,#1183fb 100%);background:#1183fb -o-linear-gradient(right,#0a48d1 0,#1183fb 100%);background:#1183fb linear-gradient(-90deg,#0a48d1 0,#1183fb 100%);background-color:#1183fb;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{display:inline-block;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>*{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;border-bottom:1px solid #ddd}#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{position:relative;padding:8px 5px;border:none;border-radius:2px!important}#main .side-col .nav-tabs>li.active>a{font-weight:700;color:#3c4353}#main .side-col .nav-tabs>li.active>a:before{position:absolute;right:0;bottom:-1px;left:0;display:block;height:2px;content:' ';background:#0c64eb}#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 .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:1px;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:4;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{width:0;height:28px;visibility:hidden;opacity:0;-webkit-transition:opacity cubic-bezier(.175,.885,.32,1) .8s;-o-transition:opacity cubic-bezier(.175,.885,.32,1) .8s;transition:opacity cubic-bezier(.175,.885,.32,1) .8s}.table-actions.show-always{width:auto;pointer-events:none;cursor:not-allowed;visibility:visible;opacity:.75}.has-row-checked .table-actions{width:auto;pointer-events:auto!important;cursor:default;visibility:visible;opacity:1}.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:0;left:0;padding:5px 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 .list-group>a.active:hover,#swapper #dropMenu .search-box .list-group>a.active,#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 From d20ba7265b227a4d20bbfeb802571fd2782f395a Mon Sep 17 00:00:00 2001 From: tianshujie Date: Tue, 11 Jan 2022 21:23:16 +0800 Subject: [PATCH 10/85] * Modify the code logic. --- module/kanban/control.php | 4 +--- module/kanban/js/view.js | 36 ++++++++++++++++++++++++++++++++---- module/kanban/model.php | 6 +++--- 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/module/kanban/control.php b/module/kanban/control.php index 640e004377..b87cf766a9 100644 --- a/module/kanban/control.php +++ b/module/kanban/control.php @@ -477,9 +477,7 @@ class kanban extends control } - if($from == 'execution') $this->loadModel('execution'); - - $kanban = $this->$from->getByID($kanbanID); + $kanban = $from == 'execution' ? $this->loadModel('execution')->getByID($kanbanID) : $this->kanban->getByID($kanbanID); $this->view->heightType = $kanban->displayCards > 2 ? 'custom' : 'auto'; diff --git a/module/kanban/js/view.js b/module/kanban/js/view.js index c69c6516fc..e44c19a47f 100644 --- a/module/kanban/js/view.js +++ b/module/kanban/js/view.js @@ -826,6 +826,7 @@ $(function() $(this).toggleClass('icon-chevron-double-up icon-chevron-double-down'); $(this).parents('.region').find('.kanban').toggle(); hideKanbanAction(); + resetRegionHeight($(this).hasClass('icon-chevron-double-up') ? 'open' : 'close'); }); $('.region-header').on('click', '.action', hideKanbanAction); @@ -1013,6 +1014,18 @@ $(function() } }); + resetRegionHeight('open'); +}); + +/** + * Reset region height according to window height. + * + * @param string fold + * @access public + * @return void + */ +function resetRegionHeight(fold) +{ if(Object.keys(regions).length == 1) { var regionID = Object.keys(regions)[0]; @@ -1022,10 +1035,25 @@ $(function() var group = region[0]; if(Object.keys(group.lanes).length == 1) { - var windowHeight = $(window).height(); - $('.region').css('height', windowHeight -132); - $('.kanban-lane').css('height', windowHeight - 222); + var regionHeaderHeight = $('.region-header').outerHeight(); + if(fold == 'open') + { + var windowHeight = $(window).height(); + var headerHeight = $('#mainHeader').height(); + var mainPadding = $('#main').css('padding-top'); + var bodyPadding = $('.panel-body').css('padding-top'); + var height = windowHeight - (parseInt(mainPadding) * 2) - (parseInt(bodyPadding) * 2) - headerHeight - 5; + var regionPadding = $('.kanban').css('padding-bottom'); + var columnHeight = $('.kanban-header').outerHeight(); + + $('.region').css('height', height); + $('.kanban-lane').css('height', height - regionHeaderHeight - parseInt(regionPadding) - columnHeight); + } + else + { + $('.region').css('height', regionHeaderHeight); + } } } } -}); +} diff --git a/module/kanban/model.php b/module/kanban/model.php index 3ffe4c260d..f5c85be4e3 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -2162,14 +2162,14 @@ class kanbanModel extends model $printSetHeight = false; if(common::hasPriv('kanban', 'setLaneHeight')) { - $lanes = $this->dao->select('t2.id')->from(TABLE_KANBANREGION)->alias('t1') + $laneCount = $this->dao->select('COUNT(t2.id) as count')->from(TABLE_KANBANREGION)->alias('t1') ->leftJoin(TABLE_KANBANLANE)->alias('t2')->on('t1.id=t2.region') ->where('t1.kanban')->eq($kanban->id) ->andWhere('t1.deleted')->eq(0) ->andWhere('t2.deleted')->eq(0) - ->fetchPairs(); + ->fetch('count'); - if(count($lanes) > 1) $printSetHeight = true; + if($laneCount > 1) $printSetHeight = true; } $printSettingBtn = (common::hasPriv('kanban', 'createRegion') or $printSetHeight or common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'delete')); From 89dc868c3c0a70ead0b024bb7b1c1e74e5473cc6 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Jan 2022 08:19:34 +0800 Subject: [PATCH 11/85] * Modify the code. --- module/kanban/model.php | 7 ++++--- www/theme/zui/fonts/ZentaoIcon.svg | 2 ++ www/theme/zui/fonts/ZentaoIcon.woff | Bin 58224 -> 58680 bytes 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/module/kanban/model.php b/module/kanban/model.php index f5c85be4e3..ec4a9bced8 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -2156,9 +2156,6 @@ class kanbanModel extends model */ public function setHeaderActions($kanban) { - $actions = ''; - $actions .= "
"; - $actions .= " {$this->lang->kanban->fullScreen}"; $printSetHeight = false; if(common::hasPriv('kanban', 'setLaneHeight')) { @@ -2172,6 +2169,10 @@ class kanbanModel extends model if($laneCount > 1) $printSetHeight = true; } + $actions = ''; + $actions .= "
"; + $actions .= " {$this->lang->kanban->fullScreen}"; + $printSettingBtn = (common::hasPriv('kanban', 'createRegion') or $printSetHeight or common::hasPriv('kanban', 'edit') or common::hasPriv('kanban', 'close') or common::hasPriv('kanban', 'delete')); if($printSettingBtn) diff --git a/www/theme/zui/fonts/ZentaoIcon.svg b/www/theme/zui/fonts/ZentaoIcon.svg index cd9d37a38c..6ae4d31a2b 100644 --- a/www/theme/zui/fonts/ZentaoIcon.svg +++ b/www/theme/zui/fonts/ZentaoIcon.svg @@ -214,8 +214,10 @@ + + diff --git a/www/theme/zui/fonts/ZentaoIcon.woff b/www/theme/zui/fonts/ZentaoIcon.woff index b0392f587efedbd830c15b4ee4250866c15db9e1..4874333d78670b0c7cf53ba67b7aab2668b8714e 100644 GIT binary patch delta 949 zcmYjQOH5Ni6ut8vwl#=-KwCYJk@k3QyP=f<#D&K#cK2De!2a{Nxi67hUMW zL}Nm_VPhg_43@}(Zj2!@pt2xcG=PbUpn!ZNCK3Y+f30^YL?`de%sq3?Oy<5j+tci` z8CH9(va}QkU|TDISUP_Gim}!wFsgx*soouAb}qh4aJZb^odC>bj1~LfT&>rekZS~Z zAEbDEdsXL_oER_Wq9&ih7@57{MiMzU#_1GC;tvydTTdTycLCTC#bj1-OKV31>Xz{g zvPJRailwWo&DnmQ?jF2_cHs9N!&?+uP#yyb zcp3dl&8lW?W^I0LasB&7$;R%N*FHb7`92W~&rNcpTrXG66>_Qpv`k9n+48Lhi$+JR z7LA%pRI(F9ZL+J0kS5a+l?GS$ym{!QBIHo<&#XorHL6vbQv{{ny-oMdVM6_8Q8dq0 ziQyr!s!Ajdv1+c|<03~M1qKG@6Ck`()21pXKN+a*{tN~N#%CaGqi@8Tmz!7twD@5IP@@6}Gcqu~ z%1g{m1&S>IDq0J|ht;o&733EKEqxp?@lUt%1E4|^pmG)l5e7yEg-0Qe#h#vedgbZe zXP=(CJpcOg;L9VES1_6|y*xbm4x^ErxPZWZft3Qq0)YbN0{Q~1{O|am@E_ps;n!eb zW?%#ch0bILCeF>VOlS6NHau{SY4h&G)sk{n4}U5Izl-O$`O3h}0<@5U;qJ4KbufBz z$X#>BPn&!0`ZKe70i~rkzjz?S1 LK9QST_T&%%riq)M From 6b4c03f5a4d4310bb45818ccb57b6c5e2d7b34f4 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Jan 2022 08:35:17 +0800 Subject: [PATCH 12/85] * Add sql statement. --- db/update16.1.sql | 3 ++- db/zentao.sql | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/db/update16.1.sql b/db/update16.1.sql index 1f7e3173b3..7428defdb7 100644 --- a/db/update16.1.sql +++ b/db/update16.1.sql @@ -9,7 +9,8 @@ CREATE TABLE `zt_kanbancell` ( UNIQUE KEY `card_group` (`kanban`,`type`,`lane`,`column`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -ALTER TABLE `zt_kanban` ADD `displayCards` smallint(6) NOT NULL AFTER `order`; +ALTER TABLE `zt_kanban` ADD `displayCards` smallint(6) NOT NULL default '0' AFTER `order`; +ALTER TABLE `zt_project` ADD `displayCards` smallint(6) NOT NULL default '0' AFTER `order`; ALTER TABLE `zt_kanbancard` DROP COLUMN `lane`; ALTER TABLE `zt_kanbancard` DROP COLUMN `column`; diff --git a/db/zentao.sql b/db/zentao.sql index 7638b9a2d0..6d76a6175f 100644 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -677,7 +677,7 @@ CREATE TABLE `zt_kanban` ( `archived` enum('0', '1') NOT NULL DEFAULT '0', `status` enum('active','closed') NOT NULL default 'active', `order` mediumint(8) NOT NULL DEFAULT '0', - `displayCards` smallint(6) NOT NULL, + `displayCards` smallint(6) NOT NULL default '0', `createdBy` char(30) NOT NULL, `createdDate` datetime NOT NULL, `lastEditedBy` char(30) NOT NULL, @@ -1020,6 +1020,7 @@ CREATE TABLE IF NOT EXISTS `zt_project` ( `acl` char(30) NOT NULL DEFAULT 'open', `whitelist` text NOT NULL, `order` mediumint(8) unsigned NOT NULL, + `displayCards` smallint(6) NOT NULL default '0', `deleted` enum('0','1') NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `parent` (`parent`), From 8206d239cc5b7ac3958ab3b3008438b416154792 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Jan 2022 09:08:56 +0800 Subject: [PATCH 13/85] * Recalculate area height. --- module/kanban/js/view.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/module/kanban/js/view.js b/module/kanban/js/view.js index e44c19a47f..03bf944210 100644 --- a/module/kanban/js/view.js +++ b/module/kanban/js/view.js @@ -1039,10 +1039,11 @@ function resetRegionHeight(fold) if(fold == 'open') { var windowHeight = $(window).height(); - var headerHeight = $('#mainHeader').height(); + var headerHeight = $('#mainHeader').outerHeight(); var mainPadding = $('#main').css('padding-top'); + var panelBorder = $('.panel').css('border-top-width'); var bodyPadding = $('.panel-body').css('padding-top'); - var height = windowHeight - (parseInt(mainPadding) * 2) - (parseInt(bodyPadding) * 2) - headerHeight - 5; + var height = windowHeight - (parseInt(mainPadding) * 2) - (parseInt(bodyPadding) * 2) - headerHeight - (parseInt(panelBorder) * 2); var regionPadding = $('.kanban').css('padding-bottom'); var columnHeight = $('.kanban-header').outerHeight(); From adf53d8754ac199d9212e5d4665ba35e6c24d79d Mon Sep 17 00:00:00 2001 From: liumengyi Date: Wed, 12 Jan 2022 10:08:15 +0800 Subject: [PATCH 14/85] * Finish task #47334.Add default view of professional RD Kanban. --- module/execution/control.php | 29 +- module/execution/css/kanban.css | 142 +- module/execution/js/kanban.js | 1690 ++++++++------------- module/execution/js/taskkanban.js | 8 +- module/execution/model.php | 2 +- module/execution/view/kanban.html.php | 188 +-- module/execution/view/taskheader.html.php | 2 +- module/execution/view/taskkanban.html.php | 4 +- module/kanban/model.php | 161 +- 9 files changed, 1000 insertions(+), 1226 deletions(-) diff --git a/module/execution/control.php b/module/execution/control.php index 407ab663c3..f934284e97 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1263,8 +1263,7 @@ class execution extends control } $project = $this->project->getByID($projectID); - - if(!empty($projectID) and $project->model == 'kanban') + if(!empty($project) and $project->model == 'kanban') { $this->lang->execution->createExec = str_replace($this->lang->execution->common, $this->lang->execution->kanban, $this->lang->execution->createExec); $this->lang->execution->execName = str_replace($this->lang->execution->common, $this->lang->execution->kanban, $this->lang->execution->execName); @@ -1962,12 +1961,34 @@ class execution extends control * @param int $executionID * @param string $browseType * @param string $orderBy - * @param string $group + * @param string $groupBy * @access public * @return void */ - public function kanban($executionID, $browseType = 'all', $orderBy = 'id_asc', $group = 'all') + public function kanban($executionID, $browseType = 'all', $orderBy = 'id_asc', $groupBy = 'all') { + unset($this->lang->execution->menu); + + $users = $this->loadModel('user')->getPairs('noletter|nodeleted'); + $kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $browseType, $orderBy, $groupBy); + $execution = $this->execution->getById($executionID); + + $userList = array(); + $avatarPairs = $this->dao->select('account, avatar')->from(TABLE_USER)->where('deleted')->eq(0)->fetchPairs(); + foreach($avatarPairs as $account => $avatar) + { + if(!$avatar) continue; + $userList[$account]['avatar'] = $avatar; + } + + $this->view->title = $this->lang->kanban->view; + $this->view->users = $users; + $this->view->regions = $kanbanData; + $this->view->execution = $execution; + $this->view->userList = $userList; + $this->view->browseType = $browseType; + $this->view->orderBy = $orderBy; + $this->view->groupBy = $groupBy; $this->display(); } diff --git a/module/execution/css/kanban.css b/module/execution/css/kanban.css index 372183c4b4..df132b1ab1 100644 --- a/module/execution/css/kanban.css +++ b/module/execution/css/kanban.css @@ -1,58 +1,110 @@ -#main {padding-bottom: 10px;} -#main > .container {max-width: 1960px!important; padding: 0 10px} +#TRAction .icon {padding: 0px 6px; font-size: 14px} -.kanban + .kanban {margin-top: 15px} -.kanban-card > .title {display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis} -.kanban-card > .infos {position: relative; margin-top: 5px} -.kanban-card > .infos > .info + .info {margin-left: 8px} -.kanban-card > .infos > .info-id, -.kanban-card > .infos > .info-deadline, -.kanban-card > .infos > .info-estimate {font-size: 12px; position: relative; top: 2px} -.kanban-card > .infos > .label-pri {min-width: 16px; line-height: 14px; height: 16px; padding: 0} -.kanban-card > .infos > .label-severity {transform: scale(.75)} -.kanban-card > .infos > .avatar {position: absolute; right: 0; top: 0} -.kanban-card > .actions {position: absolute; top: 4px; right: 4px; opacity: 0;} +.has-error .form-control {border-color: #ff4268!important;} +.has-error .form-control:focus {box-shadow: inset 0 1px 1px rgb(0 0 0 / 8%), 0 0 6px #f5b2a5!important;} +.has-error .form-control::placeholder {color: #ff4268!important;} + +.label.text-red {background: #ff4268 !important; color: #ffffff;} + +.dropdown-menu > li {padding: 0 10px;} +.dropdown-menu > li > a > .icon {position: relative; left: -5px;} + +#kanbanContainer {padding-bottom: 0; margin-bottom: 0;} +#kanbanContainer.fullscreen {overflow: auto;} + +.region {border: 1px solid #dcdcdc; background-color: #fff;} +.region + .region {margin-top: 20px;} +.region .region-header {padding: 10px;} +.region .region-header span {font-size: 14px; color: #999EAB} +.region .region-header label {color: #999; background: transparent; border: 1px solid #ddd; margin-left: 10px; margin-right: 10px} +.region .region-header .action {float: right} +.region .region-header .icon-double-angle-up,.icon-double-angle-down {cursor: pointer;} +.region .kanban-header-sub-cols .kanban-header-col > .title {max-width: 100% !important;min-width:240px;} +.region .sort .region-header {cursor: move;} + +.region .kanban {padding: 0px 10px 10px 10px; min-height: unset; overflow: auto} +.region .kanban .form-actions {margin: 0;} +.region .kanban .form-actions .btn {margin-right: 10px; min-width: 50px;} + +.region .kanban-board + .kanban-board {margin-top: 20px;} +.region .kanban-board > .kanban-header > .kanban-group-header {padding: 8px 2px; width: 20px;} +.region .kanban-board > .kanban-header > .kanban-group-header:hover {cursor: move;} +.region .kanban-board.sort > .kanban-header {padding-left: 0;} + +.region .kanban-header {border-bottom: none!important; min-width: max-content; min-width: -moz-max-content;} +.region .kanban-header-col > .title {max-width: 80% !important;} +.region .kanban-header-col > .title {margin: 0} +.region .kanban-header-col > .title > span {display: inline-block; overflow: hidden; padding-right:2px; position: initial; max-width: 140px !important;} +.region .kanban-header-col > .title > .text-grey {opacity: .5; font-weight: bold; color: #8b91a2;} +.region .kanban-header-col > .title > .count {opacity: .5; font-weight: bold; color: #8b91a2;} +.region .kanban-header-col > .title > .error {color: #333333; padding-left: 2px; font-size: 10px; padding-top: 1px; padding-right: 2px;} +.kanban-affixed .kanban-header-col > .title > .text {color: #fff!important} +.region .kanban-header-col > .actions {position: relative; right: -30px;} +.region .kanban-header-parent-col > .actions {position: absolute; right: 0px;} +.region .kanban-header-sub-cols .actions {position: absolute; right: 0px;} + +.region .kanban-lane {position: relative; border-bottom: none!important; min-height: 200px !important} + +.region .kanban-lane > .kanban-lane-name > .text {margin: auto 0; max-height: 150px; overflow: hidden; text-overflow: ellipsis} +.region .kanban-lane > .kanban-lane-name > .actions {position: absolute; top: 0; left: 0; right: 0; opacity: 0;} +.region .kanban-lane > .kanban-lane-name > .actions > a {display: block; width: 20px; height: 20px; line-height: 20px; text-align: center; opacity: .7; color: #fff;} +.region .kanban-lane > .kanban-lane-name > .actions > a:hover {background-color: rgba(0,0,0,.2); opacity: 1;} +.region .kanban-lane > .kanban-lane-name:hover > .actions {opacity: 1;} +.region .kanban-lane.sort > .kanban-lane-name {cursor: move;} + +.region .kanban-lane-col {max-height: unset !important; overflow: auto!important; position: relative;} +.region .kanban-lane-col.has-scrollbar > .kanban-lane-actions {position: absolute; background-color: inherit; bottom: 0; left: 0; right: 0;} + +.region .kanban-lane-items {overflow: auto; padding-bottom: 10px;} + +.region .kanban-item {position: relative} +.region .kanban-item > .kanban-card > .title:hover {color: #2272eb} +.region .kanban-item > .kanban-card > .info {margin-top: 5px; position: relative;} +.region .kanban-item > .kanban-card > .info > .pri {height: 14px; border-width: 1px; font-size: 12px; line-height: 12px; min-width: 14px; padding: 0 1px;} +.region .kanban-item > .kanban-card > .info > .estimate{margin-left: 4px; color: #999; background-color: rgb(255, 255, 255); padding: 3px 0px} +.region .kanban-item > .kanban-card > .info > .time {margin-left: 4px; font-size: 12px; background: rgb(242, 242, 242)} +.region .kanban-item > .kanban-card > .info > .user {position: absolute; right: 0; top: -2px} +.region .kanban-item > .kanban-card > .info > .user > .avatar {display: inline-block; width: 24px; height: 24px; line-height: 24px; margin-right: 0px; margin-left: 2px} +.region .kanban-item > .kanban-card > .info > .user > span {display: inline-block; color: transparent; width: 2px; height: 2px; background-color: #8990a2; position: sticky; border-radius: 50%; top: 3px; margin: 0 7px;} +.region .kanban-item > .kanban-card > .info > .user > span:before, +.region .kanban-item > .kanban-card > .info > .user > span:after {content: ''; display: block; position: absolute; width: 2px; height: 2px; background-color: #8990a2; top: 0; border-radius: 50%} +.region .kanban-item > .kanban-card > .info > .user > span:before {left: -4px;} +.region .kanban-item > .kanban-card > .info > .user > span:after {right: -4px;} +.region .kanban-item > .kanban-card > .actions > a {display: block; float: left; width: 20px; height: 20px; line-height: 20px; text-align: center; border-radius: 4px; opacity: .7;} +.region .kanban-item > .kanban-card > .actions > a:hover {background-color: rgba(0,0,0,.075); opacity: 1;} +.region .kanban-item:hover > .actions {opacity: 1;} +.region .kanban-item .has-color .title, +.region .kanban-item .has-color .actions .icon-more-v, +.region .kanban-item .has-color .info > .label-pri, +.region .kanban-item .has-color .info > .estimate, +.region .kanban-item .has-color .info > .user .lable-teamSumCount, +.region .kanban-item .has-color .info > .label-light {color: #FFFFFF;} +.region .kanban-item .has-color .info > .label-pri {border-color: #FFFFFF;} +.region .kanban-item .item-more {position: absolute; right: 6px; top: 0px;} + +.kanban-card {height: auto !important; padding: 8px 14px !important} +.kanban-card > .title {word-break: break-all;} +.kanban-card > .info {position: relative; margin-top: 5px} +.kanban-card > .info > .info + .info {margin-left: 8px} .kanban-card:hover > .actions {opacity: 1;} +.kanban-card > .actions {position: absolute; top: 4px; right: 4px; opacity: 0;} .kanban-card > .actions > a {display: block; float: left; width: 20px; height: 20px; line-height: 20px; text-align: center; border-radius: 4px; opacity: .7;} .kanban-card > .actions > a:hover {background-color: rgba(0,0,0,.075); opacity: 1;} -.kanban-header-col > .actions {padding-top: 22px} -.kanban-header-parent-col .kanban-header-col > .actions {padding-top: 6px; padding-right: 2px;} -.kanban-header-col > .actions > a {display: block; float: left; width: 20px; height: 20px; line-height: 20px; text-align: center; border-radius: 4px; opacity: .7;} -.kanban-header-col > .actions > a:hover {background-color: rgba(0,0,0,.075); opacity: 1;} +.cardcolor {width:40px; height: 14px; float: left; margin-left: 5px; margin-right: 5px; margin-top: 2px; border-radius: 2px;} +#cardcolormenu {padding:2px 2px; width: 100px;} -.kanban-lane-name > .actions {position: absolute; top: 0; left: 0; right: 0; opacity: 0;} -.kanban-lane-name:hover > .actions {opacity: 1;} -.kanban-lane-name > .actions > a {display: block; width: 20px; height: 20px; line-height: 20px; text-align: center; opacity: .7; color: #fff;} -.kanban-lane-name > .actions > a:hover {background-color: rgba(0,0,0,.2); opacity: 1;} +.kanban-col[data-type=ADD] {display: none;} +.kanban-col[data-type=EMPTY] {display: none;} +.kanban-item:hover .title {padding-right: 10px;} +.gray .actions {display:none;} -.kanban-affixed .kanban-header-col > .title > .text, -.kanban-affixed .kanban-header-col > .title > .count {color: #fff!important;} - -#kanbanContainer {margin: 0;} -#kanbanContainer > .panel-body {overflow: auto;} -#kanbans .kanban {min-height: initial;} -#kanbans .kanban-lane {min-height: 150px; margin-top: 2px;} -#kanbans .kanban-affixed > .kanban-header {top: 100px;} -#kanbans .kanban-card[data-scale-size="4"] {padding: 8px;} -#kanbans .kanban-card[data-scale-size="3"] {padding: 3px 4px;} -#kanbans .kanban-card[data-scale-size="3"] > .title {white-space: normal; max-height: 100%;} -#kanbans .kanban-card[data-scale-size="2"] {padding: 3px 4px; overflow: hidden;} -#kanbans .kanban-card[data-scale-size="2"] > .title {display: inline; line-height: 18px; white-space: normal; max-height: 100%; word-break: break-all;} -#kanbans .kanban-card[data-scale-size="2"] > .infos {display: inline-block; height: 18px; vertical-align: top; margin: 0;} -#kanbans .kanban-card[data-scale-size="2"] > .infos > .info-pri {transform: scale(.8); vertical-align: top;} -#kanbans .kanban-card[data-scale-size="2"] > .infos > .avatar {display: inline-block; transform: scale(.8); position: relative; top: -2px; vertical-align: top; margin-right: -1px;} +.c-type {width: 150px !important; overflow: unset;} +.c-group {width: 190px !important; overflow: unset;} +.c-type {margin-left: 0px !important;} #kanbanScaleControl {width: 100px;} #kanbanScaleControl .input-group-addon {background: #fff; padding: 5px;} #kanbanScaleControl > .input-group-btn:first-child > .btn {border-radius: 16px 0 0 16px; border-right-color: transparent;} #kanbanScaleControl > .input-group-btn:last-child > .btn {border-radius: 0 16px 16px 0; border-left-color: transparent;} #kanbanScaleControl > .input-group-btn > .btn:hover {border-color: #b8bfce;} - -#type_chosen .icon-kanban {padding-right: 10px; font-size: 15px;} - -.dropdown-menu a {text-align: left;} -.scrollbar-hover {max-height: 2000px; overflow: scroll !important;} -.c-type {width: 150px !important; overflow: unset;} -.c-group {width: 190px !important; overflow: unset;} -.c-type {margin-left: 0px !important;} diff --git a/module/execution/js/kanban.js b/module/execution/js/kanban.js index daf1724e18..ccbd589e45 100644 --- a/module/execution/js/kanban.js +++ b/module/execution/js/kanban.js @@ -1,886 +1,3 @@ -function changeView(view) -{ - var link = createLink('execution', 'kanban', "executionID=" + executionID + '&type=' + view); - location.href = link; -} - -/** - * Render user avatar - * @param {String|{account: string, avatar: string}} user User account or user object - * @returns {string} - */ -function renderUserAvatar(user, objectType, objectID, size) -{ - var avatarSizeClass = 'avatar-' + (size || 'sm'); - var $noPrivAndNoAssigned = $('
'); - if(objectType == 'task') - { - if(!priv.canAssignTask && !user) return $noPrivAndNoAssigned; - var link = createLink('task', 'assignto', 'executionID=' + executionID + '&id=' + objectID, '', true); - } - if(objectType == 'story') - { - if(!priv.canAssignStory && !user) return $noPrivAndNoAssigned; - var link = createLink('story', 'assignto', 'id=' + objectID, '', true); - } - if(objectType == 'bug') - { - if(!priv.canAssignBug && !user) return $noPrivAndNoAssigned; - var link = createLink('bug', 'assignto', 'id=' + objectID, '', true); - } - - if(!user) return $(''); - - if(typeof user === 'string') user = {account: user}; - if(!user.avatar && window.userList && window.userList[user.account]) user = window.userList[user.account]; - - var $noPrivAvatar = $('
').avatar({user: user}); - if(objectType == 'task' && !priv.canAssignTask) return $noPrivAvatar; - if(objectType == 'story' && !priv.canAssignStory) return $noPrivAvatar; - if(objectType == 'bug' && !priv.canAssignBug) return $noPrivAvatar; - - return $('').avatar({user: user}); -} - -/** - * Render deadline - * @param {String|Date} deadline Deadline - * @returns {JQuery} - */ -function renderDeadline(deadline) -{ - if(deadline == '0000-00-00') return; - - var date = $.zui.createDate(deadline); - var now = new Date(); - now.setHours(0); - now.setMinutes(0); - now.setSeconds(0); - now.setMilliseconds(0); - var isEarlyThanToday = date.getTime() < now.getTime(); - var deadlineDate = $.zui.formatDate(date, 'MM-dd'); - - return $('').text(deadlineLang + ' ' + deadlineDate).addClass(isEarlyThanToday ? 'text-red' : 'text-muted'); -} - -/** - * Render story item - * @param {Object} item Story item object - * @param {JQuery} $item Kanban item element - * @param {Object} col Column object - * @returns {JQuery} $item Kanban item element - */ -function renderStoryItem(item, $item, col) -{ - var scaleSize = window.kanbanScaleSize; - if(+$item.attr('data-scale-size') !== scaleSize) $item.empty().attr('data-scale-size', scaleSize); - - if(scaleSize <= 3) - { - var $title = $item.find('.title'); - if(!$title.length) - { - $title = $('' + (scaleSize <= 1 ? ' ' : '') + '') - .attr('href', $.createLink('story', 'view', 'storyID=' + item.id, '', true)); - $title.appendTo($item); - } - $title.attr('title', item.title).find('.text').text(item.title); - } - - if(scaleSize <= 2) - { - var idHtml = scaleSize <= 1 ? ('#' + item.id + '') : ''; - var priHtml = '' + item.pri + ''; - var hoursHtml = (item.estimate && scaleSize <= 1) ? ('' + item.estimate + 'h') : ''; - var avatarHtml = renderUserAvatar(item.assignedTo, 'story', item.id); - var $infos = $item.find('.infos'); - if(!$infos.length) $infos = $('
'); - $infos.html([idHtml, priHtml, hoursHtml].join('')); - - $infos[scaleSize <= 1 ? 'append' : 'prepend'](avatarHtml); - if(scaleSize <= 1) $infos.appendTo($item); - else if(scaleSize === 2) $infos.prependTo($item); - else $infos.prependTo($item.find('.title')); - } - else if(scaleSize === 4) - { - $item.html(renderUserAvatar(item.assignedTo, 'story', item.id, 'md')); - } - - if(scaleSize <= 1) - { - var $actions = $item.find('.actions'); - if(!$actions.length && item.menus.length) - { - $actions = $([ - '
', - '', - '', - '', - '
' - ].join('')).appendTo($item); - } - } - - return $item.attr('data-type', 'story').addClass('kanban-item-story'); -} - -/** - * Render bug item - * @param {Object} item Bug item object - * @param {JQuery} $item Kanban item element - * @param {Object} col Column object - * @returns {JQuery} $item Kanban item element - */ -function renderBugItem(item, $item, col) -{ - var scaleSize = window.kanbanScaleSize; - if(+$item.attr('data-scale-size') !== scaleSize) $item.empty().attr('data-scale-size', scaleSize); - - if(scaleSize <= 3) - { - var $title = $item.find('.title'); - if(!$title.length) - { - $title = $('' + (scaleSize <= 1 ? ' ' : '') + '') - .attr('href', $.createLink('bug', 'view', 'bugID=' + item.id, '', true)); - $title.appendTo($item); - } - $title.attr('title', item.title).find('.text').text(item.title); - } - - if(scaleSize <= 2) - { - var idHtml = scaleSize <= 1 ? ('#' + item.id + '') : ''; - var severityHtml = scaleSize <= 1 ? ('') : ''; - var priHtml = '' + item.pri + ''; - var avatarHtml = renderUserAvatar(item.assignedTo, 'bug', item.id); - - var $infos = $item.find('.infos'); - if(!$infos.length) $infos = $('
'); - $infos.html([idHtml, severityHtml, priHtml].join('')); - if(item.deadline && scaleSize <= 1) $infos.append(renderDeadline(item.deadline)); - $infos[scaleSize <= 1 ? 'append' : 'prepend'](avatarHtml); - - if(scaleSize <= 1) $infos.appendTo($item); - else if(scaleSize === 2) $infos.prependTo($item); - else $infos.prependTo($item.find('.title')); - } - else if(scaleSize === 4) - { - $item.html(renderUserAvatar(item.assignedTo, 'bug', item.id, 'md')); - } - - if(scaleSize <= 1) - { - var $actions = $item.find('.actions'); - if(!$actions.length && item.menus.length) - { - $actions = $([ - '
', - '', - '', - '', - '
' - ].join('')).appendTo($item); - } - } - - return $item.attr('data-type', 'bug').addClass('kanban-item-bug'); -} - -/** - * Render task item - * @param {Object} item Task item object - * @param {JQuery} $item Kanban item element - * @param {Object} col Column object - * @returns {JQuery} $item Kanban item element - */ -function renderTaskItem(item, $item, col) -{ - var scaleSize = window.kanbanScaleSize; - if(+$item.attr('data-scale-size') !== scaleSize) $item.empty().attr('data-scale-size', scaleSize); - - if(scaleSize <= 3) - { - var $title = $item.find('.title'); - if(!$title.length) - { - $title = $('' + (scaleSize <= 1 ? ' ' : '') + '') - .attr('href', $.createLink('task', 'view', 'taskID=' + item.id, '', true)); - $title.appendTo($item); - } - $title.attr('title', item.name).find('.text').text(item.name); - } - - if(scaleSize <= 2) - { - var idHtml = scaleSize <= 1 ? ('#' + item.id + '') : ''; - var priHtml = '' + item.pri + ''; - var hoursHtml = (item.estimate && scaleSize <= 1) ? ('' + item.estimate + 'h') : ''; - var avatarHtml = renderUserAvatar(item.assignedTo, 'task', item.id); - - var $infos = $item.find('.infos'); - if(!$infos.length) $infos = $('
'); - $infos.html([idHtml, priHtml, hoursHtml].join('')); - if(item.deadline && scaleSize <= 1) $infos.append(renderDeadline(item.deadline)); - $infos[scaleSize <= 1 ? 'append' : 'prepend'](avatarHtml); - - if(scaleSize <= 1) $infos.appendTo($item); - else if(scaleSize === 2) $infos.prependTo($item); - else $infos.prependTo($item.find('.title')); - } - else if(scaleSize === 4) - { - $item.html(renderUserAvatar(item.assignedTo, 'task', item.id, 'md')); - } - - if(scaleSize <= 1) - { - var $actions = $item.find('.actions'); - if(!$actions.length && item.menus.length) - { - $actions = $([ - '
', - '', - '', - '', - '
' - ].join('')).appendTo($item); - } - } - - $item.attr('data-type', 'task').addClass('kanban-item-task'); - - return $item; -} - -/* Add column renderer */ -addColumnRenderer('story', renderStoryItem); -addColumnRenderer('bug', renderBugItem); -addColumnRenderer('task', renderTaskItem); - -/** - * Render column count - * @param {JQuery} $count Kanban count element - * @param {number} count Column cards count - * @param {number} col Column object - * @param {Object} kanban Kanban intance - */ -function renderColumnCount($count, count, col) -{ - var text = count + '/' + (col.limit < 0 ? '' : col.limit); - $count.html(text + ''); -} - -/** - * Render header column - * @param {JQuery} $col Header column element - * @param {Object} col Header column object - * @param {JQuery} $header Header element - * @param {Object} kanban Kanban object - */ -function renderHeaderCol($col, col, $header, kanban) -{ - if(col.asParent) $col = $col.children('.kanban-header-col'); - var $actions = $('
'); - var printStoryButton = printTaskButton = printBugButton = false; - if(priv.canCreateStory || priv.canBatchCreateStory || priv.canLinkStory || priv.canLinkStoryByPlane) printStoryButton = true; - if(priv.canCreateTask || priv.canBatchCreateTask) printTaskButton = true; - if(priv.canCreateBug || priv.canBatchCreateBug) printBugButton = true; - - if((col.type === 'backlog' && printStoryButton) || (col.type === 'wait' && printTaskButton) || (col.type == 'unconfirmed' && printBugButton)) - { - $actions.append([ - '', - '', - '' - ].join('')); - } - - $actions.append([ - '', - '', - '' - ].join('')); - $actions.appendTo($col); -} - -/** - * Render lane name - * @param {JQuery} $name Name element - * @param {Object} lane Lane object - * @param {JQuery} $kanban $kanban element - * @param {Object} columns Kanban columns - * @param {Object} kanban Kanban object - */ -function renderLaneName($name, lane, $kanban, columns, kanban) -{ - if(lane.id != 'story' && lane.id != 'task' && lane.id != 'bug') return false; - if(!$name.children('.actions').length && (priv.canSetLane || priv.canMoveLane)) - { - $([ - '
', - '', - '', - '', - '
' - ].join('')).appendTo($name); - } -} - -/** - * Updata kanban data - * @param {string} kanbanID Kanban id - * @param {Object} data Kanban data - */ -function updateKanban(kanbanID, data) -{ - var $kanban = $('#kanban-' + kanbanID); - if(!$kanban.length) return; - - $kanban.data('zui.kanban').render(data); -} - -/** - * Create kanban in page - * @param {string} kanbanID Kanban id - * @param {Object} data Kanban data - * @param {Object} options Kanban options - */ -function createKanban(kanbanID, data, options) -{ - var $kanban = $('#kanban-' + kanbanID); - if($kanban.length) return updateKanban(kanbanID, data); - - $kanban = $('
').appendTo('#kanbans'); - $kanban.kanban($.extend({data: data}, options)); -} - -function fullScreen() -{ - var element = document.getElementById('kanbanContainer'); - var requestMethod = element.requestFullScreen || element.webkitRequestFullScreen || element.mozRequestFullScreen || element.msRequestFullScreen; - if(requestMethod) - { - var afterEnterFullscreen = function() - { - $('#kanbanContainer').addClass('scrollbar-hover'); - $('.actions').hide(); - $('#kanbanContainer a.iframe').each(function() - { - if($(this).hasClass('iframe')) - { - var href = $(this).attr('href'); - $(this).removeClass('iframe'); - $(this).attr('href', 'javascript:void(0)'); - $(this).attr('href-bak', href); - } - }) - $.cookie('isFullScreen', 1); - } - - var whenFailEnterFullscreen = function() - { - exitFullScreen(); - } - - try - { - var result = requestMethod.call(element); - if(result && (typeof result.then === 'function' || result instanceof window.Promise)) - { - result.then(afterEnterFullscreen).catch(whenFailEnterFullscreen); - } - else - { - afterEnterFullscreen(); - } - } - catch (error) - { - whenFailEnterFullscreen(error); - } - } -} - -/** - * Exit full screen. - * - * @access public - * @return void - */ -function exitFullScreen() -{ - $('#kanbanContainer').removeClass('scrollbar-hover'); - $('.actions').show(); - $('#kanbanContainer a').each(function() - { - var hrefBak = $(this).attr('href-bak'); - if(hrefBak) - { - $(this).addClass('iframe'); - $(this).attr('href', hrefBak); - } - }) - $.cookie('isFullScreen', 0); -} - -document.addEventListener('fullscreenchange', function (e) -{ - if(!document.fullscreenElement) exitFullScreen(); -}); - -document.addEventListener('webkitfullscreenchange', function (e) -{ - if(!document.webkitFullscreenElement) exitFullScreen(); -}); - -document.addEventListener('mozfullscreenchange', function (e) -{ - if(!document.mozFullScreenElement) exitFullScreen(); -}); - -document.addEventListener('msfullscreenChange', function (e) -{ - if(!document.msfullscreenElement) exitFullScreen(); -}); - -/* Define drag and drop rules */ -if(!window.kanbanDropRules) -{ - window.kanbanDropRules = - { - story: - { - backlog: ['ready'], - ready: ['backlog'], - }, - bug: - { - 'unconfirmed': ['confirmed', 'fixing', 'fixed'], - 'confirmed': ['fixing', 'fixed'], - 'fixing': ['fixed'], - 'fixed': ['testing', 'tested', 'fixing'], - 'testing': ['tested', 'closed', 'fixing'], - 'tested': ['closed', 'fixing'], - 'closed': ['fixing'], - }, - task: - { - 'wait': ['developing', 'developed', 'canceled', 'closed'], - 'developing': ['developed', 'pause'], - 'developed': ['canceled', 'closed'], - 'pause': ['developing'], - 'canceled': ['developing'], - 'closed': ['developing'], - } - } -} - -/* - * Find drop columns - * @param {JQuery} $element Drag element - * @param {JQuery} $root Dnd root element - */ -function findDropColumns($element, $root) -{ - var $col = $element.closest('.kanban-col'); - var col = $col.data(); - var kanbanID = $root.data('id'); - var kanbanRules = window.kanbanDropRules ? window.kanbanDropRules[kanbanID] : null; - - if(!kanbanRules) return $root.find('.kanban-lane-col:not([data-type="' + col.type + '"])'); - - var colRules = kanbanRules[col.type]; - var lane = $col.closest('.kanban-lane').data('lane'); - return $root.find('.kanban-lane-col').filter(function() - { - if(!colRules) return false; - if(colRules === true) return true; - - var $newCol = $(this); - var newCol = $newCol.data(); - if(newCol.id === col.id) return false; - - var $newLane = $newCol.closest('.kanban-lane'); - var newLane = $newLane.data('lane'); - var canDropHere = colRules.indexOf(newCol.type) > -1 && newLane.id === lane.id; - if(canDropHere) $newCol.addClass('can-drop-here'); - return canDropHere; - }); -} - -/** - * Change column type for a card - * @param {Object} card Card object - * @param {String} fromColType The column type before change - * @param {String} toColType The column type after change - * @param {String} kanbanID Kanban ID - */ -function changeCardColType(card, fromColType, toColType, kanbanID) -{ - if(typeof card == 'undefined') return false; - var objectID = card.id; - var showIframe = false; - var moveCard = false; - - /* Task lane. */ - if(kanbanID == 'task') - { - if(toColType == 'developed') - { - if((fromColType == 'developing' || fromColType == 'wait') && priv.canFinishTask) - { - var link = createLink('task', 'finish', 'taskID=' + objectID, '', true); - showIframe = true; - } - } - else if(toColType == 'pause') - { - if(fromColType == 'developing' && priv.canPauseTask) - { - var link = createLink('task', 'pause', 'taskID=' + objectID, '', true); - showIframe = true; - } - } - else if(toColType == 'developing') - { - if((fromColType == 'pause' || fromColType == 'cancel' || fromColType == 'closed' || fromColType == 'developed') && priv.canActivateTask) - { - var link = createLink('task', 'activate', 'taskID=' + objectID, '', true); - showIframe = true; - } - if(fromColType == 'wait' && priv.canStartTask) - { - var link = createLink('task', 'start', 'taskID=' + objectID, '', true); - showIframe = true; - } - } - else if(toColType == 'canceled') - { - if((fromColType == 'developing' || fromColType == 'wait' || fromColType == 'pause') && priv.canCancelTask) - { - var link = createLink('task', 'cancel', 'taskID=' + objectID, '', true); - showIframe = true; - } - } - else if(toColType == 'closed') - { - if((fromColType == 'developed' || fromColType == 'canceled') && priv.canCloseTask) - { - var link = createLink('task', 'close', 'taskID=' + objectID, '', true); - showIframe = true; - } - } - } - - /* Bug lane. */ - if(kanbanID == 'bug') - { - if(toColType == 'confirmed') - { - if(fromColType == 'unconfirmed' && priv.canConfirmBug) - { - var link = createLink('bug', 'confirmBug', 'bugID=' + objectID, '', true); - showIframe = true; - } - } - else if(toColType == 'fixing') - { - if(fromColType == 'confirmed' || fromColType == 'unconfirmed') moveCard = true; - if((fromColType == 'closed' || fromColType == 'fixed' || fromColType == 'testing' || fromColType == 'tested') && priv.canActivateBug) - { - var link = createLink('bug', 'activate', 'bugID=' + objectID, '', true); - showIframe = true; - } - } - else if(toColType == 'fixed') - { - if(fromColType == 'fixing' || fromColType == 'confirmed' || fromColType == 'unconfirmed') - { - var link = createLink('bug', 'resolve', 'bugID=' + objectID, '', true); - showIframe = true; - } - } - else if(toColType == 'testing') - { - if(fromColType == 'fixed') moveCard = true; - } - else if(toColType == 'tested') - { - if(fromColType == 'fixed' || fromColType == 'testing') moveCard = true; - } - else if(toColType == 'closed') - { - if(fromColType == 'testing' || fromColType == 'tested') - { - var link = createLink('bug', 'close', 'bugID=' + objectID, '', true); - showIframe = true; - } - } - - if(moveCard) - { - var colID = card.$col.columnID; - var link = createLink('kanban', 'ajaxMoveCard', 'cardID=' + objectID + '&colID=' + colID + '&toColType=' + toColType + '&execitionID=' + executionID + '&browseType=' + browseType + '&groupBy=' + groupBy); - $.get(link, function(data) - { - if(data) - { - kanbanGroup = $.parseJSON(data); - if(groupBy == 'default') - { - updateKanban('bug', kanbanGroup.bug); - } - else - { - updateKanban(browseType, kanbanGroup[groupBy]); - } - } - }) - } - } - - /* Story lane. */ - if(kanbanID == 'story') - { - if(toColType == 'ready' || toColType == 'backlog') - { - var colID = card.$col.columnID; - var link = createLink('kanban', 'ajaxMoveCard', 'cardID=' + objectID + '&colID=' + colID + '&toColType=' + toColType + '&execitionID=' + executionID + '&browseType=' + browseType + '&groupBy=' + groupBy); - $.get(link, function(data) - { - if(data) - { - kanbanGroup = $.parseJSON(data); - if(groupBy == 'default') - { - updateKanban('story', kanbanGroup.story); - } - else - { - updateKanban(browseType, kanbanGroup[groupBy]); - } - } - }) - } - } - - if(showIframe) - { - var modalTrigger = new $.zui.ModalTrigger({type: 'iframe', width: '80%', url: link}); - modalTrigger.show(); - } -} - -/** - * Handle finish drop task - * @param {Object} event Event object - * @returns {void} - */ -function handleFinishDrop(event) -{ - var $card = $(event.element); // The drag card - var $dragCol = $card.closest('.kanban-lane-col'); - var $dropCol = $(event.target); - - /* Get d-n-d(drag and drop) infos */ - var card = $card.data('item'); - var fromColType = $dragCol.data('type'); - var toColType = $dropCol.data('type'); - var kanbanID = $card.closest('.kanban').data('id'); - - changeCardColType(card, fromColType, toColType, kanbanID); - - $('#kanbans').find('.can-drop-here').removeClass('can-drop-here'); -} - -/** Handle sort cards in column */ -function handleSortColCards() -{ - /* TODO: handle sort cards from column contextmenu */ - return false; -} - -/** - * Create column menu - * @returns {Object[]} - */ -function createColumnMenu(options) -{ - var $col = options.$trigger.closest('.kanban-col'); - var col = $col.data('col'); - var kanbanID = options.kanban; - - var items = []; - if(priv.canEditName) items.push({label: executionLang.editName, url: $.createLink('kanban', 'setColumn', 'col=' + col.columnID + '&executionID=' + executionID + '&from=execution'), className: 'iframe', attrs: {'data-width': '500px'}}) - if(priv.canSetWIP) items.push({label: executionLang.setWIP, url: $.createLink('kanban', 'setWIP', 'col=' + col.columnID + '&executionID=' + executionID + '&from=execution'), className: 'iframe', attrs: {'data-width': '500px'}}) - //if(priv.canSortCards) items.push({label: executionLang.sortColumn, items: ['按ID倒序', '按ID顺序'], className: 'iframe', onClick: handleSortColCards}) - return items; -} - -/** - * Create column create button menu - * @returns {Object[]} - */ -function createColumnCreateMenu(options) -{ - var $col = options.$trigger.closest('.kanban-col'); - var col = $col.data('col'); - var items = []; - - if(col.laneType == 'story') - { - if(priv.canCreateStory) items.push({label: storyLang.create, url: $.createLink('story', 'create', 'productID=' + productID, '', true), className: 'iframe'}); - if(priv.canBatchCreateStory) items.push({label: executionLang.batchCreateStroy, url: $.createLink('story', 'batchcreate', 'productID=' + productID + '&branch=0&moduleID=0&storyID=0&executionID=' + executionID, '', true), className: 'iframe', attrs: {'data-width': '90%'}}); - if(priv.canLinkStory) items.push({label: executionLang.linkStory, url: $.createLink('execution', 'linkStory', 'executionID=' + executionID, '', true), className: 'iframe', attrs: {'data-width': '90%'}}); - if(priv.canLinkStoryByPlane) items.push({label: executionLang.linkStoryByPlan, url: '#linkStoryByPlan', 'attrs' : {'data-toggle': 'modal'}}); - } - else if(col.laneType == 'bug') - { - if(priv.canCreateBug) items.push({label: bugLang.create, url: $.createLink('bug', 'create', 'productID=0&moduleID=0&extra=executionID=' + executionID, '', true), className: 'iframe'}); - if(priv.canBatchCreateBug) items.push({label: bugLang.batchCreate, url: $.createLink('bug', 'batchcreate', 'productID=' + productID + '&moduleID=0&executionID=' + executionID, '', true), className: 'iframe'}); - } - else - { - if(priv.canCreateTask) items.push({label: taskLang.create, url: $.createLink('task', 'create', 'executionID=' + executionID, '', true), className: 'iframe'}); - if(priv.canBatchCreateTask) items.push({label: taskLang.batchCreate, url: $.createLink('task', 'batchcreate', 'executionID=' + executionID, '', true), className: 'iframe'}); - } - return items; -} - -/** - * Create lane menu - * @returns {Object[]} - */ -function createLaneMenu(options) -{ - var $lane = options.$trigger.closest('.kanban-lane'); - var $kanban = $lane.closest('.kanban'); - var lane = $lane.data('lane'); - var kanbanID = options.kanban; - var upTargetKanban = $kanban.prev('.kanban').length ? $kanban.prev('.kanban').data('id') : ''; - var downTargetKanban = $kanban.next('.kanban').length ? $kanban.next('.kanban').data('id') : ''; - - var items = []; - if(priv.canSetLane) items.push({label: kanbanLang.setLane, icon: 'edit', url: $.createLink('kanban', 'setLane', 'lane=' + lane.laneID + '&executionID=' + executionID + '&from=execution'), className: 'iframe'}); - if(priv.canMoveLane) items.push( - {label: kanbanLang.moveUp, icon: 'arrow-up', url: $.createLink('kanban', 'laneMove', 'executionID=' + executionID + '¤tLane=' + lane.id + '&targetLane=' + upTargetKanban), className: 'iframe', disabled: !$kanban.prev('.kanban').length}, - {label: kanbanLang.moveDown, icon: 'arrow-down', url: $.createLink('kanban', 'laneMove', 'executionID=' + executionID + '¤tLane=' + lane.id + '&targetLane=' + downTargetKanban), className: 'iframe', disabled: !$kanban.next('.kanban').length} - ); - - var bounds = options.$trigger[0].getBoundingClientRect(); - items.$options = {x: bounds.right, y: bounds.top}; - return items; -} - -/** - * Create story menu - * @returns {Object[]} - */ -function createStoryMenu(options) -{ - var $card = options.$trigger.closest('.kanban-item'); - var story = $card.data('item'); - - var items = []; - $.each(story.menus, function() - { - var item = {label: this.label, icon: this.icon, url: this.url, attrs: {'data-toggle': 'modal', 'data-type': 'iframe'}}; - if(this.size) item.attrs['data-width'] = this.size; - - if(this.icon == 'unlink') item = {label: this.label, icon: this.icon, url: this.url, attrs: {'target': 'hiddenwin'}}; - items.push(item); - }); - - return items; -} - -/** - * Create bug menu - * @returns {Object[]} - */ -function createBugMenu(options) -{ - var $card = options.$trigger.closest('.kanban-item'); - var bug = $card.data('item'); - - var items = []; - $.each(bug.menus, function() - { - var item = {label: this.label, icon: this.icon, url: this.url, attrs: {'data-toggle': 'modal', 'data-type': 'iframe'}}; - if(this.size) item.attrs['data-width'] = this.size; - - items.push(item); - }); - - return items; -} - - /** - * Create task menu - * @returns {Object[]} - */ -function createTaskMenu(options) -{ - var $card = options.$trigger.closest('.kanban-item'); - var task = $card.data('item'); - - var items = []; - $.each(task.menus, function() - { - var item = {label: this.label, icon: this.icon, url: this.url, attrs: {'data-toggle': 'modal', 'data-type': 'iframe'}}; - if(this.size) item.attrs['data-width'] = this.size; - - items.push(item); - }); - - return items; -} - -/** Resize kanban container size */ -function resizeKanbanContainer() -{ - var $container = $('#kanbanContainer'); - var maxHeight = window.innerHeight - 98 - 15; - if($.cookie('isFullScreen') == 1) maxHeight = window.innerHeight - 15; - $container.children('.panel-body').css('max-height', maxHeight); -} - -/* Define menu creators */ -window.menuCreators = -{ - column: createColumnMenu, - columnCreate: createColumnCreateMenu, - lane: createLaneMenu, - story: createStoryMenu, - bug: createBugMenu, - task: createTaskMenu, -}; - -/* Set kanban affix container */ -window.kanbanAffixContainer = '#kanbanContainer>.panel-body'; - -/* Overload kanban default options */ -$.extend($.fn.kanban.Constructor.DEFAULTS, -{ - onRender: function() - { - var maxWidth = 0; - $('#kanbans .kanban-board').each(function() - { - maxWidth = Math.max(maxWidth, $(this).outerWidth()); - }); - $('#kanbans').css('min-width', maxWidth); - } -}); - -/** Get card height */ -function getCardHeight() -{ - return [59, 59, 62, 62, 47][window.kanbanScaleSize]; -} /** Change kanban scale size */ function changeKanbanScaleSize(newScaleSize) @@ -904,143 +21,6 @@ function changeKanbanScaleSize(newScaleSize) return newScaleSize; } -/* Example code: */ -$(function() -{ - $.cookie('isFullScreen', 0); - - window.kanbanScaleSize = +$.zui.store.get('executionKanbanScaleSize', 1); - $('#kanbanScaleSize').text(window.kanbanScaleSize); - $('#kanbanScaleControl .btn[data-type="+"]').attr('disabled', window.kanbanScaleSize >= 4 ? 'disabled' : null); - $('#kanbanScaleControl .btn[data-type="-"]').attr('disabled', window.kanbanScaleSize <= 1 ? 'disabled' : null); - - /* Common options */  - var commonOptions = - { - maxColHeight: 'auto', - minColWidth: 240, - maxColWidth: 240, - cardHeight: getCardHeight(), - showCount: true, - showZeroCount: true, - fluidBoardWidth: false, - cardsPerRow: window.kanbanScaleSize, - virtualize: true, - virtualRenderOptions: {container: '#kanbanContainer>.panel-body'}, - droppable: - { - target: findDropColumns, - finish: handleFinishDrop, - mouseButton: 'left' - }, - onRenderHeaderCol: renderHeaderCol, - onRenderLaneName: renderLaneName, - onRenderCount: renderColumnCount - }; - - /* Create kanban */ - if(groupBy == 'default') - { - var kanbanLane = ''; - for(var i in kanbanList) - { - if(kanbanList[i] == 'story') kanbanLane = kanbanGroup.story; - if(kanbanList[i] == 'bug') kanbanLane = kanbanGroup.bug; - if(kanbanList[i] == 'task') kanbanLane = kanbanGroup.task; - - if(browseType == kanbanList[i] || browseType == 'all') createKanban(kanbanList[i], kanbanLane, commonOptions); - } - } - else - { - /* Create kanban by group. */ - createKanban(browseType, kanbanGroup[groupBy], commonOptions); - } - - /* Init iframe modals */ - $(document).on('click', '#kanbans .iframe,.contextmenu-menu .iframe', function(event) - { - var $link = $(this); - if($link.data('zui.modaltrigger')) return; - $link.modalTrigger({show: true}); - event.preventDefault(); - }); - - /* Init contextmenu */ - $('#kanbans').on('click', '[data-contextmenu]', function(event) - { - var $trigger = $(this); - var menuType = $trigger.data('contextmenu'); - - var menuCreator = window.menuCreators[menuType]; - if(!menuCreator) return; - - var options = $.extend({event: event, $trigger: $trigger}, $trigger.data()); - var items = menuCreator(options); - if(!items || !items.length) return; - - $.zui.ContextMenu.show(items, items.$options || {event: event}); - }); - - /* Make kanbanScaleControl works */ - $('#kanbanScaleControl').on('click', '.btn', function() - { - changeKanbanScaleSize(window.kanbanScaleSize + ($(this).data('type') === '+' ? 1 : -1)); - }); - - /* Resize kanban container on window resize */ - resizeKanbanContainer(); - $(window).on('resize', resizeKanbanContainer); - - /* Hide contextmenu when page scroll */ - $(window).on('scroll', function() - { - $.zui.ContextMenu.hide(); - }); - - $('#toStoryButton').on('click', function() - { - var planID = $('#plan').val(); - if(planID) - { - location.href = createLink('execution', 'importPlanStories', 'executionID=' + executionID + '&planID=' + planID + '&productID=0&fromMethod=kanban'); - } - }); - - $('#type_chosen .chosen-single span').prepend(''); - $('#group_chosen .chosen-single span').prepend(kanbanLang.laneGroup + ': '); - - /* Ajax update kanban. */ - var lastUpdateData; - setInterval(function() - { - $.get(createLink('execution', 'ajaxUpdateKanban', "executionID=" + executionID + "&entertime=" + entertime + "&browseType=" + browseType + "&groupBy=" + groupBy), function(data) - { - if(data && lastUpdateData !== data) - { - lastUpdateData = data; - kanbanGroup = $.parseJSON(data); - if(groupBy == 'default') - { - var kanbanLane = ''; - for(var i in kanbanList) - { - if(kanbanList[i] == 'story') kanbanLane = kanbanGroup.story; - if(kanbanList[i] == 'bug') kanbanLane = kanbanGroup.bug; - if(kanbanList[i] == 'task') kanbanLane = kanbanGroup.task; - - if(browseType == kanbanList[i] || browseType == 'all') updateKanban(kanbanList[i], kanbanLane); - } - } - else - { - updateKanban(browseType, kanbanGroup[groupBy]); - } - } - }); - }, 10000); -}); - $('#type').change(function() { var type = $('#type').val(); @@ -1055,16 +35,672 @@ $('#type').change(function() }) } - var link = createLink('execution', 'kanban', "executionID=" + executionID + '&type=' + type); + var link = createLink('execution', 'kanban', "executionID=" + executionID + '&browseType=' + type); location.href = link; }); -$('.c-group').change(function() +/** + * Create lane menu. + * + * @param object $options + * @access public + * @return void + */ +function createLaneMenu(options) { - $('.c-group').show(); + var lane = options.$trigger.closest('.kanban-lane').data('lane'); + var privs = lane.actions; + if(!privs.length) return []; - var type = $('#type').val(); - var group = $('#group').val(); - var link = createLink('execution', 'kanban', 'executionID=' + executionID + '&type=' + type + '&orderBy=order_asc' + '&groupBy=' + group); - location.href = link; + var items = []; + if(privs.includes('setLane')) items.push({label: kanbanLang.setLane, icon: 'edit', url: createLink('kanban', 'setLane', 'laneID=' + lane.id + '&executionID=0&from=kanban'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '635px'}}); + if(privs.includes('deleteLane')) items.push({label: kanbanLang.deleteLane, icon: 'trash', url: createLink('kanban', 'deleteLane', 'lane=' + lane.id), attrs: {'target': 'hiddenwin'}}); + + var bounds = options.$trigger[0].getBoundingClientRect(); + items.$options = {x: bounds.right, y: bounds.top}; + return items; +} + +/** + * Create card menu. + * + * @param object $options + * @access public + * @return array + */ +function createCardMenu(options) +{ + var card = options.$trigger.closest('.kanban-item').data('item'); + var privs = card.actions; + if(!privs.length) return []; + + var items = []; + if(privs.includes('editCard')) items.push({label: kanbanLang.editCard, icon: 'edit', url: createLink('kanban', 'editCard', 'cardID=' + card.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}}); + if(privs.includes('archiveCard') && kanban.archived == '1') items.push({label: kanbanLang.archiveCard, icon: 'card-archive', url: createLink('kanban', 'archiveCard', 'cardID=' + card.id), attrs: {'target': 'hiddenwin'}}); + if(privs.includes('copyCard')) items.push({label: kanbanLang.copyCard, icon: 'copy', url: createLink('kanban', 'copyCard', 'cardID=' + card.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal'}}); + if(privs.includes('deleteCard')) items.push({label: kanbanLang.deleteCard, icon: 'trash', url: createLink('kanban', 'deleteCard', 'cardID=' + card.id), attrs: {'target': 'hiddenwin'}}); + if(privs.includes('moveCard')) + { + var moveCardItems = []; + var moveColumns = []; + var parentColumns = []; + var regionGroups = regions[options.$trigger.closest('.region').data('id')].groups; + for(let i = 0; i < regionGroups.length ; i ++ ) + { + if(regionGroups[i].id == options.$trigger.closest('.kanban-board').data('id')) + { + moveColumns = regionGroups[i].columns; + break; + } + } + for(let i = moveColumns.length-1 ; i >= 0 ; i -- ) + { + if(moveColumns[i].parent > 0) parentColumns.push(moveColumns[i].parent); + if(moveColumns[i].id == card.column || $.inArray(moveColumns[i].id, parentColumns) >= 0) continue; + moveCardItems.push({label: moveColumns[i].name, onClick: function(){moveCard(card.id, moveColumns[i].id, card.lane, card.kanban, card.region);}}); + } + moveCardItems = moveCardItems.reverse(); + items.push({label: kanbanLang.moveCard, icon: 'move', items: moveCardItems}); + } + if(privs.includes('setCardColor')) + { + var cardColoritems = []; + if(!card.color) color = "#fff"; + for(let i = 0 ; i < colorList.length ; i ++ ) + { + var attr = card.color == colorList[i] ? '' : ''; + var border = i == 0 ? 'border:1px solid #b0b0b0;' : ''; + cardColoritems.push({label: "
" + colorListLang[colorList[i]] + attr , + onClick: function(){setCardColor(card.id, colorList[i], card.kanban, card.region);}, html: true, attrs: {id: 'cardcolormenu'}, className: 'color' + i}); + }; + items.push({label: kanbanLang.cardColor, icon: 'color', items: cardColoritems}); + } + + var bounds = options.$trigger[0].getBoundingClientRect(); + items.$options = {x: bounds.right, y: bounds.top}; + return items; +} + +function createColumnMenu(options) +{ + var column = options.$trigger.closest('.kanban-col').data('col'); + var privs = column.actions; + if(!privs.length) return []; + + var items = []; + if(privs.includes('setColumn')) items.push({label: kanbanLang.editColumn, icon: 'edit', url: createLink('kanban', 'setColumn', 'columnID=' + column.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal'}}); + if(privs.includes('setWIP')) items.push({label: kanbanLang.setWIP, icon: 'alert', url: createLink('kanban', 'setWIP', 'columnID=' + column.id), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width' : '500px'}}); + if(privs.includes('splitColumn')) items.push({label: kanbanLang.splitColumn, icon: 'col-split', url: createLink('kanban', 'splitColumn', 'columnID=' + column.id, '', true), className: 'iframe', attrs: {'data-toggle': 'modal'}}); + if(privs.includes('createColumn')) + { + items.push({label: kanbanLang.createColumnOnLeft, icon: 'col-add-left', url: createLink('kanban', 'createColumn', 'columnID=' + column.id + '&position=left'), className: 'iframe', attrs: {'data-toggle': 'modal'}}); + items.push({label: kanbanLang.createColumnOnRight, icon: 'col-add-right', url: createLink('kanban', 'createColumn', 'columnID=' + column.id + '&position=right'), className: 'iframe', attrs: {'data-toggle': 'modal'}}); + } + if(privs.includes('copyColumn')) items.push({label: kanbanLang.copyColumn, icon: 'copy', url: createLink('kanban', 'copyColumn', 'columnID=' + column.id), className: 'iframe', attrs: {'data-toggle': 'modal'}}); + if(privs.includes('archiveColumn') && kanban.archived == '1' && column.$kanbanData.columns.length > 1) items.push({label: kanbanLang.archiveColumn, icon: 'card-archive', url: createLink('kanban', 'archiveColumn', 'columnID=' + column.id), attrs: {'target': 'hiddenwin'}}); + if(privs.includes('deleteColumn') && column.$kanbanData.columns.length > 1) items.push({label: kanbanLang.deleteColumn, icon: 'trash', url: createLink('kanban', 'deleteColumn', 'columnID=' + column.id), attrs: {'target': 'hiddenwin'}}); + + var bounds = options.$trigger[0].getBoundingClientRect(); + items.$options = {x: bounds.right, y: bounds.top}; + return items; +} + + +/** + * Hide kanban action + */ +function hideKanbanAction() +{ + $('.kanban').attr('data-action-enabled', null); + $('.contextmenu').removeClass('contextmenu-show'); + $('.contextmenu .contextmenu-menu').removeClass('open').removeClass('in'); + $('#moreTasks, #moreColumns').animate({right: -400}, 500); +} + +/** + * Handle finish drop task + */ +function handleFinishDrop() +{ + $('.kanban').find('.can-drop-here').removeClass('can-drop-here'); +} + +/** + * Find drop columns + * @param {JQuery} $element Drag element + * @param {JQuery} $root Dnd root element + */ +function findDropColumns($element, $root) +{ + var $task = $element; + var task = $task.data('task'); + //var status = task.status; + var $col = $task.closest('.kanban-col'); + var col = $col.data(); + var lane = $col.closest('.kanban-lane').data('lane'); + var allStatusCanChange = statusChangeMap[status]; + + hideKanbanAction(); + + return $root.find('.kanban-lane-col:not([data-type="EMPTY"],[data-type=""])').filter(function() + { + var $newCol = $(this); + var newCol = $newCol.data(); + var $newLane = $newCol.closest('.kanban-lane'); + var newLane = $newLane.data('lane'); + + $newCol.addClass('can-drop-here'); + return true; + }); +} + +/** + * Render items count of a column. + */ +function renderCount($count, count, column) +{ + /* Render WIP. */ + var limit = !column.limit || column.limit == '-1' ? '' : column.limit; + if($count.parent().find('.limit').length) + { + $count.parent().find('.limit').html(limit); + } + else + { + $count.parent().find('.count').before("("); + $count.parent().find('.count').after("/" + limit + ")"); + } + + if(column.limit != -1 && column.limit < count) + { + $count.parents('.title').parent('.kanban-header-col').css('background-color', '#F6A1A1'); + $count.parents('.title').find('.text').css('max-width', $count.parents('.title').width() - 200); + $count.css('color', '#E33030'); + if(!$count.parent().find('.error').length) $count.parent().find('.include-last').after(""); + } + else + { + $count.parents('.title').parent('.kanban-header-col').css('background-color', 'transparent'); + $count.parents('.title').find('.text').css('max-width', $count.parents('.title').width() - 120); + $count.css('color', '#8B91A2'); + $count.parent().find('.error').remove(); + } +} + +/** + * Render header of a column. + */ +function renderHeaderCol($column, column, $header, kanbanData) +{ + /* Render group header. */ + var privs = kanbanData.actions; + var columnPrivs = kanbanData.columns[0].actions; + + if(privs.includes('sortGroup')) + { + var groups = regions[column.region].groups; + if($header.closest('.kanban').data('zui.kanban')) + { + groups = $header.closest('.kanban').data('zui.kanban').data; + } + if(groups.length > 1) + { + $column.closest('.kanban-board').addClass('sort'); + $column.closest('.kanban-header').find('.kanban-group-header').remove(); + $column.closest('.kanban-header').prepend('
'); + } + } + + var regionID = $column.closest('.kanban').data('id'); + var groupID = $column.closest('.kanban-board').data('id'); + var laneID = column.$kanbanData.lanes[0].id ? column.$kanbanData.lanes[0].id : 0; + var columnID = $column.closest('.kanban-col').data('id'); + var printMoreBtn = (columnPrivs.includes('setColumn') || columnPrivs.includes('setWIP') || columnPrivs.includes('createColumn') || columnPrivs.includes('copyColumn') || columnPrivs.includes('archiveColumn') || columnPrivs.includes('deleteColumn') || columnPrivs.includes('splitColumn')); + + /* Render more menu. */ + if(columnPrivs.includes('createCard') || printMoreBtn) + { + var addItemBtn = ''; + var moreAction = ''; + + if(!$column.children('.actions').length) $column.append('
'); + var $actions = $column.children('.actions'); + + if(columnPrivs.includes('createCard') && column.parent != -1) + { + var cardUrl = createLink('kanban', 'createCard', 'kanbanID=' + kanbanID + '®ionID=' + regionID + '&groupID=' + groupID + '&laneID=' + laneID + '&columnID=' + columnID); + addItemBtn = ['', '', ''].join(''); + } + + var moreAction = ' '; + $actions.html(addItemBtn + moreAction); + } +} + +/** + * Render lane name. + * + * @param object $lane + * @param int lane + * @param object $kanban + * @param array columns + * @param object $kanban + * @access public + * @return void + */ +function renderLaneName($lane, lane, $kanban, columns, kanban) +{ + var canSet = lane.actions.includes('setLane'); + var canSort = lane.actions.includes('sortLane') && kanban.lanes.length > 1; + var canDelete = lane.actions.includes('deleteLane'); + + $lane.parent().toggleClass('sort', canSort); + + if(!$lane.children('.actions').length && (canSet || canDelete)) + { + $([ + '
', + '', + '', + '', + '
' + ].join('')).appendTo($lane); + } +} +/** + * Adjust add button postion in column + */ +function adjustAddBtnPosition($kanban) +{ + if(!$kanban) + { + $('.kanban').children('.kanban-board').each(function() + { + adjustAddBtnPosition($(this)); + }); + return; + } + + $kanban.find('.kanban-lane-col:not([data-type="EMPTY"])').each(function() + { + var $col = $(this); + var items = $col.children('.kanban-lane-items')[0]; + $col.toggleClass('has-scrollbar', items.scrollHeight > items.clientHeight); + }); +} +/** + * Handle kanban action + */ +function handleKanbanAction(action, $element, event, kanban) +{ + $('.kanban').attr('data-action-enabled', action); + var handler = kanbanActionHandlers[action]; + if(handler) handler($element, event, kanban); +} + +function processMinusBtn() +{ + var columnCount = $('#splitTable .child-column').size(); + if(columnCount > 2 && columnCount < 10) + { + $('#splitTable .btn-plus').show(); + $('#splitTable .btn-close').show(); + } + else if(columnCount <= 2) + { + $('#splitTable .btn-close').hide(); + } + else if(columnCount >= 10) + { + $('#splitTable .btn-plus').hide(); + } +} +/** + * The function for rendering kanban item + */ +function renderKanbanItem(item, $item) +{ + var $title = $item.children('.title'); + var privs = item.actions; + var printMoreBtn = (privs.includes('editCard') || privs.includes('archiveCard') || privs.includes('copyCard') || privs.includes('deleteCard') || privs.includes('moveCard') || privs.includes('setCardColor')); + if(!$title.length) + { + if(privs.includes('viewCard')) $title = $('').appendTo($item).attr('href', createLink('kanban', 'viewCard', 'cardID=' + item.id, '', true)); + if(!privs.includes('viewCard')) $title = $('

').appendTo($item); + } + + $title.text(item.name).attr('title', item.name); + + if(printMoreBtn) + { + $( + [ + '
', + '', + '', + '', + '
' + ].join('')).appendTo($item); + } + + var $info = $item.children('.info'); + if(!$info.length) $info = $( + [ + '
', + '', + '', + '', + '
', + '
' + ].join('')).appendTo($item); + + $item.data('card', item); + + $info.children('.estimate').text(item.estimate + kanbancardLang.lblHour); + if(item.estimate == 0) $info.children('.estimate').hide(); + + $info.children('.pri') + .attr('class', 'pri label-pri label-pri-' + item.pri) + .text(item.pri); + + $item.css('background-color', item.color); + $item.toggleClass('has-color', item.color != '#fff' && item.color != ''); + $item.find('.info > .label-light').css('background-color', item.color); + + var $time = $info.children('.time'); + if(item.end == '0000-00-00' && item.begin == '0000-00-00') + { + $time.hide(); + } + else + { + var today = new Date(); + var begin = $.zui.createDate(item.begin); + var end = $.zui.createDate(item.end); + var needRemind = (begin.toLocaleDateString() == today.toLocaleDateString() || end.toLocaleDateString() == today.toLocaleDateString()); + if(item.end == '0000-00-00' && item.begin != '0000-00-00') + { + $time.text($.zui.formatDate(begin, 'MM/dd') + ' ' + kanbancardLang.beginAB).attr('title', $.zui.formatDate(begin, 'yyyy/MM/dd') + ' ' +kanbancardLang.beginAB).show(); + } + else if(item.begin == '0000-00-00' && item.end != '0000-00-00') + { + $time.text($.zui.formatDate(end, 'MM/dd') + ' ' + kanbancardLang.deadlineAB).attr('title', $.zui.formatDate(end, 'yyyy/MM/dd') + ' ' + kanbancardLang.deadlineAB).show(); + } + else if(item.begin != '0000-00-00' && item.end != '0000-00-00') + { + $time.text($.zui.formatDate(begin, 'MM/dd') + ' ' + kanbancardLang.to + ' ' + $.zui.formatDate(end, 'MM/dd')).attr('title', $.zui.formatDate(begin, 'yyyy/MM/dd') + kanbancardLang.to + $.zui.formatDate(end, 'yyyy/MM/dd')).show(); + } + + if(!$item.hasClass('has-color') && needRemind) $time.css('background-color', 'rgba(210, 50, 61, 0.3)'); + if($item.hasClass('has-color') && needRemind) $time.css('background-color', 'rgba(255, 255, 255, 0.3)'); + if(!needRemind) $time.css('background-color', 'rgba(0, 0, 0, 0.15)'); + } + + /* Display avatars of assignedTo. */ + var assignedTo = item.assignedTo.split(','); + var $user = $info.children('.user'); + var title = []; + for(i = 0; i < assignedTo.length; i++) title.push(users[assignedTo[i]]); + $user.html(renderUsersAvatar(assignedTo, item.id)).attr('title', title); +} +/* Define menu creators */ +window.menuCreators = +{ + card: createCardMenu, + lane: createLaneMenu, + column: createColumnMenu +}; + +/** + * init Kanban + */ +function initKanban($kanban) +{ + var id = $kanban.data('id'); + var region = regions[id]; + + $kanban.kanban( + { + data: region.groups, + maxColHeight: 510, + fluidBoardWidth: false, + minColWidth: 300, + maxColWidth: 300, + createColumnText: kanbanLang.createColumn, + addItemText: '', + itemRender: renderKanbanItem, + onAction: handleKanbanAction, + onRenderKanban: adjustAddBtnPosition, + onRenderLaneName: renderLaneName, + onRenderHeaderCol: renderHeaderCol, + onRenderCount: renderCount, + droppable: + { + target: findDropColumns, + finish: handleFinishDrop, + mouseButton: 'left' + } + }); + + $kanban.on('click', '.action-cancel', hideKanbanAction); + $kanban.on('scroll', function() + { + $.zui.ContextMenu.hide(); + }); +} + +/** + * Init when page ready + */ +$(function() +{ + if($.cookie('isFullScreen') == 1) fullScreen(); + + window.kanbanScaleSize = +$.zui.store.get('executionKanbanScaleSize', 1); + $('#kanbanScaleSize').text(window.kanbanScaleSize); + $('#kanbanScaleControl .btn[data-type="+"]').attr('disabled', window.kanbanScaleSize >= 4 ? 'disabled' : null); + $('#kanbanScaleControl .btn[data-type="-"]').attr('disabled', window.kanbanScaleSize <= 1 ? 'disabled' : null); + + /* Make kanbanScaleControl works */ + $('#kanbanScaleControl').on('click', '.btn', function() + { + changeKanbanScaleSize(window.kanbanScaleSize + ($(this).data('type') === '+' ? 1 : -1)); + }); + + /* Init first kanban */ + $('.kanban').each(function() + { + initKanban($(this)); + }); + + $('.icon-chevron-double-up,.icon-chevron-double-down').on('click', function() + { + $(this).toggleClass('icon-chevron-double-up icon-chevron-double-down'); + $(this).parents('.region').find('.kanban').toggle(); + hideKanbanAction(); + }); + + $('.region-header').on('click', '.action', hideKanbanAction); + $('#TRAction').on('click', '.btn', hideKanbanAction); + + /* Hide action box when user click document */ + $(document).on('click', function(e) + { + $('.kanban').each(function() + { + var currentAction = $(this).kanban().attr('data-action-enabled'); + var canHideAction = (currentAction === 'headerMore' || currentAction === 'editLaneName') + && !$(e.target).closest('.action,.action-box').length; + if(canHideAction) hideKanbanAction(); + }); + }); + + /* Init contextmenu */ + $('#kanban').on('click', '[data-contextmenu]', function(event) + { + var $trigger = $(this); + var menuType = $trigger.data('contextmenu'); + var menuCreator = window.menuCreators[menuType]; + if(!menuCreator) return; + + var options = $.extend({event: event, $trigger: $trigger}, $trigger.data()); + var items = menuCreator(options); + if(!items || !items.length) return; + + $.zui.ContextMenu.show(items, items.$options || {event: event}); + }); + + /* Adjust the add button position on window resize */ + $(window).on('resize', function(a) + { + adjustAddBtnPosition(); + }); + + + /* Hide contextmenu when page scroll */ + $(window).on('scroll', function() + { + $.zui.ContextMenu.hide(); + }); + + $(document).on('click', '#splitTable .btn-plus', function() + { + var tr = $(this).closest('tr'); + tr.after($('#childTpl').html().replace(/key/g, key)); + tr.next().find('input[name^=color]').colorPicker(); + key++; + processMinusBtn(); + return false; + }); + + /* Remove a trade detail item. */ + $(document).on('click', '#splitTable .btn-close', function() + { + $(this).closest('tr').remove(); + processMinusBtn(); + return false; + }); + + /* Mofidy dafault color's border color. */ + $(document).on('mouseout', '.color0', function() + { + $('.color0 .cardcolor').css('border', '1px solid #b0b0b0'); + }); + + /* Mofidy dafault color's border color. */ + $(document).on('mouseover', '.color0', function() + { + $('.color0 .cardcolor').css('border', '1px solid #fff'); + }); + + /* Init sortable */ + var sortType = ''; + var $cards = null; + $('#kanban').sortable( + { + selector: '.region, .kanban-board, .kanban-lane', + trigger: '.region.sort > .region-header, .kanban-board.sort > .kanban-header > .kanban-group-header, .kanban-lane.sort > .kanban-lane-name', + container: function($ele) + { + return $ele.parent(); + }, + targetSelector: function($ele) + { + /* Sort regions */ + if($ele.hasClass('region')) + { + sortType = 'region'; + return $ele.parent().children('.region'); + } + + /* Sort boards */ + if($ele.hasClass('kanban-board')) + { + sortType = 'board'; + return $ele.parent().children('.kanban-board'); + } + + /* Sort lanes */ + if($ele.hasClass('kanban-lane')) + { + sortType = 'lane'; + $cards = $ele.find('.kanban-item'); + + return $ele.parent().children('.kanban-lane'); + } + + /* Sort lanes */ + if($ele.hasClass('kanban-item')) + { + sortType = 'item'; + return $ele.parent().children('.kanban-item'); + } + }, + start: function(e) + { + if(sortType == 'region') + { + showRegionIdList = ''; + $('.icon-chevron-double-up').each(function() + { + showRegionIdList += $(this).attr('data-id') + ','; + $(this).attr('class', 'icon-chevron-double-down'); + }); + + $('.region').find('.kanban').hide(); + hideKanbanAction(); + } + }, + finish: function(e) + { + var url = ''; + var orders = []; + e.list.each(function(index, data) + { + orders.push(data.item.data('id')); + }); + + if(sortType == 'region') + { + $('.region').each(function() + { + if(showRegionIdList.includes($(this).attr('data-id'))) + { + $(this).find('.icon-chevron-double-down').attr('class', 'icon-chevron-double-up'); + $(this).find('.kanban').show(); + } + }) + + url = createLink('kanban', 'sortRegion', 'regions=' + orders.join(',')); + } + if(sortType == 'board') + { + var region = e.element.parent().data('id'); + url = createLink('kanban', 'sortGroup', 'region=' + region + '&groups=' + orders.join(',')); + } + if(sortType == 'lane') + { + var region = e.element.parent().parent().data('id'); + url = createLink('kanban', 'sortLane', 'region=' + region + '&lanes=' + orders.join(',')); + } + if(sortType == 'item') + { + url = createLink('task', 'sort', 'kanbanID=' + kanbanID + '&tasks=' + orders.join(',')); + } + if(!url) return true; + + $.getJSON(url, function(response) + { + if(response.result == 'fail' && response.message.length) + { + bootbox.alert(response.message); + setTimeout(function(){return location.reload()}, 3000); + } + }); + }, + always: function(e) + { + if(sortType == 'lane') $cards.show(); + } + }); }); diff --git a/module/execution/js/taskkanban.js b/module/execution/js/taskkanban.js index daf1724e18..76842aa51b 100644 --- a/module/execution/js/taskkanban.js +++ b/module/execution/js/taskkanban.js @@ -1,6 +1,6 @@ function changeView(view) { - var link = createLink('execution', 'kanban', "executionID=" + executionID + '&type=' + view); + var link = createLink('execution', 'taskKanban', "executionID=" + executionID + '&type=' + view); location.href = link; } @@ -597,7 +597,7 @@ function changeCardColType(card, fromColType, toColType, kanbanID) } else if(toColType == 'fixed') { - if(fromColType == 'fixing' || fromColType == 'confirmed' || fromColType == 'unconfirmed') + if(fromColType == 'fixing' || fromColType == 'confirmed' || fromColType == 'unconfirmed') { var link = createLink('bug', 'resolve', 'bugID=' + objectID, '', true); showIframe = true; @@ -1055,7 +1055,7 @@ $('#type').change(function() }) } - var link = createLink('execution', 'kanban', "executionID=" + executionID + '&type=' + type); + var link = createLink('execution', 'taskKanban', "executionID=" + executionID + '&type=' + type); location.href = link; }); @@ -1065,6 +1065,6 @@ $('.c-group').change(function() var type = $('#type').val(); var group = $('#group').val(); - var link = createLink('execution', 'kanban', 'executionID=' + executionID + '&type=' + type + '&orderBy=order_asc' + '&groupBy=' + group); + var link = createLink('execution', 'taskKanban', 'executionID=' + executionID + '&type=' + type + '&orderBy=order_asc' + '&groupBy=' + group); location.href = link; }); diff --git a/module/execution/model.php b/module/execution/model.php index 81a958accc..e897bac7eb 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -2480,7 +2480,7 @@ class executionModel extends model /** * Get members by execution id list. - * + * * @param array $executionIdList * @access public * @return void diff --git a/module/execution/view/kanban.html.php b/module/execution/view/kanban.html.php index 28fb732228..2ecc5dc6dd 100644 --- a/module/execution/view/kanban.html.php +++ b/module/execution/view/kanban.html.php @@ -1,15 +1,42 @@ * @package execution - * @version $Id: kanban.html.php $ + * @version $Id: kanban.html.php 935 2022-01-11 16:49:24Z $ + * @link https://www.zentao.net */ ?> + +laneCount; + +js::set('regions', $regions); +js::set('execution', $execution); +js::set('kanbanLang', $lang->kanban); +js::set('kanbanlaneLang', $lang->kanbanlane); +js::set('kanbancolumnLang', $lang->kanbancolumn); +js::set('kanbancardLang', $lang->kanbancard); +js::set('executionID', $execution->id); +js::set('laneCount', $laneCount); +js::set('userList', $userList); +js::set('noAssigned', $lang->kanbancard->noAssigned); +js::set('users', $users); +js::set('colorListLang', $lang->kanbancard->colorList); +js::set('colorList', $this->config->kanban->cardColorList); + +$canSortRegion = commonModel::hasPriv('kanban', 'sortRegion') && count($regions) > 1; +$canEditRegion = commonModel::hasPriv('kanban', 'editRegion'); +$canDeleteRegion = commonModel::hasPriv('kanban', 'deleteRegion'); +$canCreateLane = commonModel::hasPriv('kanban', 'createLane'); +?> + -
-
-
-
- -
- + - model != 'kanban'):?> + type != 'kanban'):?>
kanban->laneHeight;?>kanbanlane->heightTypeList, 'custom', "onclick='setCardCount(this.value);'"));?>kanbanlane->heightTypeList, $heightType, "onclick='setCardCount(this.value);'"));?>
diff --git a/module/project/control.php b/module/project/control.php index 2851aa5228..36288c0ac5 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -586,8 +586,7 @@ class project extends control } } - $canChangeModel = $this->project->checkCanChangeModel($projectID, $project->model); - $disableModel = $canChangeModel == true ? '' : 'disabled'; + if($project->model != 'kanban') $canChangeModel = $this->project->checkCanChangeModel($projectID, $project->model); $this->view->title = $this->lang->project->edit; $this->view->position[] = $this->lang->project->edit; @@ -614,7 +613,7 @@ class project extends control $this->view->availableBudget = $this->program->getBudgetLeft($parentProject) + (float)$project->budget; $this->view->budgetUnitList = $this->project->getBudgetUnitList(); $this->view->model = $project->model; - $this->view->disableModel = $disableModel; + $this->view->disableModel = (isset($canChangeModel) and $canChangeModel == true) ? '' : 'disabled'; $this->display(); } diff --git a/module/project/view/edit.html.php b/module/project/view/edit.html.php index e8f430a273..2909dd3673 100644 --- a/module/project/view/edit.html.php +++ b/module/project/view/edit.html.php @@ -34,10 +34,12 @@
+ model != 'kanban'):?> + Date: Wed, 12 Jan 2022 11:07:02 +0800 Subject: [PATCH 17/85] * Working with Kanban Data. --- module/execution/config.php | 1 + module/execution/control.php | 9 ++++----- module/execution/model.php | 8 ++++---- module/execution/view/ajaxgetdropmenu.html.php | 5 +++++ module/project/model.php | 2 +- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/module/execution/config.php b/module/execution/config.php index ec4ef74386..3de6ff2291 100644 --- a/module/execution/config.php +++ b/module/execution/config.php @@ -11,6 +11,7 @@ $config->execution->list->exportFields = 'id,name,projectName,code,PM,end,status $config->execution->modelList['scrum'] = 'sprint'; $config->execution->modelList['waterfall'] = 'stage'; +$config->execution->modelList['kanban'] = 'kanban'; global $lang, $app; $app->loadLang('task'); diff --git a/module/execution/control.php b/module/execution/control.php index f934284e97..0e874bebae 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1967,13 +1967,12 @@ class execution extends control */ public function kanban($executionID, $browseType = 'all', $orderBy = 'id_asc', $groupBy = 'all') { - unset($this->lang->execution->menu); - - $users = $this->loadModel('user')->getPairs('noletter|nodeleted'); + $this->lang->execution->menu = new stdclass(); + $execution = $this->commonAction($executionID); $kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $browseType, $orderBy, $groupBy); - $execution = $this->execution->getById($executionID); $userList = array(); + $users = $this->loadModel('user')->getPairs('noletter|nodeleted'); $avatarPairs = $this->dao->select('account, avatar')->from(TABLE_USER)->where('deleted')->eq(0)->fetchPairs(); foreach($avatarPairs as $account => $avatar) { @@ -2945,7 +2944,7 @@ class execution extends control $projects = $this->loadModel('program')->getProjectList(0, 'all', 0, 'order_asc', null, 0, 0, true); $executionGroups = $this->dao->select('*')->from(TABLE_EXECUTION) ->where('deleted')->eq(0) - ->andWhere('type')->in('sprint,stage') + ->andWhere('type')->in('sprint,stage,kanban') ->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->sprints)->fi() ->beginIF($this->config->systemMode == 'new')->andWhere('project')->in(array_keys($projects))->fi() ->orderBy('id_desc') diff --git a/module/execution/model.php b/module/execution/model.php index e897bac7eb..d2332fd56e 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -65,7 +65,7 @@ class executionModel extends model { if(!$this->app->user->admin and strpos(",{$this->app->user->view->sprints},", ",$executionID,") === false and !defined('TUTORIAL') and $executionID != 0) die(js::error($this->lang->execution->accessDenied) . js::locate('back')); - $executions = $this->loadModel('execution')->getPairs(0, 'all', 'nocode'); + $executions = $this->getPairs(0, 'all', 'nocode'); if(!$executionID and $this->session->execution) $executionID = $this->session->execution; if(!$executionID or !in_array($executionID, array_keys($executions))) $executionID = key($executions); $this->session->set('execution', $executionID); @@ -1054,7 +1054,7 @@ class executionModel extends model /* Order by status's content whether or not done */ $executions = $this->dao->select('*, IF(INSTR("done,closed", status) < 2, 0, 1) AS isDone, INSTR("doing,wait,suspended,closed", status) AS sortStatus')->from(TABLE_EXECUTION) ->where('deleted')->eq(0) - ->beginIF($type == 'all')->andWhere('type')->in('stage,sprint')->fi() + ->beginIF($type == 'all')->andWhere('type')->in('stage,sprint,kanban')->fi() ->beginIF($projectID and $this->config->systemMode == 'new')->andWhere('project')->eq($projectID)->fi() ->beginIF($type != 'all' and $this->config->systemMode == 'new')->andWhere('type')->eq($type)->fi() ->beginIF(strpos($mode, 'withdelete') === false)->andWhere('deleted')->eq(0)->fi() @@ -1319,7 +1319,7 @@ class executionModel extends model $module = 'execution'; $method = 'task'; } - if($module == 'testcase' and ($method == 'view' || $method == 'edit' || $method == 'batchedit')) + if($module == 'testcase' and ($method == 'view' or $method == 'edit' or $method == 'batchedit')) { $module = 'execution'; $method = 'testcase'; @@ -1329,7 +1329,7 @@ class executionModel extends model $module = 'execution'; $method = 'testtask'; } - if($module == 'build' and ($method == 'edit' || $method= 'view')) + if($module == 'build' and ($method == 'edit' or $method == 'view')) { $module = 'execution'; $method = 'build'; diff --git a/module/execution/view/ajaxgetdropmenu.html.php b/module/execution/view/ajaxgetdropmenu.html.php index e5ac0900c0..48f728d304 100644 --- a/module/execution/view/ajaxgetdropmenu.html.php +++ b/module/execution/view/ajaxgetdropmenu.html.php @@ -75,6 +75,11 @@ foreach($executions as $projectID => $projectExecutions) $selected = $execution->id == $executionID ? 'selected' : ''; if($execution->status != 'done' and $execution->status != 'closed' and ($execution->PM == $this->app->user->account or isset($execution->teams[$this->app->user->account]))) { + $kanbanLink = "/execution-kanban-%s.html"; + $taskLink = "/execution-task-%s.html"; + if($execution->type != 'kanban' and $link == $kanbanLink) $link = $taskLink; + if($execution->type == 'kanban' and $link != $kanbanLink) $link = $kanbanLink; + $myExecutionsHtml .= '
  • ' . html::a(sprintf($link, $execution->id), $execution->name, '', "class='$selected executionName' title='{$execution->name}' data-key='" . zget($executionsPinYin, $execution->name, '') . "' data-app='{$this->app->tab}'") . '
  • '; if($selected == 'selected') $tabActive = 'myExecution'; diff --git a/module/project/model.php b/module/project/model.php index 0895b4bfe6..60b703035a 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -1836,7 +1836,7 @@ class projectModel extends model $executions = $this->dao->select('t1.*,t2.name projectName, t2.model as projectModel')->from(TABLE_EXECUTION)->alias('t1') ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') - ->where('t1.type')->in('sprint,stage') + ->where('t1.type')->in('sprint,stage,kanban') ->beginIF($projectID != 0)->andWhere('t1.project')->eq($projectID)->fi() ->beginIF(!empty($myExecutionIDList))->andWhere('t1.id')->in(array_keys($myExecutionIDList))->fi() ->beginIF($status == 'undone')->andWhere('t1.status')->notIN('done,closed')->fi() From 7870309514558c35c8b155f6e53479ac730a76ec Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Jan 2022 11:13:16 +0800 Subject: [PATCH 18/85] * Modify create and execute jump app error. --- module/execution/control.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/execution/control.php b/module/execution/control.php index 0e874bebae..f29a2d76ac 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1397,7 +1397,7 @@ class execution extends control $this->loadModel('kanban')->createRDKanban($execution); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('kanban', "executionID=$executionID"))); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('kanban', "executionID=$executionID") . '#app=execution')); } if(!empty($planID)) From 0afb843ef5dfee45724783174970f82eabcd3874 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B9=BF=E6=98=8E?= Date: Wed, 12 Jan 2022 11:23:05 +0800 Subject: [PATCH 19/85] * Refactor kanban code. --- config/zentaopms.php | 1 + module/execution/model.php | 2 +- module/kanban/model.php | 145 +++++++++++++++++-------------------- 3 files changed, 70 insertions(+), 78 deletions(-) diff --git a/config/zentaopms.php b/config/zentaopms.php index 5d1ef5ed25..b7b187ba3a 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -245,6 +245,7 @@ define('TABLE_KANBANCOLUMN', '`' . $config->db->prefix . 'kanbancolumn`'); define('TABLE_KANBANORDER', '`' . $config->db->prefix . 'kanbanorder`'); define('TABLE_KANBANGROUP', '`' . $config->db->prefix . 'kanbangroup`'); define('TABLE_KANBANCARD', '`' . $config->db->prefix . 'kanbancard`'); +define('TABLE_KANBANCELL', '`' . $config->db->prefix . 'kanbancell`'); if(!defined('TABLE_LANG')) define('TABLE_LANG', '`' . $config->db->prefix . 'lang`'); if(!defined('TABLE_PROJECTSPEC')) define('TABLE_PROJECTSPEC', '`' . $config->db->prefix . 'projectspec`'); diff --git a/module/execution/model.php b/module/execution/model.php index e897bac7eb..53652b26b0 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -381,7 +381,7 @@ class executionModel extends model $creatorExists = false; $teamMembers = array(); - if(isset($project) and $project->model != 'kanban') $this->loadModel('kanban')->createExecutionLane($executionID); + if((isset($project) and $project->model != 'kanban') or empty($project)) $this->loadModel('kanban')->createExecutionLane($executionID); /* Save order. */ $this->dao->update(TABLE_EXECUTION)->set('`order`')->eq($executionID * 5)->where('id')->eq($executionID)->exec(); diff --git a/module/kanban/model.php b/module/kanban/model.php index a24ad1b8f9..cee72db6a3 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -313,6 +313,11 @@ class kanbanModel extends model $this->dao->update(TABLE_KANBANCOLUMN)->set('type')->eq("column{$columnID}")->where('id')->eq($columnID)->exec(); + /* Add kanban cell. */ + $lanes = $this->dao->select('id')->from(TABLE_KANBANLANE)->where('`group`')->eq($column->group)->fetchPairs(); + $kanbanID = $this->dao->select('kanban')->from(TABLE_KANBANREGION)->where('id')->eq($regionID)->fetch('kanban'); + foreach($lanes as $laneID) $this->addKanbanCell($kanbanID, $laneID, $columnID, 'card'); + return $columnID; } @@ -418,8 +423,6 @@ class kanbanModel extends model ->add('kanban', $kanbanID) ->add('region', $regionID) ->add('group', $groupID) - ->add('lane', $laneID) - ->add('column', $columnID) ->add('createdBy', $this->app->user->account) ->add('createdDate', $now) ->add('assignedDate', $now) @@ -444,6 +447,7 @@ class kanbanModel extends model $cardID = $this->dao->lastInsertID(); $this->file->saveUpload('kanbancard', $cardID); $this->file->updateObjectID($this->post->uid, $cardID, 'kanbancard'); + $this->addKanbanCell($kanbanID, $laneID, $columnID, 'card', $cardID); return $cardID; } @@ -953,19 +957,21 @@ class kanbanModel extends model if(empty($lanes)) return array(); - foreach($lanes as $lane) $this->updateCards($lane); + foreach($lanes as $lane) $this->refreshCards($lane); - $columns = $this->dao->select('*')->from(TABLE_KANBANCOLUMN) - ->where('deleted')->eq(0) - ->andWhere('lane')->in(array_keys($lanes)) + $columns = $this->dao->select('t1.cards, t1.lane, t2.id, t2.type, t2.name, t2.color, t2.limit, t2.parent')->from(TABLE_KANBANCELL)->alias('t1') + ->leftJoin(TABLE_KANBANCOLUMN)->alias('t2')->on('t1.column = t2.id') + ->where('t2.deleted')->eq(0) + ->andWhere('t1.lane')->in(array_keys($lanes)) ->orderBy('id_asc') ->fetchGroup('lane', 'id'); /* Get parent column type pairs. */ - $parentTypes = $this->dao->select('id, type')->from(TABLE_KANBANCOLUMN) - ->where('deleted')->eq(0) - ->andWhere('lane')->in(array_keys($lanes)) - ->andWhere('parent')->eq(-1) + $parentTypes = $this->dao->select('t2.id, t2.type')->from(TABLE_KANBANCELL)->alias('t1') + ->leftJoin(TABLE_KANBANCOLUMN)->alias('t2')->on('t1.column = t2.id') + ->where('t2.deleted')->eq(0) + ->andWhere('t1.lane')->in(array_keys($lanes)) + ->andWhere('t2.parent')->eq(-1) ->fetchPairs('id', 'type'); /* Get group objects. */ @@ -1554,7 +1560,6 @@ class kanbanModel extends model } } - $cards = ''; $devColumnID = $testColumnID = $resolvingColumnID = 0; if($type == 'story') { @@ -1576,15 +1581,7 @@ class kanbanModel extends model if($colType == 'develop') $devColumnID = $colID; if($colType == 'test') $testColumnID = $colID; - if(strpos(',ready,develop,test,', $colType) === false) - { - $storyStatus = $this->config->kanban->storyColumnStatusList[$colType]; - $storyStage = $this->config->kanban->storyColumnStageList[$colType]; - foreach($objects as $storyID => $story) - { - if($story->status == $storyStatus and $story->stage == $storyStage) $cards .= $storyID . ','; - } - } + if(strpos(',develop,test,', $colType) === false) $this->addKanbanCell($executionID, $laneID, $colID, 'story'); } } elseif($type == 'bug') @@ -1606,25 +1603,7 @@ class kanbanModel extends model if($colType == 'resolving') $resolvingColumnID = $colID; if($colType == 'test') $testColumnID = $colID; - if(strpos(',resolving,fixing,test,testing,tested,', $colType) === false) - { - $bugStatus = $this->config->kanban->bugColumnStatusList[$colType]; - foreach($objects as $bugID => $bug) - { - if($colType == 'unconfirmed' and $bug->status == $bugStatus and $bug->confirmed == 0) - { - $cards .= $bugID . ','; - } - elseif($colType == 'confirmed' and $bug->status == $bugStatus and $bug->confirmed == 1) - { - $cards .= $bugID . ','; - } - elseif(strpos(',unconfirmed,confirmed,', $colType) === false and $bug->status == $bugStatus) - { - $cards .= $bugID . ','; - } - } - } + if(strpos(',resolving,test,', $colType) === false) $this->addKanbanCell($executionID, $laneID, $colID, 'bug'); } } elseif($type == 'task') @@ -1643,46 +1622,48 @@ class kanbanModel extends model $colID = $this->dao->lastInsertId(); if($colType == 'develop') $devColumnID = $colID; - } - - if(strpos(',develop,', $colType) === false) - { - $taskStatus = $this->config->kanban->taskColumnStatusList[$colType]; - foreach($objects as $taskID => $task) - { - if($task->status == $taskStatus) $cards .= $taskID . ','; - } + if($colType != 'develop') $this->addKanbanCell($executionID, $laneID, $colID, 'task'); } } - - if(!empty($cards)) $this->parkCards($executionID, $laneID, $colID, $cards, $type); } /** - * Park cards into kanban cell. + * Add kanban cell for new lane. * * @param int $kanbanID * @param int $laneID * @param int $colID - * @param string $cards - * @param string $type + * @param string $type story|task|bug|card * @access public * @return void */ - public function parkCards($kanbanID, $laneID, $colID, $cards, $type) + public function addKanbanCell($kanbanID, $laneID, $colID, $type, $cardID = 0) { - $cards = ',' . $cards; + $cell = $this->dao->select('id, cards')->from(TABLE_KANBANCELL) + ->where('kanban')->eq($kanbanID) + ->andWhere('lane')->eq($laneID) + ->andWhere('`column`')->eq($colID) + ->andWhere('type')->eq($type) + ->fetch(); - $cardGroup = new stdclass(); - $cardGroup->kanban = $executionID; - $cardGroup->lane = $laneID; - $cardGroup->column = $colID; - $cardGroup->type = $type; - $cardGroup->cards = $cards; + if(empty($cell)) + { + $cell = new stdclass(); + $cell->kanban = $kanbanID; + $cell->lane = $laneID; + $cell->column = $colID; + $cell->type = $type; - $this->dao->insert(TABLE_KANBANCELL)->data($cardGroup)->exec(); + $this->dao->insert(TABLE_KANBANCELL)->data($cell)->exec(); + } + else + { + $cell->cards = $cell->cards ? $cell->cards . "$carID," : ",$carID,"; + $this->dao->update(TABLE_KANBANCELL)->set('cards')->eq($cell->cards)->where('id')->eq($cell->id)->exec(); + } } + /** * Create a default RD kanban. * @@ -1846,24 +1827,25 @@ class kanbanModel extends model ->andWhere('type')->eq($laneType) ->fetchAll('id'); - foreach($lanes as $lane) $this->updateCards($lane); + foreach($lanes as $lane) $this->refreshCards($lane); } /** - * Update column cards. + * Refresh column cards. * * @param object $lane * @access public * @return void */ - public function updateCards($lane) + public function refreshCards($lane) { $laneType = $lane->type; $executionID = $lane->execution; - $cardPairs = $this->dao->select('*')->from(TABLE_KANBANCOLUMN) - ->where('deleted')->eq(0) - ->andWhere('lane')->eq($lane->id) - ->fetchPairs('type' ,'cards'); + $cardPairs = $this->dao->select('t2.type, t1.cards')->from(TABLE_KANBANCELL)->alias('t1') + ->leftJoin(TABLE_KANBANCOLUMN)->alias('t2')->on('t1.`column` = t2.id') + ->where('t1.kanban')->eq($executionID) + ->andWhere('t1.lane')->eq($lane->id) + ->fetchPairs(); if($laneType == 'story') { @@ -1877,21 +1859,23 @@ class kanbanModel extends model $cardPairs[$colType] = str_replace(",$storyID,", ',', $cardPairs[$colType]); } - if(strpos(',ready,develop,test,', $colType) !== false) continue; + if(strpos(',ready,backlog,develop,test,', $colType) !== false) continue; if($lane->groupby and $story->{$lane->groupby} != $lane->extra) { $cardPairs[$colType] = str_replace(",$storyID,", ',', $cardPairs[$colType]); } - elseif($colType == 'backlog' and $story->stage == $stage and strpos($cardPairs['ready'], ",$storyID,") === false and strpos($cardPairs['backlog'], ",$storyID,") === false) - { - $cardPairs['backlog'] = empty($cardPairs['backlog']) ? ",$storyID," : ",$storyID" . $cardPairs['backlog']; - } - elseif($story->stage == $stage and strpos($cardPairs[$colType], ",$storyID,") === false and $colType != 'backlog') + elseif($story->stage == $stage and strpos($cardPairs[$colType], ",$storyID,") === false) { $cardPairs[$colType] = empty($cardPairs[$colType]) ? ",$storyID," : ",$storyID" . $cardPairs[$colType]; } } + + if($story->stage == 'projected' and strpos($cardPairs['ready'], ",$storyID,") === false and strpos($cardPairs['backlog'], ",$storyID,") === false) + { + $cardPairs['backlog'] = empty($cardPairs['backlog']) ? ",$storyID," : ",$storyID" . $cardPairs['backlog']; + } + } } elseif($laneType == 'bug') @@ -1966,9 +1950,16 @@ class kanbanModel extends model } } + $colPairs = $this->dao->select('t2.type, t2.id')->from(TABLE_KANBANCELL)->alias('t1') + ->leftJoin(TABLE_KANBANCOLUMN)->alias('t2')->on('t1.`column` = t2.id') + ->where('t1.kanban')->eq($executionID) + ->andWhere('t1.lane')->eq($lane->id) + ->fetchPairs(); + foreach($cardPairs as $colType => $cards) { - $this->dao->update(TABLE_KANBANCOLUMN)->set('cards')->eq($cards)->where('lane')->eq($lane->id)->andWhere('type')->eq($colType)->exec(); + if(!isset($colPairs[$colType])) continue; + $this->dao->update(TABLE_KANBANCELL)->set('cards')->eq($cards)->where('lane')->eq($lane->id)->andWhere('`column`')->eq($colPairs[$colType])->exec(); } $this->dao->update(TABLE_KANBANLANE)->set('lastEditedTime')->eq(helper::now())->where('id')->eq($lane->id)->exec(); @@ -2031,7 +2022,7 @@ class kanbanModel extends model } $this->dao->update(TABLE_KANBANLANE)->set('name')->eq($laneName)->where('id')->eq($laneID)->exec(); - $this->updateCards($lane); + $this->refreshCards($lane); $colorIndex += 1; if($colorIndex == count($this->config->kanban->laneColorList)) $colorIndex = 0; From aa0faea2708f5ef837eb3c135ef0043770fd697b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B9=BF=E6=98=8E?= Date: Wed, 12 Jan 2022 11:32:25 +0800 Subject: [PATCH 20/85] * Adjust code. --- module/kanban/model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/kanban/model.php b/module/kanban/model.php index cee72db6a3..faaa39a421 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -314,7 +314,7 @@ class kanbanModel extends model $this->dao->update(TABLE_KANBANCOLUMN)->set('type')->eq("column{$columnID}")->where('id')->eq($columnID)->exec(); /* Add kanban cell. */ - $lanes = $this->dao->select('id')->from(TABLE_KANBANLANE)->where('`group`')->eq($column->group)->fetchPairs(); + $lanes = $this->dao->select('id')->from(TABLE_KANBANLANE)->where('`group`')->eq($column->group)->fetchPairs(); $kanbanID = $this->dao->select('kanban')->from(TABLE_KANBANREGION)->where('id')->eq($regionID)->fetch('kanban'); foreach($lanes as $laneID) $this->addKanbanCell($kanbanID, $laneID, $columnID, 'card'); From 0b334a246f91a2cd54082c0bc5c7b6a80971f00a Mon Sep 17 00:00:00 2001 From: liumengyi Date: Wed, 12 Jan 2022 15:39:33 +0800 Subject: [PATCH 21/85] * Add column menu. --- module/execution/control.php | 14 +++ module/execution/js/kanban.js | 135 +++++++++----------------- module/execution/view/kanban.html.php | 50 +++++++++- module/kanban/model.php | 30 +++--- 4 files changed, 121 insertions(+), 108 deletions(-) diff --git a/module/execution/control.php b/module/execution/control.php index f934284e97..5df0d4b454 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1981,6 +1981,18 @@ class execution extends control $userList[$account]['avatar'] = $avatar; } + /* Get execution's product. */ + $productID = 0; + $products = $this->loadModel('product')->getProducts($execution->project); + if($products) $productID = key($products); + + $plans = $this->execution->getPlans($products); + $allPlans = array('' => ''); + if(!empty($plans)) + { + foreach($plans as $plan) $allPlans += $plan; + } + $this->view->title = $this->lang->kanban->view; $this->view->users = $users; $this->view->regions = $kanbanData; @@ -1989,6 +2001,8 @@ class execution extends control $this->view->browseType = $browseType; $this->view->orderBy = $orderBy; $this->view->groupBy = $groupBy; + $this->view->productID = $productID; + $this->view->allPlans = $allPlans; $this->display(); } diff --git a/module/execution/js/kanban.js b/module/execution/js/kanban.js index ccbd589e45..9094d0c3cf 100644 --- a/module/execution/js/kanban.js +++ b/module/execution/js/kanban.js @@ -61,66 +61,6 @@ function createLaneMenu(options) return items; } -/** - * Create card menu. - * - * @param object $options - * @access public - * @return array - */ -function createCardMenu(options) -{ - var card = options.$trigger.closest('.kanban-item').data('item'); - var privs = card.actions; - if(!privs.length) return []; - - var items = []; - if(privs.includes('editCard')) items.push({label: kanbanLang.editCard, icon: 'edit', url: createLink('kanban', 'editCard', 'cardID=' + card.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}}); - if(privs.includes('archiveCard') && kanban.archived == '1') items.push({label: kanbanLang.archiveCard, icon: 'card-archive', url: createLink('kanban', 'archiveCard', 'cardID=' + card.id), attrs: {'target': 'hiddenwin'}}); - if(privs.includes('copyCard')) items.push({label: kanbanLang.copyCard, icon: 'copy', url: createLink('kanban', 'copyCard', 'cardID=' + card.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal'}}); - if(privs.includes('deleteCard')) items.push({label: kanbanLang.deleteCard, icon: 'trash', url: createLink('kanban', 'deleteCard', 'cardID=' + card.id), attrs: {'target': 'hiddenwin'}}); - if(privs.includes('moveCard')) - { - var moveCardItems = []; - var moveColumns = []; - var parentColumns = []; - var regionGroups = regions[options.$trigger.closest('.region').data('id')].groups; - for(let i = 0; i < regionGroups.length ; i ++ ) - { - if(regionGroups[i].id == options.$trigger.closest('.kanban-board').data('id')) - { - moveColumns = regionGroups[i].columns; - break; - } - } - for(let i = moveColumns.length-1 ; i >= 0 ; i -- ) - { - if(moveColumns[i].parent > 0) parentColumns.push(moveColumns[i].parent); - if(moveColumns[i].id == card.column || $.inArray(moveColumns[i].id, parentColumns) >= 0) continue; - moveCardItems.push({label: moveColumns[i].name, onClick: function(){moveCard(card.id, moveColumns[i].id, card.lane, card.kanban, card.region);}}); - } - moveCardItems = moveCardItems.reverse(); - items.push({label: kanbanLang.moveCard, icon: 'move', items: moveCardItems}); - } - if(privs.includes('setCardColor')) - { - var cardColoritems = []; - if(!card.color) color = "#fff"; - for(let i = 0 ; i < colorList.length ; i ++ ) - { - var attr = card.color == colorList[i] ? '' : ''; - var border = i == 0 ? 'border:1px solid #b0b0b0;' : ''; - cardColoritems.push({label: "
    " + colorListLang[colorList[i]] + attr , - onClick: function(){setCardColor(card.id, colorList[i], card.kanban, card.region);}, html: true, attrs: {id: 'cardcolormenu'}, className: 'color' + i}); - }; - items.push({label: kanbanLang.cardColor, icon: 'color', items: cardColoritems}); - } - - var bounds = options.$trigger[0].getBoundingClientRect(); - items.$options = {x: bounds.right, y: bounds.top}; - return items; -} - function createColumnMenu(options) { var column = options.$trigger.closest('.kanban-col').data('col'); @@ -130,14 +70,6 @@ function createColumnMenu(options) var items = []; if(privs.includes('setColumn')) items.push({label: kanbanLang.editColumn, icon: 'edit', url: createLink('kanban', 'setColumn', 'columnID=' + column.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal'}}); if(privs.includes('setWIP')) items.push({label: kanbanLang.setWIP, icon: 'alert', url: createLink('kanban', 'setWIP', 'columnID=' + column.id), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width' : '500px'}}); - if(privs.includes('splitColumn')) items.push({label: kanbanLang.splitColumn, icon: 'col-split', url: createLink('kanban', 'splitColumn', 'columnID=' + column.id, '', true), className: 'iframe', attrs: {'data-toggle': 'modal'}}); - if(privs.includes('createColumn')) - { - items.push({label: kanbanLang.createColumnOnLeft, icon: 'col-add-left', url: createLink('kanban', 'createColumn', 'columnID=' + column.id + '&position=left'), className: 'iframe', attrs: {'data-toggle': 'modal'}}); - items.push({label: kanbanLang.createColumnOnRight, icon: 'col-add-right', url: createLink('kanban', 'createColumn', 'columnID=' + column.id + '&position=right'), className: 'iframe', attrs: {'data-toggle': 'modal'}}); - } - if(privs.includes('copyColumn')) items.push({label: kanbanLang.copyColumn, icon: 'copy', url: createLink('kanban', 'copyColumn', 'columnID=' + column.id), className: 'iframe', attrs: {'data-toggle': 'modal'}}); - if(privs.includes('archiveColumn') && kanban.archived == '1' && column.$kanbanData.columns.length > 1) items.push({label: kanbanLang.archiveColumn, icon: 'card-archive', url: createLink('kanban', 'archiveColumn', 'columnID=' + column.id), attrs: {'target': 'hiddenwin'}}); if(privs.includes('deleteColumn') && column.$kanbanData.columns.length > 1) items.push({label: kanbanLang.deleteColumn, icon: 'trash', url: createLink('kanban', 'deleteColumn', 'columnID=' + column.id), attrs: {'target': 'hiddenwin'}}); var bounds = options.$trigger[0].getBoundingClientRect(); @@ -145,6 +77,35 @@ function createColumnMenu(options) return items; } +/** + * Create column create button menu + * @returns {Object[]} + */ +function createColumnCreateMenu(options) +{ + var $col = options.$trigger.closest('.kanban-col'); + var col = $col.data('col'); + var items = []; + + if(col.type == 'backlog') + { + if(priv.canCreateStory) items.push({label: storyLang.create, url: $.createLink('story', 'create', 'productID=' + productID)}); + if(priv.canBatchCreateStory) items.push({label: executionLang.batchCreateStroy, url: $.createLink('story', 'batchcreate', 'productID=' + productID + '&branch=0&moduleID=0&storyID=0&executionID=' + executionID)}); + if(priv.canLinkStory) items.push({label: executionLang.linkStory, url: $.createLink('execution', 'linkStory', 'executionID=' + executionID)}); + if(priv.canLinkStoryByPlane) items.push({label: executionLang.linkStoryByPlan, url: '#linkStoryByPlan', 'attrs' : {'data-toggle': 'modal'}}); + } + else if(col.type == 'unconfirmed') + { + if(priv.canCreateBug) items.push({label: bugLang.create, url: $.createLink('bug', 'create', 'productID=0&moduleID=0&extra=executionID=' + executionID)}); + if(priv.canBatchCreateBug) items.push({label: bugLang.batchCreate, url: $.createLink('bug', 'batchcreate', 'productID=' + productID + '&moduleID=0&executionID=' + executionID)}); + } + else if(col.type == 'wait') + { + if(priv.canCreateTask) items.push({label: taskLang.create, url: $.createLink('task', 'create', 'executionID=' + executionID, '', true), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}}); + if(priv.canBatchCreateTask) items.push({label: taskLang.batchCreate, url: $.createLink('task', 'batchcreate', 'executionID=' + executionID, '', true), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}}); + } + return items; +} /** * Hide kanban action @@ -235,6 +196,7 @@ function renderHeaderCol($column, column, $header, kanbanData) /* Render group header. */ var privs = kanbanData.actions; var columnPrivs = kanbanData.columns[0].actions; + var $actions = $('
    '); if(privs.includes('sortGroup')) { @@ -255,26 +217,22 @@ function renderHeaderCol($column, column, $header, kanbanData) var groupID = $column.closest('.kanban-board').data('id'); var laneID = column.$kanbanData.lanes[0].id ? column.$kanbanData.lanes[0].id : 0; var columnID = $column.closest('.kanban-col').data('id'); - var printMoreBtn = (columnPrivs.includes('setColumn') || columnPrivs.includes('setWIP') || columnPrivs.includes('createColumn') || columnPrivs.includes('copyColumn') || columnPrivs.includes('archiveColumn') || columnPrivs.includes('deleteColumn') || columnPrivs.includes('splitColumn')); + var printMoreBtn = (columnPrivs.includes('setColumn') || columnPrivs.includes('setWIP') || columnPrivs.includes('deleteColumn')); /* Render more menu. */ - if(columnPrivs.includes('createCard') || printMoreBtn) + if((column.type == 'backlog' && hasStoryButton) || (column.type == 'wait' && hasTaskButton) || (column.type == 'unconfirmed' && hasBugButton)) { - var addItemBtn = ''; - var moreAction = ''; - - if(!$column.children('.actions').length) $column.append('
    '); - var $actions = $column.children('.actions'); - - if(columnPrivs.includes('createCard') && column.parent != -1) - { - var cardUrl = createLink('kanban', 'createCard', 'kanbanID=' + kanbanID + '®ionID=' + regionID + '&groupID=' + groupID + '&laneID=' + laneID + '&columnID=' + columnID); - addItemBtn = ['', '', ''].join(''); - } - - var moreAction = ' '; - $actions.html(addItemBtn + moreAction); + $actions.append([ + '', + '', + '' + ].join('')); } + if(printMoreBtn) + { + $actions.append(' '); + } + $actions.appendTo($column); } /** @@ -307,6 +265,7 @@ function renderLaneName($lane, lane, $kanban, columns, kanban) ].join('')).appendTo($lane); } } + /** * Adjust add button postion in column */ @@ -328,6 +287,7 @@ function adjustAddBtnPosition($kanban) $col.toggleClass('has-scrollbar', items.scrollHeight > items.clientHeight); }); } + /** * Handle kanban action */ @@ -355,6 +315,7 @@ function processMinusBtn() $('#splitTable .btn-plus').hide(); } } + /** * The function for rendering kanban item */ @@ -446,9 +407,9 @@ function renderKanbanItem(item, $item) /* Define menu creators */ window.menuCreators = { - card: createCardMenu, - lane: createLaneMenu, - column: createColumnMenu + lane: createLaneMenu, + column: createColumnMenu, + columnCreate: createColumnCreateMenu }; /** diff --git a/module/execution/view/kanban.html.php b/module/execution/view/kanban.html.php index 2ecc5dc6dd..9b79c075de 100644 --- a/module/execution/view/kanban.html.php +++ b/module/execution/view/kanban.html.php @@ -19,8 +19,13 @@ foreach($regions as $region) $laneCount += $region->laneCount; js::set('regions', $regions); js::set('execution', $execution); +js::set('productID', $productID); js::set('kanbanLang', $lang->kanban); js::set('kanbanlaneLang', $lang->kanbanlane); +js::set('storyLang', $lang->story); +js::set('executionLang', $lang->execution); +js::set('bugLang', $lang->bug); +js::set('taskLang', $lang->task); js::set('kanbancolumnLang', $lang->kanbancolumn); js::set('kanbancardLang', $lang->kanbancard); js::set('executionID', $execution->id); @@ -35,6 +40,33 @@ $canSortRegion = commonModel::hasPriv('kanban', 'sortRegion') && count($region $canEditRegion = commonModel::hasPriv('kanban', 'editRegion'); $canDeleteRegion = commonModel::hasPriv('kanban', 'deleteRegion'); $canCreateLane = commonModel::hasPriv('kanban', 'createLane'); +$canCreateTask = common::hasPriv('task', 'create'); +$canBatchCreateTask = common::hasPriv('task', 'batchCreate'); +$canCreateBug = common::hasPriv('bug', 'create'); +$canBatchCreateBug = common::hasPriv('bug', 'batchCreate'); +$canCreateStory = ($productID and common::hasPriv('story', 'create')); +$canBatchCreateStory = ($productID and common::hasPriv('story', 'batchCreate')); +$canLinkStory = ($productID and common::hasPriv('execution', 'linkStory')); +$canLinkStoryByPlane = ($productID and common::hasPriv('execution', 'importplanstories')); +$hasStoryButton = ($canCreateStory or $canBatchCreateStory or $canLinkStory or $canLinkStoryByPlane); +$hasTaskButton = ($canCreateTask or $canBatchCreateTask); +$hasBugButton = ($canCreateBug or $canBatchCreateBug); + +js::set('priv', + array( + 'canCreateTask' => $canCreateTask, + 'canBatchCreateTask' => $canBatchCreateTask, + 'canCreateBug' => $canCreateBug, + 'canBatchCreateBug' => $canBatchCreateBug, + 'canCreateStory' => $canCreateStory, + 'canBatchCreateStory' => $canBatchCreateStory, + 'canLinkStory' => $canLinkStory, + 'canLinkStoryByPlane' => $canLinkStoryByPlane, + ) +); +js::set('hasStoryButton', $hasStoryButton); +js::set('hasBugButton', $hasBugButton); +js::set('hasTaskButton', $hasTaskButton); ?>
    -
    -
    + diff --git a/module/kanban/model.php b/module/kanban/model.php index a24ad1b8f9..e17755d2e8 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -649,7 +649,7 @@ class kanbanModel extends model $lanes = zget($laneGroup, $group->id, array()); if(!$lanes) continue; - foreach($lanes as $lane) $lane->items = array(); + foreach($lanes as $lane) $lane->items = array(); $group->columns = zget($columnGroup, $group->id, array()); $group->lanes = $lanes; @@ -913,18 +913,10 @@ class kanbanModel extends model */ public function getCardGroupByExecution($executionID, $browseType = 'all', $orderBy = 'id_asc') { - $cards = $this->dao->select("id, title, pri, type, severity, assignedTo, '' as estimate, deadline")->from(TABLE_BUG) - ->where('deleted')->eq(0) - ->andWhere('execution')->eq($executionID) - ->fetchAll('id'); -/* - $cards .= $this->dao->select("id, name, pri, '' as severity, assignedTo, deadline")->from(TABLE_TASK) - ->where('deleted')->eq(0) - ->andWhere('execution')->eq($executionID) - ->fetchAll('id'); - */ - - $planList = $this->loadModel('execution')->getById($executionID); + $cards = array(); + if($browseType == 'all' or $browseType == 'story') $cards['story'] = $this->loadModel('story')->getExecutionStories($executionID, 0, 0, $orderBy); + if($browseType == 'all' or $browseType == 'bug') $cards['bug'] = $this->loadModel('bug')->getExecutionBugs($executionID, 0, 0, '', 0, $orderBy); + if($browseType == 'all' or $browseType == 'task') $cards['task'] = $this->loadModel('execution')->getKanbanTasks($executionID, $orderBy); return $cards; } @@ -1660,12 +1652,12 @@ class kanbanModel extends model /** * Park cards into kanban cell. - * - * @param int $kanbanID - * @param int $laneID - * @param int $colID - * @param string $cards - * @param string $type + * + * @param int $kanbanID + * @param int $laneID + * @param int $colID + * @param string $cards + * @param string $type * @access public * @return void */ From 4bca0680ab417ba46e19a7490e63661af24562b4 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Jan 2022 15:44:44 +0800 Subject: [PATCH 22/85] * Finish task #47335. --- module/execution/config.php | 2 ++ module/execution/control.php | 41 ++++++++++++++++++--------- module/execution/css/kanban.css | 1 + module/execution/model.php | 4 ++- module/execution/view/kanban.html.php | 33 +++++++++++++++++++++ 5 files changed, 67 insertions(+), 14 deletions(-) diff --git a/module/execution/config.php b/module/execution/config.php index 3de6ff2291..69eeeb5f7d 100644 --- a/module/execution/config.php +++ b/module/execution/config.php @@ -13,6 +13,8 @@ $config->execution->modelList['scrum'] = 'sprint'; $config->execution->modelList['waterfall'] = 'stage'; $config->execution->modelList['kanban'] = 'kanban'; +$config->execution->statusActions = array('start', 'putoff', 'suspend', 'close', 'activate'); + global $lang, $app; $app->loadLang('task'); $config->execution->task = new stdclass(); diff --git a/module/execution/control.php b/module/execution/control.php index f29a2d76ac..34254711b1 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -1397,7 +1397,8 @@ class execution extends control $this->loadModel('kanban')->createRDKanban($execution); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); - return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('kanban', "executionID=$executionID") . '#app=execution')); + if($this->app->tab == 'project') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => $this->createLink('project', 'index', "projectID=$projectID"))); + return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('kanban', "executionID=$executionID"))); } if(!empty($planID)) @@ -1476,6 +1477,7 @@ class execution extends control $this->app->loadLang('stage'); $this->app->loadLang('programplan'); $browseExecutionLink = $this->createLink('execution', 'browse', "executionID=$executionID"); + $execution = $this->execution->getById($executionID); if(!empty($_POST)) { @@ -1527,6 +1529,7 @@ class execution extends control $this->executeHooks($executionID); if($_POST['status'] == 'doing') $this->loadModel('common')->syncPPEStatus($executionID); + if($execution->type == 'kanban') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => 'parent')); return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('view', "executionID=$executionID"))); } @@ -1534,7 +1537,6 @@ class execution extends control $this->execution->setMenu($executionID); $executions = array('' => '') + $this->executions; - $execution = $this->execution->getById($executionID); $managers = $this->execution->getDefaultManagers($executionID); $project = $this->project->getByID($execution->project); @@ -1721,6 +1723,7 @@ class execution extends control { $execution = $this->commonAction($executionID); $executionID = $execution->id; + if($execution->type == 'kanban') $this->lang->executionCommon = $this->lang->execution->kanban; if(!empty($_POST)) { @@ -1793,6 +1796,7 @@ class execution extends control { $execution = $this->commonAction($executionID); $executionID = $execution->id; + if($execution->type == 'kanban') $this->lang->executionCommon = $this->lang->execution->kanban; if(!empty($_POST)) { @@ -1828,6 +1832,7 @@ class execution extends control { $execution = $this->commonAction($executionID); $executionID = $execution->id; + if($execution->type == 'kanban') $this->lang->executionCommon = $this->lang->execution->kanban; if(!empty($_POST)) { @@ -1870,6 +1875,7 @@ class execution extends control { $execution = $this->commonAction($executionID); $executionID = $execution->id; + if($execution->type == 'kanban') $this->lang->executionCommon = $this->lang->execution->kanban; if(!empty($_POST)) { @@ -1968,8 +1974,14 @@ class execution extends control public function kanban($executionID, $browseType = 'all', $orderBy = 'id_asc', $groupBy = 'all') { $this->lang->execution->menu = new stdclass(); - $execution = $this->commonAction($executionID); - $kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $browseType, $orderBy, $groupBy); + $execution = $this->commonAction($executionID); + $kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $browseType, $orderBy, $groupBy); + $executionActions = array(); + + foreach($this->config->execution->statusActions as $action) + { + if($this->execution->isClickable($execution, $action)) $executionActions[] = $action; + } $userList = array(); $users = $this->loadModel('user')->getPairs('noletter|nodeleted'); @@ -1980,14 +1992,15 @@ class execution extends control $userList[$account]['avatar'] = $avatar; } - $this->view->title = $this->lang->kanban->view; - $this->view->users = $users; - $this->view->regions = $kanbanData; - $this->view->execution = $execution; - $this->view->userList = $userList; - $this->view->browseType = $browseType; - $this->view->orderBy = $orderBy; - $this->view->groupBy = $groupBy; + $this->view->title = $this->lang->kanban->view; + $this->view->users = $users; + $this->view->regions = $kanbanData; + $this->view->execution = $execution; + $this->view->userList = $userList; + $this->view->browseType = $browseType; + $this->view->orderBy = $orderBy; + $this->view->groupBy = $groupBy; + $this->view->executionActions = $executionActions; $this->display(); } @@ -2382,6 +2395,7 @@ class execution extends control else { /* Delete execution. */ + $execution = $this->execution->getByID($executionID); $this->dao->update(TABLE_EXECUTION)->set('deleted')->eq(1)->where('id')->eq($executionID)->exec(); $this->loadModel('action')->create('execution', $executionID, 'deleted', '', ACTIONMODEL::CAN_UNDELETED); $this->execution->updateUserView($executionID); @@ -2390,7 +2404,8 @@ class execution extends control $this->executeHooks($executionID); if($this->viewType == 'json') return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess)); - die(js::reload('parent')); + if($execution->type == 'kanban') return print(js::locate($this->createLink('execution', 'all'), 'parent')); + return print(js::reload('parent')); } } diff --git a/module/execution/css/kanban.css b/module/execution/css/kanban.css index df132b1ab1..ec349e5541 100644 --- a/module/execution/css/kanban.css +++ b/module/execution/css/kanban.css @@ -108,3 +108,4 @@ #kanbanScaleControl > .input-group-btn:first-child > .btn {border-radius: 16px 0 0 16px; border-right-color: transparent;} #kanbanScaleControl > .input-group-btn:last-child > .btn {border-radius: 0 16px 16px 0; border-left-color: transparent;} #kanbanScaleControl > .input-group-btn > .btn:hover {border-color: #b8bfce;} +#kanbanActionMenu {top: 24px; right: 28px;} diff --git a/module/execution/model.php b/module/execution/model.php index d2332fd56e..b9a5aed9b7 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -3038,7 +3038,9 @@ class executionModel extends model */ public static function isClickable($execution, $action) { - $action = strtolower($action); + $action = strtolower($action); + $clickable = commonModel::hasPriv('execution', $action); + if(!$clickable) return false; if($action == 'start') return $execution->status == 'wait'; if($action == 'close') return $execution->status != 'closed'; diff --git a/module/execution/view/kanban.html.php b/module/execution/view/kanban.html.php index 2ecc5dc6dd..227d766668 100644 --- a/module/execution/view/kanban.html.php +++ b/module/execution/view/kanban.html.php @@ -59,6 +59,39 @@ $canCreateLane = commonModel::hasPriv('kanban', 'createLane'); +
    + " . $lang->kanban->fullScreen, '', "class='btn btn-link'"); + $actions = ''; + $printSettingBtn = (common::hasPriv('kanban', 'createRegion') or (common::hasPriv('kanban', 'setLaneHeight')) or common::hasPriv('execution', 'edit') or common::hasPriv('execution', 'close') or common::hasPriv('execution', 'delete') or !empty($executionActions)); + + if($printSettingBtn) + { + $actions .= html::a('javascript:;', "" . $lang->kanban->setting, '', "data-toggle='dropdown' class='btn btn-link'"); + $actions .= ""; + } + + $actions .= "
    "; + + echo $actions; + ?> +
    From c5bf8afbc291f23ff8d2bb596c1ef805926566f9 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Jan 2022 15:50:44 +0800 Subject: [PATCH 23/85] * Modify the link judgment method. --- module/execution/view/ajaxgetdropmenu.html.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/execution/view/ajaxgetdropmenu.html.php b/module/execution/view/ajaxgetdropmenu.html.php index 48f728d304..c52d2687f1 100644 --- a/module/execution/view/ajaxgetdropmenu.html.php +++ b/module/execution/view/ajaxgetdropmenu.html.php @@ -75,8 +75,8 @@ foreach($executions as $projectID => $projectExecutions) $selected = $execution->id == $executionID ? 'selected' : ''; if($execution->status != 'done' and $execution->status != 'closed' and ($execution->PM == $this->app->user->account or isset($execution->teams[$this->app->user->account]))) { - $kanbanLink = "/execution-kanban-%s.html"; - $taskLink = "/execution-task-%s.html"; + $kanbanLink = $this->createLink('execution', 'kanban', "executionID=%s"); + $taskLink = $this->createLink('execution', 'task', "executionID=%s"); if($execution->type != 'kanban' and $link == $kanbanLink) $link = $taskLink; if($execution->type == 'kanban' and $link != $kanbanLink) $link = $kanbanLink; From 8b22fdcabcda8344130c8edcae7eb8c5fbd0e00d Mon Sep 17 00:00:00 2001 From: tianshujie Date: Wed, 12 Jan 2022 16:28:16 +0800 Subject: [PATCH 24/85] * Finish task #47336,47344,47345. --- module/action/model.php | 2 +- module/execution/view/kanban.html.php | 2 +- module/kanban/control.php | 7 ++++--- module/kanban/model.php | 7 ++++--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/module/action/model.php b/module/action/model.php index 20778d1b2f..ae8211fbd8 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -862,7 +862,7 @@ class actionModel extends model /* Get actions. */ $actions = $this->dao->select('*')->from(TABLE_ACTION) - ->where(1) + ->where('objectType')->notIN('kanbanregion,kanbanlane,kanbancolumn') ->beginIF($period != 'all')->andWhere('date')->gt($begin)->fi() ->beginIF($period != 'all')->andWhere('date')->lt($end)->fi() ->beginIF($date)->andWhere('date' . ($direction == 'next' ? '<' : '>') . "'{$date}'")->fi() diff --git a/module/execution/view/kanban.html.php b/module/execution/view/kanban.html.php index 8799bdd2ce..24200cdb58 100644 --- a/module/execution/view/kanban.html.php +++ b/module/execution/view/kanban.html.php @@ -102,7 +102,7 @@ js::set('hasTaskButton', $hasTaskButton); $actions .= html::a('javascript:;', "" . $lang->kanban->setting, '', "data-toggle='dropdown' class='btn btn-link'"); $actions .= "
    project->model;?> project->modelList, $model, "class='form-control chosen' required $disableModel");?>
    program->parent;?>
    + + + + + + + + + + + + + + + + + + + + + + + +
    kanbanlane->name;?> +
    + +
    kanbanlane->WIPType;?>kanban->laneTypeList, 'story');?>
    kanbanlane->column;?>kanbanlane->modeList, $mode, '', 'block');?>>
    kanbanlane->color;?> +
    + +
    + + cancel, "data-dismiss='modal'", 'btn btn-wide');?> +
    +
    + + + From b8321c127a20e960631e86a0a2eef06a3f7cdb64 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Thu, 13 Jan 2022 10:10:30 +0800 Subject: [PATCH 30/85] * Finish task #47353. --- module/common/lang/en.php | 1 + module/common/lang/zh-cn.php | 1 + module/kanban/control.php | 5 ++++- module/kanban/lang/en.php | 3 ++- module/kanban/lang/zh-cn.php | 3 ++- module/story/lang/en.php | 1 - module/story/lang/zh-cn.php | 1 - 7 files changed, 10 insertions(+), 5 deletions(-) diff --git a/module/common/lang/en.php b/module/common/lang/en.php index 0ffad68872..24cfef7f6d 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -157,6 +157,7 @@ $lang->repo->common = 'Code'; $lang->report->common = 'Statistic'; $lang->system->common = 'System'; $lang->admin->common = 'Admin'; +$lang->story->common = 'Story'; $lang->task->common = 'Task'; $lang->bug->common = 'Bug'; $lang->testcase->common = 'Testcase'; diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index ffde5b8940..8c2b961bad 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -157,6 +157,7 @@ $lang->repo->common = '代码'; $lang->report->common = '统计'; $lang->system->common = '组织'; $lang->admin->common = '后台'; +$lang->story->common = $lang->SRCommon; $lang->task->common = '任务'; $lang->bug->common = 'Bug'; $lang->testcase->common = '用例'; diff --git a/module/kanban/control.php b/module/kanban/control.php index f674e3bde0..1ae4faeb6c 100644 --- a/module/kanban/control.php +++ b/module/kanban/control.php @@ -503,7 +503,10 @@ class kanban extends control { if($confirm == 'no') { - die(js::confirm($this->lang->kanbanlane->confirmDelete, $this->createLink('kanban', 'deleteLane', "laneID=$laneID&confirm=yes"), '')); + $laneType = $this->kanban->getLaneById($laneID)->type; + $confirmTip = in_array($laneType, array('story', 'task', 'bug')) ? sprintf($this->lang->kanbanlane->confirmDeleteTip, $this->lang->{$laneType}->common) : $this->lang->kanbanlane->confirmDelete; + + die(js::confirm($confirmTip, $this->createLink('kanban', 'deleteLane', "laneID=$laneID&confirm=yes"), '')); } else { diff --git a/module/kanban/lang/en.php b/module/kanban/lang/en.php index e975268415..965a27b9cf 100644 --- a/module/kanban/lang/en.php +++ b/module/kanban/lang/en.php @@ -250,7 +250,8 @@ $lang->kanbanlane->otherlane = 'Select Existed Lane'; $lang->kanbanlane->color = 'Lane Color'; $lang->kanbanlane->WIPType = 'Lane WIP Type'; -$lang->kanbanlane->confirmDelete = 'Are you sure to delete this lane? After deleting the lane, all data (columns and cards) in the lane will also be deleted.'; +$lang->kanbanlane->confirmDelete = 'Are you sure to delete this lane? After deleting the lane, all data (columns and cards) in the lane will also be deleted.'; +$lang->kanbanlane->confirmDeleteTip = 'Are you sure to delete this lane? After deleting the lane, all %s in the lane will be hidden.'; $lang->kanbanlane->modeList['sameAsOther'] = 'Use the same Kanban column as other lanes'; $lang->kanbanlane->modeList['independent'] = 'Independent Kanban column is adopted'; diff --git a/module/kanban/lang/zh-cn.php b/module/kanban/lang/zh-cn.php index 0470cf225a..0d267ad399 100644 --- a/module/kanban/lang/zh-cn.php +++ b/module/kanban/lang/zh-cn.php @@ -250,7 +250,8 @@ $lang->kanbanlane->otherlane = '选择共享看板列的泳道'; $lang->kanbanlane->color = '泳道颜色'; $lang->kanbanlane->WIPType = '泳道在制品类型'; -$lang->kanbanlane->confirmDelete = '您确认删除该泳道吗?删除泳道后,该泳道中所有数据(列、卡片)也会被删除。'; +$lang->kanbanlane->confirmDelete = '您确认删除该泳道吗?删除泳道后,该泳道中所有数据(列、卡片)也会被删除。'; +$lang->kanbanlane->confirmDeleteTip = '您确认删除该泳道吗?删除泳道后,该泳道中所有的%s将被隐藏。'; $lang->kanbanlane->modeList['sameAsOther'] = '与其他泳道使用相同看板列'; $lang->kanbanlane->modeList['independent'] = '采用独立的看板列'; diff --git a/module/story/lang/en.php b/module/story/lang/en.php index 666f2dbf96..6c6ea9a440 100644 --- a/module/story/lang/en.php +++ b/module/story/lang/en.php @@ -86,7 +86,6 @@ $lang->story->batchToTaskTips = "This action will create a task with the same na $lang->story->successToTask = "Converted to task."; $lang->story->storyRound = '%s time estimation'; -$lang->story->common = 'Story'; $lang->story->id = 'ID'; $lang->story->parent = 'Parent'; $lang->story->product = $lang->productCommon; diff --git a/module/story/lang/zh-cn.php b/module/story/lang/zh-cn.php index b05db77036..9e7c9209aa 100644 --- a/module/story/lang/zh-cn.php +++ b/module/story/lang/zh-cn.php @@ -86,7 +86,6 @@ $lang->story->batchToTaskTips = "此操作会创建与所选{$lang->SRCommon}同 $lang->story->successToTask = '批量转任务成功'; $lang->story->storyRound = '第 %s 轮估算'; -$lang->story->common = $lang->SRCommon; $lang->story->id = '编号'; $lang->story->parent = '父需求'; $lang->story->product = "所属{$lang->productCommon}"; From e00b854154fb4953ff5a87673250cb6963874428 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Thu, 13 Jan 2022 10:20:51 +0800 Subject: [PATCH 31/85] * Finish task #47313. --- module/kanban/lang/en.php | 1 + module/kanban/lang/zh-cn.php | 1 + module/kanban/view/space.html.php | 6 ++++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/module/kanban/lang/en.php b/module/kanban/lang/en.php index 965a27b9cf..68073e31d5 100644 --- a/module/kanban/lang/en.php +++ b/module/kanban/lang/en.php @@ -86,6 +86,7 @@ $lang->kanban->cardCountTip = 'Please enter the number of cards'; $lang->kanban->aclGroup['open'] = 'Open'; $lang->kanban->aclGroup['private'] = 'Private'; +$lang->kanban->aclGroup['extend'] = 'Extend'; $lang->kanban->aclList['extend'] = 'Extend (Accessible with space view permissions)'; $lang->kanban->aclList['private'] = 'Private (For the kanban team, whitelist members and space owner only)'; diff --git a/module/kanban/lang/zh-cn.php b/module/kanban/lang/zh-cn.php index 0d267ad399..c5ccff65c5 100644 --- a/module/kanban/lang/zh-cn.php +++ b/module/kanban/lang/zh-cn.php @@ -86,6 +86,7 @@ $lang->kanban->cardCountTip = '请输入卡片数量'; $lang->kanban->aclGroup['open'] = '公开'; $lang->kanban->aclGroup['private'] = '私有'; +$lang->kanban->aclGroup['extend'] = '继承空间'; $lang->kanban->aclList['extend'] = '继承空间访问权限(能访问当前空间,即可访问)'; $lang->kanban->aclList['private'] = '私有(看板团队成员、白名单、空间负责人可访问)'; diff --git a/module/kanban/view/space.html.php b/module/kanban/view/space.html.php index 2b7cef680d..2f77d810c0 100644 --- a/module/kanban/view/space.html.php +++ b/module/kanban/view/space.html.php @@ -141,9 +141,11 @@
    kanban->teamSumCount, $teamCount);?>
    - acl == 'open' ? 'unlock' : 'lock';?> + + acl == 'private') $icon = 'lock';?> + acl == 'extend') $icon = 'inherit-space';?> - kanban->aclGroup, $kanban->acl == 'open' ? 'open' : 'private', '');?> + kanban->aclGroup, $kanban->acl, '');?>
    From 1ea0bb47607b3da3e2823ce4c6231919f667af32 Mon Sep 17 00:00:00 2001 From: liumengyi Date: Thu, 13 Jan 2022 10:35:04 +0800 Subject: [PATCH 32/85] * Finish task #47334.Add card view. --- module/execution/css/kanban.css | 54 ++- module/execution/js/kanban.js | 461 ++++++++++++++++++-------- module/execution/view/kanban.html.php | 13 +- module/kanban/model.php | 79 ++++- 4 files changed, 420 insertions(+), 187 deletions(-) diff --git a/module/execution/css/kanban.css b/module/execution/css/kanban.css index ec349e5541..dc4cba5734 100644 --- a/module/execution/css/kanban.css +++ b/module/execution/css/kanban.css @@ -58,38 +58,8 @@ .region .kanban-lane-items {overflow: auto; padding-bottom: 10px;} .region .kanban-item {position: relative} -.region .kanban-item > .kanban-card > .title:hover {color: #2272eb} -.region .kanban-item > .kanban-card > .info {margin-top: 5px; position: relative;} -.region .kanban-item > .kanban-card > .info > .pri {height: 14px; border-width: 1px; font-size: 12px; line-height: 12px; min-width: 14px; padding: 0 1px;} -.region .kanban-item > .kanban-card > .info > .estimate{margin-left: 4px; color: #999; background-color: rgb(255, 255, 255); padding: 3px 0px} -.region .kanban-item > .kanban-card > .info > .time {margin-left: 4px; font-size: 12px; background: rgb(242, 242, 242)} -.region .kanban-item > .kanban-card > .info > .user {position: absolute; right: 0; top: -2px} -.region .kanban-item > .kanban-card > .info > .user > .avatar {display: inline-block; width: 24px; height: 24px; line-height: 24px; margin-right: 0px; margin-left: 2px} -.region .kanban-item > .kanban-card > .info > .user > span {display: inline-block; color: transparent; width: 2px; height: 2px; background-color: #8990a2; position: sticky; border-radius: 50%; top: 3px; margin: 0 7px;} -.region .kanban-item > .kanban-card > .info > .user > span:before, -.region .kanban-item > .kanban-card > .info > .user > span:after {content: ''; display: block; position: absolute; width: 2px; height: 2px; background-color: #8990a2; top: 0; border-radius: 50%} -.region .kanban-item > .kanban-card > .info > .user > span:before {left: -4px;} -.region .kanban-item > .kanban-card > .info > .user > span:after {right: -4px;} -.region .kanban-item > .kanban-card > .actions > a {display: block; float: left; width: 20px; height: 20px; line-height: 20px; text-align: center; border-radius: 4px; opacity: .7;} -.region .kanban-item > .kanban-card > .actions > a:hover {background-color: rgba(0,0,0,.075); opacity: 1;} -.region .kanban-item:hover > .actions {opacity: 1;} -.region .kanban-item .has-color .title, -.region .kanban-item .has-color .actions .icon-more-v, -.region .kanban-item .has-color .info > .label-pri, -.region .kanban-item .has-color .info > .estimate, -.region .kanban-item .has-color .info > .user .lable-teamSumCount, -.region .kanban-item .has-color .info > .label-light {color: #FFFFFF;} -.region .kanban-item .has-color .info > .label-pri {border-color: #FFFFFF;} -.region .kanban-item .item-more {position: absolute; right: 6px; top: 0px;} .kanban-card {height: auto !important; padding: 8px 14px !important} -.kanban-card > .title {word-break: break-all;} -.kanban-card > .info {position: relative; margin-top: 5px} -.kanban-card > .info > .info + .info {margin-left: 8px} -.kanban-card:hover > .actions {opacity: 1;} -.kanban-card > .actions {position: absolute; top: 4px; right: 4px; opacity: 0;} -.kanban-card > .actions > a {display: block; float: left; width: 20px; height: 20px; line-height: 20px; text-align: center; border-radius: 4px; opacity: .7;} -.kanban-card > .actions > a:hover {background-color: rgba(0,0,0,.075); opacity: 1;} .cardcolor {width:40px; height: 14px; float: left; margin-left: 5px; margin-right: 5px; margin-top: 2px; border-radius: 2px;} #cardcolormenu {padding:2px 2px; width: 100px;} @@ -109,3 +79,27 @@ #kanbanScaleControl > .input-group-btn:last-child > .btn {border-radius: 0 16px 16px 0; border-left-color: transparent;} #kanbanScaleControl > .input-group-btn > .btn:hover {border-color: #b8bfce;} #kanbanActionMenu {top: 24px; right: 28px;} + +.kanban + .kanban {margin-top: 15px} +.kanban-card > .title {display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis} +.kanban-card > .infos {position: relative; margin-top: 5px} +.kanban-card > .infos > .info + .info {margin-left: 8px} +.kanban-card > .infos > .info-id, +.kanban-card > .infos > .info-deadline, +.kanban-card > .infos > .info-estimate {font-size: 12px; position: relative; top: 2px} +.kanban-card > .infos > .label-pri {min-width: 16px; line-height: 14px; height: 16px; padding: 0} +.kanban-card > .infos > .label-severity {transform: scale(.75)} +.kanban-card > .infos > .avatar {position: absolute; right: 0; top: 0} +.kanban-card > .actions {position: absolute; top: 4px; right: 4px; opacity: 0;} +.kanban-card:hover > .actions {opacity: 1;} +.kanban-card > .actions > a {display: block; float: left; width: 20px; height: 20px; line-height: 20px; text-align: center; border-radius: 4px; opacity: .7;} +.kanban-card > .actions > a:hover {background-color: rgba(0,0,0,.075); opacity: 1;} + +#kanban .kanban-card[data-scale-size="4"] {padding: 8px;} +#kanban .kanban-card[data-scale-size="3"] {padding: 3px 4px;} +#kanban .kanban-card[data-scale-size="3"] > .title {white-space: normal; max-height: 100%;} +#kanban .kanban-card[data-scale-size="2"] {padding: 3px 4px; overflow: hidden;} +#kanban .kanban-card[data-scale-size="2"] > .title {display: inline; line-height: 18px; white-space: normal; max-height: 100%; word-break: break-all;} +#kanban .kanban-card[data-scale-size="2"] > .infos {display: inline-block; height: 18px; vertical-align: top; margin: 0;} +#kanban .kanban-card[data-scale-size="2"] > .infos > .info-pri {transform: scale(.8); vertical-align: top;} +#kanban .kanban-card[data-scale-size="2"] > .infos > .avatar {display: inline-block; transform: scale(.8); position: relative; top: -2px; vertical-align: top; margin-right: -1px;} diff --git a/module/execution/js/kanban.js b/module/execution/js/kanban.js index 9094d0c3cf..839fed12c9 100644 --- a/module/execution/js/kanban.js +++ b/module/execution/js/kanban.js @@ -11,7 +11,7 @@ function changeKanbanScaleSize(newScaleSize) $('#kanbanScaleControl .btn[data-type="+"]').attr('disabled', newScaleSize >= 4 ? 'disabled' : null); $('#kanbanScaleControl .btn[data-type="-"]').attr('disabled', newScaleSize <= 1 ? 'disabled' : null); - $('#kanbans').children('.kanban').each(function() + $('#kanban').children('.region').children("div[id^='kanban']").each(function() { var kanban = $(this).data('zui.kanban'); if(!kanban) return; @@ -21,6 +21,12 @@ function changeKanbanScaleSize(newScaleSize) return newScaleSize; } +/** Get card height */ +function getCardHeight() +{ + return [59, 59, 62, 62, 47][window.kanbanScaleSize]; +} + $('#type').change(function() { var type = $('#type').val(); @@ -70,7 +76,6 @@ function createColumnMenu(options) var items = []; if(privs.includes('setColumn')) items.push({label: kanbanLang.editColumn, icon: 'edit', url: createLink('kanban', 'setColumn', 'columnID=' + column.id, '', 'true'), className: 'iframe', attrs: {'data-toggle': 'modal'}}); if(privs.includes('setWIP')) items.push({label: kanbanLang.setWIP, icon: 'alert', url: createLink('kanban', 'setWIP', 'columnID=' + column.id), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width' : '500px'}}); - if(privs.includes('deleteColumn') && column.$kanbanData.columns.length > 1) items.push({label: kanbanLang.deleteColumn, icon: 'trash', url: createLink('kanban', 'deleteColumn', 'columnID=' + column.id), attrs: {'target': 'hiddenwin'}}); var bounds = options.$trigger[0].getBoundingClientRect(); items.$options = {x: bounds.right, y: bounds.top}; @@ -126,35 +131,327 @@ function handleFinishDrop() $('.kanban').find('.can-drop-here').removeClass('can-drop-here'); } -/** +/* Define drag and drop rules */ +if(!window.kanbanDropRules) +{ + window.kanbanDropRules = + { + story: + { + backlog: ['ready'], + ready: ['backlog'], + }, + bug: + { + 'unconfirmed': ['confirmed', 'fixing', 'fixed'], + 'confirmed': ['fixing', 'fixed'], + 'fixing': ['fixed'], + 'fixed': ['testing', 'tested', 'fixing'], + 'testing': ['tested', 'closed', 'fixing'], + 'tested': ['closed', 'fixing'], + 'closed': ['fixing'], + }, + task: + { + 'wait': ['developing', 'developed', 'canceled', 'closed'], + 'developing': ['developed', 'pause'], + 'developed': ['canceled', 'closed'], + 'pause': ['developing'], + 'canceled': ['developing'], + 'closed': ['developing'], + } + } +} + +/* * Find drop columns * @param {JQuery} $element Drag element * @param {JQuery} $root Dnd root element */ function findDropColumns($element, $root) { - var $task = $element; - var task = $task.data('task'); - //var status = task.status; - var $col = $task.closest('.kanban-col'); - var col = $col.data(); - var lane = $col.closest('.kanban-lane').data('lane'); - var allStatusCanChange = statusChangeMap[status]; + var $col = $element.closest('.kanban-col'); + var col = $col.data(); + var kanbanID = $root.data('id'); + var kanbanRules = window.kanbanDropRules ? window.kanbanDropRules[kanbanID] : null; - hideKanbanAction(); + if(!kanbanRules) return $root.find('.kanban-lane-col:not([data-type="' + col.type + '"])'); - return $root.find('.kanban-lane-col:not([data-type="EMPTY"],[data-type=""])').filter(function() + var colRules = kanbanRules[col.type]; + var lane = $col.closest('.kanban-lane').data('lane'); + return $root.find('.kanban-lane-col').filter(function() { + if(!colRules) return false; + if(colRules === true) return true; + var $newCol = $(this); var newCol = $newCol.data(); + if(newCol.id === col.id) return false; + var $newLane = $newCol.closest('.kanban-lane'); var newLane = $newLane.data('lane'); - - $newCol.addClass('can-drop-here'); - return true; + var canDropHere = colRules.indexOf(newCol.type) > -1 && newLane.id === lane.id; + if(canDropHere) $newCol.addClass('can-drop-here'); + return canDropHere; }); } +/** + * Render user avatar + * @param {String|{account: string, avatar: string}} user User account or user object + * @returns {string} + */ +function renderUserAvatar(user, objectType, objectID, size) +{ + var avatarSizeClass = 'avatar-' + (size || 'sm'); + var $noPrivAndNoAssigned = $('
    '); + if(objectType == 'task') + { + if(!priv.canAssignTask && !user) return $noPrivAndNoAssigned; + var link = createLink('task', 'assignto', 'executionID=' + executionID + '&id=' + objectID, '', true); + } + if(objectType == 'story') + { + if(!priv.canAssignStory && !user) return $noPrivAndNoAssigned; + var link = createLink('story', 'assignto', 'id=' + objectID, '', true); + } + if(objectType == 'bug') + { + if(!priv.canAssignBug && !user) return $noPrivAndNoAssigned; + var link = createLink('bug', 'assignto', 'id=' + objectID, '', true); + } + + if(!user) return $(''); + + if(typeof user === 'string') user = {account: user}; + if(!user.avatar && window.userList && window.userList[user.account]) user = {avatar: userList[user.account].avatar, account: user.account}; + + var $noPrivAvatar = $('
    ').avatar({user: user}); + if(objectType == 'task' && !priv.canAssignTask) return $noPrivAvatar; + if(objectType == 'story' && !priv.canAssignStory) return $noPrivAvatar; + if(objectType == 'bug' && !priv.canAssignBug) return $noPrivAvatar; + + return $('').avatar({user: user}).attr('data-toggle', 'modal').attr('data-width', '80%'); +} + +/** + * Render deadline + * @param {String|Date} deadline Deadline + * @returns {JQuery} + */ +function renderDeadline(deadline) +{ + if(deadline == '0000-00-00') return; + + var date = $.zui.createDate(deadline); + var now = new Date(); + now.setHours(0); + now.setMinutes(0); + now.setSeconds(0); + now.setMilliseconds(0); + var isEarlyThanToday = date.getTime() < now.getTime(); + var deadlineDate = $.zui.formatDate(date, 'MM-dd'); + + return $('').text(deadlineLang + ' ' + deadlineDate).addClass(isEarlyThanToday ? 'text-red' : 'text-muted'); +} + +/** + * Render story item + * @param {Object} item Story item object + * @param {JQuery} $item Kanban item element + * @param {Object} col Column object + * @returns {JQuery} $item Kanban item element + */ +function renderStoryItem(item, $item, col) +{ + var scaleSize = window.kanbanScaleSize; + if(+$item.attr('data-scale-size') !== scaleSize) $item.empty().attr('data-scale-size', scaleSize); + + if(scaleSize <= 3) + { + var $title = $item.find('.title'); + if(!$title.length) + { + $title = $('' + (scaleSize <= 1 ? ' ' : '') + '') + .attr('href', $.createLink('story', 'view', 'storyID=' + item.id, '', true)).attr('data-toggle', 'modal').attr('data-width', '80%'); + $title.appendTo($item); + } + $title.attr('title', item.title).find('.text').text(item.title); + } + + if(scaleSize <= 2) + { + var idHtml = scaleSize <= 1 ? ('#' + item.id + '') : ''; + var priHtml = '' + item.pri + ''; + var hoursHtml = (item.estimate && scaleSize <= 1) ? ('' + item.estimate + 'h') : ''; + var avatarHtml = renderUserAvatar(item.assignedTo, 'story', item.id); + var $infos = $item.find('.infos'); + if(!$infos.length) $infos = $('
    '); + $infos.html([idHtml, priHtml, hoursHtml].join('')); + + $infos[scaleSize <= 1 ? 'append' : 'prepend'](avatarHtml); + if(scaleSize <= 1) $infos.appendTo($item); + else if(scaleSize === 2) $infos.prependTo($item); + else $infos.prependTo($item.find('.title')); + } + else if(scaleSize === 4) + { + $item.html(renderUserAvatar(item.assignedTo, 'story', item.id, 'md')); + } + + if(scaleSize <= 1) + { + var $actions = $item.find('.actions'); + if(!$actions.length && item.menus && item.menus.length) + { + $actions = $([ + '
    ', + '', + '', + '', + '
    ' + ].join('')).appendTo($item); + } + } + + return $item.attr('data-type', 'story').addClass('kanban-item-story'); +} + +/** + * Render bug item + * @param {Object} item Bug item object + * @param {JQuery} $item Kanban item element + * @param {Object} col Column object + * @returns {JQuery} $item Kanban item element + */ +function renderBugItem(item, $item, col) +{ + var scaleSize = window.kanbanScaleSize; + if(+$item.attr('data-scale-size') !== scaleSize) $item.empty().attr('data-scale-size', scaleSize); + + if(scaleSize <= 3) + { + var $title = $item.find('.title'); + if(!$title.length) + { + $title = $('' + (scaleSize <= 1 ? ' ' : '') + '') + .attr('href', $.createLink('bug', 'view', 'bugID=' + item.id, '', true)).attr('data-toggle', 'modal').attr('data-width', '80%'); + $title.appendTo($item); + } + $title.attr('title', item.title).find('.text').text(item.title); + } + + if(scaleSize <= 2) + { + var idHtml = scaleSize <= 1 ? ('#' + item.id + '') : ''; + var severityHtml = scaleSize <= 1 ? ('') : ''; + var priHtml = '' + item.pri + ''; + var avatarHtml = renderUserAvatar(item.assignedTo, 'bug', item.id); + + var $infos = $item.find('.infos'); + if(!$infos.length) $infos = $('
    '); + $infos.html([idHtml, severityHtml, priHtml].join('')); + if(item.deadline && scaleSize <= 1) $infos.append(renderDeadline(item.deadline)); + $infos[scaleSize <= 1 ? 'append' : 'prepend'](avatarHtml); + + if(scaleSize <= 1) $infos.appendTo($item); + else if(scaleSize === 2) $infos.prependTo($item); + else $infos.prependTo($item.find('.title')); + } + else if(scaleSize === 4) + { + $item.html(renderUserAvatar(item.assignedTo, 'bug', item.id, 'md')); + } + + if(scaleSize <= 1) + { + var $actions = $item.find('.actions'); + if(!$actions.length && item.menus && item.menus.length) + { + $actions = $([ + '
    ', + '', + '', + '', + '
    ' + ].join('')).appendTo($item); + } + } + + return $item.attr('data-type', 'bug').addClass('kanban-item-bug'); +} + +/** + * Render task item + * @param {Object} item Task item object + * @param {JQuery} $item Kanban item element + * @param {Object} col Column object + * @returns {JQuery} $item Kanban item element + */ +function renderTaskItem(item, $item, col) +{ + var scaleSize = window.kanbanScaleSize; + if(+$item.attr('data-scale-size') !== scaleSize) $item.empty().attr('data-scale-size', scaleSize); + + if(scaleSize <= 3) + { + var $title = $item.find('.title'); + if(!$title.length) + { + $title = $('' + (scaleSize <= 1 ? ' ' : '') + '') + .attr('href', $.createLink('task', 'view', 'taskID=' + item.id, '', true)).attr('data-toggle', 'modal').attr('data-width', '80%'); + $title.appendTo($item); + } + $title.attr('title', item.name).find('.text').text(item.name); + } + + if(scaleSize <= 2) + { + var idHtml = scaleSize <= 1 ? ('#' + item.id + '') : ''; + var priHtml = '' + item.pri + ''; + var hoursHtml = (item.estimate && scaleSize <= 1) ? ('' + item.estimate + 'h') : ''; + var avatarHtml = renderUserAvatar(item.assignedTo, 'task', item.id); + + var $infos = $item.find('.infos'); + if(!$infos.length) $infos = $('
    '); + $infos.html([idHtml, priHtml, hoursHtml].join('')); + if(item.deadline && scaleSize <= 1) $infos.append(renderDeadline(item.deadline)); + $infos[scaleSize <= 1 ? 'append' : 'prepend'](avatarHtml); + + if(scaleSize <= 1) $infos.appendTo($item); + else if(scaleSize === 2) $infos.prependTo($item); + else $infos.prependTo($item.find('.title')); + } + else if(scaleSize === 4) + { + $item.html(renderUserAvatar(item.assignedTo, 'task', item.id, 'md')); + } + + if(scaleSize <= 1) + { + var $actions = $item.find('.actions'); + if(!$actions.length && item.menus && item.menus.length) + { + $actions = $([ + '
    ', + '', + '', + '', + '
    ' + ].join('')).appendTo($item); + } + } + + $item.attr('data-type', 'task').addClass('kanban-item-task'); + + return $item; +} + +/* Add column renderer */ +addColumnRenderer('story', renderStoryItem); +addColumnRenderer('bug', renderBugItem); +addColumnRenderer('task', renderTaskItem); + /** * Render items count of a column. */ @@ -196,7 +493,7 @@ function renderHeaderCol($column, column, $header, kanbanData) /* Render group header. */ var privs = kanbanData.actions; var columnPrivs = kanbanData.columns[0].actions; - var $actions = $('
    '); + var $actions = $column.children('.actions'); if(privs.includes('sortGroup')) { @@ -213,14 +510,10 @@ function renderHeaderCol($column, column, $header, kanbanData) } } - var regionID = $column.closest('.kanban').data('id'); - var groupID = $column.closest('.kanban-board').data('id'); - var laneID = column.$kanbanData.lanes[0].id ? column.$kanbanData.lanes[0].id : 0; - var columnID = $column.closest('.kanban-col').data('id'); - var printMoreBtn = (columnPrivs.includes('setColumn') || columnPrivs.includes('setWIP') || columnPrivs.includes('deleteColumn')); + var printMoreBtn = (columnPrivs.includes('setColumn') || columnPrivs.includes('setWIP')); /* Render more menu. */ - if((column.type == 'backlog' && hasStoryButton) || (column.type == 'wait' && hasTaskButton) || (column.type == 'unconfirmed' && hasBugButton)) + if(((column.type == 'backlog' && hasStoryButton) || (column.type == 'wait' && hasTaskButton) || (column.type == 'unconfirmed' && hasBugButton)) && $actions.children('.text-primary').length == 0) { $actions.append([ '', @@ -228,11 +521,10 @@ function renderHeaderCol($column, column, $header, kanbanData) '' ].join('')); } - if(printMoreBtn) + if(printMoreBtn && $actions.children('.btn').length == 0) { $actions.append(' '); } - $actions.appendTo($column); } /** @@ -266,28 +558,6 @@ function renderLaneName($lane, lane, $kanban, columns, kanban) } } -/** - * Adjust add button postion in column - */ -function adjustAddBtnPosition($kanban) -{ - if(!$kanban) - { - $('.kanban').children('.kanban-board').each(function() - { - adjustAddBtnPosition($(this)); - }); - return; - } - - $kanban.find('.kanban-lane-col:not([data-type="EMPTY"])').each(function() - { - var $col = $(this); - var items = $col.children('.kanban-lane-items')[0]; - $col.toggleClass('has-scrollbar', items.scrollHeight > items.clientHeight); - }); -} - /** * Handle kanban action */ @@ -316,94 +586,6 @@ function processMinusBtn() } } -/** - * The function for rendering kanban item - */ -function renderKanbanItem(item, $item) -{ - var $title = $item.children('.title'); - var privs = item.actions; - var printMoreBtn = (privs.includes('editCard') || privs.includes('archiveCard') || privs.includes('copyCard') || privs.includes('deleteCard') || privs.includes('moveCard') || privs.includes('setCardColor')); - if(!$title.length) - { - if(privs.includes('viewCard')) $title = $('').appendTo($item).attr('href', createLink('kanban', 'viewCard', 'cardID=' + item.id, '', true)); - if(!privs.includes('viewCard')) $title = $('

    ').appendTo($item); - } - - $title.text(item.name).attr('title', item.name); - - if(printMoreBtn) - { - $( - [ - '
    ', - '', - '', - '', - '
    ' - ].join('')).appendTo($item); - } - - var $info = $item.children('.info'); - if(!$info.length) $info = $( - [ - '
    ', - '', - '', - '', - '
    ', - '
    ' - ].join('')).appendTo($item); - - $item.data('card', item); - - $info.children('.estimate').text(item.estimate + kanbancardLang.lblHour); - if(item.estimate == 0) $info.children('.estimate').hide(); - - $info.children('.pri') - .attr('class', 'pri label-pri label-pri-' + item.pri) - .text(item.pri); - - $item.css('background-color', item.color); - $item.toggleClass('has-color', item.color != '#fff' && item.color != ''); - $item.find('.info > .label-light').css('background-color', item.color); - - var $time = $info.children('.time'); - if(item.end == '0000-00-00' && item.begin == '0000-00-00') - { - $time.hide(); - } - else - { - var today = new Date(); - var begin = $.zui.createDate(item.begin); - var end = $.zui.createDate(item.end); - var needRemind = (begin.toLocaleDateString() == today.toLocaleDateString() || end.toLocaleDateString() == today.toLocaleDateString()); - if(item.end == '0000-00-00' && item.begin != '0000-00-00') - { - $time.text($.zui.formatDate(begin, 'MM/dd') + ' ' + kanbancardLang.beginAB).attr('title', $.zui.formatDate(begin, 'yyyy/MM/dd') + ' ' +kanbancardLang.beginAB).show(); - } - else if(item.begin == '0000-00-00' && item.end != '0000-00-00') - { - $time.text($.zui.formatDate(end, 'MM/dd') + ' ' + kanbancardLang.deadlineAB).attr('title', $.zui.formatDate(end, 'yyyy/MM/dd') + ' ' + kanbancardLang.deadlineAB).show(); - } - else if(item.begin != '0000-00-00' && item.end != '0000-00-00') - { - $time.text($.zui.formatDate(begin, 'MM/dd') + ' ' + kanbancardLang.to + ' ' + $.zui.formatDate(end, 'MM/dd')).attr('title', $.zui.formatDate(begin, 'yyyy/MM/dd') + kanbancardLang.to + $.zui.formatDate(end, 'yyyy/MM/dd')).show(); - } - - if(!$item.hasClass('has-color') && needRemind) $time.css('background-color', 'rgba(210, 50, 61, 0.3)'); - if($item.hasClass('has-color') && needRemind) $time.css('background-color', 'rgba(255, 255, 255, 0.3)'); - if(!needRemind) $time.css('background-color', 'rgba(0, 0, 0, 0.15)'); - } - - /* Display avatars of assignedTo. */ - var assignedTo = item.assignedTo.split(','); - var $user = $info.children('.user'); - var title = []; - for(i = 0; i < assignedTo.length; i++) title.push(users[assignedTo[i]]); - $user.html(renderUsersAvatar(assignedTo, item.id)).attr('title', title); -} /* Define menu creators */ window.menuCreators = { @@ -429,9 +611,9 @@ function initKanban($kanban) maxColWidth: 300, createColumnText: kanbanLang.createColumn, addItemText: '', - itemRender: renderKanbanItem, + cardHeight: getCardHeight(), + cardsPerRow: window.kanbanScaleSize, onAction: handleKanbanAction, - onRenderKanban: adjustAddBtnPosition, onRenderLaneName: renderLaneName, onRenderHeaderCol: renderHeaderCol, onRenderCount: renderCount, @@ -511,13 +693,6 @@ $(function() $.zui.ContextMenu.show(items, items.$options || {event: event}); }); - /* Adjust the add button position on window resize */ - $(window).on('resize', function(a) - { - adjustAddBtnPosition(); - }); - - /* Hide contextmenu when page scroll */ $(window).on('scroll', function() { diff --git a/module/execution/view/kanban.html.php b/module/execution/view/kanban.html.php index 24200cdb58..fd4462ec3d 100644 --- a/module/execution/view/kanban.html.php +++ b/module/execution/view/kanban.html.php @@ -62,6 +62,17 @@ js::set('priv', 'canBatchCreateStory' => $canBatchCreateStory, 'canLinkStory' => $canLinkStory, 'canLinkStoryByPlane' => $canLinkStoryByPlane, + 'canAssignTask' => common::hasPriv('task', 'assignto'), + 'canAssignStory' => common::hasPriv('story', 'assignto'), + 'canFinishTask' => common::hasPriv('task', 'finish'), + 'canPauseTask' => common::hasPriv('task', 'pause'), + 'canCancelTask' => common::hasPriv('task', 'cancel'), + 'canCloseTask' => common::hasPriv('task', 'close'), + 'canActivateTask' => common::hasPriv('task', 'activate'), + 'canStartTask' => common::hasPriv('task', 'start'), + 'canAssignBug' => common::hasPriv('bug', 'assignto'), + 'canConfirmBug' => common::hasPriv('bug', 'confirmBug'), + 'canActivateBug' => common::hasPriv('bug', 'activate') ) ); js::set('hasStoryButton', $hasStoryButton); @@ -119,8 +130,6 @@ js::set('hasTaskButton', $hasTaskButton); $actions .= ""; } - $actions .= "
    "; - echo $actions; ?>
    diff --git a/module/kanban/model.php b/module/kanban/model.php index b2de333aa5..44ca064ee7 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -654,7 +654,12 @@ class kanbanModel extends model $lanes = zget($laneGroup, $group->id, array()); if(!$lanes) continue; - foreach($lanes as $lane) $lane->items = array(); + foreach($lanes as $lane) + { + $this->refreshCards($lane); + $lane->items = isset($cardGroup[$lane->id]) ? $cardGroup[$lane->id] : array(); + $lane->defaultCardType = $lane->type; + } $group->columns = zget($columnGroup, $group->id, array()); $group->lanes = $lanes; @@ -918,12 +923,60 @@ class kanbanModel extends model */ public function getCardGroupByExecution($executionID, $browseType = 'all', $orderBy = 'id_asc') { - $cards = array(); - if($browseType == 'all' or $browseType == 'story') $cards['story'] = $this->loadModel('story')->getExecutionStories($executionID, 0, 0, $orderBy); - if($browseType == 'all' or $browseType == 'bug') $cards['bug'] = $this->loadModel('bug')->getExecutionBugs($executionID, 0, 0, '', 0, $orderBy); - if($browseType == 'all' or $browseType == 'task') $cards['task'] = $this->loadModel('execution')->getKanbanTasks($executionID, $orderBy); + $cards = $this->dao->select('t1.*, t2.type as columnType') + ->from(TABLE_KANBANCELL)->alias('t1') + ->leftJoin(TABLE_KANBANCOLUMN)->alias('t2')->on('t1.column=t2.id') + ->where('t1.kanban')->eq($executionID) + ->beginIF($browseType != 'all')->andWhere('t1.type')->eq($browseType)->fi() + ->orderby($orderBy) + ->fetchgroup('lane', 'column'); - return $cards; + /* Get group objects. */ + if($browseType == 'all' or $browseType == 'story') $objectGroup['story'] = $this->loadModel('story')->getExecutionStories($executionID); + if($browseType == 'all' or $browseType == 'bug') $objectGroup['bug'] = $this->loadModel('bug')->getExecutionBugs($executionID); + if($browseType == 'all' or $browseType == 'task') $objectGroup['task'] = $this->loadModel('execution')->getKanbanTasks($executionID, "id"); + + $cardGroup = array(); + + foreach($cards as $laneID => $cells) + { + foreach($cells as $columnID => $cell) + { + $cardIdList = array_filter(explode(',', $cell->cards)); + $cardOrder = 1; + foreach($cardIdList as $cardID) + { + $cardData = array(); + $objects = zget($objectGroup, $cell->type, array()); + $object = zget($objects, $cardID, array()); + + if(empty($object)) continue; + + $cardData['id'] = $object->id; + $cardData['order'] = $cardOrder++; + $cardData['pri'] = $object->pri ? $object->pri : ''; + $cardData['estimate'] = $cell->type == 'bug' ? '' : $object->estimate; + $cardData['assignedTo'] = $object->assignedTo; + $cardData['deadline'] = $cell->type == 'story' ? '' : $object->deadline; + $cardData['severity'] = $cell->type == 'bug' ? $object->severity : ''; + $cardData['acl'] = 'open'; + $cardData['lane'] = $laneID; + $cardData['column'] = $cell->column; + + if($cell->type == 'task') + { + $cardData['name'] = $object->name; + } + else + { + $cardData['title'] = $object->title; + } + $cardGroup[$laneID][$cell->columnType][] = $cardData; + } + } + } + + return $cardGroup; } /** @@ -1616,10 +1669,10 @@ class kanbanModel extends model /** * Add kanban cell for new lane. - * - * @param int $kanbanID - * @param int $laneID - * @param int $colID + * + * @param int $kanbanID + * @param int $laneID + * @param int $colID * @param string $type story|task|bug|card * @access public * @return void @@ -1725,7 +1778,7 @@ class kanbanModel extends model $this->dao->insert(TABLE_KANBANLANE)->data($lane)->autoCheck()->exec(); if(dao::isError()) return false; - $this->createRDColumn($regionID, $groupID, $this->dao->lastInsertId(), $type); + $this->createRDColumn($regionID, $groupID, $this->dao->lastInsertId(), $type, $executionID); } } @@ -1740,7 +1793,7 @@ class kanbanModel extends model * @access public * @return bool */ - public function createRDColumn($regionID, $groupID, $laneID, $laneType) + public function createRDColumn($regionID, $groupID, $laneID, $laneType, $executionID) { $devColumnID = $testColumnID = $resolvingColumnID = 0; if($laneType == 'story') $columnList = $this->lang->kanban->storyColumn; @@ -1768,6 +1821,8 @@ class kanbanModel extends model if($type == 'develop') $devColumnID = $this->dao->lastInsertId(); if($type == 'test') $testColumnID = $this->dao->lastInsertId(); if($type == 'resolving') $resolvingColumnID = $this->dao->lastInsertId(); + + $this->addKanbanCell($executionID, $laneID, $this->dao->lastInsertId(), $laneType); } } From fa461923423824c18584b6e5c33ee0b23537ae62 Mon Sep 17 00:00:00 2001 From: liumengyi Date: Thu, 13 Jan 2022 10:39:59 +0800 Subject: [PATCH 33/85] * Modify execution kanban view. --- module/execution/js/kanban.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/execution/js/kanban.js b/module/execution/js/kanban.js index 839fed12c9..cae23472c8 100644 --- a/module/execution/js/kanban.js +++ b/module/execution/js/kanban.js @@ -221,7 +221,7 @@ function renderUserAvatar(user, objectType, objectID, size) var link = createLink('bug', 'assignto', 'id=' + objectID, '', true); } - if(!user) return $(''); + if(!user) return $(''); if(typeof user === 'string') user = {account: user}; if(!user.avatar && window.userList && window.userList[user.account]) user = {avatar: userList[user.account].avatar, account: user.account}; From bc265f93645923ba92b4fc7e43054bc7af11c119 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Thu, 13 Jan 2022 11:02:07 +0800 Subject: [PATCH 34/85] * Finish task #47333,47313. --- module/execution/css/all.css | 1 + module/execution/lang/en.php | 1 + module/execution/lang/zh-cn.php | 1 + module/execution/view/all.html.php | 4 +--- module/execution/view/kanban.html.php | 6 +++--- module/kanban/lang/en.php | 4 ++-- module/project/model.php | 18 ++++++++++-------- module/project/view/browsebycard.html.php | 14 ++++++++------ module/project/view/browsebylist.html.php | 2 -- 9 files changed, 27 insertions(+), 24 deletions(-) diff --git a/module/execution/css/all.css b/module/execution/css/all.css index b01e13c585..ead807410e 100644 --- a/module/execution/css/all.css +++ b/module/execution/css/all.css @@ -22,3 +22,4 @@ td.flex span.project-type-label {margin-left: 5px; min-width: 36px;} .c-progress, .c-burn {width: 60px;} .c-percent, .c-realBegan, .c-end, .c-begin, .c-realEnd{width: 100px;} .c-action {text-align: center;} +.c-name > span {margin-right: 2px;} diff --git a/module/execution/lang/en.php b/module/execution/lang/en.php index 40578c1152..0c9e2b4696 100644 --- a/module/execution/lang/en.php +++ b/module/execution/lang/en.php @@ -424,6 +424,7 @@ $lang->printKanban->typeList['increment'] = 'Increment'; $lang->execution->typeList[''] = ''; $lang->execution->typeList['stage'] = 'Stage'; $lang->execution->typeList['sprint'] = $lang->executionCommon; +$lang->execution->typeList['kanban'] = 'Kanban'; $lang->execution->featureBar['task']['all'] = $lang->execution->allTasks; $lang->execution->featureBar['task']['unclosed'] = $lang->execution->unclosed; diff --git a/module/execution/lang/zh-cn.php b/module/execution/lang/zh-cn.php index f33c35aeac..a9c80f9ddf 100644 --- a/module/execution/lang/zh-cn.php +++ b/module/execution/lang/zh-cn.php @@ -424,6 +424,7 @@ $lang->printKanban->typeList['increment'] = '增量'; $lang->execution->typeList[''] = ''; $lang->execution->typeList['stage'] = '阶段'; $lang->execution->typeList['sprint'] = $lang->executionCommon; +$lang->execution->typeList['kanban'] = '看板'; $lang->execution->featureBar['task']['all'] = $lang->execution->allTasks; $lang->execution->featureBar['task']['unclosed'] = $lang->execution->unclosed; diff --git a/module/execution/view/all.html.php b/module/execution/view/all.html.php index 3652b0b19f..38e8118dfb 100644 --- a/module/execution/view/all.html.php +++ b/module/execution/view/all.html.php @@ -118,9 +118,7 @@ id);?>
    flex' title='name?>'> - config->maxVersion)):?> - '>execution->typeList[$execution->type]?> - + '>execution->typeList[$execution->type]?> projectModel == 'kanban' ? html::a($this->createLink('execution', 'kanban', 'executionID=' . $execution->id), $execution->name, '', "class='text-ellipsis'") : html::a($this->createLink('execution', 'task', 'execution=' . $execution->id), $execution->name, '', "class='text-ellipsis'"); echo !empty($execution->children) ? $execution->name : $executionLink; diff --git a/module/execution/view/kanban.html.php b/module/execution/view/kanban.html.php index babdc60730..55b33e55a1 100644 --- a/module/execution/view/kanban.html.php +++ b/module/execution/view/kanban.html.php @@ -102,10 +102,10 @@ js::set('hasTaskButton', $hasTaskButton); $actions .= html::a('javascript:;', "" . $lang->kanban->setting, '', "data-toggle='dropdown' class='btn btn-link'"); $actions .= " diff --git a/module/user/model.php b/module/user/model.php index d45f9b21bc..b368cfe684 100644 --- a/module/user/model.php +++ b/module/user/model.php @@ -1624,7 +1624,7 @@ class userModel extends model if($allProducts === null) $allProducts = $this->dao->select('id,PO,QD,RD,createdBy,acl,whitelist,program,createdBy')->from(TABLE_PRODUCT)->where('acl')->ne('open')->fetchAll('id'); if($allProjects === null) $allProjects = $this->dao->select('id,PO,PM,QD,RD,acl,type,path,parent,openedBy')->from(TABLE_PROJECT)->where('acl')->ne('open')->andWhere('type')->eq('project')->fetchAll('id'); if($allPrograms === null) $allPrograms = $this->dao->select('id,PO,PM,QD,RD,acl,type,path,parent,openedBy')->from(TABLE_PROGRAM)->where('acl')->ne('open')->andWhere('type')->eq('program')->fetchAll('id'); - if($allSprints === null) $allSprints = $this->dao->select('id,PO,PM,QD,RD,acl,project,path,parent,type,openedBy')->from(TABLE_PROJECT)->where('acl')->eq('private')->beginIF($this->config->systemMode == 'new')->andWhere('type')->in('sprint,stage')->fi()->fetchAll('id'); + if($allSprints === null) $allSprints = $this->dao->select('id,PO,PM,QD,RD,acl,project,path,parent,type,openedBy')->from(TABLE_PROJECT)->where('acl')->eq('private')->beginIF($this->config->systemMode == 'new')->andWhere('type')->in('sprint,stage,kanban')->fi()->fetchAll('id'); /* Get teams. */ if($teams === null) @@ -1869,7 +1869,7 @@ class userModel extends model /* Set opened sprints and stages into userview. */ $openedSprints = $this->dao->select('id')->from(TABLE_PROJECT) ->where('acl')->eq('open') - ->beginIF($this->config->systemMode == 'new')->andWhere('type')->in('sprint,stage')->fi() + ->beginIF($this->config->systemMode == 'new')->andWhere('type')->in('sprint,stage,kanban')->fi() ->beginIF($this->config->systemMode == 'new')->andWhere('project')->in($userView->projects)->fi() ->fetchAll('id'); From d45ff40e16d523e3be719a9e04c119b0d653e425 Mon Sep 17 00:00:00 2001 From: liumengyi Date: Sun, 16 Jan 2022 19:33:52 +0800 Subject: [PATCH 77/85] * Add code annotation. --- module/execution/control.php | 1 + 1 file changed, 1 insertion(+) diff --git a/module/execution/control.php b/module/execution/control.php index f2e20def84..090ae310b4 100644 --- a/module/execution/control.php +++ b/module/execution/control.php @@ -2374,6 +2374,7 @@ class execution extends control * * @param int $executionID * @param string $confirm yes|no + * @param string $kanban yes|no * @access public * @return void */ From 758c03968fce5bac737bd463990779346d8f7332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B9=BF=E6=98=8E?= Date: Mon, 17 Jan 2022 08:41:59 +0800 Subject: [PATCH 78/85] * Add kanban type in query. --- module/doc/model.php | 2 +- module/execution/model.php | 2 +- module/kanban/control.php | 2 +- module/product/model.php | 2 +- module/productplan/model.php | 2 +- module/program/model.php | 4 ++-- module/projectstory/model.php | 2 +- module/report/model.php | 2 +- module/story/model.php | 2 +- module/upgrade/model.php | 4 ++-- module/user/model.php | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/module/doc/model.php b/module/doc/model.php index 3efa6e55f6..bfd4127b49 100644 --- a/module/doc/model.php +++ b/module/doc/model.php @@ -1377,7 +1377,7 @@ class docModel extends model $executions = $this->dao->select('*')->from(TABLE_EXECUTION) ->where('deleted')->eq(0) - ->andWhere('type')->in('sprint,stage') + ->andWhere('type')->in('sprint,stage,kanban') ->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->sprints)->fi() ->orderBy('order_asc') ->fetchAll('id'); diff --git a/module/execution/model.php b/module/execution/model.php index 6d42ab9a32..d9d9c22da3 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -1200,7 +1200,7 @@ class executionModel extends model public function getIdList($projectID, $status = 'all') { return $this->dao->select('id')->from(TABLE_EXECUTION) - ->where('type')->in('sprint,stage') + ->where('type')->in('sprint,stage,kanban') ->andWhere('deleted')->eq('0') ->beginIF($projectID)->andWhere('project')->eq($projectID)->fi() ->beginIF($status == 'undone')->andWhere('status')->notIN('done,closed')->fi() diff --git a/module/kanban/control.php b/module/kanban/control.php index 8b3797a3c9..923e54d155 100644 --- a/module/kanban/control.php +++ b/module/kanban/control.php @@ -1041,7 +1041,7 @@ class kanban extends control * @access public * @return void */ - public function ajaxMoveCard($cardID = 0, $fromColID = 0, $toColID = 0, $fromLaneID = 0, $toLaneID = 0, $executionID = 0, $browseType = 'all', $groupBy = '', $regionID = 0, $orderBy) + public function ajaxMoveCard($cardID = 0, $fromColID = 0, $toColID = 0, $fromLaneID = 0, $toLaneID = 0, $executionID = 0, $browseType = 'all', $groupBy = '', $regionID = 0, $orderBy = '') { $fromCell = $this->dao->select('id, cards')->from(TABLE_KANBANCELL) ->where('kanban')->eq($executionID) diff --git a/module/product/model.php b/module/product/model.php index 410e59c268..771ea5148e 100644 --- a/module/product/model.php +++ b/module/product/model.php @@ -1465,7 +1465,7 @@ class productModel extends model ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project = t2.id') ->where('t2.deleted')->eq(0) ->andWhere('t1.product')->eq($productID) - ->andWhere('t2.type')->in('sprint,stage') + ->andWhere('t2.type')->in('sprint,stage,kanban') ->fetch(); $product->stories = $stories; diff --git a/module/productplan/model.php b/module/productplan/model.php index 596c73f0cd..3a4202134b 100644 --- a/module/productplan/model.php +++ b/module/productplan/model.php @@ -99,7 +99,7 @@ class productplanModel extends model ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id') ->where('t1.product')->eq($product) ->andWhere('t1.plan')->in(array_keys($plans)) - ->andWhere('t2.type')->in('sprint,stage') + ->andWhere('t2.type')->in('sprint,stage,kanban') ->fetchPairs('plan', 'project'); $storyCountInTable = $this->dao->select('plan,count(story) as count')->from(TABLE_PLANSTORY)->where('plan')->in($planIdList)->groupBy('plan')->fetchPairs('plan', 'count'); diff --git a/module/program/model.php b/module/program/model.php index 02b3f2e1be..70faddc9c5 100644 --- a/module/program/model.php +++ b/module/program/model.php @@ -205,7 +205,7 @@ class programModel extends model /* Get doing executions. */ $doingExecutions = $this->dao->select('id, project, name, end')->from(TABLE_EXECUTION) - ->where('type')->in('sprint,stage') + ->where('type')->in('sprint,stage,kanban') ->andWhere('status')->eq('doing') ->andWhere('deleted')->eq(0) ->beginIF(!$this->app->user->admin)->andWhere('id')->in($this->app->user->view->sprints)->fi() @@ -1254,7 +1254,7 @@ class programModel extends model $executions = $this->dao->select('id')->from(TABLE_EXECUTION) ->where('deleted')->eq(0) ->andWhere('project')->in($projectKeys) - ->andWhere('type')->in('sprint,stage') + ->andWhere('type')->in('sprint,stage,kanban') ->fetchAll('id'); /* Get all tasks and compute totalEstimate, totalConsumed, totalLeft, progress according to them. */ diff --git a/module/projectstory/model.php b/module/projectstory/model.php index 2ea88a04a0..834b23e358 100644 --- a/module/projectstory/model.php +++ b/module/projectstory/model.php @@ -49,7 +49,7 @@ class projectstoryModel extends model ->leftJoin(TABLE_STORY)->alias('t2')->on('t1.story=t2.id') ->leftJoin(TABLE_EXECUTION)->alias('t3')->on('t1.project=t3.id') ->where('t1.story')->in($storyIdList) - ->andWhere('t3.type')->in('sprint,stage') + ->andWhere('t3.type')->in('sprint,stage,kanban') ->andWhere('t3.project')->eq($projectID) ->andWhere('t3.deleted')->eq(0) ->fetchAll('id'); diff --git a/module/report/model.php b/module/report/model.php index 588c72979d..256dc816fa 100644 --- a/module/report/model.php +++ b/module/report/model.php @@ -1060,7 +1060,7 @@ class reportModel extends model { $projectStatus = $this->dao->select('t1.id,t1.status')->from(TABLE_PROJECT)->alias('t1') ->leftJoin(TABLE_TEAM)->alias('t2')->on("t1.id=t2.root") - ->where('t1.type')->in($this->config->systemMode == 'classic' ? 'sprint,stage' : 'project') + ->where('t1.type')->in($this->config->systemMode == 'classic' ? 'sprint,stage,kanban' : 'project') ->beginIF($this->config->systemMode == 'classic')->andWhere('t2.type')->eq('execution')->fi() ->beginIF($this->config->systemMode == 'new')->andWhere('t2.type')->eq('project')->fi() ->beginIF(!empty($accounts))->andWhere('t2.account')->in($accounts)->fi() diff --git a/module/story/model.php b/module/story/model.php index 52c3b7c4e9..9472c2c020 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -44,7 +44,7 @@ class storyModel extends model $story->executions = $this->dao->select('t1.project, t2.name, t2.status')->from(TABLE_PROJECTSTORY)->alias('t1') ->leftJoin(TABLE_EXECUTION)->alias('t2')->on('t1.project = t2.id') ->where('t1.story')->eq($storyID) - ->andWhere('t2.type')->in('sprint,stage') + ->andWhere('t2.type')->in('sprint,stage,kanban') ->orderBy('t1.`order` DESC') ->fetchAll('project'); $story->tasks = $this->dao->select('id, name, assignedTo, execution, status, consumed, `left`,type')->from(TABLE_TASK)->where('story')->eq($storyID)->andWhere('deleted')->eq(0)->orderBy('id DESC')->fetchGroup('execution'); diff --git a/module/upgrade/model.php b/module/upgrade/model.php index a1ccf11096..bc351933a6 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -4285,7 +4285,7 @@ class upgradeModel extends model } } - $executionPairs = $this->dao->select('id')->from(TABLE_PROJECT)->where('id')->in($projectIdList)->andWhere('type')->in('sprint,stage')->fetchAll('id', 'id'); + $executionPairs = $this->dao->select('id')->from(TABLE_PROJECT)->where('id')->in($projectIdList)->andWhere('type')->in('sprint,stage,kanban')->fetchAll('id', 'id'); foreach($userViews as $account => $userView) { $projects = zget($accountProjects, $account, array()); @@ -4856,7 +4856,7 @@ class upgradeModel extends model $this->personnel->updateWhitelist($whitelist, 'product', $product->id, 'whitelist', 'upgrade', 'increase'); } - $customSprints = $this->dao->select('*')->from(TABLE_PROJECT)->where('whitelist')->ne('')->andWhere('type')->in('sprint,stage')->fetchAll('id'); + $customSprints = $this->dao->select('*')->from(TABLE_PROJECT)->where('whitelist')->ne('')->andWhere('type')->in('sprint,stage,kanban')->fetchAll('id'); $whitelistACL = $this->dao->select('account')->from(TABLE_ACL)->where('objectID')->in(array_keys($customSprints))->andWhere('objectType')->eq('sprint')->andWhere('type')->eq('whitelist')->fetchPairs('account'); foreach($customSprints as $sprint) { diff --git a/module/user/model.php b/module/user/model.php index d45f9b21bc..fc407db983 100644 --- a/module/user/model.php +++ b/module/user/model.php @@ -1092,7 +1092,7 @@ class userModel extends model */ public function getObjects($account, $type = 'execution', $status = 'all', $orderBy = 'id_desc', $pager = null) { - $objectType = $type == 'execution' ? 'sprint,stage' : $type; + $objectType = $type == 'execution' ? 'sprint,stage,kanban' : $type; $myObjectsList = $this->dao->select('t1.*,t2.*')->from(TABLE_TEAM)->alias('t1') ->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.root = t2.id') ->where('t1.type')->eq($type) From 58c2fe04af93b87721100fb303aae45beb16ac65 Mon Sep 17 00:00:00 2001 From: tianshujie Date: Mon, 17 Jan 2022 08:48:42 +0800 Subject: [PATCH 79/85] *Fix bug #18475. --- module/program/css/project.css | 3 +++ module/program/view/project.html.php | 4 ---- 2 files changed, 3 insertions(+), 4 deletions(-) create mode 100644 module/program/css/project.css diff --git a/module/program/css/project.css b/module/program/css/project.css new file mode 100644 index 0000000000..9368f76487 --- /dev/null +++ b/module/program/css/project.css @@ -0,0 +1,3 @@ +.project-type-label.label-outline {width: 50px; min-width: 50px;} +.project-type-label.label {overflow: unset !important; text-overflow: unset !important; white-space: unset !important;} +[lang^='en'] #projectTableList .project-name > .label-warning {width: 55px;} diff --git a/module/program/view/project.html.php b/module/program/view/project.html.php index e532ca9ed0..f5f336d3d9 100644 --- a/module/program/view/project.html.php +++ b/module/program/view/project.html.php @@ -15,10 +15,6 @@ js::set('programID', $programID); js::set('browseType', $browseType); ?> -
    execution->type;?> diff --git a/module/kanban/model.php b/module/kanban/model.php index b523c5dd2b..a030284f05 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -1113,10 +1113,9 @@ class kanbanModel extends model public function getKanban4Group($executionID, $browseType, $groupBy) { /* Get card data. */ - $cardList = array(); - if($browseType == 'story') $cardList .= $this->loadModel('story')->getExecutionStories($executionID); - if($browseType == 'bug') $cardList .= $this->loadModel('bug')->getExecutionBugs($executionID); - if($browseType == 'task') $cardList .= $this->loadModel('execution')->getKanbanTasks($executionID, "id"); + if($browseType == 'story') $cardList = $this->loadModel('story')->getExecutionStories($executionID); + if($browseType == 'bug') $cardList = $this->loadModel('bug')->getExecutionBugs($executionID); + if($browseType == 'task') $cardList = $this->loadModel('execution')->getKanbanTasks($executionID, "id"); $lanes = $this->getLanes4Group($executionID, $browseType, $groupBy, $cardList); if(empty($lanes)) return array(); diff --git a/module/project/lang/zh-cn.php b/module/project/lang/zh-cn.php index c0e8a48e9b..132c11dc68 100644 --- a/module/project/lang/zh-cn.php +++ b/module/project/lang/zh-cn.php @@ -155,7 +155,7 @@ $lang->project->etc = "等"; $lang->project->product = '所属产品'; $lang->project->branch = '所属分支'; $lang->project->plan = '所属计划'; -$lang->project->createKanban = '创建看板'; +$lang->project->createKanban = '添加看板'; $lang->project->kanban = '看板'; /* Project Kanban. */ From fd20384534d0a2130ed4bb30e49e6355151e70b3 Mon Sep 17 00:00:00 2001 From: liumengyi Date: Mon, 17 Jan 2022 09:21:11 +0800 Subject: [PATCH 81/85] * Fix bug #18470. --- module/project/control.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/module/project/control.php b/module/project/control.php index fa5a7d6d34..0951995446 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -374,6 +374,8 @@ class project extends control $this->loadModel('execution'); $this->loadModel('product'); + if($model == 'kanban') unset($this->lang->project->authList['reset']); + if($_POST) { $projectID = $this->project->create(); From b2324c3406a107c05987b03d9d8b0c9491eb5cd8 Mon Sep 17 00:00:00 2001 From: liumengyi Date: Mon, 17 Jan 2022 10:13:31 +0800 Subject: [PATCH 82/85] * Fix bug #18485,#18474. --- module/execution/js/create.js | 2 +- module/execution/js/kanban.js | 2 +- module/execution/view/create.html.php | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/module/execution/js/create.js b/module/execution/js/create.js index 4420527143..2e76285f06 100644 --- a/module/execution/js/create.js +++ b/module/execution/js/create.js @@ -1,6 +1,6 @@ function setCopyProject(executionID) { - location.href = createLink('execution', 'create', 'projectID=&executionID=0©ExecutionID=' + executionID); + location.href = createLink('execution', 'create', 'projectID=' + projectID + '&executionID=0©ExecutionID=' + executionID); } $(function() diff --git a/module/execution/js/kanban.js b/module/execution/js/kanban.js index e8b43262f4..3e604123a9 100644 --- a/module/execution/js/kanban.js +++ b/module/execution/js/kanban.js @@ -306,7 +306,7 @@ function renderUserAvatar(user, objectType, objectID, size) if(!user) return $(''); if(typeof user === 'string') user = {account: user}; - if(!user.avatar && window.userList && window.userList[user.account]) user = {avatar: userList[user.account].avatar, account: user.account, realname: users[user.account]}; + if(!user.avatar && window.users && window.users[user.account]) user = {avatar: users[user.account].avatar, account: user.account, realname: users[user.account]}; var $noPrivAvatar = $('
    ').avatar({user: user}); if(objectType == 'task' && !priv.canAssignTask) return $noPrivAvatar; diff --git a/module/execution/view/create.html.php b/module/execution/view/create.html.php index 96203eba46..b4ea6625c5 100644 --- a/module/execution/view/create.html.php +++ b/module/execution/view/create.html.php @@ -42,6 +42,7 @@ project->common);?> systemMode);?> +
    From a49076b0d8a6c1caf56b75d74bde3917f4cfdf6d Mon Sep 17 00:00:00 2001 From: hufangzhou Date: Mon, 17 Jan 2022 10:14:50 +0800 Subject: [PATCH 83/85] * Fix bug #18407. --- module/search/lang/en.php | 1 + module/search/lang/zh-cn.php | 1 + module/search/model.php | 9 ++++++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/module/search/lang/en.php b/module/search/lang/en.php index 14e0710118..78e4db7e8f 100644 --- a/module/search/lang/en.php +++ b/module/search/lang/en.php @@ -98,5 +98,6 @@ $lang->search->objectTypeList['story'] = $lang->SRCommon; $lang->search->objectTypeList['requirement'] = $lang->URCommon; $lang->search->objectTypeList['stage'] = 'stage'; $lang->search->objectTypeList['sprint'] = $lang->executionCommon; +$lang->search->objectTypeList['kanban'] = 'kanban'; $lang->search->objectTypeList['commonIssue'] = 'Issue'; $lang->search->objectTypeList['stakeholderIssue'] = 'Stakeholder Issue'; diff --git a/module/search/lang/zh-cn.php b/module/search/lang/zh-cn.php index 5ec2f1b0ca..c7d5f00f49 100644 --- a/module/search/lang/zh-cn.php +++ b/module/search/lang/zh-cn.php @@ -98,5 +98,6 @@ $lang->search->objectTypeList['story'] = $lang->SRCommon; $lang->search->objectTypeList['requirement'] = $lang->URCommon; $lang->search->objectTypeList['stage'] = '阶段'; $lang->search->objectTypeList['sprint'] = $lang->executionCommon; +$lang->search->objectTypeList['kanban'] = '看板'; $lang->search->objectTypeList['commonIssue'] = '问题'; $lang->search->objectTypeList['stakeholderIssue'] = '干系人问题'; diff --git a/module/search/model.php b/module/search/model.php index a233ae3974..40f2c1ab10 100644 --- a/module/search/model.php +++ b/module/search/model.php @@ -609,9 +609,16 @@ class searchModel extends model $record->url = helper::createLink($module, $method, "id={$record->objectID}", '', false, $issue->project); $record->extraType = empty($issue->owner) ? 'commonIssue' : 'stakeholderIssue'; } + elseif($module == 'project') + { + $projectModel = $this->dao->select('model')->from(TABLE_PROJECT)->where('id')->eq($record->objectID)->fetch('model'); + $method = $projectModel == 'kanban' ? 'index' : 'view'; + $record->url = helper::createLink('project', $method, "id={$record->objectID}"); + } elseif($module == 'execution') { $execution = $this->dao->select('id,type,project')->from(TABLE_EXECUTION)->where('id')->eq($record->objectID)->fetch(); + $method = $execution->type == 'kanban' ? 'kanban' : $method; $record->url = helper::createLink('execution', $method, "id={$record->objectID}"); $record->extraType = empty($execution->type) ? '' : $execution->type; } @@ -1015,7 +1022,7 @@ class searchModel extends model ->where('1') ->beginIF($type == 'program')->andWhere('type')->eq('program')->fi() ->beginIF($type == 'project')->andWhere('type')->eq('project')->fi() - ->beginIF($type == 'execution')->andWhere('type')->in('stage,sprint')->fi() + ->beginIF($type == 'execution')->andWhere('type')->in('stage,sprint,kanban')->fi() ->beginIF(isset($data->deleted))->andWhere('t1.deleted')->eq(0)->fi(); } return $query; From 5f58ada8611719a94a90a791947cfa662cba0158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B9=BF=E6=98=8E?= Date: Mon, 17 Jan 2022 10:20:06 +0800 Subject: [PATCH 84/85] * Fix locate bug. --- module/project/js/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/project/js/index.js b/module/project/js/index.js index 8f88d4351d..da84c9f94a 100644 --- a/module/project/js/index.js +++ b/module/project/js/index.js @@ -3,7 +3,7 @@ $('#cards').on('click', '.panel', function(e) { if(!$(e.target).closest('.kanban-actions').length) { - window.location.href = $(this).data('url'); + $.apps.open($(this).data('url')); } }); From a42faa10f1cc014cad9f082c0ba85c84d969616f Mon Sep 17 00:00:00 2001 From: tianshujie Date: Mon, 17 Jan 2022 10:22:51 +0800 Subject: [PATCH 85/85] * Fix bug. --- module/execution/js/kanban.js | 9 +++++---- module/kanban/model.php | 2 +- module/program/css/project.css | 2 +- module/project/css/browse.css | 2 +- module/task/control.php | 2 ++ 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/module/execution/js/kanban.js b/module/execution/js/kanban.js index e8b43262f4..b58c26b636 100644 --- a/module/execution/js/kanban.js +++ b/module/execution/js/kanban.js @@ -172,9 +172,10 @@ function createColumnMenu(options) */ function createColumnCreateMenu(options) { - var $col = options.$trigger.closest('.kanban-col'); - var col = $col.data('col'); - var items = []; + var $col = options.$trigger.closest('.kanban-col'); + var col = $col.data('col'); + var items = []; + var laneID = col.$kanbanData.lanes[0].id ? col.$kanbanData.lanes[0].id : 0; if(col.type == 'backlog') { @@ -190,7 +191,7 @@ function createColumnCreateMenu(options) } else if(col.type == 'wait') { - if(priv.canCreateTask) items.push({label: taskLang.create, url: $.createLink('task', 'create', 'executionID=' + executionID, '', true), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}}); + if(priv.canCreateTask) items.push({label: taskLang.create, url: $.createLink('task', 'create', 'executionID=' + executionID + "&storyID=0&moduleID=0&taskID=0&todoID=0&extra=laneID=" + laneID + ",columnID=" + col.id, '', true), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}}); if(priv.canBatchCreateTask) items.push({label: taskLang.batchCreate, url: $.createLink('task', 'batchcreate', 'executionID=' + executionID, '', true), className: 'iframe', attrs: {'data-toggle': 'modal', 'data-width': '80%'}}); } return items; diff --git a/module/kanban/model.php b/module/kanban/model.php index a030284f05..d258680dfd 100644 --- a/module/kanban/model.php +++ b/module/kanban/model.php @@ -1526,7 +1526,7 @@ class kanbanModel extends model ->add('region', $regionID) ->add('order', $maxOrder ? $maxOrder + 1 : 1) ->add('lastEditedTime', helper::now()) - ->setIF(isset($this->post->laneType), 'execution', $kanbanID) + ->setIF(isset($_POST['laneType']), 'execution', $kanbanID) ->trim('name') ->setDefault('color', '#7ec5ff') ->remove('laneType') diff --git a/module/program/css/project.css b/module/program/css/project.css index 9368f76487..499e53ecc1 100644 --- a/module/program/css/project.css +++ b/module/program/css/project.css @@ -1,3 +1,3 @@ .project-type-label.label-outline {width: 50px; min-width: 50px;} .project-type-label.label {overflow: unset !important; text-overflow: unset !important; white-space: unset !important;} -[lang^='en'] #projectTableList .project-name > .label-warning {width: 55px;} +[lang^='en'] .project-name > .label-warning {width: 55px !important;} diff --git a/module/project/css/browse.css b/module/project/css/browse.css index a61a305bae..5e32206b22 100644 --- a/module/project/css/browse.css +++ b/module/project/css/browse.css @@ -17,4 +17,4 @@ th.c-name {width: 360px !important;} { th.c-name {width: auto;} } -[lang^='en'] #projectTableList .project-name > .label-warning {width: 55px;} +[lang^='en'] .project-name > .label-warning {width: 55px !important;} diff --git a/module/task/control.php b/module/task/control.php index 69400b914e..956dd1a83b 100644 --- a/module/task/control.php +++ b/module/task/control.php @@ -106,6 +106,8 @@ class task extends control return $this->send($response); } + if(isset($output['laneID']) and isset($output['columnID'])) $this->loadModel('kanban')->addKanbanCell($executionID, $output['laneID'], $output['columnID'], 'task', $taskID); + /* if the count of tasksID is 1 then check exists. */ if(count($tasksID) == 1) {