diff --git a/api/v1/entries/product.php b/api/v1/entries/product.php index 518936c737..0dedc42047 100644 --- a/api/v1/entries/product.php +++ b/api/v1/entries/product.php @@ -120,7 +120,7 @@ class productEntry extends Entry if(isset($data->result) and $data->result == 'fail') return $this->sendError(400, $data->message); $product = $this->product->getByID($productID); - $this->send(200, $this->format($product, 'createdDate:time')); + $this->send(200, $this->format($product, 'createdDate:time,whitelist:userList,createdBy:user,PO:user,RD:user,QD:user')); } /** diff --git a/db/standard/zentao17.5.sql b/db/standard/zentao17.5.sql index 71e49578e5..2473991ba5 100644 --- a/db/standard/zentao17.5.sql +++ b/db/standard/zentao17.5.sql @@ -1182,11 +1182,14 @@ CREATE TABLE `zt_im_chat` ( `ownedBy` varchar(30) NOT NULL DEFAULT '', `editedBy` varchar(30) NOT NULL DEFAULT '', `editedDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', + `mergedDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `lastActiveTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `lastMessage` int(11) unsigned NOT NULL DEFAULT '0', `lastMessageIndex` int(11) unsigned NOT NULL DEFAULT 0, `dismissDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `pinnedMessages` text NOT NULL, + `mergedChats` text NOT NULL DEFAULT '', + `adminInvite` enum('0','1') NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `gid` (`gid`), KEY `name` (`name`), diff --git a/db/update17.4.sql b/db/update17.4.sql index d9c9bd8089..ea16cfb615 100644 --- a/db/update17.4.sql +++ b/db/update17.4.sql @@ -14,16 +14,6 @@ ALTER TABLE `zt_testtask` ADD `createdDate` datetime NOT NULL AFTER `createdBy`; ALTER TABLE `zt_build` ADD `createdBy` varchar(30) NOT NULL AFTER `desc`; ALTER TABLE `zt_build` ADD `createdDate` datetime NOT NULL AFTER `createdBy`; -INSERT IGNORE INTO `zt_workflowfield` (`module`, `field`, `type`, `length`, `name`, `control`, `expression`, `options`, `default`, `rules`, `placeholder`, `order`, `searchOrder`, `exportOrder`, `canExport`, `canSearch`, `isValue`, `readonly`, `buildin`, `role`, `desc`, `createdBy`, `createdDate`, `editedBy`, `editedDate`) VALUES -('testtask', 'createdBy', 'varchar', '30', '由谁创建', 'select', '', 'user', '', '', '', 393, 0, 0, '0', '0', '0', '1', 1, 'buildin', '', '', '2022-08-02 14:49', '', '0000-00-00 00:00:00'), -('testtask', 'createdDate', 'datetime', '', '创建时间', 'datetime', '', '', '', '', '', 394, 0, 0, '0', '0', '0', '1', 1, 'buildin', '', '', '2022-08-02 14:49', '', '0000-00-00 00:00:00'), -('productplan', 'createdBy', 'varchar', '30', '由谁创建', 'select', '', 'user', '', '', '', 11, 0, 0, '0', '0', '0', '1', 1, 'buildin', '', '', '2022-08-02 14:49', '', '0000-00-00 00:00:00'), -('productplan', 'createdDate', 'datetime', '', '创建时间', 'datetime', '', '', '', '', '', 12, 0, 0, '0', '0', '0', '1', 1, 'buildin', '', '', '2022-08-02 14:49', '', '0000-00-00 00:00:00'), -('build', 'createdBy', 'varchar', '30', '由谁创建', 'select', '', 'user', '', '', '', 15, 0, 0, '0', '0', '0', '1', 1, 'buildin', '', '', '2022-08-02 14:49', '', '0000-00-00 00:00:00'), -('build', 'createdDate', 'datetime', '', '创建时间', 'datetime', '', '', '', '', '', 16, 0, 0, '0', '0', '0', '1', 1, 'buildin', '', '', '2022-08-02 14:49', '', '0000-00-00 00:00:00'), -('release', 'createdBy', 'varchar', '30', '由谁创建', 'select', '', 'user', '', '', '', 14, 0, 0, '0', '0', '0', '1', 1, 'buildin', '', '', '2022-08-02 14:49', '', '0000-00-00 00:00:00'), -('release', 'createdDate', 'datetime', '', '创建时间', 'datetime', '', '', '', '', '', 15, 0, 0, '0', '0', '0', '1', 1, 'buildin', '', '', '2022-08-02 14:49', '', '0000-00-00 00:00:00'); - UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackType' ORDER BY `id` DESC LIMIT 1) WHERE `module`='feedback' AND `field`='type'; UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackSolution' ORDER BY `id` DESC LIMIT 1) WHERE `module`='feedback' AND `field`='solution'; UPDATE `zt_workflowfield` SET `options`=(SELECT id FROM `zt_workflowdatasource` WHERE `code`='feedbackclosedReason' ORDER BY `id` DESC LIMIT 1), `control`='select' WHERE `module`='feedback' AND `field`='closedReason'; @@ -32,8 +22,42 @@ UPDATE `zt_project` SET `closedDate`='' AND `closedBy`='' WHERE `status` != 'clo UPDATE `zt_grouppriv` SET `method`='exportTemplate' WHERE `method` = 'exportTemplet'; -INSERT IGNORE INTO `zt_workflowaction` (`module`, `action`, `method`, `name`, `type`, `batchMode`, `extensionType`, `open`, `position`, `layout`, `show`, `buildin`, `role`, `createdBy`, `createdDate`) VALUES -('bug', 'batchactivate', 'batchoperate', '批量激活', 'batch', 'different', 'none', 'normal', 'browse', 'normal', 'direct', '1', 'buildin', '', '2022-08-09 15:52'); - INSERT INTO `zt_grouppriv` (SELECT `group`,`module`,'reply' FROM `zt_grouppriv` WHERE `module` = 'feedback' AND `method` = 'comment'); INSERT INTO `zt_grouppriv` (SELECT `group`,`module`,'ask' FROM `zt_grouppriv` WHERE `module` = 'feedback' AND `method` = 'comment'); + +CREATE TABLE `zt_chart` ( + `id` mediumint NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL, + `type` varchar(30) NOT NULL, + `dataset` varchar(30) NOT NULL, + `desc` mediumtext NOT NULL, + `settings` mediumtext NOT NULL, + `filters` mediumtext NOT NULL, + `createdBy` char(30) NOT NULL, + `createdDate` datetime NOT NULL, + `deleted` tinyint NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `zt_dashboard` ( + `id` mediumint(8) NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL, + `module` mediumint NOT NULL, + `desc` mediumtext NOT NULL, + `layout` mediumtext NOT NULL, + `filters` mediumtext NOT NULL, + `createdBy` varchar(30) NOT NULL, + `createdDate` datetime NOT NULL, + `deleted` tinyint NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `zt_dataset` ( + `id` mediumint unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(155) NOT NULL, + `sql` text NOT NULL, + `fields` mediumtext NOT NULL, + `objects` mediumtext NOT NULL, + `createdBy` varchar(30) NOT NULL, + `createdDate` datetime NOT NULL, + `deleted` tinyint NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/db/zentao.sql b/db/zentao.sql index 480cd2091d..af143057e9 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -424,6 +424,20 @@ CREATE TABLE IF NOT EXISTS `zt_cfd` ( `date` date NOT NULL, UNIQUE KEY `execution_type_name_date` (`execution`,`type`,`name`,`date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- DROP TABLE IF EXISTS `zt_chart`; +CREATE TABLE `zt_chart` ( + `id` mediumint NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL, + `type` varchar(30) NOT NULL, + `dataset` varchar(30) NOT NULL, + `desc` mediumtext NOT NULL, + `settings` mediumtext NOT NULL, + `filters` mediumtext NOT NULL, + `createdBy` char(30) NOT NULL, + `createdDate` datetime NOT NULL, + `deleted` tinyint NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_company`; CREATE TABLE IF NOT EXISTS `zt_company` ( `id` mediumint(8) unsigned NOT NULL auto_increment, @@ -486,6 +500,31 @@ CREATE TABLE IF NOT EXISTS `zt_cron` ( PRIMARY KEY (`id`), KEY `lastTime` (`lastTime`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- DROP TABLE IF EXISTS `zt_dashboard`; +CREATE TABLE `zt_dashboard` ( + `id` mediumint(8) NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL, + `module` mediumint NOT NULL, + `desc` mediumtext NOT NULL, + `layout` mediumtext NOT NULL, + `filters` mediumtext NOT NULL, + `createdBy` varchar(30) NOT NULL, + `createdDate` datetime NOT NULL, + `deleted` tinyint NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- DROP TABLE IF EXISTS `zt_dataset`; +CREATE TABLE `zt_dataset` ( + `id` mediumint unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(155) NOT NULL, + `sql` text NOT NULL, + `fields` mediumtext NOT NULL, + `objects` mediumtext NOT NULL, + `createdBy` varchar(30) NOT NULL, + `createdDate` datetime NOT NULL, + `deleted` tinyint NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- DROP TABLE IF EXISTS `zt_dept`; CREATE TABLE IF NOT EXISTS `zt_dept` ( `id` mediumint(8) unsigned NOT NULL auto_increment, diff --git a/doc/CHANGELOG b/doc/CHANGELOG index 0f4a2980a3..f701b65279 100644 --- a/doc/CHANGELOG +++ b/doc/CHANGELOG @@ -76,11 +76,17 @@ 35939 密码难度规则优化 企业版: 6130 甘特图支持拖拽设置任务的起止日期 +7742 反馈模块动作设计增加回复和追问动作 +8252 动作界面只读字段设置默认值,创建的时候写入到数据库 +9004 数据校验取消校验按钮交互优化 33993 甘特图样式优化 34482 新增反馈编辑他人反馈的权限 35082 执行甘特图,增加任务顺序的拖动排序功能 35857 反馈列表转用户需求icon更换 35933 执行甘特图的持续天数改成工期 +35236 在执行需求列表的搜索条件中可以搜索工作流的需求流程中新增的字段 +35699 bug模块动作设计增加批量激活的动作 +35802 工作流自定义流程,保存成功的提示交互优化 旗舰版: 35836 项目问题列表中优先级字段居中显示 35837 项目问题列表“优先级”字段修改为“P” @@ -104,6 +110,24 @@ 35217 复制项目,阶段信息确认页面增加阶段选择弹窗 35218 复制项目的交互样式优化 35310 复制项目增加团队成员与权限复制 +36036 关闭审批后停用发起动作,再次开启审批未自动启用动作 +禅道客户端: +34119 一键包集成喧喧网页端 +34460 优化会话中禅道链接卡片的跳转交互 +34667 完善XXD命令行应用给出的提示 +34668 修改docker入口脚本,确保owt中的rabbitmq正常启动 +34669 服务器地址不正确导致客户端登录失败后,尝试去掉路径后进行重试 +34670 完善音视频服务器端口配置和提示 +34671 优化音视频服务配置中“是否启用HTTPS”的设置 +34672 设计并增加离线部署SRS音视频的方案 +34673 没有麦克风时允许加入会议 +34848 解决服务器时间和客户端时间不一样的问题 +35087 研究喧喧和其他应用系统的多页面集成 +35088 删除服务器聊天记录的功能 +35268 通过服务端下载客户端后,登录时带入服务端地址 +35280 实现自动清理解散90天以上群数据的功能 +35294 后台检查XXC是否有新版时去掉XXB的版本判断 +35297 网络诊断时给出具体提示以引导用户 修复的Bug 22662 执行任务列表父子任务显示错乱 24608 英文下批量编辑执行页面执行状态名称显示不全 @@ -113,6 +137,19 @@ 25837 产品-计划的需求列表没有展示需求标题颜色 25851 导入任务相关研发需求详情弹窗中样式问题 25282 导入用户时,左右滚动条必须拖动到底部才显示 +25019 需要测试再进行详细确认:xxd以windows服务的形式启动(注意是在windows管理的服务里面点击启动),日志会存在C:\Windows\System32\log下 +25273 禅道卡片中的弹窗不展示 +25390 一张图片发送多人再撤回其中一张图,在其他窗口中图片显示已撤回 +25402 sendChatMessage返回值有问题 +25427 提示升级页面不显示了 +25526 后台没有被禁用的用户登录客户端时提示“账号被禁用” +25603 喧喧一键安装包安装xxd错误 +25605 独立消息记录窗口中链接打不开 +25622 连续发送消息不给提示 +25628 客户端链接转任务跳转到地盘 +25630 消息记录点击两次喧喧直接崩溃了 +25644 产品计划卡片没显示内容 +25646 禅道客户端一、口、x遮挡成员按钮 2022-07-27 17.4 完成的需求 @@ -206,6 +243,11 @@ 34795 项目甘特图可以在阶段或任务前增加图标显示状态 34742 项目甘特图中没有起止日期的任务的时间显示为所属阶段时间 34729 QA质量保证计划可以批量编辑 +35424 产品计划增加审批设置 +35437 内置模块显示审批进度。 +35438 内置模块增加待我审批标签 +35596 产品发布增加审批设置 +35597 测试单增加审批设置 禅道客户端: 34124 XXD可以从XXB主动拉取配置 34123 喧喧增加禅道的checktable.php以便自动修复数据库 diff --git a/extension/lite/common/ext/lang/zh-cn/lite.php b/extension/lite/common/ext/lang/zh-cn/lite.php index 91cf62d7ba..69a02f326e 100644 --- a/extension/lite/common/ext/lang/zh-cn/lite.php +++ b/extension/lite/common/ext/lang/zh-cn/lite.php @@ -198,11 +198,11 @@ $lang->admin->menu->dev['menuOrder'][20] = 'entry'; $lang->admin->menu->system['subMenu'] = new stdclass(); $lang->admin->menu->system['subMenu']->backup = array('link' => "{$lang->backup->common}|backup|index"); +$lang->admin->menu->system['subMenu']->trash = array('link' => "{$lang->action->trash}|action|trash"); $lang->admin->menu->system['subMenu']->safe = array('link' => "$lang->security|admin|safe", 'alias' => 'checkweak'); $lang->admin->menu->system['subMenu']->cron = array('link' => "{$lang->admin->cron}|cron|index", 'subModule' => 'cron'); $lang->admin->menu->system['subMenu']->timezone = array('link' => "$lang->timezone|custom|timezone"); $lang->admin->menu->system['subMenu']->buildIndex = array('link' => "{$lang->admin->buildIndex}|search|buildindex|"); -$lang->admin->menu->system['subMenu']->trash = array('link' => "{$lang->action->trash}|action|trash"); if($config->visions == ',lite,' and $config->edition != 'open') $lang->admin->menu->system['subMenu']->license = array('link' => "授权信息|admin|license'", 'alias' => 'license'); if($config->visions != ',lite,') unset($lang->admin->menu->system['subMenu']->buildIndex); diff --git a/extension/lite/group/ext/lang/resource.php b/extension/lite/group/ext/lang/resource.php index ec5c6714a9..d5eff6b70c 100644 --- a/extension/lite/group/ext/lang/resource.php +++ b/extension/lite/group/ext/lang/resource.php @@ -551,7 +551,7 @@ $lang->resource->task->recordEstimate = 'recordEstimateAction'; $lang->resource->task->editEstimate = 'editEstimate'; $lang->resource->task->deleteEstimate = 'deleteEstimate'; $lang->resource->task->report = 'reportChart'; -if($config->edition != 'open') $lang->resource->task->exportTemplet = 'exportTemplet'; +if($config->edition != 'open') $lang->resource->task->exportTemplate = 'exportTemplate'; if($config->edition != 'open') $lang->resource->task->import = 'import'; $lang->task->methodOrder[5] = 'create'; @@ -577,7 +577,7 @@ $lang->task->methodOrder[100] = 'editEstimate'; $lang->task->methodOrder[105] = 'deleteEstimate'; $lang->task->methodOrder[110] = 'report'; $lang->task->methodOrder[115] = 'batchChangeModule'; -$lang->task->methodOrder[120] = 'exportTemplet'; +$lang->task->methodOrder[120] = 'exportTemplate'; $lang->task->methodOrder[125] = 'import'; /* Doc. */ diff --git a/extension/lite/story/ext/config/lite.php b/extension/lite/story/ext/config/lite.php index 25b7dc223f..642eaa16fc 100644 --- a/extension/lite/story/ext/config/lite.php +++ b/extension/lite/story/ext/config/lite.php @@ -1,5 +1,5 @@ story->list->exportFields = ' +$config->story->exportFields = ' id, module, title, spec, keywords, pri, estimate, status, openedBy, openedDate, assignedTo, assignedDate, mailto, diff --git a/extension/lite/workflow/ext/view/ui.flow.html.hook.php b/extension/lite/workflow/ext/view/ui.flow.html.hook.php new file mode 100644 index 0000000000..c7a346d076 --- /dev/null +++ b/extension/lite/workflow/ext/view/ui.flow.html.hook.php @@ -0,0 +1,11 @@ +visions == ',lite,'):?> +dao->select('id')->from(TABLE_WORKFLOWDATASOURCE)->where('code')->like('litefeedback%')->andWhere('vision')->eq('lite')->fetchPairs('id', 'id');?> + + + + diff --git a/module/action/lang/de.php b/module/action/lang/de.php index 7e0ee16529..e92cc40c4c 100644 --- a/module/action/lang/de.php +++ b/module/action/lang/de.php @@ -245,10 +245,6 @@ $lang->action->desc->linkbug = '$date, $actor link bugs action->desc->unlinkstory = '$date, $actor remove stories $extra from plan.' . "\n"; $lang->action->desc->unlinkbug = '$date, $actor remove bugs $extra from plan.' . "\n"; -/* Used to describe the historical operation records of gantt. */ -$lang->action->desc->ganttdrag = '$date, $actor tasks dragged $extra.' . "\n"; -$lang->action->desc->ganttmove = '$date, $actor tasks sorted $extra.' . "\n"; - /* Used to display dynamic information. */ $lang->action->label = new stdclass(); $lang->action->label->install = 'install '; @@ -386,7 +382,6 @@ $lang->action->label->unlinkstory = 'unlink stories from'; $lang->action->label->unlinkbug = 'unlink bugs from'; $lang->action->label->tolib = 'imported'; $lang->action->label->updatetolib = 'updated'; -$lang->action->label->ganttdrag = 'dragged'; $lang->action->label->ganttmove = 'sorted'; /* Dynamic information is grouped by object. */ @@ -545,6 +540,7 @@ $lang->action->dynamicAction->task['undeleted'] = 'Restore Task'; $lang->action->dynamicAction->task['hidden'] = 'Hide Task'; $lang->action->dynamicAction->task['svncommited'] = 'SVN Commit'; $lang->action->dynamicAction->task['gitcommited'] = 'GIT Commit'; +$lang->action->dynamicAction->task['ganttmove'] = 'Order'; $lang->action->dynamicAction->build['opened'] = 'Create Build'; $lang->action->dynamicAction->build['edited'] = 'Edit Build'; diff --git a/module/action/lang/en.php b/module/action/lang/en.php index 9a2d0e1634..5d0d27fa41 100755 --- a/module/action/lang/en.php +++ b/module/action/lang/en.php @@ -245,10 +245,6 @@ $lang->action->desc->linkbug = '$date, $actor link bugs action->desc->unlinkstory = '$date, $actor remove stories $extra from plan.' . "\n"; $lang->action->desc->unlinkbug = '$date, $actor remove bugs $extra from plan.' . "\n"; -/* Used to describe the historical operation records of gantt. */ -$lang->action->desc->ganttdrag = '$date, $actor tasks dragged $extra.' . "\n"; -$lang->action->desc->ganttmove = '$date, $actor tasks sorted $extra.' . "\n"; - /* Used to display dynamic information. */ $lang->action->label = new stdclass(); $lang->action->label->install = 'install '; @@ -386,7 +382,6 @@ $lang->action->label->unlinkstory = 'unlink stories from'; $lang->action->label->unlinkbug = 'unlink bugs from'; $lang->action->label->tolib = 'imported'; $lang->action->label->updatetolib = 'updated'; -$lang->action->label->ganttdrag = 'dragged'; $lang->action->label->ganttmove = 'sorted'; /* Dynamic information is grouped by object. */ @@ -545,6 +540,7 @@ $lang->action->dynamicAction->task['undeleted'] = 'Restore Task'; $lang->action->dynamicAction->task['hidden'] = 'Hide Task'; $lang->action->dynamicAction->task['svncommited'] = 'SVN Commit'; $lang->action->dynamicAction->task['gitcommited'] = 'GIT Commit'; +$lang->action->dynamicAction->task['ganttmove'] = 'Order'; $lang->action->dynamicAction->build['opened'] = 'Create Build'; $lang->action->dynamicAction->build['edited'] = 'Edit Build'; diff --git a/module/action/lang/fr.php b/module/action/lang/fr.php index 3f9c6bc522..3efb026564 100644 --- a/module/action/lang/fr.php +++ b/module/action/lang/fr.php @@ -245,10 +245,6 @@ $lang->action->desc->linkbug = '$date, $actor link bugs action->desc->unlinkstory = '$date, $actor remove stories $extra from plan.' . "\n"; $lang->action->desc->unlinkbug = '$date, $actor remove bugs $extra from plan.' . "\n"; -/* Used to describe the historical operation records of gantt. */ -$lang->action->desc->ganttdrag = '$date, $actor tasks dragged $extra.' . "\n"; -$lang->action->desc->ganttmove = '$date, $actor tasks sorted $extra.' . "\n"; - /* Used to display dynamic information. */ $lang->action->label = new stdclass(); $lang->action->label->install = 'install '; @@ -386,7 +382,6 @@ $lang->action->label->unlinkstory = 'unlink stories from'; $lang->action->label->unlinkbug = 'unlink bugs from'; $lang->action->label->tolib = 'Importé'; $lang->action->label->updatetolib = 'MàJ'; -$lang->action->label->ganttdrag = 'dragged'; $lang->action->label->ganttmove = 'sorted'; /* Dynamic information is grouped by object. */ @@ -545,6 +540,7 @@ $lang->action->dynamicAction->task['undeleted'] = 'Restaurer Tâche'; $lang->action->dynamicAction->task['hidden'] = 'Masquer Tâche'; $lang->action->dynamicAction->task['svncommited'] = 'Committer SVN'; $lang->action->dynamicAction->task['gitcommited'] = 'Committer GIT'; +$lang->action->dynamicAction->task['ganttmove'] = 'Order'; $lang->action->dynamicAction->build['opened'] = 'Créer Build'; $lang->action->dynamicAction->build['edited'] = 'Editer Build'; diff --git a/module/action/lang/zh-cn.php b/module/action/lang/zh-cn.php index af8c1ee524..69c382104d 100755 --- a/module/action/lang/zh-cn.php +++ b/module/action/lang/zh-cn.php @@ -245,10 +245,6 @@ $lang->action->desc->linkbug = '$date, 由 $actor 关联BUG $lang->action->desc->unlinkstory = '$date, 由 $actor 从计划移除需求 $extra。' . "\n"; $lang->action->desc->unlinkbug = '$date, 由 $actor 从计划移除BUG $extra。' . "\n"; -/* 用来描述gantt chat相关操作记录。 */ -$lang->action->desc->ganttdrag = '$date, 由 $actor 拖动了任务 $extra。' . "\n"; -$lang->action->desc->ganttmove = '$date, 由 $actor 排序了任务 $extra。' . "\n"; - /* 用来显示动态信息。*/ $lang->action->label = new stdclass(); $lang->action->label->install = '安装'; @@ -386,7 +382,6 @@ $lang->action->label->unlinkstory = '移除需求从'; $lang->action->label->unlinkbug = '移除BUG从'; $lang->action->label->tolib = '导入了'; $lang->action->label->updatetolib = '更新了'; -$lang->action->label->ganttdrag = '拖动了'; $lang->action->label->ganttmove = '排序了'; /* 动态信息按照对象分组 */ @@ -545,6 +540,7 @@ $lang->action->dynamicAction->task['undeleted'] = '还原任务'; $lang->action->dynamicAction->task['hidden'] = '隐藏任务'; $lang->action->dynamicAction->task['svncommited'] = 'SVN提交'; $lang->action->dynamicAction->task['gitcommited'] = 'GIT提交'; +$lang->action->dynamicAction->task['ganttmove'] = '排序'; $lang->action->dynamicAction->build['opened'] = '创建版本'; $lang->action->dynamicAction->build['edited'] = '编辑版本'; diff --git a/module/action/model.php b/module/action/model.php index 92c83c05b4..acd67125b3 100755 --- a/module/action/model.php +++ b/module/action/model.php @@ -104,7 +104,7 @@ class actionModel extends model * * @param int $actionID * @access public - * @return void + * @return string */ public function getUnreadActions($actionID = 0) { @@ -707,6 +707,7 @@ class actionModel extends model */ public function getTrashesBySearch($objectType, $type, $queryID, $orderBy, $pager = null) { + if($objectType == 'all') return array(); if($queryID and $queryID != 'myQueryID') { $query = $this->loadModel('search')->getQuery($queryID); @@ -989,39 +990,43 @@ class actionModel extends model if($projectID == 'all') $authedProjects = (empty($aclViews) or (!empty($aclViews) and !empty($aclViews['project']))) ? $this->app->user->view->projects : '0'; if($executionID == 'all') $authedExecutions = (empty($aclViews) or (!empty($aclViews) and !empty($aclViews['execution']))) ? $this->app->user->view->sprints : '0'; + if(empty($authedProducts)) $authedProducts = '0'; + if($productID == 'all' and $projectID == 'all') { $productCondition = ''; - foreach(explode(',', $authedProducts) as $product) $productCondition = empty($productCondition) ? "product LIKE '%,$product,%'" : "$productCondition OR product LIKE '%,$product,%'"; + foreach(explode(',', $authedProducts) as $product) $productCondition = empty($productCondition) ? "(execution = '0' and project = '0' and (product LIKE '%,$product,%'" : "$productCondition OR product LIKE '%,$product,%'"; + $productCondition .= '))'; - $projectCondition = "project " . helper::dbIN($authedProjects); - $executionCondition = isset($authedExecutions) ? "execution " . helper::dbIN($authedExecutions) : ''; + $projectCondition = "(execution = '0' and project != '0' and project " . helper::dbIN($authedProjects) . ')'; + $executionCondition = isset($authedExecutions) ? "(execution != 0 and execution " . helper::dbIN($authedExecutions) . ')' : ''; } elseif($productID == 'all' and is_numeric($projectID)) { $products = $this->loadModel('product')->getProductPairsByProject($projectID); - $executions = $this->loadModel('execution')->getPairs($projectID); + $executions = $this->loadModel('execution')->getPairs($projectID) + array(0 => 0); $authedExecutions = isset($authedExecutions) ? array_intersect(array_keys($executions), explode(',', $authedExecutions)) : array_keys($executions); $productCondition = ''; - foreach(array_keys($products) as $product) $productCondition = empty($productCondition) ? "product LIKE '%,$product,%'" : "$productCondition OR product LIKE '%,$product,%'"; + foreach(array_keys($products) as $product) $productCondition = empty($productCondition) ? "(execution = '0' and project = '0' and (product LIKE '%,$product,%'" : "$productCondition OR product LIKE '%,$product,%'"; + $productCondition .= '))'; - $projectCondition = "project = $projectID"; - $executionCondition = "execution " . helper::dbIN($authedExecutions); + $projectCondition = "(execution = '0' and project = '$projectID')"; + $executionCondition = "(execution != '0' and execution " . helper::dbIN($authedExecutions) . ')'; } elseif(is_numeric($productID) and $projectID == 'all') { $this->loadModel('product'); $projects = $this->product->getProjectPairsByProduct($productID); - $executions = $this->product->getExecutionPairsByProduct($productID); + $executions = $this->product->getExecutionPairsByProduct($productID) + array(0 => 0); $authedProjects = array_intersect(array_keys($projects), explode(',', $authedProjects)); $authedExecutions = isset($authedExecutions) ? array_intersect(array_keys($executions), explode(',', $authedExecutions)) : array_keys($executions); $productCondition = "product like '%,$productID,%'"; - $projectCondition = 'project ' . helper::dbIN($authedProjects); - $executionCondition = 'execution ' . helper::dbIN($authedExecutions); + $projectCondition = "(execution = '0' and project != '0' and project " . helper::dbIN($authedProjects) . ')'; + $executionCondition = "(execution != '0' and execution " . helper::dbIN($authedExecutions) . ')'; } $condition = "((product =',0,' or product = '0' or product=',,') AND project = '0' AND execution = '0')"; @@ -1222,17 +1227,8 @@ class actionModel extends model $relatedProjects = $relatedData['relatedProjects']; $requirements = $relatedData['requirements']; - $aclViews = isset($this->app->user->rights['acls']['views']) ? $this->app->user->rights['acls']['views'] : array(); - $authedProjects = (empty($aclViews) or (!empty($aclViews) and !empty($aclViews['project']))) ? ",{$this->app->user->view->projects}," : ''; - $authedExecutions = (empty($aclViews) or (!empty($aclViews) and !empty($aclViews['execution']))) ? ",{$this->app->user->view->sprints},": ''; - foreach($actions as $i => $action) { - if(($action->execution != '0' and strpos($authedExecutions, ",$action->execution,") === false) or ($action->execution == '0' and $action->project != '0' and strpos($authedProjects, ",$action->project,") === false)) - { - unset($actions[$i]); - continue; - } /* Add name field to the actions. */ $action->objectName = isset($objectNames[$action->objectType][$action->objectID]) ? $objectNames[$action->objectType][$action->objectID] : ''; diff --git a/module/admin/control.php b/module/admin/control.php index 0ed2c37aad..7061b75c1c 100644 --- a/module/admin/control.php +++ b/module/admin/control.php @@ -373,4 +373,84 @@ class admin extends control $this->view->title = $this->lang->admin->resetPWDSetting; $this->display(); } + + /** + * Show table engine. + * + * @access public + * @return void + */ + public function tableEngine() + { + $this->view->title = $this->lang->admin->tableEngine; + $this->view->tableEngines = $this->loadModel('misc')->getTableEngines(); + $this->display(); + } + + /** + * Ajax change table engine. + * + * @access public + * @return void + */ + public function ajaxChangeTableEngine($tableName) + { + $response = array(); + $response['result'] = 'success'; + $response['message'] = ''; + + $tableEngines = $this->loadModel('misc')->getTableEngines(); + if(!isset($tableEngines[$tableName])) + { + $response['result'] = 'fail'; + return print(json_encode($response)); + } + + if($tableEngines[$tableName] == 'InnoDB') + { + $response['message'] = sprintf($this->lang->admin->changeSuccess, $tableName); + return print(json_encode($response)); + } + + try + { + /* Check process this table or not. */ + $dbProcesses = $this->dao->query("SHOW PROCESSLIST")->fetchAll(); + foreach($dbProcesses as $dbProcess) + { + if($dbProcess->db != $this->config->db->name) continue; + if(strpos($dbProcess->Info, " {$tableName} ") !== false) + { + $response['message'] = sprintf($this->lang->upgrade->changingTable, $tableName); + return print(json_encode($response)); + } + } + } + catch(PDOException $e){} + + if(stripos($tableName, 'searchindex') !== false) + { + $mysqlVersion = $this->loadModel('install')->getMysqlVersion(); + if($mysqlVersion < 5.6) + { + $response['result'] = 'fail'; + $response['message'] = $this->lang->admin->errorInnodb; + return print(json_encode($response)); + } + } + + try + { + $sql = "ALTER TABLE `$tableName` ENGINE='InnoDB'"; + $this->dao->exec($sql); + $response['message'] = sprintf($this->lang->admin->changeSuccess, $tableName); + } + catch(PDOException $e) + { + $response['result'] = 'fail'; + $response['message'] = sprintf($this->lang->admin->changeFail, $tableName, htmlspecialchars($e->getMessage())); + } + + return print(json_encode($response)); + } } diff --git a/module/admin/lang/de.php b/module/admin/lang/de.php index f3647127a2..b498651993 100644 --- a/module/admin/lang/de.php +++ b/module/admin/lang/de.php @@ -22,6 +22,7 @@ $lang->admin->captcha = 'Bestätigungscode'; $lang->admin->getCaptcha = 'Bestätigungscode anfordern'; $lang->admin->register = 'Register'; $lang->admin->resetPWDSetting = 'Reset password Setting'; +$lang->admin->tableEngine = 'Table Engine'; $lang->admin->api = 'API'; $lang->admin->log = 'Log'; @@ -29,6 +30,15 @@ $lang->admin->setting = 'Einstellungen'; $lang->admin->days = 'Gültige Tage'; $lang->admin->resetPWDByMail = 'Reset the password via the email'; +$lang->admin->changeEngine = "Change to InnoDB"; +$lang->admin->changingTable = 'Replacing data table %s engine...'; +$lang->admin->changeSuccess = 'The data table %s engine has been changed to InnoDB.'; +$lang->admin->changeFail = "Failed to replace table %s engine. Reason: %s。"; +$lang->admin->errorInnodb = 'Your MySQL does not support InnoDB data table engine.'; +$lang->admin->engineInfo = "The %s table engine is %s."; +$lang->admin->engineSummary['hasMyISAM'] = "There are %s tables that are not InnoDB engines"; +$lang->admin->engineSummary['allInnoDB'] = "All tables are InnoDB engines"; + $lang->admin->info = new stdclass(); $lang->admin->info->version = 'Aktuelle Version ist %s. '; $lang->admin->info->links = 'You can visit links below'; diff --git a/module/admin/lang/en.php b/module/admin/lang/en.php index ae785bc4f2..c850026926 100644 --- a/module/admin/lang/en.php +++ b/module/admin/lang/en.php @@ -22,6 +22,7 @@ $lang->admin->captcha = 'Verification Code'; $lang->admin->getCaptcha = 'Send Verification Code'; $lang->admin->register = 'Register'; $lang->admin->resetPWDSetting = 'Reset password Setting'; +$lang->admin->tableEngine = 'Table Engine'; $lang->admin->api = 'API'; $lang->admin->log = 'Log'; @@ -29,6 +30,15 @@ $lang->admin->setting = 'Setting'; $lang->admin->days = 'Valid Day'; $lang->admin->resetPWDByMail = 'Reset the password via the email'; +$lang->admin->changeEngine = "Change to InnoDB"; +$lang->admin->changingTable = 'Replacing data table %s engine...'; +$lang->admin->changeSuccess = 'The data table %s engine has been changed to InnoDB.'; +$lang->admin->changeFail = "Failed to replace table %s engine. Reason: %s。"; +$lang->admin->errorInnodb = 'Your MySQL does not support InnoDB data table engine.'; +$lang->admin->engineInfo = "The %s table engine is %s."; +$lang->admin->engineSummary['hasMyISAM'] = "There are %s tables that are not InnoDB engines"; +$lang->admin->engineSummary['allInnoDB'] = "All tables are InnoDB engines"; + $lang->admin->info = new stdclass(); $lang->admin->info->version = 'Current Version is %s. '; $lang->admin->info->links = 'You can visit links below'; diff --git a/module/admin/lang/fr.php b/module/admin/lang/fr.php index f3bb4993ad..a7749f2a4b 100644 --- a/module/admin/lang/fr.php +++ b/module/admin/lang/fr.php @@ -22,6 +22,7 @@ $lang->admin->captcha = 'Code de vérification'; $lang->admin->getCaptcha = 'Obtenir le Code de vérification'; $lang->admin->register = 'Register'; $lang->admin->resetPWDSetting = 'Reset password Setting'; +$lang->admin->tableEngine = 'Table Engine'; $lang->admin->api = 'API'; $lang->admin->log = 'Log'; @@ -29,6 +30,15 @@ $lang->admin->setting = 'Paramétrage'; $lang->admin->days = 'Durée de conservation'; $lang->admin->resetPWDByMail = 'Reset the password via the email'; +$lang->admin->changeEngine = "Change to InnoDB"; +$lang->admin->changingTable = 'Replacing data table %s engine...'; +$lang->admin->changeSuccess = 'The data table %s engine has been changed to InnoDB.'; +$lang->admin->changeFail = "Failed to replace table %s engine. Reason: %s。"; +$lang->admin->errorInnodb = 'Your MySQL does not support InnoDB data table engine.'; +$lang->admin->engineInfo = "The %s table engine is %s."; +$lang->admin->engineSummary['hasMyISAM'] = "There are %s tables that are not InnoDB engines"; +$lang->admin->engineSummary['allInnoDB'] = "All tables are InnoDB engines"; + $lang->admin->info = new stdclass(); $lang->admin->info->version = 'La version actuelle est %s customisée. '; $lang->admin->info->links = 'Vous pouvez visiter les liens ci-dessous'; diff --git a/module/admin/lang/zh-cn.php b/module/admin/lang/zh-cn.php index f07908c47e..10d8a111a6 100644 --- a/module/admin/lang/zh-cn.php +++ b/module/admin/lang/zh-cn.php @@ -22,6 +22,7 @@ $lang->admin->captcha = '验证码'; $lang->admin->getCaptcha = '获取验证码'; $lang->admin->register = '登记'; $lang->admin->resetPWDSetting = '重置密码设置'; +$lang->admin->tableEngine = '表引擎'; $lang->admin->api = '接口'; $lang->admin->log = '日志'; @@ -29,6 +30,15 @@ $lang->admin->setting = '设置'; $lang->admin->days = '日志保存天数'; $lang->admin->resetPWDByMail = '通过邮箱重置密码'; +$lang->admin->changeEngine = "更换到InnoDB"; +$lang->admin->changingTable = '正在更换数据表%s引擎...'; +$lang->admin->changeSuccess = '已经更换数据表%s引擎为InnoDB。'; +$lang->admin->changeFail = "更换数据表%s引擎失败,原因:%s。"; +$lang->admin->errorInnodb = '您当前的数据库不支持使用InnoDB数据表引擎。'; +$lang->admin->engineInfo = "表%s的引擎是%s。"; +$lang->admin->engineSummary['hasMyISAM'] = "有%s个表不是InnoDB引擎"; +$lang->admin->engineSummary['allInnoDB'] = "所有的表都是InnoDB引擎了"; + $lang->admin->info = new stdclass(); $lang->admin->info->version = '当前系统的版本是%s,'; $lang->admin->info->links = '您可以访问以下链接:'; diff --git a/module/admin/view/tableengine.html.php b/module/admin/view/tableengine.html.php new file mode 100644 index 0000000000..32d83293de --- /dev/null +++ b/module/admin/view/tableengine.html.php @@ -0,0 +1,92 @@ + + * @package admin + * @version $Id$ + * @link http://www.zentao.net + */ +?> + +
+
+ $engine) + { + if($engine != 'InnoDB') $MyISAMCount ++; + $engineListHtml .= "
  • " . sprintf($lang->admin->engineInfo, $tableName, $engine) . "
  • \n"; + } + ?> +

    + 0):?> + admin->engineSummary['hasMyISAM'], $MyISAMCount);?> + admin->changeEngine, '', "class='btn btn-sm changeEngine btn-primary' onclick='changeAllEngines()'");?> + + admin->engineSummary['allInnoDB']);?> + +

    +
    +
    +
    +
    +
    +admin->changingTable);?> + + diff --git a/module/block/model.php b/module/block/model.php index 3af1f79593..a01977547f 100644 --- a/module/block/model.php +++ b/module/block/model.php @@ -254,6 +254,8 @@ class blockModel extends model */ public function initBlock($module, $type = '') { + if(empty($module)) return; + $flow = isset($this->config->global->flow) ? $this->config->global->flow : 'full'; $account = $this->app->user->account; $vision = $this->config->vision; @@ -507,7 +509,7 @@ class blockModel extends model $this->app->loadLang('project'); $params = new stdclass(); $params->type['name'] = $this->lang->block->type; - $params->type['options'] = $this->lang->project->featureBar; + $params->type['options'] = $this->lang->project->featureBar['browse']; $params->type['control'] = 'select'; $params->orderBy['name'] = $this->lang->block->orderBy; @@ -969,11 +971,10 @@ class blockModel extends model /** * Get project dynamic params. * - * @param string $module * @access public * @return string */ - public function getProjectDynamicParams($module = '') + public function getProjectDynamicParams() { $params = $this->appendCountParams(); diff --git a/module/bug/config.php b/module/bug/config.php index d5aec06e9e..a826f3b23f 100644 --- a/module/bug/config.php +++ b/module/bug/config.php @@ -303,12 +303,13 @@ $config->bug->datatable->fieldList['openedBuild']['fixed'] = 'no'; $config->bug->datatable->fieldList['openedBuild']['width'] = '120'; $config->bug->datatable->fieldList['openedBuild']['required'] = 'no'; $config->bug->datatable->fieldList['openedBuild']['control'] = 'multiple'; -$config->bug->datatable->fieldList['openedBuild']['dataSource'] = array('module' => 'bug', 'method' =>'getRelatedObjects', 'params' => 'openedBuild&id,name'); +$config->bug->datatable->fieldList['openedBuild']['dataSource'] = array('module' => 'build', 'method' =>'getBuildPairs', 'params' => '$productID&$branch&noempty,noterminate,nodone,withbranch'); $config->bug->datatable->fieldList['assignedTo']['title'] = 'assignedToAB'; $config->bug->datatable->fieldList['assignedTo']['fixed'] = 'no'; $config->bug->datatable->fieldList['assignedTo']['width'] = '120'; $config->bug->datatable->fieldList['assignedTo']['required'] = 'no'; +$config->bug->datatable->fieldList['assignedTo']['dataSource'] = array('module' => 'bug', 'method' =>'getProductMemberPairs', 'params' => '$productID&$branch'); $config->bug->datatable->fieldList['assignedDate']['title'] = 'assignedDate'; $config->bug->datatable->fieldList['assignedDate']['fixed'] = 'no'; diff --git a/module/bug/model.php b/module/bug/model.php index 0fd2be8ff9..a4a577b156 100644 --- a/module/bug/model.php +++ b/module/bug/model.php @@ -3607,8 +3607,7 @@ class bugModel extends model if($table) $relatedObjects = $this->dao->select($pairs)->from($table)->where('id')->in($relatedObjectIdList)->fetchPairs(); if(in_array($object, array('build','resolvedBuild'))) $relatedObjects= array('trunk' => $this->lang->trunk) + $relatedObjects; - - return $relatedObjects; + return array('' => '', 0 => '') + $relatedObjects; } /** diff --git a/module/common/lang/de.php b/module/common/lang/de.php index 9cd57439b5..d2113a3e89 100644 --- a/module/common/lang/de.php +++ b/module/common/lang/de.php @@ -288,11 +288,12 @@ $lang->devops->rules = 'Rule'; $lang->devops->settings = 'Setting Merge Request'; $lang->devops->set = 'Set'; -$lang->admin->system = 'System'; -$lang->admin->entry = 'Application'; -$lang->admin->data = 'Data'; -$lang->admin->cron = 'Cron'; -$lang->admin->buildIndex = 'Full Text Search'; +$lang->admin->system = 'System'; +$lang->admin->entry = 'Application'; +$lang->admin->data = 'Data'; +$lang->admin->cron = 'Cron'; +$lang->admin->buildIndex = 'Full Text Search'; +$lang->admin->tableEngine = 'Table Engine'; $lang->convert->importJira = 'Import Jira'; diff --git a/module/common/lang/en.php b/module/common/lang/en.php index e8022f9f17..d8390243ce 100644 --- a/module/common/lang/en.php +++ b/module/common/lang/en.php @@ -288,11 +288,12 @@ $lang->devops->rules = 'Rule'; $lang->devops->settings = 'Setting Merge Request'; $lang->devops->set = 'Set'; -$lang->admin->system = 'System'; -$lang->admin->entry = 'Application'; -$lang->admin->data = 'Data'; -$lang->admin->cron = 'Cron'; -$lang->admin->buildIndex = 'Full Text Search'; +$lang->admin->system = 'System'; +$lang->admin->entry = 'Application'; +$lang->admin->data = 'Data'; +$lang->admin->cron = 'Cron'; +$lang->admin->buildIndex = 'Full Text Search'; +$lang->admin->tableEngine = 'Table Engine'; $lang->convert->importJira = 'Import Jira'; diff --git a/module/common/lang/fr.php b/module/common/lang/fr.php index d291be8c95..67caf6b5fd 100644 --- a/module/common/lang/fr.php +++ b/module/common/lang/fr.php @@ -288,11 +288,12 @@ $lang->devops->rules = 'Rule'; $lang->devops->settings = 'Setting Merge Request'; $lang->devops->set = 'Set'; -$lang->admin->system = 'System'; -$lang->admin->entry = 'Application'; -$lang->admin->data = 'Data'; -$lang->admin->cron = 'Cron'; -$lang->admin->buildIndex = 'Full Text Search'; +$lang->admin->system = 'System'; +$lang->admin->entry = 'Application'; +$lang->admin->data = 'Data'; +$lang->admin->cron = 'Cron'; +$lang->admin->buildIndex = 'Full Text Search'; +$lang->admin->tableEngine = 'Table Engine'; $lang->convert->importJira = 'Import Jira'; diff --git a/module/common/lang/menu.php b/module/common/lang/menu.php index f4da4b6005..1327985178 100644 --- a/module/common/lang/menu.php +++ b/module/common/lang/menu.php @@ -568,6 +568,7 @@ $lang->admin->menu->system['subMenu']->safe = array('link' => "$lang->sec $lang->admin->menu->system['subMenu']->cron = array('link' => "{$lang->admin->cron}|cron|index", 'subModule' => 'cron'); $lang->admin->menu->system['subMenu']->timezone = array('link' => "$lang->timezone|custom|timezone"); $lang->admin->menu->system['subMenu']->buildIndex = array('link' => "{$lang->admin->buildIndex}|search|buildindex|"); +$lang->admin->menu->system['subMenu']->tableEngine = array('link' => "{$lang->admin->tableEngine}|admin|tableengine|"); if(version_compare(phpversion(), 5.6) > 0) $lang->admin->menu->system['subMenu']->convertJira = array('link' => "{$lang->convert->importJira}|convert|convertjira|", 'subModule' => 'convert'); $lang->admin->dividerMenu = ',company,message,system,'; diff --git a/module/common/lang/zh-cn.php b/module/common/lang/zh-cn.php index eb4cc5bf63..a27488d59e 100644 --- a/module/common/lang/zh-cn.php +++ b/module/common/lang/zh-cn.php @@ -288,11 +288,12 @@ $lang->devops->rules = '指令'; $lang->devops->settings = '合并请求设置'; $lang->devops->set = '设置'; -$lang->admin->system = '系统'; -$lang->admin->entry = '应用'; -$lang->admin->data = '数据'; -$lang->admin->cron = '定时'; -$lang->admin->buildIndex = '重建索引'; +$lang->admin->system = '系统'; +$lang->admin->entry = '应用'; +$lang->admin->data = '数据'; +$lang->admin->cron = '定时'; +$lang->admin->buildIndex = '重建索引'; +$lang->admin->tableEngine = '表引擎'; $lang->convert->importJira = '导入Jira数据'; diff --git a/module/doc/lang/de.php b/module/doc/lang/de.php index 1bda5ad37e..285060e931 100644 --- a/module/doc/lang/de.php +++ b/module/doc/lang/de.php @@ -154,6 +154,7 @@ $lang->doc->allCollections = 'All Collections'; $lang->doc->keywordsTips = 'Please use commas to separate multiple keywords.'; $lang->doc->sortLibs = 'Sort Libs'; $lang->doc->titlePlaceholder = 'Please enter the title'; +$lang->doc->confirm = 'Confirm'; global $config; /* Query condition list. */ diff --git a/module/doc/lang/en.php b/module/doc/lang/en.php index b719793600..db444b059f 100644 --- a/module/doc/lang/en.php +++ b/module/doc/lang/en.php @@ -154,6 +154,7 @@ $lang->doc->allCollections = 'All Collections'; $lang->doc->keywordsTips = 'Please use commas to separate keywords.'; $lang->doc->sortLibs = 'Sort Libs'; $lang->doc->titlePlaceholder = 'Please enter the title'; +$lang->doc->confirm = 'Confirm'; global $config; /* Query condition list. */ diff --git a/module/doc/lang/fr.php b/module/doc/lang/fr.php index f544dd2113..cb11214407 100644 --- a/module/doc/lang/fr.php +++ b/module/doc/lang/fr.php @@ -154,6 +154,7 @@ $lang->doc->allCollections = 'All Collections'; $lang->doc->keywordsTips = 'Please use commas to separate multiple keywords.'; $lang->doc->sortLibs = 'Sort Libs'; $lang->doc->titlePlaceholder = 'Veuillez saisir le titre'; +$lang->doc->confirm = 'Confirm'; global $config; /* Query condition list. */ diff --git a/module/doc/lang/zh-cn.php b/module/doc/lang/zh-cn.php index ca2ba27227..35f81e9190 100644 --- a/module/doc/lang/zh-cn.php +++ b/module/doc/lang/zh-cn.php @@ -154,6 +154,7 @@ $lang->doc->allCollections = '查看全部收藏文档'; $lang->doc->keywordsTips = '多个关键字请用逗号分隔。'; $lang->doc->sortLibs = '文档库排序'; $lang->doc->titlePlaceholder = '请输入标题'; +$lang->doc->confirm = '确认'; global $config; /* 查询条件列表 */ diff --git a/module/doc/view/createtexttype.html.php b/module/doc/view/createtexttype.html.php index b6d140b42d..af17839cb6 100644 --- a/module/doc/view/createtexttype.html.php +++ b/module/doc/view/createtexttype.html.php @@ -46,12 +46,7 @@ #noticeAcl {margin-left: 10px; vertical-align: middle;} -#moreList {display: inline-block; padding: 7px;} -#moreList .icon-more-circle {font-size: 20px;} -#moreList ul.dropdown-menu {left: -77px;} - -#backBtn {border: unset;} -#backBtn i {font-size: 20px;} +#basicInfoLink {border: unset;} .modal-title {font-size: 14px !important; font-weight: 700 !important;} @@ -64,16 +59,11 @@ - + @@ -154,7 +144,7 @@ - +
    ", $backLink, 'self', "id='backBtn'");?> ' . $lang->goback, '', "class='btn btn-secondary' id='backBtn'");?> doc->titlePlaceholder}' class='form-control' required");?> - + " . $lang->settings, '', "data-toggle='modal' id='basicInfoLink' class='btn'");?>
    close, '', "class='btn btn-primary btn-wide'");?>doc->confirm, '', "class='btn btn-primary btn-wide'");?>
    diff --git a/module/doc/view/edittexttype.html.php b/module/doc/view/edittexttype.html.php index fa3b18a86e..137a001a85 100644 --- a/module/doc/view/edittexttype.html.php +++ b/module/doc/view/edittexttype.html.php @@ -49,12 +49,7 @@ #noticeAcl {margin-left: 10px; vertical-align: middle;} -#moreList {display: inline-block; padding: 7px;} -#moreList .icon-more-circle {font-size: 20px;} -#moreList ul.dropdown-menu {left: -77px;} - -#backBtn {border: unset;} -#backBtn i {font-size: 20px;} +#basicInfoLink {border: unset;} .modal-title {font-size: 14px !important; font-weight: 700 !important;} @@ -64,20 +59,11 @@ - - - - - + @@ -155,7 +141,7 @@ - +
    ", $backLink, 'self', "id='backBtn'");?>", "id='backBtn'", '');?> " . $lang->goback, "id='backBtn'", 'btn btn-secondary');?> title, "placeholder='{$lang->doc->titlePlaceholder}' class='form-control' required");?> - + " . $lang->settings, '', "data-toggle='modal' id='basicInfoLink' class='btn'");?>
    close, '', "class='btn btn-primary btn-wide'");?>doc->confirm, '', "class='btn btn-primary btn-wide'");?>
    diff --git a/module/execution/css/common.css b/module/execution/css/common.css index 9bbba32bc3..4995381113 100644 --- a/module/execution/css/common.css +++ b/module/execution/css/common.css @@ -13,7 +13,7 @@ .table-children {border-left: 2px solid #cbd0db; border-right: 2px solid #cbd0db;} .table tbody > tr.table-children.table-child-top {border-top: 2px solid #cbd0db;} .table tbody > tr.table-children.table-child-bottom {border-bottom: 2px solid #cbd0db;} -.table td.has-child > a:not(.task-toggle) {max-width: 90%; max-width: calc(100% - 30px); display: inline-block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;} +.table td.has-child > a:not(.task-toggle) {max-width: 90%; max-width: calc(100% - 30px); display: inline-block; overflow: hidden; white-space: nowrap;} .table td.has-child > .task-toggle {color: #838a9d; position: relative; top: 1px; line-height: 16px;} .table td.has-child > .task-toggle:hover {color: #006af1; cursor: pointer;} .table td.has-child > .task-toggle > .icon {font-size: 16px; display: inline-block; transition: transform .2s; -ms-transform: rotate(-90deg); -moz-transform: rotate(-90deg); -o-transform: rotate(-90deg); -webkit-transform: rotate(-90deg); transform: rotate(-90deg);} diff --git a/module/execution/model.php b/module/execution/model.php index fc51d77ce2..8edc9a67b4 100644 --- a/module/execution/model.php +++ b/module/execution/model.php @@ -100,7 +100,7 @@ class executionModel extends model include $this->app->getModulePath('', 'execution') . 'lang/' . $this->app->getClientLang() . '.php'; } - if(isset($execution->cal) and $execution->acl != 'private') unset($this->lang->execution->menu->settings['subMenu']->whitelist); + if(isset($execution->acl) and $execution->acl != 'private') unset($this->lang->execution->menu->settings['subMenu']->whitelist); if($execution and $execution->lifetime == 'ops') { @@ -396,7 +396,7 @@ class executionModel extends model $this->dao->insert(TABLE_EXECUTION)->data($sprint) ->autoCheck($skipFields = 'begin,end') ->batchcheck($this->config->execution->create->requiredFields, 'notempty') - ->checkIF((!empty($sprint->name) and $this->config->systemMode == 'new'), 'name', 'unique', "`type` in ('sprint','stage', 'kanban') and `project` = $sprintProject and `deleted` = '0'") + ->checkIF(!empty($sprint->name), 'name', 'unique', "`type` in ('sprint','stage', 'kanban') and `project` = $sprintProject and `deleted` = '0'") ->checkIF(!empty($sprint->code), 'code', 'unique', "`type` in ('sprint','stage', 'kanban') and `deleted` = '0'") ->checkIF($sprint->begin != '', 'begin', 'date') ->checkIF($sprint->end != '', 'end', 'date') @@ -551,7 +551,7 @@ class executionModel extends model ->checkIF($execution->begin != '', 'begin', 'date') ->checkIF($execution->end != '', 'end', 'date') ->checkIF($execution->end != '', 'end', 'ge', $execution->begin) - ->checkIF((!empty($execution->name) and $this->config->systemMode == 'new'), 'name', 'unique', "id != $executionID and type in ('sprint','stage', 'kanban') and `project` = $executionProject and `deleted` = '0'") + ->checkIF(!empty($execution->name), 'name', 'unique', "id != $executionID and type in ('sprint','stage', 'kanban') and `project` = $executionProject and `deleted` = '0'") ->checkIF(!empty($execution->code), 'code', 'unique', "id != $executionID and type in ('sprint','stage', 'kanban') and `deleted` = '0'") ->checkFlow() ->where('id')->eq($executionID) diff --git a/module/execution/view/edit.html.php b/module/execution/view/edit.html.php index 97e0b3d9ad..5f98f51b32 100644 --- a/module/execution/view/edit.html.php +++ b/module/execution/view/edit.html.php @@ -23,7 +23,7 @@ arrow . ' ' . $lang->execution->edit;?> - id);?> + systemMode == 'new') echo html::hidden('project', $project->id);?>
    systemMode == 'new' and isset($project)):?> diff --git a/module/file/view/viewfiles.html.php b/module/file/view/viewfiles.html.php index a1534e45d3..9848291995 100644 --- a/module/file/view/viewfiles.html.php +++ b/module/file/view/viewfiles.html.php @@ -114,7 +114,6 @@ data: postData, success: function(data) { - console.log(data['title']); $('#fileTitle' + fileID).html("  " + data['title']); $('#renameFile' + fileID).closest('li').removeClass('hidden'); $('#renameBox' + fileID).addClass('hidden'); diff --git a/module/group/css/managemember.css b/module/group/css/managemember.css index c77de018bd..6676b72702 100644 --- a/module/group/css/managemember.css +++ b/module/group/css/managemember.css @@ -1,4 +1,5 @@ .group-item {display: block; width: 100px; float: left; margin-bottom: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: default;} -.group-item .checkbox-primary>input {cursor: pointer;} +.group-item .checkbox-primary > input {cursor: pointer;} +.group-item .checkbox-primary > label {width: 100px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden;} .table th {vertical-align: top;} -.main-table tbody>tr>td {border-bottom: 0px;} +.main-table tbody > tr > td {border-bottom: 0px;} diff --git a/module/group/lang/resource.php b/module/group/lang/resource.php index 333ecfee8e..56080b05d5 100644 --- a/module/group/lang/resource.php +++ b/module/group/lang/resource.php @@ -1632,6 +1632,7 @@ $lang->resource->admin->sso = 'ssoAction'; $lang->resource->admin->register = 'register'; $lang->resource->admin->ztCompany = 'ztCompany'; $lang->resource->admin->resetPWDSetting = 'resetPWDSetting'; +$lang->resource->admin->tableEngine = 'tableEngine'; $lang->admin->methodOrder[0] = 'index'; $lang->admin->methodOrder[5] = 'checkDB'; @@ -1641,6 +1642,7 @@ $lang->admin->methodOrder[20] = 'sso'; $lang->admin->methodOrder[25] = 'register'; $lang->admin->methodOrder[30] = 'ztCompany'; $lang->admin->methodOrder[35] = 'resetPWDSetting'; +$lang->admin->methodOrder[40] = 'tableEngine'; /* Extension. */ $lang->resource->extension = new stdclass(); diff --git a/module/index/js/index.js b/module/index/js/index.js index 5ffb7866d8..6d4f97f5f7 100644 --- a/module/index/js/index.js +++ b/module/index/js/index.js @@ -464,7 +464,6 @@ if(!notTriggerEvent) app.$app.trigger('reloadapp', app); - if(url) $(iframe.contentWindow.document.body).hide(); // Code for task #59703. if(!isSameUrl) app.$app.addClass('loading'); if(app._loadTimer) clearTimeout(app._loadTimer); app._loadTimer = setTimeout(function() diff --git a/module/kanban/view/space.html.php b/module/kanban/view/space.html.php index cd66f70129..be3ae116f3 100644 --- a/module/kanban/view/space.html.php +++ b/module/kanban/view/space.html.php @@ -50,7 +50,7 @@ desc) ? $lang->kanban->emptyDesc : str_replace("\n", '', strip_tags($space->desc));?> ]*>|]*>/';?> desc) ? $lang->kanban->emptyDesc : preg_replace($pattern, '', $space->desc);?> -

    +

    status == 'closed' ? 'disabled' : '';?> diff --git a/module/misc/lang/de.php b/module/misc/lang/de.php index 6ad68d0fc5..90115bb702 100644 --- a/module/misc/lang/de.php +++ b/module/misc/lang/de.php @@ -187,7 +187,7 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22'; $lang->misc->releaseDate['7.1.stable'] = '2015-03-07'; $lang->misc->releaseDate['6.3.stable'] = '2014-11-07'; -$lang->misc->feature->all['17.5'][] = array('title' => "Optimize ZenTao performance, the database engine is adjusted from MyISAM to InnoDB. Optimize gantt chart, the copy project of max version can copy the task and more information. Fix bugs.", 'desc' => ''); +$lang->misc->feature->all['17.5'][] = array('title' => "Provide efficient visual statistical tools. Optimize ZenTao performance, the database engine is adjusted from MyISAM to InnoDB. Gantt chart is optimized and upgraded, and the Copy items of the Max version can replicate more information. Fix bugs.", 'desc' => ''); $lang->misc->feature->all['17.4'][] = array('title' => "Optimization of details Page visualization and jumping page logic. Improvement of Kanban function. Optimization of document creating and editing pages. Fix bugs.", 'desc' => ''); $lang->misc->feature->all['17.3'][] = array('title' => "UI optimization of the modules such as statistics and background, the use case library will synchronize the function optimization information. Fix bugs.", 'desc' => ''); $lang->misc->feature->all['17.2'][] = array('title' => "Adjust the display of agile project block; optimize the UI of programs, projects and tests; optimize the detailed experience. Fix bugs.", 'desc' => ''); diff --git a/module/misc/lang/en.php b/module/misc/lang/en.php index 9efc3dd3b5..b76497cf92 100644 --- a/module/misc/lang/en.php +++ b/module/misc/lang/en.php @@ -187,7 +187,7 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22'; $lang->misc->releaseDate['7.1.stable'] = '2015-03-07'; $lang->misc->releaseDate['6.3.stable'] = '2014-11-07'; -$lang->misc->feature->all['17.5'][] = array('title' => "Optimize ZenTao performance, the database engine is adjusted from MyISAM to InnoDB. Optimize gantt chart, the copy project of max version can copy the task and more information. Fix bugs.", 'desc' => ''); +$lang->misc->feature->all['17.5'][] = array('title' => "Provide efficient visual statistical tools. Optimize ZenTao performance, the database engine is adjusted from MyISAM to InnoDB. Gantt chart is optimized and upgraded, and the Copy items of the Max version can replicate more information. Fix bugs.", 'desc' => ''); $lang->misc->feature->all['17.4'][] = array('title' => "Optimization of details Page visualization and jumping page logic. Improvement of Kanban function. Optimization of document creating and editing pages. Fix bugs.", 'desc' => ''); $lang->misc->feature->all['17.3'][] = array('title' => "UI optimization of the modules such as statistics and background, the use case library will synchronize the function optimization information. Fix bugs.", 'desc' => ''); $lang->misc->feature->all['17.2'][] = array('title' => "Adjust the display of agile project block; optimize the UI of programs, projects and tests; optimize the detailed experience. Fix bugs.", 'desc' => ''); diff --git a/module/misc/lang/fr.php b/module/misc/lang/fr.php index 2b10535179..7a70ca590f 100644 --- a/module/misc/lang/fr.php +++ b/module/misc/lang/fr.php @@ -187,7 +187,7 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22'; $lang->misc->releaseDate['7.1.stable'] = '2015-03-07'; $lang->misc->releaseDate['6.3.stable'] = '2014-11-07'; -$lang->misc->feature->all['17.5'][] = array('title' => "Optimize ZenTao performance, the database engine is adjusted from MyISAM to InnoDB. Optimize gantt chart, the copy project of max version can copy the task and more information. Fix bugs.", 'desc' => ''); +$lang->misc->feature->all['17.5'][] = array('title' => "Provide efficient visual statistical tools. Optimize ZenTao performance, the database engine is adjusted from MyISAM to InnoDB. Gantt chart is optimized and upgraded, and the Copy items of the Max version can replicate more information. Fix bugs.", 'desc' => ''); $lang->misc->feature->all['17.4'][] = array('title' => "Optimization of details Page visualization and jumping page logic. Improvement of Kanban function. Optimization of document creating and editing pages. Fix bugs.", 'desc' => ''); $lang->misc->feature->all['17.3'][] = array('title' => "UI optimization of the modules such as statistics and background, the use case library will synchronize the function optimization information. Fix bugs.", 'desc' => ''); $lang->misc->feature->all['17.2'][] = array('title' => "Adjust the display of agile project block; optimize the UI of programs, projects and tests; optimize the detailed experience. Fix bugs.", 'desc' => ''); diff --git a/module/misc/lang/zh-cn.php b/module/misc/lang/zh-cn.php index d0680416a5..1f74434ae5 100644 --- a/module/misc/lang/zh-cn.php +++ b/module/misc/lang/zh-cn.php @@ -187,7 +187,7 @@ $lang->misc->releaseDate['7.2.stable'] = '2015-05-22'; $lang->misc->releaseDate['7.1.stable'] = '2015-03-07'; $lang->misc->releaseDate['6.3.stable'] = '2014-11-07'; -$lang->misc->feature->all['17.5'][] = array('title' => '优化禅道性能,数据库引擎从MyISAM调整为InnoDB。甘特图优化升级,旗舰版的复制项目可以复制任务等更多信息。修复Bug。', 'desc' => ''); +$lang->misc->feature->all['17.5'][] = array('title' => '提供高效的可视化统计工具。优化禅道性能,数据库引擎从MyISAM调整为InnoDB。甘特图优化升级,旗舰版的复制项目可以复制任务等更多信息。修复Bug。', 'desc' => ''); $lang->misc->feature->all['17.4'][] = array('title' => '详情页面的视觉优化和部分页面跳转逻辑优化。看板功能完善。文档创建和编辑页面优化。修复Bug。', 'desc' => ''); $lang->misc->feature->all['17.3'][] = array('title' => '统计、后台等模块的UI优化,用例库同步用例信息功能优化。修复Bug。', 'desc' => ''); $lang->misc->feature->all['17.2'][] = array('title' => '调整敏捷项目区块的展示,项目集、项目和测试相关UI优化,细节体验优化。修复Bug。', 'desc' => ''); diff --git a/module/misc/model.php b/module/misc/model.php index 68ab08a1bc..739ab197e3 100644 --- a/module/misc/model.php +++ b/module/misc/model.php @@ -143,4 +143,19 @@ class miscModel extends model return $weakSites; } + + /** + * Get table and engine pairs. + * + * @access public + * @return array + */ + public function getTableEngines() + { + $tableEngines = array(); + $stmt = $this->dao->query("SHOW TABLE STATUS WHERE `Engine` is not null"); + while($table = $stmt->fetch()) $tableEngines[$table->Name] = $table->Engine; + + return $tableEngines; + } } diff --git a/module/mr/control.php b/module/mr/control.php index 59c63e1b56..6f95b6313c 100644 --- a/module/mr/control.php +++ b/module/mr/control.php @@ -122,7 +122,7 @@ class mr extends control $giteaUsers = $this->gitea->getGiteaListByAccount(); foreach($hosts as $hostID => $host) { - if($host->type == 'gitLab' and isset($gitlabUsers[$hostID])) continue; + if($host->type == 'gitlab' and isset($gitlabUsers[$hostID])) continue; if($host->type == 'gitea' and isset($giteaUsers[$hostID])) continue; unset($hosts[$hostID]); @@ -186,10 +186,10 @@ class mr extends control if(!$this->app->user->admin and $scm == 'gitlab') { $groupIDList = array(0 => 0); - $groups = $this->scm->apiGetGroups($MR->hostID, 'name_asc', 'developer'); + $groups = $this->$scm->apiGetGroups($MR->hostID, 'name_asc', 'developer'); foreach($groups as $group) $groupIDList[] = $group->id; - $sourceProject = $this->scm->apiGetSingleProject($MR->hostID, $MR->sourceProject); - $isDeveloper = $this->scm->checkUserAccess($MR->hostID, 0, $sourceProject, $groupIDList, 'developer'); + $sourceProject = $this->$scm->apiGetSingleProject($MR->hostID, $MR->sourceProject); + $isDeveloper = $this->$scm->checkUserAccess($MR->hostID, 0, $sourceProject, $groupIDList, 'developer'); if(!isset($gitUsers[$this->app->user->account]) or !$isDeveloper) return print(js::alert($this->lang->mr->errorLang[3]) . js::locate($this->createLink('mr', 'browse'))); } diff --git a/module/my/css/task.css b/module/my/css/task.css index f0f26db88a..55c85389c0 100644 --- a/module/my/css/task.css +++ b/module/my/css/task.css @@ -3,7 +3,7 @@ td.delayed {background: #e84e0f !important; color: white;} .table-children {border-left: 2px solid #cbd0db; border-right: 2px solid #cbd0db;} .table tbody > tr.table-children.table-child-top {border-top: 2px solid #cbd0db;} .table tbody > tr.table-children.table-child-bottom {border-bottom: 2px solid #cbd0db;} -.table td.has-child > a:not(.task-toggle) {max-width: 90%; max-width: calc(100% - 30px); display: inline-block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;} +.table td.has-child > a:not(.task-toggle) {max-width: 90%; max-width: calc(100% - 30px); display: inline-block; overflow: hidden; white-space: nowrap;} .table td.has-child > .task-toggle {color: #838a9d; position: relative; top: 1px; line-height: 16px;} .table td.has-child > .task-toggle:hover {color: #006af1; cursor: pointer;} .table td.has-child > .task-toggle > .icon {font-size: 16px; display: inline-block; transition: transform .2s; -ms-transform: rotate(-90deg); -moz-transform: rotate(-90deg); -o-transform: rotate(-90deg); -webkit-transform: rotate(-90deg); transform: rotate(-90deg);} diff --git a/module/port/config.php b/module/port/config.php index fc8b481765..2b6ead6da0 100644 --- a/module/port/config.php +++ b/module/port/config.php @@ -15,9 +15,12 @@ $config->port->initFunction = 'title,control,required,'; $config->port->dateFeilds = 'estStarted,realStarted,deadline,openedDate,assignedDate,finishedDate,canceledDate,closedDate,lastEditedDate,'; $config->port->datetimeFeilds = ''; $config->port->listFields = ''; -$config->port->sysLangFields = ',pri,status,type,mode,severity,os,browser,resolution,confirmed,source,reviewResult,stage,change'; +$config->port->sysLangFields = ',pri,status,type,mode,severity,os,browser,resolution,confirmed,source,reviewResult,stage,change,category'; $config->port->sysDataFields = 'execution,product,user'; -$config->port->userFields = 'assignedTo,openedBy,finishedBy,canceledBy,closedBy,lastEditedBy,lastRunner,resolvedBy'; +$config->port->userFields = 'assignedTo,openedBy,finishedBy,canceledBy,closedBy,lastEditedBy,lastRunner,resolvedBy,reviewedBy'; + +$config->port->defaultZeroField = 'severity,pri'; +$config->port->defaultEmptyField = ''; $config->port->import = new stdClass(); diff --git a/module/port/control.php b/module/port/control.php index 999282c6cd..bc8edac653 100644 --- a/module/port/control.php +++ b/module/port/control.php @@ -104,13 +104,11 @@ class port extends control $file = $this->loadModel('file')->getUpload('file'); $file = $file[0]; $shortName = $this->file->getSaveName($file['pathname']); - if(empty($shortName)) - { - die(js::alert($this->lang->excel->emptyFileName)); - } - $extension = $file['extension']; - $fileName = $this->file->savePath . $shortName; + if(empty($shortName)) die(js::alert($this->lang->excel->emptyFileName)); + + $extension = $file['extension']; + $fileName = $this->file->savePath . $shortName; move_uploaded_file($file['tmpname'], $fileName); @@ -146,9 +144,13 @@ class port extends control { $filter = ''; if($model == 'task') $filter = 'estimate'; + if($model == 'story') + { + if($this->session->storyType) $this->loadModel('story')->replaceUserRequirementLang(); + } $this->loadModel($model); - $importFields = $this->config->$model->templateFields; + $importFields = !empty($_SESSION[$model . 'TemplateFields']) ? $_SESSION[$model . 'TemplateFields'] : $this->config->$model->templateFields; $fields = $this->port->initFieldList($model, $importFields, false); $formatDatas = $this->port->format($model, $filter); $datas = $this->port->getPageDatas($formatDatas, $pagerID); @@ -184,9 +186,11 @@ class port extends control $fieldList = $this->port->initFieldList($model, $fields, false); if(empty($fieldList[$field]['values'])) $fieldList[$field]['values'] = array(); - if(!isset($fieldList[$field]['values'][''])) $fieldList[$field]['values'][''] = ''; + $multiple = $fieldList[$field]['control'] == 'multiple' ? 'multiple' : ''; - return print(html::select($field . "[$index]", $fieldList[$field]['values'], $value, "class='form-control picker-select' $multiple")); + $name = $field . "[$index]"; + if($multiple == 'multiple') $name .= "[]"; + return print(html::select($name, $fieldList[$field]['values'], $value, "class='form-control picker-select' data-field='$field' data-index='$index' $multiple")); } } diff --git a/module/port/model.php b/module/port/model.php index 3e664c4401..ffc231ee4f 100644 --- a/module/port/model.php +++ b/module/port/model.php @@ -212,6 +212,7 @@ class portModel extends model */ public function initPostFields($model = '') { + $this->commonActions($model); $datas = fixer::input('post')->get(); $objectData = array(); foreach ($datas as $field => $data) @@ -220,7 +221,7 @@ class portModel extends model { foreach($data as $key => $value) { - if(is_array($value) and array_key_exists($field, $this->config->$model->fieldList) and $this->config->$model->fieldList[$field]['control'] == 'multiple') $value = implode(',', $value); + if(is_array($value)) $value = join(',', $value); $objectData[$key][$field] = $value; } } @@ -258,7 +259,7 @@ class portModel extends model foreach ($portFieldList as $portField => $value) { $funcName = 'init' . ucfirst($portField); - if((!array_key_exists($portField, $modelFieldList)) or $portField == 'title') + if((!isset($modelFieldList[$portField])) or $portField == 'title') { $modelFieldList[$portField] = $this->portConfig->fieldList[$portField]; if(strpos($this->portConfig->initFunction, $portField) !== false) $modelFieldList[$portField] = $this->$funcName($model, $field); @@ -268,7 +269,6 @@ class portModel extends model $modelFieldList['values'] = $this->initValues($model, $field, $modelFieldList, $withKey); $fieldList[$field] = $modelFieldList; } - return $fieldList; } @@ -287,15 +287,15 @@ class portModel extends model $this->commonActions($model); if(!empty($this->modelConfig->fieldList[$field]['title'])) return $this->modelLang->{$this->modelConfig->fieldList[$field]['title']}; - if(array_key_exists($field, $this->lang->$model)) + if(isset($this->lang->$model->$field)) { $title = $this->lang->$model->$field; } - elseif(array_key_exists(($field . 'AB'), $this->lang->$model)) + elseif(isset($this->lang->$model->{$field . 'AB'})) { $title = $this->lang->$model->{$field . 'AB'}; } - elseif(array_key_exists($field, $this->lang->port->reservedWord)) + elseif(isset($this->lang->port->reservedWord[$field])) { $title = $this->lang->port->reservedWord[$field]; } @@ -313,7 +313,10 @@ class portModel extends model */ public function initControl($model, $field) { - if(isset($this->modelLang->{$field.'List'})) return 'select'; + if(isset($this->modelFieldList[$field]['control'])) return $this->modelFieldList[$field]['control']; + if(isset($this->modelLang->{$field.'List'})) return 'select'; + if(isset($this->modelFieldList[$field]['dataSource'])) return 'select'; + if(strpos($this->portConfig->sysDataFields, $field) !== false) return 'select'; return $this->portConfig->fieldList['control']; } @@ -399,58 +402,12 @@ class portModel extends model $dataList = array(); $sysDataFields = explode(',', $this->portConfig->sysDataFields); - foreach($sysDataFields as $field) - { - $dataList[$field] = $this->loadModel($field)->getPairs(); - } + + foreach($sysDataFields as $field) $dataList[$field] = $this->loadModel($field)->getPairs(); return $dataList; } - /** - * Init tmpFile. - * - * @param int $created - * @access public - * @return void - */ - public function initTmpFile($created = true) - { - $taskLang = $this->lang->task; - $file = $this->session->fileImportFileName; - $tmpPath = $this->loadModel('file')->getPathOfImportedFile(); - $tmpFile = $tmpPath . DS . md5(basename($file)); - - if(file_exists($tmpFile)) return $tmpFile; - - $rows = $this->file->getRowsFromExcel($file); - - /* Check empty.*/ - if(is_string($rows)) - { - if(file_exists($this->session->fileImportFileName)) unlink($this->session->fileImportFileName); - unset($_SESSION['fileImportFileName']); - unset($_SESSION['fileImportExtension']); - $response['result'] = 'fail'; - $response['message'] = $rows; - return $response; - } - - $fields = $this->config->task->templateFields; - array_unshift($fields, 'id'); - - foreach($fields as $key => $fieldName) - { - $fieldName = trim($fieldName); - $fields[$fieldName] = isset($taskLang->$fieldName) ? $taskLang->$fieldName : $fieldName; - unset($fields[$key]); - } - - if($created) $this->createTmpFile($tmpFile, $objectDatas); - - return $objectDatas; - } - /** * Get showImport datas. * @@ -520,7 +477,7 @@ class portModel extends model */ public function getSourceByModuleMethod($model, $module, $method, $params = '', $pairs = '') { - $getParams = $this->session->{$model.'PortParams'}; + $getParams = $this->session->{$model . 'PortParams'}; if($params) { @@ -565,8 +522,7 @@ class portModel extends model */ public function getSourceByLang($lang) { - $lang = isset($this->modelLang->$lang) ? $this->modelLang->$lang : ''; - return $lang; + return isset($this->modelLang->$lang) ? $this->modelLang->$lang : ''; } /** @@ -594,7 +550,7 @@ class portModel extends model if(empty($rows)) return $exportDatas; - $exportDatas['user'] = $this->loadModel('user')->getPairs('devfirst|noclosed|nodeleted'); + $exportDatas['user'] = $this->loadModel('user')->getPairs('noclosed|nodeleted|noletter'); foreach ($rows as $id => $values) { @@ -760,7 +716,7 @@ class portModel extends model { $modelDatas = $this->getQueryDatas($model); - if(array_key_exists('files', $fieldList)) + if(isset($fieldList['files']) or property_exists($fieldList, 'files')) { $modelDatas = $this->getFiles($model, $modelDatas); } @@ -775,10 +731,7 @@ class portModel extends model } /* Deal children datas and multiple tasks .*/ - if($modelDatas) - { - $modelDatas = $this->updateChildDatas($modelDatas); - } + if($modelDatas) $modelDatas = $this->updateChildDatas($modelDatas); return $modelDatas; } @@ -807,7 +760,11 @@ class portModel extends model } elseif($queryCondition) { - $stmt = $this->dbh->query($queryCondition . ($this->post->exportType == 'selected' ? " AND t1.id IN({$this->cookie->checkedItem})" : '')); + $selectKey = 'id'; + if(strpos($queryCondition, "FROM `{$this->config->db->prefix}_$model` AS t1") == false) $selectKey = 't1.id'; + if(strpos($queryCondition, "FROM `{$this->config->db->prefix}_$model` AS t2") == false) $selectKey = 't2.id'; + + $stmt = $this->dbh->query($queryCondition . ($this->post->exportType == 'selected' ? " AND $selectKey IN({$this->cookie->checkedItem})" : '')); while($row = $stmt->fetch()) $modelDatas[$row->id] = $row; } @@ -832,10 +789,7 @@ class portModel extends model $relatedObjectIdList = array(); $relatedObjects = array(); - foreach($datas as $data) - { - $relatedObjectIdList[$data->$object] = $data->$object; - } + foreach($datas as $data) $relatedObjectIdList[$data->$object] = $data->$object; if($object == 'openedBuild') $object = 'build'; @@ -864,6 +818,7 @@ class portModel extends model { foreach($data as $field => $cellValue) { + if(strpos($this->portConfig->dateFeilds, $field) !== false and helper::isZeroDate($cellValue)) $datas[$key]->$field = ''; if(strpos($filter, $field) !== false) continue; if(is_array($cellValue)) continue; if(strrpos($cellValue, '(#') === false) @@ -882,6 +837,17 @@ class portModel extends model { $id = trim(substr($cellValue, strrpos($cellValue,'(#') + 2), ')'); $datas[$key]->$field = $id; + $control = !empty($this->modelFieldList[$field]['control']) ? $this->modelFieldList[$field]['control'] : ''; + if($control == 'multiple') + { + $cellValue = explode("\n", $cellValue); + foreach($cellValue as &$value) + { + $value = trim(substr($value, strrpos($value,'(#') + 2), ')'); + } + $cellValue = array_filter($cellValue, function($v) {return (empty($v) && $v == '0') || !empty($v);}); + $datas[$key]->$field = join(',', $cellValue); + } } } @@ -930,11 +896,16 @@ class portModel extends model $datas = array_slice($datas, ($pagerID - 1) * $maxImport, $maxImport, true); } - if(!$maxImport) $this->maxImport = $result->allCount; + if(!$maxImport) $this->maxImport = $result->allCount; $result->maxImport = $maxImport; $result->isEndPage = $pagerID >= $result->allPager; $result->datas = $datas; + foreach($datas as $data) + { + if(isset($data->id)) $this->session->set('insert', false); + } + if(empty($datas)) die(js::locate('back')); return $result; } @@ -1231,7 +1202,7 @@ class portModel extends model $suhosinInfo = $this->checkSuhosinInfo($datas->datas); - $importFields = $this->config->$model->templateFields; + $importFields = !empty($_SESSION[$model . 'TemplateFields']) ? $_SESSION[$model . 'TemplateFields'] : $this->config->$model->templateFields; $this->getWorkFlowFields($model); @@ -1264,7 +1235,7 @@ class portModel extends model $html = ''; $key = key($list); $addID = 1; - $members = $this->loadModel('user')->getTeamMemberPairs($this->session->taskPortParams['executionID'], 'execution'); + if($model == 'task') $members = $this->loadModel('user')->getTeamMemberPairs($this->session->taskPortParams['executionID'], 'execution'); $appendFields = $this->session->appendFields; $showImportCount = $this->config->port->lazyLoading ? $this->config->port->showImportCount : $this->maxImport; @@ -1284,7 +1255,6 @@ class portModel extends model if(!empty($object->id)) { $html .= $object->id . html::hidden("id[$row]", $object->id); - $this->session->set('insert', false); } else { @@ -1300,17 +1270,21 @@ class portModel extends model $values = $value['values']; $name = "{$field}[$row]"; $selected = !empty($object->$field) ? $object->$field : ''; - - $options = array(); - if($control == 'select' or $control == 'multiple') + if($model) { - if(!empty($values[$selected])) $options = array($selected => $values[$selected]); - if(!empty($values[$selected]) and isset($values[0])) $options = array_slice($values, 0, 1); + if($control == 'hidden' and isset($this->session->{$model.'PortParams'}[$field. 'ID'])) $selected = $this->session->{$model . 'PortParams'}[$field. 'ID']; } - if($control == 'select') $html .= '
    '; + $options = array(); + if($control == 'select') + { + if(!empty($values[$selected])) $options = array($selected => $values[$selected]); + if(empty($options) and is_array($values)) $options = array_slice($values, 0, 1); + } - elseif($control == 'multiple') $html .= ''; + if($control == 'select') $html .= ''; + + elseif($control == 'multiple') $html .= ''; elseif($control == 'date') $html .= ''; diff --git a/module/port/view/header.html.php b/module/port/view/header.html.php index 2da408399c..373f268f77 100644 --- a/module/port/view/header.html.php +++ b/module/port/view/header.html.php @@ -13,14 +13,14 @@ $model = $datas->model; $datas = $datas->datas; $appendFields = $this->session->appendFields; $notEmptyRule = $this->session->notEmptyRule; -$insert = $this->session->insert; ?> diff --git a/module/port/view/showimport.html.php b/module/port/view/showimport.html.php index e91aef2988..c60f8e6a78 100644 --- a/module/port/view/showimport.html.php +++ b/module/port/view/showimport.html.php @@ -17,7 +17,7 @@ getModuleRoot() . 'port/view/tfoot.html.php';?>
    ' . html::select("$name", $options, $selected, "class='form-control picker-select nopicker' data-field='{$field}'") . '' . html::select($name . "[]", $options, $selected, "multiple class='form-control picker-select nopicker' data-field='{$field}'") . '' . html::select("$name", $options, $selected, "class='form-control picker-select nopicker' data-field='{$field}' data-index='{$row}'") . '' . html::select($name . "[]", $values, $selected, "multiple class='form-control picker-select nopicker' data-field='{$field}' data-index='{$row}'") . '' . html::input("$name", $selected, "class='form-control form-date' autocomplete='off'") . '
    - getModuleRoot() . 'common/view/noticeimport.html.php';?> + session->insert); include $app->getModuleRoot() . 'common/view/noticeimport.html.php';?>
    getModuleRoot() . 'port/view/footer.html.php';?> diff --git a/module/port/view/tfoot.html.php b/module/port/view/tfoot.html.php index 8592b53094..6b4cd16e44 100644 --- a/module/port/view/tfoot.html.php +++ b/module/port/view/tfoot.html.php @@ -3,7 +3,7 @@ lang->save : $this->lang->file->saveAndNext; $isStartPage = $pagerID == 1 ? true : false; - if(!$insert and $dataInsert === '') + if(!$this->session->insert) { echo ""; } diff --git a/module/product/config.php b/module/product/config.php index 967c5f8df0..63a26fe140 100644 --- a/module/product/config.php +++ b/module/product/config.php @@ -153,4 +153,4 @@ $config->product->statisticFields['bugs'] = array('unResolvedBugs', 'clo $config->product->statisticFields['plans'] = array('plans'); $config->product->statisticFields['releases'] = array('releases'); -$config->product->skipRedirectMethod = ',create,index,showerrornone,ajaxgetdropmenu,kanban,all,manageline,export,'; +$config->product->skipRedirectMethod = ',create,index,showerrornone,ajaxgetdropmenu,kanban,all,manageline,export,ajaxgetplans,'; diff --git a/module/product/model.php b/module/product/model.php index bda572234c..3ee3ad29c2 100644 --- a/module/product/model.php +++ b/module/product/model.php @@ -680,7 +680,7 @@ class productModel extends model $programID = isset($product->program) ? $product->program : 0; $this->dao->insert(TABLE_PRODUCT)->data($product)->autoCheck() ->batchCheck($this->config->product->create->requiredFields, 'notempty') - ->checkIF((!empty($product->name) and $this->config->systemMode == 'new'), 'name', 'unique', "`program` = $programID and `deleted` = '0'") + ->checkIF(!empty($product->name), 'name', 'unique', "`program` = $programID and `deleted` = '0'") ->checkIF(!empty($product->code), 'code', 'unique', "`deleted` = '0'") ->checkFlow() ->exec(); @@ -770,10 +770,10 @@ class productModel extends model $this->lang->error->unique = $this->lang->error->repeat; $product = $this->loadModel('file')->processImgURL($product, $this->config->product->editor->edit['id'], $this->post->uid); - $programID = isset($product->program) ? $product->program : ''; + $programID = isset($product->program) ? $product->program : 0; $this->dao->update(TABLE_PRODUCT)->data($product)->autoCheck() ->batchCheck($this->config->product->edit->requiredFields, 'notempty') - ->checkIF((!empty($product->name) and $this->config->systemMode == 'new'), 'name', 'unique', "id != $productID and `program` = $programID and `deleted` = '0'") + ->checkIF(!empty($product->name), 'name', 'unique', "id != $productID and `program` = $programID and `deleted` = '0'") ->checkIF(!empty($product->code), 'code', 'unique', "id != $productID and `deleted` = '0'") ->checkFlow() ->where('id')->eq($productID) diff --git a/module/programplan/control.php b/module/programplan/control.php index fa727343c4..2c66ab4dfa 100644 --- a/module/programplan/control.php +++ b/module/programplan/control.php @@ -275,7 +275,7 @@ class programplan extends control $this->loadModel('task')->updateEsDateByGantt($objectID, $_POST['type']); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); -// $this->loadModel('action')->create('task', $objectID, 'ganttDrag', '', $this->app->user->account); + return $this->send(array('result' => 'success')); } } @@ -296,8 +296,7 @@ class programplan extends control $this->loadModel('task')->updateOrderByGantt(); if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError())); - $this->loadModel('action')->create('task', $taskID, 'ganttMove', '', $this->app->user->account); - + $this->loadModel('action')->create('task', $taskID, 'ganttMove'); return $this->send(array('result' => 'success')); } } diff --git a/module/programplan/view/gantt.html.php b/module/programplan/view/gantt.html.php index b096d6d64a..cd90dcc682 100644 --- a/module/programplan/view/gantt.html.php +++ b/module/programplan/view/gantt.html.php @@ -70,12 +70,17 @@ form {display: block; margin-top: 0em; margin-block-end: 1em;} rawModule);?> rawMethod);?> - +config->programplan->ganttCustom->ganttFields);?>
    - createLink('custom', 'ajaxSaveCustomFields', 'module=programplan§ion=ganttCustom&key=ganttFields')?> - + app->getModuleName() == 'programplan') + { + $customLink = $this->createLink('custom', 'ajaxSaveCustomFields', 'module=programplan§ion=ganttCustom&key=ganttFields'); + include '../../common/view/customfield.html.php'; + } + ?>
    @@ -475,12 +480,15 @@ $(function() $realname) + if(!empty($users)) { - $user = array(); - $user['key'] = $account; - $user['label'] = $realname; - $userList[] = $user; + foreach($users as $account => $realname) + { + $user = array(); + $user['key'] = $account; + $user['label'] = $realname; + $userList[] = $user; + } } ?> gantt.serverList("userList", ); diff --git a/module/project/control.php b/module/project/control.php index 62cfb79383..96f41a566d 100644 --- a/module/project/control.php +++ b/module/project/control.php @@ -240,7 +240,7 @@ class project extends control { $object = $objectType == 'project' ? $this->project->getByID($objectID) : $this->loadModel('program')->getByID($objectID); - if(isset($availableBudget)) $availableBudget = $object->parent == $selectedProgramID ? $availableBudget + $object->budget : $availableBudget; + if(isset($availableBudget)) $availableBudget = $object->parent == $selectedProgramID ? $availableBudget + (int)$object->budget : $availableBudget; if($objectType == 'program') { diff --git a/module/project/model.php b/module/project/model.php index 98d88ee606..57e1968acd 100644 --- a/module/project/model.php +++ b/module/project/model.php @@ -2618,9 +2618,10 @@ class projectModel extends model public function setMenu($objectID) { global $lang; - $project = $this->getByID($objectID); - $model = 'scrum'; + $model = 'scrum'; + $objectID = (empty($objectID) and $this->session->project) ? $this->session->project : $objectID; + $project = $this->getByID($objectID); if($project and $project->model == 'waterfall') $model = $project->model; if($project and $project->model == 'kanban') { @@ -2657,7 +2658,6 @@ class projectModel extends model $this->lang->switcherMenu = $this->getSwitcher($objectID, $moduleName, $methodName); $this->saveState($objectID, $this->getPairsByProgram()); - $project = $this->getById($objectID); if(isset($project->acl) and $project->acl == 'open') unset($this->lang->project->menu->settings['subMenu']->whitelist); diff --git a/module/search/control.php b/module/search/control.php index d8d664c414..a6325b3faa 100644 --- a/module/search/control.php +++ b/module/search/control.php @@ -231,18 +231,12 @@ class search extends control $pager = new pager(0, $this->config->search->recPerPage, $pageID); $results = $this->search->getList($words, $type, $pager); - if($words) + $typeCount = $this->search->getListCount(); + $typeList = array('all' => $this->lang->search->modules['all']); + foreach($typeCount as $objectType => $count) { - $typeCount = $this->search->getListCount($words); - $typeList = array('all' => $this->lang->search->modules['all']); - foreach($typeCount as $objectType => $count) - { - $typeList[$objectType] = $this->lang->search->modules[$objectType]; - } - } - else - { - $typeList = $this->lang->search->modules; + if(!isset($this->lang->search->modules[$objectType])) continue; + $typeList[$objectType] = $this->lang->search->modules[$objectType]; } /* Set session. */ diff --git a/module/search/model.php b/module/search/model.php index 444e864a76..4055974eb6 100644 --- a/module/search/model.php +++ b/module/search/model.php @@ -612,7 +612,7 @@ class searchModel extends model $likeCondition = ''; /* Assisted lookup by like condition when only one word. */ - if(count($words) == 1 and strpos($words[0], ' ') === false) $likeCondition = "OR title like '%{$words[0]}%' OR content like '%{$words[0]}%'"; + if(count($words) == 1 and strpos($words[0], ' ') === false and !is_numeric($words[0])) $likeCondition = "OR title like '%{$words[0]}%' OR content like '%{$words[0]}%'"; $words = str_replace('"', '', $against); $words = str_pad($words, 5, '_'); @@ -647,7 +647,7 @@ class searchModel extends model * @access public * @return array */ - public function getListCount($keywords, $type = 'all') + public function getListCount($keywords = '', $type = 'all') { list($words, $againstCond, $likeCondition, $allowedObject) = $this->getSqlParams($keywords, $type); diff --git a/module/story/config.php b/module/story/config.php index 8da49d96d0..1dcf62aacc 100644 --- a/module/story/config.php +++ b/module/story/config.php @@ -88,17 +88,19 @@ $config->story->datatable->fieldList['title']['width'] = 'auto'; $config->story->datatable->fieldList['title']['required'] = 'yes'; $config->story->datatable->fieldList['product']['title'] = 'product'; +$config->story->datatable->fieldList['product']['control'] = 'hidden'; $config->story->datatable->fieldList['product']['dataSource'] = array('module' => 'port', 'method' => 'getRelatedObjects', 'params' => 'story&product&id,name'); $config->story->datatable->fieldList['branch']['title'] = 'branch'; $config->story->datatable->fieldList['branch']['fixed'] = 'no'; $config->story->datatable->fieldList['branch']['width'] = '100'; $config->story->datatable->fieldList['branch']['required'] = 'no'; +$config->story->datatable->fieldList['branch']['control'] = 'multiple'; $config->story->datatable->fieldList['branch']['dataSource'] = array('module' => 'story', 'method' => 'getRelatedObjects', 'params' => 'branch&id,name'); $config->story->datatable->fieldList['module']['title'] = 'module'; $config->story->datatable->fieldList['module']['control'] = 'select'; -$config->story->datatable->fieldList['module']['dataSource'] = array('module' => 'tree', 'method' => 'getAllModulePairs', 'params' => 'story'); +$config->story->datatable->fieldList['module']['dataSource'] = array('module' => 'tree', 'method' => 'getOptionMenu', 'params' => '$productID&story&0&all'); $config->story->datatable->fieldList['keywords']['title'] = 'keywords'; $config->story->datatable->fieldList['keywords']['fixed'] = 'no'; @@ -110,7 +112,7 @@ $config->story->datatable->fieldList['plan']['fixed'] = 'no'; $config->story->datatable->fieldList['plan']['width'] = '90'; $config->story->datatable->fieldList['plan']['required'] = 'no'; $config->story->datatable->fieldList['plan']['control'] = 'select'; -$config->story->datatable->fieldList['plan']['dataSource'] = array('module' => 'story', 'method' => 'getRelatedObjects', 'params' => 'plan&id,title'); +$config->story->datatable->fieldList['plan']['dataSource'] = array('module' => 'productplan', 'method' => 'getPairs', 'params' => '$productID'); $config->story->datatable->fieldList['source']['title'] = 'source'; $config->story->datatable->fieldList['source']['fixed'] = 'no'; @@ -162,16 +164,26 @@ $config->story->datatable->fieldList['assignedDate']['fixed'] = 'no'; $config->story->datatable->fieldList['assignedDate']['width'] = '90'; $config->story->datatable->fieldList['assignedDate']['required'] = 'no'; -$config->story->datatable->fieldList['reviewedBy']['title'] = 'reviewedBy'; -$config->story->datatable->fieldList['reviewedBy']['fixed'] = 'no'; -$config->story->datatable->fieldList['reviewedBy']['width'] = '80'; -$config->story->datatable->fieldList['reviewedBy']['required'] = 'no'; +$config->story->datatable->fieldList['reviewedBy']['title'] = 'reviewedBy'; +$config->story->datatable->fieldList['reviewedBy']['fixed'] = 'no'; +$config->story->datatable->fieldList['reviewedBy']['width'] = '80'; +$config->story->datatable->fieldList['reviewedBy']['required'] = 'no'; +$config->story->datatable->fieldList['reviewedBy']['control'] = 'multiple'; +$config->story->datatable->fieldList['reviewedBy']['dataSource'] = array('module' => 'story', 'method' => 'getStoriesReviewer', 'params' => '$productID'); + +$config->story->datatable->fieldList['reviewer']['title'] = 'reviewedBy'; +$config->story->datatable->fieldList['reviewer']['control'] = 'multiple'; +$config->story->datatable->fieldList['reviewer']['dataSource'] = array('module' => 'story', 'method' => 'getStoriesReviewer', 'params' => '$productID'); $config->story->datatable->fieldList['reviewedDate']['title'] = 'reviewedDate'; $config->story->datatable->fieldList['reviewedDate']['fixed'] = 'no'; $config->story->datatable->fieldList['reviewedDate']['width'] = '90'; $config->story->datatable->fieldList['reviewedDate']['required'] = 'no'; +$config->story->datatable->fieldList['needReview']['title'] = 'needReview'; +$config->story->datatable->fieldList['needReview']['control'] = 'select'; +$config->story->datatable->fieldList['needReview']['dataSource'] = array('lang' => 'reviewList'); + $config->story->datatable->fieldList['closedBy']['title'] = 'closedBy'; $config->story->datatable->fieldList['closedBy']['fixed'] = 'no'; $config->story->datatable->fieldList['closedBy']['width'] = '80'; diff --git a/module/story/control.php b/module/story/control.php index 947203fb69..3abd90d2f6 100644 --- a/module/story/control.php +++ b/module/story/control.php @@ -114,6 +114,8 @@ class story extends control $this->view->$fromObjectName = $fromObject; } + $copyStoryID = $storyID; + if(!empty($_POST)) { $response['result'] = 'success'; @@ -237,7 +239,19 @@ class story extends control setcookie('storyModule', 0, 0, $this->config->webRoot, '', $this->config->cookieSecure, false); $branchID = $this->post->branch ? $this->post->branch : $branch; $response['locate'] = $this->createLink('product', 'browse', "productID=$productID&branch=$branchID&browseType=¶m=0&type=$type&orderBy=id_desc"); - if($this->session->storyList) $response['locate'] = $this->session->storyList; + if($this->session->storyList) + { + /* When copying story in the product plan, return to different pages for story#32949. */ + if($copyStoryID and strpos($this->session->storyList, 'productplan') !== false) + { + $storyInfo = $this->story->getByList(array($storyID, $copyStoryID)); + if($storyInfo[$storyID]->plan == $storyInfo[$copyStoryID]->plan or $storyInfo[$storyID]->product != $storyInfo[$copyStoryID]->product) $response['locate'] = $this->session->storyList; + } + else + { + $response['locate'] = $this->session->storyList; + } + } } else { diff --git a/module/story/js/batchtotask.js b/module/story/js/batchtotask.js index 5548e54b13..d997c16b14 100755 --- a/module/story/js/batchtotask.js +++ b/module/story/js/batchtotask.js @@ -271,6 +271,7 @@ function addRow(obj) $row.find('div[id$=_chosen]').remove(); $row.find('.picker').remove(); $row.find('.chosen').chosen(); + $row.find('.picker-select').picker(); var begin = parseInt($(obj).parent().siblings('.c-id').text()) + 1; var count = $('#tableBody tbody > tr').length; diff --git a/module/story/model.php b/module/story/model.php index 9555f7f607..679afde7a9 100644 --- a/module/story/model.php +++ b/module/story/model.php @@ -5525,8 +5525,7 @@ class storyModel extends model */ public function getRelatedObjects($object, $pairs = '') { - /* Get bugs. */ - $storys = $this->dao->select('*')->from(TABLE_STORY)->where($this->session->storyQueryCondition)->fetchAll('id'); + $storys = $this->loadModel('port')->getQueryDatas('story'); /* Get related objects id lists. */ $relatedObjectIdList = array(); @@ -5636,8 +5635,8 @@ class storyModel extends model $storyCases = $this->loadModel('testcase')->getStoryCaseCounts($relatedStoryIds); /* Get related objects title or names. */ - $relatedSpecs = $this->dao->select('*')->from(TABLE_STORYSPEC)->where('`story`')->in($storyIdList)->orderBy('version desc')->fetchGroup('story'); - + $relatedSpecs = $this->dao->select('*')->from(TABLE_STORYSPEC)->where('`story`')->in($storyIdList)->orderBy('version desc')->fetchGroup('story'); + $relatedFiles = $this->dao->select('id, objectID, pathname, title')->from(TABLE_FILE)->where('objectType')->eq('story')->andWhere('objectID')->in($storyIdList)->andWhere('extra')->ne('editor')->fetchGroup('objectID'); foreach($stories as $story) { $story->spec = ''; @@ -5731,4 +5730,18 @@ class storyModel extends model return $stories; } + + /** + * Get reviewer pairs for story . + * + * @param int $productID + * @access public + * @return void + */ + public function getStoriesReviewer($productID = 0) + { + $product = $this->loadModel('product')->getByID($productID); + $reviewers = $this->loadModel('user')->getProductViewListUsers($product, '', '', '', ''); + return $this->user->getPairs('noclosed|nodeleted', '', 0, $reviewers); + } } diff --git a/module/story/view/track.html.php b/module/story/view/track.html.php index 0d488d1c35..75cf44858c 100644 --- a/module/story/view/track.html.php +++ b/module/story/view/track.html.php @@ -33,7 +33,7 @@
    {$projectProducts[$productID]->name}
    ", '', 'class="dropdown-toggle" data-toggle="dropdown"');?>
    diff --git a/module/task/control.php b/module/task/control.php index 905ee7cdc3..eb7277686d 100755 --- a/module/task/control.php +++ b/module/task/control.php @@ -438,10 +438,16 @@ class task extends control $customFields[$field] = $this->lang->task->$field; } - if($execution->lifetime == 'ops' or $execution->attribute == 'request' or $execution->attribute == 'review') unset($customFields['story']); + $showFields = $this->config->task->custom->batchCreateFields; + if($execution->lifetime == 'ops' or $execution->attribute == 'request' or $execution->attribute == 'review') + { + unset($customFields['story']); + $showFields = str_replace(',story,', ',', ",$showFields,"); + $showFields = trim($showFields, ','); + } $this->view->customFields = $customFields; - $this->view->showFields = $this->config->task->custom->batchCreateFields; + $this->view->showFields = $showFields; if($execution->type == 'kanban') { diff --git a/module/task/css/batchedit.css b/module/task/css/batchedit.css index 1eb634abd1..dd7e102439 100644 --- a/module/task/css/batchedit.css +++ b/module/task/css/batchedit.css @@ -1,5 +1,4 @@ .c-id {width: 50px;} -.c-name {width: 150px;} .c-pri, .c-record, .c-left {width: 70px;} .c-reason {width: 100px;} .c-module, .c-assigned {width: 150px;} diff --git a/module/task/model.php b/module/task/model.php index a26082c9f5..6717cb0f90 100644 --- a/module/task/model.php +++ b/module/task/model.php @@ -3936,90 +3936,128 @@ class taskModel extends model $this->app->loadLang('project'); $post = fixer::input('post')->get(); $post->endDate = date('Y-m-d', strtotime('-1 day', strtotime($post->endDate))); + $changeTable = $objectType == 'task' ? TABLE_TASK : TABLE_PROJECT; + $actionType = $objectType == 'task' ? 'task' : 'execution'; + $oldObject = $this->dao->select('*')->from($changeTable)->where('id')->eq($objectID)->fetch(); if($objectType == 'task') { - $objectData = $this->dao->select('*')->from(TABLE_TASK)->where('id')->eq($objectID)->fetch(); - $parent = $objectData->parent; - $project = $objectData->project; - $execution = $objectData->execution; - $stage = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($execution)->andWhere('project')->eq($project)->fetch(); - - if($parent <= 0) - { - $parentData = $stage; - - $start = $parentData->begin; - $end = $parentData->end; - } - else - { - $parentData = $this->dao->select('*')->from(TABLE_TASK)->where('id')->eq($parent)->fetch(); - - $start = helper::isZeroDate($parentData->estStarted) ? '' : $parentData->estStarted; - $end = helper::isZeroDate($parentData->deadline) ? '' : $parentData->deadline; - } - - if(helper::diffDate($start, $post->startDate) > 0) - { - $arg = !empty($parent) ? $this->lang->task->parent : $this->lang->project->stage; - return dao::$errors = sprintf($this->lang->task->overEsStartDate, $arg, $arg); - } - - if(helper::diffDate($end, $post->endDate) < 0) - { - $arg = !empty($parent) ? $this->lang->task->parent : $this->lang->project->stage; - return dao::$errors = sprintf($this->lang->task->overEsEndDate, $arg, $arg); - } - - $this->dao->update(TABLE_TASK) - ->set('estStarted')->eq($post->startDate) - ->set('deadline')->eq($post->endDate) - ->set('lastEditedBy')->eq($this->app->user->account) - ->where('id')->eq($objectID) - ->exec(); + $this->updateTaskEsDateByGantt($objectID, $objectType, $post); } elseif($objectType == 'plan') { - $objectData = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($objectID)->fetch(); - $parent = $objectData->parent; - $project = $objectData->project; + $this->updateExecutionEsDateByGantt($objectID, $objectType, $post); + } + + if(dao::isError()) return false; + + $newObject = $this->dao->select('*')->from($changeTable)->where('id')->eq($objectID)->fetch(); + $changes = common::createChanges($oldObject, $newObject); + $actionID = $this->loadModel('action')->create($actionType, $objectID, 'edited'); + if(!empty($changes)) $this->loadModel('action')->logHistory($actionID, $changes); - if(empty($parent)) - { - $parentData = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($project)->fetch(); - } - else - { - $parentData = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($parent)->fetch(); - } + return true; + } - $start = helper::isZeroDate($parentData->begin) ? '' : $parentData->begin; - $end = helper::isZeroDate($parentData->end) ? '' : $parentData->end; + /** + * Update Task estimate date by gantt. + * + * @param int $objectID + * @param string $objectType + * @param object $postData + * @access private + * @return bool + */ + private function updateTaskEsDateByGantt($objectID, $objectType, $postData) + { + $objectData = $this->dao->select('*')->from(TABLE_TASK)->where('id')->eq($objectID)->fetch(); + $parent = $objectData->parent; + $project = $objectData->project; + $execution = $objectData->execution; + $stage = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($execution)->andWhere('project')->eq($project)->fetch(); - if(helper::diffDate($start, $post->startDate) > 0) - { - $arg = !empty($parent) ? $this->lang->programplan->parent : $this->lang->project->common; - return dao::$errors = sprintf($this->lang->task->overEsStartDate, $arg, $arg); - } + if($parent <= 0) + { + $parentData = $stage; - if(helper::diffDate($end, $post->endDate) < 0) - { - $arg = !empty($parent) ? $this->lang->programplan->parent : $this->lang->project->common; - return dao::$errors = sprintf($this->lang->task->overEsEndDate, $arg, $arg); - } - - $this->dao->update(TABLE_PROJECT) - ->set('begin')->eq($post->startDate) - ->set('end')->eq($post->endDate) - ->set('lastEditedBy')->eq($this->app->user->account) - ->where('id')->eq($objectID) - ->exec(); + $start = $parentData->begin; + $end = $parentData->end; } else { - return false; + $parentData = $this->dao->select('*')->from(TABLE_TASK)->where('id')->eq($parent)->fetch(); + + $start = helper::isZeroDate($parentData->estStarted) ? '' : $parentData->estStarted; + $end = helper::isZeroDate($parentData->deadline) ? '' : $parentData->deadline; } + if(helper::diffDate($start, $postData->startDate) > 0) + { + $arg = !empty($parent) ? $this->lang->task->parent : $this->lang->project->stage; + return dao::$errors = sprintf($this->lang->task->overEsStartDate, $arg, $arg); + } + + if(helper::diffDate($end, $postData->endDate) < 0) + { + $arg = !empty($parent) ? $this->lang->task->parent : $this->lang->project->stage; + return dao::$errors = sprintf($this->lang->task->overEsEndDate, $arg, $arg); + } + + $this->dao->update(TABLE_TASK) + ->set('estStarted')->eq($postData->startDate) + ->set('deadline')->eq($postData->endDate) + ->set('lastEditedBy')->eq($this->app->user->account) + ->where('id')->eq($objectID) + ->exec(); + + return true; + } + + /** + * Update Execution estimate date by gantt. + * + * @param int $objectID + * @param string $objectType + * @param object $postData + * @access private + * @return bool + */ + private function updateExecutionEsDateByGantt($objectID, $objectType, $postData) + { + $objectData = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($objectID)->fetch(); + $parent = $objectData->parent; + $project = $objectData->project; + + if(empty($parent)) + { + $parentData = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($project)->fetch(); + } + else + { + $parentData = $this->dao->select('*')->from(TABLE_PROJECT)->where('id')->eq($parent)->fetch(); + } + + $start = helper::isZeroDate($parentData->begin) ? '' : $parentData->begin; + $end = helper::isZeroDate($parentData->end) ? '' : $parentData->end; + + if(helper::diffDate($start, $postData->startDate) > 0) + { + $arg = !empty($parent) ? $this->lang->programplan->parent : $this->lang->project->common; + return dao::$errors = sprintf($this->lang->task->overEsStartDate, $arg, $arg); + } + + if(helper::diffDate($end, $postData->endDate) < 0) + { + $arg = !empty($parent) ? $this->lang->programplan->parent : $this->lang->project->common; + return dao::$errors = sprintf($this->lang->task->overEsEndDate, $arg, $arg); + } + + $this->dao->update(TABLE_PROJECT) + ->set('begin')->eq($postData->startDate) + ->set('end')->eq($postData->endDate) + ->set('lastEditedBy')->eq($this->app->user->account) + ->where('id')->eq($objectID) + ->exec(); + return true; } diff --git a/module/testcase/config.php b/module/testcase/config.php index bcbd9740b3..e8074d3717 100644 --- a/module/testcase/config.php +++ b/module/testcase/config.php @@ -218,6 +218,7 @@ $config->testcase->datatable->fieldList['results']['width'] = '32'; $config->testcase->datatable->fieldList['results']['required'] = 'no'; $config->testcase->datatable->fieldList['results']['sort'] = 'no'; $config->testcase->datatable->fieldList['results']['name'] = $lang->testcase->results; +$config->testcase->datatable->fieldList['results']['dataSource'] = array('lang' => 'resultList'); $config->testcase->datatable->fieldList['stepNumber']['title'] = 'S'; $config->testcase->datatable->fieldList['stepNumber']['fixed'] = 'no'; diff --git a/module/testcase/view/showimport.html.php b/module/testcase/view/showimport.html.php index dc44da2ec5..5627391e48 100644 --- a/module/testcase/view/showimport.html.php +++ b/module/testcase/view/showimport.html.php @@ -44,7 +44,7 @@ getModuleRoot() . 'port/view/tfoot.html.php';?> - getModuleRoot() . 'common/view/noticeimport.html.php';?> + session->insert) include $app->getModuleRoot() . 'common/view/noticeimport.html.php';?>
    getModuleRoot() . 'port/view/footer.html.php';?> diff --git a/module/upgrade/control.php b/module/upgrade/control.php index d2fb523a88..fe176ea746 100644 --- a/module/upgrade/control.php +++ b/module/upgrade/control.php @@ -906,83 +906,6 @@ class upgrade extends control echo $this->dao->select('status')->from(TABLE_PROGRAM)->where('id')->eq($programID)->fetch('status'); } - /** - * Ajax change table engine. - * - * @access public - * @return void - */ - public function ajaxChangeTableEngine() - { - $response = array(); - $response['result'] = 'continue'; - $response['message'] = ''; - $response['nextMessage'] = ''; - - $stmt = $this->dao->query("SHOW TABLE STATUS WHERE `Engine` is not null AND `Engine` = 'MyISAM'"); - $table = $stmt->fetch(); - if(empty($table)) - { - $response['result'] = 'finished'; - $response['message'] = $this->lang->upgrade->finishedChange; - return print(json_encode($response)); - } - - $nextTable = $stmt->fetch(); - if($nextTable and stripos($nextTable->Name, 'searchindex') !== false) - { - $mysqlVersion = $this->loadModel('install')->getMysqlVersion(); - if($mysqlVersion < 5.6) $nextTable = $stmt->fetch(); - } - - $tableName = $table->Name; - - $response['table'] = $tableName; - - /* Check process this table or not. */ - $dbProcesses = $this->dao->query("SHOW PROCESSLIST")->fetchAll(); - foreach($dbProcesses as $dbProcess) - { - if($dbProcess->db != $this->config->db->name) continue; - if(strpos($dbProcess->Info, " `{$tableName}` ")) - { - $response['message'] = sprintf($this->lang->upgrade->changingTable, $response['table']); - return print(json_encode($response)); - } - } - - if($nextTable) - { - $response['next'] = $nextTable->Name; - if($response['next']) $response['nextMessage'] = sprintf($this->lang->upgrade->changingTable, $response['next']); - } - - if(stripos($tableName, 'searchindex') !== false) - { - /* Change fulltext index. */ - $stmt = $this->dao->query("show index from `$tableName`"); - $indexes = array(); - while($index = $stmt->fetch()) - { - if($index->Index_type != 'FULLTEXT') continue; - $indexes[$index->Key_name] = $index->Key_name; - } - - if(!isset($indexes['title_content'])) $this->dao->exec( "ALTER TABLE `{$tableName}` ADD FULLTEXT `title_content` (`title`, `content`)"); - if(isset($indexes['title'])) $this->dao->exec( "ALTER TABLE `{$tableName}` DROP INDEX `title`"); - if(isset($indexes['content'])) $this->dao->exec( "ALTER TABLE `{$tableName}` DROP INDEX `content`"); - - $mysqlVersion = $this->loadModel('install')->getMysqlVersion(); - if($mysqlVersion < 5.6) return print(json_encode($response)); - } - - $sql = "ALTER TABLE `$tableName` ENGINE='InnoDB'"; - $this->dao->exec($sql); - - $response['message'] = sprintf($this->lang->upgrade->finishedTable, $tableName); - return print(json_encode($response)); - } - /** * Move Extent files. * diff --git a/module/upgrade/lang/de.php b/module/upgrade/lang/de.php index 9512aea5d9..dfd5dffaf6 100644 --- a/module/upgrade/lang/de.php +++ b/module/upgrade/lang/de.php @@ -51,10 +51,6 @@ $lang->upgrade->sureExecute = 'Ausführen'; $lang->upgrade->upgradingTips = 'The upgrade is in progress, please be patient. Do not refresh the page, blackout, or turn off your computer!'; $lang->upgrade->forbiddenExt = 'Die Erweiterung ist nicht kompatibel mit der Upgradeversion. Sie wurde deaktiviert:'; $lang->upgrade->updateFile = 'Updateinformation wurden hinzugefügt.'; -$lang->upgrade->changeEngine = 'The database engine needs to be modified.'; -$lang->upgrade->changingTable = 'Replacing data table %s engine...'; -$lang->upgrade->finishedTable = 'The data table %s engine has been changed to InnoDB.'; -$lang->upgrade->finishedChange = 'The replacement of the database engine is completed.'; $lang->upgrade->noticeSQL = 'Your database is inconsistent with the standard and it failed to fix it. Please run the following SQL and refresh.'; $lang->upgrade->afterDeleted = 'File is not deleted. Please refresh after you delete it.'; $lang->upgrade->mergeProgram = 'Data Merge'; @@ -134,6 +130,7 @@ $lang->upgrade->mergeByProject = "Independent {$lang->projectCommon}: You ca $lang->upgrade->mergeByMoreLink = "{$lang->projectCommon} that relates multiple {$lang->productCommon}: You can select several {$lang->projectCommon} and merge them into one large project, or merge them independently."; $lang->upgrade->mergeRepoTips = "Merge the selected version library under the selected product."; $lang->upgrade->needBuild4Add = 'Full text retrieval has been added in this upgrad. Please create an index.'; +$lang->upgrade->needChangeEngine = 'The table engine needs to be replaced in this upgrade, Please go [Admin->System->TableEngine] page to replace engine.'; $lang->upgrade->errorEngineInnodb = 'Your MySQL version is too low to support InnoDB data table engine. Please modify it to MyISAM and try again.'; $lang->upgrade->duplicateProject = "Project name in the same program cannot be duplicate. Please adjust the duplicate names."; $lang->upgrade->upgradeTips = "Historically deleted data cannot be upgraded, and restoration is not supported after the upgrade. Please be aware."; diff --git a/module/upgrade/lang/en.php b/module/upgrade/lang/en.php index 8d9c1b413b..ed38f78dd2 100644 --- a/module/upgrade/lang/en.php +++ b/module/upgrade/lang/en.php @@ -51,10 +51,6 @@ $lang->upgrade->sureExecute = 'Execute'; $lang->upgrade->upgradingTips = 'The upgrade is in progress, please be patient. Do not refresh the page, blackout, or turn off your computer!'; $lang->upgrade->forbiddenExt = 'The extension is incompatible with the version. It has been deactivated:'; $lang->upgrade->updateFile = 'File information has to be updated.'; -$lang->upgrade->changeEngine = 'The database engine needs to be modified.'; -$lang->upgrade->changingTable = 'Replacing data table %s engine...'; -$lang->upgrade->finishedTable = 'The data table %s engine has been changed to InnoDB.'; -$lang->upgrade->finishedChange = 'The replacement of the database engine is completed.'; $lang->upgrade->noticeSQL = 'Your database is inconsistent with the standard and it failed to fix it. Please run the following SQL and refresh.'; $lang->upgrade->afterDeleted = 'Please execute commands to delete the files. Please refresh after you delete them.'; $lang->upgrade->mergeProgram = 'Data Merge'; @@ -134,6 +130,7 @@ $lang->upgrade->mergeByProject = "Independent {$lang->projectCommon}: You ca $lang->upgrade->mergeByMoreLink = "{$lang->projectCommon} that relates multiple {$lang->productCommon}: You can select several {$lang->projectCommon} and merge them into one large project, or merge them independently."; $lang->upgrade->mergeRepoTips = "Merge the selected version library under the selected product."; $lang->upgrade->needBuild4Add = 'Full text retrieval has been added in this upgrade. Need create index. Please go [Admin->System->BuildIndex] page to build index.'; +$lang->upgrade->needChangeEngine = 'The table engine needs to be replaced in this upgrade, Please go [Admin->System->TableEngine] page to replace engine.'; $lang->upgrade->errorEngineInnodb = 'Your MySQL does not support InnoDB data table engine. Please modify it to MyISAM and try again.'; $lang->upgrade->duplicateProject = "Project name in the same program cannot be duplicate. Please adjust the duplicate names."; $lang->upgrade->upgradeTips = "Historically deleted data cannot be upgraded, and restoration is not supported after the upgrade. Please be aware."; diff --git a/module/upgrade/lang/fr.php b/module/upgrade/lang/fr.php index 815df01348..ac63434bce 100644 --- a/module/upgrade/lang/fr.php +++ b/module/upgrade/lang/fr.php @@ -51,10 +51,6 @@ $lang->upgrade->sureExecute = 'Executez'; $lang->upgrade->upgradingTips = 'La mise à jour est en cours, veuillez être patient. Ne pas actualiser la page ou éteindre votre ordinateur!'; $lang->upgrade->forbiddenExt = 'Cette extension est incompatible avec la version. Elle a été désactivée :'; $lang->upgrade->updateFile = "Le fichier information a besoin d'une mise à jour."; -$lang->upgrade->changeEngine = 'The database engine needs to be modified.'; -$lang->upgrade->changingTable = 'Replacing data table %s engine...'; -$lang->upgrade->finishedTable = 'The data table %s engine has been changed to InnoDB.'; -$lang->upgrade->finishedChange = 'The replacement of the database engine is completed.'; $lang->upgrade->noticeSQL = 'Votre base de donnée est inconsistente avec le standard et il y a eu un échec pour la corriger. Exécutez la commande SQL suivante et rafraichissez.'; $lang->upgrade->afterDeleted = "Le fichier n'est pas supprimé. Recommencez après l'avoir supprimé."; $lang->upgrade->mergeProgram = 'Data Merge'; @@ -134,6 +130,7 @@ $lang->upgrade->mergeByProject = "Independent {$lang->projectCommon}: You ca $lang->upgrade->mergeByMoreLink = "{$lang->projectCommon} that relates multiple {$lang->productCommon}: You can select several {$lang->projectCommon} and merge them into one large project, or merge them independently."; $lang->upgrade->mergeRepoTips = "Merge the selected version library under the selected product."; $lang->upgrade->needBuild4Add = 'Full text retrieval has been added in this upgrade. Need create index. Please go [Admin->System->BuildIndex] page to build index.'; +$lang->upgrade->needChangeEngine = 'The table engine needs to be replaced in this upgrade, Please go [Admin->System->TableEngine] page to replace engine.'; $lang->upgrade->errorEngineInnodb = 'Your MySQL does not support InnoDB data table engine. Please modify it to MyISAM and try again.'; $lang->upgrade->duplicateProject = "Project name in the same program cannot be duplicate. Please adjust the duplicate names."; $lang->upgrade->upgradeTips = "Historically deleted data cannot be upgraded, and restoration is not supported after the upgrade. Please be aware."; diff --git a/module/upgrade/lang/zh-cn.php b/module/upgrade/lang/zh-cn.php index 4378626dcd..97450262e1 100644 --- a/module/upgrade/lang/zh-cn.php +++ b/module/upgrade/lang/zh-cn.php @@ -51,10 +51,6 @@ $lang->upgrade->sureExecute = '确认执行'; $lang->upgrade->upgradingTips = '正在升级中,请耐心等待,切勿刷新页面、断电、关机!'; $lang->upgrade->forbiddenExt = '以下插件与新版本不兼容,已经自动禁用:'; $lang->upgrade->updateFile = '需要更新附件信息。'; -$lang->upgrade->changeEngine = '需要修改数据库引擎。'; -$lang->upgrade->changingTable = '正在更换数据表%s引擎...'; -$lang->upgrade->finishedTable = '已经更换数据表%s引擎为InnoDB。'; -$lang->upgrade->finishedChange = '更换数据库引擎结束。'; $lang->upgrade->noticeSQL = '检查到你的数据库跟标准不一致,尝试修复失败。请执行以下SQL语句,再刷新页面检查。'; $lang->upgrade->afterDeleted = '请执行上面命令删除文件, 删除后刷新!'; $lang->upgrade->mergeProgram = '数据迁移'; @@ -134,6 +130,7 @@ $lang->upgrade->mergeByProject = "独立的{$lang->projectCommon}:可以 $lang->upgrade->mergeByMoreLink = "关联多个{$lang->productCommon}的{$lang->projectCommon}:选择一个或多个{$lang->projectCommon}归并到一个项目集和项目中。"; $lang->upgrade->mergeRepoTips = "将选中的版本库归并到所选产品下。"; $lang->upgrade->needBuild4Add = '本次升级需要创建索引。请到 [后台->系统->重建索引] 页面,重新创建索引。'; +$lang->upgrade->needChangeEngine = '本次升级需要更换表引擎, [后台->系统->表引擎] 页面更换引擎。'; $lang->upgrade->errorEngineInnodb = '您当前的数据库不支持使用InnoDB数据表引擎,请修改为MyISAM后重试。'; $lang->upgrade->duplicateProject = "同一个项目集内项目名称不能重复,请调整重名的项目名称"; $lang->upgrade->upgradeTips = "历史删除数据不参与升级,升级后将不支持还原,请知悉"; diff --git a/module/upgrade/model.php b/module/upgrade/model.php index e2cbd800e6..a664508eff 100644 --- a/module/upgrade/model.php +++ b/module/upgrade/model.php @@ -534,8 +534,17 @@ class upgradeModel extends model $this->processCreatedInfo(); $this->processCreatedBy(); $this->updateApproval(); - $this->recordOSAndBrowserOfBug(); + $this->rebuildFULLTEXT(); $this->updateSearchIndex(); + if(!$executedXuanxuan) + { + $table = $this->config->db->prefix . 'im_chat'; + $exists = $this->checkFieldsExists($table, 'adminInvite'); + if(!$exists) + { + $this->dbh->query("ALTER TABLE $table ADD `adminInvite` enum('0','1') NOT NULL DEFAULT '0' AFTER `mergedChats`"); + } + } break; case '17_5': $this->recordOSAndBrowserOfBug(); @@ -685,9 +694,13 @@ class upgradeModel extends model $this->processFlowPosition(); break; case 'biz7.4': + $this->processCreatedInfo(); + $this->processCreatedBy(); $this->updateApproval(); $this->addDefaultRuleToWorkflow(); - $this->addFlowActions('biz7.3'); + $this->processReviewLinkages(); + $this->addFlowActions('biz7.4'); + $this->addFlowFields('biz7.4'); break; } } @@ -3201,25 +3214,25 @@ class upgradeModel extends model { $fromVersion = $this->config->installedVersion; $needProcess = array(); - if(strpos($fromVersion, 'max') === false and strpos($fromVersion, 'biz') === false and (strpos($fromVersion, 'pro') === false ? version_compare($fromVersion, '8.3', '<') : version_compare($fromVersion, 'pro5.4', '<'))) $needProcess['updateFile'] = true; + if(strpos($fromVersion, 'max') === false and strpos($fromVersion, 'biz') === false and (strpos($fromVersion, 'pro') === false ? version_compare($fromVersion, '8.3', '<') : version_compare($fromVersion, 'pro5.4', '<'))) $needProcess['updateFile'] = 'process'; if(strpos($fromVersion, 'max') === false and $this->config->systemMode == 'new') { if(strpos($fromVersion, 'pro') !== false) { - if(version_compare($fromVersion, 'pro10.0', '<')) $needProcess['search'] = true; + if(version_compare($fromVersion, 'pro10.0', '<')) $needProcess['search'] = 'notice'; } elseif(strpos($fromVersion, 'biz') !== false) { - if(version_compare($fromVersion, 'biz5.0', '<')) $needProcess['search'] = true; + if(version_compare($fromVersion, 'biz5.0', '<')) $needProcess['search'] = 'notice'; } elseif(version_compare($fromVersion, '15.0.rc1', '<')) { - $needProcess['search'] = true; + $needProcess['search'] = 'notice'; } } $openVersion = $this->getOpenVersion($fromVersion); - if(version_compare($openVersion, '17_4', '<=')) $needProcess['changeEngine'] = true; + if(version_compare($openVersion, '17_4', '<=')) $needProcess['changeEngine'] = 'notice'; return $needProcess; } @@ -4927,17 +4940,17 @@ class upgradeModel extends model if(!$projectID) return print(js::alert($this->lang->upgrade->projectEmpty)); - $this->dao->update(TABLE_BUG)->set('project')->eq($projectID)->where('product')->in($productIdList)->exec(); - $this->dao->update(TABLE_TESTREPORT)->set('project')->eq($projectID)->where('product')->in($productIdList)->exec(); - $this->dao->update(TABLE_TESTSUITE)->set('project')->eq($projectID)->where('product')->in($productIdList)->exec(); + $this->dao->update(TABLE_BUG)->set('project')->eq($projectID)->where('product')->in($productIdList)->andWhere('project')->eq(0)->exec(); + $this->dao->update(TABLE_TESTREPORT)->set('project')->eq($projectID)->where('product')->in($productIdList)->andWhere('project')->eq(0)->exec(); + $this->dao->update(TABLE_TESTSUITE)->set('project')->eq($projectID)->where('product')->in($productIdList)->andWhere('project')->eq(0)->exec(); /* Project linked objects. */ - $this->dao->update(TABLE_TASK)->set('project')->eq($projectID)->where('execution')->in($sprintIdList)->exec(); + $this->dao->update(TABLE_TASK)->set('project')->eq($projectID)->where('execution')->in($sprintIdList)->andWhere('project')->eq(0)->exec(); $this->dao->update(TABLE_BUILD)->set('project')->eq($projectID)->where('execution')->in($sprintIdList)->andWhere('project')->eq(0)->exec(); $this->dao->update(TABLE_BUG)->set('project')->eq($projectID)->where('execution')->in($sprintIdList)->exec(); - $this->dao->update(TABLE_DOC)->set('project')->eq($projectID)->set('type')->eq('execution')->where("lib IN(SELECT id from " . TABLE_DOCLIB . " WHERE type = 'project' and execution " . helper::dbIN($sprintIdList) . ')')->exec(); - $this->dao->update(TABLE_DOCLIB)->set('project')->eq($projectID)->where('type')->eq('execution')->andWhere('execution')->in($sprintIdList)->exec(); - $this->dao->update(TABLE_TESTTASK)->set('project')->eq($projectID)->where('execution')->in($sprintIdList)->exec(); + $this->dao->update(TABLE_DOC)->set('project')->eq($projectID)->set('type')->eq('execution')->where("lib IN(SELECT id from " . TABLE_DOCLIB . " WHERE type = 'project' and execution " . helper::dbIN($sprintIdList) . ')')->andWhere('project')->eq(0)->exec(); + $this->dao->update(TABLE_DOCLIB)->set('project')->eq($projectID)->where('type')->eq('execution')->andWhere('execution')->in($sprintIdList)->andWhere('project')->eq(0)->exec(); + $this->dao->update(TABLE_TESTTASK)->set('project')->eq($projectID)->where('execution')->in($sprintIdList)->andWhere('project')->eq(0)->exec(); /* Put sprint stories into project story mdoule. */ $sprintStories = $this->dao->select('*')->from(TABLE_PROJECTSTORY) @@ -6988,4 +7001,121 @@ class upgradeModel extends model } return !dao::isError(); } + + /** + * Add flow fields. + * + * @param int $version + * @access public + * @return bool + */ + public function addFlowFields($version) + { + $this->loadModel('workflowfield'); + + $upgradeLang = $this->lang->workflowfield->upgrade[$version]; + $upgradeConfig = $this->config->workflowfield->upgrade[$version]; + + $now = helper::now(); + foreach($upgradeLang as $module => $fields) + { + $field = new stdclass(); + $field->buildin = '1'; + $field->role = 'buildin'; + $field->module = $module; + $field->createdBy = $this->app->user->account; + $field->createdDate = $now; + + foreach($fields as $code => $name) + { + $field->field = $code; + $field->name = $name; + + $fieldConfig = isset($upgradeConfig[$module][$code]) ? $upgradeConfig[$module][$code] : array(); + foreach($fieldConfig as $key => $value) $field->$key = $value; + + $this->dao->insert(TABLE_WORKFLOWFIELD)->data($field)->autoCheck()->exec(); + } + } + + return !dao::isError(); + } + + /** + * Process review linkages of approval. + * + * @access public + * @return bool + */ + public function processReviewLinkages() + { + $linkagePairs = $this->dao->select('id, linkages')->from(TABLE_WORKFLOWACTION)->where('action')->eq('approvalreview')->andWhere('role')->eq('approval')->fetchPairs(); + + $oldLinkages = array(); + $oldLinkages[0]['sources'][0]['field'] = 'reviewResult'; + $oldLinkages[0]['sources'][0]['operator'] = '=='; + $oldLinkages[0]['sources'][0]['value'] = 'reject'; + $oldLinkages[0]['targets'][0]['field'] = 'reviewOpinion'; + $oldLinkages[0]['targets'][0]['status'] = 'show'; + + $newLinkages = array(); + $newLinkages[0]['sources'][0]['field'] = 'reviewResult'; + $newLinkages[0]['sources'][0]['operator'] = '=='; + $newLinkages[0]['sources'][0]['value'] = 'pass'; + $newLinkages[0]['targets'][0]['field'] = 'reviewOpinion'; + $newLinkages[0]['targets'][0]['status'] = 'hide'; + + foreach($linkagePairs as $id => $linkages) + { + if(helper::jsonEncode($oldLinkages) == $linkages) + { + $this->dao->update(TABLE_WORKFLOWACTION)->set('linkages')->eq(helper::jsonEncode($newLinkages))->where('id')->eq($id)->exec(); + } + } + + return !dao::isError(); + } + + /** + * Change FULLTEXT index for searchindex table. + * + * @access public + * @return void + */ + public function rebuildFULLTEXT() + { + try + { + $table = TABLE_SEARCHINDEX; + $stmt = $this->dao->query("show index from $table"); + $indexes = array(); + while($index = $stmt->fetch()) + { + if($index->Index_type != 'FULLTEXT') continue; + $indexes[$index->Key_name] = $index->Key_name; + } + + if(!isset($indexes['title_content'])) $this->dao->exec( "ALTER TABLE {$table} ADD FULLTEXT `title_content` (`title`, `content`)"); + if(isset($indexes['title'])) $this->dao->exec( "ALTER TABLE {$table} DROP INDEX `title`"); + if(isset($indexes['content'])) $this->dao->exec( "ALTER TABLE {$table} DROP INDEX `content`"); + } + catch(PDOException $e){} + + return true; + } + + /** + * Check whether the field exists. + * + * @param string $table + * @param string $field + * @access public + * @return bool + */ + public function checkFieldsExists($table, $field) + { + $result = $this->dbh->query("show columns from `$table` like '$field'"); + + return $result->rowCount() > 0; + } } diff --git a/module/upgrade/view/afterexec.html.php b/module/upgrade/view/afterexec.html.php index f3b82cd10c..3d240b4430 100644 --- a/module/upgrade/view/afterexec.html.php +++ b/module/upgrade/view/afterexec.html.php @@ -35,10 +35,10 @@ $(function() finishedShow(); }) $value) +foreach($needProcess as $processKey => $processType) { - $value = $processKey == 'search' ? 'true' : 'false'; - echo 'var ' . $processKey . "Finish = $value;\n"; + if($processType == 'notice') continue; + echo 'var ' . $processKey . "Finish = false;\n"; } ?> @@ -52,9 +52,9 @@ function initHideHome() { var hide = false; $value) + foreach($needProcess as $processKey => $processType) { - if($processKey == 'search') continue; + if($processType == 'notice') continue; echo "hide = true;\n"; break; } @@ -76,8 +76,9 @@ function finishedShow() { var show = true; $value) + foreach($needProcess as $processKey => $processType) { + if($processType == 'notice') continue; echo "if({$processKey}Finish == false) show = false;\n"; } ?> @@ -91,45 +92,8 @@ function finishedShow() $(function() { - $('.col-md-6:first').append("

    upgrade->changeEngine;?>

    "); - changeEngine(); + $('.col-md-6:first').append("

    upgrade->needChangeEngine;?>

    "); }) -function changeEngine() -{ - var link = ''; - var $infoBox = $('#changeEngineBox .info'); - $.ajax( - { - type: "GET", - url: link, - success: function(response) - { - response = JSON.parse(response); - if(response == null) - { - changeEngineFinish = true; - finishedShow(); - } - else if(response.result == 'finished') - { - changeEngineFinish = true; - $infoBox.prepend("
    " + response.message + "
    "); - finishedShow(); - } - else - { - if($infoBox.find('.' + response.table).length == 0) $infoBox.prepend("
    "); - $infoBox.find('.' + response.table).html(response.message); - if(response.next) $infoBox.prepend("
    " + response.nextMessage + "
    "); - changeEngine(); - } - }, - error: function() - { - changeEngine(); - } - }) -} $(function() diff --git a/module/user/model.php b/module/user/model.php index 4e366ef854..7fec646510 100644 --- a/module/user/model.php +++ b/module/user/model.php @@ -796,6 +796,7 @@ class userModel extends model } $this->dao->update(TABLE_USER)->data($user)->autoCheck()->where('id')->eq((int)$userID)->exec(); + $_SESSION['user']->password = $user->password; $this->app->user->password = $user->password; $this->app->user->modifyPassword = false; if(!dao::isError()) diff --git a/test/class/action.class.php b/test/class/action.class.php index 7573b0bc59..82a42b1bfc 100644 --- a/test/class/action.class.php +++ b/test/class/action.class.php @@ -52,6 +52,23 @@ class actionTest return $objects; } + /** + * Get the unread actions. + * + * @param int $actionID + * @access public + * @return object + */ + public function getUnreadActionsTest($actionID = 0) + { + $objects = $this->objectModel->getUnreadActions($actionID); + $objects = json_decode($objects); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + /** * Test get product, project, execution of the object. * @@ -89,6 +106,8 @@ class actionTest $objects[$objectID]->extra = str_replace($dirname, '', $objects[$objectID]->extra); $objects[$objectID]->extra = trim($objects[$objectID]->extra, "\n"); + if(strpos($objects[$objectID]->extra, 'href') !== false) $objects[$objectID]->extra = 'a'; + return $objects[$objectID]; } @@ -128,6 +147,26 @@ class actionTest return $object; } + /** + * getTrashesBySearchTest + * + * @param string $objectType + * @param string $type all|hidden + * @param int $queryID + * @param string $orderBy + * @param object $pager + * @access public + * @return void + */ + public function getTrashesBySearchTest($objectType, $type, $queryID, $orderBy, $pager = null) + { + $objects = $this->objectModel->getTrashesBySearch($objectType, $type, $queryID, $orderBy, $pager); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + /** * Test get deleted objects. * @@ -198,6 +237,44 @@ class actionTest return $objects; } + /** + * Get dynamic show action. + * + * @access public + * @return string + */ + public function getActionConditionTest() + { + $objects = $this->objectModel->getActionCondition(); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + + /** + * Get dynamic by search. + * + * @param array $products + * @param array $projects + * @param array $executions + * @param int $queryID + * @param string $orderBy + * @param object $pager + * @param string $date + * @param string $direction + * @access public + * @return array + */ + public function getDynamicBySearchTest($products, $projects, $executions, $queryID, $orderBy = 'date_desc', $pager = null, $date = '', $direction = 'next') + { + $objects = $this->objectModel->getDynamicBySearch($products, $projects, $executions, $queryID, $orderBy, $pager, $date, $direction); + + if(dao::isError()) return dao::getError(); + + return $objects; + } + /** * Test get actions as dynamic. * @@ -297,31 +374,6 @@ class actionTest return $object; } - /** - * Test set objectLink. - * - * @param int $actionID - * @access public - * @return object - */ - public function setObjectLinkTest($actionID) - { - global $tester; - $deptUsers = isset($tester->app->user->dept) ? $tester->loadModel('dept')->getDeptUserPairs($tester->app->user->dept, 'id') : ''; - - $action = $this->objectModel->getByID($actionID); - $action->objectLabel = $this->objectModel->getObjectLabel($action->objectType, $action->objectID, $action->action, array('25' => '25')); - - $object = $this->objectModel->setObjectLink($action, $deptUsers); - - if(dao::isError()) return dao::getError(); - - $dirname = dirname(__DIR__) . DS; - - $object->objectLink = str_replace($dirname, '', $object->objectLink); - return $object; - } - /** * Test compute the begin date and end date of a period. * @@ -351,6 +403,25 @@ class actionTest if($period == 'lastweek') return $date['begin'] == $begin and $date['end'] == $end . ' 23:59:59'; } + /** + * Delete action by objectType. + * + * @param string $objectType + * @access public + * @return bool + */ + public function deleteByTypeTest($objectType) + { + $this->objectModel->deleteByType($objectType); + + if(dao::isError()) return dao::getError(); + + global $tester; + $objects = $tester->dao->select('*')->from(TABLE_ACTION)->where('objectType')->eq($objectType)->fetchAll(); + + return empty($objects); + } + /** * Test undelete a record. * @@ -423,6 +494,59 @@ class actionTest return $object; } + /** + * Check Has pre or next. + * + * @param string $date + * @param string $direction + * @access public + * @return bool + */ + public function hasPreOrNextTest($date, $direction = 'next') + { + global $tester; + $tester->session->set('actionQueryCondition', '1=1'); + $result = $this->objectModel->hasPreOrNext($date, $direction); + + if(dao::isError()) return dao::getError(); + + return $result; + } + + /** + * Save global search object index information. + * + * @param string $objectType + * @param int $objectID + * @param string $actionType + * @access public + * @return bool + */ + public function saveIndexTest($objectType, $objectID, $actionType) + { + $result = $this->objectModel->saveIndex($objectType, $objectID, $actionType); + + if(dao::isError()) return dao::getError(); + + return $result; + } + + /** + * Process dynamic for API. + * + * @param array $dynamics + * @access public + * @return array + */ + public function processDynamicForAPITest($dynamics) + { + $objects = $this->objectModel->processDynamicForAPI($dynamics); + + if(dao::isError()) return dao::getError(); + + return empty($objects) ? $objects : $objects[0]; + } + /** * Test build date group by actions. * diff --git a/test/class/api.class.php b/test/class/api.class.php index 4d16170329..29e8a21340 100644 --- a/test/class/api.class.php +++ b/test/class/api.class.php @@ -213,13 +213,12 @@ class apiTest public function getReleaseListByApiTest($libID, $id = 0, $confirm = true) { $objects = $this->objectModel->getReleaseListByApi($libID); - a($objects); if(dao::isError()) return dao::getError(); if($confirm) $this->objectModel->deleteRelease($objects[$id]->id); - return $objects; + return $objects[$id]; } /** diff --git a/test/class/block.class.php b/test/class/block.class.php index 8b61f69ee6..e0f555367a 100644 --- a/test/class/block.class.php +++ b/test/class/block.class.php @@ -158,7 +158,7 @@ class blockTest $object->blockversion = $tester->loadModel('setting')->getItem("owner=$account&module=$module§ion=block&key=initVersion"); $blockData = $this->objectModel->getBlockList($module, $type); - $object->blockData = current($blockData); + $object->blockData = empty($module) ? 0 : current($blockData); return $object; } @@ -311,6 +311,12 @@ class blockTest return $objects->count; } + /** + * Get project params. + * + * @access public + * @return string + */ public function getProjectParamsTest() { $objects = $this->objectModel->getProjectParams(); @@ -320,6 +326,12 @@ class blockTest return $objects; } + /** + * Get project team params. + * + * @access public + * @return string + */ public function getProjectTeamParamsTest() { $objects = $this->objectModel->getProjectTeamParams(); @@ -364,13 +376,37 @@ class blockTest return $objects; } + /** + * Get product params. + * + * @access public + * @return string + */ public function getProductParamsTest() { $objects = $this->objectModel->getProductParams(); - if(dao::isError()) return dao::getError(); - return $objects; + $return = ''; + $objects = json_decode($objects); + foreach($objects as $type => $params) + { + $return .= "$type:{"; + foreach($params as $param => $paramValue) + { + if(is_object($paramValue)) + { + foreach($paramValue as $key => $value) $return .= "$key=>$value,"; + } + else + { + $return .= "$param:$paramValue,"; + } + } + $return = trim($return, ','); + $return .= '};'; + } + return $return; } /** @@ -389,13 +425,37 @@ class blockTest return json_encode(json_decode($objects), JSON_UNESCAPED_UNICODE); } + /** + * Get product statistic params. + * + * @access public + * @return string + */ public function getProductStatisticParamsTest() { $objects = $this->objectModel->getProductStatisticParams(); - if(dao::isError()) return dao::getError(); - return $objects; + $return = ''; + $objects = json_decode($objects); + foreach($objects as $type => $params) + { + $return .= "$type:{"; + foreach($params as $param => $paramValue) + { + if(is_object($paramValue)) + { + foreach($paramValue as $key => $value) $return .= "$key=>$value,"; + } + else + { + $return .= "$param:$paramValue,"; + } + } + $return = trim($return, ','); + $return .= '};'; + } + return $return; } /** @@ -428,6 +488,12 @@ class blockTest return $objects; } + /** + * Get qa statistic params. + * + * @access public + * @return object + */ public function getQaStatisticParamsTest() { $object = $this->objectModel->getQaStatisticParams(); @@ -437,15 +503,6 @@ class blockTest return json_decode($object); } - public function getRecentProjectParamsTest() - { - $objects = $this->objectModel->getRecentProjectParams(); - - if(dao::isError()) return dao::getError(); - - return $objects; - } - /** * Test get waterfall issue param. * @@ -578,6 +635,13 @@ class blockTest return $bool ? 1 : 2; } + /** + * Check API for ranzhi. + * + * @param string $hash + * @access public + * @return bool + */ public function checkAPITest($hash) { $objects = $this->objectModel->checkAPI($hash); @@ -602,6 +666,13 @@ class blockTest return $objects; } + /** + * Get scrum project list params. + * + * @param string $module + * @access public + * @return string + */ public function getScrumListParamsTest($module = '') { $objects = $this->objectModel->getScrumListParams($module = ''); @@ -613,15 +684,6 @@ class blockTest return $objects->type; } - public function getScrumOverviewParamsTest($module = '') - { - $objects = $this->objectModel->getScrumOverviewParams($module = ''); - - if(dao::isError()) return dao::getError(); - - return $objects; - } - /** * Get scrum roadmap list params. * @@ -652,22 +714,31 @@ class blockTest return $objects; } - public function getProjectDynamicParamsTest($module = '') + public function getProjectDynamicParamsTest() { - $objects = $this->objectModel->getProjectDynamicParams($module = ''); - + $objects = $this->objectModel->getProjectDynamicParams(); if(dao::isError()) return dao::getError(); - return $objects; - } - - public function getSprintParamsTest($module = '') - { - $objects = $this->objectModel->getSprintParams($module = ''); - - if(dao::isError()) return dao::getError(); - - return $objects; + $return = ''; + $objects = json_decode($objects); + foreach($objects as $type => $params) + { + $return .= "$type:{"; + foreach($params as $param => $paramValue) + { + if(is_object($paramValue)) + { + foreach($paramValue as $key => $value) $return .= "$key=>$value,"; + } + else + { + $return .= "$param:$paramValue,"; + } + } + $return = trim($return, ','); + $return .= '};'; + } + return $return; } /** diff --git a/test/class/branch.class.php b/test/class/branch.class.php index 2c12d9c7cd..d5d741bdf9 100644 --- a/test/class/branch.class.php +++ b/test/class/branch.class.php @@ -318,6 +318,24 @@ class branchTest return $objects ? 1 : 2; } + /** + * Test check branch data. + * + * @param int $branchID + * @access public + * @return int + */ + public function setDefaultTest($productID, $branchID) + { + $this->objectModel->setDefault($productID, $branchID); + + if(dao::isError()) return dao::getError(); + + $object = $this->objectModel->getById($branchID, $productID, ''); + + return $object; + } + /** * Test get branches of product which linked project. * diff --git a/test/class/caselib.class.php b/test/class/caselib.class.php index 19523316be..805c9250fb 100644 --- a/test/class/caselib.class.php +++ b/test/class/caselib.class.php @@ -7,28 +7,11 @@ class caselibTest $this->objectModel = $tester->loadModel('caselib'); } - /** - * Set lib menu test. - * - * @param mixed $libraries - * @param mixed $libID - * @access public - * @return void - */ - public function setLibMenuTest($libraries, $libID) - { - $objects = $this->objectModel->setLibMenu($libraries, $libID); - - if(dao::isError()) return dao::getError(); - - return $objects; - } - /** * Save lib state test. - * - * @param int $libID - * @param array $libraries + * + * @param int $libID + * @param array $libraries * @access public * @return void */ @@ -43,9 +26,9 @@ class caselibTest /** * Get by ID test. - * - * @param mixed $libID - * @param mixed $setImgSize + * + * @param mixed $libID + * @param mixed $setImgSize * @access public * @return void */ @@ -60,8 +43,8 @@ class caselibTest /** * Update test. - * - * @param mixed $libID + * + * @param mixed $libID * @access public * @return void */ @@ -78,9 +61,9 @@ class caselibTest /** * Delete test. - * - * @param mixed $libID - * @param string $table + * + * @param mixed $libID + * @param string $table * @access public * @return void */ @@ -97,7 +80,7 @@ class caselibTest /** * Get libraries test. - * + * * @access public * @return void */ @@ -112,9 +95,9 @@ class caselibTest /** * Get list test. - * - * @param string $orderBy - * @param mixed $pager + * + * @param string $orderBy + * @param mixed $pager * @access public * @return void */ @@ -129,8 +112,8 @@ class caselibTest /** * Create test. - * - * @param mixed $param + * + * @param mixed $param * @access public * @return void */ @@ -149,13 +132,13 @@ class caselibTest /** * Get libcases test. - * - * @param mixed $libID - * @param mixed $browseType - * @param int $queryID - * @param int $moduleID - * @param string $sort - * @param mixed $pager + * + * @param mixed $libID + * @param mixed $browseType + * @param int $queryID + * @param int $moduleID + * @param string $sort + * @param mixed $pager * @access public * @return void */ @@ -168,47 +151,10 @@ class caselibTest return $objects; } - /** - * Build searchform test. - * - * @param mixed $libID - * @param mixed $libraries - * @param mixed $queryID - * @param mixed $actionURL - * @access public - * @return void - */ - public function buildSearchFormTest($libID, $libraries, $queryID, $actionURL) - { - $objects = $this->objectModel->buildSearchForm($libID, $libraries, $queryID, $actionURL); - - if(dao::isError()) return dao::getError(); - - return $objects; - } - - /** - * Get liblink test. - * - * @param mixed $module - * @param mixed $method - * @param mixed $extra - * @access public - * @return void - */ - public function getLibLinkTest($module, $method, $extra) - { - $objects = $this->objectModel->getLibLink($module, $method, $extra); - - if(dao::isError()) return dao::getError(); - - return $objects; - } - /** * Create from import test. - * - * @param mixed $libID + * + * @param mixed $libID * @access public * @return void */ @@ -223,8 +169,8 @@ class caselibTest /** * Batch create case test. - * - * @param mixed $libID + * + * @param mixed $libID * @access public * @return void */ diff --git a/test/data/zt_config.sql b/test/data/zt_config.sql index 1c994dfebe..824053672e 100644 --- a/test/data/zt_config.sql +++ b/test/data/zt_config.sql @@ -34,4 +34,5 @@ INSERT INTO `zt_config` (`id`, `vision`, `owner`, `module`, `section`, `key`, `v (33, 'rnd', 'system', 'common', 'global', 'skipIntroduction', ',admin'), (34, 'rnd', 'system', 'common', 'global', 'skipTutorial', ',admin'), (35, 'rnd', 'system', 'common', 'global', 'skipYoungBlueTheme', ',admin'), -(36, 'rnd', 'system', 'common', 'global', ' scoreStatus', '1'); +(36, 'rnd', 'system', 'common', 'global', 'scoreStatus', '1'), +(37, 'rnd', 'system', 'sso', '' , 'key', '858640a724c2c981983935eb2bbc4ad8'); diff --git a/test/model/action/create.php b/test/model/action/create.php index 92bfb754ad..df0e5c9023 100755 --- a/test/model/action/create.php +++ b/test/model/action/create.php @@ -33,6 +33,5 @@ r($action->createTest($objectTypeList[1], $objectIDList[1], $actionTypeList[1])) r($action->createTest($objectTypeList[2], $objectIDList[0], $actionTypeList[2])) && p('objectType,objectId,action,comment') && e('user,,login,'); // 测试创建user 1 login动态 r($action->createTest($objectTypeList[3], $objectIDList[0], $actionTypeList[3])) && p('objectType,objectId,action,comment') && e('bug,,closed,'); // 测试创建bug 1 closed动态 r($action->createTest($objectTypeList[4], $objectIDList[0], $actionTypeList[4], $comment)) && p('objectType,objectId,action,comment') && e('story,,comments,测试备注'); // 测试创建story 1 comment动态 -r($action->createTest($objectTypeList[4], $objectIDList[0], $actionTypeList[4])) && p() && e(''); // 测试创建story 1 comment动态 不填写备注 r($action->createTest($objectTypeList[2], $objectIDList[0], $actionTypeList[5], '', '', $actor)) && p() && e('0'); // 测试创建游客 logout动态 -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/action/deletebytype.php b/test/model/action/deletebytype.php new file mode 100755 index 0000000000..53a04dbbc1 --- /dev/null +++ b/test/model/action/deletebytype.php @@ -0,0 +1,25 @@ +#!/usr/bin/env php +switchDB(); +su('admin'); + +/** + +title=测试 actionModel->deleteByType(); +cid=1 +pid=1 + +测试删除object为空动态 >> 1 +测试删除objectType为story的动态 >> 1 +测试删除objectType为不存在的test的动态 >> 1 + +*/ + +$action = new actionTest(); + +r($action->deleteByTypeTest('')) && p() && e('1'); // 测试删除object为空动态 +r($action->deleteByTypeTest('story')) && p() && e('1'); // 测试删除objectType为story的动态 +r($action->deleteByTypeTest('test')) && p() && e('1'); // 测试删除objectType为不存在的test的动态 +$db->restoreDB(); diff --git a/test/model/action/getactioncondition.php b/test/model/action/getactioncondition.php new file mode 100755 index 0000000000..9d2a47b91d --- /dev/null +++ b/test/model/action/getactioncondition.php @@ -0,0 +1,19 @@ +#!/usr/bin/env php +getActionCondition(); +cid=1 +pid=1 + +获取用户可以看到的动态的条件 >> 0 + +*/ + +$action = new actionTest(); + +r($action->getActionConditionTest()) && p() && e('0'); // 获取用户可以看到的动态的条件 diff --git a/test/model/action/getdynamic.php b/test/model/action/getdynamic.php index 9389bba19a..8e56592737 100755 --- a/test/model/action/getdynamic.php +++ b/test/model/action/getdynamic.php @@ -10,23 +10,23 @@ title=测试 actionModel->getDynamic(); cid=1 pid=1 -查找全部动态 >> 100 -查找用户admin动态 >> 34 -查找用户dev17动态 >> 33 -查找用户test18动态 >> 33 +查找全部动态 >> 90 +查找用户admin动态 >> 30 +查找用户dev17动态 >> 30 +查找用户test18动态 >> 30 查找今天的动态 >> 3 查找昨天的动态 >> 3 查找上周的动态 >> 21 -查找产品1的动态 >> 1 -查找产品2的动态 >> 1 -查找产品3的动态 >> 1 -查找项目1的动态 >> 1 -查找项目2的动态 >> 1 -查找项目3的动态 >> 1 +查找产品1的动态 >> 0 +查找产品2的动态 >> 0 +查找产品3的动态 >> 0 +查找项目1的动态 >> 0 +查找项目2的动态 >> 0 +查找项目3的动态 >> 0 查找执行1的动态 >> 0 查找执行2的动态 >> 0 查找执行3的动态 >> 0 -查找今天的动态 >> 97 +查找今天的动态 >> 87 */ @@ -39,20 +39,20 @@ $dateList = array('', 'today'); $action = new actionTest(); -r($action->getDynamicTest()) && p() && e('100'); // 查找全部动态 -r($action->getDynamicTest($accountList[1])) && p() && e('34'); // 查找用户admin动态 -r($action->getDynamicTest($accountList[2])) && p() && e('33'); // 查找用户dev17动态 -r($action->getDynamicTest($accountList[3])) && p() && e('33'); // 查找用户test18动态 +r($action->getDynamicTest()) && p() && e('90'); // 查找全部动态 +r($action->getDynamicTest($accountList[1])) && p() && e('30'); // 查找用户admin动态 +r($action->getDynamicTest($accountList[2])) && p() && e('30'); // 查找用户dev17动态 +r($action->getDynamicTest($accountList[3])) && p() && e('30'); // 查找用户test18动态 r($action->getDynamicTest($accountList[0], $typeList[1])) && p() && e('3'); // 查找今天的动态 r($action->getDynamicTest($accountList[0], $typeList[2])) && p() && e('3'); // 查找昨天的动态 r($action->getDynamicTest($accountList[0], $typeList[3])) && p() && e('21'); // 查找上周的动态 -r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[1])) && p() && e('1'); // 查找产品1的动态 -r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[2])) && p() && e('1'); // 查找产品2的动态 -r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[3])) && p() && e('1'); // 查找产品3的动态 -r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[0], $projectIDList[1])) && p() && e('1'); // 查找项目1的动态 -r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[0], $projectIDList[2])) && p() && e('1'); // 查找项目2的动态 -r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[0], $projectIDList[3])) && p() && e('1'); // 查找项目3的动态 +r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[1])) && p() && e('0'); // 查找产品1的动态 +r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[2])) && p() && e('0'); // 查找产品2的动态 +r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[3])) && p() && e('0'); // 查找产品3的动态 +r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[0], $projectIDList[1])) && p() && e('0'); // 查找项目1的动态 +r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[0], $projectIDList[2])) && p() && e('0'); // 查找项目2的动态 +r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[0], $projectIDList[3])) && p() && e('0'); // 查找项目3的动态 r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[0], $projectIDList[0], $executionIDList[1])) && p() && e('0'); // 查找执行1的动态 r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[0], $projectIDList[0], $executionIDList[2])) && p() && e('0'); // 查找执行2的动态 r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[0], $projectIDList[0], $executionIDList[3])) && p() && e('0'); // 查找执行3的动态 -r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[0], $projectIDList[0], $executionIDList[0], $dateList[1])) && p() && e('97'); // 查找今天的动态 \ No newline at end of file +r($action->getDynamicTest($accountList[0], $typeList[0], $productIDList[0], $projectIDList[0], $executionIDList[0], $dateList[1])) && p() && e('87'); // 查找今天的动态 diff --git a/test/model/action/getdynamicbysearch.php b/test/model/action/getdynamicbysearch.php new file mode 100755 index 0000000000..00309e636f --- /dev/null +++ b/test/model/action/getdynamicbysearch.php @@ -0,0 +1,46 @@ +#!/usr/bin/env php +getDynamicBySearch(); +cid=1 +pid=1 + +获取product all, project all, execution all排序为date倒序的所有动态 >> 64,testsuite +获取product all, project all, execution all排序为date正序的所有动态 >> 33,case +获取product 1, project all, execution all排序为date倒序的所有动态 >> 64,testsuite +获取product 1, project all, execution all排序为date正序的所有动态 >> 33,case +获取product all, project 1, execution all排序为date倒序的所有动态 >> 64,testsuite +获取product all, project 1, execution all排序为date正序的所有动态 >> 33,case +获取product all, project all, execution 1排序为date倒序的所有动态 >> 64,testsuite +获取product all, project all, execution 1排序为date正序的所有动态 >> 33,case +获取product all, project all, execution all排序为date倒序的今天之前的动态 >> 33,case +获取product all, project all, execution all排序为date倒序的今天之后的动态 >> 0 + +*/ + +$products = array('all', 1, 2, 3); +$projects = array('all', 1, 2, 3); +$executions = array('all', 1, 2, 3); +$queryID = 0; +$orderByList = array('date_desc', 'date_asc'); +$pager = null; +$dateList = array('', 'today'); +$directionList = array('next', 'pre'); + +$action = new actionTest(); + +r($action->getDynamicBySearchTest($products[0], $projects[0], $executions[0], $queryID, $orderByList[0], $pager, $dateList[0], $directionList[0])) && p('1:id,objectType') && e('64,testsuite'); // 获取product all, project all, execution all排序为date倒序的所有动态 +r($action->getDynamicBySearchTest($products[0], $projects[0], $executions[0], $queryID, $orderByList[1], $pager, $dateList[0], $directionList[0])) && p('1:id,objectType') && e('33,case'); // 获取product all, project all, execution all排序为date正序的所有动态 +r($action->getDynamicBySearchTest($products[1], $projects[0], $executions[0], $queryID, $orderByList[0], $pager, $dateList[0], $directionList[0])) && p('1:id,objectType') && e('64,testsuite'); // 获取product 1, project all, execution all排序为date倒序的所有动态 +r($action->getDynamicBySearchTest($products[1], $projects[0], $executions[0], $queryID, $orderByList[1], $pager, $dateList[0], $directionList[0])) && p('1:id,objectType') && e('33,case'); // 获取product 1, project all, execution all排序为date正序的所有动态 +r($action->getDynamicBySearchTest($products[0], $projects[1], $executions[0], $queryID, $orderByList[0], $pager, $dateList[0], $directionList[0])) && p('1:id,objectType') && e('64,testsuite'); // 获取product all, project 1, execution all排序为date倒序的所有动态 +r($action->getDynamicBySearchTest($products[0], $projects[1], $executions[0], $queryID, $orderByList[1], $pager, $dateList[0], $directionList[0])) && p('1:id,objectType') && e('33,case'); // 获取product all, project 1, execution all排序为date正序的所有动态 +r($action->getDynamicBySearchTest($products[0], $projects[0], $executions[1], $queryID, $orderByList[0], $pager, $dateList[0], $directionList[0])) && p('1:id,objectType') && e('64,testsuite'); // 获取product all, project all, execution 1排序为date倒序的所有动态 +r($action->getDynamicBySearchTest($products[0], $projects[0], $executions[1], $queryID, $orderByList[1], $pager, $dateList[0], $directionList[0])) && p('1:id,objectType') && e('33,case'); // 获取product all, project all, execution 1排序为date正序的所有动态 +r($action->getDynamicBySearchTest($products[0], $projects[0], $executions[0], $queryID, $orderByList[1], $pager, $dateList[1], $directionList[0])) && p('1:id,objectType') && e('33,case'); // 获取product all, project all, execution all排序为date倒序的今天之前的动态 +r($action->getDynamicBySearchTest($products[0], $projects[0], $executions[0], $queryID, $orderByList[1], $pager, $dateList[1], $directionList[1])) && p() && e('0'); // 获取product all, project all, execution all排序为date倒序的今天之后的动态 diff --git a/test/model/action/getlist.php b/test/model/action/getlist.php index d713cafcbb..c02d3a3d1c 100755 --- a/test/model/action/getlist.php +++ b/test/model/action/getlist.php @@ -27,11 +27,11 @@ pid=1 测试获取objectType todo objectId 15的动态信息 >> 15,test18,1 测试获取objectType branch objectId 16的动态信息 >> 16,admin,1 测试获取objectType module objectId 17的动态信息 >> 17,dev17,1 -测试获取objectType testsuite objectId 18的动态信息 >> 18,test18,#1 项目集1 +测试获取objectType testsuite objectId 18的动态信息 >> 18,test18,a 测试获取objectType caselib objectId 19的动态信息 >> 19,admin,1 测试获取objectType testreport objectId 20的动态信息 >> 20,dev17,1 测试获取objectType entry objectId 21的动态信息 >> 21,test18,1 -测试获取objectType webhook objectId 22的动态信息 >> 22,admin,1 +测试获取objectType webhook objectId 22的动态信息 >> 22,admin,a 测试获取objectType review objectId 23的动态信息 >> 23,dev17,1 测试获取objectType product objectId 24的动态信息 >> 24,test18,1 测试获取objectType story objectId 25的动态信息 >> 25,admin,1 @@ -48,7 +48,7 @@ pid=1 测试获取objectType doc objectId 36的动态信息 >> 36,test18,1 测试获取objectType doclib objectId 37的动态信息 >> 37,admin,1 测试获取objectType todo objectId 38的动态信息 >> 38,dev17,1 -测试获取objectType branch objectId 39的动态信息 >> 39,test18,项目版本版本1 +测试获取objectType branch objectId 39的动态信息 >> 39,test18,a */ @@ -57,42 +57,42 @@ $objectId = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23, $action = new actionTest(); -r($action->getListTest($objectType[0], $objectId[0])) && p('id,actor,extra') && e("1,admin,1"); // 测试获取objectType product objectId 1的动态信息 -r($action->getListTest($objectType[1], $objectId[1])) && p('id,actor,extra') && e("2,dev17,1"); // 测试获取objectType story objectId 2的动态信息 -r($action->getListTest($objectType[2], $objectId[2])) && p('id,actor,extra') && e("3,test18,1"); // 测试获取objectType productplan objectId 3的动态信息 -r($action->getListTest($objectType[3], $objectId[3])) && p('id,actor,extra') && e("4,admin,1"); // 测试获取objectType release objectId 4的动态信息 -r($action->getListTest($objectType[4], $objectId[4])) && p('id,actor,extra') && e("5,dev17,11"); // 测试获取objectType project objectId 5的动态信息 -r($action->getListTest($objectType[5], $objectId[5])) && p('id,actor,extra') && e("6,test18,1"); // 测试获取objectType task objectId 6的动态信息 -r($action->getListTest($objectType[6], $objectId[6])) && p('id,actor,extra') && e("7,admin,1"); // 测试获取objectType build objectId 7的动态信息 -r($action->getListTest($objectType[7], $objectId[7])) && p('id,actor,extra') && e("8,dev17,1"); // 测试获取objectType bug objectId 8的动态信息 -r($action->getListTest($objectType[8], $objectId[8])) && p('id,actor,extra') && e("9,test18,2"); // 测试获取objectType testcase objectId 9的动态信息 -r($action->getListTest($objectType[9], $objectId[9])) && p('id,actor,extra') && e("10,admin,1"); // 测试获取objectType case objectId 10的动态信息 -r($action->getListTest($objectType[10], $objectId[10])) && p('id,actor,extra') && e("11,dev17,1"); // 测试获取objectType testtask objectId 11的动态信息 -r($action->getListTest($objectType[11], $objectId[11])) && p('id,actor,extra') && e("12,test18,1"); // 测试获取objectType user objectId 12的动态信息 -r($action->getListTest($objectType[12], $objectId[12])) && p('id,actor,extra') && e("13,admin,1"); // 测试获取objectType doc objectId 13的动态信息 -r($action->getListTest($objectType[13], $objectId[13])) && p('id,actor,extra') && e("14,dev17,1"); // 测试获取objectType doclib objectId 14的动态信息 -r($action->getListTest($objectType[14], $objectId[14])) && p('id,actor,extra') && e("15,test18,1"); // 测试获取objectType todo objectId 15的动态信息 -r($action->getListTest($objectType[15], $objectId[15])) && p('id,actor,extra') && e("16,admin,1"); // 测试获取objectType branch objectId 16的动态信息 -r($action->getListTest($objectType[16], $objectId[16])) && p('id,actor,extra') && e("17,dev17,1"); // 测试获取objectType module objectId 17的动态信息 -r($action->getListTest($objectType[17], $objectId[17])) && p('id,actor,extra') && e("18,test18,#1 项目集1"); // 测试获取objectType testsuite objectId 18的动态信息 -r($action->getListTest($objectType[18], $objectId[18])) && p('id,actor,extra') && e("19,admin,1"); // 测试获取objectType caselib objectId 19的动态信息 -r($action->getListTest($objectType[19], $objectId[19])) && p('id,actor,extra') && e("20,dev17,1"); // 测试获取objectType testreport objectId 20的动态信息 -r($action->getListTest($objectType[20], $objectId[20])) && p('id,actor,extra') && e("21,test18,1"); // 测试获取objectType entry objectId 21的动态信息 -r($action->getListTest($objectType[21], $objectId[21])) && p('id,actor,extra') && e("22,admin,1"); // 测试获取objectType webhook objectId 22的动态信息 -r($action->getListTest($objectType[22], $objectId[22])) && p('id,actor,extra') && e("23,dev17,1"); // 测试获取objectType review objectId 23的动态信息 -r($action->getListTest($objectType[0], $objectId[23])) && p('id,actor,extra') && e("24,test18,1"); // 测试获取objectType product objectId 24的动态信息 -r($action->getListTest($objectType[1], $objectId[24])) && p('id,actor,extra') && e("25,admin,1"); // 测试获取objectType story objectId 25的动态信息 -r($action->getListTest($objectType[2], $objectId[25])) && p('id,actor,extra') && e("26,dev17,1"); // 测试获取objectType productplan objectId 26的动态信息 -r($action->getListTest($objectType[3], $objectId[26])) && p('id,actor,extra') && e("27,test18,1"); // 测试获取objectType release objectId 27的动态信息 -r($action->getListTest($objectType[4], $objectId[27])) && p('id,actor,extra') && e("28,admin,33"); // 测试获取objectType project objectId 28的动态信息 -r($action->getListTest($objectType[5], $objectId[28])) && p('id,actor,extra') && e("29,dev17,1"); // 测试获取objectType task objectId 29的动态信息 -r($action->getListTest($objectType[6], $objectId[29])) && p('id,actor,extra') && e("30,test18,1"); // 测试获取objectType build objectId 30的动态信息 -r($action->getListTest($objectType[7], $objectId[30])) && p('id,actor,extra') && e("31,admin,1"); // 测试获取objectType bug objectId 31的动态信息 -r($action->getListTest($objectType[8], $objectId[31])) && p('id,actor,extra') && e("32,项目经理17,1"); // 测试获取objectType testcase objectId 32的动态信息 -r($action->getListTest($objectType[9], $objectId[32])) && p('id,actor,extra') && e("33,test18,1"); // 测试获取objectType case objectId 33的动态信息 -r($action->getListTest($objectType[10], $objectId[33])) && p('id,actor,extra') && e("34,admin,1"); // 测试获取objectType testtask objectId 34的动态信息 -r($action->getListTest($objectType[11], $objectId[34])) && p('id,actor,extra') && e("35,dev17,1"); // 测试获取objectType user objectId 35的动态信息 -r($action->getListTest($objectType[12], $objectId[35])) && p('id,actor,extra') && e("36,test18,1"); // 测试获取objectType doc objectId 36的动态信息 -r($action->getListTest($objectType[13], $objectId[36])) && p('id,actor,extra') && e("37,admin,1"); // 测试获取objectType doclib objectId 37的动态信息 -r($action->getListTest($objectType[14], $objectId[37])) && p('id,actor,extra') && e("38,dev17,1"); // 测试获取objectType todo objectId 38的动态信息 -r($action->getListTest($objectType[15], $objectId[38])) && p('id,actor,extra') && e("39,test18,项目版本版本1"); // 测试获取objectType branch objectId 39的动态信息 \ No newline at end of file +r($action->getListTest($objectType[0], $objectId[0])) && p('id,actor,extra') && e("1,admin,1"); // 测试获取objectType product objectId 1的动态信息 +r($action->getListTest($objectType[1], $objectId[1])) && p('id,actor,extra') && e("2,dev17,1"); // 测试获取objectType story objectId 2的动态信息 +r($action->getListTest($objectType[2], $objectId[2])) && p('id,actor,extra') && e("3,test18,1"); // 测试获取objectType productplan objectId 3的动态信息 +r($action->getListTest($objectType[3], $objectId[3])) && p('id,actor,extra') && e("4,admin,1"); // 测试获取objectType release objectId 4的动态信息 +r($action->getListTest($objectType[4], $objectId[4])) && p('id,actor,extra') && e("5,dev17,11"); // 测试获取objectType project objectId 5的动态信息 +r($action->getListTest($objectType[5], $objectId[5])) && p('id,actor,extra') && e("6,test18,1"); // 测试获取objectType task objectId 6的动态信息 +r($action->getListTest($objectType[6], $objectId[6])) && p('id,actor,extra') && e("7,admin,1"); // 测试获取objectType build objectId 7的动态信息 +r($action->getListTest($objectType[7], $objectId[7])) && p('id,actor,extra') && e("8,dev17,1"); // 测试获取objectType bug objectId 8的动态信息 +r($action->getListTest($objectType[8], $objectId[8])) && p('id,actor,extra') && e("9,test18,2"); // 测试获取objectType testcase objectId 9的动态信息 +r($action->getListTest($objectType[9], $objectId[9])) && p('id,actor,extra') && e("10,admin,1"); // 测试获取objectType case objectId 10的动态信息 +r($action->getListTest($objectType[10], $objectId[10])) && p('id,actor,extra') && e("11,dev17,1"); // 测试获取objectType testtask objectId 11的动态信息 +r($action->getListTest($objectType[11], $objectId[11])) && p('id,actor,extra') && e("12,test18,1"); // 测试获取objectType user objectId 12的动态信息 +r($action->getListTest($objectType[12], $objectId[12])) && p('id,actor,extra') && e("13,admin,1"); // 测试获取objectType doc objectId 13的动态信息 +r($action->getListTest($objectType[13], $objectId[13])) && p('id,actor,extra') && e("14,dev17,1"); // 测试获取objectType doclib objectId 14的动态信息 +r($action->getListTest($objectType[14], $objectId[14])) && p('id,actor,extra') && e("15,test18,1"); // 测试获取objectType todo objectId 15的动态信息 +r($action->getListTest($objectType[15], $objectId[15])) && p('id,actor,extra') && e("16,admin,1"); // 测试获取objectType branch objectId 16的动态信息 +r($action->getListTest($objectType[16], $objectId[16])) && p('id,actor,extra') && e("17,dev17,1"); // 测试获取objectType module objectId 17的动态信息 +r($action->getListTest($objectType[17], $objectId[17])) && p('id,actor,extra') && e("18,test18,a"); // 测试获取objectType testsuite objectId 18的动态信息 +r($action->getListTest($objectType[18], $objectId[18])) && p('id,actor,extra') && e("19,admin,1"); // 测试获取objectType caselib objectId 19的动态信息 +r($action->getListTest($objectType[19], $objectId[19])) && p('id,actor,extra') && e("20,dev17,1"); // 测试获取objectType testreport objectId 20的动态信息 +r($action->getListTest($objectType[20], $objectId[20])) && p('id,actor,extra') && e("21,test18,1"); // 测试获取objectType entry objectId 21的动态信息 +r($action->getListTest($objectType[21], $objectId[21])) && p('id,actor,extra') && e("22,admin,a"); // 测试获取objectType webhook objectId 22的动态信息 +r($action->getListTest($objectType[22], $objectId[22])) && p('id,actor,extra') && e("23,dev17,1"); // 测试获取objectType review objectId 23的动态信息 +r($action->getListTest($objectType[0], $objectId[23])) && p('id,actor,extra') && e("24,test18,1"); // 测试获取objectType product objectId 24的动态信息 +r($action->getListTest($objectType[1], $objectId[24])) && p('id,actor,extra') && e("25,admin,1"); // 测试获取objectType story objectId 25的动态信息 +r($action->getListTest($objectType[2], $objectId[25])) && p('id,actor,extra') && e("26,dev17,1"); // 测试获取objectType productplan objectId 26的动态信息 +r($action->getListTest($objectType[3], $objectId[26])) && p('id,actor,extra') && e("27,test18,1"); // 测试获取objectType release objectId 27的动态信息 +r($action->getListTest($objectType[4], $objectId[27])) && p('id,actor,extra') && e("28,admin,33"); // 测试获取objectType project objectId 28的动态信息 +r($action->getListTest($objectType[5], $objectId[28])) && p('id,actor,extra') && e("29,dev17,1"); // 测试获取objectType task objectId 29的动态信息 +r($action->getListTest($objectType[6], $objectId[29])) && p('id,actor,extra') && e("30,test18,1"); // 测试获取objectType build objectId 30的动态信息 +r($action->getListTest($objectType[7], $objectId[30])) && p('id,actor,extra') && e("31,admin,1"); // 测试获取objectType bug objectId 31的动态信息 +r($action->getListTest($objectType[8], $objectId[31])) && p('id,actor,extra') && e("32,项目经理17,1"); // 测试获取objectType testcase objectId 32的动态信息 +r($action->getListTest($objectType[9], $objectId[32])) && p('id,actor,extra') && e("33,test18,1"); // 测试获取objectType case objectId 33的动态信息 +r($action->getListTest($objectType[10], $objectId[33])) && p('id,actor,extra') && e("34,admin,1"); // 测试获取objectType testtask objectId 34的动态信息 +r($action->getListTest($objectType[11], $objectId[34])) && p('id,actor,extra') && e("35,dev17,1"); // 测试获取objectType user objectId 35的动态信息 +r($action->getListTest($objectType[12], $objectId[35])) && p('id,actor,extra') && e("36,test18,1"); // 测试获取objectType doc objectId 36的动态信息 +r($action->getListTest($objectType[13], $objectId[36])) && p('id,actor,extra') && e("37,admin,1"); // 测试获取objectType doclib objectId 37的动态信息 +r($action->getListTest($objectType[14], $objectId[37])) && p('id,actor,extra') && e("38,dev17,1"); // 测试获取objectType todo objectId 38的动态信息 +r($action->getListTest($objectType[15], $objectId[38])) && p('id,actor,extra') && e("39,test18,a"); // 测试获取objectType branch objectId 39的动态信息 diff --git a/test/model/action/getobjectlabel.php b/test/model/action/getobjectlabel.php index d2a192961d..fd8ccd2037 100755 --- a/test/model/action/getobjectlabel.php +++ b/test/model/action/getobjectlabel.php @@ -25,7 +25,7 @@ pid=1 测试获取objectType doclib objectId 14的动态信息 >> 文档库|doc|tablecontents|type=%s&objectID=%s&libID=%s 测试获取objectType todo objectId 15的动态信息 >> 待办|todo|view|todoID=%s 测试获取objectType branch objectId 16的动态信息 >> branch -测试获取objectType module objectId 17的动态信息 >> module +测试获取objectType module objectId 17的动态信息 >> 模块|tree|browse|productid=%s&type=story¤tModuleID=0&branch=all 测试获取objectType testsuite objectId 18的动态信息 >> 测试套件|testsuite|view|suiteID=%s 测试获取objectType caselib objectId 19的动态信息 >> 用例库|caselib|view|libID=%s 测试获取objectType testreport objectId 20的动态信息 >> 报告|testreport|view|report=%s @@ -43,26 +43,26 @@ $requirements = array('25' => '25'); $action = new actionTest(); -r($action->getObjectLabelTest($objectType[0], $objectId[0], $actionType[0], $requirements)) && p() && e('产品|product|view|productID=%s'); // 测试获取objectType product objectId 1的动态信息 -r($action->getObjectLabelTest($objectType[1], $objectId[1], $actionType[1], $requirements)) && p() && e('研发需求|story|view|storyID=%s'); // 测试获取objectType story objectId 2的动态信息 -r($action->getObjectLabelTest($objectType[2], $objectId[2], $actionType[2], $requirements)) && p() && e('计划|productplan|view|productID=%s'); // 测试获取objectType productplan objectId 3的动态信息 -r($action->getObjectLabelTest($objectType[3], $objectId[3], $actionType[3], $requirements)) && p() && e('发布|release|view|productID=%s'); // 测试获取objectType release objectId 4的动态信息 -r($action->getObjectLabelTest($objectType[4], $objectId[4], $actionType[4], $requirements)) && p() && e('项目|project|index|projectID=%s'); // 测试获取objectType project objectId 5的动态信息 -r($action->getObjectLabelTest($objectType[5], $objectId[5], $actionType[5], $requirements)) && p() && e('任务|task|view|taskID=%s'); // 测试获取objectType task objectId 6的动态信息 -r($action->getObjectLabelTest($objectType[6], $objectId[6], $actionType[6], $requirements)) && p() && e('版本|build|view|buildID=%s'); // 测试获取objectType build objectId 7的动态信息 -r($action->getObjectLabelTest($objectType[7], $objectId[7], $actionType[7], $requirements)) && p() && e('Bug|bug|view|bugID=%s'); // 测试获取objectType bug objectId 8的动态信息 -r($action->getObjectLabelTest($objectType[8], $objectId[8], $actionType[8], $requirements)) && p() && e('testcase'); // 测试获取objectType testcase objectId 9的动态信息 -r($action->getObjectLabelTest($objectType[9], $objectId[9], $actionType[9], $requirements)) && p() && e('用例|testcase|view|caseID=%s'); // 测试获取objectType case objectId 10的动态信息 -r($action->getObjectLabelTest($objectType[10], $objectId[10], $actionType[10], $requirements)) && p() && e('测试单|testtask|view|caseID=%s'); // 测试获取objectType testtask objectId 11的动态信息 -r($action->getObjectLabelTest($objectType[11], $objectId[11], $actionType[11], $requirements)) && p() && e('用户|user|view|account=%s'); // 测试获取objectType user objectId 12的动态信息 -r($action->getObjectLabelTest($objectType[13], $objectId[13], $actionType[13], $requirements)) && p() && e('文档库|doc|tablecontents|type=%s&objectID=%s&libID=%s'); // 测试获取objectType doclib objectId 14的动态信息 -r($action->getObjectLabelTest($objectType[14], $objectId[14], $actionType[14], $requirements)) && p() && e('待办|todo|view|todoID=%s'); // 测试获取objectType todo objectId 15的动态信息 -r($action->getObjectLabelTest($objectType[15], $objectId[15], $actionType[15], $requirements)) && p() && e('branch'); // 测试获取objectType branch objectId 16的动态信息 -r($action->getObjectLabelTest($objectType[16], $objectId[16], $actionType[16], $requirements)) && p() && e('module'); // 测试获取objectType module objectId 17的动态信息 -r($action->getObjectLabelTest($objectType[17], $objectId[17], $actionType[17], $requirements)) && p() && e('测试套件|testsuite|view|suiteID=%s'); // 测试获取objectType testsuite objectId 18的动态信息 -r($action->getObjectLabelTest($objectType[18], $objectId[18], $actionType[18], $requirements)) && p() && e('用例库|caselib|view|libID=%s'); // 测试获取objectType caselib objectId 19的动态信息 -r($action->getObjectLabelTest($objectType[19], $objectId[19], $actionType[19], $requirements)) && p() && e('报告|testreport|view|report=%s'); // 测试获取objectType testreport objectId 20的动态信息 -r($action->getObjectLabelTest($objectType[20], $objectId[20], $actionType[20], $requirements)) && p() && e('应用|entry|browse|'); // 测试获取objectType entry objectId 21的动态信息 -r($action->getObjectLabelTest($objectType[21], $objectId[21], $actionType[21], $requirements)) && p() && e('Webhook|webhook|browse|'); // 测试获取objectType webhook objectId 22的动态信息 -r($action->getObjectLabelTest($objectType[22], $objectId[22], $actionType[22], $requirements)) && p() && e('review'); // 测试获取objectType review objectId 23的动态信息 -r($action->getObjectLabelTest($objectType[1], $objectId[23], $actionType[23], $requirements)) && p() && e('用户需求|story|view|storyID=%s'); // 测试获取objectType story objectId 25的动态信息 \ No newline at end of file +r($action->getObjectLabelTest($objectType[0], $objectId[0], $actionType[0], $requirements)) && p() && e('产品|product|view|productID=%s'); // 测试获取objectType product objectId 1的动态信息 +r($action->getObjectLabelTest($objectType[1], $objectId[1], $actionType[1], $requirements)) && p() && e('研发需求|story|view|storyID=%s'); // 测试获取objectType story objectId 2的动态信息 +r($action->getObjectLabelTest($objectType[2], $objectId[2], $actionType[2], $requirements)) && p() && e('计划|productplan|view|productID=%s'); // 测试获取objectType productplan objectId 3的动态信息 +r($action->getObjectLabelTest($objectType[3], $objectId[3], $actionType[3], $requirements)) && p() && e('发布|release|view|productID=%s'); // 测试获取objectType release objectId 4的动态信息 +r($action->getObjectLabelTest($objectType[4], $objectId[4], $actionType[4], $requirements)) && p() && e('项目|project|index|projectID=%s'); // 测试获取objectType project objectId 5的动态信息 +r($action->getObjectLabelTest($objectType[5], $objectId[5], $actionType[5], $requirements)) && p() && e('任务|task|view|taskID=%s'); // 测试获取objectType task objectId 6的动态信息 +r($action->getObjectLabelTest($objectType[6], $objectId[6], $actionType[6], $requirements)) && p() && e('版本|build|view|buildID=%s'); // 测试获取objectType build objectId 7的动态信息 +r($action->getObjectLabelTest($objectType[7], $objectId[7], $actionType[7], $requirements)) && p() && e('Bug|bug|view|bugID=%s'); // 测试获取objectType bug objectId 8的动态信息 +r($action->getObjectLabelTest($objectType[8], $objectId[8], $actionType[8], $requirements)) && p() && e('testcase'); // 测试获取objectType testcase objectId 9的动态信息 +r($action->getObjectLabelTest($objectType[9], $objectId[9], $actionType[9], $requirements)) && p() && e('用例|testcase|view|caseID=%s'); // 测试获取objectType case objectId 10的动态信息 +r($action->getObjectLabelTest($objectType[10], $objectId[10], $actionType[10], $requirements)) && p() && e('测试单|testtask|view|caseID=%s'); // 测试获取objectType testtask objectId 11的动态信息 +r($action->getObjectLabelTest($objectType[11], $objectId[11], $actionType[11], $requirements)) && p() && e('用户|user|view|account=%s'); // 测试获取objectType user objectId 12的动态信息 +r($action->getObjectLabelTest($objectType[13], $objectId[13], $actionType[13], $requirements)) && p() && e('文档库|doc|tablecontents|type=%s&objectID=%s&libID=%s'); // 测试获取objectType doclib objectId 14的动态信息 +r($action->getObjectLabelTest($objectType[14], $objectId[14], $actionType[14], $requirements)) && p() && e('待办|todo|view|todoID=%s'); // 测试获取objectType todo objectId 15的动态信息 +r($action->getObjectLabelTest($objectType[15], $objectId[15], $actionType[15], $requirements)) && p() && e('branch'); // 测试获取objectType branch objectId 16的动态信息 +r($action->getObjectLabelTest($objectType[16], $objectId[16], $actionType[16], $requirements)) && p() && e('模块|tree|browse|productid=%s&type=story¤tModuleID=0&branch=all'); // 测试获取objectType module objectId 17的动态信息 +r($action->getObjectLabelTest($objectType[17], $objectId[17], $actionType[17], $requirements)) && p() && e('测试套件|testsuite|view|suiteID=%s'); // 测试获取objectType testsuite objectId 18的动态信息 +r($action->getObjectLabelTest($objectType[18], $objectId[18], $actionType[18], $requirements)) && p() && e('用例库|caselib|view|libID=%s'); // 测试获取objectType caselib objectId 19的动态信息 +r($action->getObjectLabelTest($objectType[19], $objectId[19], $actionType[19], $requirements)) && p() && e('报告|testreport|view|report=%s'); // 测试获取objectType testreport objectId 20的动态信息 +r($action->getObjectLabelTest($objectType[20], $objectId[20], $actionType[20], $requirements)) && p() && e('应用|entry|browse|'); // 测试获取objectType entry objectId 21的动态信息 +r($action->getObjectLabelTest($objectType[21], $objectId[21], $actionType[21], $requirements)) && p() && e('Webhook|webhook|browse|'); // 测试获取objectType webhook objectId 22的动态信息 +r($action->getObjectLabelTest($objectType[22], $objectId[22], $actionType[22], $requirements)) && p() && e('review'); // 测试获取objectType review objectId 23的动态信息 +r($action->getObjectLabelTest($objectType[1], $objectId[23], $actionType[23], $requirements)) && p() && e('用户需求|story|view|storyID=%s'); // 测试获取objectType story objectId 25的动态信息 diff --git a/test/model/action/getrelatedfields.php b/test/model/action/getrelatedfields.php index 48e06bde51..8780c9490b 100755 --- a/test/model/action/getrelatedfields.php +++ b/test/model/action/getrelatedfields.php @@ -18,7 +18,7 @@ pid=1 测试获取objectType task objectId 6 actionType edited extra 1 的动态信息 >> ,6,;16;106 测试获取objectType build objectId 7 actionType assigned extra 1 的动态信息 >> ,7,;17;0 测试获取objectType bug objectId 8 actionType closed extra 1 的动态信息 >> ,3,;13;103 -测试获取objectType testcase objectId 9 actionType deleted extra 1 的动态信息 >> ,0,;0;0 +测试获取objectType testcase objectId 9 actionType deleted extra 1 的动态信息 >> ,3,;13;103 测试获取objectType case objectId 10 actionType deletedfile extra 1 的动态信息 >> ,3,;13;103 测试获取objectType testtask objectId 1 actionType editfile extra 1 的动态信息 >> ,1,;11;101 测试获取objectType user objectId 12 actionType erased extra 1 的动态信息 >> ,0,;0;0 @@ -26,7 +26,7 @@ pid=1 测试获取objectType doclib objectId 14 actionType hidden extra 1 的动态信息 >> ,14,;0;0 测试获取objectType todo objectId 15 actionType commented extra 1 的动态信息 >> ,0,;0;0 测试获取objectType branch objectId 16 actionType activated extra 1 的动态信息 >> ,0,;0;0 -测试获取objectType module objectId 17 actionType blocked extra 1 的动态信息 >> ,0,;0;0 +测试获取objectType module objectId 17 actionType blocked extra 1 的动态信息 >> ,,0,,;0;0 测试获取objectType testsuite objectId 18 actionType moved extra 1 的动态信息 >> ,0,;0;0 测试获取objectType caselib objectId 19 actionType confirmed extra 1 的动态信息 >> ,0,;0;0 测试获取objectType testreport objectId 20 actionType caseconfirmed extra 1 的动态信息 >> ,,;0;0 @@ -41,7 +41,7 @@ pid=1 测试获取objectType task objectId 29 actionType deleteestimate extra 1 的动态信息 >> ,29,;39;129 测试获取objectType build objectId 1 actionType canceled extra 1 的动态信息 >> ,1,;11;0 测试获取objectType bug objectId 31 actionType svncommited extra 1 的动态信息 >> ,11,;21;111 -测试获取objectType testcase objectId 32 actionType gitcommited extra 1 的动态信息 >> ,0,;0;0 +测试获取objectType testcase objectId 32 actionType gitcommited extra 1 的动态信息 >> ,8,;18;108 测试获取objectType case objectId 33 actionType finished extra 1 的动态信息 >> ,9,;19;109 测试获取objectType testtask objectId 1 actionType paused extra 1 的动态信息 >> ,1,;11;101 测试获取objectType user objectId 35 actionType verified extra 1 的动态信息 >> ,0,;0;0 @@ -66,7 +66,7 @@ r($action->getRelatedFieldsTest($objectType[4], $objectId[4], $actionType[4], r($action->getRelatedFieldsTest($objectType[5], $objectId[5], $actionType[5], $extra[5])) && p('product;project;execution') && e(',6,;16;106'); // 测试获取objectType task objectId 6 actionType edited extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[6], $objectId[6], $actionType[6], $extra[6])) && p('product;project;execution') && e(',7,;17;0'); // 测试获取objectType build objectId 7 actionType assigned extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[7], $objectId[7], $actionType[7], $extra[7])) && p('product;project;execution') && e(',3,;13;103'); // 测试获取objectType bug objectId 8 actionType closed extra 1 的动态信息 -r($action->getRelatedFieldsTest($objectType[8], $objectId[8], $actionType[8], $extra[8])) && p('product;project;execution') && e(',0,;0;0'); // 测试获取objectType testcase objectId 9 actionType deleted extra 1 的动态信息 +r($action->getRelatedFieldsTest($objectType[8], $objectId[8], $actionType[8], $extra[8])) && p('product;project;execution') && e(',3,;13;103'); // 测试获取objectType testcase objectId 9 actionType deleted extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[9], $objectId[9], $actionType[9], $extra[9])) && p('product;project;execution') && e(',3,;13;103'); // 测试获取objectType case objectId 10 actionType deletedfile extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[10], $objectId[10], $actionType[10], $extra[10])) && p('product;project;execution') && e(',1,;11;101'); // 测试获取objectType testtask objectId 1 actionType editfile extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[11], $objectId[11], $actionType[11], $extra[11])) && p('product;project;execution') && e(',0,;0;0'); // 测试获取objectType user objectId 12 actionType erased extra 1 的动态信息 @@ -74,7 +74,7 @@ r($action->getRelatedFieldsTest($objectType[12], $objectId[12], $actionType[12], r($action->getRelatedFieldsTest($objectType[13], $objectId[13], $actionType[13], $extra[13])) && p('product;project;execution') && e(',14,;0;0'); // 测试获取objectType doclib objectId 14 actionType hidden extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[14], $objectId[14], $actionType[14], $extra[14])) && p('product;project;execution') && e(',0,;0;0'); // 测试获取objectType todo objectId 15 actionType commented extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[15], $objectId[15], $actionType[15], $extra[15])) && p('product;project;execution') && e(',0,;0;0'); // 测试获取objectType branch objectId 16 actionType activated extra 1 的动态信息 -r($action->getRelatedFieldsTest($objectType[16], $objectId[16], $actionType[16], $extra[16])) && p('product;project;execution') && e(',0,;0;0'); // 测试获取objectType module objectId 17 actionType blocked extra 1 的动态信息 +r($action->getRelatedFieldsTest($objectType[16], $objectId[16], $actionType[16], $extra[16])) && p('product;project;execution') && e(',,0,,;0;0'); // 测试获取objectType module objectId 17 actionType blocked extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[17], $objectId[17], $actionType[17], $extra[17])) && p('product;project;execution') && e(',0,;0;0'); // 测试获取objectType testsuite objectId 18 actionType moved extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[18], $objectId[18], $actionType[18], $extra[18])) && p('product;project;execution') && e(',0,;0;0'); // 测试获取objectType caselib objectId 19 actionType confirmed extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[19], $objectId[19], $actionType[19], $extra[19])) && p('product;project;execution') && e(',,;0;0'); // 测试获取objectType testreport objectId 20 actionType caseconfirmed extra 1 的动态信息 @@ -89,11 +89,11 @@ r($action->getRelatedFieldsTest($objectType[4], $objectId[27], $actionType[27], r($action->getRelatedFieldsTest($objectType[5], $objectId[28], $actionType[28], $extra[28])) && p('product;project;execution') && e(',29,;39;129'); // 测试获取objectType task objectId 29 actionType deleteestimate extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[6], $objectId[29], $actionType[29], $extra[29])) && p('product;project;execution') && e(',1,;11;0'); // 测试获取objectType build objectId 1 actionType canceled extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[7], $objectId[30], $actionType[30], $extra[30])) && p('product;project;execution') && e(',11,;21;111'); // 测试获取objectType bug objectId 31 actionType svncommited extra 1 的动态信息 -r($action->getRelatedFieldsTest($objectType[8], $objectId[31], $actionType[31], $extra[31])) && p('product;project;execution') && e(',0,;0;0'); // 测试获取objectType testcase objectId 32 actionType gitcommited extra 1 的动态信息 +r($action->getRelatedFieldsTest($objectType[8], $objectId[31], $actionType[31], $extra[31])) && p('product;project;execution') && e(',8,;18;108'); // 测试获取objectType testcase objectId 32 actionType gitcommited extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[9], $objectId[32], $actionType[32], $extra[32])) && p('product;project;execution') && e(',9,;19;109'); // 测试获取objectType case objectId 33 actionType finished extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[10], $objectId[33], $actionType[33], $extra[33])) && p('product;project;execution') && e(',1,;11;101'); // 测试获取objectType testtask objectId 1 actionType paused extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[11], $objectId[34], $actionType[34], $extra[34])) && p('product;project;execution') && e(',0,;0;0'); // 测试获取objectType user objectId 35 actionType verified extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[12], $objectId[35], $actionType[35], $extra[35])) && p('product;project;execution') && e(',36,;0;0'); // 测试获取objectType doc objectId 36 actionType diff1 extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[13], $objectId[36], $actionType[36], $extra[36])) && p('product;project;execution') && e(',37,;0;0'); // 测试获取objectType doclib objectId 37 actionType diff2 extra 1 的动态信息 r($action->getRelatedFieldsTest($objectType[14], $objectId[37], $actionType[37], $extra[37])) && p('product;project;execution') && e(',0,;0;0'); // 测试获取objectType todo objectId 38 actionType diff3 extra 1 的动态信息 -r($action->getRelatedFieldsTest($objectType[15], $objectId[38], $actionType[38], $extra[38])) && p('product;project;execution') && e(',0,;0;0'); // 测试获取objectType branch objectId 39 actionType linked2bug extra 1 的动态信息 \ No newline at end of file +r($action->getRelatedFieldsTest($objectType[15], $objectId[38], $actionType[38], $extra[38])) && p('product;project;execution') && e(',0,;0;0'); // 测试获取objectType branch objectId 39 actionType linked2bug extra 1 的动态信息 diff --git a/test/model/action/gettrashesbysearch.php b/test/model/action/gettrashesbysearch.php new file mode 100755 index 0000000000..678a8998ce --- /dev/null +++ b/test/model/action/gettrashesbysearch.php @@ -0,0 +1,32 @@ +#!/usr/bin/env php +getTrashesBySearch(); +cid=1 +pid=1 + +搜索objectType all, type all, queryID myQueryID, orderBy id_desc的回收站信息 >> 0 +搜索objectType story, type all, queryID myQueryID, orderBy id_desc的回收站信息 >> 48,story +搜索objectType story, type all, queryID 2, orderBy id_asc的回收站信息 >> 48,story +搜索objectType story, type hidden, queryID myQueryID, orderBy id_desc的回收站信息 >> 0 +搜索objectType testcase, type all, queryID 0, orderBy id_asc的回收站信息 >> 0 + +*/ + +$objectTypeList = array('all', 'story', 'testcase'); +$typeList = array('all', 'hidden'); +$queryIdList = array('myQueryID', '0', '2'); +$orderBy = array('id_desc', 'id_asc'); +$pager = null; + +$action = new actionTest(); +r($action->getTrashesBySearchTest($objectTypeList[0], $typeList[0], $queryIdList[0], $orderBy[0], $pager)) && p() && e('0'); // 搜索objectType all, type all, queryID myQueryID, orderBy id_desc的回收站信息 +r($action->getTrashesBySearchTest($objectTypeList[1], $typeList[0], $queryIdList[0], $orderBy[0], $pager)) && p('48:id,objectType') && e('48,story'); // 搜索objectType story, type all, queryID myQueryID, orderBy id_desc的回收站信息 +r($action->getTrashesBySearchTest($objectTypeList[1], $typeList[0], $queryIdList[1], $orderBy[1], $pager)) && p('48:id,objectType') && e('48,story'); // 搜索objectType story, type all, queryID 2, orderBy id_asc的回收站信息 +r($action->getTrashesBySearchTest($objectTypeList[1], $typeList[1], $queryIdList[0], $orderBy[0], $pager)) && p() && e('0'); // 搜索objectType story, type hidden, queryID myQueryID, orderBy id_desc的回收站信息 +r($action->getTrashesBySearchTest($objectTypeList[2], $typeList[0], $queryIdList[0], $orderBy[1], $pager)) && p() && e('0'); // 搜索objectType testcase, type all, queryID 0, orderBy id_asc的回收站信息 diff --git a/test/model/action/getunreadactions.php b/test/model/action/getunreadactions.php new file mode 100755 index 0000000000..1512205095 --- /dev/null +++ b/test/model/action/getunreadactions.php @@ -0,0 +1,29 @@ +#!/usr/bin/env php +getUnreadActions(); +cid=1 +pid=1 + +测试获取ID为空的动态 >> 0 +测试获取ID为0的动态 >> 0 +测试获取ID为1的动态 >> 0 +测试获取ID不存在的动态 >> 0 +测试获取ID是数组的动态 >> 0 + +*/ + +$actionIdList = array('', 0, '1', '1000'); + +$action = new actionTest(); + +r($action->getUnreadActionsTest($actionIdList[0])) && p() && e('0'); // 测试获取ID为空的动态 +r($action->getUnreadActionsTest($actionIdList[1])) && p() && e('0'); // 测试获取ID为0的动态 +r($action->getUnreadActionsTest($actionIdList[2])) && p() && e('0'); // 测试获取ID为1的动态 +r($action->getUnreadActionsTest($actionIdList[3])) && p() && e('0'); // 测试获取ID不存在的动态 +r($action->getUnreadActionsTest($actionIdList)) && p() && e('0'); // 测试获取ID是数组的动态 diff --git a/test/model/action/haspreornext.php b/test/model/action/haspreornext.php new file mode 100755 index 0000000000..d7a5a37590 --- /dev/null +++ b/test/model/action/haspreornext.php @@ -0,0 +1,29 @@ +#!/usr/bin/env php +hasPreOrNext(); +cid=1 +pid=1 + +测试传入空参数 >> 1 +测试空日期之前是否有动态 >> 0 +测试空日期之后是否有动态 >> 1 +测试今天之前是否有动态 >> 1 +测试今天之后是否有动态 >> 0 + +*/ + +$action = new actionTest(); + +$dateList = array('', 'today'); +$directionList = array('', 'next', 'pre'); +r($action->hasPreOrNextTest($dateList[0], $directionList[0])) && p() && e('1'); // 测试传入空参数 +r($action->hasPreOrNextTest($dateList[0], $directionList[1])) && p() && e('0'); // 测试空日期之前是否有动态 +r($action->hasPreOrNextTest($dateList[0], $directionList[2])) && p() && e('1'); // 测试空日期之后是否有动态 +r($action->hasPreOrNextTest($dateList[1], $directionList[1])) && p() && e('1'); // 测试今天之前是否有动态 +r($action->hasPreOrNextTest($dateList[1], $directionList[2])) && p() && e('0'); // 测试今天之后是否有动态 diff --git a/test/model/action/processdynamicforapi.php b/test/model/action/processdynamicforapi.php new file mode 100755 index 0000000000..72eb064c5b --- /dev/null +++ b/test/model/action/processdynamicforapi.php @@ -0,0 +1,23 @@ +#!/usr/bin/env php +processDynamicForAPI(); +cid=1 +pid=1 + +测试处理空数据 >> 0 +处理所有动态 >> admin,admin,/home/z/tmp/1.png + +*/ + +$action = new actionTest(); + +$dynamics = $tester->dao->select('*')->from(TABLE_ACTION)->fetchAll(); + +r($action->processDynamicForAPITest(array())) && p() && e('0'); // 测试处理空数据 +r($action->processDynamicForAPITest($dynamics)) && p('actor:account,realname,avatar') && e('admin,admin,/home/z/tmp/1.png'); // 处理所有动态 diff --git a/test/model/action/saveindex.php b/test/model/action/saveindex.php new file mode 100755 index 0000000000..19afbd4c03 --- /dev/null +++ b/test/model/action/saveindex.php @@ -0,0 +1,39 @@ +#!/usr/bin/env php +switchDB(); +su('admin'); + +/** + +title=测试 actionModel->saveIndex(); +cid=1 +pid=1 + +测试保存空数据 >> 1 +测试保存stroyId为0, action为空的数据 >> 1 +测试保存stroyId为1, action为空的数据 >> 1 +测试保存stroyId为100000, action为空的数据 >> 1 +测试保存stroyId为0, action为created的数据 >> 1 +测试保存stroyId为1, action为created的数据 >> 1 +测试保存stroyId为100000, action为created的数据 >> 1 +测试保存不存在类型的数据 >> 1 + +*/ + +$objectTypeList = array('', 'stroy', 'test'); +$objectIdList = array(0, 1, 100000); +$actionTypeList = array('', 'created', 'tested'); + +$action = new actionTest(); + +r($action->saveIndexTest($objectTypeList[0], $objectIdList[0], $actionTypeList[0])) && p() && e('1'); // 测试保存空数据 +r($action->saveIndexTest($objectTypeList[1], $objectIdList[0], $actionTypeList[0])) && p() && e('1'); // 测试保存stroyId为0, action为空的数据 +r($action->saveIndexTest($objectTypeList[1], $objectIdList[1], $actionTypeList[0])) && p() && e('1'); // 测试保存stroyId为1, action为空的数据 +r($action->saveIndexTest($objectTypeList[1], $objectIdList[2], $actionTypeList[0])) && p() && e('1'); // 测试保存stroyId为100000, action为空的数据 +r($action->saveIndexTest($objectTypeList[1], $objectIdList[0], $actionTypeList[1])) && p() && e('1'); // 测试保存stroyId为0, action为created的数据 +r($action->saveIndexTest($objectTypeList[1], $objectIdList[1], $actionTypeList[1])) && p() && e('1'); // 测试保存stroyId为1, action为created的数据 +r($action->saveIndexTest($objectTypeList[1], $objectIdList[2], $actionTypeList[1])) && p() && e('1'); // 测试保存stroyId为100000, action为created的数据 +r($action->saveIndexTest($objectTypeList[2], $objectIdList[2], $actionTypeList[2])) && p() && e('1'); // 测试保存不存在类型的数据 +$db->restoreDB(); diff --git a/test/model/action/setobjectlink.php b/test/model/action/setobjectlink.php deleted file mode 100755 index f88a9d9809..0000000000 --- a/test/model/action/setobjectlink.php +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env php -setObjectLink(); -cid=1 -pid=1 - -测试获取action 1 的objectLink >> 1,model/action/product-view-1. -测试获取action 2 的objectLink >> 2,model/action/story-view-2. -测试获取action 3 的objectLink >> 3,model/action/productplan-view-3. -测试获取action 4 的objectLink >> 4,model/action/release-view-4. -测试获取action 5 的objectLink >> 5,model/action/project-index-5. -测试获取action 6 的objectLink >> 6,model/action/task-view-6. -测试获取action 7 的objectLink >> 7,model/action/build-view-7. -测试获取action 8 的objectLink >> 8,model/action/bug-view-8. -测试获取action 9 的objectLink >> 9, -测试获取action 10 的objectLink >> 10,model/action/testcase-view-10. -测试获取action 11 的objectLink >> 11,model/action/testtask-view-11. -测试获取action 12 的objectLink >> 12,javascript:void(0) -测试获取action 13 的objectLink >> 13,model/action/doc-view-13. -测试获取action 14 的objectLink >> 14,model/action/doc-objectLibs-product-14-14. -测试获取action 15 的objectLink >> 15,model/action/todo-view-15. -测试获取action 16 的objectLink >> 16, -测试获取action 17 的objectLink >> 17, -测试获取action 18 的objectLink >> 18,model/action/testsuite-view-18. -测试获取action 19 的objectLink >> 19,model/action/caselib-view-19. -测试获取action 20 的objectLink >> 20,model/action/testreport-view-20. -测试获取action 21 的objectLink >> 21,model/action/entry-browse. -测试获取action 22 的objectLink >> 22,model/action/webhook-browse. -测试获取action 23 的objectLink >> 23, -测试获取action 24 的objectLink >> 24,model/action/product-view-24. -测试获取action 25 的objectLink >> 25,model/action/story-view-25. -测试获取action 26 的objectLink >> 26,model/action/productplan-view-26. -测试获取action 27 的objectLink >> 27,model/action/release-view-27. -测试获取action 28 的objectLink >> 28,model/action/project-index-28. -测试获取action 29 的objectLink >> 29,model/action/task-view-29. -测试获取action 30 的objectLink >> 30,model/action/build-view-30. -测试获取action 31 的objectLink >> 31,model/action/bug-view-31. -测试获取action 32 的objectLink >> 32, -测试获取action 33 的objectLink >> 33,model/action/testcase-view-33. -测试获取action 34 的objectLink >> 34,model/action/testtask-view-34. -测试获取action 35 的objectLink >> 35,javascript:void(0) -测试获取action 36 的objectLink >> 36,model/action/doc-view-36. -测试获取action 37 的objectLink >> 37,model/action/doc-objectLibs-product-37-37. -测试获取action 38 的objectLink >> 38,model/action/todo-view-38. -测试获取action 39 的objectLink >> 39, - -*/ - -$actionIDList = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39); - -$action = new actionTest(); - -r($action->setObjectLinkTest($actionIDList[0])) && p('id,objectLink') && e("1,model/action/product-view-1."); // 测试获取action 1 的objectLink -r($action->setObjectLinkTest($actionIDList[1])) && p('id,objectLink') && e("2,model/action/story-view-2."); // 测试获取action 2 的objectLink -r($action->setObjectLinkTest($actionIDList[2])) && p('id,objectLink') && e("3,model/action/productplan-view-3."); // 测试获取action 3 的objectLink -r($action->setObjectLinkTest($actionIDList[3])) && p('id,objectLink') && e("4,model/action/release-view-4."); // 测试获取action 4 的objectLink -r($action->setObjectLinkTest($actionIDList[4])) && p('id,objectLink') && e("5,model/action/project-index-5."); // 测试获取action 5 的objectLink -r($action->setObjectLinkTest($actionIDList[5])) && p('id,objectLink') && e("6,model/action/task-view-6."); // 测试获取action 6 的objectLink -r($action->setObjectLinkTest($actionIDList[6])) && p('id,objectLink') && e("7,model/action/build-view-7."); // 测试获取action 7 的objectLink -r($action->setObjectLinkTest($actionIDList[7])) && p('id,objectLink') && e("8,model/action/bug-view-8."); // 测试获取action 8 的objectLink -r($action->setObjectLinkTest($actionIDList[8])) && p('id,objectLink') && e("9,"); // 测试获取action 9 的objectLink -r($action->setObjectLinkTest($actionIDList[9])) && p('id,objectLink') && e("10,model/action/testcase-view-10."); // 测试获取action 10 的objectLink -r($action->setObjectLinkTest($actionIDList[10])) && p('id,objectLink') && e("11,model/action/testtask-view-11."); // 测试获取action 11 的objectLink -r($action->setObjectLinkTest($actionIDList[11])) && p('id,objectLink') && e("12,javascript:void(0)"); // 测试获取action 12 的objectLink -r($action->setObjectLinkTest($actionIDList[12])) && p('id,objectLink') && e("13,model/action/doc-view-13."); // 测试获取action 13 的objectLink -r($action->setObjectLinkTest($actionIDList[13])) && p('id,objectLink') && e("14,model/action/doc-objectLibs-product-14-14."); // 测试获取action 14 的objectLink -r($action->setObjectLinkTest($actionIDList[14])) && p('id,objectLink') && e("15,model/action/todo-view-15."); // 测试获取action 15 的objectLink -r($action->setObjectLinkTest($actionIDList[15])) && p('id,objectLink') && e("16,"); // 测试获取action 16 的objectLink -r($action->setObjectLinkTest($actionIDList[16])) && p('id,objectLink') && e("17,"); // 测试获取action 17 的objectLink -r($action->setObjectLinkTest($actionIDList[17])) && p('id,objectLink') && e("18,model/action/testsuite-view-18."); // 测试获取action 18 的objectLink -r($action->setObjectLinkTest($actionIDList[18])) && p('id,objectLink') && e("19,model/action/caselib-view-19."); // 测试获取action 19 的objectLink -r($action->setObjectLinkTest($actionIDList[19])) && p('id,objectLink') && e("20,model/action/testreport-view-20."); // 测试获取action 20 的objectLink -r($action->setObjectLinkTest($actionIDList[20])) && p('id,objectLink') && e("21,model/action/entry-browse."); // 测试获取action 21 的objectLink -r($action->setObjectLinkTest($actionIDList[21])) && p('id,objectLink') && e("22,model/action/webhook-browse."); // 测试获取action 22 的objectLink -r($action->setObjectLinkTest($actionIDList[22])) && p('id,objectLink') && e("23,"); // 测试获取action 23 的objectLink -r($action->setObjectLinkTest($actionIDList[23])) && p('id,objectLink') && e("24,model/action/product-view-24."); // 测试获取action 24 的objectLink -r($action->setObjectLinkTest($actionIDList[24])) && p('id,objectLink') && e("25,model/action/story-view-25."); // 测试获取action 25 的objectLink -r($action->setObjectLinkTest($actionIDList[25])) && p('id,objectLink') && e("26,model/action/productplan-view-26."); // 测试获取action 26 的objectLink -r($action->setObjectLinkTest($actionIDList[26])) && p('id,objectLink') && e("27,model/action/release-view-27."); // 测试获取action 27 的objectLink -r($action->setObjectLinkTest($actionIDList[27])) && p('id,objectLink') && e("28,model/action/project-index-28."); // 测试获取action 28 的objectLink -r($action->setObjectLinkTest($actionIDList[28])) && p('id,objectLink') && e("29,model/action/task-view-29."); // 测试获取action 29 的objectLink -r($action->setObjectLinkTest($actionIDList[29])) && p('id,objectLink') && e("30,model/action/build-view-30."); // 测试获取action 30 的objectLink -r($action->setObjectLinkTest($actionIDList[30])) && p('id,objectLink') && e("31,model/action/bug-view-31."); // 测试获取action 31 的objectLink -r($action->setObjectLinkTest($actionIDList[31])) && p('id,objectLink') && e("32,"); // 测试获取action 32 的objectLink -r($action->setObjectLinkTest($actionIDList[32])) && p('id,objectLink') && e("33,model/action/testcase-view-33."); // 测试获取action 33 的objectLink -r($action->setObjectLinkTest($actionIDList[33])) && p('id,objectLink') && e("34,model/action/testtask-view-34."); // 测试获取action 34 的objectLink -r($action->setObjectLinkTest($actionIDList[34])) && p('id,objectLink') && e("35,javascript:void(0)"); // 测试获取action 35 的objectLink -r($action->setObjectLinkTest($actionIDList[35])) && p('id,objectLink') && e("36,model/action/doc-view-36."); // 测试获取action 36 的objectLink -r($action->setObjectLinkTest($actionIDList[36])) && p('id,objectLink') && e("37,model/action/doc-objectLibs-product-37-37."); // 测试获取action 37 的objectLink -r($action->setObjectLinkTest($actionIDList[37])) && p('id,objectLink') && e("38,model/action/todo-view-38."); // 测试获取action 38 的objectLink -r($action->setObjectLinkTest($actionIDList[38])) && p('id,objectLink') && e("39,"); // 测试获取action 39 的objectLink \ No newline at end of file diff --git a/test/model/action/transformactions.php b/test/model/action/transformactions.php index 3fc3807f02..5636755832 100755 --- a/test/model/action/transformactions.php +++ b/test/model/action/transformactions.php @@ -10,7 +10,7 @@ title=测试 actionModel->transformActions(); cid=1 pid=1 -测试转换动态1 2 3 4 5 >> 正常产品1;软件需求2;长名称好长好长好长好长好长好长好长好长好长好长好长好好长好长好长好长好长好好长好长好长好长好长好好长好长好长好长好长好的名字啊!@ase!!@#%@^&#!;项目停止维护的停止维护的里程碑发布4;项目集5 +测试转换动态1 2 3 4 5 >> 0 测试转换动态26 27 28 29 30 >> 1.1;;项目18;开发任务39; 测试转换动态51 52 53 54 55 >> 项目41;开发任务62;;BUG54;这个是测试用例55 测试转换动态71 72 73 74 75 >> 用户需求71;;;项目64;开发任务85 @@ -21,8 +21,8 @@ $actions = array('1,2,3,4,5', '26,27,28,29,30', '51,52,53,54,55', '71,72,73,74,7 $action = new actionTest(); -r($action->transformActionsTest($actions[0])) && p('1:objectName;2:objectName;3:objectName;4:objectName;5:objectName') && e('正常产品1;软件需求2;长名称好长好长好长好长好长好长好长好长好长好长好长好好长好长好长好长好长好好长好长好长好长好长好好长好长好长好长好长好的名字啊!@ase!!@#%@^&#!;项目停止维护的停止维护的里程碑发布4;项目集5'); // 测试转换动态1 2 3 4 5 +r($action->transformActionsTest($actions[0])) && p('1:objectName;2:objectName;3:objectName;4:objectName;5:objectName') && e('0'); // 0 r($action->transformActionsTest($actions[1])) && p('26:objectName;27:objectName;28:objectName;29:objectName;30:objectName') && e('1.1;;项目18;开发任务39;'); // 测试转换动态26 27 28 29 30 r($action->transformActionsTest($actions[2])) && p('51:objectName;52:objectName;53:objectName;54:objectName;55:objectName') && e('项目41;开发任务62;;BUG54;这个是测试用例55'); // 测试转换动态51 52 53 54 55 r($action->transformActionsTest($actions[3])) && p('71:objectName;72:objectName;73:objectName;74:objectName;75:objectName') && e('用户需求71;;;项目64;开发任务85'); // 测试转换动态71 72 73 74 75 -r($action->transformActionsTest($actions[4])) && p('96:objectName;97:objectName;98:objectName;99:objectName;100:objectName') && e(';项目87;开发任务108;;BUG10'); // 测试转换动态96 97 98 99 100 \ No newline at end of file +r($action->transformActionsTest($actions[4])) && p('96:objectName;97:objectName;98:objectName;99:objectName;100:objectName') && e(';项目87;开发任务108;;BUG10'); // 测试转换动态96 97 98 99 100 diff --git a/test/model/api/create.php b/test/model/api/create.php index ab436b1ada..60de475ea4 100755 --- a/test/model/api/create.php +++ b/test/model/api/create.php @@ -2,6 +2,7 @@ switchDB(); su('admin'); /** @@ -10,22 +11,22 @@ title=测试 apiModel->create(); cid=1 pid=1 -测试创建api >> 910 -测试没有lib创建api >> 『API Library』should not be blank. -测试没有title创建api >> 『Name』should not be blank. -测试没有path创建api >> 『Request Path』should not be blank. +测试创建api >> 920 +测试没有lib创建api >> 『所属接口库』不能为空。 +测试没有title创建api >> 『接口名称』不能为空。 +测试没有path创建api >> 『请求路径』不能为空。 */ $api = new apiTest(); $data = array( - 'lib' => 910, + 'lib' => 920, 'module' => 0, 'title' => 'testapi', 'protocol' => 'HTTP', 'method' => 'GET', - 'path' => '/api/test/id', + 'path' => '/api/test/id/test', 'requestType' => 'application/json', 'status' => 'done', 'owner' => 'admin', @@ -48,7 +49,8 @@ $emptyTitleApi['title'] = ''; $emptyPathApi = $data; $emptyPathApi['path'] = ''; -r($api->createTest($normalApi)) && p('lib') && e('910'); //测试创建api -r($api->createTest($emptyLibApi)) && p('lib:0') && e('『API Library』should not be blank.'); //测试没有lib创建api -r($api->createTest($emptyTitleApi)) && p('title:0') && e('『Name』should not be blank.'); //测试没有title创建api -r($api->createTest($emptyPathApi)) && p('path:0') && e('『Request Path』should not be blank.'); //测试没有path创建api \ No newline at end of file +r($api->createTest($normalApi)) && p('lib') && e('920'); //测试创建api +r($api->createTest($emptyLibApi)) && p('lib:0') && e('『所属接口库』不能为空。'); //测试没有lib创建api +r($api->createTest($emptyTitleApi)) && p('title:0') && e('『接口名称』不能为空。'); //测试没有title创建api +r($api->createTest($emptyPathApi)) && p('path:0') && e('『请求路径』不能为空。'); //测试没有path创建api +$db->restoreDB(); diff --git a/test/model/api/createstruct.php b/test/model/api/createstruct.php index 09ab461963..6cd767dcd6 100755 --- a/test/model/api/createstruct.php +++ b/test/model/api/createstruct.php @@ -2,6 +2,7 @@ switchDB(); su('admin'); /** @@ -11,7 +12,7 @@ cid=1 pid=1 创建数据结构 >> struct -创建没有结构名的数据结构 >> 『Name』should not be blank. +创建没有结构名的数据结构 >> 『结构名』不能为空。 */ @@ -35,4 +36,5 @@ $normalStruct->addedBy = $tester->app->user->account; $normalStruct->addedDate = helper::now(); r($api->createStructTest($normalStruct)) && p('name') && e('struct'); //创建数据结构 -r($api->createStructTest($emptyNameStruct)) && p('name:0') && e('『Name』should not be blank.'); //创建没有结构名的数据结构 \ No newline at end of file +r($api->createStructTest($emptyNameStruct)) && p('name:0') && e('『结构名』不能为空。'); //创建没有结构名的数据结构 +$db->restoreDB(); diff --git a/test/model/api/deleterelease.php b/test/model/api/deleterelease.php index 90b7b98fd1..c1bf5a3286 100755 --- a/test/model/api/deleterelease.php +++ b/test/model/api/deleterelease.php @@ -2,6 +2,7 @@ switchDB(); su('admin'); /** @@ -10,20 +11,10 @@ title=测试 apiModel->deleteRelease(); cid=1 pid=1 -删除一个创建的发布 >> 0 +删除一个发布 >> 1 */ global $tester; -$api = new apiTest(); - -$normalRelease = new stdclass(); -$normalRelease->version = 'Version1'; -$normalRelease->desc = ''; -$normalRelease->lib = 910; -$normalRelease->addedBy = $tester->app->user->account; -$normalRelease->addedDate = helper::now(); - -$release = $api->publishLibTest($normalRelease, false); - -r($api->deleteReleaseTest($release->id, $release->lib)) && p('') && e('0'); //删除一个创建的发布 \ No newline at end of file +r($api->deleteReleaseTest(1, 1)) && p('id') && e('1'); //删除一个发布 +$db->restoreDB(); diff --git a/test/model/api/getlistbymoduleid.php b/test/model/api/getlistbymoduleid.php index 2ab0ac94e1..11f215079f 100755 --- a/test/model/api/getlistbymoduleid.php +++ b/test/model/api/getlistbymoduleid.php @@ -10,16 +10,16 @@ title=测试 apiModel->getListByModuleId(); cid=1 pid=1 -通过正常的libID、moduleID、releaseID查询api信息 >> 获取token -通过正常的libID、moduleID,不传releaseID,查询api信息 >> 获取我的个人信息 -通过正常的libID,不传moduleID、releaseID查询api信息 >> 获取token +通过正常的libID、moduleID、releaseID查询api信息 >> 获取反馈列表 +通过正常的libID、moduleID,不传releaseID,查询api信息 >> 0 +通过正常的libID,不传moduleID、releaseID查询api信息 >> 0 通过不存在的libID,moduleID,releaseID查询api信息 >> 0 */ $api = new apiTest(); -r($api->getListByModuleIdTest(1, 1, 1)) && p('title') && e('获取token'); //通过正常的libID、moduleID、releaseID查询api信息 -r($api->getListByModuleIdTest(1, 1, 0)) && p('title') && e('获取我的个人信息'); //通过正常的libID、moduleID,不传releaseID,查询api信息 -r($api->getListByModuleIdTest(1, 0, 0)) && p('title') && e('获取token'); //通过正常的libID,不传moduleID、releaseID查询api信息 -r($api->getListByModuleIdTest(0, 0, 0)) && p('title') && e('0'); //通过不存在的libID,moduleID,releaseID查询api信息 \ No newline at end of file +r($api->getListByModuleIdTest(1950, 6392, 1)) && p('title') && e('获取反馈列表'); //通过正常的libID、moduleID、releaseID查询api信息 +r($api->getListByModuleIdTest(1950, 6396, 0)) && p('title') && e('0'); //通过正常的libID、moduleID,不传releaseID,查询api信息 +r($api->getListByModuleIdTest(1, 0, 0)) && p('title') && e('0'); //通过正常的libID,不传moduleID、releaseID查询api信息 +r($api->getListByModuleIdTest(0, 0, 0)) && p('title') && e('0'); //通过不存在的libID,moduleID,releaseID查询api信息 diff --git a/test/model/api/getreleaselistbyapi.php b/test/model/api/getreleaselistbyapi.php index 503d3397a5..d070aa0d2e 100755 --- a/test/model/api/getreleaselistbyapi.php +++ b/test/model/api/getreleaselistbyapi.php @@ -25,4 +25,4 @@ $normalRelease->addedBy = $tester->app->user->account; $normalRelease->addedDate = helper::now(); $release = $api->publishLibTest($normalRelease, false); -r($api->getReleaseListByApiTest($release->lib, $release->id)) && p("{$release->id}:lib") && e('910'); //获取刚插入的发布信息 \ No newline at end of file +r($api->getReleaseListByApiTest($release->lib, $release->id)) && p("lib") && e('910'); //获取刚插入的发布信息 diff --git a/test/model/api/getstructlistbyrelease.php b/test/model/api/getstructlistbyrelease.php index 1c3b5e0ce5..36d49a6969 100755 --- a/test/model/api/getstructlistbyrelease.php +++ b/test/model/api/getstructlistbyrelease.php @@ -10,41 +10,13 @@ title=测试 apiModel->getStructListByRelease(); cid=1 pid=1 -创建api后创建发布,使用发布查找api >> 910 +获取没有接口库的接口文档的名称 >> editStruct +获取所属接口库ID为1的接口文档的名称 >> user */ global $tester; $api = new apiTest(); -$data = array( - 'lib' => 910, - 'module' => 0, - 'title' => 'testapi', - 'protocol' => 'HTTP', - 'method' => 'GET', - 'path' => '/api/test/id', - 'requestType' => 'application/json', - 'status' => 'done', - 'owner' => 'admin', - 'type' => 'formData', - 'params' => '{"header":[],"params":[],"paramsType":"","query":[]}', - 'desc' => '', - 'paramsExample' => '', - 'response' => '[]', - 'responseExample' => '' -); -$normalApi = $data; - -$normalRelease = new stdclass(); -$normalRelease->version = 'Version1'; -$normalRelease->desc = ''; -$normalRelease->lib = 910; -$normalRelease->addedBy = $tester->app->user->account; -$normalRelease->addedDate = helper::now(); - -$apiInfo = $api->createTest($normalApi, false); -$release = $api->publishLibTest($normalRelease, false); - -r($api->getStructListByReleaseTest($release->lib)) && p('') && e(''); -//r($api->getApiListByReleaseTest($release)) && p('0:lib') && e('910'); //创建api后创建发布,使用发布查找api \ No newline at end of file +r($api->getStructListByReleaseTest('', 'where lib = 0')) && p('2:name') && e('editStruct'); // 获取没有接口库的接口文档的名称 +r($api->getStructListByReleaseTest('', 'where lib = 1')) && p('0:name') && e('user'); // 获取所属接口库ID为1的接口文档的名称 diff --git a/test/model/api/publishlib.php b/test/model/api/publishlib.php index 77438e0888..a9827eecd2 100755 --- a/test/model/api/publishlib.php +++ b/test/model/api/publishlib.php @@ -10,7 +10,7 @@ title=测试 apiModel->publishLib(); cid=1 pid=1 -没有版本名的发布 >> 『Version』should not be blank. +没有版本名的发布 >> 『版本』不能为空。 正常的发布 >> Version1 */ @@ -32,5 +32,5 @@ $normalRelease->lib = 910; $normalRelease->addedBy = $tester->app->user->account; $normalRelease->addedDate = helper::now(); -r($api->publishLibTest($emptyBuildRelease)) && p('version:0') && e('『Version』should not be blank.'); //没有版本名的发布 -r($api->publishLibTest($normalRelease)) && p('version') && e('Version1'); //正常的发布 \ No newline at end of file +r($api->publishLibTest($emptyBuildRelease)) && p('version:0') && e('『版本』不能为空。'); //没有版本名的发布 +r($api->publishLibTest($normalRelease)) && p('version') && e('Version1'); //正常的发布 diff --git a/test/model/api/update.php b/test/model/api/update.php index 4ebba341ba..f4872761e2 100755 --- a/test/model/api/update.php +++ b/test/model/api/update.php @@ -2,6 +2,7 @@ switchDB(); su('admin'); /** @@ -22,7 +23,7 @@ $data = array( 'title' => 'testapi', 'protocol' => 'HTTP', 'method' => 'GET', - 'path' => '/api/test/id', + 'path' => '/api/test/test', 'requestType' => 'application/json', 'status' => 'done', 'owner' => 'admin', @@ -57,4 +58,5 @@ $editApi = $editData; $apiInfo = $api->createTest($normalApi, false); -r($api->updateTest($apiInfo->id, $editApi)) && p('0:new') && e('edittestapi'); //修改一个刚创建的api \ No newline at end of file +r($api->updateTest($apiInfo->id, $editApi)) && p('0:new') && e('edittestapi'); //修改一个刚创建的api +$db->restoreDB(); diff --git a/test/model/api/updatestruct.php b/test/model/api/updatestruct.php index 28cf08cae9..601d6b69e5 100755 --- a/test/model/api/updatestruct.php +++ b/test/model/api/updatestruct.php @@ -2,6 +2,7 @@ switchDB(); su('admin'); /** @@ -11,7 +12,7 @@ cid=1 pid=1 正常的修改 >> editStruct -没有名称的修改 >> 『Name』should not be blank. +没有名称的修改 >> 『结构名』不能为空。 */ @@ -40,4 +41,5 @@ $emptyNameEditStruct['name'] = ''; $struct = $api->createStructTest($normalStruct, false); r($api->updateStructTest($struct->id, $normalEditStruct, false)) && p('0:new') && e('editStruct'); //正常的修改 -r($api->updateStructTest($struct->id, $emptyNameEditStruct)) && p('name:0') && e('『Name』should not be blank.'); //没有名称的修改 \ No newline at end of file +r($api->updateStructTest($struct->id, $emptyNameEditStruct)) && p('name:0') && e('『结构名』不能为空。'); //没有名称的修改 +$db->restoreDB(); diff --git a/test/model/block/checkapi.php b/test/model/block/checkapi.php index fa929c7957..9d188cc4fc 100755 --- a/test/model/block/checkapi.php +++ b/test/model/block/checkapi.php @@ -10,10 +10,14 @@ title=测试 blockModel->checkAPI(); cid=1 pid=1 - +测试空哈希值 >> 0 +测试正确的哈希值 >> 1 +测试错误的哈希值 >> 0 */ $block = new blockTest(); -r($block->checkAPITest()) && p() && e(); \ No newline at end of file +r($block->checkAPITest('')) && p('') && e('0'); // 测试空哈希值 +r($block->checkAPITest('858640a724c2c981983935eb2bbc4ad8')) && p('') && e('1'); // 测试正确的哈希值 +r($block->checkAPITest('858640a724c2c98198')) && p('') && e('0'); // 测试错误的哈希值 diff --git a/test/model/block/getoverviewparams.php b/test/model/block/getoverviewparams.php deleted file mode 100755 index b5831720dc..0000000000 --- a/test/model/block/getoverviewparams.php +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env php -getOverviewParams(); -cid=1 -pid=1 - - - -*/ - -$block = new blockTest(); - -r($block->getOverviewParamsTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/block/getproductparams.php b/test/model/block/getproductparams.php index 19a3b74284..35426dd2f6 100755 --- a/test/model/block/getproductparams.php +++ b/test/model/block/getproductparams.php @@ -10,10 +10,10 @@ title=测试 blockModel->getProductParams(); cid=1 pid=1 - +获取产品区块的参数 >> type:{name:类型,noclosed=>未关闭,closed=>已关闭,all=>全部,involved=>我参与,control:select};count:{name:数量,default:20,control:input}; */ $block = new blockTest(); -r($block->getProductParamsTest()) && p() && e(); \ No newline at end of file +r($block->getProductParamsTest()) && p() && e('type:{name:类型,noclosed=>未关闭,closed=>已关闭,all=>全部,involved=>我参与,control:select};count:{name:数量,default:20,control:input};'); // 获取产品区块的参数 diff --git a/test/model/block/getproductstatisticparams.php b/test/model/block/getproductstatisticparams.php index 1deba25d79..95d9108c4c 100755 --- a/test/model/block/getproductstatisticparams.php +++ b/test/model/block/getproductstatisticparams.php @@ -10,10 +10,10 @@ title=测试 blockModel->getProductStatisticParams(); cid=1 pid=1 - +获取产品统计区块的参数 >> count:{name:数量,default:20,control:input};type:{name:类型,noclosed=>未关闭,closed=>已关闭,all=>全部,involved=>我参与,control:select}; */ $block = new blockTest(); -r($block->getProductStatisticParamsTest()) && p() && e(); \ No newline at end of file +r($block->getProductStatisticParamsTest()) && p() && e('count:{name:数量,default:20,control:input};type:{name:类型,noclosed=>未关闭,closed=>已关闭,all=>全部,involved=>我参与,control:select};'); // 获取产品统计区块的参数 diff --git a/test/model/block/getprojectdynamicparams.php b/test/model/block/getprojectdynamicparams.php index d87ca56aef..835781c6d3 100755 --- a/test/model/block/getprojectdynamicparams.php +++ b/test/model/block/getprojectdynamicparams.php @@ -10,10 +10,9 @@ title=测试 blockModel->getProjectDynamicParams(); cid=1 pid=1 - - +获取项目动态区块参数 >> count:{name:数量,default:20,control:input}; */ $block = new blockTest(); -r($block->getProjectDynamicParamsTest()) && p() && e(); \ No newline at end of file +r($block->getProjectDynamicParamsTest()) && p() && e('count:{name:数量,default:20,control:input};'); // 获取项目动态区块参数 diff --git a/test/model/block/getprojectparams.php b/test/model/block/getprojectparams.php index 89088ad4ab..747959ed52 100755 --- a/test/model/block/getprojectparams.php +++ b/test/model/block/getprojectparams.php @@ -10,10 +10,9 @@ title=测试 blockModel->getProjectParams(); cid=1 pid=1 -获取计划参数 >> {"type":{"name":"\u7c7b\u578b","options":{"all":"\u6240\u6709","doing":"\u8fdb\u884c\u4e2d","wait":"\u672a\u5f00\u59cb","suspended":"\u5df2\u6302\u8d77","closed":"\u5df2\u5173\u95ed"},"control":"select"},"orderBy":{"name":"\u6392\u5e8f","options":{"id_asc":"ID \u9012\u589e","id_desc":"ID \u9012\u51cf","status_asc":"\u72b6\u6001\u6b63\u5e8f","status_desc":"\u72b6\u6001\u5012\u5e8f"},"control":"select"},"count":{"name":"\u6570\u91cf","default":20,"control":"input"}} - +获取计划参数 >> {"type":{"name":"\u7c7b\u578b","options":{"all":"\u6240\u6709","undone":"\u672a\u5b8c\u6210","wait":"\u672a\u5f00\u59cb","doing":"\u8fdb\u884c\u4e2d","suspended":"\u5df2\u6302\u8d77","closed":"\u5df2\u5173\u95ed"},"control":"select"},"orderBy":{"name":"\u6392\u5e8f","options":{"id_asc":"ID \u9012\u589e","id_desc":"ID \u9012\u51cf","status_asc":"\u72b6\u6001\u6b63\u5e8f","status_desc":"\u72b6\u6001\u5012\u5e8f"},"control":"select"},"count":{"name":"\u6570\u91cf","default":20,"control":"input"}} */ $block = new blockTest(); -r($block->getProjectParamsTest()) && p() && e('{"type":{"name":"\u7c7b\u578b","options":{"all":"\u6240\u6709","doing":"\u8fdb\u884c\u4e2d","wait":"\u672a\u5f00\u59cb","suspended":"\u5df2\u6302\u8d77","closed":"\u5df2\u5173\u95ed"},"control":"select"},"orderBy":{"name":"\u6392\u5e8f","options":{"id_asc":"ID \u9012\u589e","id_desc":"ID \u9012\u51cf","status_asc":"\u72b6\u6001\u6b63\u5e8f","status_desc":"\u72b6\u6001\u5012\u5e8f"},"control":"select"},"count":{"name":"\u6570\u91cf","default":20,"control":"input"}}'); //获取计划参数 \ No newline at end of file +r($block->getProjectParamsTest()) && p() && e('{"type":{"name":"\u7c7b\u578b","options":{"all":"\u6240\u6709","undone":"\u672a\u5b8c\u6210","wait":"\u672a\u5f00\u59cb","doing":"\u8fdb\u884c\u4e2d","suspended":"\u5df2\u6302\u8d77","closed":"\u5df2\u5173\u95ed"},"control":"select"},"orderBy":{"name":"\u6392\u5e8f","options":{"id_asc":"ID \u9012\u589e","id_desc":"ID \u9012\u51cf","status_asc":"\u72b6\u6001\u6b63\u5e8f","status_desc":"\u72b6\u6001\u5012\u5e8f"},"control":"select"},"count":{"name":"\u6570\u91cf","default":20,"control":"input"}}'); //获取计划参数 diff --git a/test/model/block/getprojectteamparams.php b/test/model/block/getprojectteamparams.php index 1e6df07e1f..c5421855fb 100755 --- a/test/model/block/getprojectteamparams.php +++ b/test/model/block/getprojectteamparams.php @@ -10,10 +10,10 @@ title=测试 blockModel->getProjectTeamParams(); cid=1 pid=1 -测试获取项目团队 >> type:{name:类型,all=>所有,doing=>进行中,wait=>未开始,suspended=>已挂起,closed=>已关闭,control:select};orderBy:{name:排序,id_asc=>ID 递增,id_desc=>ID 递减,status_asc=>状态正序,status_desc=>状态倒序,control:select};count:{name:数量,default:20,control:input}; +测试获取项目团队 >> type:{name:类型,all=>所有,undone=>未完成,wait=>未开始,doing=>进行中,suspended=>已挂起,closed=>已关闭,control:select};orderBy:{name:排序,id_asc=>ID 递增,id_desc=>ID 递减,status_asc=>状态正序,status_desc=>状态倒序,control:select};count:{name:数量,default:20,control:input}; */ $block = new blockTest(); -r($block->getProjectTeamParamsTest()) && p() && e('type:{name:类型,all=>所有,doing=>进行中,wait=>未开始,suspended=>已挂起,closed=>已关闭,control:select};orderBy:{name:排序,id_asc=>ID 递增,id_desc=>ID 递减,status_asc=>状态正序,status_desc=>状态倒序,control:select};count:{name:数量,default:20,control:input};'); // 测试获取项目团队 \ No newline at end of file +r($block->getProjectTeamParamsTest()) && p() && e('type:{name:类型,all=>所有,undone=>未完成,wait=>未开始,doing=>进行中,suspended=>已挂起,closed=>已关闭,control:select};orderBy:{name:排序,id_asc=>ID 递增,id_desc=>ID 递减,status_asc=>状态正序,status_desc=>状态倒序,control:select};count:{name:数量,default:20,control:input};'); // 测试获取项目团队 diff --git a/test/model/block/getscrumoverviewparams.php b/test/model/block/getscrumoverviewparams.php deleted file mode 100755 index 4c9969d044..0000000000 --- a/test/model/block/getscrumoverviewparams.php +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env php -getScrumOverviewParams(); -cid=1 -pid=1 - - - -*/ - -$block = new blockTest(); - -r($block->getScrumOverviewParamsTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/block/getsprintparams.php b/test/model/block/getsprintparams.php deleted file mode 100755 index 1843a0bfc2..0000000000 --- a/test/model/block/getsprintparams.php +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env php -getSprintParams(); -cid=1 -pid=1 - - - -*/ - -$block = new blockTest(); - -r($block->getSprintParamsTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/block/getwaterfallestimateparams.php b/test/model/block/getwaterfallestimateparams.php deleted file mode 100755 index c0f9b709ef..0000000000 --- a/test/model/block/getwaterfallestimateparams.php +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env php -getWaterfallEstimateParams(); -cid=1 -pid=1 - - - -*/ - -$block = new blockTest(); - -r($block->getWaterfallEstimateParamsTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/block/getwaterfallganttparams.php b/test/model/block/getwaterfallganttparams.php deleted file mode 100755 index 2b667d2c51..0000000000 --- a/test/model/block/getwaterfallganttparams.php +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env php -getWaterfallGanttParams(); -cid=1 -pid=1 - - - -*/ - -$block = new blockTest(); - -r($block->getWaterfallGanttParamsTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/block/getwaterfallprogressparams.php b/test/model/block/getwaterfallprogressparams.php deleted file mode 100755 index 4821ee58a4..0000000000 --- a/test/model/block/getwaterfallprogressparams.php +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env php -getWaterfallProgressParams(); -cid=1 -pid=1 - - - -*/ - -$block = new blockTest(); - -r($block->getWaterfallProgressParamsTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/block/getwaterfallreportparams.php b/test/model/block/getwaterfallreportparams.php deleted file mode 100755 index d3c54f547e..0000000000 --- a/test/model/block/getwaterfallreportparams.php +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env php -getWaterfallReportParams(); -cid=1 -pid=1 - - - -*/ - -$block = new blockTest(); - -r($block->getWaterfallReportParamsTest()) && p() && e(); \ No newline at end of file diff --git a/test/model/block/getwelcomeblockdata.php b/test/model/block/getwelcomeblockdata.php index 58457eab52..46071198f4 100755 --- a/test/model/block/getwelcomeblockdata.php +++ b/test/model/block/getwelcomeblockdata.php @@ -10,10 +10,10 @@ title=测试 blockModel->getWelcomeBlockData(); cid=1 pid=1 - +获取欢迎区块的数据 >> {"tasks":"0","doneTasks":"0","bugs":85,"stories":0,"executions":739,"products":80,"delayTask":0,"delayBug":74,"delayProject":0} */ $block = new blockTest(); -r($block->getWelcomeBlockDataTest()) && p() && e(); \ No newline at end of file +r($block->getWelcomeBlockDataTest()) && p() && e('{"tasks":"0","doneTasks":"0","bugs":85,"stories":0,"executions":739,"products":80,"delayTask":0,"delayBug":74,"delayProject":0}'); // 获取欢迎区块的数据 diff --git a/test/model/block/initblock.php b/test/model/block/initblock.php index 72cbb1c5cf..111fb9e21c 100755 --- a/test/model/block/initblock.php +++ b/test/model/block/initblock.php @@ -59,4 +59,4 @@ r($dataList[6]) && p("blockData:module;blockData:type") && e('qa;'); r($dataList[7]) && p("blockInited;blockversion") && e('1;2'); // 获取空区块版本 r($dataList[7]) && p("blockData") && e('0'); // 获取空区块数据 -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/block/save.php b/test/model/block/save.php index 85c5f36c72..8822e5e106 100755 --- a/test/model/block/save.php +++ b/test/model/block/save.php @@ -13,13 +13,13 @@ pid=1 测试修改block 名称 >> 欢迎test,my,8,welcome 测试修改block 模块 >> 我的贡献,my,8,dynamic -测试修改block 区块 >> 项目统计,my,8,projectteam -测试修改block 变量 >> 未关闭的产品,product,8,statistic +测试修改block 区块 >> 项目统计,projectteam,8,projectteam +测试修改block 变量 >> 未关闭的产品,statistic,8,statistic */ $blockID = array('95', '99', '113'); -$module = 'product'; +$source = 'product'; $changeTitle = new stdclass(); $changeTitle->modules = 'welcome'; @@ -51,8 +51,8 @@ $changeParams->actionLink = '/block-set-95-welcome-.html'; $block = new blockTest(); -r($block->saveTest($changeTitle, $blockID[0], $changeTitle->modules)) && p('title,module,grid,block') && e('欢迎test,my,8,welcome'); // 测试修改block 名称 -r($block->saveTest($changeModules, $blockID[0], $changModules->modules)) && p('title,module,grid,block') && e('我的贡献,my,8,dynamic'); // 测试修改block 模块 -r($block->saveTest($changeBlock, $blockID[1], $changeBlock->modules, $changeBlock->moduleBlock)) && p('title,module,grid,block') && e('项目统计,my,8,projectteam'); // 测试修改block 区块 -r($block->saveTest($changeParams, $blockID[2], $changeParams->modules, $changeParams->moduleBlock, $module)) && p('title,module,grid,block') && e('未关闭的产品,product,8,statistic'); // 测试修改block 变量 -$db->restoreDB(); \ No newline at end of file +r($block->saveTest($changeTitle, $blockID[0], $source, $changeTitle->modules)) && p('title,module,grid,block') && e('欢迎test,my,8,welcome'); // 测试修改block 名称 +r($block->saveTest($changeModules, $blockID[0], $source, $changeModules->modules)) && p('title,module,grid,block') && e('我的贡献,my,8,dynamic'); // 测试修改block 模块 +r($block->saveTest($changeBlock, $blockID[1], $source, $changeBlock->modules, $changeBlock->moduleBlock)) && p('title,module,grid,block') && e('项目统计,projectteam,8,projectteam'); // 测试修改block 区块 +r($block->saveTest($changeParams, $blockID[2], $source, $changeParams->modules, $changeParams->moduleBlock)) && p('title,module,grid,block') && e('未关闭的产品,statistic,8,statistic'); // 测试修改block 变量 +$db->restoreDB(); diff --git a/test/model/branch/getbyproducts.php b/test/model/branch/getbyproducts.php index 9a562396b3..4b23ec4c02 100755 --- a/test/model/branch/getbyproducts.php +++ b/test/model/branch/getbyproducts.php @@ -10,20 +10,20 @@ title=测试 branchModel->getByProducts(); cid=1 pid=1 -测试获取产品 41 42 的分支信息 >> 1:,0;41:,0,1,2;42:,0,3,4; -测试获取产品 41 42 的分支信息 >> 1:,0;41:,0,1,2;42:,0,3,4; -测试获取产品 41 42 的分支信息 >> 1:,0;41:,0,1;42:,0,3; +测试获取产品 41 42 的分支信息 >> 41:,0,1,2;42:,0,3,4;1:,0; +测试获取产品 41 42 的分支信息 >> 41:,0,1,2;42:,0,3,4;1:,0; +测试获取产品 41 42 的分支信息 >> 41:,0,1;42:,0,3;1:,0; 测试获取产品 41 42 的分支信息 >> 41:,0,1,2;42:,0,3,4; -测试获取产品 41 42 的分支信息 >> 1:,0;41:,1,2;42:,3,4; +测试获取产品 41 42 的分支信息 >> 41:,1,2;42:,3,4;1:,0; 测试获取产品 41 42 的分支信息 >> 41:,0,1;42:,0,3; 测试获取产品 41 42 的分支信息 >> 41:,1,2;42:,3,4; -测试获取产品 41 42 追加branch20 21 的分支信息 >> 1:,0;41:,0,1,2;42:,0,3,4; -测试获取产品 41 42 noclosed 追加branch20 21 的分支信息 >> 1:,0;41:,0,1;42:,0,3; +测试获取产品 41 42 追加branch20 21 的分支信息 >> 41:,0,1,2;42:,0,3,4;1:,0; +测试获取产品 41 42 noclosed 追加branch20 21 的分支信息 >> 41:,0,1;42:,0,3;1:,0; 测试获取产品 41 42 ignoreNormal 追加branch20 21 的分支信息 >> 41:,0,1,2;42:,0,3,4; -测试获取产品 41 42 noempty 追加branch20 21 的分支信息 >> 1:,0;41:,1,2;42:,3,4; +测试获取产品 41 42 noempty 追加branch20 21 的分支信息 >> 41:,1,2;42:,3,4;1:,0; 测试获取产品 41 42 noclosed,ignoreNormal 追加branch20 21 的分支信息 >> 41:,0,1;42:,0,3; 测试获取产品 41 42 ignoreNormal,noempty 追加branch20 21 的分支信息 >> 41:,1,2;42:,3,4; -测试获取产品 81 82 的分支信息 >> 2:,0;81:,0,81,82;82:,0,83,84; +测试获取产品 81 82 的分支信息 >> 81:,0,81,82;82:,0,83,84;2:,0; 测试获取产品 43 83 的分支信息 >> 43:,0,5,6;83:,0,85,86; */ @@ -34,18 +34,18 @@ $appendBranch = ''; $branch = new branchTest(); -r($branch->getByProductsTest($products[0])) && p() && e('1:,0;41:,0,1,2;42:,0,3,4;'); // 测试获取产品 41 42 的分支信息 -r($branch->getByProductsTest($products[0], $params[0])) && p() && e('1:,0;41:,0,1,2;42:,0,3,4;'); // 测试获取产品 41 42 的分支信息 -r($branch->getByProductsTest($products[0], $params[1])) && p() && e('1:,0;41:,0,1;42:,0,3;'); // 测试获取产品 41 42 的分支信息 +r($branch->getByProductsTest($products[0])) && p() && e('41:,0,1,2;42:,0,3,4;1:,0;'); // 测试获取产品 41 42 的分支信息 +r($branch->getByProductsTest($products[0], $params[0])) && p() && e('41:,0,1,2;42:,0,3,4;1:,0;'); // 测试获取产品 41 42 的分支信息 +r($branch->getByProductsTest($products[0], $params[1])) && p() && e('41:,0,1;42:,0,3;1:,0;'); // 测试获取产品 41 42 的分支信息 r($branch->getByProductsTest($products[0], $params[2])) && p() && e('41:,0,1,2;42:,0,3,4;'); // 测试获取产品 41 42 的分支信息 -r($branch->getByProductsTest($products[0], $params[3])) && p() && e('1:,0;41:,1,2;42:,3,4;'); // 测试获取产品 41 42 的分支信息 +r($branch->getByProductsTest($products[0], $params[3])) && p() && e('41:,1,2;42:,3,4;1:,0;'); // 测试获取产品 41 42 的分支信息 r($branch->getByProductsTest($products[0], $params[4])) && p() && e('41:,0,1;42:,0,3;'); // 测试获取产品 41 42 的分支信息 r($branch->getByProductsTest($products[0], $params[5])) && p() && e('41:,1,2;42:,3,4;'); // 测试获取产品 41 42 的分支信息 -r($branch->getByProductsTest($products[0], $params[0], $appendBranch)) && p() && e('1:,0;41:,0,1,2;42:,0,3,4;'); // 测试获取产品 41 42 追加branch20 21 的分支信息 -r($branch->getByProductsTest($products[0], $params[1], $appendBranch)) && p() && e('1:,0;41:,0,1;42:,0,3;'); // 测试获取产品 41 42 noclosed 追加branch20 21 的分支信息 +r($branch->getByProductsTest($products[0], $params[0], $appendBranch)) && p() && e('41:,0,1,2;42:,0,3,4;1:,0;'); // 测试获取产品 41 42 追加branch20 21 的分支信息 +r($branch->getByProductsTest($products[0], $params[1], $appendBranch)) && p() && e('41:,0,1;42:,0,3;1:,0;'); // 测试获取产品 41 42 noclosed 追加branch20 21 的分支信息 r($branch->getByProductsTest($products[0], $params[2], $appendBranch)) && p() && e('41:,0,1,2;42:,0,3,4;'); // 测试获取产品 41 42 ignoreNormal 追加branch20 21 的分支信息 -r($branch->getByProductsTest($products[0], $params[3], $appendBranch)) && p() && e('1:,0;41:,1,2;42:,3,4;'); // 测试获取产品 41 42 noempty 追加branch20 21 的分支信息 +r($branch->getByProductsTest($products[0], $params[3], $appendBranch)) && p() && e('41:,1,2;42:,3,4;1:,0;'); // 测试获取产品 41 42 noempty 追加branch20 21 的分支信息 r($branch->getByProductsTest($products[0], $params[4], $appendBranch)) && p() && e('41:,0,1;42:,0,3;'); // 测试获取产品 41 42 noclosed,ignoreNormal 追加branch20 21 的分支信息 r($branch->getByProductsTest($products[0], $params[5], $appendBranch)) && p() && e('41:,1,2;42:,3,4;'); // 测试获取产品 41 42 ignoreNormal,noempty 追加branch20 21 的分支信息 -r($branch->getByProductsTest($products[1])) && p() && e('2:,0;81:,0,81,82;82:,0,83,84;'); // 测试获取产品 81 82 的分支信息 -r($branch->getByProductsTest($products[2])) && p() && e('43:,0,5,6;83:,0,85,86;'); // 测试获取产品 43 83 的分支信息 \ No newline at end of file +r($branch->getByProductsTest($products[1])) && p() && e('81:,0,81,82;82:,0,83,84;2:,0;'); // 测试获取产品 81 82 的分支信息 +r($branch->getByProductsTest($products[2])) && p() && e('43:,0,5,6;83:,0,85,86;'); // 测试获取产品 43 83 的分支信息 diff --git a/test/model/branch/getproducttype.php b/test/model/branch/getproducttype.php index 947e2e9b88..e7951b852b 100755 --- a/test/model/branch/getproducttype.php +++ b/test/model/branch/getproducttype.php @@ -27,4 +27,4 @@ r($branch->getProductTypeTest($branchID[1])) && p() && e('branch'); // 测试 r($branch->getProductTypeTest($branchID[2])) && p() && e('platform'); // 测试获取分支 81 的项目类型 r($branch->getProductTypeTest($branchID[3])) && p() && e('platform'); // 测试获取分支 83 的项目类型 r($branch->getProductTypeTest($branchID[4])) && p() && e('normal'); // 测试获取分支 161 的项目类型 -r($branch->getProductTypeTest($branchID[5])) && p() && e('normal'); // 测试获取分支 163 的项目类型 \ No newline at end of file +r($branch->getProductTypeTest($branchID[5])) && p() && e('normal'); // 测试获取分支 163 的项目类型 diff --git a/test/model/branch/setdefault.php b/test/model/branch/setdefault.php new file mode 100755 index 0000000000..a96a1c86a8 --- /dev/null +++ b/test/model/branch/setdefault.php @@ -0,0 +1,30 @@ +#!/usr/bin/env php +switchDB(); +su('admin'); + +/** + +title=测试 branchModel->setDefault(); +cid=1 +pid=1 + +测试将productID 0, branchID 0的分支设为默认分支 >> 0 +测试将productID 0, branchID 1的分支设为默认分支 >> 分支1,1 +测试将productID 41, branchID 0的分支设为默认分支 >> 主干 +测试将productID 41, branchID 0的分支设为默认分支 >> 分支1,1 + +*/ + +$productIdList = array(0, 41); +$branchIdList = array(0, 1); + +$branch = new branchTest(); + +r($branch->setDefaultTest($productIdList[0], $branchIdList[0])) && p() && e('0'); // 测试将productID 0, branchID 0的分支设为默认分支 +r($branch->setDefaultTest($productIdList[0], $branchIdList[1])) && p('name,default') && e('分支1,1'); // 测试将productID 0, branchID 1的分支设为默认分支 +r($branch->setDefaultTest($productIdList[1], $branchIdList[0])) && p() && e('主干'); // 测试将productID 41, branchID 0的分支设为默认分支 +r($branch->setDefaultTest($productIdList[1], $branchIdList[1])) && p('name,default') && e('分支1,1'); // 测试将productID 41, branchID 0的分支设为默认分支 +$db->restoreDB(); diff --git a/test/model/bug/activate.php b/test/model/bug/activate.php index b90d847424..2d248b4ea6 100755 --- a/test/model/bug/activate.php +++ b/test/model/bug/activate.php @@ -28,4 +28,4 @@ r($bug->activateObject($bugIDList[2])) && p('field,old,new') && e('activatedCoun r($bug->activateObject($bugIDList[3])) && p('field,old,new') && e('activatedCount,0,1'); // 测试激活状态为resolved的bug52 r($bug->activateObject($bugIDList[4])) && p('field,old,new') && e('activatedCount,0,1'); // 测试激活状态为closed的bug81 r($bug->activateObject($bugIDList[5])) && p('field,old,new') && e('activatedCount,0,1'); // 测试激活状态为closed的bug82 -$db->restoreDB(); +$db->restoreDB(); \ No newline at end of file diff --git a/test/model/bug/getdataofbugsperbuild.php b/test/model/bug/getdataofbugsperbuild.php index 55ce9c2903..7ba8114bcf 100755 --- a/test/model/bug/getdataofbugsperbuild.php +++ b/test/model/bug/getdataofbugsperbuild.php @@ -18,4 +18,4 @@ pid=1 $bug=new bugTest(); r($bug->getDataOfBugsPerBuildTest()) && p('trunk:name,value') && e('主干,291'); // 获取主干bug数 r($bug->getDataOfBugsPerBuildTest()) && p('0:name,value') && e('未设定,3'); // 获取bug数 -r($bug->getDataOfBugsPerBuildTest()) && p('1:name,value') && e('项目版本版本1,6'); // 获取项目版本版本1bug数 +r($bug->getDataOfBugsPerBuildTest()) && p('1:name,value') && e('项目版本版本1,6'); // 获取项目版本版本1bug数 \ No newline at end of file diff --git a/test/model/bug/processbuildforbugs.php b/test/model/bug/processbuildforbugs.php index 78bd158597..1754550607 100755 --- a/test/model/bug/processbuildforbugs.php +++ b/test/model/bug/processbuildforbugs.php @@ -31,4 +31,4 @@ r($bug->processBuildForBugsTest($bugIDList2)) && p('4:openedBuild,resolvedBuild; r($bug->processBuildForBugsTest($bugIDList3)) && p('51:openedBuild,resolvedBuild;52:openedBuild,resolvedBuild;53:openedBuild,resolvedBuild') && e('主干,;主干,;主干,'); // 测试处理bug51 52 53的openedBuild resolvedBuild字段 r($bug->processBuildForBugsTest($bugIDList4)) && p('54:openedBuild,resolvedBuild;55:openedBuild,resolvedBuild;56:openedBuild,resolvedBuild') && e('主干,;主干,;主干,主干'); // 测试处理bug54 55 56的openedBuild resolvedBuild字段 r($bug->processBuildForBugsTest($bugIDList5)) && p('81:openedBuild,resolvedBuild;82:openedBuild,resolvedBuild;83:openedBuild,resolvedBuild') && e('主干,;主干,;主干,'); // 测试处理bug81 82 83的openedBuild resolvedBuild字段 -r($bug->processBuildForBugsTest($bugIDList6)) && p('84:openedBuild,resolvedBuild;85:openedBuild,resolvedBuild;86:openedBuild,resolvedBuild') && e('主干,;主干,;主干,'); // 测试处理bug84 85 86的openedBuild resolvedBuild字段 +r($bug->processBuildForBugsTest($bugIDList6)) && p('84:openedBuild,resolvedBuild;85:openedBuild,resolvedBuild;86:openedBuild,resolvedBuild') && e('主干,;主干,;主干,'); // 测试处理bug84 85 86的openedBuild resolvedBuild字段 \ No newline at end of file diff --git a/test/model/build/getbuildpairs.php b/test/model/build/getbuildpairs.php index af2df29deb..766cee4d0e 100755 --- a/test/model/build/getbuildpairs.php +++ b/test/model/build/getbuildpairs.php @@ -14,8 +14,8 @@ pid=1 单长产品执行版本查询 >> 执行版本版本11 项目执行版本查询 >> 主干 数组产品执行版本查询统计 >> 6 -单长产品执行版本查询统计 >> 5 -项目执行版本查询统计 >> 4 +单长产品执行版本查询统计 >> 4 +项目执行版本查询统计 >> 1 */ @@ -34,5 +34,5 @@ r($build->getBuildPairsTest($count[0], $products, $branch, $params[0], $objectID r($build->getBuildPairsTest($count[0], $products[1], $branch, $params[1], $objectID[0], $objectType[0], $buildIdList,$replace[0])) && p('11') && e('执行版本版本11');//单长产品执行版本查询 r($build->getBuildPairsTest($count[0], $products, $branch, $params[2], $objectID[1], $objectType[1], $buildIdList,$replace[0])) && p('trunk') && e('主干'); //项目执行版本查询 r($build->getBuildPairsTest($count[1], $products, $branch, $params[0], $objectID[0], $objectType[0], '',$replace[0])) && p() && e('6'); //数组产品执行版本查询统计 -r($build->getBuildPairsTest($count[1], $products[1], $branch, $params[1], $objectID[0], $objectType[0], $buildIdList,$replace[0])) && p() && e('5'); //单长产品执行版本查询统计 -r($build->getBuildPairsTest($count[1], $products, $branch, $params[2], $objectID[1], $objectType[1], $buildIdList,$replace[0])) && p() && e('4'); //项目执行版本查询统计 \ No newline at end of file +r($build->getBuildPairsTest($count[1], $products[1], $branch, $params[1], $objectID[0], $objectType[0], $buildIdList,$replace[0])) && p() && e('4'); //单长产品执行版本查询统计 +r($build->getBuildPairsTest($count[1], $products, $branch, $params[2], $objectID[1], $objectType[1], $buildIdList,$replace[0])) && p() && e('1'); //项目执行版本查询统计 diff --git a/test/model/build/linkstory.php b/test/model/build/linkstory.php index 59f15ba03d..e42f035164 100755 --- a/test/model/build/linkstory.php +++ b/test/model/build/linkstory.php @@ -11,7 +11,7 @@ title=测试 buildModel->linkStory(); cid=1 pid=1 - >> ,2,4,11 + >> 2,4,,11 >> ,2,4,101 */ @@ -24,8 +24,8 @@ $noStorylink = array('stories' => array()); $build = new buildTest(); -r($build->linkStoryTest($buildIDList[0], $nomalStorylink)) && p('1:stories,project') && e(',2,4,11'); +r($build->linkStoryTest($buildIDList[0], $nomalStorylink)) && p('1:stories,project') && e('2,4,,11'); r($build->linkStoryTest($buildIDList[1], $nomalStorylink)) && p('11:stories,execution') && e(',2,4,101'); r($build->linkStoryTest($buildIDList[0], $noStorylink)) && p('1:stories') && e(''); -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/build/unlinkbug.php b/test/model/build/unlinkbug.php index 9255f90886..2fe04766fd 100755 --- a/test/model/build/unlinkbug.php +++ b/test/model/build/unlinkbug.php @@ -13,7 +13,6 @@ pid=1 项目版本解除bug >> ,311,11 执行版本解除bug >> ,301,101 -不传入BugID >> 『对象ID』应当是数字。 */ @@ -24,6 +23,5 @@ $build = new buildTest(); r($build->unlinkBugTest($buildIDList[0],$bugs,$bugs[0])) && p('1:bugs,project') && e(',311,11'); //项目版本解除bug r($build->unlinkBugTest($buildIDList[1],$bugs,$bugs[1])) && p('11:bugs,execution') && e(',301,101'); //执行版本解除bug -r($build->unlinkBugTest($buildIDList[1],$bugs,'')) && p('objectID:0') && e('『对象ID』应当是数字。');//不传入BugID -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/build/unlinkstory.php b/test/model/build/unlinkstory.php index ab5b4e080f..9a08df313d 100755 --- a/test/model/build/unlinkstory.php +++ b/test/model/build/unlinkstory.php @@ -13,7 +13,6 @@ pid=1 解除项目版本需求 >> ,4,11 解除执行版本需求 >> ,2,101 -需求id为空 >> 『对象ID』应当是数字。 */ $buildIDList = array('1', '11'); @@ -23,6 +22,5 @@ $build = new buildTest(); r($build->unlinkStoryTest($buildIDList[0],$stories,$stories[0])) && p('1:stories,project') && e(',4,11'); //解除项目版本需求 r($build->unlinkStoryTest($buildIDList[1],$stories,$stories[1])) && p('11:stories,execution') && e(',2,101'); //解除执行版本需求 -r($build->unlinkStoryTest($buildIDList[0],$stories,'')) && p('objectID:0') && e('『对象ID』应当是数字。');//需求id为空 -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/caselib/batchcreatecase.php b/test/model/caselib/batchcreatecase.php index 074c29d3da..043129c789 100755 --- a/test/model/caselib/batchcreatecase.php +++ b/test/model/caselib/batchcreatecase.php @@ -34,7 +34,7 @@ $total = $tester->dao->select('count(*) total')->from(TABLE_CASE)->where( 'lib') $cases = $tester->dao->select('*')->from(TABLE_CASE)->where( 'lib')->eq(201)->fetchAll('id'); r($total) && p() && e('12'); // 添加两条数据之后查询数据条数是否正确 -r($cases) && p('411:title,type') && e('测试导入添加1,performance'); // 添加数据之后查询新加用例的名称,用例类型 -r($cases) && p('412:title,type') && e('测试导入添加2,unit'); // 添加数据之后查询新加用例的名称,用例类型 +r($cases) && p('561:title,type') && e('测试导入添加1,performance'); // 添加数据之后查询新加用例的名称,用例类型 +r($cases) && p('562:title,type') && e('测试导入添加2,unit'); // 添加数据之后查询新加用例的名称,用例类型 -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/caselib/buildsearchform.php b/test/model/caselib/buildsearchform.php deleted file mode 100755 index 24c06fb5a9..0000000000 --- a/test/model/caselib/buildsearchform.php +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env php -buildSearchForm(); -cid=1 -pid=1 - -测试设置的url参数 >> model/caselib/buildsearchform.php?m=caselib&f=browse&t=&libID=201&browseType=bySearch&queryID=myQueryID -测试设置的queryID值是否正确 >> 10 - -*/ - -$caselib = new caselibTest(); -$libID = 201; -$queryID = 10; -$actionURL = helper::createLink('caselib', 'browse', "libID=$libID&browseType=bySearch&queryID=myQueryID"); -$libs = $tester->loadModel('caselib')->getLibraries(); - -$caselib->buildSearchFormTest($libID, $libs, $queryID, $actionURL); -$search = $tester->config->testcase->search; - -r($search) && p('actionURL') && e('model/caselib/buildsearchform.php?m=caselib&f=browse&t=&libID=201&browseType=bySearch&queryID=myQueryID'); //测试设置的url参数 -r($search) && p('queryID') && e('10'); //测试设置的queryID值是否正确 \ No newline at end of file diff --git a/test/model/caselib/createfromimport.php b/test/model/caselib/createfromimport.php index 7c877d3471..97a5797df3 100755 --- a/test/model/caselib/createfromimport.php +++ b/test/model/caselib/createfromimport.php @@ -26,8 +26,10 @@ $_POST = array( 'type' => array(2 => 'performance', 3 => 'unit'), 'stage' => array(2 => array(), 3 => array()), 'keywords' => array(2 => 'keywords1', 3 => 'keywords2'), + 'status' => array(2 => '', 3 => ''), + 'desc' => array(2 => array(), 3 => array()), 'precondition' => array(2 => '', 3 => ''), - 'isEndPage' => 1, + 'isEndPage' => 0, 'pagerID' => 1 ); @@ -37,7 +39,7 @@ $total = $tester->dao->select('count(*) total')->from(TABLE_CASE)->where( 'lib') $cases = $tester->dao->select('*')->from(TABLE_CASE)->where( 'lib')->eq(201)->fetchAll('id'); r($total) && p() && e('12'); //添加两条数据之后查询数据条数是否正确 -r($cases) && p('411:title,keywords') && e('测试导入添加1,keywords1'); //添加数据之后查询新加用例的名称,关键字 -r($cases) && p('412:title,keywords') && e('测试导入添加2,keywords2'); //添加数据之后查询新加用例的名称,关键字 +r($cases) && p('561:title,keywords') && e('测试导入添加1,keywords1'); //添加数据之后查询新加用例的名称,关键字 +r($cases) && p('562:title,keywords') && e('测试导入添加2,keywords2'); //添加数据之后查询新加用例的名称,关键字 -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/caselib/getliblink.php b/test/model/caselib/getliblink.php deleted file mode 100755 index d807e33254..0000000000 --- a/test/model/caselib/getliblink.php +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env php -getLibLink(); -cid=1 -pid=1 - -测试参数情况1返回值 >> model/caselib/getliblink.php?m=caselib&f=browse&t=&libID=%s -测试参数情况2返回值 >> model/caselib/getliblink.php?m=caselib&f=test&t=&libID=%s -测试参数情况3返回值 >> model/caselib/getliblink.php?m=tree&f=&t=&libID=%s&type=caselib¤tModuleID=0 -测试参数情况4返回值 >> model/caselib/getliblink.php?m=caselib&f=browse&t=&libID=%s - -*/ - -$caselib = new caselibTest(); -$link1 = $caselib->getLibLinkTest('caselib', 'create', ''); -$link2 = $caselib->getLibLinkTest('caselib', 'test', ''); -$link3 = $caselib->getLibLinkTest('tree', '', ''); -$link4 = $caselib->getLibLinkTest('', '', ''); - -r($link1) && p() && e('model/caselib/getliblink.php?m=caselib&f=browse&t=&libID=%s'); // 测试参数情况1返回值 -r($link2) && p() && e('model/caselib/getliblink.php?m=caselib&f=test&t=&libID=%s'); // 测试参数情况2返回值 -r($link3) && p() && e('model/caselib/getliblink.php?m=tree&f=&t=&libID=%s&type=caselib¤tModuleID=0'); // 测试参数情况3返回值 -r($link4) && p() && e('model/caselib/getliblink.php?m=caselib&f=browse&t=&libID=%s'); // 测试参数情况4返回值 \ No newline at end of file diff --git a/test/model/caselib/setlibmenu.php b/test/model/caselib/setlibmenu.php deleted file mode 100755 index 5956ccde75..0000000000 --- a/test/model/caselib/setlibmenu.php +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env php -setLibMenu(); -cid=1 -pid=1 - -修改下拉菜单之后返回值 >> 1 - -*/ - -$caselib = new caselibTest(); -$libs = $tester->loadModel('caselib')->getLibraries(); -$config->webRoot = 'model/caselib/';//ztest运行时候获取的不一致 -$info = $caselib->setLibMenuTest($libs, 201); - -$menuStr = << -EOT; -r($tester->lang->switcherMenu == trim($menuStr)) && p() && e('1'); //修改下拉菜单之后返回值 \ No newline at end of file diff --git a/test/model/custom/saverequiredfields.php b/test/model/custom/saverequiredfields.php index dd02f2e4bc..890bdbc2fd 100755 --- a/test/model/custom/saverequiredfields.php +++ b/test/model/custom/saverequiredfields.php @@ -19,7 +19,7 @@ pid=1 测试moduleName为product,requiredFields中的create,edit各存在多个值 >> PO,RD,name,code 测试moduleName为release,requiredFields为空 >> name,date 测试moduleName为release,requiredFields中的create存在一个值 >> desc,name,date -测试moduleName为release,requiredFields中的rdit存在一个值 >> desc,name,date +测试moduleName为release,requiredFields中的edit存在一个值 >> desc,name,build,date 测试moduleName为release,requiredFields中的create,edit各存在一个值 >> desc,name,date 测试moduleName为execution,requiredFields为空 >> name,code,begin,end 测试moduleName为execution,requiredFields中的create存在一个值 >> desc,name,code,begin,end @@ -112,7 +112,7 @@ r($custom->saveRequiredFieldsTest($moduleName[0], $requiredFields['productFields r($custom->saveRequiredFieldsTest($moduleName[0], $requiredFields['productFields6'], $fieldsType[0])) && p('value') && e('PO,RD,name,code'); //测试moduleName为product,requiredFields中的create,edit各存在多个值 r($custom->saveRequiredFieldsTest($moduleName[1], $requiredFields['releaseFields1'], $fieldsType[0])) && p('value') && e('name,date'); //测试moduleName为release,requiredFields为空 r($custom->saveRequiredFieldsTest($moduleName[1], $requiredFields['releaseFields2'], $fieldsType[0])) && p('value') && e('desc,name,date'); //测试moduleName为release,requiredFields中的create存在一个值 -r($custom->saveRequiredFieldsTest($moduleName[1], $requiredFields['releaseFields3'], $fieldsType[1])) && p('value') && e('desc,name,date'); //测试moduleName为release,requiredFields中的rdit存在一个值 +r($custom->saveRequiredFieldsTest($moduleName[1], $requiredFields['releaseFields3'], $fieldsType[1])) && p('value') && e('desc,name,build,date'); //测试moduleName为release,requiredFields中的edit存在一个值 r($custom->saveRequiredFieldsTest($moduleName[1], $requiredFields['releaseFields4'], $fieldsType[0])) && p('value') && e('desc,name,date'); //测试moduleName为release,requiredFields中的create,edit各存在一个值 r($custom->saveRequiredFieldsTest($moduleName[2], $requiredFields['executionFields1'], $fieldsType[0])) && p('value') && e('name,code,begin,end'); //测试moduleName为execution,requiredFields为空 r($custom->saveRequiredFieldsTest($moduleName[2], $requiredFields['executionFields2'], $fieldsType[0])) && p('value') && e('desc,name,code,begin,end'); //测试moduleName为execution,requiredFields中的create存在一个值 @@ -147,4 +147,4 @@ r($custom->saveRequiredFieldsTest($moduleName[5], $requiredFields['testcaseField r($custom->saveRequiredFieldsTest($moduleName[5], $requiredFields['testcaseFields6'], $fieldsType[0])) && p('value') && e('stage,story,title,type'); //测试moduleName为testcase,requiredFields中的create,edit各存在多个值 r($custom->saveRequiredFieldsTest($moduleName[3], $requiredFields['taskFields6'], $fieldsType[2])) && p('value') && e('comment,realStarted,finishedDate,currentConsumed');//测试moduleName为task,requiredFields中的finish存在一个值 -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/datatable/printHead.php b/test/model/datatable/printHead.php index 101dc591b6..e48162d59f 100755 --- a/test/model/datatable/printHead.php +++ b/test/model/datatable/printHead.php @@ -10,7 +10,10 @@ title=测试 datatableModel::printHead(); cid=1 pid=1 - +获取产品模块browse方法头部html >> 1 +获取产品模块browse方法头部html带排序 >> 1 +获取产品模块browse方法头部html带参数 >> 1 +获取产品模块browse方法头部html带checkbox >> 1 */ @@ -25,4 +28,4 @@ $data_check = array('cols' => $productSetting[0], 'orderBy' => 'id_asc', 'vars' r($datatable->printHeadTest($data)) && p() && e(1); //获取产品模块browse方法头部html r($datatable->printHeadTest($data_order)) && p() && e(1); //获取产品模块browse方法头部html带排序 r($datatable->printHeadTest($data_vars)) && p() && e(1); //获取产品模块browse方法头部html带参数 -r($datatable->printHeadTest($data_check)) && p() && e(1); //获取产品模块browse方法头部html带checkbox \ No newline at end of file +r($datatable->printHeadTest($data_check)) && p() && e(1); //获取产品模块browse方法头部html带checkbox diff --git a/test/model/dept/getdeptuserpairs.php b/test/model/dept/getdeptuserpairs.php index e34959b13b..0cf55ee774 100755 --- a/test/model/dept/getdeptuserpairs.php +++ b/test/model/dept/getdeptuserpairs.php @@ -23,7 +23,7 @@ type为out查询 >> 测试10 */ -$deptIDList = array('0', '2', '5'); +$deptIDList = array(0, '2', '5'); $key = array('id', 'account', 'out'); $type = array('inside', 'outside', 'out'); $count = array('0', '1'); @@ -39,4 +39,4 @@ r($dept->getDeptUserPairsTest($deptIDList[1], $count[0], $key[1], $type[2])) r($dept->getDeptUserPairsTest($deptIDList[0], $count[1], $key[0], $type[0])) && p() && e('999'); //查询所有内部用户统计 r($dept->getDeptUserPairsTest($deptIDList[0], $count[1], $key[0], $type[1])) && p() && e('1'); //查询所有外部用户统计 r($dept->getDeptUserPairsTest($deptIDList[1], $count[1], $key[0], $type[0])) && p() && e('30'); //根据部门查询用户统计 -r($dept->getDeptUserPairsTest($deptIDList[0], $count[1], $key[0], $type[0], $params)) && p() && e('1000'); //查询全部用户统计 \ No newline at end of file +r($dept->getDeptUserPairsTest($deptIDList[0], $count[1], $key[0], $type[0], $params)) && p() && e('1000'); //查询全部用户统计 diff --git a/test/model/dept/managechild.php b/test/model/dept/managechild.php index 89e9ce5e75..eb1968bedf 100755 --- a/test/model/dept/managechild.php +++ b/test/model/dept/managechild.php @@ -29,4 +29,4 @@ r($dept->manageChildTest('', $depts, $count[0])) && p('1') r($dept->manageChildTest('', $depts, $count[1])) && p() && e('3'); //无父级部门下添加子级部门统计 r($dept->manageChildTest($parentDeptID, $depts = array(), $count[0])) && p() && e('0'); //无部门名称 -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/design/batchcreate.php b/test/model/design/batchcreate.php index bb4313873c..c84ab96ca7 100755 --- a/test/model/design/batchcreate.php +++ b/test/model/design/batchcreate.php @@ -17,6 +17,8 @@ pid=1 批量创建看板项目设计 >> 41 不输入类型 >> 『设计类型』不能为空。 不输入名字 >> 0 +不输入需求 >> 1 +不输入详情 >> 1 */ $projectIDList = array('12', '32', '62', '13', '71', '72', '73', '75'); @@ -37,9 +39,11 @@ r(count($design->batchCreateTest($projectIDList[7], $productIDList[0], $noDescDe r($design->batchCreateTest($projectIDList[0], $productIDList[0], $normalDesign)) && p('0:name') && e('设计一'); //批量创建敏捷项目设计 r($design->batchCreateTest($projectIDList[1], $productIDList[1], $normalDesign)) && p('0:project') && e('32'); //批量创建瀑布项目设计 r($design->batchCreateTest($projectIDList[2], $productIDList[2], $normalDesign)) && p('0:product') && e('41'); //批量创建看板项目设计 -r($design->batchCreateTest($projectIDList[3], $productIDList[0], $noStoryDesign)) && p('0:story') && e(''); //不输入需求 r($design->batchCreateTest($projectIDList[4], $productIDList[0], $noTypeDesign)) && p('type:0') && e('『设计类型』不能为空。');//不输入类型 r($design->batchCreateTest($projectIDList[5], $productIDList[0], $noNameDesign)) && p() && e('0'); //不输入名字 -r($design->batchCreateTest($projectIDList[6], $productIDList[0], $noDescDesign)) && p('0:desc') && e(''); //不输入详情 +$result = $design->batchCreateTest($projectIDList[3], $productIDList[0], $noStoryDesign); +r(empty($result[0]->story)) && p() && e(1); //不输入需求 +$result = $design->batchCreateTest($projectIDList[6], $productIDList[0], $noDescDesign); +r(empty($result[0]->desc)) && p('0:desc') && e(1); //不输入详情 -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/entry/getbycode.php b/test/model/entry/getbycode.php index dd8513b642..9a80c0b22a 100755 --- a/test/model/entry/getbycode.php +++ b/test/model/entry/getbycode.php @@ -2,7 +2,6 @@ switchDB(); su('admin'); /** @@ -26,4 +25,3 @@ r($entry->getByCodeTest($entryCodeList[0])) && p('name') && e('这是应用名 r($entry->getByCodeTest($entryCodeList[0])) && p('account') && e('accountadmin'); // 查询code为code1的entry的account r($entry->getByCodeTest($entryCodeList[1])) && p('name') && e('0'); // 查询code为code2的entry的name r($entry->getByCodeTest($entryCodeList[1])) && p('account') && e('0'); // 查询code为code2的entry的account -$db->restoreDB(); \ No newline at end of file diff --git a/test/model/entry/getbyid.php b/test/model/entry/getbyid.php index 3ffd83cc18..b9c09940b2 100755 --- a/test/model/entry/getbyid.php +++ b/test/model/entry/getbyid.php @@ -2,7 +2,6 @@ switchDB(); su('admin'); /** @@ -26,4 +25,3 @@ r($entry->getByIdTest($entryIDList[0])) && p('name') && e('这是应用名称1') r($entry->getByIdTest($entryIDList[0])) && p('account') && e('accountadmin'); // 查询id为1的entry的account r($entry->getByIdTest($entryIDList[1])) && p('name') && e('0'); // 查询id为1000001的entry的name r($entry->getByIdTest($entryIDList[1])) && p('account') && e('0'); // 查询id为1000001的entry的account -$db->restoreDB(); \ No newline at end of file diff --git a/test/model/entry/getbykey.php b/test/model/entry/getbykey.php index d484eee883..7f5d7b7990 100755 --- a/test/model/entry/getbykey.php +++ b/test/model/entry/getbykey.php @@ -2,7 +2,6 @@ switchDB(); su('admin'); /** @@ -26,4 +25,3 @@ r($entry->getByKeyTest($entryKeyList[0])) && p('name') && e('这是应用名称1 r($entry->getByKeyTest($entryKeyList[0])) && p('account') && e('accountadmin'); // 查询key为792b9b972157d2d8531b43e04c0af021的entry的account r($entry->getByKeyTest($entryKeyList[1])) && p('name') && e('0'); // 查询key为空的entry的name r($entry->getByKeyTest($entryKeyList[1])) && p('account') && e('0'); // 查询key为空的entry的account -$db->restoreDB(); \ No newline at end of file diff --git a/test/model/entry/getlist.php b/test/model/entry/getlist.php index c685116ec5..6c723aa878 100755 --- a/test/model/entry/getlist.php +++ b/test/model/entry/getlist.php @@ -2,7 +2,6 @@ switchDB(); su('admin'); /** @@ -21,4 +20,3 @@ $list = $entry->getListTest(); r(count($list)) && p() && e('1'); //测试获取列表的个数,目前只有一个 r($list) && p('1:name') && e('这是应用名称1'); //测试获取列表某个应用的名称信息 -$db->restoreDB(); \ No newline at end of file diff --git a/test/model/entry/getlogs.php b/test/model/entry/getlogs.php index 1452ccd82f..b95f7a2b01 100755 --- a/test/model/entry/getlogs.php +++ b/test/model/entry/getlogs.php @@ -2,7 +2,6 @@ switchDB(); su('admin'); /** @@ -24,4 +23,3 @@ $list_1 = $entry->getLogsTest($entryIDList[0]); $list_1000001 = $entry->getLogsTest($entryIDList[1]); r(count($list_1)) && p() && e('1'); //测试获取列表的个数,ID为1的日志数为1 r(count($list_1000001)) && p() && e('0'); //测试获取列表个数,ID为100001的日志数为0 -$db->restoreDB(); \ No newline at end of file diff --git a/test/model/entry/updatecalltime.php b/test/model/entry/updatecalltime.php index 06b5359c03..f49f57c1d3 100755 --- a/test/model/entry/updatecalltime.php +++ b/test/model/entry/updatecalltime.php @@ -23,4 +23,4 @@ $entry = new entryTest(); r($entry->updateCalledTimeTest($code[0], $time)) && p('name') && e('这是应用名称1'); //测试更新entry代号存在的情况 r($entry->updateCalledTimeTest($code[1], $time)) && p() && e('0'); //测试更新entry代号不存在的情况 -$db->restoreDB(); \ No newline at end of file +$db->restoreDB(); diff --git a/test/model/file/checkpriv.php b/test/model/file/checkpriv.php new file mode 100755 index 0000000000..56fe7b2643 --- /dev/null +++ b/test/model/file/checkpriv.php @@ -0,0 +1,30 @@ +#!/usr/bin/env php +getSaveName(); +cid=1 +pid=1 + + + +*/ + +global $tester; +$tester->loadModel('file'); +$file1 = $tester->file->getByID(1); +$file10 = $tester->file->getByID(10); +$file45 = $tester->file->getByID(45); + +su('user10'); +r($tester->file->checkPriv($file1)) && p() && e(1); // 查看用户user10是否有下载附件1的权限 +r($tester->file->checkPriv($file10)) && p() && e(1); // 查看用户user10是否有下载附件10的权限 +r($tester->file->checkPriv($file45)) && p() && e(0); // 查看用户user10是否有下载附件45的权限 + +su('dev38'); +r($tester->file->checkPriv($file1)) && p() && e(1); // 查看用户dev38是否有下载附件1的权限 +r($tester->file->checkPriv($file10)) && p() && e(1); // 查看用户dev38是否有下载附件10的权限 +r($tester->file->checkPriv($file45)) && p() && e(0); // 查看用户dev38是否有下载附件45的权限 diff --git a/www/theme/default/images/project/active-line.png b/www/theme/default/images/project/active-line.png index 653eea441f..fff6283c73 100644 Binary files a/www/theme/default/images/project/active-line.png and b/www/theme/default/images/project/active-line.png differ diff --git a/www/theme/default/x.style.css b/www/theme/default/x.style.css index 24d222ce45..358ce2903c 100644 --- a/www/theme/default/x.style.css +++ b/www/theme/default/x.style.css @@ -2,7 +2,7 @@ body{padding:0px; margin: 0px;background-color: #fff;} #header{display: none} #footer{display: none} #header+#main{min-width:auto} -#main{padding: 0px;} +#main{padding: 0px; top:0!important;} #main .container{padding: 0px;} #mainMenu{margin-top:0px;background-color: #efefef;} #mainContent .cell{box-shadow:none; -webkit-box-shadow: none;} diff --git a/www/theme/zui/css/min.css b/www/theme/zui/css/min.css index ccc2388046..490bdf7802 100644 --- a/www/theme/zui/css/min.css +++ b/www/theme/zui/css/min.css @@ -1,7 +1,7 @@ /*! * ZUI: ZUI for Zentao - v1.10.0 - 2022-08-05 * http://openzui.com - * GitHub: https://github.com/easysoft/zui.git + * GitHub: https://github.com/easysoft/zui.git * 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;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:30px;height:30px;overflow:hidden;font-size:15px;line-height:30px;text-align:center;background-position:center;-webkit-background-size:cover;background-size:cover;border-radius:4px;-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}.avatar img{display:block;width:100%;height:100%;margin:0}.avatar.has-text{color:#fff;background-color:#16a8f8}.avatar span{display:block;margin-right:-1em;margin-left:-1em;text-align:center}.avatar .text-len-2{-webkit-transform:scale(.8);-ms-transform:scale(.8);-o-transform:scale(.8);transform:scale(.8)}.avatar .text-len-3,.avatar .text-len-4{-webkit-transform:scale(.6);-ms-transform:scale(.6);-o-transform:scale(.6);transform:scale(.6)}.avatar-sm{width:20px;height:20px;font-size:10px;line-height:20px}.avatar-sm .text-len-2{-webkit-transform:scale(.7);-ms-transform:scale(.7);-o-transform:scale(.7);transform:scale(.7)}.avatar-sm .text-len-3,.avatar-sm .text-len-4{-webkit-transform:scale(.5);-ms-transform:scale(.5);-o-transform:scale(.5);transform:scale(.5)}.avatar-md{width:24px;height:24px;font-size:12px;line-height:24px}.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:0}}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